2 * Credential Management APIs
4 * Copyright 2007 Robert Shearman for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 # include <Security/SecKeychain.h>
26 # include <Security/SecKeychainItem.h>
27 # include <Security/SecKeychainSearch.h>
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(cred
);
43 /* the size of the ARC4 key used to encrypt the password data */
46 static const WCHAR wszCredentialManagerKey
[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
47 'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0};
48 static const WCHAR wszEncryptionKeyValue
[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0};
50 static const WCHAR wszFlagsValue
[] = {'F','l','a','g','s',0};
51 static const WCHAR wszTypeValue
[] = {'T','y','p','e',0};
52 static const WCHAR wszCommentValue
[] = {'C','o','m','m','e','n','t',0};
53 static const WCHAR wszLastWrittenValue
[] = {'L','a','s','t','W','r','i','t','t','e','n',0};
54 static const WCHAR wszPersistValue
[] = {'P','e','r','s','i','s','t',0};
55 static const WCHAR wszTargetAliasValue
[] = {'T','a','r','g','e','t','A','l','i','a','s',0};
56 static const WCHAR wszUserNameValue
[] = {'U','s','e','r','N','a','m','e',0};
57 static const WCHAR wszPasswordValue
[] = {'P','a','s','s','w','o','r','d',0};
59 static DWORD
read_credential_blob(HKEY hkey
, const BYTE key_data
[KEY_SIZE
],
60 LPBYTE credential_blob
,
61 DWORD
*credential_blob_size
)
66 *credential_blob_size
= 0;
67 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, NULL
, credential_blob_size
);
68 if (ret
!= ERROR_SUCCESS
)
70 else if (type
!= REG_BINARY
)
71 return ERROR_REGISTRY_CORRUPT
;
77 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, credential_blob
,
78 credential_blob_size
);
79 if (ret
!= ERROR_SUCCESS
)
81 else if (type
!= REG_BINARY
)
82 return ERROR_REGISTRY_CORRUPT
;
84 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
85 key
.Buffer
= (unsigned char *)key_data
;
87 data
.Length
= data
.MaximumLength
= *credential_blob_size
;
88 data
.Buffer
= credential_blob
;
89 SystemFunction032(&data
, &key
);
94 static DWORD
registry_read_credential(HKEY hkey
, PCREDENTIALW credential
,
95 const BYTE key_data
[KEY_SIZE
],
96 char *buffer
, DWORD
*len
)
102 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, NULL
, &count
);
103 if (ret
!= ERROR_SUCCESS
)
105 else if (type
!= REG_SZ
)
106 return ERROR_REGISTRY_CORRUPT
;
110 credential
->TargetName
= (LPWSTR
)buffer
;
111 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, (LPVOID
)credential
->TargetName
,
113 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) return ret
;
117 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, NULL
, &count
);
118 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
120 else if (type
!= REG_SZ
)
121 return ERROR_REGISTRY_CORRUPT
;
125 credential
->Comment
= (LPWSTR
)buffer
;
126 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, (LPVOID
)credential
->Comment
,
128 if (ret
== ERROR_FILE_NOT_FOUND
)
129 credential
->Comment
= NULL
;
130 else if (ret
!= ERROR_SUCCESS
)
132 else if (type
!= REG_SZ
)
133 return ERROR_REGISTRY_CORRUPT
;
138 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, NULL
, &count
);
139 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
141 else if (type
!= REG_SZ
)
142 return ERROR_REGISTRY_CORRUPT
;
146 credential
->TargetAlias
= (LPWSTR
)buffer
;
147 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, (LPVOID
)credential
->TargetAlias
,
149 if (ret
== ERROR_FILE_NOT_FOUND
)
150 credential
->TargetAlias
= NULL
;
151 else if (ret
!= ERROR_SUCCESS
)
153 else if (type
!= REG_SZ
)
154 return ERROR_REGISTRY_CORRUPT
;
159 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, NULL
, &count
);
160 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
162 else if (type
!= REG_SZ
)
163 return ERROR_REGISTRY_CORRUPT
;
167 credential
->UserName
= (LPWSTR
)buffer
;
168 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, (LPVOID
)credential
->UserName
,
170 if (ret
== ERROR_FILE_NOT_FOUND
)
171 credential
->UserName
= NULL
;
172 else if (ret
!= ERROR_SUCCESS
)
174 else if (type
!= REG_SZ
)
175 return ERROR_REGISTRY_CORRUPT
;
180 ret
= read_credential_blob(hkey
, key_data
, NULL
, &count
);
181 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
186 credential
->CredentialBlob
= (LPBYTE
)buffer
;
187 ret
= read_credential_blob(hkey
, key_data
, credential
->CredentialBlob
, &count
);
188 if (ret
== ERROR_FILE_NOT_FOUND
)
189 credential
->CredentialBlob
= NULL
;
190 else if (ret
!= ERROR_SUCCESS
)
192 credential
->CredentialBlobSize
= count
;
195 /* FIXME: Attributes */
198 credential
->AttributeCount
= 0;
199 credential
->Attributes
= NULL
;
202 if (!credential
) return ERROR_SUCCESS
;
204 count
= sizeof(credential
->Flags
);
205 ret
= RegQueryValueExW(hkey
, wszFlagsValue
, NULL
, &type
, (LPVOID
)&credential
->Flags
,
207 if (ret
!= ERROR_SUCCESS
)
209 else if (type
!= REG_DWORD
)
210 return ERROR_REGISTRY_CORRUPT
;
211 count
= sizeof(credential
->Type
);
212 ret
= RegQueryValueExW(hkey
, wszTypeValue
, NULL
, &type
, (LPVOID
)&credential
->Type
,
214 if (ret
!= ERROR_SUCCESS
)
216 else if (type
!= REG_DWORD
)
217 return ERROR_REGISTRY_CORRUPT
;
219 count
= sizeof(credential
->LastWritten
);
220 ret
= RegQueryValueExW(hkey
, wszLastWrittenValue
, NULL
, &type
, (LPVOID
)&credential
->LastWritten
,
222 if (ret
!= ERROR_SUCCESS
)
224 else if (type
!= REG_BINARY
)
225 return ERROR_REGISTRY_CORRUPT
;
226 count
= sizeof(credential
->Persist
);
227 ret
= RegQueryValueExW(hkey
, wszPersistValue
, NULL
, &type
, (LPVOID
)&credential
->Persist
,
229 if (ret
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
230 return ERROR_REGISTRY_CORRUPT
;
235 static DWORD
mac_read_credential_from_item(SecKeychainItemRef item
, BOOL require_password
,
236 PCREDENTIALW credential
, char *buffer
,
241 UInt32 cred_blob_len
;
243 LPWSTR domain
= NULL
;
245 BOOL user_name_present
= FALSE
;
246 SecKeychainAttributeInfo info
;
247 SecKeychainAttributeList
*attr_list
;
248 UInt32 info_tags
[] = { kSecServerItemAttr
, kSecSecurityDomainItemAttr
, kSecAccountItemAttr
,
249 kSecCommentItemAttr
, kSecCreationDateItemAttr
};
250 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
251 info
.tag
= info_tags
;
253 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, &cred_blob
);
254 if (status
== errSecAuthFailed
&& !require_password
)
258 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, &cred_blob_len
, NULL
);
262 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
263 return ERROR_NOT_FOUND
;
266 for (i
= 0; i
< attr_list
->count
; i
++)
267 if (attr_list
->attr
[i
].tag
== kSecAccountItemAttr
&& attr_list
->attr
[i
].data
)
269 user_name_present
= TRUE
;
272 if (!user_name_present
)
274 WARN("no kSecAccountItemAttr for item\n");
275 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
276 return ERROR_NOT_FOUND
;
281 credential
->Flags
= 0;
282 credential
->Type
= CRED_TYPE_DOMAIN_PASSWORD
;
283 credential
->TargetName
= NULL
;
284 credential
->Comment
= NULL
;
285 memset(&credential
->LastWritten
, 0, sizeof(credential
->LastWritten
));
286 credential
->CredentialBlobSize
= 0;
287 credential
->CredentialBlob
= NULL
;
288 credential
->Persist
= CRED_PERSIST_LOCAL_MACHINE
;
289 credential
->AttributeCount
= 0;
290 credential
->Attributes
= NULL
;
291 credential
->TargetAlias
= NULL
;
292 credential
->UserName
= NULL
;
294 for (i
= 0; i
< attr_list
->count
; i
++)
296 switch (attr_list
->attr
[i
].tag
)
298 case kSecServerItemAttr
:
299 TRACE("kSecServerItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
300 (char *)attr_list
->attr
[i
].data
);
301 if (!attr_list
->attr
[i
].data
) continue;
305 credential
->TargetName
= (LPWSTR
)buffer
;
306 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
307 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
308 credential
->TargetName
[str_len
] = '\0';
309 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
310 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
315 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
316 attr_list
->attr
[i
].length
, NULL
, 0);
317 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
320 case kSecAccountItemAttr
:
323 TRACE("kSecAccountItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
324 (char *)attr_list
->attr
[i
].data
);
325 if (!attr_list
->attr
[i
].data
) continue;
326 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
327 attr_list
->attr
[i
].length
, NULL
, 0);
328 user
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
329 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
330 attr_list
->attr
[i
].length
, user
, str_len
);
331 user
[str_len
] = '\0';
334 case kSecCommentItemAttr
:
335 TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
336 (char *)attr_list
->attr
[i
].data
);
337 if (!attr_list
->attr
[i
].data
) continue;
341 credential
->Comment
= (LPWSTR
)buffer
;
342 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
343 attr_list
->attr
[i
].length
, (LPWSTR
)buffer
, 0xffff);
344 credential
->Comment
[str_len
] = '\0';
345 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
346 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
351 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
352 attr_list
->attr
[i
].length
, NULL
, 0);
353 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
356 case kSecSecurityDomainItemAttr
:
359 TRACE("kSecSecurityDomainItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
360 (char *)attr_list
->attr
[i
].data
);
361 if (!attr_list
->attr
[i
].data
) continue;
362 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
363 attr_list
->attr
[i
].length
, NULL
, 0);
364 domain
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
365 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[i
].data
,
366 attr_list
->attr
[i
].length
, domain
, str_len
);
367 domain
[str_len
] = '\0';
370 case kSecCreationDateItemAttr
:
371 TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list
->attr
[i
].length
,
372 (char *)attr_list
->attr
[i
].data
);
375 LARGE_INTEGER win_time
;
378 memset(&tm
, 0, sizeof(tm
));
379 strptime(attr_list
->attr
[i
].data
, "%Y%m%d%H%M%SZ", &tm
);
381 RtlSecondsSince1970ToTime(time
, &win_time
);
382 credential
->LastWritten
.dwLowDateTime
= win_time
.u
.LowPart
;
383 credential
->LastWritten
.dwHighDateTime
= win_time
.u
.HighPart
;
393 credential
->UserName
= (LPWSTR
)buffer
;
396 str_len
= strlenW(domain
);
397 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
400 memcpy(credential
->UserName
, domain
, str_len
* sizeof(WCHAR
));
401 /* FIXME: figure out when to use an '@' */
402 credential
->UserName
[str_len
] = '\\';
403 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
406 str_len
= strlenW(user
);
407 *len
+= (str_len
+ 1) * sizeof(WCHAR
);
410 memcpy(buffer
, user
, (str_len
+ 1) * sizeof(WCHAR
));
411 buffer
+= (str_len
+ 1) * sizeof(WCHAR
);
412 TRACE("UserName = %s\n", debugstr_w(credential
->UserName
));
415 HeapFree(GetProcessHeap(), 0, user
);
416 HeapFree(GetProcessHeap(), 0, domain
);
423 credential
->CredentialBlob
= (BYTE
*)buffer
;
424 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
425 (LPWSTR
)buffer
, 0xffff);
426 credential
->CredentialBlobSize
= str_len
* sizeof(WCHAR
);
427 *len
+= str_len
* sizeof(WCHAR
);
432 str_len
= MultiByteToWideChar(CP_UTF8
, 0, cred_blob
, cred_blob_len
,
434 *len
+= str_len
* sizeof(WCHAR
);
437 SecKeychainItemFreeAttributesAndData(attr_list
, cred_blob
);
438 return ERROR_SUCCESS
;
442 static DWORD
write_credential_blob(HKEY hkey
, LPCWSTR target_name
, DWORD type
,
443 const BYTE key_data
[KEY_SIZE
],
444 const BYTE
*credential_blob
, DWORD credential_blob_size
)
446 LPBYTE encrypted_credential_blob
;
451 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
452 key
.Buffer
= (unsigned char *)key_data
;
454 encrypted_credential_blob
= HeapAlloc(GetProcessHeap(), 0, credential_blob_size
);
455 if (!encrypted_credential_blob
) return ERROR_OUTOFMEMORY
;
457 memcpy(encrypted_credential_blob
, credential_blob
, credential_blob_size
);
458 data
.Length
= data
.MaximumLength
= credential_blob_size
;
459 data
.Buffer
= encrypted_credential_blob
;
460 SystemFunction032(&data
, &key
);
462 ret
= RegSetValueExW(hkey
, wszPasswordValue
, 0, REG_BINARY
, encrypted_credential_blob
, credential_blob_size
);
463 HeapFree(GetProcessHeap(), 0, encrypted_credential_blob
);
468 static DWORD
registry_write_credential(HKEY hkey
, const CREDENTIALW
*credential
,
469 const BYTE key_data
[KEY_SIZE
], BOOL preserve_blob
)
472 FILETIME LastWritten
;
474 GetSystemTimeAsFileTime(&LastWritten
);
476 ret
= RegSetValueExW(hkey
, wszFlagsValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Flags
,
477 sizeof(credential
->Flags
));
478 if (ret
!= ERROR_SUCCESS
) return ret
;
479 ret
= RegSetValueExW(hkey
, wszTypeValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Type
,
480 sizeof(credential
->Type
));
481 if (ret
!= ERROR_SUCCESS
) return ret
;
482 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (LPVOID
)credential
->TargetName
,
483 sizeof(WCHAR
)*(strlenW(credential
->TargetName
)+1));
484 if (ret
!= ERROR_SUCCESS
) return ret
;
485 if (credential
->Comment
)
487 ret
= RegSetValueExW(hkey
, wszCommentValue
, 0, REG_SZ
, (LPVOID
)credential
->Comment
,
488 sizeof(WCHAR
)*(strlenW(credential
->Comment
)+1));
489 if (ret
!= ERROR_SUCCESS
) return ret
;
491 ret
= RegSetValueExW(hkey
, wszLastWrittenValue
, 0, REG_BINARY
, (LPVOID
)&LastWritten
,
492 sizeof(LastWritten
));
493 if (ret
!= ERROR_SUCCESS
) return ret
;
494 ret
= RegSetValueExW(hkey
, wszPersistValue
, 0, REG_DWORD
, (const BYTE
*)&credential
->Persist
,
495 sizeof(credential
->Persist
));
496 if (ret
!= ERROR_SUCCESS
) return ret
;
497 /* FIXME: Attributes */
498 if (credential
->TargetAlias
)
500 ret
= RegSetValueExW(hkey
, wszTargetAliasValue
, 0, REG_SZ
, (LPVOID
)credential
->TargetAlias
,
501 sizeof(WCHAR
)*(strlenW(credential
->TargetAlias
)+1));
502 if (ret
!= ERROR_SUCCESS
) return ret
;
504 if (credential
->UserName
)
506 ret
= RegSetValueExW(hkey
, wszUserNameValue
, 0, REG_SZ
, (LPVOID
)credential
->UserName
,
507 sizeof(WCHAR
)*(strlenW(credential
->UserName
)+1));
508 if (ret
!= ERROR_SUCCESS
) return ret
;
512 ret
= write_credential_blob(hkey
, credential
->TargetName
, credential
->Type
,
513 key_data
, credential
->CredentialBlob
,
514 credential
->CredentialBlobSize
);
520 static DWORD
mac_write_credential(const CREDENTIALW
*credential
, BOOL preserve_blob
)
523 SecKeychainItemRef keychain_item
;
529 UInt32 domainlen
= 0;
533 SecKeychainAttribute attrs
[1];
534 SecKeychainAttributeList attr_list
;
536 if (credential
->Flags
)
537 FIXME("Flags 0x%x not written\n", credential
->Flags
);
538 if (credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
539 FIXME("credential type of %d not supported\n", credential
->Type
);
540 if (credential
->Persist
!= CRED_PERSIST_LOCAL_MACHINE
)
541 FIXME("persist value of %d not supported\n", credential
->Persist
);
542 if (credential
->AttributeCount
)
543 FIXME("custom attributes not supported\n");
545 p
= strchrW(credential
->UserName
, '\\');
548 domainlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
,
549 p
- credential
->UserName
, NULL
, 0, NULL
, NULL
);
550 domain
= HeapAlloc(GetProcessHeap(), 0, (domainlen
+ 1) * sizeof(*domain
));
551 WideCharToMultiByte(CP_UTF8
, 0, credential
->UserName
, p
- credential
->UserName
,
552 domain
, domainlen
, NULL
, NULL
);
553 domain
[domainlen
] = '\0';
557 p
= credential
->UserName
;
558 userlen
= WideCharToMultiByte(CP_UTF8
, 0, p
, -1, NULL
, 0, NULL
, NULL
);
559 username
= HeapAlloc(GetProcessHeap(), 0, userlen
* sizeof(*username
));
560 WideCharToMultiByte(CP_UTF8
, 0, p
, -1, username
, userlen
, NULL
, NULL
);
562 serverlen
= WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
563 servername
= HeapAlloc(GetProcessHeap(), 0, serverlen
* sizeof(*servername
));
564 WideCharToMultiByte(CP_UTF8
, 0, credential
->TargetName
, -1, servername
, serverlen
, NULL
, NULL
);
565 pwlen
= WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
566 credential
->CredentialBlobSize
/ sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
567 password
= HeapAlloc(GetProcessHeap(), 0, pwlen
* sizeof(*domain
));
568 WideCharToMultiByte(CP_UTF8
, 0, (LPCWSTR
)credential
->CredentialBlob
,
569 credential
->CredentialBlobSize
/ sizeof(WCHAR
), password
, pwlen
, NULL
, NULL
);
571 TRACE("adding server %s, domain %s, username %s using Keychain\n", servername
, domain
, username
);
572 status
= SecKeychainAddInternetPassword(NULL
, strlen(servername
), servername
,
573 strlen(domain
), domain
, strlen(username
),
574 username
, 0, NULL
, 0,
576 kSecAuthenticationTypeDefault
,
577 strlen(password
), password
, &keychain_item
);
579 ERR("SecKeychainAddInternetPassword returned %ld\n", status
);
580 if (status
== errSecDuplicateItem
)
582 SecKeychainItemRef keychain_item
;
584 status
= SecKeychainFindInternetPassword(NULL
, strlen(servername
), servername
,
585 strlen(domain
), domain
,
586 strlen(username
), username
,
587 0, NULL
/* any path */, 0,
588 0 /* any protocol */,
589 0 /* any authentication type */,
590 0, NULL
, &keychain_item
);
592 ERR("SecKeychainFindInternetPassword returned %ld\n", status
);
594 HeapFree(GetProcessHeap(), 0, domain
);
595 HeapFree(GetProcessHeap(), 0, username
);
596 HeapFree(GetProcessHeap(), 0, servername
);
599 HeapFree(GetProcessHeap(), 0, password
);
600 return ERROR_GEN_FAILURE
;
602 if (credential
->Comment
)
605 attr_list
.attr
= attrs
;
606 attrs
[0].tag
= kSecCommentItemAttr
;
607 attrs
[0].length
= WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, NULL
, 0, NULL
, NULL
);
608 if (attrs
[0].length
) attrs
[0].length
--;
609 attrs
[0].data
= HeapAlloc(GetProcessHeap(), 0, attrs
[0].length
);
610 WideCharToMultiByte(CP_UTF8
, 0, credential
->Comment
, -1, attrs
[0].data
, attrs
[0].length
, NULL
, NULL
);
615 attr_list
.attr
= NULL
;
617 status
= SecKeychainItemModifyAttributesAndData(keychain_item
, &attr_list
,
618 preserve_blob
? 0 : strlen(password
),
619 preserve_blob
? NULL
: password
);
620 if (credential
->Comment
)
621 HeapFree(GetProcessHeap(), 0, attrs
[0].data
);
622 HeapFree(GetProcessHeap(), 0, password
);
623 /* FIXME: set TargetAlias attribute */
624 CFRelease(keychain_item
);
626 return ERROR_GEN_FAILURE
;
627 return ERROR_SUCCESS
;
631 static DWORD
open_cred_mgr_key(HKEY
*hkey
, BOOL open_for_write
)
633 return RegCreateKeyExW(HKEY_CURRENT_USER
, wszCredentialManagerKey
, 0,
634 NULL
, REG_OPTION_NON_VOLATILE
,
635 KEY_READ
| (open_for_write
? KEY_WRITE
: 0), NULL
, hkey
, NULL
);
638 static DWORD
get_cred_mgr_encryption_key(HKEY hkeyMgr
, BYTE key_data
[KEY_SIZE
])
640 static const BYTE my_key_data
[KEY_SIZE
] = { 0 };
648 memcpy(key_data
, my_key_data
, KEY_SIZE
);
651 ret
= RegQueryValueExW(hkeyMgr
, wszEncryptionKeyValue
, NULL
, &type
, key_data
,
653 if (ret
== ERROR_SUCCESS
)
655 if (type
!= REG_BINARY
)
656 return ERROR_REGISTRY_CORRUPT
;
658 return ERROR_SUCCESS
;
660 if (ret
!= ERROR_FILE_NOT_FOUND
)
663 GetSystemTimeAsFileTime(&ft
);
664 seed
= ft
.dwLowDateTime
;
665 value
= RtlUniform(&seed
);
666 *(DWORD
*)key_data
= value
;
667 seed
= ft
.dwHighDateTime
;
668 value
= RtlUniform(&seed
);
669 *(DWORD
*)(key_data
+ 4) = value
;
671 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
673 if (ret
== ERROR_ACCESS_DENIED
)
675 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
676 if (ret
== ERROR_SUCCESS
)
678 ret
= RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
680 RegCloseKey(hkeyMgr
);
686 static LPWSTR
get_key_name_for_target(LPCWSTR target_name
, DWORD type
)
688 static const WCHAR wszGenericPrefix
[] = {'G','e','n','e','r','i','c',':',' ',0};
689 static const WCHAR wszDomPasswdPrefix
[] = {'D','o','m','P','a','s','s','w','d',':',' ',0};
691 LPCWSTR prefix
= NULL
;
694 len
= strlenW(target_name
);
695 if (type
== CRED_TYPE_GENERIC
)
697 prefix
= wszGenericPrefix
;
698 len
+= sizeof(wszGenericPrefix
)/sizeof(wszGenericPrefix
[0]);
702 prefix
= wszDomPasswdPrefix
;
703 len
+= sizeof(wszDomPasswdPrefix
)/sizeof(wszDomPasswdPrefix
[0]);
706 key_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
707 if (!key_name
) return NULL
;
709 strcpyW(key_name
, prefix
);
710 strcatW(key_name
, target_name
);
712 for (p
= key_name
; *p
; p
++)
713 if (*p
== '\\') *p
= '_';
718 static BOOL
credential_matches_filter(HKEY hkeyCred
, LPCWSTR filter
)
726 if (!filter
) return TRUE
;
728 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, NULL
, &count
);
729 if (ret
!= ERROR_SUCCESS
)
731 else if (type
!= REG_SZ
)
734 target_name
= HeapAlloc(GetProcessHeap(), 0, count
);
737 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, (LPVOID
)target_name
, &count
);
738 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
740 HeapFree(GetProcessHeap(), 0, target_name
);
744 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
),
745 debugstr_w(target_name
));
747 p
= strchrW(filter
, '*');
748 ret
= CompareStringW(GetThreadLocale(), 0, filter
,
749 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
750 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
752 HeapFree(GetProcessHeap(), 0, target_name
);
756 static DWORD
registry_enumerate_credentials(HKEY hkeyMgr
, LPCWSTR filter
,
758 DWORD target_name_len
, const BYTE key_data
[KEY_SIZE
],
759 PCREDENTIALW
*credentials
, char **buffer
,
760 DWORD
*len
, DWORD
*count
)
767 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
768 if (ret
== ERROR_NO_MORE_ITEMS
)
773 else if (ret
!= ERROR_SUCCESS
)
775 TRACE("target_name = %s\n", debugstr_w(target_name
));
776 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
777 if (ret
!= ERROR_SUCCESS
)
779 if (!credential_matches_filter(hkeyCred
, filter
))
781 RegCloseKey(hkeyCred
);
786 *len
= sizeof(CREDENTIALW
);
787 credentials
[*count
] = (PCREDENTIALW
)*buffer
;
790 *len
+= sizeof(CREDENTIALW
);
791 ret
= registry_read_credential(hkeyCred
, buffer
? credentials
[*count
] : NULL
,
792 key_data
, buffer
? *buffer
+ sizeof(CREDENTIALW
) : NULL
,
794 RegCloseKey(hkeyCred
);
795 if (ret
!= ERROR_SUCCESS
) break;
796 if (buffer
) *buffer
+= *len
;
803 static DWORD
mac_enumerate_credentials(LPCWSTR filter
, PCREDENTIALW
*credentials
,
804 char *buffer
, DWORD
*len
, DWORD
*count
)
806 SecKeychainSearchRef search
;
807 SecKeychainItemRef item
;
809 Boolean saved_user_interaction_allowed
;
812 SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed
);
813 SecKeychainSetUserInteractionAllowed(false);
815 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecInternetPasswordItemClass
, NULL
, &search
);
818 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
820 SecKeychainAttributeInfo info
;
821 SecKeychainAttributeList
*attr_list
;
822 UInt32 info_tags
[] = { kSecServerItemAttr
};
823 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
824 info
.tag
= info_tags
;
826 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
829 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
834 *len
= sizeof(CREDENTIALW
);
835 credentials
[*count
] = (PCREDENTIALW
)buffer
;
838 *len
+= sizeof(CREDENTIALW
);
839 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServerItemAttr
) continue;
840 TRACE("server item: %.*s\n", (int)attr_list
->attr
[0].length
, (char *)attr_list
->attr
[0].data
);
841 /* FIXME: filter based on attr_list->attr[0].data */
842 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
843 ret
= mac_read_credential_from_item(item
, FALSE
,
844 buffer
? credentials
[*count
] : NULL
,
845 buffer
? buffer
+ sizeof(CREDENTIALW
) : NULL
,
848 if (ret
== ERROR_SUCCESS
)
851 if (buffer
) buffer
+= *len
;
857 ERR("SecKeychainSearchCreateFromAttributes returned status %ld\n", status
);
858 SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed
);
859 return ERROR_SUCCESS
;
862 static DWORD
mac_delete_credential(LPCWSTR TargetName
)
865 SecKeychainSearchRef search
;
866 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecInternetPasswordItemClass
, NULL
, &search
);
869 SecKeychainItemRef item
;
870 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
872 SecKeychainAttributeInfo info
;
873 SecKeychainAttributeList
*attr_list
;
874 UInt32 info_tags
[] = { kSecServerItemAttr
};
877 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
878 info
.tag
= info_tags
;
880 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
883 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
886 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServerItemAttr
)
891 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
892 target_name
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
893 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
895 target_name
[str_len
] = '\0';
896 if (strcmpiW(TargetName
, target_name
))
899 HeapFree(GetProcessHeap(), 0, target_name
);
902 HeapFree(GetProcessHeap(), 0, target_name
);
903 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
904 SecKeychainItemDelete(item
);
908 return ERROR_SUCCESS
;
912 return ERROR_NOT_FOUND
;
916 /******************************************************************************
917 * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
919 * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
923 static INT
convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW
*CredentialW
, PCREDENTIALA CredentialA
, DWORD len
)
927 INT needed
= sizeof(CREDENTIALA
);
931 if (CredentialW
->TargetName
)
932 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
933 if (CredentialW
->Comment
)
934 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, NULL
, 0, NULL
, NULL
);
935 needed
+= CredentialW
->CredentialBlobSize
;
936 if (CredentialW
->TargetAlias
)
937 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, NULL
, 0, NULL
, NULL
);
938 if (CredentialW
->UserName
)
939 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, NULL
, 0, NULL
, NULL
);
945 buffer
= (char *)CredentialA
+ sizeof(CREDENTIALA
);
946 len
-= sizeof(CREDENTIALA
);
947 CredentialA
->Flags
= CredentialW
->Flags
;
948 CredentialA
->Type
= CredentialW
->Type
;
950 if (CredentialW
->TargetName
)
952 CredentialA
->TargetName
= buffer
;
953 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, buffer
, len
, NULL
, NULL
);
954 buffer
+= string_len
;
955 needed
+= string_len
;
959 CredentialA
->TargetName
= NULL
;
960 if (CredentialW
->Comment
)
962 CredentialA
->Comment
= buffer
;
963 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, buffer
, len
, NULL
, NULL
);
964 buffer
+= string_len
;
965 needed
+= string_len
;
969 CredentialA
->Comment
= NULL
;
970 CredentialA
->LastWritten
= CredentialW
->LastWritten
;
971 CredentialA
->CredentialBlobSize
= CredentialW
->CredentialBlobSize
;
972 if (CredentialW
->CredentialBlobSize
&& (CredentialW
->CredentialBlobSize
<= len
))
974 CredentialA
->CredentialBlob
=(LPBYTE
)buffer
;
975 memcpy(CredentialA
->CredentialBlob
, CredentialW
->CredentialBlob
,
976 CredentialW
->CredentialBlobSize
);
977 buffer
+= CredentialW
->CredentialBlobSize
;
978 needed
+= CredentialW
->CredentialBlobSize
;
979 len
-= CredentialW
->CredentialBlobSize
;
982 CredentialA
->CredentialBlob
= NULL
;
983 CredentialA
->Persist
= CredentialW
->Persist
;
984 CredentialA
->AttributeCount
= 0;
985 CredentialA
->Attributes
= NULL
; /* FIXME */
986 if (CredentialW
->TargetAlias
)
988 CredentialA
->TargetAlias
= buffer
;
989 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, buffer
, len
, NULL
, NULL
);
990 buffer
+= string_len
;
991 needed
+= string_len
;
995 CredentialA
->TargetAlias
= NULL
;
996 if (CredentialW
->UserName
)
998 CredentialA
->UserName
= buffer
;
999 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, buffer
, len
, NULL
, NULL
);
1000 needed
+= string_len
;
1003 CredentialA
->UserName
= NULL
;
1008 /******************************************************************************
1009 * convert_PCREDENTIALA_to_PCREDENTIALW [internal]
1011 * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
1014 static INT
convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA
*CredentialA
, PCREDENTIALW CredentialW
, INT len
)
1018 INT needed
= sizeof(CREDENTIALW
);
1022 if (CredentialA
->TargetName
)
1023 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, NULL
, 0);
1024 if (CredentialA
->Comment
)
1025 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, NULL
, 0);
1026 needed
+= CredentialA
->CredentialBlobSize
;
1027 if (CredentialA
->TargetAlias
)
1028 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, NULL
, 0);
1029 if (CredentialA
->UserName
)
1030 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, NULL
, 0);
1035 buffer
= (char *)CredentialW
+ sizeof(CREDENTIALW
);
1036 len
-= sizeof(CREDENTIALW
);
1037 CredentialW
->Flags
= CredentialA
->Flags
;
1038 CredentialW
->Type
= CredentialA
->Type
;
1039 if (CredentialA
->TargetName
)
1041 CredentialW
->TargetName
= (LPWSTR
)buffer
;
1042 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, CredentialW
->TargetName
, len
/ sizeof(WCHAR
));
1043 buffer
+= sizeof(WCHAR
) * string_len
;
1044 needed
+= sizeof(WCHAR
) * string_len
;
1045 len
-= sizeof(WCHAR
) * string_len
;
1048 CredentialW
->TargetName
= NULL
;
1049 if (CredentialA
->Comment
)
1051 CredentialW
->Comment
= (LPWSTR
)buffer
;
1052 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, CredentialW
->Comment
, len
/ sizeof(WCHAR
));
1053 buffer
+= sizeof(WCHAR
) * string_len
;
1054 needed
+= sizeof(WCHAR
) * string_len
;
1055 len
-= sizeof(WCHAR
) * string_len
;
1058 CredentialW
->Comment
= NULL
;
1059 CredentialW
->LastWritten
= CredentialA
->LastWritten
;
1060 CredentialW
->CredentialBlobSize
= CredentialA
->CredentialBlobSize
;
1061 if (CredentialA
->CredentialBlobSize
)
1063 CredentialW
->CredentialBlob
=(LPBYTE
)buffer
;
1064 memcpy(CredentialW
->CredentialBlob
, CredentialA
->CredentialBlob
,
1065 CredentialA
->CredentialBlobSize
);
1066 buffer
+= CredentialA
->CredentialBlobSize
;
1067 needed
+= CredentialA
->CredentialBlobSize
;
1068 len
-= CredentialA
->CredentialBlobSize
;
1071 CredentialW
->CredentialBlob
= NULL
;
1072 CredentialW
->Persist
= CredentialA
->Persist
;
1073 CredentialW
->AttributeCount
= 0;
1074 CredentialW
->Attributes
= NULL
; /* FIXME */
1075 if (CredentialA
->TargetAlias
)
1077 CredentialW
->TargetAlias
= (LPWSTR
)buffer
;
1078 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, CredentialW
->TargetAlias
, len
/ sizeof(WCHAR
));
1079 buffer
+= sizeof(WCHAR
) * string_len
;
1080 needed
+= sizeof(WCHAR
) * string_len
;
1081 len
-= sizeof(WCHAR
) * string_len
;
1084 CredentialW
->TargetAlias
= NULL
;
1085 if (CredentialA
->UserName
)
1087 CredentialW
->UserName
= (LPWSTR
)buffer
;
1088 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, CredentialW
->UserName
, len
/ sizeof(WCHAR
));
1089 needed
+= sizeof(WCHAR
) * string_len
;
1092 CredentialW
->UserName
= NULL
;
1097 /******************************************************************************
1098 * CredDeleteA [ADVAPI32.@]
1100 BOOL WINAPI
CredDeleteA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
)
1106 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName
), Type
, Flags
);
1110 SetLastError(ERROR_INVALID_PARAMETER
);
1114 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1115 TargetNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1118 SetLastError(ERROR_OUTOFMEMORY
);
1121 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1123 ret
= CredDeleteW(TargetNameW
, Type
, Flags
);
1125 HeapFree(GetProcessHeap(), 0, TargetNameW
);
1130 /******************************************************************************
1131 * CredDeleteW [ADVAPI32.@]
1133 BOOL WINAPI
CredDeleteW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
)
1139 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName
), Type
, Flags
);
1143 SetLastError(ERROR_INVALID_PARAMETER
);
1147 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1149 FIXME("unhandled type %d\n", Type
);
1150 SetLastError(ERROR_INVALID_PARAMETER
);
1156 FIXME("unhandled flags 0x%x\n", Flags
);
1157 SetLastError(ERROR_INVALID_FLAGS
);
1162 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1164 ret
= mac_delete_credential(TargetName
);
1165 if (ret
== ERROR_SUCCESS
)
1170 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
1171 if (ret
!= ERROR_SUCCESS
)
1173 WARN("couldn't open/create manager key, error %d\n", ret
);
1174 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1178 key_name
= get_key_name_for_target(TargetName
, Type
);
1179 ret
= RegDeleteKeyW(hkeyMgr
, key_name
);
1180 HeapFree(GetProcessHeap(), 0, key_name
);
1181 RegCloseKey(hkeyMgr
);
1182 if (ret
!= ERROR_SUCCESS
)
1184 SetLastError(ERROR_NOT_FOUND
);
1191 /******************************************************************************
1192 * CredEnumerateA [ADVAPI32.@]
1194 BOOL WINAPI
CredEnumerateA(LPCSTR Filter
, DWORD Flags
, DWORD
*Count
,
1195 PCREDENTIALA
**Credentials
)
1198 PCREDENTIALW
*CredentialsW
;
1204 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter
), Flags
, Count
, Credentials
);
1208 len
= MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, NULL
, 0);
1209 FilterW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1212 SetLastError(ERROR_OUTOFMEMORY
);
1215 MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, FilterW
, len
);
1220 if (!CredEnumerateW(FilterW
, Flags
, Count
, &CredentialsW
))
1222 HeapFree(GetProcessHeap(), 0, FilterW
);
1225 HeapFree(GetProcessHeap(), 0, FilterW
);
1227 len
= *Count
* sizeof(PCREDENTIALA
);
1228 for (i
= 0; i
< *Count
; i
++)
1229 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1231 *Credentials
= HeapAlloc(GetProcessHeap(), 0, len
);
1234 CredFree(CredentialsW
);
1235 SetLastError(ERROR_OUTOFMEMORY
);
1239 buffer
= (char *)&(*Credentials
)[*Count
];
1240 len
-= *Count
* sizeof(PCREDENTIALA
);
1241 for (i
= 0; i
< *Count
; i
++)
1243 (*Credentials
)[i
] = (PCREDENTIALA
)buffer
;
1244 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1249 CredFree(CredentialsW
);
1254 /******************************************************************************
1255 * CredEnumerateW [ADVAPI32.@]
1257 BOOL WINAPI
CredEnumerateW(LPCWSTR Filter
, DWORD Flags
, DWORD
*Count
,
1258 PCREDENTIALW
**Credentials
)
1263 DWORD target_name_len
;
1266 BYTE key_data
[KEY_SIZE
];
1268 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter
), Flags
, Count
, Credentials
);
1272 SetLastError(ERROR_INVALID_FLAGS
);
1276 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1277 if (ret
!= ERROR_SUCCESS
)
1279 WARN("couldn't open/create manager key, error %d\n", ret
);
1280 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1284 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1285 if (ret
!= ERROR_SUCCESS
)
1287 RegCloseKey(hkeyMgr
);
1292 ret
= RegQueryInfoKeyW(hkeyMgr
, NULL
, NULL
, NULL
, NULL
, &target_name_len
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1293 if (ret
!= ERROR_SUCCESS
)
1295 RegCloseKey(hkeyMgr
);
1300 target_name
= HeapAlloc(GetProcessHeap(), 0, (target_name_len
+1)*sizeof(WCHAR
));
1303 RegCloseKey(hkeyMgr
);
1304 SetLastError(ERROR_OUTOFMEMORY
);
1310 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
, target_name_len
,
1311 key_data
, NULL
, NULL
, &len
, Count
);
1313 if (ret
== ERROR_SUCCESS
)
1314 ret
= mac_enumerate_credentials(Filter
, NULL
, NULL
, &len
, Count
);
1316 if (ret
== ERROR_SUCCESS
&& *Count
== 0)
1317 ret
= ERROR_NOT_FOUND
;
1318 if (ret
!= ERROR_SUCCESS
)
1320 HeapFree(GetProcessHeap(), 0, target_name
);
1321 RegCloseKey(hkeyMgr
);
1325 len
+= *Count
* sizeof(PCREDENTIALW
);
1327 if (ret
== ERROR_SUCCESS
)
1329 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
1330 *Credentials
= (PCREDENTIALW
*)buffer
;
1333 buffer
+= *Count
* sizeof(PCREDENTIALW
);
1335 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
,
1336 target_name_len
, key_data
,
1337 *Credentials
, &buffer
, &len
,
1340 if (ret
== ERROR_SUCCESS
)
1341 ret
= mac_enumerate_credentials(Filter
, *Credentials
,
1342 buffer
, &len
, Count
);
1346 ret
= ERROR_OUTOFMEMORY
;
1349 HeapFree(GetProcessHeap(), 0, target_name
);
1350 RegCloseKey(hkeyMgr
);
1352 if (ret
!= ERROR_SUCCESS
)
1360 /******************************************************************************
1361 * CredFree [ADVAPI32.@]
1363 VOID WINAPI
CredFree(PVOID Buffer
)
1365 HeapFree(GetProcessHeap(), 0, Buffer
);
1368 /******************************************************************************
1369 * CredReadA [ADVAPI32.@]
1371 BOOL WINAPI
CredReadA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALA
*Credential
)
1374 PCREDENTIALW CredentialW
;
1377 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName
), Type
, Flags
, Credential
);
1381 SetLastError(ERROR_INVALID_PARAMETER
);
1385 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1386 TargetNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1389 SetLastError(ERROR_OUTOFMEMORY
);
1392 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1394 if (!CredReadW(TargetNameW
, Type
, Flags
, &CredentialW
))
1396 HeapFree(GetProcessHeap(), 0, TargetNameW
);
1399 HeapFree(GetProcessHeap(), 0, TargetNameW
);
1401 len
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, NULL
, 0);
1402 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
1405 SetLastError(ERROR_OUTOFMEMORY
);
1408 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, *Credential
, len
);
1410 CredFree(CredentialW
);
1415 /******************************************************************************
1416 * CredReadW [ADVAPI32.@]
1418 BOOL WINAPI
CredReadW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALW
*Credential
)
1425 BYTE key_data
[KEY_SIZE
];
1427 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName
), Type
, Flags
, Credential
);
1431 SetLastError(ERROR_INVALID_PARAMETER
);
1435 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1437 FIXME("unhandled type %d\n", Type
);
1438 SetLastError(ERROR_INVALID_PARAMETER
);
1444 FIXME("unhandled flags 0x%x\n", Flags
);
1445 SetLastError(ERROR_INVALID_FLAGS
);
1450 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1453 SecKeychainSearchRef search
;
1454 status
= SecKeychainSearchCreateFromAttributes(NULL
, kSecInternetPasswordItemClass
, NULL
, &search
);
1455 if (status
== noErr
)
1457 SecKeychainItemRef item
;
1458 while (SecKeychainSearchCopyNext(search
, &item
) == noErr
)
1460 SecKeychainAttributeInfo info
;
1461 SecKeychainAttributeList
*attr_list
;
1462 UInt32 info_tags
[] = { kSecServerItemAttr
};
1465 info
.count
= sizeof(info_tags
)/sizeof(info_tags
[0]);
1466 info
.tag
= info_tags
;
1468 status
= SecKeychainItemCopyAttributesAndData(item
, &info
, NULL
, &attr_list
, NULL
, NULL
);
1469 len
= sizeof(**Credential
);
1470 if (status
!= noErr
)
1472 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status
);
1475 if (attr_list
->count
!= 1 || attr_list
->attr
[0].tag
!= kSecServerItemAttr
)
1480 str_len
= MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, NULL
, 0);
1481 target_name
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
1482 MultiByteToWideChar(CP_UTF8
, 0, attr_list
->attr
[0].data
, attr_list
->attr
[0].length
, target_name
, str_len
);
1484 target_name
[str_len
] = '\0';
1485 if (strcmpiW(TargetName
, target_name
))
1488 HeapFree(GetProcessHeap(), 0, target_name
);
1491 HeapFree(GetProcessHeap(), 0, target_name
);
1492 SecKeychainItemFreeAttributesAndData(attr_list
, NULL
);
1493 ret
= mac_read_credential_from_item(item
, TRUE
, NULL
, NULL
, &len
);
1494 if (ret
== ERROR_SUCCESS
)
1496 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
1499 len
= sizeof(**Credential
);
1500 ret
= mac_read_credential_from_item(item
, TRUE
, *Credential
,
1501 (char *)(*Credential
+ 1), &len
);
1504 ret
= ERROR_OUTOFMEMORY
;
1507 if (ret
!= ERROR_SUCCESS
)
1521 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1522 if (ret
!= ERROR_SUCCESS
)
1524 WARN("couldn't open/create manager key, error %d\n", ret
);
1525 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1529 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1530 if (ret
!= ERROR_SUCCESS
)
1532 RegCloseKey(hkeyMgr
);
1537 key_name
= get_key_name_for_target(TargetName
, Type
);
1538 ret
= RegOpenKeyExW(hkeyMgr
, key_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
1539 HeapFree(GetProcessHeap(), 0, key_name
);
1540 if (ret
!= ERROR_SUCCESS
)
1542 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName
));
1543 SetLastError(ERROR_NOT_FOUND
);
1547 len
= sizeof(**Credential
);
1548 ret
= registry_read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
1549 if (ret
== ERROR_SUCCESS
)
1551 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
1554 len
= sizeof(**Credential
);
1555 ret
= registry_read_credential(hkeyCred
, *Credential
, key_data
,
1556 (char *)(*Credential
+ 1), &len
);
1559 ret
= ERROR_OUTOFMEMORY
;
1562 RegCloseKey(hkeyCred
);
1563 RegCloseKey(hkeyMgr
);
1565 if (ret
!= ERROR_SUCCESS
)
1573 /******************************************************************************
1574 * CredReadDomainCredentialsA [ADVAPI32.@]
1576 BOOL WINAPI
CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation
,
1577 DWORD Flags
, DWORD
*Size
, PCREDENTIALA
**Credentials
)
1579 PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW
;
1582 WCHAR
*buffer
, *end
;
1584 PCREDENTIALW
* CredentialsW
;
1586 TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation
, Flags
, Size
, Credentials
);
1588 /* follow Windows behavior - do not test for NULL, initialize early */
1590 *Credentials
= NULL
;
1592 if (!TargetInformation
)
1594 SetLastError(ERROR_INVALID_PARAMETER
);
1598 len
= sizeof(*TargetInformationW
);
1599 if (TargetInformation
->TargetName
)
1600 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1, NULL
, 0) * sizeof(WCHAR
);
1601 if (TargetInformation
->NetbiosServerName
)
1602 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1603 if (TargetInformation
->DnsServerName
)
1604 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1605 if (TargetInformation
->NetbiosDomainName
)
1606 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1607 if (TargetInformation
->DnsDomainName
)
1608 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1609 if (TargetInformation
->DnsTreeName
)
1610 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1, NULL
, 0) * sizeof(WCHAR
);
1611 if (TargetInformation
->PackageName
)
1612 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1, NULL
, 0) * sizeof(WCHAR
);
1614 TargetInformationW
= HeapAlloc(GetProcessHeap(), 0, len
);
1615 if (!TargetInformationW
)
1617 SetLastError(ERROR_OUTOFMEMORY
);
1620 buffer
= (WCHAR
*)(TargetInformationW
+ 1);
1621 end
= (WCHAR
*)((char *)TargetInformationW
+ len
);
1623 if (TargetInformation
->TargetName
)
1625 TargetInformationW
->TargetName
= buffer
;
1626 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1,
1627 TargetInformationW
->TargetName
, end
- buffer
);
1629 TargetInformationW
->TargetName
= NULL
;
1631 if (TargetInformation
->NetbiosServerName
)
1633 TargetInformationW
->NetbiosServerName
= buffer
;
1634 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1,
1635 TargetInformationW
->NetbiosServerName
, end
- buffer
);
1637 TargetInformationW
->NetbiosServerName
= NULL
;
1639 if (TargetInformation
->DnsServerName
)
1641 TargetInformationW
->DnsServerName
= buffer
;
1642 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1,
1643 TargetInformationW
->DnsServerName
, end
- buffer
);
1645 TargetInformationW
->DnsServerName
= NULL
;
1647 if (TargetInformation
->NetbiosDomainName
)
1649 TargetInformationW
->NetbiosDomainName
= buffer
;
1650 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1,
1651 TargetInformationW
->NetbiosDomainName
, end
- buffer
);
1653 TargetInformationW
->NetbiosDomainName
= NULL
;
1655 if (TargetInformation
->DnsDomainName
)
1657 TargetInformationW
->DnsDomainName
= buffer
;
1658 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1,
1659 TargetInformationW
->DnsDomainName
, end
- buffer
);
1661 TargetInformationW
->DnsDomainName
= NULL
;
1663 if (TargetInformation
->DnsTreeName
)
1665 TargetInformationW
->DnsTreeName
= buffer
;
1666 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1,
1667 TargetInformationW
->DnsTreeName
, end
- buffer
);
1669 TargetInformationW
->DnsTreeName
= NULL
;
1671 if (TargetInformation
->PackageName
)
1673 TargetInformationW
->PackageName
= buffer
;
1674 MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1,
1675 TargetInformationW
->PackageName
, end
- buffer
);
1677 TargetInformationW
->PackageName
= NULL
;
1679 TargetInformationW
->Flags
= TargetInformation
->Flags
;
1680 TargetInformationW
->CredTypeCount
= TargetInformation
->CredTypeCount
;
1681 TargetInformationW
->CredTypes
= TargetInformation
->CredTypes
;
1683 ret
= CredReadDomainCredentialsW(TargetInformationW
, Flags
, Size
, &CredentialsW
);
1685 HeapFree(GetProcessHeap(), 0, TargetInformationW
);
1692 len
= *Size
* sizeof(PCREDENTIALA
);
1693 for (i
= 0; i
< *Size
; i
++)
1694 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1696 *Credentials
= HeapAlloc(GetProcessHeap(), 0, len
);
1699 CredFree(CredentialsW
);
1700 SetLastError(ERROR_OUTOFMEMORY
);
1704 buf
= (char *)&(*Credentials
)[*Size
];
1705 len
-= *Size
* sizeof(PCREDENTIALA
);
1706 for (i
= 0; i
< *Size
; i
++)
1708 (*Credentials
)[i
] = (PCREDENTIALA
)buf
;
1709 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1714 CredFree(CredentialsW
);
1719 /******************************************************************************
1720 * CredReadDomainCredentialsW [ADVAPI32.@]
1722 BOOL WINAPI
CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation
, DWORD Flags
,
1723 DWORD
*Size
, PCREDENTIALW
**Credentials
)
1725 FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation
, Flags
, Size
, Credentials
);
1727 /* follow Windows behavior - do not test for NULL, initialize early */
1729 *Credentials
= NULL
;
1730 if (!TargetInformation
)
1732 SetLastError(ERROR_INVALID_PARAMETER
);
1736 SetLastError(ERROR_NOT_FOUND
);
1740 /******************************************************************************
1741 * CredWriteA [ADVAPI32.@]
1743 BOOL WINAPI
CredWriteA(PCREDENTIALA Credential
, DWORD Flags
)
1747 PCREDENTIALW CredentialW
;
1749 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1751 if (!Credential
|| !Credential
->TargetName
)
1753 SetLastError(ERROR_INVALID_PARAMETER
);
1757 len
= convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, NULL
, 0);
1758 CredentialW
= HeapAlloc(GetProcessHeap(), 0, len
);
1761 SetLastError(ERROR_OUTOFMEMORY
);
1765 convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, CredentialW
, len
);
1767 ret
= CredWriteW(CredentialW
, Flags
);
1769 HeapFree(GetProcessHeap(), 0, CredentialW
);
1774 /******************************************************************************
1775 * CredWriteW [ADVAPI32.@]
1777 BOOL WINAPI
CredWriteW(PCREDENTIALW Credential
, DWORD Flags
)
1783 BYTE key_data
[KEY_SIZE
];
1785 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1787 if (!Credential
|| !Credential
->TargetName
)
1789 SetLastError(ERROR_INVALID_PARAMETER
);
1793 if (Flags
& ~CRED_PRESERVE_CREDENTIAL_BLOB
)
1795 FIXME("unhandled flags 0x%x\n", Flags
);
1796 SetLastError(ERROR_INVALID_FLAGS
);
1800 if (Credential
->Type
!= CRED_TYPE_GENERIC
&& Credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1802 FIXME("unhandled type %d\n", Credential
->Type
);
1803 SetLastError(ERROR_INVALID_PARAMETER
);
1807 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential
->TargetName
));
1808 TRACE("Credential->UserName = %s\n", debugstr_w(Credential
->UserName
));
1810 if (Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1812 if (!Credential
->UserName
||
1813 (!strchrW(Credential
->UserName
, '\\') && !strchrW(Credential
->UserName
, '@')))
1815 ERR("bad username %s\n", debugstr_w(Credential
->UserName
));
1816 SetLastError(ERROR_BAD_USERNAME
);
1822 if (!Credential
->AttributeCount
&&
1823 Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
&&
1824 (Credential
->Persist
== CRED_PERSIST_LOCAL_MACHINE
|| Credential
->Persist
== CRED_PERSIST_ENTERPRISE
))
1826 ret
= mac_write_credential(Credential
, Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1827 if (ret
!= ERROR_SUCCESS
)
1836 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1837 if (ret
!= ERROR_SUCCESS
)
1839 WARN("couldn't open/create manager key, error %d\n", ret
);
1840 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1844 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1845 if (ret
!= ERROR_SUCCESS
)
1847 RegCloseKey(hkeyMgr
);
1852 key_name
= get_key_name_for_target(Credential
->TargetName
, Credential
->Type
);
1853 ret
= RegCreateKeyExW(hkeyMgr
, key_name
, 0, NULL
,
1854 Credential
->Persist
== CRED_PERSIST_SESSION
? REG_OPTION_VOLATILE
: REG_OPTION_NON_VOLATILE
,
1855 KEY_READ
|KEY_WRITE
, NULL
, &hkeyCred
, NULL
);
1856 HeapFree(GetProcessHeap(), 0, key_name
);
1857 if (ret
!= ERROR_SUCCESS
)
1859 TRACE("credentials for target name %s not found\n",
1860 debugstr_w(Credential
->TargetName
));
1861 SetLastError(ERROR_NOT_FOUND
);
1865 ret
= registry_write_credential(hkeyCred
, Credential
, key_data
,
1866 Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1868 RegCloseKey(hkeyCred
);
1869 RegCloseKey(hkeyMgr
);
1871 if (ret
!= ERROR_SUCCESS
)
1879 /******************************************************************************
1880 * CredGetSessionTypes [ADVAPI32.@]
1882 WINADVAPI BOOL WINAPI
CredGetSessionTypes(DWORD persistCount
, LPDWORD persists
)
1884 TRACE("(%u, %p)\n", persistCount
, persists
);
1886 memset(persists
, CRED_PERSIST_NONE
, persistCount
*sizeof(*persists
));
1887 if (CRED_TYPE_GENERIC
< persistCount
)
1889 persists
[CRED_TYPE_GENERIC
] = CRED_PERSIST_ENTERPRISE
;
1891 if (CRED_TYPE_DOMAIN_PASSWORD
< persistCount
)
1893 persists
[CRED_TYPE_DOMAIN_PASSWORD
] = CRED_PERSIST_ENTERPRISE
;
1899 /******************************************************************************
1900 * CredMarshalCredentialA [ADVAPI32.@]
1902 BOOL WINAPI
CredMarshalCredentialA( CRED_MARSHAL_TYPE type
, PVOID cred
, LPSTR
*out
)
1907 TRACE("%u, %p, %p\n", type
, cred
, out
);
1909 if ((ret
= CredMarshalCredentialW( type
, cred
, &outW
)))
1911 int len
= WideCharToMultiByte( CP_ACP
, 0, outW
, -1, NULL
, 0, NULL
, NULL
);
1912 if (!(*out
= HeapAlloc( GetProcessHeap(), 0, len
)))
1914 HeapFree( GetProcessHeap(), 0, outW
);
1917 WideCharToMultiByte( CP_ACP
, 0, outW
, -1, *out
, len
, NULL
, NULL
);
1918 HeapFree( GetProcessHeap(), 0, outW
);
1923 static UINT
cred_encode( const char *bin
, unsigned int len
, WCHAR
*cred
)
1925 static char enc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#-";
1930 cred
[n
++] = enc
[bin
[0] & 0x3f];
1931 x
= (bin
[0] & 0xc0) >> 6;
1937 cred
[n
++] = enc
[((bin
[1] & 0xf) << 2) | x
];
1938 x
= (bin
[1] & 0xf0) >> 4;
1944 cred
[n
++] = enc
[((bin
[2] & 0x3) << 4) | x
];
1945 cred
[n
++] = enc
[(bin
[2] & 0xfc) >> 2];
1952 /******************************************************************************
1953 * CredMarshalCredentialW [ADVAPI32.@]
1955 BOOL WINAPI
CredMarshalCredentialW( CRED_MARSHAL_TYPE type
, PVOID cred
, LPWSTR
*out
)
1957 CERT_CREDENTIAL_INFO
*cert
= cred
;
1958 USERNAME_TARGET_CREDENTIAL_INFO
*target
= cred
;
1962 TRACE("%u, %p, %p\n", type
, cred
, out
);
1964 if (!cred
|| (type
== CertCredential
&& cert
->cbSize
< sizeof(*cert
)) ||
1965 (type
!= CertCredential
&& type
!= UsernameTargetCredential
&& type
!= BinaryBlobCredential
) ||
1966 (type
== UsernameTargetCredential
&& (!target
->UserName
|| !target
->UserName
[0])))
1968 SetLastError( ERROR_INVALID_PARAMETER
);
1973 case CertCredential
:
1975 char hash
[CERT_HASH_LENGTH
+ 2];
1977 memcpy( hash
, cert
->rgbHashOfCert
, sizeof(cert
->rgbHashOfCert
) );
1978 memset( hash
+ sizeof(cert
->rgbHashOfCert
), 0, sizeof(hash
) - sizeof(cert
->rgbHashOfCert
) );
1980 size
= sizeof(hash
) * 4 / 3;
1981 if (!(p
= HeapAlloc( GetProcessHeap(), 0, (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1985 len
= cred_encode( (const char *)hash
, sizeof(hash
), p
+ 3 );
1989 case UsernameTargetCredential
:
1991 len
= strlenW( target
->UserName
);
1992 size
= (sizeof(DWORD
) + len
* sizeof(WCHAR
) + 2) * 4 / 3;
1993 if (!(p
= HeapAlloc( GetProcessHeap(), 0, (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1997 size
= len
* sizeof(WCHAR
);
1998 len
= cred_encode( (const char *)&size
, sizeof(DWORD
), p
+ 3 );
1999 len
+= cred_encode( (const char *)target
->UserName
, size
, p
+ 3 + len
);
2003 case BinaryBlobCredential
:
2004 FIXME("BinaryBlobCredential not implemented\n");
2013 /******************************************************************************
2014 * CredUnmarshalCredentialA [ADVAPI32.@]
2016 BOOL WINAPI
CredUnmarshalCredentialA( LPCSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
2019 WCHAR
*credW
= NULL
;
2021 TRACE("%s, %p, %p\n", debugstr_a(cred
), type
, out
);
2025 int len
= MultiByteToWideChar( CP_ACP
, 0, cred
, -1, NULL
, 0 );
2026 if (!(credW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return FALSE
;
2027 MultiByteToWideChar( CP_ACP
, 0, cred
, -1, credW
, len
);
2029 ret
= CredUnmarshalCredentialW( credW
, type
, out
);
2030 HeapFree( GetProcessHeap(), 0, credW
);
2034 static inline char char_decode( WCHAR c
)
2036 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
2037 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
2038 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
2039 if (c
== '#') return 62;
2040 if (c
== '-') return 63;
2044 static BOOL
cred_decode( const WCHAR
*cred
, unsigned int len
, char *buf
)
2047 char c0
, c1
, c2
, c3
;
2048 const WCHAR
*p
= cred
;
2052 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2053 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2054 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2055 if ((c3
= char_decode( p
[3] )) > 63) return FALSE
;
2057 buf
[i
+ 0] = (c1
<< 6) | c0
;
2058 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2059 buf
[i
+ 2] = (c3
<< 2) | (c2
>> 4);
2066 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2067 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2068 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
2070 buf
[i
+ 0] = (c1
<< 6) | c0
;
2071 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
2072 buf
[i
+ 2] = c2
>> 4;
2076 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2077 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
2079 buf
[i
+ 0] = (c1
<< 6) | c0
;
2080 buf
[i
+ 1] = c1
>> 2;
2085 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
2094 /******************************************************************************
2095 * CredUnmarshalCredentialW [ADVAPI32.@]
2097 BOOL WINAPI
CredUnmarshalCredentialW( LPCWSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
2099 unsigned int len
, buflen
, size
;
2101 TRACE("%s, %p, %p\n", debugstr_w(cred
), type
, out
);
2103 if (!cred
|| cred
[0] != '@' || cred
[1] != '@' || !cred
[2] || !cred
[3])
2105 SetLastError( ERROR_INVALID_PARAMETER
);
2108 len
= strlenW( cred
+ 3 );
2109 switch (cred
[2] - 'A')
2111 case CertCredential
:
2113 char hash
[CERT_HASH_LENGTH
+ 2];
2114 CERT_CREDENTIAL_INFO
*cert
;
2116 if (len
!= 27 || !cred_decode( cred
+ 3, len
, hash
))
2118 SetLastError( ERROR_INVALID_PARAMETER
);
2121 if (!(cert
= HeapAlloc( GetProcessHeap(), 0, sizeof(*cert
) ))) return FALSE
;
2122 memcpy( cert
->rgbHashOfCert
, hash
, sizeof(cert
->rgbHashOfCert
) );
2123 cert
->cbSize
= sizeof(*cert
);
2124 *type
= CertCredential
;
2128 case UsernameTargetCredential
:
2130 USERNAME_TARGET_CREDENTIAL_INFO
*target
;
2132 if (len
< 9 || !cred_decode( cred
+ 3, 6, (char *)&size
) || !size
|| size
% sizeof(WCHAR
))
2134 SetLastError( ERROR_INVALID_PARAMETER
);
2137 buflen
= sizeof(*target
) + size
+ sizeof(WCHAR
);
2138 if (!(target
= HeapAlloc( GetProcessHeap(), 0, buflen
))) return FALSE
;
2139 if (!cred_decode( cred
+ 9, len
- 6, (char *)(target
+ 1) ))
2141 HeapFree( GetProcessHeap(), 0, target
);
2144 target
->UserName
= (WCHAR
*)(target
+ 1);
2145 target
->UserName
[size
/ sizeof(WCHAR
)] = 0;
2146 *type
= UsernameTargetCredential
;
2150 case BinaryBlobCredential
:
2151 FIXME("BinaryBlobCredential not implemented\n");
2154 WARN("unhandled type %u\n", cred
[2] - 'A');
2160 /******************************************************************************
2161 * CredIsMarshaledCredentialW [ADVAPI32.@]
2163 * Check, if the name parameter is a marshaled credential, hash or binary blob
2166 * name the name to check
2169 * TRUE: the name parameter is a marshaled credential, hash or binary blob
2170 * FALSE: the name is a plain username
2172 BOOL WINAPI
CredIsMarshaledCredentialW(LPCWSTR name
)
2174 TRACE("(%s)\n", debugstr_w(name
));
2176 if (name
&& name
[0] == '@' && name
[1] == '@' && name
[2] > 'A' && name
[3])
2178 char hash
[CERT_HASH_LENGTH
+ 2];
2179 int len
= strlenW(name
+ 3 );
2182 if ((name
[2] - 'A') == CertCredential
&& (len
== 27) && cred_decode(name
+ 3, len
, hash
))
2185 if (((name
[2] - 'A') == UsernameTargetCredential
) &&
2186 (len
>= 9) && cred_decode(name
+ 3, 6, (char *)&size
) && size
)
2189 if ((name
[2] - 'A') == BinaryBlobCredential
)
2190 FIXME("BinaryBlobCredential not checked\n");
2192 if ((name
[2] - 'A') > BinaryBlobCredential
)
2193 TRACE("unknown type: %d\n", (name
[2] - 'A'));
2196 SetLastError(ERROR_INVALID_PARAMETER
);
2200 /******************************************************************************
2201 * CredIsMarshaledCredentialA [ADVAPI32.@]
2203 * See CredIsMarshaledCredentialW
2206 BOOL WINAPI
CredIsMarshaledCredentialA(LPCSTR name
)
2208 LPWSTR nameW
= NULL
;
2212 TRACE("(%s)\n", debugstr_a(name
));
2216 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0);
2217 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2218 MultiByteToWideChar(CP_ACP
, 0, name
, -1, nameW
, len
);
2221 res
= CredIsMarshaledCredentialW(nameW
);
2222 HeapFree(GetProcessHeap(), 0, nameW
);