Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/advapi32/cred.c
4387 views
1
/*
2
* Credential Management APIs
3
*
4
* Copyright 2007 Robert Shearman for CodeWeavers
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include <stdarg.h>
22
#include <time.h>
23
#include <limits.h>
24
25
#include "windef.h"
26
#include "winbase.h"
27
#include "winreg.h"
28
#include "wincred.h"
29
#include "winternl.h"
30
#include "winioctl.h"
31
#define WINE_MOUNTMGR_EXTENSIONS
32
#include "ddk/mountmgr.h"
33
34
#include "crypt.h"
35
36
#include "wine/debug.h"
37
38
#include "advapi32_misc.h"
39
40
WINE_DEFAULT_DEBUG_CHANNEL(cred);
41
42
/* the size of the ARC4 key used to encrypt the password data */
43
#define KEY_SIZE 8
44
45
static DWORD read_credential_blob(HKEY hkey, const BYTE key_data[KEY_SIZE],
46
LPBYTE credential_blob,
47
DWORD *credential_blob_size)
48
{
49
DWORD ret;
50
DWORD type;
51
52
*credential_blob_size = 0;
53
ret = RegQueryValueExW(hkey, L"Password", 0, &type, NULL, credential_blob_size);
54
if (ret != ERROR_SUCCESS)
55
return ret;
56
else if (type != REG_BINARY)
57
return ERROR_REGISTRY_CORRUPT;
58
if (credential_blob)
59
{
60
struct ustring data;
61
struct ustring key;
62
63
ret = RegQueryValueExW(hkey, L"Password", 0, &type, credential_blob,
64
credential_blob_size);
65
if (ret != ERROR_SUCCESS)
66
return ret;
67
else if (type != REG_BINARY)
68
return ERROR_REGISTRY_CORRUPT;
69
70
key.Length = key.MaximumLength = KEY_SIZE;
71
key.Buffer = (unsigned char *)key_data;
72
73
data.Length = data.MaximumLength = *credential_blob_size;
74
data.Buffer = credential_blob;
75
SystemFunction032(&data, &key);
76
}
77
return ERROR_SUCCESS;
78
}
79
80
static DWORD registry_read_credential(HKEY hkey, PCREDENTIALW credential,
81
const BYTE key_data[KEY_SIZE],
82
char *buffer, DWORD *len)
83
{
84
DWORD type;
85
DWORD ret;
86
DWORD count;
87
88
ret = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &count);
89
if (ret != ERROR_SUCCESS)
90
return ret;
91
else if (type != REG_SZ)
92
return ERROR_REGISTRY_CORRUPT;
93
*len += count;
94
if (credential)
95
{
96
credential->TargetName = (LPWSTR)buffer;
97
ret = RegQueryValueExW(hkey, NULL, 0, &type, (LPVOID)credential->TargetName,
98
&count);
99
if (ret != ERROR_SUCCESS || type != REG_SZ) return ret;
100
buffer += count;
101
}
102
103
ret = RegQueryValueExW(hkey, L"Comment", 0, &type, NULL, &count);
104
if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
105
return ret;
106
else if (type != REG_SZ)
107
return ERROR_REGISTRY_CORRUPT;
108
*len += count;
109
if (credential)
110
{
111
credential->Comment = (LPWSTR)buffer;
112
ret = RegQueryValueExW(hkey, L"Comment", 0, &type, (LPVOID)credential->Comment,
113
&count);
114
if (ret == ERROR_FILE_NOT_FOUND)
115
credential->Comment = NULL;
116
else if (ret != ERROR_SUCCESS)
117
return ret;
118
else if (type != REG_SZ)
119
return ERROR_REGISTRY_CORRUPT;
120
else
121
buffer += count;
122
}
123
124
ret = RegQueryValueExW(hkey, L"TargetAlias", 0, &type, NULL, &count);
125
if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
126
return ret;
127
else if (type != REG_SZ)
128
return ERROR_REGISTRY_CORRUPT;
129
*len += count;
130
if (credential)
131
{
132
credential->TargetAlias = (LPWSTR)buffer;
133
ret = RegQueryValueExW(hkey, L"TargetAlias", 0, &type, (LPVOID)credential->TargetAlias,
134
&count);
135
if (ret == ERROR_FILE_NOT_FOUND)
136
credential->TargetAlias = NULL;
137
else if (ret != ERROR_SUCCESS)
138
return ret;
139
else if (type != REG_SZ)
140
return ERROR_REGISTRY_CORRUPT;
141
else
142
buffer += count;
143
}
144
145
ret = RegQueryValueExW(hkey, L"UserName", 0, &type, NULL, &count);
146
if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
147
return ret;
148
else if (type != REG_SZ)
149
return ERROR_REGISTRY_CORRUPT;
150
*len += count;
151
if (credential)
152
{
153
credential->UserName = (LPWSTR)buffer;
154
ret = RegQueryValueExW(hkey, L"UserName", 0, &type, (LPVOID)credential->UserName,
155
&count);
156
if (ret == ERROR_FILE_NOT_FOUND)
157
credential->UserName = NULL;
158
else if (ret != ERROR_SUCCESS)
159
return ret;
160
else if (type != REG_SZ)
161
return ERROR_REGISTRY_CORRUPT;
162
else
163
buffer += count;
164
}
165
166
ret = read_credential_blob(hkey, key_data, NULL, &count);
167
if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
168
return ret;
169
*len += count;
170
if (credential)
171
{
172
credential->CredentialBlob = (LPBYTE)buffer;
173
ret = read_credential_blob(hkey, key_data, credential->CredentialBlob, &count);
174
if (ret == ERROR_FILE_NOT_FOUND)
175
credential->CredentialBlob = NULL;
176
else if (ret != ERROR_SUCCESS)
177
return ret;
178
credential->CredentialBlobSize = count;
179
}
180
181
/* FIXME: Attributes */
182
if (credential)
183
{
184
credential->AttributeCount = 0;
185
credential->Attributes = NULL;
186
}
187
188
if (!credential) return ERROR_SUCCESS;
189
190
count = sizeof(credential->Flags);
191
ret = RegQueryValueExW(hkey, L"Flags", NULL, &type, (LPVOID)&credential->Flags,
192
&count);
193
if (ret != ERROR_SUCCESS)
194
return ret;
195
else if (type != REG_DWORD)
196
return ERROR_REGISTRY_CORRUPT;
197
count = sizeof(credential->Type);
198
ret = RegQueryValueExW(hkey, L"Type", NULL, &type, (LPVOID)&credential->Type,
199
&count);
200
if (ret != ERROR_SUCCESS)
201
return ret;
202
else if (type != REG_DWORD)
203
return ERROR_REGISTRY_CORRUPT;
204
205
count = sizeof(credential->LastWritten);
206
ret = RegQueryValueExW(hkey, L"LastWritten", NULL, &type, (LPVOID)&credential->LastWritten,
207
&count);
208
if (ret != ERROR_SUCCESS)
209
return ret;
210
else if (type != REG_BINARY)
211
return ERROR_REGISTRY_CORRUPT;
212
count = sizeof(credential->Persist);
213
ret = RegQueryValueExW(hkey, L"Persist", NULL, &type, (LPVOID)&credential->Persist,
214
&count);
215
if (ret == ERROR_SUCCESS && type != REG_DWORD)
216
return ERROR_REGISTRY_CORRUPT;
217
return ret;
218
}
219
220
static DWORD write_credential_blob(HKEY hkey, LPCWSTR target_name, DWORD type,
221
const BYTE key_data[KEY_SIZE],
222
const BYTE *credential_blob, DWORD credential_blob_size)
223
{
224
LPBYTE encrypted_credential_blob;
225
struct ustring data;
226
struct ustring key;
227
DWORD ret;
228
229
key.Length = key.MaximumLength = KEY_SIZE;
230
key.Buffer = (unsigned char *)key_data;
231
232
encrypted_credential_blob = malloc(credential_blob_size);
233
if (!encrypted_credential_blob) return ERROR_OUTOFMEMORY;
234
235
memcpy(encrypted_credential_blob, credential_blob, credential_blob_size);
236
data.Length = data.MaximumLength = credential_blob_size;
237
data.Buffer = encrypted_credential_blob;
238
SystemFunction032(&data, &key);
239
240
ret = RegSetValueExW(hkey, L"Password", 0, REG_BINARY, encrypted_credential_blob, credential_blob_size);
241
free(encrypted_credential_blob);
242
243
return ret;
244
}
245
246
static DWORD registry_write_credential(HKEY hkey, const CREDENTIALW *credential,
247
const BYTE key_data[KEY_SIZE], BOOL preserve_blob)
248
{
249
DWORD ret;
250
FILETIME LastWritten;
251
252
GetSystemTimeAsFileTime(&LastWritten);
253
254
ret = RegSetValueExW(hkey, L"Flags", 0, REG_DWORD, (const BYTE*)&credential->Flags,
255
sizeof(credential->Flags));
256
if (ret != ERROR_SUCCESS) return ret;
257
ret = RegSetValueExW(hkey, L"Type", 0, REG_DWORD, (const BYTE*)&credential->Type,
258
sizeof(credential->Type));
259
if (ret != ERROR_SUCCESS) return ret;
260
ret = RegSetValueExW(hkey, NULL, 0, REG_SZ, (LPVOID)credential->TargetName,
261
sizeof(WCHAR)*(lstrlenW(credential->TargetName)+1));
262
if (ret != ERROR_SUCCESS) return ret;
263
if (credential->Comment)
264
{
265
ret = RegSetValueExW(hkey, L"Comment", 0, REG_SZ, (LPVOID)credential->Comment,
266
sizeof(WCHAR)*(lstrlenW(credential->Comment)+1));
267
if (ret != ERROR_SUCCESS) return ret;
268
}
269
ret = RegSetValueExW(hkey, L"LastWritten", 0, REG_BINARY, (LPVOID)&LastWritten,
270
sizeof(LastWritten));
271
if (ret != ERROR_SUCCESS) return ret;
272
ret = RegSetValueExW(hkey, L"Persist", 0, REG_DWORD, (const BYTE*)&credential->Persist,
273
sizeof(credential->Persist));
274
if (ret != ERROR_SUCCESS) return ret;
275
/* FIXME: Attributes */
276
if (credential->TargetAlias)
277
{
278
ret = RegSetValueExW(hkey, L"TargetAlias", 0, REG_SZ, (LPVOID)credential->TargetAlias,
279
sizeof(WCHAR)*(lstrlenW(credential->TargetAlias)+1));
280
if (ret != ERROR_SUCCESS) return ret;
281
}
282
if (credential->UserName)
283
{
284
ret = RegSetValueExW(hkey, L"UserName", 0, REG_SZ, (LPVOID)credential->UserName,
285
sizeof(WCHAR)*(lstrlenW(credential->UserName)+1));
286
if (ret != ERROR_SUCCESS) return ret;
287
}
288
if (!preserve_blob)
289
{
290
ret = write_credential_blob(hkey, credential->TargetName, credential->Type,
291
key_data, credential->CredentialBlob,
292
credential->CredentialBlobSize);
293
}
294
return ret;
295
}
296
297
static DWORD host_write_credential( const CREDENTIALW *credential, BOOL preserve_blob )
298
{
299
struct mountmgr_credential *cred;
300
HANDLE mgr;
301
DWORD size;
302
WCHAR *ptr;
303
BOOL ret;
304
305
if (credential->Flags)
306
FIXME( "flags 0x%lx not written\n", credential->Flags );
307
if (credential->Type != CRED_TYPE_DOMAIN_PASSWORD)
308
FIXME( "credential type of %ld not supported\n", credential->Type );
309
if (credential->Persist != CRED_PERSIST_LOCAL_MACHINE)
310
FIXME( "persist value of %ld not supported\n", credential->Persist );
311
if (credential->AttributeCount)
312
FIXME( "custom attributes not supported\n" );
313
314
if (credential->CredentialBlobSize % sizeof(WCHAR)) return ERROR_NOT_SUPPORTED;
315
316
mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
317
OPEN_EXISTING, 0, 0 );
318
if (mgr == INVALID_HANDLE_VALUE) return GetLastError();
319
320
size = sizeof(*cred) + (lstrlenW( credential->TargetName ) + lstrlenW( credential->UserName ) + 2) * sizeof(WCHAR);
321
size += credential->CredentialBlobSize;
322
if (credential->Comment) size += (lstrlenW( credential->Comment ) + 1) * sizeof(WCHAR);
323
if (!(cred = malloc( size )))
324
{
325
CloseHandle( mgr );
326
return ERROR_OUTOFMEMORY;
327
}
328
ptr = (WCHAR *)(cred + 1);
329
330
cred->targetname_offset = sizeof(*cred);
331
cred->targetname_size = (lstrlenW( credential->TargetName ) + 1) * sizeof(WCHAR);
332
lstrcpyW( ptr, credential->TargetName );
333
ptr += cred->targetname_size / sizeof(WCHAR);
334
335
cred->username_offset = cred->targetname_offset + cred->targetname_size;
336
cred->username_size = (lstrlenW( credential->UserName ) + 1) * sizeof(WCHAR);
337
lstrcpyW( ptr, credential->UserName );
338
ptr += cred->username_size / sizeof(WCHAR);
339
340
cred->blob_offset = cred->username_offset + cred->username_size;
341
if (credential->CredentialBlob)
342
{
343
cred->blob_size = credential->CredentialBlobSize;
344
memcpy( ptr, credential->CredentialBlob, credential->CredentialBlobSize );
345
ptr += cred->blob_size / sizeof(WCHAR);
346
}
347
else cred->blob_size = 0;
348
cred->blob_preserve = preserve_blob;
349
350
cred->comment_offset = cred->blob_offset + cred->blob_size;
351
if (credential->Comment)
352
{
353
cred->comment_size = (lstrlenW( credential->Comment ) + 1) * sizeof(WCHAR);
354
lstrcpyW( ptr, credential->Comment );
355
}
356
else cred->comment_size = 0;
357
358
ret = DeviceIoControl( mgr, IOCTL_MOUNTMGR_WRITE_CREDENTIAL, cred, size, NULL, 0, NULL, NULL );
359
free( cred );
360
CloseHandle( mgr );
361
362
return ret ? ERROR_SUCCESS : GetLastError();
363
}
364
365
static DWORD open_cred_mgr_key(HKEY *hkey, BOOL open_for_write)
366
{
367
return RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Wine\\Credential Manager", 0,
368
NULL, REG_OPTION_NON_VOLATILE,
369
KEY_READ | (open_for_write ? KEY_WRITE : 0), NULL, hkey, NULL);
370
}
371
372
static DWORD get_cred_mgr_encryption_key(HKEY hkeyMgr, BYTE key_data[KEY_SIZE])
373
{
374
static const BYTE my_key_data[KEY_SIZE] = { 0 };
375
DWORD type;
376
DWORD count;
377
FILETIME ft;
378
ULONG seed;
379
ULONG value;
380
DWORD ret;
381
382
memcpy(key_data, my_key_data, KEY_SIZE);
383
384
count = KEY_SIZE;
385
ret = RegQueryValueExW(hkeyMgr, L"EncryptionKey", NULL, &type, key_data,
386
&count);
387
if (ret == ERROR_SUCCESS)
388
{
389
if (type != REG_BINARY)
390
return ERROR_REGISTRY_CORRUPT;
391
else
392
return ERROR_SUCCESS;
393
}
394
if (ret != ERROR_FILE_NOT_FOUND)
395
return ret;
396
397
GetSystemTimeAsFileTime(&ft);
398
seed = ft.dwLowDateTime;
399
value = RtlUniform(&seed);
400
*(DWORD *)key_data = value;
401
seed = ft.dwHighDateTime;
402
value = RtlUniform(&seed);
403
*(DWORD *)(key_data + 4) = value;
404
405
ret = RegSetValueExW(hkeyMgr, L"EncryptionKey", 0, REG_BINARY,
406
key_data, KEY_SIZE);
407
if (ret == ERROR_ACCESS_DENIED)
408
{
409
ret = open_cred_mgr_key(&hkeyMgr, TRUE);
410
if (ret == ERROR_SUCCESS)
411
{
412
ret = RegSetValueExW(hkeyMgr, L"EncryptionKey", 0, REG_BINARY,
413
key_data, KEY_SIZE);
414
RegCloseKey(hkeyMgr);
415
}
416
}
417
return ret;
418
}
419
420
static LPWSTR get_key_name_for_target(LPCWSTR target_name, DWORD type)
421
{
422
INT len;
423
LPCWSTR prefix = NULL;
424
LPWSTR key_name, p;
425
426
len = lstrlenW(target_name);
427
if (type == CRED_TYPE_GENERIC)
428
{
429
prefix = L"Generic: ";
430
len += ARRAY_SIZE(L"Generic: ");
431
}
432
else
433
{
434
prefix = L"DomPasswd: ";
435
len += ARRAY_SIZE(L"DomPasswd: ");
436
}
437
438
key_name = malloc(len * sizeof(WCHAR));
439
if (!key_name) return NULL;
440
441
lstrcpyW(key_name, prefix);
442
lstrcatW(key_name, target_name);
443
444
for (p = key_name; *p; p++)
445
if (*p == '\\') *p = '_';
446
447
return key_name;
448
}
449
450
static BOOL registry_credential_matches_filter(HKEY hkeyCred, LPCWSTR filter)
451
{
452
LPWSTR target_name;
453
DWORD ret;
454
DWORD type;
455
DWORD count;
456
LPCWSTR p;
457
458
if (!filter) return TRUE;
459
460
ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, NULL, &count);
461
if (ret != ERROR_SUCCESS)
462
return FALSE;
463
else if (type != REG_SZ)
464
return FALSE;
465
466
target_name = malloc(count);
467
if (!target_name)
468
return FALSE;
469
ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, (LPVOID)target_name, &count);
470
if (ret != ERROR_SUCCESS || type != REG_SZ)
471
{
472
free(target_name);
473
return FALSE;
474
}
475
476
TRACE("comparing filter %s to target name %s\n", debugstr_w(filter),
477
debugstr_w(target_name));
478
479
p = wcschr(filter, '*');
480
ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, filter,
481
(p && !p[1] ? p - filter : -1), target_name,
482
(p && !p[1] ? p - filter : -1)) == CSTR_EQUAL;
483
484
free(target_name);
485
return ret;
486
}
487
488
static DWORD registry_enumerate_credentials(HKEY hkeyMgr, LPCWSTR filter,
489
LPWSTR target_name,
490
DWORD target_name_len, const BYTE key_data[KEY_SIZE],
491
PCREDENTIALW *credentials, char **buffer,
492
DWORD *len, DWORD *count)
493
{
494
DWORD i;
495
DWORD ret;
496
for (i = 0;; i++)
497
{
498
HKEY hkeyCred;
499
ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1);
500
if (ret == ERROR_NO_MORE_ITEMS)
501
{
502
ret = ERROR_SUCCESS;
503
break;
504
}
505
else if (ret != ERROR_SUCCESS)
506
continue;
507
TRACE("target_name = %s\n", debugstr_w(target_name));
508
ret = RegOpenKeyExW(hkeyMgr, target_name, 0, KEY_QUERY_VALUE, &hkeyCred);
509
if (ret != ERROR_SUCCESS)
510
continue;
511
if (!registry_credential_matches_filter(hkeyCred, filter))
512
{
513
RegCloseKey(hkeyCred);
514
continue;
515
}
516
if (buffer)
517
{
518
*len = sizeof(CREDENTIALW);
519
credentials[*count] = (PCREDENTIALW)*buffer;
520
}
521
else
522
*len += sizeof(CREDENTIALW);
523
ret = registry_read_credential(hkeyCred, buffer ? credentials[*count] : NULL,
524
key_data, buffer ? *buffer + sizeof(CREDENTIALW) : NULL,
525
len);
526
RegCloseKey(hkeyCred);
527
if (ret != ERROR_SUCCESS) break;
528
if (buffer) *buffer += *len;
529
(*count)++;
530
}
531
return ret;
532
}
533
534
/******************************************************************************
535
* convert_PCREDENTIALW_to_PCREDENTIALA [internal]
536
*
537
* convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
538
*
539
*/
540
541
static INT convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW *CredentialW, PCREDENTIALA CredentialA, DWORD len)
542
{
543
char *buffer;
544
INT string_len;
545
INT needed = sizeof(CREDENTIALA);
546
547
if (!CredentialA)
548
{
549
if (CredentialW->TargetName)
550
needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, NULL, 0, NULL, NULL);
551
if (CredentialW->Comment)
552
needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, NULL, 0, NULL, NULL);
553
needed += CredentialW->CredentialBlobSize;
554
if (CredentialW->TargetAlias)
555
needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, NULL, 0, NULL, NULL);
556
if (CredentialW->UserName)
557
needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, NULL, 0, NULL, NULL);
558
559
return needed;
560
}
561
562
563
buffer = (char *)CredentialA + sizeof(CREDENTIALA);
564
len -= sizeof(CREDENTIALA);
565
CredentialA->Flags = CredentialW->Flags;
566
CredentialA->Type = CredentialW->Type;
567
568
if (CredentialW->TargetName)
569
{
570
CredentialA->TargetName = buffer;
571
string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, buffer, len, NULL, NULL);
572
buffer += string_len;
573
needed += string_len;
574
len -= string_len;
575
}
576
else
577
CredentialA->TargetName = NULL;
578
if (CredentialW->Comment)
579
{
580
CredentialA->Comment = buffer;
581
string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, buffer, len, NULL, NULL);
582
buffer += string_len;
583
needed += string_len;
584
len -= string_len;
585
}
586
else
587
CredentialA->Comment = NULL;
588
CredentialA->LastWritten = CredentialW->LastWritten;
589
CredentialA->CredentialBlobSize = CredentialW->CredentialBlobSize;
590
if (CredentialW->CredentialBlobSize && (CredentialW->CredentialBlobSize <= len))
591
{
592
CredentialA->CredentialBlob =(LPBYTE)buffer;
593
memcpy(CredentialA->CredentialBlob, CredentialW->CredentialBlob,
594
CredentialW->CredentialBlobSize);
595
buffer += CredentialW->CredentialBlobSize;
596
needed += CredentialW->CredentialBlobSize;
597
len -= CredentialW->CredentialBlobSize;
598
}
599
else
600
CredentialA->CredentialBlob = NULL;
601
CredentialA->Persist = CredentialW->Persist;
602
CredentialA->AttributeCount = 0;
603
CredentialA->Attributes = NULL; /* FIXME */
604
if (CredentialW->TargetAlias)
605
{
606
CredentialA->TargetAlias = buffer;
607
string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, buffer, len, NULL, NULL);
608
buffer += string_len;
609
needed += string_len;
610
len -= string_len;
611
}
612
else
613
CredentialA->TargetAlias = NULL;
614
if (CredentialW->UserName)
615
{
616
CredentialA->UserName = buffer;
617
string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, buffer, len, NULL, NULL);
618
needed += string_len;
619
}
620
else
621
CredentialA->UserName = NULL;
622
623
return needed;
624
}
625
626
/******************************************************************************
627
* convert_PCREDENTIALA_to_PCREDENTIALW [internal]
628
*
629
* convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
630
*
631
*/
632
static INT convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA *CredentialA, PCREDENTIALW CredentialW, INT len)
633
{
634
char *buffer;
635
INT string_len;
636
INT needed = sizeof(CREDENTIALW);
637
638
if (!CredentialW)
639
{
640
if (CredentialA->TargetName)
641
needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, NULL, 0);
642
if (CredentialA->Comment)
643
needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, NULL, 0);
644
needed += CredentialA->CredentialBlobSize;
645
if (CredentialA->TargetAlias)
646
needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, NULL, 0);
647
if (CredentialA->UserName)
648
needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, NULL, 0);
649
650
return needed;
651
}
652
653
buffer = (char *)CredentialW + sizeof(CREDENTIALW);
654
len -= sizeof(CREDENTIALW);
655
CredentialW->Flags = CredentialA->Flags;
656
CredentialW->Type = CredentialA->Type;
657
if (CredentialA->TargetName)
658
{
659
CredentialW->TargetName = (LPWSTR)buffer;
660
string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, CredentialW->TargetName, len / sizeof(WCHAR));
661
buffer += sizeof(WCHAR) * string_len;
662
needed += sizeof(WCHAR) * string_len;
663
len -= sizeof(WCHAR) * string_len;
664
}
665
else
666
CredentialW->TargetName = NULL;
667
if (CredentialA->Comment)
668
{
669
CredentialW->Comment = (LPWSTR)buffer;
670
string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, CredentialW->Comment, len / sizeof(WCHAR));
671
buffer += sizeof(WCHAR) * string_len;
672
needed += sizeof(WCHAR) * string_len;
673
len -= sizeof(WCHAR) * string_len;
674
}
675
else
676
CredentialW->Comment = NULL;
677
CredentialW->LastWritten = CredentialA->LastWritten;
678
CredentialW->CredentialBlobSize = CredentialA->CredentialBlobSize;
679
if (CredentialA->CredentialBlobSize)
680
{
681
CredentialW->CredentialBlob =(LPBYTE)buffer;
682
memcpy(CredentialW->CredentialBlob, CredentialA->CredentialBlob,
683
CredentialA->CredentialBlobSize);
684
buffer += CredentialA->CredentialBlobSize;
685
needed += CredentialA->CredentialBlobSize;
686
len -= CredentialA->CredentialBlobSize;
687
}
688
else
689
CredentialW->CredentialBlob = NULL;
690
CredentialW->Persist = CredentialA->Persist;
691
CredentialW->AttributeCount = 0;
692
CredentialW->Attributes = NULL; /* FIXME */
693
if (CredentialA->TargetAlias)
694
{
695
CredentialW->TargetAlias = (LPWSTR)buffer;
696
string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, CredentialW->TargetAlias, len / sizeof(WCHAR));
697
buffer += sizeof(WCHAR) * string_len;
698
needed += sizeof(WCHAR) * string_len;
699
len -= sizeof(WCHAR) * string_len;
700
}
701
else
702
CredentialW->TargetAlias = NULL;
703
if (CredentialA->UserName)
704
{
705
CredentialW->UserName = (LPWSTR)buffer;
706
string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, CredentialW->UserName, len / sizeof(WCHAR));
707
needed += sizeof(WCHAR) * string_len;
708
}
709
else
710
CredentialW->UserName = NULL;
711
712
return needed;
713
}
714
715
/******************************************************************************
716
* CredDeleteA [ADVAPI32.@]
717
*/
718
BOOL WINAPI CredDeleteA(LPCSTR TargetName, DWORD Type, DWORD Flags)
719
{
720
LPWSTR TargetNameW;
721
DWORD len;
722
BOOL ret;
723
724
TRACE("(%s, %ld, 0x%lx)\n", debugstr_a(TargetName), Type, Flags);
725
726
if (!TargetName)
727
{
728
SetLastError(ERROR_INVALID_PARAMETER);
729
return FALSE;
730
}
731
732
len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0);
733
TargetNameW = malloc(len * sizeof(WCHAR));
734
if (!TargetNameW)
735
{
736
SetLastError(ERROR_OUTOFMEMORY);
737
return FALSE;
738
}
739
MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len);
740
741
ret = CredDeleteW(TargetNameW, Type, Flags);
742
743
free(TargetNameW);
744
745
return ret;
746
}
747
748
static DWORD host_delete_credential( const WCHAR *targetname )
749
{
750
struct mountmgr_credential *cred;
751
DWORD size, name_size = (lstrlenW( targetname ) + 1) * sizeof(WCHAR);
752
HANDLE mgr;
753
WCHAR *ptr;
754
BOOL ret;
755
756
mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
757
OPEN_EXISTING, 0, 0 );
758
if (mgr == INVALID_HANDLE_VALUE) return GetLastError();
759
760
size = sizeof(*cred) + name_size;
761
if (!(cred = malloc( size )))
762
{
763
CloseHandle( mgr );
764
return ERROR_OUTOFMEMORY;
765
}
766
cred->targetname_offset = sizeof(*cred);
767
cred->targetname_size = name_size;
768
ptr = (WCHAR *)(cred + 1);
769
lstrcpyW( ptr, targetname );
770
771
ret = DeviceIoControl( mgr, IOCTL_MOUNTMGR_DELETE_CREDENTIAL, cred, size, NULL, 0, NULL, NULL );
772
free( cred );
773
CloseHandle( mgr );
774
775
return ret ? ERROR_SUCCESS : GetLastError();
776
}
777
778
/******************************************************************************
779
* CredDeleteW [ADVAPI32.@]
780
*/
781
BOOL WINAPI CredDeleteW(LPCWSTR TargetName, DWORD Type, DWORD Flags)
782
{
783
HKEY hkeyMgr;
784
DWORD ret;
785
LPWSTR key_name;
786
787
TRACE("(%s, %ld, 0x%lx)\n", debugstr_w(TargetName), Type, Flags);
788
789
if (!TargetName)
790
{
791
SetLastError(ERROR_INVALID_PARAMETER);
792
return FALSE;
793
}
794
795
if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
796
{
797
FIXME("unhandled type %ld\n", Type);
798
SetLastError(ERROR_INVALID_PARAMETER);
799
return FALSE;
800
}
801
802
if (Flags)
803
{
804
FIXME("unhandled flags 0x%lx\n", Flags);
805
SetLastError(ERROR_INVALID_FLAGS);
806
return FALSE;
807
}
808
809
if (Type == CRED_TYPE_DOMAIN_PASSWORD)
810
{
811
ret = host_delete_credential(TargetName);
812
if (ret == ERROR_SUCCESS)
813
return TRUE;
814
}
815
816
ret = open_cred_mgr_key(&hkeyMgr, TRUE);
817
if (ret != ERROR_SUCCESS)
818
{
819
WARN("couldn't open/create manager key, error %ld\n", ret);
820
SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
821
return FALSE;
822
}
823
824
key_name = get_key_name_for_target(TargetName, Type);
825
ret = RegDeleteKeyW(hkeyMgr, key_name);
826
free(key_name);
827
RegCloseKey(hkeyMgr);
828
if (ret != ERROR_SUCCESS)
829
{
830
SetLastError(ERROR_NOT_FOUND);
831
return FALSE;
832
}
833
834
return TRUE;
835
}
836
837
/******************************************************************************
838
* CredEnumerateA [ADVAPI32.@]
839
*/
840
BOOL WINAPI CredEnumerateA(LPCSTR Filter, DWORD Flags, DWORD *Count,
841
PCREDENTIALA **Credentials)
842
{
843
LPWSTR FilterW;
844
PCREDENTIALW *CredentialsW;
845
DWORD i;
846
INT len;
847
INT needed;
848
char *buffer;
849
850
TRACE("(%s, 0x%lx, %p, %p)\n", debugstr_a(Filter), Flags, Count, Credentials);
851
852
if (Filter)
853
{
854
len = MultiByteToWideChar(CP_ACP, 0, Filter, -1, NULL, 0);
855
FilterW = malloc(len * sizeof(WCHAR));
856
if (!FilterW)
857
{
858
SetLastError(ERROR_OUTOFMEMORY);
859
return FALSE;
860
}
861
MultiByteToWideChar(CP_ACP, 0, Filter, -1, FilterW, len);
862
}
863
else
864
FilterW = NULL;
865
866
if (!CredEnumerateW(FilterW, Flags, Count, &CredentialsW))
867
{
868
free(FilterW);
869
return FALSE;
870
}
871
free(FilterW);
872
873
len = *Count * sizeof(PCREDENTIALA);
874
for (i = 0; i < *Count; i++)
875
len += convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, 0);
876
877
*Credentials = malloc(len);
878
if (!*Credentials)
879
{
880
CredFree(CredentialsW);
881
SetLastError(ERROR_OUTOFMEMORY);
882
return FALSE;
883
}
884
885
buffer = (char *)&(*Credentials)[*Count];
886
len -= *Count * sizeof(PCREDENTIALA);
887
for (i = 0; i < *Count; i++)
888
{
889
(*Credentials)[i] = (PCREDENTIALA)buffer;
890
needed = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], len);
891
buffer += needed;
892
len -= needed;
893
}
894
895
CredFree(CredentialsW);
896
897
return TRUE;
898
}
899
900
#define CRED_LIST_COUNT 16
901
#define CRED_DATA_SIZE 2048
902
static DWORD host_enumerate_credentials( const WCHAR *filter, CREDENTIALW **credentials, char *buf, DWORD *len, DWORD *count )
903
{
904
struct mountmgr_credential_list *list, *tmp;
905
DWORD i, j, ret, size, filter_size, offset = 0;
906
HANDLE mgr;
907
WCHAR *ptr;
908
909
if (filter) filter_size = (lstrlenW( filter ) + 1) * sizeof(WCHAR);
910
else
911
{
912
filter = L"";
913
filter_size = sizeof(L"");
914
}
915
916
mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
917
if (mgr == INVALID_HANDLE_VALUE) return GetLastError();
918
919
size = FIELD_OFFSET( struct mountmgr_credential_list, creds[CRED_LIST_COUNT] ) + filter_size + CRED_DATA_SIZE;
920
if (!(list = malloc( size )))
921
{
922
CloseHandle( mgr );
923
return ERROR_OUTOFMEMORY;
924
}
925
926
for (;;)
927
{
928
list->filter_offset = sizeof(*list);
929
list->filter_size = filter_size;
930
ptr = (WCHAR *)((char *)list + list->filter_offset);
931
lstrcpyW( ptr, filter );
932
933
if (DeviceIoControl( mgr, IOCTL_MOUNTMGR_ENUMERATE_CREDENTIALS, list, size, list, size, NULL, NULL )) break;
934
if ((ret = GetLastError()) != ERROR_MORE_DATA) goto done;
935
936
size = list->size + filter_size;
937
if (!(tmp = realloc( list, size )))
938
{
939
ret = ERROR_OUTOFMEMORY;
940
goto done;
941
}
942
list = tmp;
943
}
944
945
for (i = 0, j = *count; i < list->count; i++)
946
{
947
CREDENTIALW *cred = (CREDENTIALW *)(buf + offset);
948
949
offset += sizeof(*cred) + list->creds[i].targetname_size + list->creds[i].comment_size + list->creds[i].blob_size +
950
list->creds[i].username_size;
951
if (!buf) continue;
952
953
ptr = (WCHAR *)(cred + 1);
954
cred->Flags = 0;
955
cred->Type = CRED_TYPE_DOMAIN_PASSWORD;
956
cred->TargetName = ptr;
957
memcpy( cred->TargetName, (char *)&list->creds[i] + list->creds[i].targetname_offset, list->creds[i].targetname_size );
958
ptr += list->creds[i].targetname_size / sizeof(WCHAR);
959
if (list->creds[i].comment_size)
960
{
961
cred->Comment = ptr;
962
memcpy( cred->Comment, (char *)&list->creds[i] + list->creds[i].comment_offset, list->creds[i].comment_size );
963
ptr += list->creds[i].comment_size / sizeof(WCHAR);
964
}
965
else cred->Comment = NULL;
966
cred->LastWritten = list->creds[i].last_written;
967
if (list->creds[i].blob_size)
968
{
969
cred->CredentialBlobSize = list->creds[i].blob_size;
970
cred->CredentialBlob = (BYTE *)ptr;
971
memcpy( cred->CredentialBlob, (char *)&list->creds[i] + list->creds[i].blob_offset, list->creds[i].blob_size );
972
ptr += list->creds[i].blob_size / sizeof(WCHAR);
973
}
974
else
975
{
976
cred->CredentialBlobSize = 0;
977
cred->CredentialBlob = NULL;
978
}
979
cred->Persist = CRED_PERSIST_LOCAL_MACHINE;
980
cred->AttributeCount = 0;
981
cred->Attributes = NULL;
982
cred->TargetAlias = NULL;
983
if (list->creds[i].username_size)
984
{
985
cred->UserName = ptr;
986
memcpy( cred->UserName, (char *)&list->creds[i] + list->creds[i].username_offset, list->creds[i].username_size );
987
}
988
else cred->UserName = NULL;
989
if (credentials) credentials[j++] = cred;
990
}
991
992
*len += offset;
993
*count += list->count;
994
ret = ERROR_SUCCESS;
995
996
done:
997
free( list );
998
CloseHandle( mgr );
999
return ret;
1000
}
1001
1002
/******************************************************************************
1003
* CredEnumerateW [ADVAPI32.@]
1004
*/
1005
BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count, PCREDENTIALW **Credentials)
1006
{
1007
HKEY hkeyMgr;
1008
DWORD ret;
1009
LPWSTR target_name;
1010
DWORD target_name_len;
1011
DWORD len;
1012
char *buffer;
1013
BYTE key_data[KEY_SIZE];
1014
1015
TRACE("(%s, 0x%lx, %p, %p)\n", debugstr_w(Filter), Flags, Count, Credentials);
1016
1017
if (Flags)
1018
{
1019
SetLastError(ERROR_INVALID_FLAGS);
1020
return FALSE;
1021
}
1022
1023
ret = open_cred_mgr_key(&hkeyMgr, FALSE);
1024
if (ret != ERROR_SUCCESS)
1025
{
1026
WARN("couldn't open/create manager key, error %ld\n", ret);
1027
SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
1028
return FALSE;
1029
}
1030
1031
ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
1032
if (ret != ERROR_SUCCESS)
1033
{
1034
RegCloseKey(hkeyMgr);
1035
SetLastError(ret);
1036
return FALSE;
1037
}
1038
1039
ret = RegQueryInfoKeyW(hkeyMgr, NULL, NULL, NULL, NULL, &target_name_len, NULL, NULL, NULL, NULL, NULL, NULL);
1040
if (ret != ERROR_SUCCESS)
1041
{
1042
RegCloseKey(hkeyMgr);
1043
SetLastError(ret);
1044
return FALSE;
1045
}
1046
1047
target_name = malloc((target_name_len + 1) * sizeof(WCHAR));
1048
if (!target_name)
1049
{
1050
RegCloseKey(hkeyMgr);
1051
SetLastError(ERROR_OUTOFMEMORY);
1052
return FALSE;
1053
}
1054
1055
*Count = 0;
1056
len = 0;
1057
ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, target_name_len,
1058
key_data, NULL, NULL, &len, Count);
1059
if (ret == ERROR_SUCCESS)
1060
{
1061
ret = host_enumerate_credentials(Filter, NULL, NULL, &len, Count);
1062
if (ret == ERROR_NOT_SUPPORTED) ret = ERROR_SUCCESS;
1063
}
1064
if (ret == ERROR_SUCCESS && *Count == 0)
1065
ret = ERROR_NOT_FOUND;
1066
if (ret != ERROR_SUCCESS)
1067
{
1068
free(target_name);
1069
RegCloseKey(hkeyMgr);
1070
SetLastError(ret);
1071
return FALSE;
1072
}
1073
len += *Count * sizeof(PCREDENTIALW);
1074
1075
if (ret == ERROR_SUCCESS)
1076
{
1077
buffer = malloc(len);
1078
*Credentials = (PCREDENTIALW *)buffer;
1079
if (buffer)
1080
{
1081
buffer += *Count * sizeof(PCREDENTIALW);
1082
*Count = 0;
1083
ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, target_name_len, key_data,
1084
*Credentials, &buffer, &len, Count);
1085
if (ret == ERROR_SUCCESS)
1086
{
1087
ret = host_enumerate_credentials(Filter, *Credentials, buffer, &len, Count);
1088
if (ret == ERROR_NOT_SUPPORTED) ret = ERROR_SUCCESS;
1089
}
1090
}
1091
else ret = ERROR_OUTOFMEMORY;
1092
}
1093
1094
free(target_name);
1095
RegCloseKey(hkeyMgr);
1096
1097
if (ret != ERROR_SUCCESS)
1098
{
1099
SetLastError(ret);
1100
return FALSE;
1101
}
1102
return TRUE;
1103
}
1104
1105
/******************************************************************************
1106
* CredFree [ADVAPI32.@]
1107
*/
1108
VOID WINAPI CredFree(PVOID Buffer)
1109
{
1110
free(Buffer);
1111
}
1112
1113
/******************************************************************************
1114
* CredReadA [ADVAPI32.@]
1115
*/
1116
BOOL WINAPI CredReadA(LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *Credential)
1117
{
1118
LPWSTR TargetNameW;
1119
PCREDENTIALW CredentialW;
1120
INT len;
1121
1122
TRACE("(%s, %ld, 0x%lx, %p)\n", debugstr_a(TargetName), Type, Flags, Credential);
1123
1124
if (!TargetName)
1125
{
1126
SetLastError(ERROR_INVALID_PARAMETER);
1127
return FALSE;
1128
}
1129
1130
len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0);
1131
TargetNameW = malloc(len * sizeof(WCHAR));
1132
if (!TargetNameW)
1133
{
1134
SetLastError(ERROR_OUTOFMEMORY);
1135
return FALSE;
1136
}
1137
MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len);
1138
1139
if (!CredReadW(TargetNameW, Type, Flags, &CredentialW))
1140
{
1141
free(TargetNameW);
1142
return FALSE;
1143
}
1144
free(TargetNameW);
1145
1146
len = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, NULL, 0);
1147
*Credential = malloc(len);
1148
if (!*Credential)
1149
{
1150
SetLastError(ERROR_OUTOFMEMORY);
1151
return FALSE;
1152
}
1153
convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, *Credential, len);
1154
1155
CredFree(CredentialW);
1156
1157
return TRUE;
1158
}
1159
1160
static DWORD host_read_credential( const WCHAR *targetname, CREDENTIALW **ret_credential )
1161
{
1162
struct mountmgr_credential *cred_in, *cred_out = NULL, *tmp;
1163
DWORD err = ERROR_OUTOFMEMORY, size_in, size_out, size_name = (lstrlenW( targetname ) + 1) * sizeof(WCHAR);
1164
HANDLE mgr;
1165
WCHAR *ptr;
1166
BOOL ret;
1167
1168
mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
1169
OPEN_EXISTING, 0, 0 );
1170
if (mgr == INVALID_HANDLE_VALUE) return GetLastError();
1171
1172
size_in = sizeof(*cred_in) + size_name;
1173
if (!(cred_in = malloc( size_in )))
1174
{
1175
CloseHandle( mgr );
1176
return ERROR_OUTOFMEMORY;
1177
}
1178
cred_in->targetname_offset = sizeof(*cred_in);
1179
cred_in->targetname_size = size_name;
1180
ptr = (WCHAR *)(cred_in + 1);
1181
lstrcpyW( ptr, targetname );
1182
1183
size_out = 256;
1184
if (!(cred_out = malloc( size_out ))) goto done;
1185
1186
for (;;)
1187
{
1188
ret = DeviceIoControl( mgr, IOCTL_MOUNTMGR_READ_CREDENTIAL, cred_in, size_in, cred_out, size_out, NULL, NULL );
1189
if (ret || (err = GetLastError()) != ERROR_MORE_DATA) break;
1190
size_out *= 2;
1191
if (!(tmp = realloc( cred_out, size_out ))) goto done;
1192
cred_out = tmp;
1193
}
1194
1195
if (ret)
1196
{
1197
CREDENTIALW *credential;
1198
DWORD size = sizeof(*credential) + cred_out->targetname_size + cred_out->username_size + cred_out->comment_size +
1199
cred_out->blob_size;
1200
1201
if (!(credential = calloc( 1, size )))
1202
{
1203
err = ERROR_OUTOFMEMORY;
1204
goto done;
1205
}
1206
ptr = (WCHAR *)(credential + 1);
1207
1208
credential->Type = CRED_TYPE_DOMAIN_PASSWORD;
1209
memcpy( ptr, (char *)cred_out + cred_out->targetname_offset, cred_out->targetname_size );
1210
credential->TargetName = ptr;
1211
ptr += lstrlenW( ptr ) + 1;
1212
if (cred_out->comment_size)
1213
{
1214
memcpy( ptr, (char *)cred_out + cred_out->comment_offset, cred_out->comment_size );
1215
credential->Comment = ptr;
1216
ptr += lstrlenW( ptr ) + 1;
1217
}
1218
credential->LastWritten = cred_out->last_written;
1219
if ((credential->CredentialBlobSize = cred_out->blob_size))
1220
{
1221
memcpy( ptr, (char *)cred_out + cred_out->blob_offset, cred_out->blob_size );
1222
credential->CredentialBlob = (BYTE *)ptr;
1223
ptr += cred_out->blob_size / sizeof(WCHAR);
1224
}
1225
credential->Persist = CRED_PERSIST_LOCAL_MACHINE;
1226
memcpy( ptr, (char *)cred_out + cred_out->username_offset, cred_out->username_size );
1227
credential->UserName = ptr;
1228
1229
*ret_credential = credential;
1230
err = ERROR_SUCCESS;
1231
}
1232
1233
done:
1234
free( cred_in );
1235
free( cred_out );
1236
CloseHandle( mgr );
1237
return err;
1238
}
1239
1240
/******************************************************************************
1241
* CredReadW [ADVAPI32.@]
1242
*/
1243
BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential)
1244
{
1245
HKEY hkeyMgr;
1246
HKEY hkeyCred;
1247
DWORD ret;
1248
LPWSTR key_name;
1249
DWORD len;
1250
BYTE key_data[KEY_SIZE];
1251
1252
TRACE("(%s, %ld, 0x%lx, %p)\n", debugstr_w(TargetName), Type, Flags, Credential);
1253
1254
if (!TargetName)
1255
{
1256
SetLastError(ERROR_INVALID_PARAMETER);
1257
return FALSE;
1258
}
1259
1260
if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
1261
{
1262
FIXME("unhandled type %ld\n", Type);
1263
SetLastError(ERROR_INVALID_PARAMETER);
1264
return FALSE;
1265
}
1266
1267
if (Flags)
1268
{
1269
FIXME("unhandled flags 0x%lx\n", Flags);
1270
SetLastError(ERROR_INVALID_FLAGS);
1271
return FALSE;
1272
}
1273
1274
if (Type == CRED_TYPE_DOMAIN_PASSWORD)
1275
{
1276
ret = host_read_credential( TargetName, Credential );
1277
if (ret != ERROR_SUCCESS && ret != ERROR_NOT_SUPPORTED)
1278
{
1279
SetLastError(ret);
1280
return FALSE;
1281
}
1282
if (ret == ERROR_SUCCESS) return TRUE;
1283
}
1284
1285
ret = open_cred_mgr_key(&hkeyMgr, FALSE);
1286
if (ret != ERROR_SUCCESS)
1287
{
1288
WARN("couldn't open/create manager key, error %ld\n", ret);
1289
SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
1290
return FALSE;
1291
}
1292
1293
ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
1294
if (ret != ERROR_SUCCESS)
1295
{
1296
RegCloseKey(hkeyMgr);
1297
SetLastError(ret);
1298
return FALSE;
1299
}
1300
1301
key_name = get_key_name_for_target(TargetName, Type);
1302
ret = RegOpenKeyExW(hkeyMgr, key_name, 0, KEY_QUERY_VALUE, &hkeyCred);
1303
free(key_name);
1304
if (ret != ERROR_SUCCESS)
1305
{
1306
TRACE("credentials for target name %s not found\n", debugstr_w(TargetName));
1307
SetLastError(ERROR_NOT_FOUND);
1308
return FALSE;
1309
}
1310
1311
len = sizeof(**Credential);
1312
ret = registry_read_credential(hkeyCred, NULL, key_data, NULL, &len);
1313
if (ret == ERROR_SUCCESS)
1314
{
1315
*Credential = malloc(len);
1316
if (*Credential)
1317
{
1318
len = sizeof(**Credential);
1319
ret = registry_read_credential(hkeyCred, *Credential, key_data,
1320
(char *)(*Credential + 1), &len);
1321
}
1322
else
1323
ret = ERROR_OUTOFMEMORY;
1324
}
1325
1326
RegCloseKey(hkeyCred);
1327
RegCloseKey(hkeyMgr);
1328
1329
if (ret != ERROR_SUCCESS)
1330
{
1331
SetLastError(ret);
1332
return FALSE;
1333
}
1334
return TRUE;
1335
}
1336
1337
/******************************************************************************
1338
* CredReadDomainCredentialsA [ADVAPI32.@]
1339
*/
1340
BOOL WINAPI CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation,
1341
DWORD Flags, DWORD *Size, PCREDENTIALA **Credentials)
1342
{
1343
PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW;
1344
INT len;
1345
DWORD i;
1346
WCHAR *buffer, *end;
1347
BOOL ret;
1348
PCREDENTIALW* CredentialsW;
1349
1350
TRACE("(%p, 0x%lx, %p, %p)\n", TargetInformation, Flags, Size, Credentials);
1351
1352
/* follow Windows behavior - do not test for NULL, initialize early */
1353
*Size = 0;
1354
*Credentials = NULL;
1355
1356
if (!TargetInformation)
1357
{
1358
SetLastError(ERROR_INVALID_PARAMETER);
1359
return FALSE;
1360
}
1361
1362
len = sizeof(*TargetInformationW);
1363
if (TargetInformation->TargetName)
1364
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->TargetName, -1, NULL, 0) * sizeof(WCHAR);
1365
if (TargetInformation->NetbiosServerName)
1366
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosServerName, -1, NULL, 0) * sizeof(WCHAR);
1367
if (TargetInformation->DnsServerName)
1368
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsServerName, -1, NULL, 0) * sizeof(WCHAR);
1369
if (TargetInformation->NetbiosDomainName)
1370
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosDomainName, -1, NULL, 0) * sizeof(WCHAR);
1371
if (TargetInformation->DnsDomainName)
1372
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsDomainName, -1, NULL, 0) * sizeof(WCHAR);
1373
if (TargetInformation->DnsTreeName)
1374
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsTreeName, -1, NULL, 0) * sizeof(WCHAR);
1375
if (TargetInformation->PackageName)
1376
len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->PackageName, -1, NULL, 0) * sizeof(WCHAR);
1377
1378
TargetInformationW = malloc(len);
1379
if (!TargetInformationW)
1380
{
1381
SetLastError(ERROR_OUTOFMEMORY);
1382
return FALSE;
1383
}
1384
buffer = (WCHAR*)(TargetInformationW + 1);
1385
end = (WCHAR *)((char *)TargetInformationW + len);
1386
1387
if (TargetInformation->TargetName)
1388
{
1389
TargetInformationW->TargetName = buffer;
1390
buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->TargetName, -1,
1391
TargetInformationW->TargetName, end - buffer);
1392
} else
1393
TargetInformationW->TargetName = NULL;
1394
1395
if (TargetInformation->NetbiosServerName)
1396
{
1397
TargetInformationW->NetbiosServerName = buffer;
1398
buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosServerName, -1,
1399
TargetInformationW->NetbiosServerName, end - buffer);
1400
} else
1401
TargetInformationW->NetbiosServerName = NULL;
1402
1403
if (TargetInformation->DnsServerName)
1404
{
1405
TargetInformationW->DnsServerName = buffer;
1406
buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsServerName, -1,
1407
TargetInformationW->DnsServerName, end - buffer);
1408
} else
1409
TargetInformationW->DnsServerName = NULL;
1410
1411
if (TargetInformation->NetbiosDomainName)
1412
{
1413
TargetInformationW->NetbiosDomainName = buffer;
1414
buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosDomainName, -1,
1415
TargetInformationW->NetbiosDomainName, end - buffer);
1416
} else
1417
TargetInformationW->NetbiosDomainName = NULL;
1418
1419
if (TargetInformation->DnsDomainName)
1420
{
1421
TargetInformationW->DnsDomainName = buffer;
1422
buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsDomainName, -1,
1423
TargetInformationW->DnsDomainName, end - buffer);
1424
} else
1425
TargetInformationW->DnsDomainName = NULL;
1426
1427
if (TargetInformation->DnsTreeName)
1428
{
1429
TargetInformationW->DnsTreeName = buffer;
1430
buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsTreeName, -1,
1431
TargetInformationW->DnsTreeName, end - buffer);
1432
} else
1433
TargetInformationW->DnsTreeName = NULL;
1434
1435
if (TargetInformation->PackageName)
1436
{
1437
TargetInformationW->PackageName = buffer;
1438
MultiByteToWideChar(CP_ACP, 0, TargetInformation->PackageName, -1,
1439
TargetInformationW->PackageName, end - buffer);
1440
} else
1441
TargetInformationW->PackageName = NULL;
1442
1443
TargetInformationW->Flags = TargetInformation->Flags;
1444
TargetInformationW->CredTypeCount = TargetInformation->CredTypeCount;
1445
TargetInformationW->CredTypes = TargetInformation->CredTypes;
1446
1447
ret = CredReadDomainCredentialsW(TargetInformationW, Flags, Size, &CredentialsW);
1448
1449
free(TargetInformationW);
1450
1451
if (ret)
1452
{
1453
char *buf;
1454
INT needed;
1455
1456
len = *Size * sizeof(PCREDENTIALA);
1457
for (i = 0; i < *Size; i++)
1458
len += convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, 0);
1459
1460
*Credentials = malloc(len);
1461
if (!*Credentials)
1462
{
1463
CredFree(CredentialsW);
1464
SetLastError(ERROR_OUTOFMEMORY);
1465
return FALSE;
1466
}
1467
1468
buf = (char *)&(*Credentials)[*Size];
1469
len -= *Size * sizeof(PCREDENTIALA);
1470
for (i = 0; i < *Size; i++)
1471
{
1472
(*Credentials)[i] = (PCREDENTIALA)buf;
1473
needed = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], len);
1474
buf += needed;
1475
len -= needed;
1476
}
1477
1478
CredFree(CredentialsW);
1479
}
1480
return ret;
1481
}
1482
1483
/******************************************************************************
1484
* CredReadDomainCredentialsW [ADVAPI32.@]
1485
*/
1486
BOOL WINAPI CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation, DWORD Flags,
1487
DWORD *Size, PCREDENTIALW **Credentials)
1488
{
1489
FIXME("(%p, 0x%lx, %p, %p) stub\n", TargetInformation, Flags, Size, Credentials);
1490
1491
/* follow Windows behavior - do not test for NULL, initialize early */
1492
*Size = 0;
1493
*Credentials = NULL;
1494
if (!TargetInformation)
1495
{
1496
SetLastError(ERROR_INVALID_PARAMETER);
1497
return FALSE;
1498
}
1499
1500
SetLastError(ERROR_NOT_FOUND);
1501
return FALSE;
1502
}
1503
1504
/******************************************************************************
1505
* CredWriteA [ADVAPI32.@]
1506
*/
1507
BOOL WINAPI CredWriteA(PCREDENTIALA Credential, DWORD Flags)
1508
{
1509
BOOL ret;
1510
INT len;
1511
PCREDENTIALW CredentialW;
1512
1513
TRACE("(%p, 0x%lx)\n", Credential, Flags);
1514
1515
if (!Credential || !Credential->TargetName)
1516
{
1517
SetLastError(ERROR_INVALID_PARAMETER);
1518
return FALSE;
1519
}
1520
1521
len = convert_PCREDENTIALA_to_PCREDENTIALW(Credential, NULL, 0);
1522
CredentialW = malloc(len);
1523
if (!CredentialW)
1524
{
1525
SetLastError(ERROR_OUTOFMEMORY);
1526
return FALSE;
1527
}
1528
1529
convert_PCREDENTIALA_to_PCREDENTIALW(Credential, CredentialW, len);
1530
1531
ret = CredWriteW(CredentialW, Flags);
1532
1533
free(CredentialW);
1534
1535
return ret;
1536
}
1537
1538
/******************************************************************************
1539
* CredWriteW [ADVAPI32.@]
1540
*/
1541
BOOL WINAPI CredWriteW(PCREDENTIALW Credential, DWORD Flags)
1542
{
1543
HKEY hkeyMgr;
1544
HKEY hkeyCred;
1545
DWORD ret;
1546
LPWSTR key_name;
1547
BYTE key_data[KEY_SIZE];
1548
1549
TRACE("(%p, 0x%lx)\n", Credential, Flags);
1550
1551
if (!Credential || !Credential->TargetName)
1552
{
1553
SetLastError(ERROR_INVALID_PARAMETER);
1554
return FALSE;
1555
}
1556
1557
if (Flags & ~CRED_PRESERVE_CREDENTIAL_BLOB)
1558
{
1559
FIXME("unhandled flags 0x%lx\n", Flags);
1560
SetLastError(ERROR_INVALID_FLAGS);
1561
return FALSE;
1562
}
1563
1564
if (Credential->Type != CRED_TYPE_GENERIC && Credential->Type != CRED_TYPE_DOMAIN_PASSWORD)
1565
{
1566
FIXME("unhandled type %ld\n", Credential->Type);
1567
SetLastError(ERROR_INVALID_PARAMETER);
1568
return FALSE;
1569
}
1570
1571
TRACE("Credential->Flags = 0x%08lx\n", Credential->Flags);
1572
TRACE("Credential->Type = %lu\n", Credential->Type);
1573
TRACE("Credential->TargetName = %s\n", debugstr_w(Credential->TargetName));
1574
TRACE("Credential->Comment = %s\n", debugstr_w(Credential->Comment));
1575
TRACE("Credential->Persist = %lu\n", Credential->Persist);
1576
TRACE("Credential->TargetAlias = %s\n", debugstr_w(Credential->TargetAlias));
1577
TRACE("Credential->UserName = %s\n", debugstr_w(Credential->UserName));
1578
1579
if (Credential->Type == CRED_TYPE_DOMAIN_PASSWORD)
1580
{
1581
if (!Credential->UserName ||
1582
(Credential->Persist == CRED_PERSIST_ENTERPRISE &&
1583
(!wcschr(Credential->UserName, '\\') && !wcschr(Credential->UserName, '@'))))
1584
{
1585
ERR("bad username %s\n", debugstr_w(Credential->UserName));
1586
SetLastError(ERROR_BAD_USERNAME);
1587
return FALSE;
1588
}
1589
}
1590
1591
if (!Credential->AttributeCount &&
1592
Credential->Type == CRED_TYPE_DOMAIN_PASSWORD &&
1593
(Credential->Persist == CRED_PERSIST_LOCAL_MACHINE || Credential->Persist == CRED_PERSIST_ENTERPRISE))
1594
{
1595
ret = host_write_credential(Credential, Flags & CRED_PRESERVE_CREDENTIAL_BLOB);
1596
if (ret != ERROR_SUCCESS && ret != ERROR_NOT_SUPPORTED)
1597
{
1598
SetLastError(ret);
1599
return FALSE;
1600
}
1601
if (ret == ERROR_SUCCESS) return TRUE;
1602
}
1603
1604
ret = open_cred_mgr_key(&hkeyMgr, FALSE);
1605
if (ret != ERROR_SUCCESS)
1606
{
1607
WARN("couldn't open/create manager key, error %ld\n", ret);
1608
SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
1609
return FALSE;
1610
}
1611
1612
ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
1613
if (ret != ERROR_SUCCESS)
1614
{
1615
RegCloseKey(hkeyMgr);
1616
SetLastError(ret);
1617
return FALSE;
1618
}
1619
1620
key_name = get_key_name_for_target(Credential->TargetName, Credential->Type);
1621
ret = RegCreateKeyExW(hkeyMgr, key_name, 0, NULL,
1622
Credential->Persist == CRED_PERSIST_SESSION ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE,
1623
KEY_READ|KEY_WRITE, NULL, &hkeyCred, NULL);
1624
free(key_name);
1625
if (ret != ERROR_SUCCESS)
1626
{
1627
TRACE("credentials for target name %s not found\n",
1628
debugstr_w(Credential->TargetName));
1629
SetLastError(ERROR_NOT_FOUND);
1630
return FALSE;
1631
}
1632
1633
ret = registry_write_credential(hkeyCred, Credential, key_data,
1634
Flags & CRED_PRESERVE_CREDENTIAL_BLOB);
1635
1636
RegCloseKey(hkeyCred);
1637
RegCloseKey(hkeyMgr);
1638
1639
if (ret != ERROR_SUCCESS)
1640
{
1641
SetLastError(ret);
1642
return FALSE;
1643
}
1644
return TRUE;
1645
}
1646
1647
/******************************************************************************
1648
* CredGetSessionTypes [ADVAPI32.@]
1649
*/
1650
WINADVAPI BOOL WINAPI CredGetSessionTypes(DWORD persistCount, LPDWORD persists)
1651
{
1652
TRACE("(%lu, %p)\n", persistCount, persists);
1653
1654
memset(persists, CRED_PERSIST_NONE, persistCount*sizeof(*persists));
1655
if (CRED_TYPE_GENERIC < persistCount)
1656
{
1657
persists[CRED_TYPE_GENERIC] = CRED_PERSIST_ENTERPRISE;
1658
1659
if (CRED_TYPE_DOMAIN_PASSWORD < persistCount)
1660
{
1661
persists[CRED_TYPE_DOMAIN_PASSWORD] = CRED_PERSIST_ENTERPRISE;
1662
}
1663
}
1664
return TRUE;
1665
}
1666
1667
/******************************************************************************
1668
* CredMarshalCredentialA [ADVAPI32.@]
1669
*/
1670
BOOL WINAPI CredMarshalCredentialA( CRED_MARSHAL_TYPE type, PVOID cred, LPSTR *out )
1671
{
1672
BOOL ret;
1673
WCHAR *outW;
1674
1675
TRACE("%u, %p, %p\n", type, cred, out);
1676
1677
if ((ret = CredMarshalCredentialW( type, cred, &outW )))
1678
{
1679
int len = WideCharToMultiByte( CP_ACP, 0, outW, -1, NULL, 0, NULL, NULL );
1680
if (!(*out = malloc( len )))
1681
{
1682
free( outW );
1683
return FALSE;
1684
}
1685
WideCharToMultiByte( CP_ACP, 0, outW, -1, *out, len, NULL, NULL );
1686
free( outW );
1687
}
1688
return ret;
1689
}
1690
1691
static UINT cred_encode( const char *bin, unsigned int len, WCHAR *cred )
1692
{
1693
static const char enc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#-";
1694
UINT n = 0, x;
1695
1696
while (len > 0)
1697
{
1698
cred[n++] = enc[bin[0] & 0x3f];
1699
x = (bin[0] & 0xc0) >> 6;
1700
if (len == 1)
1701
{
1702
cred[n++] = enc[x];
1703
break;
1704
}
1705
cred[n++] = enc[((bin[1] & 0xf) << 2) | x];
1706
x = (bin[1] & 0xf0) >> 4;
1707
if (len == 2)
1708
{
1709
cred[n++] = enc[x];
1710
break;
1711
}
1712
cred[n++] = enc[((bin[2] & 0x3) << 4) | x];
1713
cred[n++] = enc[(bin[2] & 0xfc) >> 2];
1714
bin += 3;
1715
len -= 3;
1716
}
1717
return n;
1718
}
1719
1720
/******************************************************************************
1721
* CredMarshalCredentialW [ADVAPI32.@]
1722
*/
1723
BOOL WINAPI CredMarshalCredentialW( CRED_MARSHAL_TYPE type, PVOID cred, LPWSTR *out )
1724
{
1725
CERT_CREDENTIAL_INFO *cert = cred;
1726
USERNAME_TARGET_CREDENTIAL_INFO *target = cred;
1727
DWORD len, size;
1728
WCHAR *p;
1729
1730
TRACE("%u, %p, %p\n", type, cred, out);
1731
1732
if (!cred || (type == CertCredential && cert->cbSize < sizeof(*cert)) ||
1733
(type != CertCredential && type != UsernameTargetCredential && type != BinaryBlobCredential) ||
1734
(type == UsernameTargetCredential && (!target->UserName || !target->UserName[0])))
1735
{
1736
SetLastError( ERROR_INVALID_PARAMETER );
1737
return FALSE;
1738
}
1739
switch (type)
1740
{
1741
case CertCredential:
1742
{
1743
size = (sizeof(cert->rgbHashOfCert) + 2) * 4 / 3;
1744
if (!(p = malloc( (size + 4) * sizeof(WCHAR) ))) return FALSE;
1745
p[0] = '@';
1746
p[1] = '@';
1747
p[2] = 'A' + type;
1748
len = cred_encode( (const char *)cert->rgbHashOfCert, sizeof(cert->rgbHashOfCert), p + 3 );
1749
p[len + 3] = 0;
1750
break;
1751
}
1752
case UsernameTargetCredential:
1753
{
1754
len = lstrlenW( target->UserName );
1755
size = (sizeof(DWORD) + len * sizeof(WCHAR) + 2) * 4 / 3;
1756
if (!(p = malloc( (size + 4) * sizeof(WCHAR) ))) return FALSE;
1757
p[0] = '@';
1758
p[1] = '@';
1759
p[2] = 'A' + type;
1760
size = len * sizeof(WCHAR);
1761
len = cred_encode( (const char *)&size, sizeof(DWORD), p + 3 );
1762
len += cred_encode( (const char *)target->UserName, size, p + 3 + len );
1763
p[len + 3] = 0;
1764
break;
1765
}
1766
case BinaryBlobCredential:
1767
FIXME("BinaryBlobCredential not implemented\n");
1768
return FALSE;
1769
default:
1770
return FALSE;
1771
}
1772
*out = p;
1773
return TRUE;
1774
}
1775
1776
/******************************************************************************
1777
* CredUnmarshalCredentialA [ADVAPI32.@]
1778
*/
1779
BOOL WINAPI CredUnmarshalCredentialA( LPCSTR cred, PCRED_MARSHAL_TYPE type, PVOID *out )
1780
{
1781
BOOL ret;
1782
WCHAR *credW = NULL;
1783
1784
TRACE("%s, %p, %p\n", debugstr_a(cred), type, out);
1785
1786
if (cred)
1787
{
1788
int len = MultiByteToWideChar( CP_ACP, 0, cred, -1, NULL, 0 );
1789
if (!(credW = malloc( len * sizeof(WCHAR) ))) return FALSE;
1790
MultiByteToWideChar( CP_ACP, 0, cred, -1, credW, len );
1791
}
1792
ret = CredUnmarshalCredentialW( credW, type, out );
1793
free( credW );
1794
return ret;
1795
}
1796
1797
static inline char char_decode( WCHAR c )
1798
{
1799
if (c >= 'A' && c <= 'Z') return c - 'A';
1800
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
1801
if (c >= '0' && c <= '9') return c - '0' + 52;
1802
if (c == '#') return 62;
1803
if (c == '-') return 63;
1804
return 64;
1805
}
1806
1807
static BOOL cred_decode( const WCHAR *cred, unsigned int len, char *buf )
1808
{
1809
unsigned int i = 0;
1810
char c0, c1, c2, c3;
1811
const WCHAR *p = cred;
1812
1813
while (len >= 4)
1814
{
1815
if ((c0 = char_decode( p[0] )) > 63) return FALSE;
1816
if ((c1 = char_decode( p[1] )) > 63) return FALSE;
1817
if ((c2 = char_decode( p[2] )) > 63) return FALSE;
1818
if ((c3 = char_decode( p[3] )) > 63) return FALSE;
1819
1820
buf[i + 0] = (c1 << 6) | c0;
1821
buf[i + 1] = (c2 << 4) | (c1 >> 2);
1822
buf[i + 2] = (c3 << 2) | (c2 >> 4);
1823
len -= 4;
1824
i += 3;
1825
p += 4;
1826
}
1827
if (len == 3)
1828
{
1829
if ((c0 = char_decode( p[0] )) > 63) return FALSE;
1830
if ((c1 = char_decode( p[1] )) > 63) return FALSE;
1831
if ((c2 = char_decode( p[2] )) > 63) return FALSE;
1832
1833
buf[i + 0] = (c1 << 6) | c0;
1834
buf[i + 1] = (c2 << 4) | (c1 >> 2);
1835
}
1836
else if (len == 2)
1837
{
1838
if ((c0 = char_decode( p[0] )) > 63) return FALSE;
1839
if ((c1 = char_decode( p[1] )) > 63) return FALSE;
1840
1841
buf[i + 0] = (c1 << 6) | c0;
1842
}
1843
else if (len == 1)
1844
{
1845
return FALSE;
1846
}
1847
return TRUE;
1848
}
1849
1850
/******************************************************************************
1851
* CredUnmarshalCredentialW [ADVAPI32.@]
1852
*/
1853
BOOL WINAPI CredUnmarshalCredentialW( LPCWSTR cred, PCRED_MARSHAL_TYPE type, PVOID *out )
1854
{
1855
unsigned int len, buflen;
1856
1857
TRACE("%s, %p, %p\n", debugstr_w(cred), type, out);
1858
1859
if (!cred || cred[0] != '@' || cred[1] != '@' ||
1860
char_decode( cred[2] ) > 63)
1861
{
1862
SetLastError( ERROR_INVALID_PARAMETER );
1863
return FALSE;
1864
}
1865
len = lstrlenW( cred + 3 );
1866
*type = char_decode( cred[2] );
1867
switch (*type)
1868
{
1869
case CertCredential:
1870
{
1871
char hash[CERT_HASH_LENGTH];
1872
CERT_CREDENTIAL_INFO *cert;
1873
1874
if (len != 27 || !cred_decode( cred + 3, len, hash ))
1875
{
1876
SetLastError( ERROR_INVALID_PARAMETER );
1877
return FALSE;
1878
}
1879
if (!(cert = malloc( sizeof(*cert) ))) return FALSE;
1880
memcpy( cert->rgbHashOfCert, hash, sizeof(cert->rgbHashOfCert) );
1881
cert->cbSize = sizeof(*cert);
1882
*out = cert;
1883
break;
1884
}
1885
case UsernameTargetCredential:
1886
{
1887
USERNAME_TARGET_CREDENTIAL_INFO *target;
1888
DWORD size;
1889
1890
if (len < 9 || !cred_decode( cred + 3, 6, (char *)&size ) ||
1891
size % sizeof(WCHAR) || len - 6 != (size * 4 + 2) / 3)
1892
{
1893
SetLastError( ERROR_INVALID_PARAMETER );
1894
return FALSE;
1895
}
1896
buflen = sizeof(*target) + size + sizeof(WCHAR);
1897
if (!(target = malloc( buflen ))) return FALSE;
1898
if (!cred_decode( cred + 9, len - 6, (char *)(target + 1) ))
1899
{
1900
free( target );
1901
return FALSE;
1902
}
1903
target->UserName = (WCHAR *)(target + 1);
1904
target->UserName[size / sizeof(WCHAR)] = 0;
1905
*out = target;
1906
break;
1907
}
1908
case BinaryBlobCredential:
1909
FIXME("BinaryBlobCredential not implemented\n");
1910
return FALSE;
1911
default:
1912
WARN("unhandled type %u\n", *type);
1913
SetLastError( ERROR_INVALID_PARAMETER );
1914
return FALSE;
1915
}
1916
return TRUE;
1917
}
1918
1919
/******************************************************************************
1920
* CredIsMarshaledCredentialW [ADVAPI32.@]
1921
*
1922
* Check, if the name parameter is a marshaled credential, hash or binary blob
1923
*
1924
* PARAMS
1925
* name the name to check
1926
*
1927
* RETURNS
1928
* TRUE: the name parameter is a marshaled credential, hash or binary blob
1929
* FALSE: the name is a plain username
1930
*/
1931
BOOL WINAPI CredIsMarshaledCredentialW(LPCWSTR name)
1932
{
1933
TRACE("(%s)\n", debugstr_w(name));
1934
1935
if (name && name[0] == '@' && name[1] == '@' && name[2] > 'A' && name[3])
1936
{
1937
char hash[CERT_HASH_LENGTH];
1938
int len = lstrlenW(name + 3 );
1939
DWORD size;
1940
1941
if ((name[2] - 'A') == CertCredential && (len == 27) && cred_decode(name + 3, len, hash))
1942
return TRUE;
1943
1944
if (((name[2] - 'A') == UsernameTargetCredential) &&
1945
(len >= 9) && cred_decode(name + 3, 6, (char *)&size) && size)
1946
return TRUE;
1947
1948
if ((name[2] - 'A') == BinaryBlobCredential)
1949
FIXME("BinaryBlobCredential not checked\n");
1950
1951
if ((name[2] - 'A') > BinaryBlobCredential)
1952
TRACE("unknown type: %d\n", (name[2] - 'A'));
1953
}
1954
1955
SetLastError(ERROR_INVALID_PARAMETER);
1956
return FALSE;
1957
}
1958
1959
/******************************************************************************
1960
* CredIsMarshaledCredentialA [ADVAPI32.@]
1961
*
1962
* See CredIsMarshaledCredentialW
1963
*
1964
*/
1965
BOOL WINAPI CredIsMarshaledCredentialA(LPCSTR name)
1966
{
1967
LPWSTR nameW = NULL;
1968
BOOL res;
1969
int len;
1970
1971
TRACE("(%s)\n", debugstr_a(name));
1972
1973
if (name)
1974
{
1975
len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
1976
nameW = malloc(len * sizeof(WCHAR));
1977
MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, len);
1978
}
1979
1980
res = CredIsMarshaledCredentialW(nameW);
1981
free(nameW);
1982
return res;
1983
}
1984
1985