2 * Credential Management APIs
4 * Copyright 2007 Robert Shearman for CodeWeavers
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.
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.
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
25 WINE_DEFAULT_DEBUG_CHANNEL(cred
);
27 /* the size of the ARC4 key used to encrypt the password data */
30 static const WCHAR wszCredentialManagerKey
[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
31 'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0};
32 static const WCHAR wszEncryptionKeyValue
[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0};
34 static const WCHAR wszFlagsValue
[] = {'F','l','a','g','s',0};
35 static const WCHAR wszTypeValue
[] = {'T','y','p','e',0};
36 static const WCHAR wszCommentValue
[] = {'C','o','m','m','e','n','t',0};
37 static const WCHAR wszLastWrittenValue
[] = {'L','a','s','t','W','r','i','t','t','e','n',0};
38 static const WCHAR wszPersistValue
[] = {'P','e','r','s','i','s','t',0};
39 static const WCHAR wszTargetAliasValue
[] = {'T','a','r','g','e','t','A','l','i','a','s',0};
40 static const WCHAR wszUserNameValue
[] = {'U','s','e','r','N','a','m','e',0};
41 static const WCHAR wszPasswordValue
[] = {'P','a','s','s','w','o','r','d',0};
43 static DWORD
read_credential_blob(HKEY hkey
, const BYTE key_data
[KEY_SIZE
],
44 LPBYTE credential_blob
,
45 DWORD
*credential_blob_size
)
50 *credential_blob_size
= 0;
51 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, NULL
, credential_blob_size
);
52 if (ret
!= ERROR_SUCCESS
)
54 else if (type
!= REG_BINARY
)
55 return ERROR_REGISTRY_CORRUPT
;
61 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, credential_blob
,
62 credential_blob_size
);
63 if (ret
!= ERROR_SUCCESS
)
65 else if (type
!= REG_BINARY
)
66 return ERROR_REGISTRY_CORRUPT
;
68 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
69 key
.Buffer
= (unsigned char *)key_data
;
71 data
.Length
= data
.MaximumLength
= *credential_blob_size
;
72 data
.Buffer
= credential_blob
;
73 SystemFunction032(&data
, &key
);
78 static DWORD
registry_read_credential(HKEY hkey
, PCREDENTIALW credential
,
79 const BYTE key_data
[KEY_SIZE
],
80 char *buffer
, DWORD
*len
)
86 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, NULL
, &count
);
87 if (ret
!= ERROR_SUCCESS
)
89 else if (type
!= REG_SZ
)
90 return ERROR_REGISTRY_CORRUPT
;
94 credential
->TargetName
= (LPWSTR
)buffer
;
95 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, (LPVOID
)credential
->TargetName
,
97 if (ret
!= ERROR_SUCCESS
)
99 else if (type
!= REG_SZ
)
100 return ERROR_REGISTRY_CORRUPT
;
104 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, NULL
, &count
);
105 if (ret
!= ERROR_FILE_NOT_FOUND
)
107 if (ret
!= ERROR_SUCCESS
)
109 else if (type
!= REG_SZ
)
110 return ERROR_REGISTRY_CORRUPT
;
115 credential
->Comment
= (LPWSTR
)buffer
;
116 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, (LPVOID
)credential
->Comment
,
118 if (ret
== ERROR_FILE_NOT_FOUND
)
119 credential
->Comment
= NULL
;
120 else if (ret
!= ERROR_SUCCESS
)
122 else if (type
!= REG_SZ
)
123 return ERROR_REGISTRY_CORRUPT
;
128 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, NULL
, &count
);
129 if (ret
!= ERROR_FILE_NOT_FOUND
)
131 if (ret
!= ERROR_SUCCESS
)
133 else if (type
!= REG_SZ
)
134 return ERROR_REGISTRY_CORRUPT
;
139 credential
->TargetAlias
= (LPWSTR
)buffer
;
140 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, (LPVOID
)credential
->TargetAlias
,
142 if (ret
== ERROR_FILE_NOT_FOUND
)
143 credential
->TargetAlias
= NULL
;
144 else if (ret
!= ERROR_SUCCESS
)
146 else if (type
!= REG_SZ
)
147 return ERROR_REGISTRY_CORRUPT
;
152 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, NULL
, &count
);
153 if (ret
!= ERROR_FILE_NOT_FOUND
)
155 if (ret
!= ERROR_SUCCESS
)
157 else if (type
!= REG_SZ
)
158 return ERROR_REGISTRY_CORRUPT
;
163 credential
->UserName
= (LPWSTR
)buffer
;
164 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, (LPVOID
)credential
->UserName
,
166 if (ret
== ERROR_FILE_NOT_FOUND
)
167 credential
->UserName
= NULL
;
168 else if (ret
!= ERROR_SUCCESS
)
170 else if (type
!= REG_SZ
)
171 return ERROR_REGISTRY_CORRUPT
;
176 ret
= read_credential_blob(hkey
, key_data
, NULL
, &count
);
177 if (ret
!= ERROR_FILE_NOT_FOUND
)
179 if (ret
!= ERROR_SUCCESS
)
185 credential
->CredentialBlob
= (LPBYTE
)buffer
;
186 ret
= read_credential_blob(hkey
, key_data
, credential
->CredentialBlob
, &count
);
187 if (ret
== ERROR_FILE_NOT_FOUND
)
188 credential
->CredentialBlob
= NULL
;
189 else if (ret
!= ERROR_SUCCESS
)
191 credential
->CredentialBlobSize
= count
;
194 /* FIXME: Attributes */
197 credential
->AttributeCount
= 0;
198 credential
->Attributes
= NULL
;
201 if (!credential
) return ERROR_SUCCESS
;
203 count
= sizeof(credential
->Flags
);
204 ret
= RegQueryValueExW(hkey
, wszFlagsValue
, NULL
, &type
, (LPVOID
)&credential
->Flags
,
206 if (ret
!= ERROR_SUCCESS
)
208 else if (type
!= REG_DWORD
)
209 return ERROR_REGISTRY_CORRUPT
;
210 count
= sizeof(credential
->Type
);
211 ret
= RegQueryValueExW(hkey
, wszTypeValue
, NULL
, &type
, (LPVOID
)&credential
->Type
,
213 if (ret
!= ERROR_SUCCESS
)
215 else if (type
!= REG_DWORD
)
216 return ERROR_REGISTRY_CORRUPT
;
218 count
= sizeof(credential
->LastWritten
);
219 ret
= RegQueryValueExW(hkey
, wszLastWrittenValue
, NULL
, &type
, (LPVOID
)&credential
->LastWritten
,
221 if (ret
!= ERROR_SUCCESS
)
223 else if (type
!= REG_BINARY
)
224 return ERROR_REGISTRY_CORRUPT
;
225 count
= sizeof(credential
->Persist
);
226 ret
= RegQueryValueExW(hkey
, wszPersistValue
, NULL
, &type
, (LPVOID
)&credential
->Persist
,
228 if (ret
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
229 return ERROR_REGISTRY_CORRUPT
;
234 static DWORD
mac_read_credential_from_item(SecKeychainItemRef item
, BOOL require_password
,
235 PCREDENTIALW credential
, char *buffer
,
239 UInt32 i
, cred_blob_len
;
242 BOOL user_name_present
= FALSE
;
243 SecKeychainAttributeInfo info
;
244 SecKeychainAttributeList
*attr_list
;
245 UInt32 info_tags
[] = { kSecServiceItemAttr
, kSecAccountItemAttr
,
246 kSecCommentItemAttr
, kSecCreationDateItemAttr
};
247 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
248 info
.tag
= info_tags
;
250 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, &cred_blob
);
251 if (status
== errSecAuthFailed
&& !require_password
)
255 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, NULL
);
259 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
260 return ERROR_NOT_FOUND
;
263 for (i
= 0; i
< attr_list
->count
; i
++)
264 if (attr_list
->attr
[i
].tag
== kSecAccountItemAttr
&& attr_list
->attr
[i
].data
)
266 user_name_present
= TRUE
;
269 if (!user_name_present
)
271 WARN("no kSecAccountItemAttr for item\n");
272 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
273 return ERROR_NOT_FOUND
;
278 credential
->Flags
= 0;
279 credential
->Type
= CRED_TYPE_DOMAIN_PASSWORD
;
280 credential
->TargetName
= NULL
;
281 credential
->Comment
= NULL
;
282 memset(&credential
->LastWritten
, 0, sizeof(credential
->LastWritten
));
283 credential
->CredentialBlobSize
= 0;
284 credential
->CredentialBlob
= NULL
;
285 credential
->Persist
= CRED_PERSIST_LOCAL_MACHINE
;
286 credential
->AttributeCount
= 0;
287 credential
->Attributes
= NULL
;
288 credential
->TargetAlias
= NULL
;
289 credential
->UserName
= NULL
;
291 for (i
= 0; i
< attr_list
->count
; i
++)
293 switch (attr_list
->attr
[i
].tag
)
295 case kSecServiceItemAttr
:
296 TRACE("kSecServiceItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
297 (char *)attr_list
->attr
[i
].data
);
298 if (!attr_list
->attr
[i
].data
) continue;
302 credential
->TargetName
= (LPWSTR
)buffer
;
303 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
304 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
305 credential
->TargetName
[str_len
] = '\0';
306 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
307 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
312 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
313 attr_list
->attr
[i
].length
, NULL
, 0);
314 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
317 case kSecAccountItemAttr
:
320 TRACE("kSecAccountItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
321 (char *)attr_list
->attr
[i
].data
);
322 if (!attr_list
->attr
[i
].data
) continue;
323 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
324 attr_list
->attr
[i
].length
, NULL
, 0);
325 user
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
326 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
327 attr_list
->attr
[i
].length
, user
, str_len
);
328 user
[str_len
] = '\0';
331 case kSecCommentItemAttr
:
332 TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
333 (char *)attr_list
->attr
[i
].data
);
334 if (!attr_list
->attr
[i
].data
) continue;
338 credential
->Comment
= (LPWSTR
)buffer
;
339 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
340 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
341 credential
->Comment
[str_len
] = '\0';
342 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
343 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
348 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
349 attr_list
->attr
[i
].length
, NULL
, 0);
350 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
353 case kSecCreationDateItemAttr
:
354 TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
355 (char *)attr_list
->attr
[i
].data
);
358 LARGE_INTEGER win_time
;
361 memset(&tm
, 0, sizeof(tm
));
362 strptime(attr_list
->attr
[i
].data
, "%Y%m%d%H%M%SZ", &tm
);
364 RtlSecondsSince1970ToTime(time
, &win_time
);
365 credential
->LastWritten
.dwLowDateTime
= win_time
.u
.LowPart
;
366 credential
->LastWritten
.dwHighDateTime
= win_time
.u
.HighPart
;
370 FIXME("unhandled attribute %lu\n", attr_list
->attr
[i
].tag
);
379 credential
->UserName
= (LPWSTR
)buffer
;
380 str_len
= strlenW(user
);
381 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
384 memcpy(buffer
, user
, (str_len
+ 1) * sizeof(WCHAR
));
385 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
386 TRACE("UserName = %s\n", debugstr_w(credential
->UserName
));
396 credential
->CredentialBlob
= (BYTE
*)buffer
;
397 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
398 (LPWSTR
)buffer
, 0xffff);
399 credential
->CredentialBlobSize
= str_len
* sizeof(WCHAR
);
400 *len
+= str_len
* sizeof(WCHAR
);
405 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
407 *len
+= str_len
* sizeof(WCHAR
);
410 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
411 return ERROR_SUCCESS
;
415 static DWORD
write_credential_blob(HKEY hkey
, LPCWSTR target_name
, DWORD type
,
416 const BYTE key_data
[KEY_SIZE
],
417 const BYTE
*credential_blob
, DWORD credential_blob_size
)
419 LPBYTE encrypted_credential_blob
;
424 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
425 key
.Buffer
= (unsigned char *)key_data
;
427 encrypted_credential_blob
= heap_alloc(credential_blob_size
);
428 if (!encrypted_credential_blob
) return ERROR_OUTOFMEMORY
;
430 memcpy(encrypted_credential_blob
, credential_blob
, credential_blob_size
);
431 data
.Length
= data
.MaximumLength
= credential_blob_size
;
432 data
.Buffer
= encrypted_credential_blob
;
433 SystemFunction032(&data
, &key
);
435 ret
= RegSetValueExW(hkey
, wszPasswordValue
, 0, REG_BINARY
, encrypted_credential_blob
, credential_blob_size
);
436 heap_free(encrypted_credential_blob
);
441 static DWORD
registry_write_credential(HKEY hkey
, const CREDENTIALW
*credential
,
442 const BYTE key_data
[KEY_SIZE
], BOOL preserve_blob
)
445 FILETIME LastWritten
;
447 GetSystemTimeAsFileTime(&LastWritten
);
449 ret
= RegSetValueExW(hkey
, wszFlagsValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Flags
,
450 sizeof(credential
->Flags
));
451 if (ret
!= ERROR_SUCCESS
) return ret
;
452 ret
= RegSetValueExW(hkey
, wszTypeValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Type
,
453 sizeof(credential
->Type
));
454 if (ret
!= ERROR_SUCCESS
) return ret
;
455 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (LPVOID
)credential
->TargetName
,
456 sizeof(WCHAR
)*(strlenW(credential
->TargetName
)+1));
457 if (ret
!= ERROR_SUCCESS
) return ret
;
458 if (credential
->Comment
)
460 ret
= RegSetValueExW(hkey
, wszCommentValue
, 0, REG_SZ
, (LPVOID
)credential
->Comment
,
461 sizeof(WCHAR
)*(strlenW(credential
->Comment
)+1));
462 if (ret
!= ERROR_SUCCESS
) return ret
;
464 ret
= RegSetValueExW(hkey
, wszLastWrittenValue
, 0, REG_BINARY
, (LPVOID
)&LastWritten
,
465 sizeof(LastWritten
));
466 if (ret
!= ERROR_SUCCESS
) return ret
;
467 ret
= RegSetValueExW(hkey
, wszPersistValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Persist
,
468 sizeof(credential
->Persist
));
469 if (ret
!= ERROR_SUCCESS
) return ret
;
470 /* FIXME: Attributes */
471 if (credential
->TargetAlias
)
473 ret
= RegSetValueExW(hkey
, wszTargetAliasValue
, 0, REG_SZ
, (LPVOID
)credential
->TargetAlias
,
474 sizeof(WCHAR
)*(strlenW(credential
->TargetAlias
)+1));
475 if (ret
!= ERROR_SUCCESS
) return ret
;
477 if (credential
->UserName
)
479 ret
= RegSetValueExW(hkey
, wszUserNameValue
, 0, REG_SZ
, (LPVOID
)credential
->UserName
,
480 sizeof(WCHAR
)*(strlenW(credential
->UserName
)+1));
481 if (ret
!= ERROR_SUCCESS
) return ret
;
485 ret
= write_credential_blob(hkey
, credential
->TargetName
, credential
->Type
,
486 key_data
, credential
->CredentialBlob
,
487 credential
->CredentialBlobSize
);
493 static DWORD
mac_write_credential(const CREDENTIALW
*credential
, BOOL preserve_blob
)
496 SecKeychainItemRef keychain_item
;
497 char *username
, *password
, *servername
;
498 UInt32 userlen
, pwlen
, serverlen
;
499 SecKeychainAttribute attrs
[1];
500 SecKeychainAttributeList attr_list
;
502 if (credential
->Flags
)
503 FIXME("Flags 0x%x not written\n", credential
->Flags
);
504 if (credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
505 FIXME("credential type of %d not supported\n", credential
->Type
);
506 if (credential
->Persist
!= CRED_PERSIST_LOCAL_MACHINE
)
507 FIXME("persist value of %d not supported\n", credential
->Persist
);
508 if (credential
->AttributeCount
)
509 FIXME("custom attributes not supported\n");
511 userlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, -1, NULL
, 0, NULL
, NULL
);
512 username
= heap_alloc(userlen
* sizeof(*username
));
513 WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, -1, username
, userlen
, NULL
, NULL
);
515 serverlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
516 servername
= heap_alloc(serverlen
* sizeof(*servername
));
517 WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, servername
, serverlen
, NULL
, NULL
);
518 pwlen
= WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
519 credential
->CredentialBlobSize
/ sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
520 password
= heap_alloc(pwlen
* sizeof(*password
));
521 WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
522 credential
->CredentialBlobSize
/ sizeof(WCHAR
), password
, pwlen
, NULL
, NULL
);
524 TRACE("adding server %s, username %s using Keychain\n", servername
, username
);
525 status
= SecKeychainAddGenericPassword(NULL
, strlen(servername
), servername
, strlen(username
),
526 username
, strlen(password
), password
, &keychain_item
);
528 ERR("SecKeychainAddGenericPassword returned %ld\n", status
);
529 if (status
== errSecDuplicateItem
)
531 status
= SecKeychainFindGenericPassword(NULL
, strlen(servername
), servername
, strlen(username
),
532 username
, NULL
, NULL
, &keychain_item
);
534 ERR("SecKeychainFindGenericPassword returned %ld\n", status
);
537 heap_free(servername
);
541 return ERROR_GEN_FAILURE
;
543 if (credential
->Comment
)
546 attr_list
.attr
= attrs
;
547 attrs
[0].tag
= kSecCommentItemAttr
;
548 attrs
[0].length
= WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, NULL
, 0, NULL
, NULL
);
549 if (attrs
[0].length
) attrs
[0].length
--;
550 attrs
[0].data
= heap_alloc(attrs
[0].length
);
551 WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, attrs
[0].data
, attrs
[0].length
, NULL
, NULL
);
556 attr_list
.attr
= NULL
;
558 status
= SecKeychainItemModifyAttributesAndData(keychain_item
, &attr_list
,
559 preserve_blob
? 0 : strlen(password
),
560 preserve_blob
? NULL
: password
);
561 if (credential
->Comment
)
562 heap_free(attrs
[0].data
);
564 /* FIXME: set TargetAlias attribute */
565 CFRelease(keychain_item
);
567 return ERROR_GEN_FAILURE
;
568 return ERROR_SUCCESS
;
572 static DWORD
open_cred_mgr_key(HKEY
*hkey
, BOOL open_for_write
)
574 return RegCreateKeyExW(HKEY_CURRENT_USER
, wszCredentialManagerKey
, 0,
575 NULL
, REG_OPTION_NON_VOLATILE
,
576 KEY_READ
| (open_for_write
? KEY_WRITE
: 0), NULL
, hkey
, NULL
);
579 static DWORD
get_cred_mgr_encryption_key(HKEY hkeyMgr
, BYTE key_data
[KEY_SIZE
])
581 static const BYTE my_key_data
[KEY_SIZE
] = { 0 };
589 memcpy(key_data
, my_key_data
, KEY_SIZE
);
592 ret
= RegQueryValueExW(hkeyMgr
, wszEncryptionKeyValue
, NULL
, &type
, key_data
,
594 if (ret
== ERROR_SUCCESS
)
596 if (type
!= REG_BINARY
)
597 return ERROR_REGISTRY_CORRUPT
;
599 return ERROR_SUCCESS
;
601 if (ret
!= ERROR_FILE_NOT_FOUND
)
604 GetSystemTimeAsFileTime(&ft
);
605 seed
= ft
.dwLowDateTime
;
606 value
= RtlUniform(&seed
);
607 *(DWORD
*)key_data
= value
;
608 seed
= ft
.dwHighDateTime
;
609 value
= RtlUniform(&seed
);
610 *(DWORD
*)(key_data
+ 4) = value
;
612 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
614 if (ret
== ERROR_ACCESS_DENIED
)
616 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
617 if (ret
== ERROR_SUCCESS
)
619 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
621 RegCloseKey(hkeyMgr
);
627 static LPWSTR
get_key_name_for_target(LPCWSTR target_name
, DWORD type
)
629 static const WCHAR wszGenericPrefix
[] = {'G','e','n','e','r','i','c',':',' ',0};
630 static const WCHAR wszDomPasswdPrefix
[] = {'D','o','m','P','a','s','s','w','d',':',' ',0};
632 LPCWSTR prefix
= NULL
;
635 len
= strlenW(target_name
);
636 if (type
== CRED_TYPE_GENERIC
)
638 prefix
= wszGenericPrefix
;
639 len
+= sizeof(wszGenericPrefix
)/sizeof(wszGenericPrefix
[0]);
643 prefix
= wszDomPasswdPrefix
;
644 len
+= sizeof(wszDomPasswdPrefix
)/sizeof(wszDomPasswdPrefix
[0]);
647 key_name
= heap_alloc(len
* sizeof(WCHAR
));
648 if (!key_name
) return NULL
;
650 strcpyW(key_name
, prefix
);
651 strcatW(key_name
, target_name
);
653 for (p
= key_name
; *p
; p
++)
654 if (*p
== '\\') *p
= '_';
659 static BOOL
registry_credential_matches_filter(HKEY hkeyCred
, LPCWSTR filter
)
667 if (!filter
) return TRUE
;
669 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, NULL
, &count
);
670 if (ret
!= ERROR_SUCCESS
)
672 else if (type
!= REG_SZ
)
675 target_name
= heap_alloc(count
);
678 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, (LPVOID
)target_name
, &count
);
679 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
681 heap_free(target_name
);
685 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
),
686 debugstr_w(target_name
));
688 p
= strchrW(filter
, '*');
689 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
690 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
691 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
693 heap_free(target_name
);
697 static DWORD
registry_enumerate_credentials(HKEY hkeyMgr
, LPCWSTR filter
,
699 DWORD target_name_len
, const BYTE key_data
[KEY_SIZE
],
700 PCREDENTIALW
*credentials
, char **buffer
,
701 DWORD
*len
, DWORD
*count
)
708 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
709 if (ret
== ERROR_NO_MORE_ITEMS
)
714 else if (ret
!= ERROR_SUCCESS
)
716 TRACE("target_name = %s\n", debugstr_w(target_name
));
717 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
718 if (ret
!= ERROR_SUCCESS
)
720 if (!registry_credential_matches_filter(hkeyCred
, filter
))
722 RegCloseKey(hkeyCred
);
727 *len
= sizeof(CREDENTIALW
);
728 credentials
[*count
] = (PCREDENTIALW
)*buffer
;
731 *len
+= sizeof(CREDENTIALW
);
732 ret
= registry_read_credential(hkeyCred
, buffer
? credentials
[*count
] : NULL
,
733 key_data
, buffer
? *buffer
+ sizeof(CREDENTIALW
) : NULL
,
735 RegCloseKey(hkeyCred
);
736 if (ret
!= ERROR_SUCCESS
) break;
737 if (buffer
) *buffer
+= *len
;
744 static BOOL
mac_credential_matches_filter(void *data
, UInt32 data_len
, const WCHAR
*filter
)
751 if (!filter
) return TRUE
;
753 len
= MultiByteToWideChar(CP_UTF8
, 0, data
, data_len
, NULL
, 0);
754 if (!(target_name
= heap_alloc((len
+ 1) * sizeof(WCHAR
)))) return FALSE
;
755 MultiByteToWideChar(CP_UTF8
, 0, data
, data_len
, target_name
, len
);
756 target_name
[len
] = 0;
758 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
), debugstr_w(target_name
));
760 p
= strchrW(filter
, '*');
761 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
762 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
763 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
764 heap_free(target_name
);
768 static DWORD
mac_enumerate_credentials(LPCWSTR filter
, PCREDENTIALW
*credentials
,
769 char *buffer
, DWORD
*len
, DWORD
*count
)
771 SecKeychainSearchRef search
;
772 SecKeychainItemRef item
;
774 Boolean saved_user_interaction_allowed
;
777 SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed
);
778 SecKeychainSetUserInteractionAllowed(false);
780 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
783 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
785 SecKeychainAttributeInfo info
;
786 SecKeychainAttributeList
*attr_list
;
787 UInt32 info_tags
[] = { kSecServiceItemAttr
};
790 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
791 info
.tag
= info_tags
;
793 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
796 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
801 *len
= sizeof(CREDENTIALW
);
802 credentials
[*count
] = (PCREDENTIALW
)buffer
;
805 *len
+= sizeof(CREDENTIALW
);
806 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
808 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
811 TRACE("service item: %.*s\n", (int)attr_list
->attr
[0].length
, (char *)attr_list
->attr
[0].data
);
812 match
= mac_credential_matches_filter(attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, filter
);
813 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
814 if (!match
) continue;
815 ret
= mac_read_credential_from_item(item
, FALSE
,
816 buffer
? credentials
[*count
] : NULL
,
817 buffer
? buffer
+ sizeof(CREDENTIALW
) : NULL
,
820 if (ret
== ERROR_SUCCESS
)
823 if (buffer
) buffer
+= *len
;
829 ERR("SecKeychainSearchCreateFromAttributes returned status %ld\n", status
);
830 SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed
);
831 return ERROR_SUCCESS
;
834 static DWORD
mac_delete_credential(LPCWSTR TargetName
)
837 SecKeychainSearchRef search
;
838 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
841 SecKeychainItemRef item
;
842 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
844 SecKeychainAttributeInfo info
;
845 SecKeychainAttributeList
*attr_list
;
846 UInt32 info_tags
[] = { kSecServiceItemAttr
};
849 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
850 info
.tag
= info_tags
;
852 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
855 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
858 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
863 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
864 target_name
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
865 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
867 target_name
[str_len
] = '\0';
868 if (strcmpiW(TargetName
, target_name
))
871 heap_free(target_name
);
874 heap_free(target_name
);
875 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
876 SecKeychainItemDelete(item
);
880 return ERROR_SUCCESS
;
884 return ERROR_NOT_FOUND
;
888 /******************************************************************************
889 * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
891 * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
895 static INT
convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW
*CredentialW
, PCREDENTIALA CredentialA
, DWORD len
)
899 INT needed
= sizeof(CREDENTIALA
);
903 if (CredentialW
->TargetName
)
904 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
905 if (CredentialW
->Comment
)
906 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, NULL
, 0, NULL
, NULL
);
907 needed
+= CredentialW
->CredentialBlobSize
;
908 if (CredentialW
->TargetAlias
)
909 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, NULL
, 0, NULL
, NULL
);
910 if (CredentialW
->UserName
)
911 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, NULL
, 0, NULL
, NULL
);
917 buffer
= (char *)CredentialA
+ sizeof(CREDENTIALA
);
918 len
-= sizeof(CREDENTIALA
);
919 CredentialA
->Flags
= CredentialW
->Flags
;
920 CredentialA
->Type
= CredentialW
->Type
;
922 if (CredentialW
->TargetName
)
924 CredentialA
->TargetName
= buffer
;
925 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, buffer
, len
, NULL
, NULL
);
926 buffer
+= string_len
;
927 needed
+= string_len
;
931 CredentialA
->TargetName
= NULL
;
932 if (CredentialW
->Comment
)
934 CredentialA
->Comment
= buffer
;
935 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, buffer
, len
, NULL
, NULL
);
936 buffer
+= string_len
;
937 needed
+= string_len
;
941 CredentialA
->Comment
= NULL
;
942 CredentialA
->LastWritten
= CredentialW
->LastWritten
;
943 CredentialA
->CredentialBlobSize
= CredentialW
->CredentialBlobSize
;
944 if (CredentialW
->CredentialBlobSize
&& (CredentialW
->CredentialBlobSize
<= len
))
946 CredentialA
->CredentialBlob
=(LPBYTE
)buffer
;
947 memcpy(CredentialA
->CredentialBlob
, CredentialW
->CredentialBlob
,
948 CredentialW
->CredentialBlobSize
);
949 buffer
+= CredentialW
->CredentialBlobSize
;
950 needed
+= CredentialW
->CredentialBlobSize
;
951 len
-= CredentialW
->CredentialBlobSize
;
954 CredentialA
->CredentialBlob
= NULL
;
955 CredentialA
->Persist
= CredentialW
->Persist
;
956 CredentialA
->AttributeCount
= 0;
957 CredentialA
->Attributes
= NULL
; /* FIXME */
958 if (CredentialW
->TargetAlias
)
960 CredentialA
->TargetAlias
= buffer
;
961 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, buffer
, len
, NULL
, NULL
);
962 buffer
+= string_len
;
963 needed
+= string_len
;
967 CredentialA
->TargetAlias
= NULL
;
968 if (CredentialW
->UserName
)
970 CredentialA
->UserName
= buffer
;
971 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, buffer
, len
, NULL
, NULL
);
972 needed
+= string_len
;
975 CredentialA
->UserName
= NULL
;
980 /******************************************************************************
981 * convert_PCREDENTIALA_to_PCREDENTIALW [internal]
983 * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
986 static INT
convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA
*CredentialA
, PCREDENTIALW CredentialW
, INT len
)
990 INT needed
= sizeof(CREDENTIALW
);
994 if (CredentialA
->TargetName
)
995 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, NULL
, 0);
996 if (CredentialA
->Comment
)
997 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, NULL
, 0);
998 needed
+= CredentialA
->CredentialBlobSize
;
999 if (CredentialA
->TargetAlias
)
1000 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, NULL
, 0);
1001 if (CredentialA
->UserName
)
1002 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, NULL
, 0);
1007 buffer
= (char *)CredentialW
+ sizeof(CREDENTIALW
);
1008 len
-= sizeof(CREDENTIALW
);
1009 CredentialW
->Flags
= CredentialA
->Flags
;
1010 CredentialW
->Type
= CredentialA
->Type
;
1011 if (CredentialA
->TargetName
)
1013 CredentialW
->TargetName
= (LPWSTR
)buffer
;
1014 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, CredentialW
->TargetName
, len
/ sizeof(WCHAR
));
1015 buffer
+= sizeof(WCHAR
) * string_len
;
1016 needed
+= sizeof(WCHAR
) * string_len
;
1017 len
-= sizeof(WCHAR
) * string_len
;
1020 CredentialW
->TargetName
= NULL
;
1021 if (CredentialA
->Comment
)
1023 CredentialW
->Comment
= (LPWSTR
)buffer
;
1024 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, CredentialW
->Comment
, len
/ sizeof(WCHAR
));
1025 buffer
+= sizeof(WCHAR
) * string_len
;
1026 needed
+= sizeof(WCHAR
) * string_len
;
1027 len
-= sizeof(WCHAR
) * string_len
;
1030 CredentialW
->Comment
= NULL
;
1031 CredentialW
->LastWritten
= CredentialA
->LastWritten
;
1032 CredentialW
->CredentialBlobSize
= CredentialA
->CredentialBlobSize
;
1033 if (CredentialA
->CredentialBlobSize
)
1035 CredentialW
->CredentialBlob
=(LPBYTE
)buffer
;
1036 memcpy(CredentialW
->CredentialBlob
, CredentialA
->CredentialBlob
,
1037 CredentialA
->CredentialBlobSize
);
1038 buffer
+= CredentialA
->CredentialBlobSize
;
1039 needed
+= CredentialA
->CredentialBlobSize
;
1040 len
-= CredentialA
->CredentialBlobSize
;
1043 CredentialW
->CredentialBlob
= NULL
;
1044 CredentialW
->Persist
= CredentialA
->Persist
;
1045 CredentialW
->AttributeCount
= 0;
1046 CredentialW
->Attributes
= NULL
; /* FIXME */
1047 if (CredentialA
->TargetAlias
)
1049 CredentialW
->TargetAlias
= (LPWSTR
)buffer
;
1050 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, CredentialW
->TargetAlias
, len
/ sizeof(WCHAR
));
1051 buffer
+= sizeof(WCHAR
) * string_len
;
1052 needed
+= sizeof(WCHAR
) * string_len
;
1053 len
-= sizeof(WCHAR
) * string_len
;
1056 CredentialW
->TargetAlias
= NULL
;
1057 if (CredentialA
->UserName
)
1059 CredentialW
->UserName
= (LPWSTR
)buffer
;
1060 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, CredentialW
->UserName
, len
/ sizeof(WCHAR
));
1061 needed
+= sizeof(WCHAR
) * string_len
;
1064 CredentialW
->UserName
= NULL
;
1069 /******************************************************************************
1070 * CredDeleteA [ADVAPI32.@]
1072 BOOL WINAPI
CredDeleteA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
)
1078 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName
), Type
, Flags
);
1082 SetLastError(ERROR_INVALID_PARAMETER
);
1086 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1087 TargetNameW
= heap_alloc(len
* sizeof(WCHAR
));
1090 SetLastError(ERROR_OUTOFMEMORY
);
1093 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1095 ret
= CredDeleteW(TargetNameW
, Type
, Flags
);
1097 heap_free(TargetNameW
);
1102 /******************************************************************************
1103 * CredDeleteW [ADVAPI32.@]
1105 BOOL WINAPI
CredDeleteW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
)
1111 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName
), Type
, Flags
);
1115 SetLastError(ERROR_INVALID_PARAMETER
);
1119 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1121 FIXME("unhandled type %d\n", Type
);
1122 SetLastError(ERROR_INVALID_PARAMETER
);
1128 FIXME("unhandled flags 0x%x\n", Flags
);
1129 SetLastError(ERROR_INVALID_FLAGS
);
1134 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1136 ret
= mac_delete_credential(TargetName
);
1137 if (ret
== ERROR_SUCCESS
)
1142 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
1143 if (ret
!= ERROR_SUCCESS
)
1145 WARN("couldn't open/create manager key, error %d\n", ret
);
1146 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1150 key_name
= get_key_name_for_target(TargetName
, Type
);
1151 ret
= RegDeleteKeyW(hkeyMgr
, key_name
);
1152 heap_free(key_name
);
1153 RegCloseKey(hkeyMgr
);
1154 if (ret
!= ERROR_SUCCESS
)
1156 SetLastError(ERROR_NOT_FOUND
);
1163 /******************************************************************************
1164 * CredEnumerateA [ADVAPI32.@]
1166 BOOL WINAPI
CredEnumerateA(LPCSTR Filter
, DWORD Flags
, DWORD
*Count
,
1167 PCREDENTIALA
**Credentials
)
1170 PCREDENTIALW
*CredentialsW
;
1176 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter
), Flags
, Count
, Credentials
);
1180 len
= MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, NULL
, 0);
1181 FilterW
= heap_alloc(len
* sizeof(WCHAR
));
1184 SetLastError(ERROR_OUTOFMEMORY
);
1187 MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, FilterW
, len
);
1192 if (!CredEnumerateW(FilterW
, Flags
, Count
, &CredentialsW
))
1199 len
= *Count
* sizeof(PCREDENTIALA
);
1200 for (i
= 0; i
< *Count
; i
++)
1201 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1203 *Credentials
= heap_alloc(len
);
1206 CredFree(CredentialsW
);
1207 SetLastError(ERROR_OUTOFMEMORY
);
1211 buffer
= (char *)&(*Credentials
)[*Count
];
1212 len
-= *Count
* sizeof(PCREDENTIALA
);
1213 for (i
= 0; i
< *Count
; i
++)
1215 (*Credentials
)[i
] = (PCREDENTIALA
)buffer
;
1216 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1221 CredFree(CredentialsW
);
1226 /******************************************************************************
1227 * CredEnumerateW [ADVAPI32.@]
1229 BOOL WINAPI
CredEnumerateW(LPCWSTR Filter
, DWORD Flags
, DWORD
*Count
,
1230 PCREDENTIALW
**Credentials
)
1235 DWORD target_name_len
;
1238 BYTE key_data
[KEY_SIZE
];
1240 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter
), Flags
, Count
, Credentials
);
1244 SetLastError(ERROR_INVALID_FLAGS
);
1248 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1249 if (ret
!= ERROR_SUCCESS
)
1251 WARN("couldn't open/create manager key, error %d\n", ret
);
1252 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1256 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1257 if (ret
!= ERROR_SUCCESS
)
1259 RegCloseKey(hkeyMgr
);
1264 ret
= RegQueryInfoKeyW(hkeyMgr
, NULL
, NULL
, NULL
, NULL
, &target_name_len
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1265 if (ret
!= ERROR_SUCCESS
)
1267 RegCloseKey(hkeyMgr
);
1272 target_name
= heap_alloc((target_name_len
+1)*sizeof(WCHAR
));
1275 RegCloseKey(hkeyMgr
);
1276 SetLastError(ERROR_OUTOFMEMORY
);
1282 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
, target_name_len
,
1283 key_data
, NULL
, NULL
, &len
, Count
);
1285 if (ret
== ERROR_SUCCESS
)
1286 ret
= mac_enumerate_credentials(Filter
, NULL
, NULL
, &len
, Count
);
1288 if (ret
== ERROR_SUCCESS
&& *Count
== 0)
1289 ret
= ERROR_NOT_FOUND
;
1290 if (ret
!= ERROR_SUCCESS
)
1292 heap_free(target_name
);
1293 RegCloseKey(hkeyMgr
);
1297 len
+= *Count
* sizeof(PCREDENTIALW
);
1299 if (ret
== ERROR_SUCCESS
)
1301 buffer
= heap_alloc(len
);
1302 *Credentials
= (PCREDENTIALW
*)buffer
;
1305 buffer
+= *Count
* sizeof(PCREDENTIALW
);
1307 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
,
1308 target_name_len
, key_data
,
1309 *Credentials
, &buffer
, &len
,
1312 if (ret
== ERROR_SUCCESS
)
1313 ret
= mac_enumerate_credentials(Filter
, *Credentials
,
1314 buffer
, &len
, Count
);
1318 ret
= ERROR_OUTOFMEMORY
;
1321 heap_free(target_name
);
1322 RegCloseKey(hkeyMgr
);
1324 if (ret
!= ERROR_SUCCESS
)
1332 /******************************************************************************
1333 * CredFree [ADVAPI32.@]
1335 VOID WINAPI
CredFree(PVOID Buffer
)
1340 /******************************************************************************
1341 * CredReadA [ADVAPI32.@]
1343 BOOL WINAPI
CredReadA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALA
*Credential
)
1346 PCREDENTIALW CredentialW
;
1349 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName
), Type
, Flags
, Credential
);
1353 SetLastError(ERROR_INVALID_PARAMETER
);
1357 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1358 TargetNameW
= heap_alloc(len
* sizeof(WCHAR
));
1361 SetLastError(ERROR_OUTOFMEMORY
);
1364 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1366 if (!CredReadW(TargetNameW
, Type
, Flags
, &CredentialW
))
1368 heap_free(TargetNameW
);
1371 heap_free(TargetNameW
);
1373 len
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, NULL
, 0);
1374 *Credential
= heap_alloc(len
);
1377 SetLastError(ERROR_OUTOFMEMORY
);
1380 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, *Credential
, len
);
1382 CredFree(CredentialW
);
1387 /******************************************************************************
1388 * CredReadW [ADVAPI32.@]
1390 BOOL WINAPI
CredReadW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALW
*Credential
)
1397 BYTE key_data
[KEY_SIZE
];
1399 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName
), Type
, Flags
, Credential
);
1403 SetLastError(ERROR_INVALID_PARAMETER
);
1407 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1409 FIXME("unhandled type %d\n", Type
);
1410 SetLastError(ERROR_INVALID_PARAMETER
);
1416 FIXME("unhandled flags 0x%x\n", Flags
);
1417 SetLastError(ERROR_INVALID_FLAGS
);
1422 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1425 SecKeychainSearchRef search
;
1426 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
1427 if (status
== noErr
)
1429 SecKeychainItemRef item
;
1430 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
1432 SecKeychainAttributeInfo info
;
1433 SecKeychainAttributeList
*attr_list
;
1434 UInt32 info_tags
[] = { kSecServiceItemAttr
};
1437 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
1438 info
.tag
= info_tags
;
1440 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
1441 len
= sizeof(**Credential
);
1442 if (status
!= noErr
)
1444 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
1447 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
1452 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
1453 target_name
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
1454 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
1456 target_name
[str_len
] = '\0';
1457 if (strcmpiW(TargetName
, target_name
))
1460 heap_free(target_name
);
1463 heap_free(target_name
);
1464 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
1465 ret
= mac_read_credential_from_item(item
, TRUE
, NULL
, NULL
, &len
);
1466 if (ret
== ERROR_SUCCESS
)
1468 *Credential
= heap_alloc(len
);
1471 len
= sizeof(**Credential
);
1472 ret
= mac_read_credential_from_item(item
, TRUE
, *Credential
,
1473 (char *)(*Credential
+ 1), &len
);
1476 ret
= ERROR_OUTOFMEMORY
;
1479 if (ret
!= ERROR_SUCCESS
)
1493 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1494 if (ret
!= ERROR_SUCCESS
)
1496 WARN("couldn't open/create manager key, error %d\n", ret
);
1497 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1501 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1502 if (ret
!= ERROR_SUCCESS
)
1504 RegCloseKey(hkeyMgr
);
1509 key_name
= get_key_name_for_target(TargetName
, Type
);
1510 ret
= RegOpenKeyExW(hkeyMgr
, key_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
1511 heap_free(key_name
);
1512 if (ret
!= ERROR_SUCCESS
)
1514 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName
));
1515 SetLastError(ERROR_NOT_FOUND
);
1519 len
= sizeof(**Credential
);
1520 ret
= registry_read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
1521 if (ret
== ERROR_SUCCESS
)
1523 *Credential
= heap_alloc(len
);
1526 len
= sizeof(**Credential
);
1527 ret
= registry_read_credential(hkeyCred
, *Credential
, key_data
,
1528 (char *)(*Credential
+ 1), &len
);
1531 ret
= ERROR_OUTOFMEMORY
;
1534 RegCloseKey(hkeyCred
);
1535 RegCloseKey(hkeyMgr
);
1537 if (ret
!= ERROR_SUCCESS
)
1545 /******************************************************************************
1546 * CredReadDomainCredentialsA [ADVAPI32.@]
1548 BOOL WINAPI
CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation
,
1549 DWORD Flags
, DWORD
*Size
, PCREDENTIALA
**Credentials
)
1551 PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW
;
1554 WCHAR
*buffer
, *end
;
1556 PCREDENTIALW
* CredentialsW
;
1558 TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation
, Flags
, Size
, Credentials
);
1560 /* follow Windows behavior - do not test for NULL, initialize early */
1562 *Credentials
= NULL
;
1564 if (!TargetInformation
)
1566 SetLastError(ERROR_INVALID_PARAMETER
);
1570 len
= sizeof(*TargetInformationW
);
1571 if (TargetInformation
->TargetName
)
1572 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1, NULL
, 0) * sizeof(WCHAR
);
1573 if (TargetInformation
->NetbiosServerName
)
1574 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1575 if (TargetInformation
->DnsServerName
)
1576 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1577 if (TargetInformation
->NetbiosDomainName
)
1578 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1579 if (TargetInformation
->DnsDomainName
)
1580 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1581 if (TargetInformation
->DnsTreeName
)
1582 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1, NULL
, 0) * sizeof(WCHAR
);
1583 if (TargetInformation
->PackageName
)
1584 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1, NULL
, 0) * sizeof(WCHAR
);
1586 TargetInformationW
= heap_alloc(len
);
1587 if (!TargetInformationW
)
1589 SetLastError(ERROR_OUTOFMEMORY
);
1592 buffer
= (WCHAR
*)(TargetInformationW
+ 1);
1593 end
= (WCHAR
*)((char *)TargetInformationW
+ len
);
1595 if (TargetInformation
->TargetName
)
1597 TargetInformationW
->TargetName
= buffer
;
1598 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1,
1599 TargetInformationW
->TargetName
, end
- buffer
);
1601 TargetInformationW
->TargetName
= NULL
;
1603 if (TargetInformation
->NetbiosServerName
)
1605 TargetInformationW
->NetbiosServerName
= buffer
;
1606 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1,
1607 TargetInformationW
->NetbiosServerName
, end
- buffer
);
1609 TargetInformationW
->NetbiosServerName
= NULL
;
1611 if (TargetInformation
->DnsServerName
)
1613 TargetInformationW
->DnsServerName
= buffer
;
1614 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1,
1615 TargetInformationW
->DnsServerName
, end
- buffer
);
1617 TargetInformationW
->DnsServerName
= NULL
;
1619 if (TargetInformation
->NetbiosDomainName
)
1621 TargetInformationW
->NetbiosDomainName
= buffer
;
1622 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1,
1623 TargetInformationW
->NetbiosDomainName
, end
- buffer
);
1625 TargetInformationW
->NetbiosDomainName
= NULL
;
1627 if (TargetInformation
->DnsDomainName
)
1629 TargetInformationW
->DnsDomainName
= buffer
;
1630 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1,
1631 TargetInformationW
->DnsDomainName
, end
- buffer
);
1633 TargetInformationW
->DnsDomainName
= NULL
;
1635 if (TargetInformation
->DnsTreeName
)
1637 TargetInformationW
->DnsTreeName
= buffer
;
1638 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1,
1639 TargetInformationW
->DnsTreeName
, end
- buffer
);
1641 TargetInformationW
->DnsTreeName
= NULL
;
1643 if (TargetInformation
->PackageName
)
1645 TargetInformationW
->PackageName
= buffer
;
1646 MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1,
1647 TargetInformationW
->PackageName
, end
- buffer
);
1649 TargetInformationW
->PackageName
= NULL
;
1651 TargetInformationW
->Flags
= TargetInformation
->Flags
;
1652 TargetInformationW
->CredTypeCount
= TargetInformation
->CredTypeCount
;
1653 TargetInformationW
->CredTypes
= TargetInformation
->CredTypes
;
1655 ret
= CredReadDomainCredentialsW(TargetInformationW
, Flags
, Size
, &CredentialsW
);
1657 heap_free(TargetInformationW
);
1664 len
= *Size
* sizeof(PCREDENTIALA
);
1665 for (i
= 0; i
< *Size
; i
++)
1666 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1668 *Credentials
= heap_alloc(len
);
1671 CredFree(CredentialsW
);
1672 SetLastError(ERROR_OUTOFMEMORY
);
1676 buf
= (char *)&(*Credentials
)[*Size
];
1677 len
-= *Size
* sizeof(PCREDENTIALA
);
1678 for (i
= 0; i
< *Size
; i
++)
1680 (*Credentials
)[i
] = (PCREDENTIALA
)buf
;
1681 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1686 CredFree(CredentialsW
);
1691 /******************************************************************************
1692 * CredReadDomainCredentialsW [ADVAPI32.@]
1694 BOOL WINAPI
CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation
, DWORD Flags
,
1695 DWORD
*Size
, PCREDENTIALW
**Credentials
)
1697 FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation
, Flags
, Size
, Credentials
);
1699 /* follow Windows behavior - do not test for NULL, initialize early */
1701 *Credentials
= NULL
;
1702 if (!TargetInformation
)
1704 SetLastError(ERROR_INVALID_PARAMETER
);
1708 SetLastError(ERROR_NOT_FOUND
);
1712 /******************************************************************************
1713 * CredWriteA [ADVAPI32.@]
1715 BOOL WINAPI
CredWriteA(PCREDENTIALA Credential
, DWORD Flags
)
1719 PCREDENTIALW CredentialW
;
1721 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1723 if (!Credential
|| !Credential
->TargetName
)
1725 SetLastError(ERROR_INVALID_PARAMETER
);
1729 len
= convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, NULL
, 0);
1730 CredentialW
= heap_alloc(len
);
1733 SetLastError(ERROR_OUTOFMEMORY
);
1737 convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, CredentialW
, len
);
1739 ret
= CredWriteW(CredentialW
, Flags
);
1741 heap_free(CredentialW
);
1746 /******************************************************************************
1747 * CredWriteW [ADVAPI32.@]
1749 BOOL WINAPI
CredWriteW(PCREDENTIALW Credential
, DWORD Flags
)
1755 BYTE key_data
[KEY_SIZE
];
1757 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1759 if (!Credential
|| !Credential
->TargetName
)
1761 SetLastError(ERROR_INVALID_PARAMETER
);
1765 if (Flags
& ~CRED_PRESERVE_CREDENTIAL_BLOB
)
1767 FIXME("unhandled flags 0x%x\n", Flags
);
1768 SetLastError(ERROR_INVALID_FLAGS
);
1772 if (Credential
->Type
!= CRED_TYPE_GENERIC
&& Credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1774 FIXME("unhandled type %d\n", Credential
->Type
);
1775 SetLastError(ERROR_INVALID_PARAMETER
);
1779 TRACE("Credential->Flags = 0x%08x\n", Credential
->Flags
);
1780 TRACE("Credential->Type = %u\n", Credential
->Type
);
1781 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential
->TargetName
));
1782 TRACE("Credential->Comment = %s\n", debugstr_w(Credential
->Comment
));
1783 TRACE("Credential->Persist = %u\n", Credential
->Persist
);
1784 TRACE("Credential->TargetAlias = %s\n", debugstr_w(Credential
->TargetAlias
));
1785 TRACE("Credential->UserName = %s\n", debugstr_w(Credential
->UserName
));
1787 if (Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1789 if (!Credential
->UserName
||
1790 (Credential
->Persist
== CRED_PERSIST_ENTERPRISE
&&
1791 (!strchrW(Credential
->UserName
, '\\') && !strchrW(Credential
->UserName
, '@'))))
1793 ERR("bad username %s\n", debugstr_w(Credential
->UserName
));
1794 SetLastError(ERROR_BAD_USERNAME
);
1800 if (!Credential
->AttributeCount
&&
1801 Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
&&
1802 (Credential
->Persist
== CRED_PERSIST_LOCAL_MACHINE
|| Credential
->Persist
== CRED_PERSIST_ENTERPRISE
))
1804 ret
= mac_write_credential(Credential
, Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1805 if (ret
!= ERROR_SUCCESS
)
1814 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1815 if (ret
!= ERROR_SUCCESS
)
1817 WARN("couldn't open/create manager key, error %d\n", ret
);
1818 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1822 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1823 if (ret
!= ERROR_SUCCESS
)
1825 RegCloseKey(hkeyMgr
);
1830 key_name
= get_key_name_for_target(Credential
->TargetName
, Credential
->Type
);
1831 ret
= RegCreateKeyExW(hkeyMgr
, key_name
, 0, NULL
,
1832 Credential
->Persist
== CRED_PERSIST_SESSION
? REG_OPTION_VOLATILE
: REG_OPTION_NON_VOLATILE
,
1833 KEY_READ
|KEY_WRITE
, NULL
, &hkeyCred
, NULL
);
1834 heap_free(key_name
);
1835 if (ret
!= ERROR_SUCCESS
)
1837 TRACE("credentials for target name %s not found\n",
1838 debugstr_w(Credential
->TargetName
));
1839 SetLastError(ERROR_NOT_FOUND
);
1843 ret
= registry_write_credential(hkeyCred
, Credential
, key_data
,
1844 Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1846 RegCloseKey(hkeyCred
);
1847 RegCloseKey(hkeyMgr
);
1849 if (ret
!= ERROR_SUCCESS
)
1857 /******************************************************************************
1858 * CredGetSessionTypes [ADVAPI32.@]
1860 WINADVAPI BOOL WINAPI
CredGetSessionTypes(DWORD persistCount
, LPDWORD persists
)
1862 TRACE("(%u, %p)\n", persistCount
, persists
);
1864 memset(persists
, CRED_PERSIST_NONE
, persistCount
*sizeof(*persists
));
1865 if (CRED_TYPE_GENERIC
< persistCount
)
1867 persists
[CRED_TYPE_GENERIC
] = CRED_PERSIST_ENTERPRISE
;
1869 if (CRED_TYPE_DOMAIN_PASSWORD
< persistCount
)
1871 persists
[CRED_TYPE_DOMAIN_PASSWORD
] = CRED_PERSIST_ENTERPRISE
;
1877 /******************************************************************************
1878 * CredMarshalCredentialA [ADVAPI32.@]
1880 BOOL WINAPI
CredMarshalCredentialA( CRED_MARSHAL_TYPE type
, PVOID cred
, LPSTR
*out
)
1885 TRACE("%u, %p, %p\n", type
, cred
, out
);
1887 if ((ret
= CredMarshalCredentialW( type
, cred
, &outW
)))
1889 int len
= WideCharToMultiByte( CP_ACP
, 0, outW
, -1, NULL
, 0, NULL
, NULL
);
1890 if (!(*out
= heap_alloc( len
)))
1895 WideCharToMultiByte( CP_ACP
, 0, outW
, -1, *out
, len
, NULL
, NULL
);
1901 static UINT
cred_encode( const char *bin
, unsigned int len
, WCHAR
*cred
)
1903 static const char enc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#-";
1908 cred
[n
++] = enc
[bin
[0] & 0x3f];
1909 x
= (bin
[0] & 0xc0) >> 6;
1915 cred
[n
++] = enc
[((bin
[1] & 0xf) << 2) | x
];
1916 x
= (bin
[1] & 0xf0) >> 4;
1922 cred
[n
++] = enc
[((bin
[2] & 0x3) << 4) | x
];
1923 cred
[n
++] = enc
[(bin
[2] & 0xfc) >> 2];
1930 /******************************************************************************
1931 * CredMarshalCredentialW [ADVAPI32.@]
1933 BOOL WINAPI
CredMarshalCredentialW( CRED_MARSHAL_TYPE type
, PVOID cred
, LPWSTR
*out
)
1935 CERT_CREDENTIAL_INFO
*cert
= cred
;
1936 USERNAME_TARGET_CREDENTIAL_INFO
*target
= cred
;
1940 TRACE("%u, %p, %p\n", type
, cred
, out
);
1942 if (!cred
|| (type
== CertCredential
&& cert
->cbSize
< sizeof(*cert
)) ||
1943 (type
!= CertCredential
&& type
!= UsernameTargetCredential
&& type
!= BinaryBlobCredential
) ||
1944 (type
== UsernameTargetCredential
&& (!target
->UserName
|| !target
->UserName
[0])))
1946 SetLastError( ERROR_INVALID_PARAMETER
);
1951 case CertCredential
:
1953 size
= (sizeof(cert
->rgbHashOfCert
) + 2) * 4 / 3;
1954 if (!(p
= heap_alloc( (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1958 len
= cred_encode( (const char *)cert
->rgbHashOfCert
, sizeof(cert
->rgbHashOfCert
), p
+ 3 );
1962 case UsernameTargetCredential
:
1964 len
= strlenW( target
->UserName
);
1965 size
= (sizeof(DWORD
) + len
* sizeof(WCHAR
) + 2) * 4 / 3;
1966 if (!(p
= heap_alloc( (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1970 size
= len
* sizeof(WCHAR
);
1971 len
= cred_encode( (const char *)&size
, sizeof(DWORD
), p
+ 3 );
1972 len
+= cred_encode( (const char *)target
->UserName
, size
, p
+ 3 + len
);
1976 case BinaryBlobCredential
:
1977 FIXME("BinaryBlobCredential not implemented\n");
1986 /******************************************************************************
1987 * CredUnmarshalCredentialA [ADVAPI32.@]
1989 BOOL WINAPI
CredUnmarshalCredentialA( LPCSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
1992 WCHAR
*credW
= NULL
;
1994 TRACE("%s, %p, %p\n", debugstr_a(cred
), type
, out
);
1998 int len
= MultiByteToWideChar( CP_ACP
, 0, cred
, -1, NULL
, 0 );
1999 if (!(credW
= heap_alloc( len
* sizeof(WCHAR
) ))) return FALSE
;
2000 MultiByteToWideChar( CP_ACP
, 0, cred
, -1, credW
, len
);
2002 ret
= CredUnmarshalCredentialW( credW
, type
, out
);
2007 static inline char char_decode( WCHAR c
)
2009 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
2010 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
2011 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
2012 if (c
== '#') return 62;
2013 if (c
== '-') return 63;
2017 static BOOL
cred_decode( const WCHAR
*cred
, unsigned int len
, char *buf
)
2020 char c0
, c1
, c2
, c3
;
2021 const WCHAR
*p
= cred
;
2025 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2026 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2027 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2028 if ((c3
= char_decode( p
[3] )) > 63) return FALSE
;
2030 buf
[i
+ 0] = (c1
<< 6) | c0
;
2031 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2032 buf
[i
+ 2] = (c3
<< 2) | (c2
>> 4);
2039 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2040 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2041 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2043 buf
[i
+ 0] = (c1
<< 6) | c0
;
2044 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2048 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2049 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2051 buf
[i
+ 0] = (c1
<< 6) | c0
;
2060 /******************************************************************************
2061 * CredUnmarshalCredentialW [ADVAPI32.@]
2063 BOOL WINAPI
CredUnmarshalCredentialW( LPCWSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
2065 unsigned int len
, buflen
;
2067 TRACE("%s, %p, %p\n", debugstr_w(cred
), type
, out
);
2069 if (!cred
|| cred
[0] != '@' || cred
[1] != '@' ||
2070 char_decode( cred
[2] ) > 63)
2072 SetLastError( ERROR_INVALID_PARAMETER
);
2075 len
= strlenW( cred
+ 3 );
2076 *type
= char_decode( cred
[2] );
2079 case CertCredential
:
2081 char hash
[CERT_HASH_LENGTH
];
2082 CERT_CREDENTIAL_INFO
*cert
;
2084 if (len
!= 27 || !cred_decode( cred
+ 3, len
, hash
))
2086 SetLastError( ERROR_INVALID_PARAMETER
);
2089 if (!(cert
= heap_alloc( sizeof(*cert
) ))) return FALSE
;
2090 memcpy( cert
->rgbHashOfCert
, hash
, sizeof(cert
->rgbHashOfCert
) );
2091 cert
->cbSize
= sizeof(*cert
);
2095 case UsernameTargetCredential
:
2097 USERNAME_TARGET_CREDENTIAL_INFO
*target
;
2100 if (len
< 9 || !cred_decode( cred
+ 3, 6, (char *)&size
) ||
2101 size
% sizeof(WCHAR
) || len
- 6 != (size
* 4 + 2) / 3)
2103 SetLastError( ERROR_INVALID_PARAMETER
);
2106 buflen
= sizeof(*target
) + size
+ sizeof(WCHAR
);
2107 if (!(target
= heap_alloc( buflen
))) return FALSE
;
2108 if (!cred_decode( cred
+ 9, len
- 6, (char *)(target
+ 1) ))
2110 heap_free( target
);
2113 target
->UserName
= (WCHAR
*)(target
+ 1);
2114 target
->UserName
[size
/ sizeof(WCHAR
)] = 0;
2118 case BinaryBlobCredential
:
2119 FIXME("BinaryBlobCredential not implemented\n");
2122 WARN("unhandled type %u\n", *type
);
2123 SetLastError( ERROR_INVALID_PARAMETER
);
2129 /******************************************************************************
2130 * CredIsMarshaledCredentialW [ADVAPI32.@]
2132 * Check, if the name parameter is a marshaled credential, hash or binary blob
2135 * name the name to check
2138 * TRUE: the name parameter is a marshaled credential, hash or binary blob
2139 * FALSE: the name is a plain username
2141 BOOL WINAPI
CredIsMarshaledCredentialW(LPCWSTR name
)
2143 TRACE("(%s)\n", debugstr_w(name
));
2145 if (name
&& name
[0] == '@' && name
[1] == '@' && name
[2] > 'A' && name
[3])
2147 char hash
[CERT_HASH_LENGTH
];
2148 int len
= strlenW(name
+ 3 );
2151 if ((name
[2] - 'A') == CertCredential
&& (len
== 27) && cred_decode(name
+ 3, len
, hash
))
2154 if (((name
[2] - 'A') == UsernameTargetCredential
) &&
2155 (len
>= 9) && cred_decode(name
+ 3, 6, (char *)&size
) && size
)
2158 if ((name
[2] - 'A') == BinaryBlobCredential
)
2159 FIXME("BinaryBlobCredential not checked\n");
2161 if ((name
[2] - 'A') > BinaryBlobCredential
)
2162 TRACE("unknown type: %d\n", (name
[2] - 'A'));
2165 SetLastError(ERROR_INVALID_PARAMETER
);
2169 /******************************************************************************
2170 * CredIsMarshaledCredentialA [ADVAPI32.@]
2172 * See CredIsMarshaledCredentialW
2175 BOOL WINAPI
CredIsMarshaledCredentialA(LPCSTR name
)
2177 LPWSTR nameW
= NULL
;
2181 TRACE("(%s)\n", debugstr_a(name
));
2185 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0);
2186 nameW
= heap_alloc(len
* sizeof(WCHAR
));
2187 MultiByteToWideChar(CP_ACP
, 0, name
, -1, nameW
, len
);
2190 res
= CredIsMarshaledCredentialW(nameW
);