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
26 # include <Security/SecKeychain.h>
27 # include <Security/SecKeychainItem.h>
28 # include <Security/SecKeychainSearch.h>
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(cred
);
44 /* the size of the ARC4 key used to encrypt the password data */
47 static const WCHAR wszCredentialManagerKey
[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
48 'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0};
49 static const WCHAR wszEncryptionKeyValue
[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0};
51 static const WCHAR wszFlagsValue
[] = {'F','l','a','g','s',0};
52 static const WCHAR wszTypeValue
[] = {'T','y','p','e',0};
53 static const WCHAR wszCommentValue
[] = {'C','o','m','m','e','n','t',0};
54 static const WCHAR wszLastWrittenValue
[] = {'L','a','s','t','W','r','i','t','t','e','n',0};
55 static const WCHAR wszPersistValue
[] = {'P','e','r','s','i','s','t',0};
56 static const WCHAR wszTargetAliasValue
[] = {'T','a','r','g','e','t','A','l','i','a','s',0};
57 static const WCHAR wszUserNameValue
[] = {'U','s','e','r','N','a','m','e',0};
58 static const WCHAR wszPasswordValue
[] = {'P','a','s','s','w','o','r','d',0};
60 static DWORD
read_credential_blob(HKEY hkey
, const BYTE key_data
[KEY_SIZE
],
61 LPBYTE credential_blob
,
62 DWORD
*credential_blob_size
)
67 *credential_blob_size
= 0;
68 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, NULL
, credential_blob_size
);
69 if (ret
!= ERROR_SUCCESS
)
71 else if (type
!= REG_BINARY
)
72 return ERROR_REGISTRY_CORRUPT
;
78 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, credential_blob
,
79 credential_blob_size
);
80 if (ret
!= ERROR_SUCCESS
)
82 else if (type
!= REG_BINARY
)
83 return ERROR_REGISTRY_CORRUPT
;
85 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
86 key
.Buffer
= (unsigned char *)key_data
;
88 data
.Length
= data
.MaximumLength
= *credential_blob_size
;
89 data
.Buffer
= credential_blob
;
90 SystemFunction032(&data
, &key
);
95 static DWORD
registry_read_credential(HKEY hkey
, PCREDENTIALW credential
,
96 const BYTE key_data
[KEY_SIZE
],
97 char *buffer
, DWORD
*len
)
103 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, NULL
, &count
);
104 if (ret
!= ERROR_SUCCESS
)
106 else if (type
!= REG_SZ
)
107 return ERROR_REGISTRY_CORRUPT
;
111 credential
->TargetName
= (LPWSTR
)buffer
;
112 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, (LPVOID
)credential
->TargetName
,
114 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) return ret
;
118 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, NULL
, &count
);
119 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
121 else if (type
!= REG_SZ
)
122 return ERROR_REGISTRY_CORRUPT
;
126 credential
->Comment
= (LPWSTR
)buffer
;
127 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, (LPVOID
)credential
->Comment
,
129 if (ret
== ERROR_FILE_NOT_FOUND
)
130 credential
->Comment
= NULL
;
131 else if (ret
!= ERROR_SUCCESS
)
133 else if (type
!= REG_SZ
)
134 return ERROR_REGISTRY_CORRUPT
;
139 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, NULL
, &count
);
140 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
142 else if (type
!= REG_SZ
)
143 return ERROR_REGISTRY_CORRUPT
;
147 credential
->TargetAlias
= (LPWSTR
)buffer
;
148 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, (LPVOID
)credential
->TargetAlias
,
150 if (ret
== ERROR_FILE_NOT_FOUND
)
151 credential
->TargetAlias
= NULL
;
152 else if (ret
!= ERROR_SUCCESS
)
154 else if (type
!= REG_SZ
)
155 return ERROR_REGISTRY_CORRUPT
;
160 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, NULL
, &count
);
161 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
163 else if (type
!= REG_SZ
)
164 return ERROR_REGISTRY_CORRUPT
;
168 credential
->UserName
= (LPWSTR
)buffer
;
169 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, (LPVOID
)credential
->UserName
,
171 if (ret
== ERROR_FILE_NOT_FOUND
)
172 credential
->UserName
= NULL
;
173 else if (ret
!= ERROR_SUCCESS
)
175 else if (type
!= REG_SZ
)
176 return ERROR_REGISTRY_CORRUPT
;
181 ret
= read_credential_blob(hkey
, key_data
, NULL
, &count
);
182 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
187 credential
->CredentialBlob
= (LPBYTE
)buffer
;
188 ret
= read_credential_blob(hkey
, key_data
, credential
->CredentialBlob
, &count
);
189 if (ret
== ERROR_FILE_NOT_FOUND
)
190 credential
->CredentialBlob
= NULL
;
191 else if (ret
!= ERROR_SUCCESS
)
193 credential
->CredentialBlobSize
= count
;
196 /* FIXME: Attributes */
199 credential
->AttributeCount
= 0;
200 credential
->Attributes
= NULL
;
203 if (!credential
) return ERROR_SUCCESS
;
205 count
= sizeof(credential
->Flags
);
206 ret
= RegQueryValueExW(hkey
, wszFlagsValue
, NULL
, &type
, (LPVOID
)&credential
->Flags
,
208 if (ret
!= ERROR_SUCCESS
)
210 else if (type
!= REG_DWORD
)
211 return ERROR_REGISTRY_CORRUPT
;
212 count
= sizeof(credential
->Type
);
213 ret
= RegQueryValueExW(hkey
, wszTypeValue
, NULL
, &type
, (LPVOID
)&credential
->Type
,
215 if (ret
!= ERROR_SUCCESS
)
217 else if (type
!= REG_DWORD
)
218 return ERROR_REGISTRY_CORRUPT
;
220 count
= sizeof(credential
->LastWritten
);
221 ret
= RegQueryValueExW(hkey
, wszLastWrittenValue
, NULL
, &type
, (LPVOID
)&credential
->LastWritten
,
223 if (ret
!= ERROR_SUCCESS
)
225 else if (type
!= REG_BINARY
)
226 return ERROR_REGISTRY_CORRUPT
;
227 count
= sizeof(credential
->Persist
);
228 ret
= RegQueryValueExW(hkey
, wszPersistValue
, NULL
, &type
, (LPVOID
)&credential
->Persist
,
230 if (ret
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
231 return ERROR_REGISTRY_CORRUPT
;
236 static DWORD
mac_read_credential_from_item(SecKeychainItemRef item
, BOOL require_password
,
237 PCREDENTIALW credential
, char *buffer
,
241 UInt32 i
, cred_blob_len
;
244 BOOL user_name_present
= FALSE
;
245 SecKeychainAttributeInfo info
;
246 SecKeychainAttributeList
*attr_list
;
247 UInt32 info_tags
[] = { kSecServiceItemAttr
, kSecAccountItemAttr
,
248 kSecCommentItemAttr
, kSecCreationDateItemAttr
};
249 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
250 info
.tag
= info_tags
;
252 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, &cred_blob
);
253 if (status
== errSecAuthFailed
&& !require_password
)
257 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, NULL
);
261 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
262 return ERROR_NOT_FOUND
;
265 for (i
= 0; i
< attr_list
->count
; i
++)
266 if (attr_list
->attr
[i
].tag
== kSecAccountItemAttr
&& attr_list
->attr
[i
].data
)
268 user_name_present
= TRUE
;
271 if (!user_name_present
)
273 WARN("no kSecAccountItemAttr for item\n");
274 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
275 return ERROR_NOT_FOUND
;
280 credential
->Flags
= 0;
281 credential
->Type
= CRED_TYPE_DOMAIN_PASSWORD
;
282 credential
->TargetName
= NULL
;
283 credential
->Comment
= NULL
;
284 memset(&credential
->LastWritten
, 0, sizeof(credential
->LastWritten
));
285 credential
->CredentialBlobSize
= 0;
286 credential
->CredentialBlob
= NULL
;
287 credential
->Persist
= CRED_PERSIST_LOCAL_MACHINE
;
288 credential
->AttributeCount
= 0;
289 credential
->Attributes
= NULL
;
290 credential
->TargetAlias
= NULL
;
291 credential
->UserName
= NULL
;
293 for (i
= 0; i
< attr_list
->count
; i
++)
295 switch (attr_list
->attr
[i
].tag
)
297 case kSecServiceItemAttr
:
298 TRACE("kSecServiceItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
299 (char *)attr_list
->attr
[i
].data
);
300 if (!attr_list
->attr
[i
].data
) continue;
304 credential
->TargetName
= (LPWSTR
)buffer
;
305 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
306 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
307 credential
->TargetName
[str_len
] = '\0';
308 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
309 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
314 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
315 attr_list
->attr
[i
].length
, NULL
, 0);
316 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
319 case kSecAccountItemAttr
:
322 TRACE("kSecAccountItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
323 (char *)attr_list
->attr
[i
].data
);
324 if (!attr_list
->attr
[i
].data
) continue;
325 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
326 attr_list
->attr
[i
].length
, NULL
, 0);
327 user
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
328 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
329 attr_list
->attr
[i
].length
, user
, str_len
);
330 user
[str_len
] = '\0';
333 case kSecCommentItemAttr
:
334 TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
335 (char *)attr_list
->attr
[i
].data
);
336 if (!attr_list
->attr
[i
].data
) continue;
340 credential
->Comment
= (LPWSTR
)buffer
;
341 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
342 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
343 credential
->Comment
[str_len
] = '\0';
344 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
345 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
350 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
351 attr_list
->attr
[i
].length
, NULL
, 0);
352 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
355 case kSecCreationDateItemAttr
:
356 TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
357 (char *)attr_list
->attr
[i
].data
);
360 LARGE_INTEGER win_time
;
363 memset(&tm
, 0, sizeof(tm
));
364 strptime(attr_list
->attr
[i
].data
, "%Y%m%d%H%M%SZ", &tm
);
366 RtlSecondsSince1970ToTime(time
, &win_time
);
367 credential
->LastWritten
.dwLowDateTime
= win_time
.u
.LowPart
;
368 credential
->LastWritten
.dwHighDateTime
= win_time
.u
.HighPart
;
372 FIXME("unhandled attribute %lu\n", attr_list
->attr
[i
].tag
);
381 credential
->UserName
= (LPWSTR
)buffer
;
382 str_len
= strlenW(user
);
383 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
386 memcpy(buffer
, user
, (str_len
+ 1) * sizeof(WCHAR
));
387 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
388 TRACE("UserName = %s\n", debugstr_w(credential
->UserName
));
391 HeapFree(GetProcessHeap(), 0, user
);
398 credential
->CredentialBlob
= (BYTE
*)buffer
;
399 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
400 (LPWSTR
)buffer
, 0xffff);
401 credential
->CredentialBlobSize
= str_len
* sizeof(WCHAR
);
402 *len
+= str_len
* sizeof(WCHAR
);
407 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
409 *len
+= str_len
* sizeof(WCHAR
);
412 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
413 return ERROR_SUCCESS
;
417 static DWORD
write_credential_blob(HKEY hkey
, LPCWSTR target_name
, DWORD type
,
418 const BYTE key_data
[KEY_SIZE
],
419 const BYTE
*credential_blob
, DWORD credential_blob_size
)
421 LPBYTE encrypted_credential_blob
;
426 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
427 key
.Buffer
= (unsigned char *)key_data
;
429 encrypted_credential_blob
= HeapAlloc(GetProcessHeap(), 0, credential_blob_size
);
430 if (!encrypted_credential_blob
) return ERROR_OUTOFMEMORY
;
432 memcpy(encrypted_credential_blob
, credential_blob
, credential_blob_size
);
433 data
.Length
= data
.MaximumLength
= credential_blob_size
;
434 data
.Buffer
= encrypted_credential_blob
;
435 SystemFunction032(&data
, &key
);
437 ret
= RegSetValueExW(hkey
, wszPasswordValue
, 0, REG_BINARY
, encrypted_credential_blob
, credential_blob_size
);
438 HeapFree(GetProcessHeap(), 0, encrypted_credential_blob
);
443 static DWORD
registry_write_credential(HKEY hkey
, const CREDENTIALW
*credential
,
444 const BYTE key_data
[KEY_SIZE
], BOOL preserve_blob
)
447 FILETIME LastWritten
;
449 GetSystemTimeAsFileTime(&LastWritten
);
451 ret
= RegSetValueExW(hkey
, wszFlagsValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Flags
,
452 sizeof(credential
->Flags
));
453 if (ret
!= ERROR_SUCCESS
) return ret
;
454 ret
= RegSetValueExW(hkey
, wszTypeValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Type
,
455 sizeof(credential
->Type
));
456 if (ret
!= ERROR_SUCCESS
) return ret
;
457 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (LPVOID
)credential
->TargetName
,
458 sizeof(WCHAR
)*(strlenW(credential
->TargetName
)+1));
459 if (ret
!= ERROR_SUCCESS
) return ret
;
460 if (credential
->Comment
)
462 ret
= RegSetValueExW(hkey
, wszCommentValue
, 0, REG_SZ
, (LPVOID
)credential
->Comment
,
463 sizeof(WCHAR
)*(strlenW(credential
->Comment
)+1));
464 if (ret
!= ERROR_SUCCESS
) return ret
;
466 ret
= RegSetValueExW(hkey
, wszLastWrittenValue
, 0, REG_BINARY
, (LPVOID
)&LastWritten
,
467 sizeof(LastWritten
));
468 if (ret
!= ERROR_SUCCESS
) return ret
;
469 ret
= RegSetValueExW(hkey
, wszPersistValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Persist
,
470 sizeof(credential
->Persist
));
471 if (ret
!= ERROR_SUCCESS
) return ret
;
472 /* FIXME: Attributes */
473 if (credential
->TargetAlias
)
475 ret
= RegSetValueExW(hkey
, wszTargetAliasValue
, 0, REG_SZ
, (LPVOID
)credential
->TargetAlias
,
476 sizeof(WCHAR
)*(strlenW(credential
->TargetAlias
)+1));
477 if (ret
!= ERROR_SUCCESS
) return ret
;
479 if (credential
->UserName
)
481 ret
= RegSetValueExW(hkey
, wszUserNameValue
, 0, REG_SZ
, (LPVOID
)credential
->UserName
,
482 sizeof(WCHAR
)*(strlenW(credential
->UserName
)+1));
483 if (ret
!= ERROR_SUCCESS
) return ret
;
487 ret
= write_credential_blob(hkey
, credential
->TargetName
, credential
->Type
,
488 key_data
, credential
->CredentialBlob
,
489 credential
->CredentialBlobSize
);
495 static DWORD
mac_write_credential(const CREDENTIALW
*credential
, BOOL preserve_blob
)
498 SecKeychainItemRef keychain_item
;
499 char *username
, *password
, *servername
;
500 UInt32 userlen
, pwlen
, serverlen
;
501 SecKeychainAttribute attrs
[1];
502 SecKeychainAttributeList attr_list
;
504 if (credential
->Flags
)
505 FIXME("Flags 0x%x not written\n", credential
->Flags
);
506 if (credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
507 FIXME("credential type of %d not supported\n", credential
->Type
);
508 if (credential
->Persist
!= CRED_PERSIST_LOCAL_MACHINE
)
509 FIXME("persist value of %d not supported\n", credential
->Persist
);
510 if (credential
->AttributeCount
)
511 FIXME("custom attributes not supported\n");
513 userlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, -1, NULL
, 0, NULL
, NULL
);
514 username
= HeapAlloc(GetProcessHeap(), 0, userlen
* sizeof(*username
));
515 WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, -1, username
, userlen
, NULL
, NULL
);
517 serverlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
518 servername
= HeapAlloc(GetProcessHeap(), 0, serverlen
* sizeof(*servername
));
519 WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, servername
, serverlen
, NULL
, NULL
);
520 pwlen
= WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
521 credential
->CredentialBlobSize
/ sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
522 password
= HeapAlloc(GetProcessHeap(), 0, pwlen
* sizeof(*password
));
523 WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
524 credential
->CredentialBlobSize
/ sizeof(WCHAR
), password
, pwlen
, NULL
, NULL
);
526 TRACE("adding server %s, username %s using Keychain\n", servername
, username
);
527 status
= SecKeychainAddGenericPassword(NULL
, strlen(servername
), servername
, strlen(username
),
528 username
, strlen(password
), password
, &keychain_item
);
530 ERR("SecKeychainAddGenericPassword returned %ld\n", status
);
531 if (status
== errSecDuplicateItem
)
533 status
= SecKeychainFindGenericPassword(NULL
, strlen(servername
), servername
, strlen(username
),
534 username
, NULL
, NULL
, &keychain_item
);
536 ERR("SecKeychainFindGenericPassword returned %ld\n", status
);
538 HeapFree(GetProcessHeap(), 0, username
);
539 HeapFree(GetProcessHeap(), 0, servername
);
542 HeapFree(GetProcessHeap(), 0, password
);
543 return ERROR_GEN_FAILURE
;
545 if (credential
->Comment
)
548 attr_list
.attr
= attrs
;
549 attrs
[0].tag
= kSecCommentItemAttr
;
550 attrs
[0].length
= WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, NULL
, 0, NULL
, NULL
);
551 if (attrs
[0].length
) attrs
[0].length
--;
552 attrs
[0].data
= HeapAlloc(GetProcessHeap(), 0, attrs
[0].length
);
553 WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, attrs
[0].data
, attrs
[0].length
, NULL
, NULL
);
558 attr_list
.attr
= NULL
;
560 status
= SecKeychainItemModifyAttributesAndData(keychain_item
, &attr_list
,
561 preserve_blob
? 0 : strlen(password
),
562 preserve_blob
? NULL
: password
);
563 if (credential
->Comment
)
564 HeapFree(GetProcessHeap(), 0, attrs
[0].data
);
565 HeapFree(GetProcessHeap(), 0, password
);
566 /* FIXME: set TargetAlias attribute */
567 CFRelease(keychain_item
);
569 return ERROR_GEN_FAILURE
;
570 return ERROR_SUCCESS
;
574 static DWORD
open_cred_mgr_key(HKEY
*hkey
, BOOL open_for_write
)
576 return RegCreateKeyExW(HKEY_CURRENT_USER
, wszCredentialManagerKey
, 0,
577 NULL
, REG_OPTION_NON_VOLATILE
,
578 KEY_READ
| (open_for_write
? KEY_WRITE
: 0), NULL
, hkey
, NULL
);
581 static DWORD
get_cred_mgr_encryption_key(HKEY hkeyMgr
, BYTE key_data
[KEY_SIZE
])
583 static const BYTE my_key_data
[KEY_SIZE
] = { 0 };
591 memcpy(key_data
, my_key_data
, KEY_SIZE
);
594 ret
= RegQueryValueExW(hkeyMgr
, wszEncryptionKeyValue
, NULL
, &type
, key_data
,
596 if (ret
== ERROR_SUCCESS
)
598 if (type
!= REG_BINARY
)
599 return ERROR_REGISTRY_CORRUPT
;
601 return ERROR_SUCCESS
;
603 if (ret
!= ERROR_FILE_NOT_FOUND
)
606 GetSystemTimeAsFileTime(&ft
);
607 seed
= ft
.dwLowDateTime
;
608 value
= RtlUniform(&seed
);
609 *(DWORD
*)key_data
= value
;
610 seed
= ft
.dwHighDateTime
;
611 value
= RtlUniform(&seed
);
612 *(DWORD
*)(key_data
+ 4) = value
;
614 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
616 if (ret
== ERROR_ACCESS_DENIED
)
618 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
619 if (ret
== ERROR_SUCCESS
)
621 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
623 RegCloseKey(hkeyMgr
);
629 static LPWSTR
get_key_name_for_target(LPCWSTR target_name
, DWORD type
)
631 static const WCHAR wszGenericPrefix
[] = {'G','e','n','e','r','i','c',':',' ',0};
632 static const WCHAR wszDomPasswdPrefix
[] = {'D','o','m','P','a','s','s','w','d',':',' ',0};
634 LPCWSTR prefix
= NULL
;
637 len
= strlenW(target_name
);
638 if (type
== CRED_TYPE_GENERIC
)
640 prefix
= wszGenericPrefix
;
641 len
+= sizeof(wszGenericPrefix
)/sizeof(wszGenericPrefix
[0]);
645 prefix
= wszDomPasswdPrefix
;
646 len
+= sizeof(wszDomPasswdPrefix
)/sizeof(wszDomPasswdPrefix
[0]);
649 key_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
650 if (!key_name
) return NULL
;
652 strcpyW(key_name
, prefix
);
653 strcatW(key_name
, target_name
);
655 for (p
= key_name
; *p
; p
++)
656 if (*p
== '\\') *p
= '_';
661 static BOOL
registry_credential_matches_filter(HKEY hkeyCred
, LPCWSTR filter
)
669 if (!filter
) return TRUE
;
671 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, NULL
, &count
);
672 if (ret
!= ERROR_SUCCESS
)
674 else if (type
!= REG_SZ
)
677 target_name
= HeapAlloc(GetProcessHeap(), 0, count
);
680 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, (LPVOID
)target_name
, &count
);
681 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
683 HeapFree(GetProcessHeap(), 0, target_name
);
687 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
),
688 debugstr_w(target_name
));
690 p
= strchrW(filter
, '*');
691 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
692 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
693 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
695 HeapFree(GetProcessHeap(), 0, target_name
);
699 static DWORD
registry_enumerate_credentials(HKEY hkeyMgr
, LPCWSTR filter
,
701 DWORD target_name_len
, const BYTE key_data
[KEY_SIZE
],
702 PCREDENTIALW
*credentials
, char **buffer
,
703 DWORD
*len
, DWORD
*count
)
710 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
711 if (ret
== ERROR_NO_MORE_ITEMS
)
716 else if (ret
!= ERROR_SUCCESS
)
718 TRACE("target_name = %s\n", debugstr_w(target_name
));
719 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
720 if (ret
!= ERROR_SUCCESS
)
722 if (!registry_credential_matches_filter(hkeyCred
, filter
))
724 RegCloseKey(hkeyCred
);
729 *len
= sizeof(CREDENTIALW
);
730 credentials
[*count
] = (PCREDENTIALW
)*buffer
;
733 *len
+= sizeof(CREDENTIALW
);
734 ret
= registry_read_credential(hkeyCred
, buffer
? credentials
[*count
] : NULL
,
735 key_data
, buffer
? *buffer
+ sizeof(CREDENTIALW
) : NULL
,
737 RegCloseKey(hkeyCred
);
738 if (ret
!= ERROR_SUCCESS
) break;
739 if (buffer
) *buffer
+= *len
;
746 static BOOL
mac_credential_matches_filter(void *data
, UInt32 data_len
, const WCHAR
*filter
)
753 if (!filter
) return TRUE
;
755 len
= MultiByteToWideChar(CP_UTF8
, 0, data
, data_len
, NULL
, 0);
756 if (!(target_name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
)))) return FALSE
;
757 MultiByteToWideChar(CP_UTF8
, 0, data
, data_len
, target_name
, len
);
758 target_name
[len
] = 0;
760 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
), debugstr_w(target_name
));
762 p
= strchrW(filter
, '*');
763 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
764 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
765 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
766 HeapFree(GetProcessHeap(), 0, target_name
);
770 static DWORD
mac_enumerate_credentials(LPCWSTR filter
, PCREDENTIALW
*credentials
,
771 char *buffer
, DWORD
*len
, DWORD
*count
)
773 SecKeychainSearchRef search
;
774 SecKeychainItemRef item
;
776 Boolean saved_user_interaction_allowed
;
779 SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed
);
780 SecKeychainSetUserInteractionAllowed(false);
782 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
785 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
787 SecKeychainAttributeInfo info
;
788 SecKeychainAttributeList
*attr_list
;
789 UInt32 info_tags
[] = { kSecServiceItemAttr
};
792 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
793 info
.tag
= info_tags
;
795 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
798 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
803 *len
= sizeof(CREDENTIALW
);
804 credentials
[*count
] = (PCREDENTIALW
)buffer
;
807 *len
+= sizeof(CREDENTIALW
);
808 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
810 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
813 TRACE("service item: %.*s\n", (int)attr_list
->attr
[0].length
, (char *)attr_list
->attr
[0].data
);
814 match
= mac_credential_matches_filter(attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, filter
);
815 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
816 if (!match
) continue;
817 ret
= mac_read_credential_from_item(item
, FALSE
,
818 buffer
? credentials
[*count
] : NULL
,
819 buffer
? buffer
+ sizeof(CREDENTIALW
) : NULL
,
822 if (ret
== ERROR_SUCCESS
)
825 if (buffer
) buffer
+= *len
;
831 ERR("SecKeychainSearchCreateFromAttributes returned status %ld\n", status
);
832 SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed
);
833 return ERROR_SUCCESS
;
836 static DWORD
mac_delete_credential(LPCWSTR TargetName
)
839 SecKeychainSearchRef search
;
840 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
843 SecKeychainItemRef item
;
844 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
846 SecKeychainAttributeInfo info
;
847 SecKeychainAttributeList
*attr_list
;
848 UInt32 info_tags
[] = { kSecServiceItemAttr
};
851 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
852 info
.tag
= info_tags
;
854 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
857 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
860 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
865 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
866 target_name
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
867 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
869 target_name
[str_len
] = '\0';
870 if (strcmpiW(TargetName
, target_name
))
873 HeapFree(GetProcessHeap(), 0, target_name
);
876 HeapFree(GetProcessHeap(), 0, target_name
);
877 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
878 SecKeychainItemDelete(item
);
882 return ERROR_SUCCESS
;
886 return ERROR_NOT_FOUND
;
890 /******************************************************************************
891 * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
893 * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
897 static INT
convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW
*CredentialW
, PCREDENTIALA CredentialA
, DWORD len
)
901 INT needed
= sizeof(CREDENTIALA
);
905 if (CredentialW
->TargetName
)
906 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
907 if (CredentialW
->Comment
)
908 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, NULL
, 0, NULL
, NULL
);
909 needed
+= CredentialW
->CredentialBlobSize
;
910 if (CredentialW
->TargetAlias
)
911 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, NULL
, 0, NULL
, NULL
);
912 if (CredentialW
->UserName
)
913 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, NULL
, 0, NULL
, NULL
);
919 buffer
= (char *)CredentialA
+ sizeof(CREDENTIALA
);
920 len
-= sizeof(CREDENTIALA
);
921 CredentialA
->Flags
= CredentialW
->Flags
;
922 CredentialA
->Type
= CredentialW
->Type
;
924 if (CredentialW
->TargetName
)
926 CredentialA
->TargetName
= buffer
;
927 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, buffer
, len
, NULL
, NULL
);
928 buffer
+= string_len
;
929 needed
+= string_len
;
933 CredentialA
->TargetName
= NULL
;
934 if (CredentialW
->Comment
)
936 CredentialA
->Comment
= buffer
;
937 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, buffer
, len
, NULL
, NULL
);
938 buffer
+= string_len
;
939 needed
+= string_len
;
943 CredentialA
->Comment
= NULL
;
944 CredentialA
->LastWritten
= CredentialW
->LastWritten
;
945 CredentialA
->CredentialBlobSize
= CredentialW
->CredentialBlobSize
;
946 if (CredentialW
->CredentialBlobSize
&& (CredentialW
->CredentialBlobSize
<= len
))
948 CredentialA
->CredentialBlob
=(LPBYTE
)buffer
;
949 memcpy(CredentialA
->CredentialBlob
, CredentialW
->CredentialBlob
,
950 CredentialW
->CredentialBlobSize
);
951 buffer
+= CredentialW
->CredentialBlobSize
;
952 needed
+= CredentialW
->CredentialBlobSize
;
953 len
-= CredentialW
->CredentialBlobSize
;
956 CredentialA
->CredentialBlob
= NULL
;
957 CredentialA
->Persist
= CredentialW
->Persist
;
958 CredentialA
->AttributeCount
= 0;
959 CredentialA
->Attributes
= NULL
; /* FIXME */
960 if (CredentialW
->TargetAlias
)
962 CredentialA
->TargetAlias
= buffer
;
963 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, buffer
, len
, NULL
, NULL
);
964 buffer
+= string_len
;
965 needed
+= string_len
;
969 CredentialA
->TargetAlias
= NULL
;
970 if (CredentialW
->UserName
)
972 CredentialA
->UserName
= buffer
;
973 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, buffer
, len
, NULL
, NULL
);
974 needed
+= string_len
;
977 CredentialA
->UserName
= NULL
;
982 /******************************************************************************
983 * convert_PCREDENTIALA_to_PCREDENTIALW [internal]
985 * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
988 static INT
convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA
*CredentialA
, PCREDENTIALW CredentialW
, INT len
)
992 INT needed
= sizeof(CREDENTIALW
);
996 if (CredentialA
->TargetName
)
997 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, NULL
, 0);
998 if (CredentialA
->Comment
)
999 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, NULL
, 0);
1000 needed
+= CredentialA
->CredentialBlobSize
;
1001 if (CredentialA
->TargetAlias
)
1002 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, NULL
, 0);
1003 if (CredentialA
->UserName
)
1004 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, NULL
, 0);
1009 buffer
= (char *)CredentialW
+ sizeof(CREDENTIALW
);
1010 len
-= sizeof(CREDENTIALW
);
1011 CredentialW
->Flags
= CredentialA
->Flags
;
1012 CredentialW
->Type
= CredentialA
->Type
;
1013 if (CredentialA
->TargetName
)
1015 CredentialW
->TargetName
= (LPWSTR
)buffer
;
1016 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, CredentialW
->TargetName
, len
/ sizeof(WCHAR
));
1017 buffer
+= sizeof(WCHAR
) * string_len
;
1018 needed
+= sizeof(WCHAR
) * string_len
;
1019 len
-= sizeof(WCHAR
) * string_len
;
1022 CredentialW
->TargetName
= NULL
;
1023 if (CredentialA
->Comment
)
1025 CredentialW
->Comment
= (LPWSTR
)buffer
;
1026 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, CredentialW
->Comment
, len
/ sizeof(WCHAR
));
1027 buffer
+= sizeof(WCHAR
) * string_len
;
1028 needed
+= sizeof(WCHAR
) * string_len
;
1029 len
-= sizeof(WCHAR
) * string_len
;
1032 CredentialW
->Comment
= NULL
;
1033 CredentialW
->LastWritten
= CredentialA
->LastWritten
;
1034 CredentialW
->CredentialBlobSize
= CredentialA
->CredentialBlobSize
;
1035 if (CredentialA
->CredentialBlobSize
)
1037 CredentialW
->CredentialBlob
=(LPBYTE
)buffer
;
1038 memcpy(CredentialW
->CredentialBlob
, CredentialA
->CredentialBlob
,
1039 CredentialA
->CredentialBlobSize
);
1040 buffer
+= CredentialA
->CredentialBlobSize
;
1041 needed
+= CredentialA
->CredentialBlobSize
;
1042 len
-= CredentialA
->CredentialBlobSize
;
1045 CredentialW
->CredentialBlob
= NULL
;
1046 CredentialW
->Persist
= CredentialA
->Persist
;
1047 CredentialW
->AttributeCount
= 0;
1048 CredentialW
->Attributes
= NULL
; /* FIXME */
1049 if (CredentialA
->TargetAlias
)
1051 CredentialW
->TargetAlias
= (LPWSTR
)buffer
;
1052 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, CredentialW
->TargetAlias
, len
/ sizeof(WCHAR
));
1053 buffer
+= sizeof(WCHAR
) * string_len
;
1054 needed
+= sizeof(WCHAR
) * string_len
;
1055 len
-= sizeof(WCHAR
) * string_len
;
1058 CredentialW
->TargetAlias
= NULL
;
1059 if (CredentialA
->UserName
)
1061 CredentialW
->UserName
= (LPWSTR
)buffer
;
1062 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, CredentialW
->UserName
, len
/ sizeof(WCHAR
));
1063 needed
+= sizeof(WCHAR
) * string_len
;
1066 CredentialW
->UserName
= NULL
;
1071 /******************************************************************************
1072 * CredDeleteA [ADVAPI32.@]
1074 BOOL WINAPI
CredDeleteA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
)
1080 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName
), Type
, Flags
);
1084 SetLastError(ERROR_INVALID_PARAMETER
);
1088 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1089 TargetNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1092 SetLastError(ERROR_OUTOFMEMORY
);
1095 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1097 ret
= CredDeleteW(TargetNameW
, Type
, Flags
);
1099 HeapFree(GetProcessHeap(), 0, TargetNameW
);
1104 /******************************************************************************
1105 * CredDeleteW [ADVAPI32.@]
1107 BOOL WINAPI
CredDeleteW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
)
1113 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName
), Type
, Flags
);
1117 SetLastError(ERROR_INVALID_PARAMETER
);
1121 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1123 FIXME("unhandled type %d\n", Type
);
1124 SetLastError(ERROR_INVALID_PARAMETER
);
1130 FIXME("unhandled flags 0x%x\n", Flags
);
1131 SetLastError(ERROR_INVALID_FLAGS
);
1136 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1138 ret
= mac_delete_credential(TargetName
);
1139 if (ret
== ERROR_SUCCESS
)
1144 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
1145 if (ret
!= ERROR_SUCCESS
)
1147 WARN("couldn't open/create manager key, error %d\n", ret
);
1148 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1152 key_name
= get_key_name_for_target(TargetName
, Type
);
1153 ret
= RegDeleteKeyW(hkeyMgr
, key_name
);
1154 HeapFree(GetProcessHeap(), 0, key_name
);
1155 RegCloseKey(hkeyMgr
);
1156 if (ret
!= ERROR_SUCCESS
)
1158 SetLastError(ERROR_NOT_FOUND
);
1165 /******************************************************************************
1166 * CredEnumerateA [ADVAPI32.@]
1168 BOOL WINAPI
CredEnumerateA(LPCSTR Filter
, DWORD Flags
, DWORD
*Count
,
1169 PCREDENTIALA
**Credentials
)
1172 PCREDENTIALW
*CredentialsW
;
1178 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter
), Flags
, Count
, Credentials
);
1182 len
= MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, NULL
, 0);
1183 FilterW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1186 SetLastError(ERROR_OUTOFMEMORY
);
1189 MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, FilterW
, len
);
1194 if (!CredEnumerateW(FilterW
, Flags
, Count
, &CredentialsW
))
1196 HeapFree(GetProcessHeap(), 0, FilterW
);
1199 HeapFree(GetProcessHeap(), 0, FilterW
);
1201 len
= *Count
* sizeof(PCREDENTIALA
);
1202 for (i
= 0; i
< *Count
; i
++)
1203 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1205 *Credentials
= HeapAlloc(GetProcessHeap(), 0, len
);
1208 CredFree(CredentialsW
);
1209 SetLastError(ERROR_OUTOFMEMORY
);
1213 buffer
= (char *)&(*Credentials
)[*Count
];
1214 len
-= *Count
* sizeof(PCREDENTIALA
);
1215 for (i
= 0; i
< *Count
; i
++)
1217 (*Credentials
)[i
] = (PCREDENTIALA
)buffer
;
1218 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1223 CredFree(CredentialsW
);
1228 /******************************************************************************
1229 * CredEnumerateW [ADVAPI32.@]
1231 BOOL WINAPI
CredEnumerateW(LPCWSTR Filter
, DWORD Flags
, DWORD
*Count
,
1232 PCREDENTIALW
**Credentials
)
1237 DWORD target_name_len
;
1240 BYTE key_data
[KEY_SIZE
];
1242 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter
), Flags
, Count
, Credentials
);
1246 SetLastError(ERROR_INVALID_FLAGS
);
1250 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1251 if (ret
!= ERROR_SUCCESS
)
1253 WARN("couldn't open/create manager key, error %d\n", ret
);
1254 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1258 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1259 if (ret
!= ERROR_SUCCESS
)
1261 RegCloseKey(hkeyMgr
);
1266 ret
= RegQueryInfoKeyW(hkeyMgr
, NULL
, NULL
, NULL
, NULL
, &target_name_len
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1267 if (ret
!= ERROR_SUCCESS
)
1269 RegCloseKey(hkeyMgr
);
1274 target_name
= HeapAlloc(GetProcessHeap(), 0, (target_name_len
+1)*sizeof(WCHAR
));
1277 RegCloseKey(hkeyMgr
);
1278 SetLastError(ERROR_OUTOFMEMORY
);
1284 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
, target_name_len
,
1285 key_data
, NULL
, NULL
, &len
, Count
);
1287 if (ret
== ERROR_SUCCESS
)
1288 ret
= mac_enumerate_credentials(Filter
, NULL
, NULL
, &len
, Count
);
1290 if (ret
== ERROR_SUCCESS
&& *Count
== 0)
1291 ret
= ERROR_NOT_FOUND
;
1292 if (ret
!= ERROR_SUCCESS
)
1294 HeapFree(GetProcessHeap(), 0, target_name
);
1295 RegCloseKey(hkeyMgr
);
1299 len
+= *Count
* sizeof(PCREDENTIALW
);
1301 if (ret
== ERROR_SUCCESS
)
1303 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
1304 *Credentials
= (PCREDENTIALW
*)buffer
;
1307 buffer
+= *Count
* sizeof(PCREDENTIALW
);
1309 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
,
1310 target_name_len
, key_data
,
1311 *Credentials
, &buffer
, &len
,
1314 if (ret
== ERROR_SUCCESS
)
1315 ret
= mac_enumerate_credentials(Filter
, *Credentials
,
1316 buffer
, &len
, Count
);
1320 ret
= ERROR_OUTOFMEMORY
;
1323 HeapFree(GetProcessHeap(), 0, target_name
);
1324 RegCloseKey(hkeyMgr
);
1326 if (ret
!= ERROR_SUCCESS
)
1334 /******************************************************************************
1335 * CredFree [ADVAPI32.@]
1337 VOID WINAPI
CredFree(PVOID Buffer
)
1339 HeapFree(GetProcessHeap(), 0, Buffer
);
1342 /******************************************************************************
1343 * CredReadA [ADVAPI32.@]
1345 BOOL WINAPI
CredReadA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALA
*Credential
)
1348 PCREDENTIALW CredentialW
;
1351 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName
), Type
, Flags
, Credential
);
1355 SetLastError(ERROR_INVALID_PARAMETER
);
1359 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1360 TargetNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1363 SetLastError(ERROR_OUTOFMEMORY
);
1366 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1368 if (!CredReadW(TargetNameW
, Type
, Flags
, &CredentialW
))
1370 HeapFree(GetProcessHeap(), 0, TargetNameW
);
1373 HeapFree(GetProcessHeap(), 0, TargetNameW
);
1375 len
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, NULL
, 0);
1376 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
1379 SetLastError(ERROR_OUTOFMEMORY
);
1382 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, *Credential
, len
);
1384 CredFree(CredentialW
);
1389 /******************************************************************************
1390 * CredReadW [ADVAPI32.@]
1392 BOOL WINAPI
CredReadW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALW
*Credential
)
1399 BYTE key_data
[KEY_SIZE
];
1401 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName
), Type
, Flags
, Credential
);
1405 SetLastError(ERROR_INVALID_PARAMETER
);
1409 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1411 FIXME("unhandled type %d\n", Type
);
1412 SetLastError(ERROR_INVALID_PARAMETER
);
1418 FIXME("unhandled flags 0x%x\n", Flags
);
1419 SetLastError(ERROR_INVALID_FLAGS
);
1424 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1427 SecKeychainSearchRef search
;
1428 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
1429 if (status
== noErr
)
1431 SecKeychainItemRef item
;
1432 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
1434 SecKeychainAttributeInfo info
;
1435 SecKeychainAttributeList
*attr_list
;
1436 UInt32 info_tags
[] = { kSecServiceItemAttr
};
1439 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
1440 info
.tag
= info_tags
;
1442 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
1443 len
= sizeof(**Credential
);
1444 if (status
!= noErr
)
1446 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
1449 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
1454 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
1455 target_name
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
1456 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
1458 target_name
[str_len
] = '\0';
1459 if (strcmpiW(TargetName
, target_name
))
1462 HeapFree(GetProcessHeap(), 0, target_name
);
1465 HeapFree(GetProcessHeap(), 0, target_name
);
1466 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
1467 ret
= mac_read_credential_from_item(item
, TRUE
, NULL
, NULL
, &len
);
1468 if (ret
== ERROR_SUCCESS
)
1470 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
1473 len
= sizeof(**Credential
);
1474 ret
= mac_read_credential_from_item(item
, TRUE
, *Credential
,
1475 (char *)(*Credential
+ 1), &len
);
1478 ret
= ERROR_OUTOFMEMORY
;
1481 if (ret
!= ERROR_SUCCESS
)
1495 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1496 if (ret
!= ERROR_SUCCESS
)
1498 WARN("couldn't open/create manager key, error %d\n", ret
);
1499 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1503 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1504 if (ret
!= ERROR_SUCCESS
)
1506 RegCloseKey(hkeyMgr
);
1511 key_name
= get_key_name_for_target(TargetName
, Type
);
1512 ret
= RegOpenKeyExW(hkeyMgr
, key_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
1513 HeapFree(GetProcessHeap(), 0, key_name
);
1514 if (ret
!= ERROR_SUCCESS
)
1516 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName
));
1517 SetLastError(ERROR_NOT_FOUND
);
1521 len
= sizeof(**Credential
);
1522 ret
= registry_read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
1523 if (ret
== ERROR_SUCCESS
)
1525 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
1528 len
= sizeof(**Credential
);
1529 ret
= registry_read_credential(hkeyCred
, *Credential
, key_data
,
1530 (char *)(*Credential
+ 1), &len
);
1533 ret
= ERROR_OUTOFMEMORY
;
1536 RegCloseKey(hkeyCred
);
1537 RegCloseKey(hkeyMgr
);
1539 if (ret
!= ERROR_SUCCESS
)
1547 /******************************************************************************
1548 * CredReadDomainCredentialsA [ADVAPI32.@]
1550 BOOL WINAPI
CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation
,
1551 DWORD Flags
, DWORD
*Size
, PCREDENTIALA
**Credentials
)
1553 PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW
;
1556 WCHAR
*buffer
, *end
;
1558 PCREDENTIALW
* CredentialsW
;
1560 TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation
, Flags
, Size
, Credentials
);
1562 /* follow Windows behavior - do not test for NULL, initialize early */
1564 *Credentials
= NULL
;
1566 if (!TargetInformation
)
1568 SetLastError(ERROR_INVALID_PARAMETER
);
1572 len
= sizeof(*TargetInformationW
);
1573 if (TargetInformation
->TargetName
)
1574 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1, NULL
, 0) * sizeof(WCHAR
);
1575 if (TargetInformation
->NetbiosServerName
)
1576 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1577 if (TargetInformation
->DnsServerName
)
1578 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1579 if (TargetInformation
->NetbiosDomainName
)
1580 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1581 if (TargetInformation
->DnsDomainName
)
1582 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1583 if (TargetInformation
->DnsTreeName
)
1584 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1, NULL
, 0) * sizeof(WCHAR
);
1585 if (TargetInformation
->PackageName
)
1586 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1, NULL
, 0) * sizeof(WCHAR
);
1588 TargetInformationW
= HeapAlloc(GetProcessHeap(), 0, len
);
1589 if (!TargetInformationW
)
1591 SetLastError(ERROR_OUTOFMEMORY
);
1594 buffer
= (WCHAR
*)(TargetInformationW
+ 1);
1595 end
= (WCHAR
*)((char *)TargetInformationW
+ len
);
1597 if (TargetInformation
->TargetName
)
1599 TargetInformationW
->TargetName
= buffer
;
1600 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1,
1601 TargetInformationW
->TargetName
, end
- buffer
);
1603 TargetInformationW
->TargetName
= NULL
;
1605 if (TargetInformation
->NetbiosServerName
)
1607 TargetInformationW
->NetbiosServerName
= buffer
;
1608 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1,
1609 TargetInformationW
->NetbiosServerName
, end
- buffer
);
1611 TargetInformationW
->NetbiosServerName
= NULL
;
1613 if (TargetInformation
->DnsServerName
)
1615 TargetInformationW
->DnsServerName
= buffer
;
1616 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1,
1617 TargetInformationW
->DnsServerName
, end
- buffer
);
1619 TargetInformationW
->DnsServerName
= NULL
;
1621 if (TargetInformation
->NetbiosDomainName
)
1623 TargetInformationW
->NetbiosDomainName
= buffer
;
1624 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1,
1625 TargetInformationW
->NetbiosDomainName
, end
- buffer
);
1627 TargetInformationW
->NetbiosDomainName
= NULL
;
1629 if (TargetInformation
->DnsDomainName
)
1631 TargetInformationW
->DnsDomainName
= buffer
;
1632 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1,
1633 TargetInformationW
->DnsDomainName
, end
- buffer
);
1635 TargetInformationW
->DnsDomainName
= NULL
;
1637 if (TargetInformation
->DnsTreeName
)
1639 TargetInformationW
->DnsTreeName
= buffer
;
1640 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1,
1641 TargetInformationW
->DnsTreeName
, end
- buffer
);
1643 TargetInformationW
->DnsTreeName
= NULL
;
1645 if (TargetInformation
->PackageName
)
1647 TargetInformationW
->PackageName
= buffer
;
1648 MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1,
1649 TargetInformationW
->PackageName
, end
- buffer
);
1651 TargetInformationW
->PackageName
= NULL
;
1653 TargetInformationW
->Flags
= TargetInformation
->Flags
;
1654 TargetInformationW
->CredTypeCount
= TargetInformation
->CredTypeCount
;
1655 TargetInformationW
->CredTypes
= TargetInformation
->CredTypes
;
1657 ret
= CredReadDomainCredentialsW(TargetInformationW
, Flags
, Size
, &CredentialsW
);
1659 HeapFree(GetProcessHeap(), 0, TargetInformationW
);
1666 len
= *Size
* sizeof(PCREDENTIALA
);
1667 for (i
= 0; i
< *Size
; i
++)
1668 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1670 *Credentials
= HeapAlloc(GetProcessHeap(), 0, len
);
1673 CredFree(CredentialsW
);
1674 SetLastError(ERROR_OUTOFMEMORY
);
1678 buf
= (char *)&(*Credentials
)[*Size
];
1679 len
-= *Size
* sizeof(PCREDENTIALA
);
1680 for (i
= 0; i
< *Size
; i
++)
1682 (*Credentials
)[i
] = (PCREDENTIALA
)buf
;
1683 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1688 CredFree(CredentialsW
);
1693 /******************************************************************************
1694 * CredReadDomainCredentialsW [ADVAPI32.@]
1696 BOOL WINAPI
CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation
, DWORD Flags
,
1697 DWORD
*Size
, PCREDENTIALW
**Credentials
)
1699 FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation
, Flags
, Size
, Credentials
);
1701 /* follow Windows behavior - do not test for NULL, initialize early */
1703 *Credentials
= NULL
;
1704 if (!TargetInformation
)
1706 SetLastError(ERROR_INVALID_PARAMETER
);
1710 SetLastError(ERROR_NOT_FOUND
);
1714 /******************************************************************************
1715 * CredWriteA [ADVAPI32.@]
1717 BOOL WINAPI
CredWriteA(PCREDENTIALA Credential
, DWORD Flags
)
1721 PCREDENTIALW CredentialW
;
1723 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1725 if (!Credential
|| !Credential
->TargetName
)
1727 SetLastError(ERROR_INVALID_PARAMETER
);
1731 len
= convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, NULL
, 0);
1732 CredentialW
= HeapAlloc(GetProcessHeap(), 0, len
);
1735 SetLastError(ERROR_OUTOFMEMORY
);
1739 convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, CredentialW
, len
);
1741 ret
= CredWriteW(CredentialW
, Flags
);
1743 HeapFree(GetProcessHeap(), 0, CredentialW
);
1748 /******************************************************************************
1749 * CredWriteW [ADVAPI32.@]
1751 BOOL WINAPI
CredWriteW(PCREDENTIALW Credential
, DWORD Flags
)
1757 BYTE key_data
[KEY_SIZE
];
1759 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1761 if (!Credential
|| !Credential
->TargetName
)
1763 SetLastError(ERROR_INVALID_PARAMETER
);
1767 if (Flags
& ~CRED_PRESERVE_CREDENTIAL_BLOB
)
1769 FIXME("unhandled flags 0x%x\n", Flags
);
1770 SetLastError(ERROR_INVALID_FLAGS
);
1774 if (Credential
->Type
!= CRED_TYPE_GENERIC
&& Credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1776 FIXME("unhandled type %d\n", Credential
->Type
);
1777 SetLastError(ERROR_INVALID_PARAMETER
);
1781 TRACE("Credential->Flags = 0x%08x\n", Credential
->Flags
);
1782 TRACE("Credential->Type = %u\n", Credential
->Type
);
1783 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential
->TargetName
));
1784 TRACE("Credential->Comment = %s\n", debugstr_w(Credential
->Comment
));
1785 TRACE("Credential->Persist = %u\n", Credential
->Persist
);
1786 TRACE("Credential->TargetAlias = %s\n", debugstr_w(Credential
->TargetAlias
));
1787 TRACE("Credential->UserName = %s\n", debugstr_w(Credential
->UserName
));
1789 if (Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1791 if (!Credential
->UserName
||
1792 (Credential
->Persist
== CRED_PERSIST_ENTERPRISE
&&
1793 (!strchrW(Credential
->UserName
, '\\') && !strchrW(Credential
->UserName
, '@'))))
1795 ERR("bad username %s\n", debugstr_w(Credential
->UserName
));
1796 SetLastError(ERROR_BAD_USERNAME
);
1802 if (!Credential
->AttributeCount
&&
1803 Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
&&
1804 (Credential
->Persist
== CRED_PERSIST_LOCAL_MACHINE
|| Credential
->Persist
== CRED_PERSIST_ENTERPRISE
))
1806 ret
= mac_write_credential(Credential
, Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1807 if (ret
!= ERROR_SUCCESS
)
1816 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1817 if (ret
!= ERROR_SUCCESS
)
1819 WARN("couldn't open/create manager key, error %d\n", ret
);
1820 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1824 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1825 if (ret
!= ERROR_SUCCESS
)
1827 RegCloseKey(hkeyMgr
);
1832 key_name
= get_key_name_for_target(Credential
->TargetName
, Credential
->Type
);
1833 ret
= RegCreateKeyExW(hkeyMgr
, key_name
, 0, NULL
,
1834 Credential
->Persist
== CRED_PERSIST_SESSION
? REG_OPTION_VOLATILE
: REG_OPTION_NON_VOLATILE
,
1835 KEY_READ
|KEY_WRITE
, NULL
, &hkeyCred
, NULL
);
1836 HeapFree(GetProcessHeap(), 0, key_name
);
1837 if (ret
!= ERROR_SUCCESS
)
1839 TRACE("credentials for target name %s not found\n",
1840 debugstr_w(Credential
->TargetName
));
1841 SetLastError(ERROR_NOT_FOUND
);
1845 ret
= registry_write_credential(hkeyCred
, Credential
, key_data
,
1846 Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1848 RegCloseKey(hkeyCred
);
1849 RegCloseKey(hkeyMgr
);
1851 if (ret
!= ERROR_SUCCESS
)
1859 /******************************************************************************
1860 * CredGetSessionTypes [ADVAPI32.@]
1862 WINADVAPI BOOL WINAPI
CredGetSessionTypes(DWORD persistCount
, LPDWORD persists
)
1864 TRACE("(%u, %p)\n", persistCount
, persists
);
1866 memset(persists
, CRED_PERSIST_NONE
, persistCount
*sizeof(*persists
));
1867 if (CRED_TYPE_GENERIC
< persistCount
)
1869 persists
[CRED_TYPE_GENERIC
] = CRED_PERSIST_ENTERPRISE
;
1871 if (CRED_TYPE_DOMAIN_PASSWORD
< persistCount
)
1873 persists
[CRED_TYPE_DOMAIN_PASSWORD
] = CRED_PERSIST_ENTERPRISE
;
1879 /******************************************************************************
1880 * CredMarshalCredentialA [ADVAPI32.@]
1882 BOOL WINAPI
CredMarshalCredentialA( CRED_MARSHAL_TYPE type
, PVOID cred
, LPSTR
*out
)
1887 TRACE("%u, %p, %p\n", type
, cred
, out
);
1889 if ((ret
= CredMarshalCredentialW( type
, cred
, &outW
)))
1891 int len
= WideCharToMultiByte( CP_ACP
, 0, outW
, -1, NULL
, 0, NULL
, NULL
);
1892 if (!(*out
= HeapAlloc( GetProcessHeap(), 0, len
)))
1894 HeapFree( GetProcessHeap(), 0, outW
);
1897 WideCharToMultiByte( CP_ACP
, 0, outW
, -1, *out
, len
, NULL
, NULL
);
1898 HeapFree( GetProcessHeap(), 0, outW
);
1903 static UINT
cred_encode( const char *bin
, unsigned int len
, WCHAR
*cred
)
1905 static const char enc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#-";
1910 cred
[n
++] = enc
[bin
[0] & 0x3f];
1911 x
= (bin
[0] & 0xc0) >> 6;
1917 cred
[n
++] = enc
[((bin
[1] & 0xf) << 2) | x
];
1918 x
= (bin
[1] & 0xf0) >> 4;
1924 cred
[n
++] = enc
[((bin
[2] & 0x3) << 4) | x
];
1925 cred
[n
++] = enc
[(bin
[2] & 0xfc) >> 2];
1932 /******************************************************************************
1933 * CredMarshalCredentialW [ADVAPI32.@]
1935 BOOL WINAPI
CredMarshalCredentialW( CRED_MARSHAL_TYPE type
, PVOID cred
, LPWSTR
*out
)
1937 CERT_CREDENTIAL_INFO
*cert
= cred
;
1938 USERNAME_TARGET_CREDENTIAL_INFO
*target
= cred
;
1942 TRACE("%u, %p, %p\n", type
, cred
, out
);
1944 if (!cred
|| (type
== CertCredential
&& cert
->cbSize
< sizeof(*cert
)) ||
1945 (type
!= CertCredential
&& type
!= UsernameTargetCredential
&& type
!= BinaryBlobCredential
) ||
1946 (type
== UsernameTargetCredential
&& (!target
->UserName
|| !target
->UserName
[0])))
1948 SetLastError( ERROR_INVALID_PARAMETER
);
1953 case CertCredential
:
1955 char hash
[CERT_HASH_LENGTH
+ 2];
1957 memcpy( hash
, cert
->rgbHashOfCert
, sizeof(cert
->rgbHashOfCert
) );
1958 memset( hash
+ sizeof(cert
->rgbHashOfCert
), 0, sizeof(hash
) - sizeof(cert
->rgbHashOfCert
) );
1960 size
= sizeof(hash
) * 4 / 3;
1961 if (!(p
= HeapAlloc( GetProcessHeap(), 0, (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1965 len
= cred_encode( (const char *)hash
, sizeof(hash
), p
+ 3 );
1969 case UsernameTargetCredential
:
1971 len
= strlenW( target
->UserName
);
1972 size
= (sizeof(DWORD
) + len
* sizeof(WCHAR
) + 2) * 4 / 3;
1973 if (!(p
= HeapAlloc( GetProcessHeap(), 0, (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1977 size
= len
* sizeof(WCHAR
);
1978 len
= cred_encode( (const char *)&size
, sizeof(DWORD
), p
+ 3 );
1979 len
+= cred_encode( (const char *)target
->UserName
, size
, p
+ 3 + len
);
1983 case BinaryBlobCredential
:
1984 FIXME("BinaryBlobCredential not implemented\n");
1993 /******************************************************************************
1994 * CredUnmarshalCredentialA [ADVAPI32.@]
1996 BOOL WINAPI
CredUnmarshalCredentialA( LPCSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
1999 WCHAR
*credW
= NULL
;
2001 TRACE("%s, %p, %p\n", debugstr_a(cred
), type
, out
);
2005 int len
= MultiByteToWideChar( CP_ACP
, 0, cred
, -1, NULL
, 0 );
2006 if (!(credW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return FALSE
;
2007 MultiByteToWideChar( CP_ACP
, 0, cred
, -1, credW
, len
);
2009 ret
= CredUnmarshalCredentialW( credW
, type
, out
);
2010 HeapFree( GetProcessHeap(), 0, credW
);
2014 static inline char char_decode( WCHAR c
)
2016 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
2017 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
2018 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
2019 if (c
== '#') return 62;
2020 if (c
== '-') return 63;
2024 static BOOL
cred_decode( const WCHAR
*cred
, unsigned int len
, char *buf
)
2027 char c0
, c1
, c2
, c3
;
2028 const WCHAR
*p
= cred
;
2032 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2033 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2034 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2035 if ((c3
= char_decode( p
[3] )) > 63) return FALSE
;
2037 buf
[i
+ 0] = (c1
<< 6) | c0
;
2038 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2039 buf
[i
+ 2] = (c3
<< 2) | (c2
>> 4);
2046 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2047 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2048 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2050 buf
[i
+ 0] = (c1
<< 6) | c0
;
2051 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2052 buf
[i
+ 2] = c2
>> 4;
2056 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2057 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2059 buf
[i
+ 0] = (c1
<< 6) | c0
;
2060 buf
[i
+ 1] = c1
>> 2;
2065 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2074 /******************************************************************************
2075 * CredUnmarshalCredentialW [ADVAPI32.@]
2077 BOOL WINAPI
CredUnmarshalCredentialW( LPCWSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
2079 unsigned int len
, buflen
;
2081 TRACE("%s, %p, %p\n", debugstr_w(cred
), type
, out
);
2083 if (!cred
|| cred
[0] != '@' || cred
[1] != '@' || !cred
[2] || !cred
[3])
2085 SetLastError( ERROR_INVALID_PARAMETER
);
2088 len
= strlenW( cred
+ 3 );
2089 switch (cred
[2] - 'A')
2091 case CertCredential
:
2093 char hash
[CERT_HASH_LENGTH
+ 2];
2094 CERT_CREDENTIAL_INFO
*cert
;
2096 if (len
!= 27 || !cred_decode( cred
+ 3, len
, hash
))
2098 SetLastError( ERROR_INVALID_PARAMETER
);
2101 if (!(cert
= HeapAlloc( GetProcessHeap(), 0, sizeof(*cert
) ))) return FALSE
;
2102 memcpy( cert
->rgbHashOfCert
, hash
, sizeof(cert
->rgbHashOfCert
) );
2103 cert
->cbSize
= sizeof(*cert
);
2104 *type
= CertCredential
;
2108 case UsernameTargetCredential
:
2110 USERNAME_TARGET_CREDENTIAL_INFO
*target
;
2113 if (len
< 9 || !cred_decode( cred
+ 3, 6, (char *)&size
) ||
2114 !size
|| size
% sizeof(WCHAR
) || size
> INT_MAX
)
2116 SetLastError( ERROR_INVALID_PARAMETER
);
2119 buflen
= sizeof(*target
) + size
+ sizeof(WCHAR
);
2120 if (!(target
= HeapAlloc( GetProcessHeap(), 0, buflen
))) return FALSE
;
2121 if (!cred_decode( cred
+ 9, len
- 6, (char *)(target
+ 1) ))
2123 HeapFree( GetProcessHeap(), 0, target
);
2126 target
->UserName
= (WCHAR
*)(target
+ 1);
2127 target
->UserName
[size
/ sizeof(WCHAR
)] = 0;
2128 *type
= UsernameTargetCredential
;
2132 case BinaryBlobCredential
:
2133 FIXME("BinaryBlobCredential not implemented\n");
2136 WARN("unhandled type %u\n", cred
[2] - 'A');
2142 /******************************************************************************
2143 * CredIsMarshaledCredentialW [ADVAPI32.@]
2145 * Check, if the name parameter is a marshaled credential, hash or binary blob
2148 * name the name to check
2151 * TRUE: the name parameter is a marshaled credential, hash or binary blob
2152 * FALSE: the name is a plain username
2154 BOOL WINAPI
CredIsMarshaledCredentialW(LPCWSTR name
)
2156 TRACE("(%s)\n", debugstr_w(name
));
2158 if (name
&& name
[0] == '@' && name
[1] == '@' && name
[2] > 'A' && name
[3])
2160 char hash
[CERT_HASH_LENGTH
+ 2];
2161 int len
= strlenW(name
+ 3 );
2164 if ((name
[2] - 'A') == CertCredential
&& (len
== 27) && cred_decode(name
+ 3, len
, hash
))
2167 if (((name
[2] - 'A') == UsernameTargetCredential
) &&
2168 (len
>= 9) && cred_decode(name
+ 3, 6, (char *)&size
) && size
)
2171 if ((name
[2] - 'A') == BinaryBlobCredential
)
2172 FIXME("BinaryBlobCredential not checked\n");
2174 if ((name
[2] - 'A') > BinaryBlobCredential
)
2175 TRACE("unknown type: %d\n", (name
[2] - 'A'));
2178 SetLastError(ERROR_INVALID_PARAMETER
);
2182 /******************************************************************************
2183 * CredIsMarshaledCredentialA [ADVAPI32.@]
2185 * See CredIsMarshaledCredentialW
2188 BOOL WINAPI
CredIsMarshaledCredentialA(LPCSTR name
)
2190 LPWSTR nameW
= NULL
;
2194 TRACE("(%s)\n", debugstr_a(name
));
2198 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0);
2199 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2200 MultiByteToWideChar(CP_ACP
, 0, name
, -1, nameW
, len
);
2203 res
= CredIsMarshaledCredentialW(nameW
);
2204 HeapFree(GetProcessHeap(), 0, nameW
);