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 #include "advapi32_misc.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(cred
);
46 /* the size of the ARC4 key used to encrypt the password data */
49 static const WCHAR wszCredentialManagerKey
[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
50 'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0};
51 static const WCHAR wszEncryptionKeyValue
[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0};
53 static const WCHAR wszFlagsValue
[] = {'F','l','a','g','s',0};
54 static const WCHAR wszTypeValue
[] = {'T','y','p','e',0};
55 static const WCHAR wszCommentValue
[] = {'C','o','m','m','e','n','t',0};
56 static const WCHAR wszLastWrittenValue
[] = {'L','a','s','t','W','r','i','t','t','e','n',0};
57 static const WCHAR wszPersistValue
[] = {'P','e','r','s','i','s','t',0};
58 static const WCHAR wszTargetAliasValue
[] = {'T','a','r','g','e','t','A','l','i','a','s',0};
59 static const WCHAR wszUserNameValue
[] = {'U','s','e','r','N','a','m','e',0};
60 static const WCHAR wszPasswordValue
[] = {'P','a','s','s','w','o','r','d',0};
62 static DWORD
read_credential_blob(HKEY hkey
, const BYTE key_data
[KEY_SIZE
],
63 LPBYTE credential_blob
,
64 DWORD
*credential_blob_size
)
69 *credential_blob_size
= 0;
70 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, NULL
, credential_blob_size
);
71 if (ret
!= ERROR_SUCCESS
)
73 else if (type
!= REG_BINARY
)
74 return ERROR_REGISTRY_CORRUPT
;
80 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, credential_blob
,
81 credential_blob_size
);
82 if (ret
!= ERROR_SUCCESS
)
84 else if (type
!= REG_BINARY
)
85 return ERROR_REGISTRY_CORRUPT
;
87 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
88 key
.Buffer
= (unsigned char *)key_data
;
90 data
.Length
= data
.MaximumLength
= *credential_blob_size
;
91 data
.Buffer
= credential_blob
;
92 SystemFunction032(&data
, &key
);
97 static DWORD
registry_read_credential(HKEY hkey
, PCREDENTIALW credential
,
98 const BYTE key_data
[KEY_SIZE
],
99 char *buffer
, DWORD
*len
)
105 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, NULL
, &count
);
106 if (ret
!= ERROR_SUCCESS
)
108 else if (type
!= REG_SZ
)
109 return ERROR_REGISTRY_CORRUPT
;
113 credential
->TargetName
= (LPWSTR
)buffer
;
114 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, (LPVOID
)credential
->TargetName
,
116 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) return ret
;
120 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, NULL
, &count
);
121 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
123 else if (type
!= REG_SZ
)
124 return ERROR_REGISTRY_CORRUPT
;
128 credential
->Comment
= (LPWSTR
)buffer
;
129 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, (LPVOID
)credential
->Comment
,
131 if (ret
== ERROR_FILE_NOT_FOUND
)
132 credential
->Comment
= NULL
;
133 else if (ret
!= ERROR_SUCCESS
)
135 else if (type
!= REG_SZ
)
136 return ERROR_REGISTRY_CORRUPT
;
141 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, NULL
, &count
);
142 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
144 else if (type
!= REG_SZ
)
145 return ERROR_REGISTRY_CORRUPT
;
149 credential
->TargetAlias
= (LPWSTR
)buffer
;
150 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, (LPVOID
)credential
->TargetAlias
,
152 if (ret
== ERROR_FILE_NOT_FOUND
)
153 credential
->TargetAlias
= NULL
;
154 else if (ret
!= ERROR_SUCCESS
)
156 else if (type
!= REG_SZ
)
157 return ERROR_REGISTRY_CORRUPT
;
162 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, NULL
, &count
);
163 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
165 else if (type
!= REG_SZ
)
166 return ERROR_REGISTRY_CORRUPT
;
170 credential
->UserName
= (LPWSTR
)buffer
;
171 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, (LPVOID
)credential
->UserName
,
173 if (ret
== ERROR_FILE_NOT_FOUND
)
174 credential
->UserName
= NULL
;
175 else if (ret
!= ERROR_SUCCESS
)
177 else if (type
!= REG_SZ
)
178 return ERROR_REGISTRY_CORRUPT
;
183 ret
= read_credential_blob(hkey
, key_data
, NULL
, &count
);
184 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
189 credential
->CredentialBlob
= (LPBYTE
)buffer
;
190 ret
= read_credential_blob(hkey
, key_data
, credential
->CredentialBlob
, &count
);
191 if (ret
== ERROR_FILE_NOT_FOUND
)
192 credential
->CredentialBlob
= NULL
;
193 else if (ret
!= ERROR_SUCCESS
)
195 credential
->CredentialBlobSize
= count
;
198 /* FIXME: Attributes */
201 credential
->AttributeCount
= 0;
202 credential
->Attributes
= NULL
;
205 if (!credential
) return ERROR_SUCCESS
;
207 count
= sizeof(credential
->Flags
);
208 ret
= RegQueryValueExW(hkey
, wszFlagsValue
, NULL
, &type
, (LPVOID
)&credential
->Flags
,
210 if (ret
!= ERROR_SUCCESS
)
212 else if (type
!= REG_DWORD
)
213 return ERROR_REGISTRY_CORRUPT
;
214 count
= sizeof(credential
->Type
);
215 ret
= RegQueryValueExW(hkey
, wszTypeValue
, NULL
, &type
, (LPVOID
)&credential
->Type
,
217 if (ret
!= ERROR_SUCCESS
)
219 else if (type
!= REG_DWORD
)
220 return ERROR_REGISTRY_CORRUPT
;
222 count
= sizeof(credential
->LastWritten
);
223 ret
= RegQueryValueExW(hkey
, wszLastWrittenValue
, NULL
, &type
, (LPVOID
)&credential
->LastWritten
,
225 if (ret
!= ERROR_SUCCESS
)
227 else if (type
!= REG_BINARY
)
228 return ERROR_REGISTRY_CORRUPT
;
229 count
= sizeof(credential
->Persist
);
230 ret
= RegQueryValueExW(hkey
, wszPersistValue
, NULL
, &type
, (LPVOID
)&credential
->Persist
,
232 if (ret
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
233 return ERROR_REGISTRY_CORRUPT
;
238 static DWORD
mac_read_credential_from_item(SecKeychainItemRef item
, BOOL require_password
,
239 PCREDENTIALW credential
, char *buffer
,
243 UInt32 i
, cred_blob_len
;
246 BOOL user_name_present
= FALSE
;
247 SecKeychainAttributeInfo info
;
248 SecKeychainAttributeList
*attr_list
;
249 UInt32 info_tags
[] = { kSecServiceItemAttr
, kSecAccountItemAttr
,
250 kSecCommentItemAttr
, kSecCreationDateItemAttr
};
251 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
252 info
.tag
= info_tags
;
254 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, &cred_blob
);
255 if (status
== errSecAuthFailed
&& !require_password
)
259 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, NULL
);
263 WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status
);
264 return ERROR_NOT_FOUND
;
267 for (i
= 0; i
< attr_list
->count
; i
++)
268 if (attr_list
->attr
[i
].tag
== kSecAccountItemAttr
&& attr_list
->attr
[i
].data
)
270 user_name_present
= TRUE
;
273 if (!user_name_present
)
275 WARN("no kSecAccountItemAttr for item\n");
276 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
277 return ERROR_NOT_FOUND
;
282 credential
->Flags
= 0;
283 credential
->Type
= CRED_TYPE_DOMAIN_PASSWORD
;
284 credential
->TargetName
= NULL
;
285 credential
->Comment
= NULL
;
286 memset(&credential
->LastWritten
, 0, sizeof(credential
->LastWritten
));
287 credential
->CredentialBlobSize
= 0;
288 credential
->CredentialBlob
= NULL
;
289 credential
->Persist
= CRED_PERSIST_LOCAL_MACHINE
;
290 credential
->AttributeCount
= 0;
291 credential
->Attributes
= NULL
;
292 credential
->TargetAlias
= NULL
;
293 credential
->UserName
= NULL
;
295 for (i
= 0; i
< attr_list
->count
; i
++)
297 switch (attr_list
->attr
[i
].tag
)
299 case kSecServiceItemAttr
:
300 TRACE("kSecServiceItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
301 (char *)attr_list
->attr
[i
].data
);
302 if (!attr_list
->attr
[i
].data
) continue;
306 credential
->TargetName
= (LPWSTR
)buffer
;
307 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
308 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
309 credential
->TargetName
[str_len
] = '\0';
310 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
311 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
316 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
317 attr_list
->attr
[i
].length
, NULL
, 0);
318 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
321 case kSecAccountItemAttr
:
324 TRACE("kSecAccountItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
325 (char *)attr_list
->attr
[i
].data
);
326 if (!attr_list
->attr
[i
].data
) continue;
327 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
328 attr_list
->attr
[i
].length
, NULL
, 0);
329 user
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
330 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
331 attr_list
->attr
[i
].length
, user
, str_len
);
332 user
[str_len
] = '\0';
335 case kSecCommentItemAttr
:
336 TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
337 (char *)attr_list
->attr
[i
].data
);
338 if (!attr_list
->attr
[i
].data
) continue;
342 credential
->Comment
= (LPWSTR
)buffer
;
343 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
344 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
345 credential
->Comment
[str_len
] = '\0';
346 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
347 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
352 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
353 attr_list
->attr
[i
].length
, NULL
, 0);
354 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
357 case kSecCreationDateItemAttr
:
358 TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
359 (char *)attr_list
->attr
[i
].data
);
362 LARGE_INTEGER win_time
;
365 memset(&tm
, 0, sizeof(tm
));
366 strptime(attr_list
->attr
[i
].data
, "%Y%m%d%H%M%SZ", &tm
);
368 RtlSecondsSince1970ToTime(time
, &win_time
);
369 credential
->LastWritten
.dwLowDateTime
= win_time
.u
.LowPart
;
370 credential
->LastWritten
.dwHighDateTime
= win_time
.u
.HighPart
;
374 FIXME("unhandled attribute %u\n", (unsigned)attr_list
->attr
[i
].tag
);
383 credential
->UserName
= (LPWSTR
)buffer
;
384 str_len
= strlenW(user
);
385 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
388 memcpy(buffer
, user
, (str_len
+ 1) * sizeof(WCHAR
));
389 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
390 TRACE("UserName = %s\n", debugstr_w(credential
->UserName
));
400 credential
->CredentialBlob
= (BYTE
*)buffer
;
401 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
402 (LPWSTR
)buffer
, 0xffff);
403 credential
->CredentialBlobSize
= str_len
* sizeof(WCHAR
);
404 *len
+= str_len
* sizeof(WCHAR
);
409 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
411 *len
+= str_len
* sizeof(WCHAR
);
414 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
415 return ERROR_SUCCESS
;
419 static DWORD
write_credential_blob(HKEY hkey
, LPCWSTR target_name
, DWORD type
,
420 const BYTE key_data
[KEY_SIZE
],
421 const BYTE
*credential_blob
, DWORD credential_blob_size
)
423 LPBYTE encrypted_credential_blob
;
428 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
429 key
.Buffer
= (unsigned char *)key_data
;
431 encrypted_credential_blob
= heap_alloc(credential_blob_size
);
432 if (!encrypted_credential_blob
) return ERROR_OUTOFMEMORY
;
434 memcpy(encrypted_credential_blob
, credential_blob
, credential_blob_size
);
435 data
.Length
= data
.MaximumLength
= credential_blob_size
;
436 data
.Buffer
= encrypted_credential_blob
;
437 SystemFunction032(&data
, &key
);
439 ret
= RegSetValueExW(hkey
, wszPasswordValue
, 0, REG_BINARY
, encrypted_credential_blob
, credential_blob_size
);
440 heap_free(encrypted_credential_blob
);
445 static DWORD
registry_write_credential(HKEY hkey
, const CREDENTIALW
*credential
,
446 const BYTE key_data
[KEY_SIZE
], BOOL preserve_blob
)
449 FILETIME LastWritten
;
451 GetSystemTimeAsFileTime(&LastWritten
);
453 ret
= RegSetValueExW(hkey
, wszFlagsValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Flags
,
454 sizeof(credential
->Flags
));
455 if (ret
!= ERROR_SUCCESS
) return ret
;
456 ret
= RegSetValueExW(hkey
, wszTypeValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Type
,
457 sizeof(credential
->Type
));
458 if (ret
!= ERROR_SUCCESS
) return ret
;
459 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (LPVOID
)credential
->TargetName
,
460 sizeof(WCHAR
)*(strlenW(credential
->TargetName
)+1));
461 if (ret
!= ERROR_SUCCESS
) return ret
;
462 if (credential
->Comment
)
464 ret
= RegSetValueExW(hkey
, wszCommentValue
, 0, REG_SZ
, (LPVOID
)credential
->Comment
,
465 sizeof(WCHAR
)*(strlenW(credential
->Comment
)+1));
466 if (ret
!= ERROR_SUCCESS
) return ret
;
468 ret
= RegSetValueExW(hkey
, wszLastWrittenValue
, 0, REG_BINARY
, (LPVOID
)&LastWritten
,
469 sizeof(LastWritten
));
470 if (ret
!= ERROR_SUCCESS
) return ret
;
471 ret
= RegSetValueExW(hkey
, wszPersistValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Persist
,
472 sizeof(credential
->Persist
));
473 if (ret
!= ERROR_SUCCESS
) return ret
;
474 /* FIXME: Attributes */
475 if (credential
->TargetAlias
)
477 ret
= RegSetValueExW(hkey
, wszTargetAliasValue
, 0, REG_SZ
, (LPVOID
)credential
->TargetAlias
,
478 sizeof(WCHAR
)*(strlenW(credential
->TargetAlias
)+1));
479 if (ret
!= ERROR_SUCCESS
) return ret
;
481 if (credential
->UserName
)
483 ret
= RegSetValueExW(hkey
, wszUserNameValue
, 0, REG_SZ
, (LPVOID
)credential
->UserName
,
484 sizeof(WCHAR
)*(strlenW(credential
->UserName
)+1));
485 if (ret
!= ERROR_SUCCESS
) return ret
;
489 ret
= write_credential_blob(hkey
, credential
->TargetName
, credential
->Type
,
490 key_data
, credential
->CredentialBlob
,
491 credential
->CredentialBlobSize
);
497 static DWORD
mac_write_credential(const CREDENTIALW
*credential
, BOOL preserve_blob
)
500 SecKeychainItemRef keychain_item
;
501 char *username
, *password
, *servername
;
502 UInt32 userlen
, pwlen
, serverlen
;
503 SecKeychainAttribute attrs
[1];
504 SecKeychainAttributeList attr_list
;
506 if (credential
->Flags
)
507 FIXME("Flags 0x%x not written\n", credential
->Flags
);
508 if (credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
509 FIXME("credential type of %d not supported\n", credential
->Type
);
510 if (credential
->Persist
!= CRED_PERSIST_LOCAL_MACHINE
)
511 FIXME("persist value of %d not supported\n", credential
->Persist
);
512 if (credential
->AttributeCount
)
513 FIXME("custom attributes not supported\n");
515 userlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, -1, NULL
, 0, NULL
, NULL
);
516 username
= heap_alloc(userlen
* sizeof(*username
));
517 WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, -1, username
, userlen
, NULL
, NULL
);
519 serverlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
520 servername
= heap_alloc(serverlen
* sizeof(*servername
));
521 WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, servername
, serverlen
, NULL
, NULL
);
522 pwlen
= WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
523 credential
->CredentialBlobSize
/ sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
524 password
= heap_alloc(pwlen
* sizeof(*password
));
525 WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
526 credential
->CredentialBlobSize
/ sizeof(WCHAR
), password
, pwlen
, NULL
, NULL
);
528 TRACE("adding server %s, username %s using Keychain\n", servername
, username
);
529 status
= SecKeychainAddGenericPassword(NULL
, strlen(servername
), servername
, strlen(username
),
530 username
, strlen(password
), password
, &keychain_item
);
532 ERR("SecKeychainAddGenericPassword returned %d\n", status
);
533 if (status
== errSecDuplicateItem
)
535 status
= SecKeychainFindGenericPassword(NULL
, strlen(servername
), servername
, strlen(username
),
536 username
, NULL
, NULL
, &keychain_item
);
538 ERR("SecKeychainFindGenericPassword returned %d\n", status
);
541 heap_free(servername
);
545 return ERROR_GEN_FAILURE
;
547 if (credential
->Comment
)
550 attr_list
.attr
= attrs
;
551 attrs
[0].tag
= kSecCommentItemAttr
;
552 attrs
[0].length
= WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, NULL
, 0, NULL
, NULL
);
553 if (attrs
[0].length
) attrs
[0].length
--;
554 attrs
[0].data
= heap_alloc(attrs
[0].length
);
555 WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, attrs
[0].data
, attrs
[0].length
, NULL
, NULL
);
560 attr_list
.attr
= NULL
;
562 status
= SecKeychainItemModifyAttributesAndData(keychain_item
, &attr_list
,
563 preserve_blob
? 0 : strlen(password
),
564 preserve_blob
? NULL
: password
);
565 if (credential
->Comment
)
566 heap_free(attrs
[0].data
);
568 /* FIXME: set TargetAlias attribute */
569 CFRelease(keychain_item
);
571 return ERROR_GEN_FAILURE
;
572 return ERROR_SUCCESS
;
576 static DWORD
open_cred_mgr_key(HKEY
*hkey
, BOOL open_for_write
)
578 return RegCreateKeyExW(HKEY_CURRENT_USER
, wszCredentialManagerKey
, 0,
579 NULL
, REG_OPTION_NON_VOLATILE
,
580 KEY_READ
| (open_for_write
? KEY_WRITE
: 0), NULL
, hkey
, NULL
);
583 static DWORD
get_cred_mgr_encryption_key(HKEY hkeyMgr
, BYTE key_data
[KEY_SIZE
])
585 static const BYTE my_key_data
[KEY_SIZE
] = { 0 };
593 memcpy(key_data
, my_key_data
, KEY_SIZE
);
596 ret
= RegQueryValueExW(hkeyMgr
, wszEncryptionKeyValue
, NULL
, &type
, key_data
,
598 if (ret
== ERROR_SUCCESS
)
600 if (type
!= REG_BINARY
)
601 return ERROR_REGISTRY_CORRUPT
;
603 return ERROR_SUCCESS
;
605 if (ret
!= ERROR_FILE_NOT_FOUND
)
608 GetSystemTimeAsFileTime(&ft
);
609 seed
= ft
.dwLowDateTime
;
610 value
= RtlUniform(&seed
);
611 *(DWORD
*)key_data
= value
;
612 seed
= ft
.dwHighDateTime
;
613 value
= RtlUniform(&seed
);
614 *(DWORD
*)(key_data
+ 4) = value
;
616 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
618 if (ret
== ERROR_ACCESS_DENIED
)
620 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
621 if (ret
== ERROR_SUCCESS
)
623 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
625 RegCloseKey(hkeyMgr
);
631 static LPWSTR
get_key_name_for_target(LPCWSTR target_name
, DWORD type
)
633 static const WCHAR wszGenericPrefix
[] = {'G','e','n','e','r','i','c',':',' ',0};
634 static const WCHAR wszDomPasswdPrefix
[] = {'D','o','m','P','a','s','s','w','d',':',' ',0};
636 LPCWSTR prefix
= NULL
;
639 len
= strlenW(target_name
);
640 if (type
== CRED_TYPE_GENERIC
)
642 prefix
= wszGenericPrefix
;
643 len
+= sizeof(wszGenericPrefix
)/sizeof(wszGenericPrefix
[0]);
647 prefix
= wszDomPasswdPrefix
;
648 len
+= sizeof(wszDomPasswdPrefix
)/sizeof(wszDomPasswdPrefix
[0]);
651 key_name
= heap_alloc(len
* sizeof(WCHAR
));
652 if (!key_name
) return NULL
;
654 strcpyW(key_name
, prefix
);
655 strcatW(key_name
, target_name
);
657 for (p
= key_name
; *p
; p
++)
658 if (*p
== '\\') *p
= '_';
663 static BOOL
registry_credential_matches_filter(HKEY hkeyCred
, LPCWSTR filter
)
671 if (!filter
) return TRUE
;
673 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, NULL
, &count
);
674 if (ret
!= ERROR_SUCCESS
)
676 else if (type
!= REG_SZ
)
679 target_name
= heap_alloc(count
);
682 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, (LPVOID
)target_name
, &count
);
683 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
685 heap_free(target_name
);
689 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
),
690 debugstr_w(target_name
));
692 p
= strchrW(filter
, '*');
693 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
694 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
695 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
697 heap_free(target_name
);
701 static DWORD
registry_enumerate_credentials(HKEY hkeyMgr
, LPCWSTR filter
,
703 DWORD target_name_len
, const BYTE key_data
[KEY_SIZE
],
704 PCREDENTIALW
*credentials
, char **buffer
,
705 DWORD
*len
, DWORD
*count
)
712 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
713 if (ret
== ERROR_NO_MORE_ITEMS
)
718 else if (ret
!= ERROR_SUCCESS
)
720 TRACE("target_name = %s\n", debugstr_w(target_name
));
721 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
722 if (ret
!= ERROR_SUCCESS
)
724 if (!registry_credential_matches_filter(hkeyCred
, filter
))
726 RegCloseKey(hkeyCred
);
731 *len
= sizeof(CREDENTIALW
);
732 credentials
[*count
] = (PCREDENTIALW
)*buffer
;
735 *len
+= sizeof(CREDENTIALW
);
736 ret
= registry_read_credential(hkeyCred
, buffer
? credentials
[*count
] : NULL
,
737 key_data
, buffer
? *buffer
+ sizeof(CREDENTIALW
) : NULL
,
739 RegCloseKey(hkeyCred
);
740 if (ret
!= ERROR_SUCCESS
) break;
741 if (buffer
) *buffer
+= *len
;
748 static BOOL
mac_credential_matches_filter(void *data
, UInt32 data_len
, const WCHAR
*filter
)
755 if (!filter
) return TRUE
;
757 len
= MultiByteToWideChar(CP_UTF8
, 0, data
, data_len
, NULL
, 0);
758 if (!(target_name
= heap_alloc((len
+ 1) * sizeof(WCHAR
)))) return FALSE
;
759 MultiByteToWideChar(CP_UTF8
, 0, data
, data_len
, target_name
, len
);
760 target_name
[len
] = 0;
762 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
), debugstr_w(target_name
));
764 p
= strchrW(filter
, '*');
765 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
766 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
767 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
768 heap_free(target_name
);
772 static DWORD
mac_enumerate_credentials(LPCWSTR filter
, PCREDENTIALW
*credentials
,
773 char *buffer
, DWORD
*len
, DWORD
*count
)
775 SecKeychainSearchRef search
;
776 SecKeychainItemRef item
;
778 Boolean saved_user_interaction_allowed
;
781 SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed
);
782 SecKeychainSetUserInteractionAllowed(false);
784 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
787 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
789 SecKeychainAttributeInfo info
;
790 SecKeychainAttributeList
*attr_list
;
791 UInt32 info_tags
[] = { kSecServiceItemAttr
};
794 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
795 info
.tag
= info_tags
;
797 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
800 WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status
);
805 *len
= sizeof(CREDENTIALW
);
806 credentials
[*count
] = (PCREDENTIALW
)buffer
;
809 *len
+= sizeof(CREDENTIALW
);
810 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
812 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
815 TRACE("service item: %.*s\n", (int)attr_list
->attr
[0].length
, (char *)attr_list
->attr
[0].data
);
816 match
= mac_credential_matches_filter(attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, filter
);
817 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
818 if (!match
) continue;
819 ret
= mac_read_credential_from_item(item
, FALSE
,
820 buffer
? credentials
[*count
] : NULL
,
821 buffer
? buffer
+ sizeof(CREDENTIALW
) : NULL
,
824 if (ret
== ERROR_SUCCESS
)
827 if (buffer
) buffer
+= *len
;
833 ERR("SecKeychainSearchCreateFromAttributes returned status %d\n", status
);
834 SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed
);
835 return ERROR_SUCCESS
;
838 static DWORD
mac_delete_credential(LPCWSTR TargetName
)
841 SecKeychainSearchRef search
;
842 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
845 SecKeychainItemRef item
;
846 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
848 SecKeychainAttributeInfo info
;
849 SecKeychainAttributeList
*attr_list
;
850 UInt32 info_tags
[] = { kSecServiceItemAttr
};
853 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
854 info
.tag
= info_tags
;
856 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
859 WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status
);
862 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
867 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
868 target_name
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
869 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
871 target_name
[str_len
] = '\0';
872 if (strcmpiW(TargetName
, target_name
))
875 heap_free(target_name
);
878 heap_free(target_name
);
879 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
880 SecKeychainItemDelete(item
);
884 return ERROR_SUCCESS
;
888 return ERROR_NOT_FOUND
;
892 /******************************************************************************
893 * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
895 * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
899 static INT
convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW
*CredentialW
, PCREDENTIALA CredentialA
, DWORD len
)
903 INT needed
= sizeof(CREDENTIALA
);
907 if (CredentialW
->TargetName
)
908 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
909 if (CredentialW
->Comment
)
910 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, NULL
, 0, NULL
, NULL
);
911 needed
+= CredentialW
->CredentialBlobSize
;
912 if (CredentialW
->TargetAlias
)
913 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, NULL
, 0, NULL
, NULL
);
914 if (CredentialW
->UserName
)
915 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, NULL
, 0, NULL
, NULL
);
921 buffer
= (char *)CredentialA
+ sizeof(CREDENTIALA
);
922 len
-= sizeof(CREDENTIALA
);
923 CredentialA
->Flags
= CredentialW
->Flags
;
924 CredentialA
->Type
= CredentialW
->Type
;
926 if (CredentialW
->TargetName
)
928 CredentialA
->TargetName
= buffer
;
929 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, buffer
, len
, NULL
, NULL
);
930 buffer
+= string_len
;
931 needed
+= string_len
;
935 CredentialA
->TargetName
= NULL
;
936 if (CredentialW
->Comment
)
938 CredentialA
->Comment
= buffer
;
939 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, buffer
, len
, NULL
, NULL
);
940 buffer
+= string_len
;
941 needed
+= string_len
;
945 CredentialA
->Comment
= NULL
;
946 CredentialA
->LastWritten
= CredentialW
->LastWritten
;
947 CredentialA
->CredentialBlobSize
= CredentialW
->CredentialBlobSize
;
948 if (CredentialW
->CredentialBlobSize
&& (CredentialW
->CredentialBlobSize
<= len
))
950 CredentialA
->CredentialBlob
=(LPBYTE
)buffer
;
951 memcpy(CredentialA
->CredentialBlob
, CredentialW
->CredentialBlob
,
952 CredentialW
->CredentialBlobSize
);
953 buffer
+= CredentialW
->CredentialBlobSize
;
954 needed
+= CredentialW
->CredentialBlobSize
;
955 len
-= CredentialW
->CredentialBlobSize
;
958 CredentialA
->CredentialBlob
= NULL
;
959 CredentialA
->Persist
= CredentialW
->Persist
;
960 CredentialA
->AttributeCount
= 0;
961 CredentialA
->Attributes
= NULL
; /* FIXME */
962 if (CredentialW
->TargetAlias
)
964 CredentialA
->TargetAlias
= buffer
;
965 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, buffer
, len
, NULL
, NULL
);
966 buffer
+= string_len
;
967 needed
+= string_len
;
971 CredentialA
->TargetAlias
= NULL
;
972 if (CredentialW
->UserName
)
974 CredentialA
->UserName
= buffer
;
975 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, buffer
, len
, NULL
, NULL
);
976 needed
+= string_len
;
979 CredentialA
->UserName
= NULL
;
984 /******************************************************************************
985 * convert_PCREDENTIALA_to_PCREDENTIALW [internal]
987 * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
990 static INT
convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA
*CredentialA
, PCREDENTIALW CredentialW
, INT len
)
994 INT needed
= sizeof(CREDENTIALW
);
998 if (CredentialA
->TargetName
)
999 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, NULL
, 0);
1000 if (CredentialA
->Comment
)
1001 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, NULL
, 0);
1002 needed
+= CredentialA
->CredentialBlobSize
;
1003 if (CredentialA
->TargetAlias
)
1004 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, NULL
, 0);
1005 if (CredentialA
->UserName
)
1006 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, NULL
, 0);
1011 buffer
= (char *)CredentialW
+ sizeof(CREDENTIALW
);
1012 len
-= sizeof(CREDENTIALW
);
1013 CredentialW
->Flags
= CredentialA
->Flags
;
1014 CredentialW
->Type
= CredentialA
->Type
;
1015 if (CredentialA
->TargetName
)
1017 CredentialW
->TargetName
= (LPWSTR
)buffer
;
1018 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, CredentialW
->TargetName
, len
/ sizeof(WCHAR
));
1019 buffer
+= sizeof(WCHAR
) * string_len
;
1020 needed
+= sizeof(WCHAR
) * string_len
;
1021 len
-= sizeof(WCHAR
) * string_len
;
1024 CredentialW
->TargetName
= NULL
;
1025 if (CredentialA
->Comment
)
1027 CredentialW
->Comment
= (LPWSTR
)buffer
;
1028 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, CredentialW
->Comment
, len
/ sizeof(WCHAR
));
1029 buffer
+= sizeof(WCHAR
) * string_len
;
1030 needed
+= sizeof(WCHAR
) * string_len
;
1031 len
-= sizeof(WCHAR
) * string_len
;
1034 CredentialW
->Comment
= NULL
;
1035 CredentialW
->LastWritten
= CredentialA
->LastWritten
;
1036 CredentialW
->CredentialBlobSize
= CredentialA
->CredentialBlobSize
;
1037 if (CredentialA
->CredentialBlobSize
)
1039 CredentialW
->CredentialBlob
=(LPBYTE
)buffer
;
1040 memcpy(CredentialW
->CredentialBlob
, CredentialA
->CredentialBlob
,
1041 CredentialA
->CredentialBlobSize
);
1042 buffer
+= CredentialA
->CredentialBlobSize
;
1043 needed
+= CredentialA
->CredentialBlobSize
;
1044 len
-= CredentialA
->CredentialBlobSize
;
1047 CredentialW
->CredentialBlob
= NULL
;
1048 CredentialW
->Persist
= CredentialA
->Persist
;
1049 CredentialW
->AttributeCount
= 0;
1050 CredentialW
->Attributes
= NULL
; /* FIXME */
1051 if (CredentialA
->TargetAlias
)
1053 CredentialW
->TargetAlias
= (LPWSTR
)buffer
;
1054 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, CredentialW
->TargetAlias
, len
/ sizeof(WCHAR
));
1055 buffer
+= sizeof(WCHAR
) * string_len
;
1056 needed
+= sizeof(WCHAR
) * string_len
;
1057 len
-= sizeof(WCHAR
) * string_len
;
1060 CredentialW
->TargetAlias
= NULL
;
1061 if (CredentialA
->UserName
)
1063 CredentialW
->UserName
= (LPWSTR
)buffer
;
1064 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, CredentialW
->UserName
, len
/ sizeof(WCHAR
));
1065 needed
+= sizeof(WCHAR
) * string_len
;
1068 CredentialW
->UserName
= NULL
;
1073 /******************************************************************************
1074 * CredDeleteA [ADVAPI32.@]
1076 BOOL WINAPI
CredDeleteA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
)
1082 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName
), Type
, Flags
);
1086 SetLastError(ERROR_INVALID_PARAMETER
);
1090 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1091 TargetNameW
= heap_alloc(len
* sizeof(WCHAR
));
1094 SetLastError(ERROR_OUTOFMEMORY
);
1097 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1099 ret
= CredDeleteW(TargetNameW
, Type
, Flags
);
1101 heap_free(TargetNameW
);
1106 /******************************************************************************
1107 * CredDeleteW [ADVAPI32.@]
1109 BOOL WINAPI
CredDeleteW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
)
1115 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName
), Type
, Flags
);
1119 SetLastError(ERROR_INVALID_PARAMETER
);
1123 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1125 FIXME("unhandled type %d\n", Type
);
1126 SetLastError(ERROR_INVALID_PARAMETER
);
1132 FIXME("unhandled flags 0x%x\n", Flags
);
1133 SetLastError(ERROR_INVALID_FLAGS
);
1138 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1140 ret
= mac_delete_credential(TargetName
);
1141 if (ret
== ERROR_SUCCESS
)
1146 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
1147 if (ret
!= ERROR_SUCCESS
)
1149 WARN("couldn't open/create manager key, error %d\n", ret
);
1150 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1154 key_name
= get_key_name_for_target(TargetName
, Type
);
1155 ret
= RegDeleteKeyW(hkeyMgr
, key_name
);
1156 heap_free(key_name
);
1157 RegCloseKey(hkeyMgr
);
1158 if (ret
!= ERROR_SUCCESS
)
1160 SetLastError(ERROR_NOT_FOUND
);
1167 /******************************************************************************
1168 * CredEnumerateA [ADVAPI32.@]
1170 BOOL WINAPI
CredEnumerateA(LPCSTR Filter
, DWORD Flags
, DWORD
*Count
,
1171 PCREDENTIALA
**Credentials
)
1174 PCREDENTIALW
*CredentialsW
;
1180 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter
), Flags
, Count
, Credentials
);
1184 len
= MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, NULL
, 0);
1185 FilterW
= heap_alloc(len
* sizeof(WCHAR
));
1188 SetLastError(ERROR_OUTOFMEMORY
);
1191 MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, FilterW
, len
);
1196 if (!CredEnumerateW(FilterW
, Flags
, Count
, &CredentialsW
))
1203 len
= *Count
* sizeof(PCREDENTIALA
);
1204 for (i
= 0; i
< *Count
; i
++)
1205 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1207 *Credentials
= heap_alloc(len
);
1210 CredFree(CredentialsW
);
1211 SetLastError(ERROR_OUTOFMEMORY
);
1215 buffer
= (char *)&(*Credentials
)[*Count
];
1216 len
-= *Count
* sizeof(PCREDENTIALA
);
1217 for (i
= 0; i
< *Count
; i
++)
1219 (*Credentials
)[i
] = (PCREDENTIALA
)buffer
;
1220 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1225 CredFree(CredentialsW
);
1230 /******************************************************************************
1231 * CredEnumerateW [ADVAPI32.@]
1233 BOOL WINAPI
CredEnumerateW(LPCWSTR Filter
, DWORD Flags
, DWORD
*Count
,
1234 PCREDENTIALW
**Credentials
)
1239 DWORD target_name_len
;
1242 BYTE key_data
[KEY_SIZE
];
1244 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter
), Flags
, Count
, Credentials
);
1248 SetLastError(ERROR_INVALID_FLAGS
);
1252 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1253 if (ret
!= ERROR_SUCCESS
)
1255 WARN("couldn't open/create manager key, error %d\n", ret
);
1256 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1260 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1261 if (ret
!= ERROR_SUCCESS
)
1263 RegCloseKey(hkeyMgr
);
1268 ret
= RegQueryInfoKeyW(hkeyMgr
, NULL
, NULL
, NULL
, NULL
, &target_name_len
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1269 if (ret
!= ERROR_SUCCESS
)
1271 RegCloseKey(hkeyMgr
);
1276 target_name
= heap_alloc((target_name_len
+1)*sizeof(WCHAR
));
1279 RegCloseKey(hkeyMgr
);
1280 SetLastError(ERROR_OUTOFMEMORY
);
1286 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
, target_name_len
,
1287 key_data
, NULL
, NULL
, &len
, Count
);
1289 if (ret
== ERROR_SUCCESS
)
1290 ret
= mac_enumerate_credentials(Filter
, NULL
, NULL
, &len
, Count
);
1292 if (ret
== ERROR_SUCCESS
&& *Count
== 0)
1293 ret
= ERROR_NOT_FOUND
;
1294 if (ret
!= ERROR_SUCCESS
)
1296 heap_free(target_name
);
1297 RegCloseKey(hkeyMgr
);
1301 len
+= *Count
* sizeof(PCREDENTIALW
);
1303 if (ret
== ERROR_SUCCESS
)
1305 buffer
= heap_alloc(len
);
1306 *Credentials
= (PCREDENTIALW
*)buffer
;
1309 buffer
+= *Count
* sizeof(PCREDENTIALW
);
1311 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
,
1312 target_name_len
, key_data
,
1313 *Credentials
, &buffer
, &len
,
1316 if (ret
== ERROR_SUCCESS
)
1317 ret
= mac_enumerate_credentials(Filter
, *Credentials
,
1318 buffer
, &len
, Count
);
1322 ret
= ERROR_OUTOFMEMORY
;
1325 heap_free(target_name
);
1326 RegCloseKey(hkeyMgr
);
1328 if (ret
!= ERROR_SUCCESS
)
1336 /******************************************************************************
1337 * CredFree [ADVAPI32.@]
1339 VOID WINAPI
CredFree(PVOID Buffer
)
1344 /******************************************************************************
1345 * CredReadA [ADVAPI32.@]
1347 BOOL WINAPI
CredReadA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALA
*Credential
)
1350 PCREDENTIALW CredentialW
;
1353 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName
), Type
, Flags
, Credential
);
1357 SetLastError(ERROR_INVALID_PARAMETER
);
1361 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1362 TargetNameW
= heap_alloc(len
* sizeof(WCHAR
));
1365 SetLastError(ERROR_OUTOFMEMORY
);
1368 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1370 if (!CredReadW(TargetNameW
, Type
, Flags
, &CredentialW
))
1372 heap_free(TargetNameW
);
1375 heap_free(TargetNameW
);
1377 len
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, NULL
, 0);
1378 *Credential
= heap_alloc(len
);
1381 SetLastError(ERROR_OUTOFMEMORY
);
1384 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, *Credential
, len
);
1386 CredFree(CredentialW
);
1391 /******************************************************************************
1392 * CredReadW [ADVAPI32.@]
1394 BOOL WINAPI
CredReadW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALW
*Credential
)
1401 BYTE key_data
[KEY_SIZE
];
1403 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName
), Type
, Flags
, Credential
);
1407 SetLastError(ERROR_INVALID_PARAMETER
);
1411 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1413 FIXME("unhandled type %d\n", Type
);
1414 SetLastError(ERROR_INVALID_PARAMETER
);
1420 FIXME("unhandled flags 0x%x\n", Flags
);
1421 SetLastError(ERROR_INVALID_FLAGS
);
1426 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1429 SecKeychainSearchRef search
;
1430 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, NULL
, &search
);
1431 if (status
== noErr
)
1433 SecKeychainItemRef item
;
1434 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
1436 SecKeychainAttributeInfo info
;
1437 SecKeychainAttributeList
*attr_list
;
1438 UInt32 info_tags
[] = { kSecServiceItemAttr
};
1441 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
1442 info
.tag
= info_tags
;
1444 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
1445 len
= sizeof(**Credential
);
1446 if (status
!= noErr
)
1448 WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status
);
1451 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServiceItemAttr
)
1456 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
1457 target_name
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
1458 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
1460 target_name
[str_len
] = '\0';
1461 if (strcmpiW(TargetName
, target_name
))
1464 heap_free(target_name
);
1467 heap_free(target_name
);
1468 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
1469 ret
= mac_read_credential_from_item(item
, TRUE
, NULL
, NULL
, &len
);
1470 if (ret
== ERROR_SUCCESS
)
1472 *Credential
= heap_alloc(len
);
1475 len
= sizeof(**Credential
);
1476 ret
= mac_read_credential_from_item(item
, TRUE
, *Credential
,
1477 (char *)(*Credential
+ 1), &len
);
1480 ret
= ERROR_OUTOFMEMORY
;
1483 if (ret
!= ERROR_SUCCESS
)
1497 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1498 if (ret
!= ERROR_SUCCESS
)
1500 WARN("couldn't open/create manager key, error %d\n", ret
);
1501 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1505 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1506 if (ret
!= ERROR_SUCCESS
)
1508 RegCloseKey(hkeyMgr
);
1513 key_name
= get_key_name_for_target(TargetName
, Type
);
1514 ret
= RegOpenKeyExW(hkeyMgr
, key_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
1515 heap_free(key_name
);
1516 if (ret
!= ERROR_SUCCESS
)
1518 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName
));
1519 SetLastError(ERROR_NOT_FOUND
);
1523 len
= sizeof(**Credential
);
1524 ret
= registry_read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
1525 if (ret
== ERROR_SUCCESS
)
1527 *Credential
= heap_alloc(len
);
1530 len
= sizeof(**Credential
);
1531 ret
= registry_read_credential(hkeyCred
, *Credential
, key_data
,
1532 (char *)(*Credential
+ 1), &len
);
1535 ret
= ERROR_OUTOFMEMORY
;
1538 RegCloseKey(hkeyCred
);
1539 RegCloseKey(hkeyMgr
);
1541 if (ret
!= ERROR_SUCCESS
)
1549 /******************************************************************************
1550 * CredReadDomainCredentialsA [ADVAPI32.@]
1552 BOOL WINAPI
CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation
,
1553 DWORD Flags
, DWORD
*Size
, PCREDENTIALA
**Credentials
)
1555 PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW
;
1558 WCHAR
*buffer
, *end
;
1560 PCREDENTIALW
* CredentialsW
;
1562 TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation
, Flags
, Size
, Credentials
);
1564 /* follow Windows behavior - do not test for NULL, initialize early */
1566 *Credentials
= NULL
;
1568 if (!TargetInformation
)
1570 SetLastError(ERROR_INVALID_PARAMETER
);
1574 len
= sizeof(*TargetInformationW
);
1575 if (TargetInformation
->TargetName
)
1576 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1, NULL
, 0) * sizeof(WCHAR
);
1577 if (TargetInformation
->NetbiosServerName
)
1578 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1579 if (TargetInformation
->DnsServerName
)
1580 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1581 if (TargetInformation
->NetbiosDomainName
)
1582 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1583 if (TargetInformation
->DnsDomainName
)
1584 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1585 if (TargetInformation
->DnsTreeName
)
1586 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1, NULL
, 0) * sizeof(WCHAR
);
1587 if (TargetInformation
->PackageName
)
1588 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1, NULL
, 0) * sizeof(WCHAR
);
1590 TargetInformationW
= heap_alloc(len
);
1591 if (!TargetInformationW
)
1593 SetLastError(ERROR_OUTOFMEMORY
);
1596 buffer
= (WCHAR
*)(TargetInformationW
+ 1);
1597 end
= (WCHAR
*)((char *)TargetInformationW
+ len
);
1599 if (TargetInformation
->TargetName
)
1601 TargetInformationW
->TargetName
= buffer
;
1602 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1,
1603 TargetInformationW
->TargetName
, end
- buffer
);
1605 TargetInformationW
->TargetName
= NULL
;
1607 if (TargetInformation
->NetbiosServerName
)
1609 TargetInformationW
->NetbiosServerName
= buffer
;
1610 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1,
1611 TargetInformationW
->NetbiosServerName
, end
- buffer
);
1613 TargetInformationW
->NetbiosServerName
= NULL
;
1615 if (TargetInformation
->DnsServerName
)
1617 TargetInformationW
->DnsServerName
= buffer
;
1618 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1,
1619 TargetInformationW
->DnsServerName
, end
- buffer
);
1621 TargetInformationW
->DnsServerName
= NULL
;
1623 if (TargetInformation
->NetbiosDomainName
)
1625 TargetInformationW
->NetbiosDomainName
= buffer
;
1626 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1,
1627 TargetInformationW
->NetbiosDomainName
, end
- buffer
);
1629 TargetInformationW
->NetbiosDomainName
= NULL
;
1631 if (TargetInformation
->DnsDomainName
)
1633 TargetInformationW
->DnsDomainName
= buffer
;
1634 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1,
1635 TargetInformationW
->DnsDomainName
, end
- buffer
);
1637 TargetInformationW
->DnsDomainName
= NULL
;
1639 if (TargetInformation
->DnsTreeName
)
1641 TargetInformationW
->DnsTreeName
= buffer
;
1642 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1,
1643 TargetInformationW
->DnsTreeName
, end
- buffer
);
1645 TargetInformationW
->DnsTreeName
= NULL
;
1647 if (TargetInformation
->PackageName
)
1649 TargetInformationW
->PackageName
= buffer
;
1650 MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1,
1651 TargetInformationW
->PackageName
, end
- buffer
);
1653 TargetInformationW
->PackageName
= NULL
;
1655 TargetInformationW
->Flags
= TargetInformation
->Flags
;
1656 TargetInformationW
->CredTypeCount
= TargetInformation
->CredTypeCount
;
1657 TargetInformationW
->CredTypes
= TargetInformation
->CredTypes
;
1659 ret
= CredReadDomainCredentialsW(TargetInformationW
, Flags
, Size
, &CredentialsW
);
1661 heap_free(TargetInformationW
);
1668 len
= *Size
* sizeof(PCREDENTIALA
);
1669 for (i
= 0; i
< *Size
; i
++)
1670 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1672 *Credentials
= heap_alloc(len
);
1675 CredFree(CredentialsW
);
1676 SetLastError(ERROR_OUTOFMEMORY
);
1680 buf
= (char *)&(*Credentials
)[*Size
];
1681 len
-= *Size
* sizeof(PCREDENTIALA
);
1682 for (i
= 0; i
< *Size
; i
++)
1684 (*Credentials
)[i
] = (PCREDENTIALA
)buf
;
1685 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1690 CredFree(CredentialsW
);
1695 /******************************************************************************
1696 * CredReadDomainCredentialsW [ADVAPI32.@]
1698 BOOL WINAPI
CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation
, DWORD Flags
,
1699 DWORD
*Size
, PCREDENTIALW
**Credentials
)
1701 FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation
, Flags
, Size
, Credentials
);
1703 /* follow Windows behavior - do not test for NULL, initialize early */
1705 *Credentials
= NULL
;
1706 if (!TargetInformation
)
1708 SetLastError(ERROR_INVALID_PARAMETER
);
1712 SetLastError(ERROR_NOT_FOUND
);
1716 /******************************************************************************
1717 * CredWriteA [ADVAPI32.@]
1719 BOOL WINAPI
CredWriteA(PCREDENTIALA Credential
, DWORD Flags
)
1723 PCREDENTIALW CredentialW
;
1725 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1727 if (!Credential
|| !Credential
->TargetName
)
1729 SetLastError(ERROR_INVALID_PARAMETER
);
1733 len
= convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, NULL
, 0);
1734 CredentialW
= heap_alloc(len
);
1737 SetLastError(ERROR_OUTOFMEMORY
);
1741 convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, CredentialW
, len
);
1743 ret
= CredWriteW(CredentialW
, Flags
);
1745 heap_free(CredentialW
);
1750 /******************************************************************************
1751 * CredWriteW [ADVAPI32.@]
1753 BOOL WINAPI
CredWriteW(PCREDENTIALW Credential
, DWORD Flags
)
1759 BYTE key_data
[KEY_SIZE
];
1761 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1763 if (!Credential
|| !Credential
->TargetName
)
1765 SetLastError(ERROR_INVALID_PARAMETER
);
1769 if (Flags
& ~CRED_PRESERVE_CREDENTIAL_BLOB
)
1771 FIXME("unhandled flags 0x%x\n", Flags
);
1772 SetLastError(ERROR_INVALID_FLAGS
);
1776 if (Credential
->Type
!= CRED_TYPE_GENERIC
&& Credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1778 FIXME("unhandled type %d\n", Credential
->Type
);
1779 SetLastError(ERROR_INVALID_PARAMETER
);
1783 TRACE("Credential->Flags = 0x%08x\n", Credential
->Flags
);
1784 TRACE("Credential->Type = %u\n", Credential
->Type
);
1785 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential
->TargetName
));
1786 TRACE("Credential->Comment = %s\n", debugstr_w(Credential
->Comment
));
1787 TRACE("Credential->Persist = %u\n", Credential
->Persist
);
1788 TRACE("Credential->TargetAlias = %s\n", debugstr_w(Credential
->TargetAlias
));
1789 TRACE("Credential->UserName = %s\n", debugstr_w(Credential
->UserName
));
1791 if (Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1793 if (!Credential
->UserName
||
1794 (Credential
->Persist
== CRED_PERSIST_ENTERPRISE
&&
1795 (!strchrW(Credential
->UserName
, '\\') && !strchrW(Credential
->UserName
, '@'))))
1797 ERR("bad username %s\n", debugstr_w(Credential
->UserName
));
1798 SetLastError(ERROR_BAD_USERNAME
);
1804 if (!Credential
->AttributeCount
&&
1805 Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
&&
1806 (Credential
->Persist
== CRED_PERSIST_LOCAL_MACHINE
|| Credential
->Persist
== CRED_PERSIST_ENTERPRISE
))
1808 ret
= mac_write_credential(Credential
, Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1809 if (ret
!= ERROR_SUCCESS
)
1818 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1819 if (ret
!= ERROR_SUCCESS
)
1821 WARN("couldn't open/create manager key, error %d\n", ret
);
1822 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1826 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1827 if (ret
!= ERROR_SUCCESS
)
1829 RegCloseKey(hkeyMgr
);
1834 key_name
= get_key_name_for_target(Credential
->TargetName
, Credential
->Type
);
1835 ret
= RegCreateKeyExW(hkeyMgr
, key_name
, 0, NULL
,
1836 Credential
->Persist
== CRED_PERSIST_SESSION
? REG_OPTION_VOLATILE
: REG_OPTION_NON_VOLATILE
,
1837 KEY_READ
|KEY_WRITE
, NULL
, &hkeyCred
, NULL
);
1838 heap_free(key_name
);
1839 if (ret
!= ERROR_SUCCESS
)
1841 TRACE("credentials for target name %s not found\n",
1842 debugstr_w(Credential
->TargetName
));
1843 SetLastError(ERROR_NOT_FOUND
);
1847 ret
= registry_write_credential(hkeyCred
, Credential
, key_data
,
1848 Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1850 RegCloseKey(hkeyCred
);
1851 RegCloseKey(hkeyMgr
);
1853 if (ret
!= ERROR_SUCCESS
)
1861 /******************************************************************************
1862 * CredGetSessionTypes [ADVAPI32.@]
1864 WINADVAPI BOOL WINAPI
CredGetSessionTypes(DWORD persistCount
, LPDWORD persists
)
1866 TRACE("(%u, %p)\n", persistCount
, persists
);
1868 memset(persists
, CRED_PERSIST_NONE
, persistCount
*sizeof(*persists
));
1869 if (CRED_TYPE_GENERIC
< persistCount
)
1871 persists
[CRED_TYPE_GENERIC
] = CRED_PERSIST_ENTERPRISE
;
1873 if (CRED_TYPE_DOMAIN_PASSWORD
< persistCount
)
1875 persists
[CRED_TYPE_DOMAIN_PASSWORD
] = CRED_PERSIST_ENTERPRISE
;
1881 /******************************************************************************
1882 * CredMarshalCredentialA [ADVAPI32.@]
1884 BOOL WINAPI
CredMarshalCredentialA( CRED_MARSHAL_TYPE type
, PVOID cred
, LPSTR
*out
)
1889 TRACE("%u, %p, %p\n", type
, cred
, out
);
1891 if ((ret
= CredMarshalCredentialW( type
, cred
, &outW
)))
1893 int len
= WideCharToMultiByte( CP_ACP
, 0, outW
, -1, NULL
, 0, NULL
, NULL
);
1894 if (!(*out
= heap_alloc( len
)))
1899 WideCharToMultiByte( CP_ACP
, 0, outW
, -1, *out
, len
, NULL
, NULL
);
1905 static UINT
cred_encode( const char *bin
, unsigned int len
, WCHAR
*cred
)
1907 static const char enc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#-";
1912 cred
[n
++] = enc
[bin
[0] & 0x3f];
1913 x
= (bin
[0] & 0xc0) >> 6;
1919 cred
[n
++] = enc
[((bin
[1] & 0xf) << 2) | x
];
1920 x
= (bin
[1] & 0xf0) >> 4;
1926 cred
[n
++] = enc
[((bin
[2] & 0x3) << 4) | x
];
1927 cred
[n
++] = enc
[(bin
[2] & 0xfc) >> 2];
1934 /******************************************************************************
1935 * CredMarshalCredentialW [ADVAPI32.@]
1937 BOOL WINAPI
CredMarshalCredentialW( CRED_MARSHAL_TYPE type
, PVOID cred
, LPWSTR
*out
)
1939 CERT_CREDENTIAL_INFO
*cert
= cred
;
1940 USERNAME_TARGET_CREDENTIAL_INFO
*target
= cred
;
1944 TRACE("%u, %p, %p\n", type
, cred
, out
);
1946 if (!cred
|| (type
== CertCredential
&& cert
->cbSize
< sizeof(*cert
)) ||
1947 (type
!= CertCredential
&& type
!= UsernameTargetCredential
&& type
!= BinaryBlobCredential
) ||
1948 (type
== UsernameTargetCredential
&& (!target
->UserName
|| !target
->UserName
[0])))
1950 SetLastError( ERROR_INVALID_PARAMETER
);
1955 case CertCredential
:
1957 size
= (sizeof(cert
->rgbHashOfCert
) + 2) * 4 / 3;
1958 if (!(p
= heap_alloc( (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1962 len
= cred_encode( (const char *)cert
->rgbHashOfCert
, sizeof(cert
->rgbHashOfCert
), p
+ 3 );
1966 case UsernameTargetCredential
:
1968 len
= strlenW( target
->UserName
);
1969 size
= (sizeof(DWORD
) + len
* sizeof(WCHAR
) + 2) * 4 / 3;
1970 if (!(p
= heap_alloc( (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1974 size
= len
* sizeof(WCHAR
);
1975 len
= cred_encode( (const char *)&size
, sizeof(DWORD
), p
+ 3 );
1976 len
+= cred_encode( (const char *)target
->UserName
, size
, p
+ 3 + len
);
1980 case BinaryBlobCredential
:
1981 FIXME("BinaryBlobCredential not implemented\n");
1990 /******************************************************************************
1991 * CredUnmarshalCredentialA [ADVAPI32.@]
1993 BOOL WINAPI
CredUnmarshalCredentialA( LPCSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
1996 WCHAR
*credW
= NULL
;
1998 TRACE("%s, %p, %p\n", debugstr_a(cred
), type
, out
);
2002 int len
= MultiByteToWideChar( CP_ACP
, 0, cred
, -1, NULL
, 0 );
2003 if (!(credW
= heap_alloc( len
* sizeof(WCHAR
) ))) return FALSE
;
2004 MultiByteToWideChar( CP_ACP
, 0, cred
, -1, credW
, len
);
2006 ret
= CredUnmarshalCredentialW( credW
, type
, out
);
2011 static inline char char_decode( WCHAR c
)
2013 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
2014 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
2015 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
2016 if (c
== '#') return 62;
2017 if (c
== '-') return 63;
2021 static BOOL
cred_decode( const WCHAR
*cred
, unsigned int len
, char *buf
)
2024 char c0
, c1
, c2
, c3
;
2025 const WCHAR
*p
= cred
;
2029 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2030 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2031 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2032 if ((c3
= char_decode( p
[3] )) > 63) return FALSE
;
2034 buf
[i
+ 0] = (c1
<< 6) | c0
;
2035 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2036 buf
[i
+ 2] = (c3
<< 2) | (c2
>> 4);
2043 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2044 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2045 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2047 buf
[i
+ 0] = (c1
<< 6) | c0
;
2048 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2052 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2053 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2055 buf
[i
+ 0] = (c1
<< 6) | c0
;
2064 /******************************************************************************
2065 * CredUnmarshalCredentialW [ADVAPI32.@]
2067 BOOL WINAPI
CredUnmarshalCredentialW( LPCWSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
2069 unsigned int len
, buflen
;
2071 TRACE("%s, %p, %p\n", debugstr_w(cred
), type
, out
);
2073 if (!cred
|| cred
[0] != '@' || cred
[1] != '@' ||
2074 char_decode( cred
[2] ) > 63)
2076 SetLastError( ERROR_INVALID_PARAMETER
);
2079 len
= strlenW( cred
+ 3 );
2080 *type
= char_decode( cred
[2] );
2083 case CertCredential
:
2085 char hash
[CERT_HASH_LENGTH
];
2086 CERT_CREDENTIAL_INFO
*cert
;
2088 if (len
!= 27 || !cred_decode( cred
+ 3, len
, hash
))
2090 SetLastError( ERROR_INVALID_PARAMETER
);
2093 if (!(cert
= heap_alloc( sizeof(*cert
) ))) return FALSE
;
2094 memcpy( cert
->rgbHashOfCert
, hash
, sizeof(cert
->rgbHashOfCert
) );
2095 cert
->cbSize
= sizeof(*cert
);
2099 case UsernameTargetCredential
:
2101 USERNAME_TARGET_CREDENTIAL_INFO
*target
;
2104 if (len
< 9 || !cred_decode( cred
+ 3, 6, (char *)&size
) ||
2105 size
% sizeof(WCHAR
) || len
- 6 != (size
* 4 + 2) / 3)
2107 SetLastError( ERROR_INVALID_PARAMETER
);
2110 buflen
= sizeof(*target
) + size
+ sizeof(WCHAR
);
2111 if (!(target
= heap_alloc( buflen
))) return FALSE
;
2112 if (!cred_decode( cred
+ 9, len
- 6, (char *)(target
+ 1) ))
2114 heap_free( target
);
2117 target
->UserName
= (WCHAR
*)(target
+ 1);
2118 target
->UserName
[size
/ sizeof(WCHAR
)] = 0;
2122 case BinaryBlobCredential
:
2123 FIXME("BinaryBlobCredential not implemented\n");
2126 WARN("unhandled type %u\n", *type
);
2127 SetLastError( ERROR_INVALID_PARAMETER
);
2133 /******************************************************************************
2134 * CredIsMarshaledCredentialW [ADVAPI32.@]
2136 * Check, if the name parameter is a marshaled credential, hash or binary blob
2139 * name the name to check
2142 * TRUE: the name parameter is a marshaled credential, hash or binary blob
2143 * FALSE: the name is a plain username
2145 BOOL WINAPI
CredIsMarshaledCredentialW(LPCWSTR name
)
2147 TRACE("(%s)\n", debugstr_w(name
));
2149 if (name
&& name
[0] == '@' && name
[1] == '@' && name
[2] > 'A' && name
[3])
2151 char hash
[CERT_HASH_LENGTH
];
2152 int len
= strlenW(name
+ 3 );
2155 if ((name
[2] - 'A') == CertCredential
&& (len
== 27) && cred_decode(name
+ 3, len
, hash
))
2158 if (((name
[2] - 'A') == UsernameTargetCredential
) &&
2159 (len
>= 9) && cred_decode(name
+ 3, 6, (char *)&size
) && size
)
2162 if ((name
[2] - 'A') == BinaryBlobCredential
)
2163 FIXME("BinaryBlobCredential not checked\n");
2165 if ((name
[2] - 'A') > BinaryBlobCredential
)
2166 TRACE("unknown type: %d\n", (name
[2] - 'A'));
2169 SetLastError(ERROR_INVALID_PARAMETER
);
2173 /******************************************************************************
2174 * CredIsMarshaledCredentialA [ADVAPI32.@]
2176 * See CredIsMarshaledCredentialW
2179 BOOL WINAPI
CredIsMarshaledCredentialA(LPCSTR name
)
2181 LPWSTR nameW
= NULL
;
2185 TRACE("(%s)\n", debugstr_a(name
));
2189 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0);
2190 nameW
= heap_alloc(len
* sizeof(WCHAR
));
2191 MultiByteToWideChar(CP_ACP
, 0, name
, -1, nameW
, len
);
2194 res
= CredIsMarshaledCredentialW(nameW
);