Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencred.c
Go to the documentation of this file.
00001 /* 00002 * Credential Management APIs 00003 * 00004 * Copyright 2007 Robert Shearman for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <advapi32.h> 00022 WINE_DEFAULT_DEBUG_CHANNEL(cred); 00023 00024 /* the size of the ARC4 key used to encrypt the password data */ 00025 #define KEY_SIZE 8 00026 00027 static const WCHAR wszCredentialManagerKey[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', 00028 'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0}; 00029 static const WCHAR wszEncryptionKeyValue[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0}; 00030 00031 static const WCHAR wszFlagsValue[] = {'F','l','a','g','s',0}; 00032 static const WCHAR wszTypeValue[] = {'T','y','p','e',0}; 00033 static const WCHAR wszCommentValue[] = {'C','o','m','m','e','n','t',0}; 00034 static const WCHAR wszLastWrittenValue[] = {'L','a','s','t','W','r','i','t','t','e','n',0}; 00035 static const WCHAR wszPersistValue[] = {'P','e','r','s','i','s','t',0}; 00036 static const WCHAR wszTargetAliasValue[] = {'T','a','r','g','e','t','A','l','i','a','s',0}; 00037 static const WCHAR wszUserNameValue[] = {'U','s','e','r','N','a','m','e',0}; 00038 static const WCHAR wszPasswordValue[] = {'P','a','s','s','w','o','r','d',0}; 00039 00040 static DWORD read_credential_blob(HKEY hkey, const BYTE key_data[KEY_SIZE], 00041 LPBYTE credential_blob, 00042 DWORD *credential_blob_size) 00043 { 00044 DWORD ret; 00045 DWORD type; 00046 00047 *credential_blob_size = 0; 00048 ret = RegQueryValueExW(hkey, wszPasswordValue, 0, &type, NULL, credential_blob_size); 00049 if (ret != ERROR_SUCCESS) 00050 return ret; 00051 else if (type != REG_BINARY) 00052 return ERROR_REGISTRY_CORRUPT; 00053 if (credential_blob) 00054 { 00055 struct ustring data; 00056 struct ustring key; 00057 00058 ret = RegQueryValueExW(hkey, wszPasswordValue, 0, &type, credential_blob, 00059 credential_blob_size); 00060 if (ret != ERROR_SUCCESS) 00061 return ret; 00062 else if (type != REG_BINARY) 00063 return ERROR_REGISTRY_CORRUPT; 00064 00065 key.Length = key.MaximumLength = KEY_SIZE; 00066 key.Buffer = (unsigned char *)key_data; 00067 00068 data.Length = data.MaximumLength = *credential_blob_size; 00069 data.Buffer = credential_blob; 00070 SystemFunction032(&data, &key); 00071 } 00072 return ERROR_SUCCESS; 00073 } 00074 00075 static DWORD registry_read_credential(HKEY hkey, PCREDENTIALW credential, 00076 const BYTE key_data[KEY_SIZE], 00077 char *buffer, DWORD *len) 00078 { 00079 DWORD type; 00080 DWORD ret; 00081 DWORD count; 00082 00083 ret = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &count); 00084 if (ret != ERROR_SUCCESS) 00085 return ret; 00086 else if (type != REG_SZ) 00087 return ERROR_REGISTRY_CORRUPT; 00088 *len += count; 00089 if (credential) 00090 { 00091 credential->TargetName = (LPWSTR)buffer; 00092 ret = RegQueryValueExW(hkey, NULL, 0, &type, (LPVOID)credential->TargetName, 00093 &count); 00094 if (ret != ERROR_SUCCESS) 00095 return ret; 00096 else if (type != REG_SZ) 00097 return ERROR_REGISTRY_CORRUPT; 00098 buffer += count; 00099 } 00100 00101 ret = RegQueryValueExW(hkey, wszCommentValue, 0, &type, NULL, &count); 00102 if (ret != ERROR_FILE_NOT_FOUND) 00103 { 00104 if (ret != ERROR_SUCCESS) 00105 return ret; 00106 else if (type != REG_SZ) 00107 return ERROR_REGISTRY_CORRUPT; 00108 *len += count; 00109 } 00110 if (credential) 00111 { 00112 credential->Comment = (LPWSTR)buffer; 00113 ret = RegQueryValueExW(hkey, wszCommentValue, 0, &type, (LPVOID)credential->Comment, 00114 &count); 00115 if (ret == ERROR_FILE_NOT_FOUND) 00116 credential->Comment = NULL; 00117 else if (ret != ERROR_SUCCESS) 00118 return ret; 00119 else if (type != REG_SZ) 00120 return ERROR_REGISTRY_CORRUPT; 00121 else 00122 buffer += count; 00123 } 00124 00125 ret = RegQueryValueExW(hkey, wszTargetAliasValue, 0, &type, NULL, &count); 00126 if (ret != ERROR_FILE_NOT_FOUND) 00127 { 00128 if (ret != ERROR_SUCCESS) 00129 return ret; 00130 else if (type != REG_SZ) 00131 return ERROR_REGISTRY_CORRUPT; 00132 *len += count; 00133 } 00134 if (credential) 00135 { 00136 credential->TargetAlias = (LPWSTR)buffer; 00137 ret = RegQueryValueExW(hkey, wszTargetAliasValue, 0, &type, (LPVOID)credential->TargetAlias, 00138 &count); 00139 if (ret == ERROR_FILE_NOT_FOUND) 00140 credential->TargetAlias = NULL; 00141 else if (ret != ERROR_SUCCESS) 00142 return ret; 00143 else if (type != REG_SZ) 00144 return ERROR_REGISTRY_CORRUPT; 00145 else 00146 buffer += count; 00147 } 00148 00149 ret = RegQueryValueExW(hkey, wszUserNameValue, 0, &type, NULL, &count); 00150 if (ret != ERROR_FILE_NOT_FOUND) 00151 { 00152 if (ret != ERROR_SUCCESS) 00153 return ret; 00154 else if (type != REG_SZ) 00155 return ERROR_REGISTRY_CORRUPT; 00156 *len += count; 00157 } 00158 if (credential) 00159 { 00160 credential->UserName = (LPWSTR)buffer; 00161 ret = RegQueryValueExW(hkey, wszUserNameValue, 0, &type, (LPVOID)credential->UserName, 00162 &count); 00163 if (ret == ERROR_FILE_NOT_FOUND) 00164 credential->UserName = NULL; 00165 else if (ret != ERROR_SUCCESS) 00166 return ret; 00167 else if (type != REG_SZ) 00168 return ERROR_REGISTRY_CORRUPT; 00169 else 00170 buffer += count; 00171 } 00172 00173 ret = read_credential_blob(hkey, key_data, NULL, &count); 00174 if (ret != ERROR_FILE_NOT_FOUND) 00175 { 00176 if (ret != ERROR_SUCCESS) 00177 return ret; 00178 *len += count; 00179 } 00180 if (credential) 00181 { 00182 credential->CredentialBlob = (LPBYTE)buffer; 00183 ret = read_credential_blob(hkey, key_data, credential->CredentialBlob, &count); 00184 if (ret == ERROR_FILE_NOT_FOUND) 00185 credential->CredentialBlob = NULL; 00186 else if (ret != ERROR_SUCCESS) 00187 return ret; 00188 credential->CredentialBlobSize = count; 00189 buffer += count; 00190 } 00191 00192 /* FIXME: Attributes */ 00193 if (credential) 00194 { 00195 credential->AttributeCount = 0; 00196 credential->Attributes = NULL; 00197 } 00198 00199 if (!credential) return ERROR_SUCCESS; 00200 00201 count = sizeof(credential->Flags); 00202 ret = RegQueryValueExW(hkey, wszFlagsValue, NULL, &type, (LPVOID)&credential->Flags, 00203 &count); 00204 if (ret != ERROR_SUCCESS) 00205 return ret; 00206 else if (type != REG_DWORD) 00207 return ERROR_REGISTRY_CORRUPT; 00208 count = sizeof(credential->Type); 00209 ret = RegQueryValueExW(hkey, wszTypeValue, NULL, &type, (LPVOID)&credential->Type, 00210 &count); 00211 if (ret != ERROR_SUCCESS) 00212 return ret; 00213 else if (type != REG_DWORD) 00214 return ERROR_REGISTRY_CORRUPT; 00215 00216 count = sizeof(credential->LastWritten); 00217 ret = RegQueryValueExW(hkey, wszLastWrittenValue, NULL, &type, (LPVOID)&credential->LastWritten, 00218 &count); 00219 if (ret != ERROR_SUCCESS) 00220 return ret; 00221 else if (type != REG_BINARY) 00222 return ERROR_REGISTRY_CORRUPT; 00223 count = sizeof(credential->Persist); 00224 ret = RegQueryValueExW(hkey, wszPersistValue, NULL, &type, (LPVOID)&credential->Persist, 00225 &count); 00226 if (ret == ERROR_SUCCESS && type != REG_DWORD) 00227 return ERROR_REGISTRY_CORRUPT; 00228 return ret; 00229 } 00230 00231 #ifdef __APPLE__ 00232 static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require_password, 00233 PCREDENTIALW credential, char *buffer, 00234 DWORD *len) 00235 { 00236 OSStatus status; 00237 UInt32 i; 00238 UInt32 cred_blob_len; 00239 void *cred_blob; 00240 LPWSTR domain = NULL; 00241 LPWSTR user = NULL; 00242 BOOL user_name_present = FALSE; 00243 SecKeychainAttributeInfo info; 00244 SecKeychainAttributeList *attr_list; 00245 UInt32 info_tags[] = { kSecServerItemAttr, kSecSecurityDomainItemAttr, kSecAccountItemAttr, 00246 kSecCommentItemAttr, kSecCreationDateItemAttr }; 00247 info.count = sizeof(info_tags)/sizeof(info_tags[0]); 00248 info.tag = info_tags; 00249 info.format = NULL; 00250 status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, &cred_blob_len, &cred_blob); 00251 if (status == errSecAuthFailed && !require_password) 00252 { 00253 cred_blob_len = 0; 00254 cred_blob = NULL; 00255 status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, &cred_blob_len, NULL); 00256 } 00257 if (status != noErr) 00258 { 00259 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status); 00260 return ERROR_NOT_FOUND; 00261 } 00262 00263 for (i = 0; i < attr_list->count; i++) 00264 if (attr_list->attr[i].tag == kSecAccountItemAttr && attr_list->attr[i].data) 00265 { 00266 user_name_present = TRUE; 00267 break; 00268 } 00269 if (!user_name_present) 00270 { 00271 WARN("no kSecAccountItemAttr for item\n"); 00272 return ERROR_NOT_FOUND; 00273 } 00274 00275 if (buffer) 00276 { 00277 credential->Flags = 0; 00278 credential->Type = CRED_TYPE_DOMAIN_PASSWORD; 00279 credential->TargetName = NULL; 00280 credential->Comment = NULL; 00281 memset(&credential->LastWritten, 0, sizeof(credential->LastWritten)); 00282 credential->CredentialBlobSize = 0; 00283 credential->CredentialBlob = NULL; 00284 credential->Persist = CRED_PERSIST_LOCAL_MACHINE; 00285 credential->AttributeCount = 0; 00286 credential->Attributes = NULL; 00287 credential->TargetAlias = NULL; 00288 credential->UserName = NULL; 00289 } 00290 for (i = 0; i < attr_list->count; i++) 00291 { 00292 switch (attr_list->attr[i].tag) 00293 { 00294 case kSecServerItemAttr: 00295 TRACE("kSecServerItemAttr: %.*s\n", (int)attr_list->attr[i].length, 00296 (char *)attr_list->attr[i].data); 00297 if (!attr_list->attr[i].data) continue; 00298 if (buffer) 00299 { 00300 INT str_len; 00301 credential->TargetName = (LPWSTR)buffer; 00302 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00303 attr_list->attr[i].length, (LPWSTR)buffer, 0xffff); 00304 credential->TargetName[str_len] = '\0'; 00305 buffer += (str_len + 1) * sizeof(WCHAR); 00306 *len += (str_len + 1) * sizeof(WCHAR); 00307 } 00308 else 00309 { 00310 INT str_len; 00311 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00312 attr_list->attr[i].length, NULL, 0); 00313 *len += (str_len + 1) * sizeof(WCHAR); 00314 } 00315 break; 00316 case kSecAccountItemAttr: 00317 { 00318 INT str_len; 00319 TRACE("kSecAccountItemAttr: %.*s\n", (int)attr_list->attr[i].length, 00320 (char *)attr_list->attr[i].data); 00321 if (!attr_list->attr[i].data) continue; 00322 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00323 attr_list->attr[i].length, NULL, 0); 00324 user = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR)); 00325 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00326 attr_list->attr[i].length, user, str_len); 00327 user[str_len] = '\0'; 00328 break; 00329 } 00330 case kSecCommentItemAttr: 00331 TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list->attr[i].length, 00332 (char *)attr_list->attr[i].data); 00333 if (!attr_list->attr[i].data) continue; 00334 if (buffer) 00335 { 00336 INT str_len; 00337 credential->Comment = (LPWSTR)buffer; 00338 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00339 attr_list->attr[i].length, (LPWSTR)buffer, 0xffff); 00340 credential->Comment[str_len] = '\0'; 00341 buffer += (str_len + 1) * sizeof(WCHAR); 00342 *len += (str_len + 1) * sizeof(WCHAR); 00343 } 00344 else 00345 { 00346 INT str_len; 00347 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00348 attr_list->attr[i].length, NULL, 0); 00349 *len += (str_len + 1) * sizeof(WCHAR); 00350 } 00351 break; 00352 case kSecSecurityDomainItemAttr: 00353 { 00354 INT str_len; 00355 TRACE("kSecSecurityDomainItemAttr: %.*s\n", (int)attr_list->attr[i].length, 00356 (char *)attr_list->attr[i].data); 00357 if (!attr_list->attr[i].data) continue; 00358 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00359 attr_list->attr[i].length, NULL, 0); 00360 domain = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR)); 00361 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data, 00362 attr_list->attr[i].length, domain, str_len); 00363 domain[str_len] = '\0'; 00364 break; 00365 } 00366 case kSecCreationDateItemAttr: 00367 TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list->attr[i].length, 00368 (char *)attr_list->attr[i].data); 00369 if (buffer) 00370 { 00371 LARGE_INTEGER win_time; 00372 struct tm tm; 00373 time_t time; 00374 memset(&tm, 0, sizeof(tm)); 00375 strptime(attr_list->attr[i].data, "%Y%m%d%H%M%SZ", &tm); 00376 time = mktime(&tm); 00377 RtlSecondsSince1970ToTime(time, &win_time); 00378 credential->LastWritten.dwLowDateTime = win_time.u.LowPart; 00379 credential->LastWritten.dwHighDateTime = win_time.u.HighPart; 00380 } 00381 break; 00382 } 00383 } 00384 00385 if (user) 00386 { 00387 INT str_len; 00388 if (buffer) 00389 credential->UserName = (LPWSTR)buffer; 00390 if (domain) 00391 { 00392 str_len = strlenW(domain); 00393 *len += (str_len + 1) * sizeof(WCHAR); 00394 if (buffer) 00395 { 00396 memcpy(credential->UserName, domain, str_len * sizeof(WCHAR)); 00397 /* FIXME: figure out when to use an '@' */ 00398 credential->UserName[str_len] = '\\'; 00399 buffer += (str_len + 1) * sizeof(WCHAR); 00400 } 00401 } 00402 str_len = strlenW(user); 00403 *len += (str_len + 1) * sizeof(WCHAR); 00404 if (buffer) 00405 { 00406 memcpy(buffer, user, (str_len + 1) * sizeof(WCHAR)); 00407 buffer += (str_len + 1) * sizeof(WCHAR); 00408 TRACE("UserName = %s\n", debugstr_w(credential->UserName)); 00409 } 00410 } 00411 HeapFree(GetProcessHeap(), 0, user); 00412 HeapFree(GetProcessHeap(), 0, domain); 00413 00414 if (cred_blob) 00415 { 00416 if (buffer) 00417 { 00418 INT str_len; 00419 credential->CredentialBlob = (BYTE *)buffer; 00420 str_len = MultiByteToWideChar(CP_UTF8, 0, cred_blob, cred_blob_len, 00421 (LPWSTR)buffer, 0xffff); 00422 credential->CredentialBlobSize = str_len * sizeof(WCHAR); 00423 buffer += str_len * sizeof(WCHAR); 00424 *len += str_len * sizeof(WCHAR); 00425 } 00426 else 00427 { 00428 INT str_len; 00429 str_len = MultiByteToWideChar(CP_UTF8, 0, cred_blob, cred_blob_len, 00430 NULL, 0); 00431 *len += str_len * sizeof(WCHAR); 00432 } 00433 } 00434 SecKeychainItemFreeAttributesAndData(attr_list, cred_blob); 00435 return ERROR_SUCCESS; 00436 } 00437 #endif 00438 00439 static DWORD write_credential_blob(HKEY hkey, LPCWSTR target_name, DWORD type, 00440 const BYTE key_data[KEY_SIZE], 00441 const BYTE *credential_blob, DWORD credential_blob_size) 00442 { 00443 LPBYTE encrypted_credential_blob; 00444 struct ustring data; 00445 struct ustring key; 00446 DWORD ret; 00447 00448 key.Length = key.MaximumLength = KEY_SIZE; 00449 key.Buffer = (unsigned char *)key_data; 00450 00451 encrypted_credential_blob = HeapAlloc(GetProcessHeap(), 0, credential_blob_size); 00452 if (!encrypted_credential_blob) return ERROR_OUTOFMEMORY; 00453 00454 memcpy(encrypted_credential_blob, credential_blob, credential_blob_size); 00455 data.Length = data.MaximumLength = credential_blob_size; 00456 data.Buffer = encrypted_credential_blob; 00457 SystemFunction032(&data, &key); 00458 00459 ret = RegSetValueExW(hkey, wszPasswordValue, 0, REG_BINARY, encrypted_credential_blob, credential_blob_size); 00460 HeapFree(GetProcessHeap(), 0, encrypted_credential_blob); 00461 00462 return ret; 00463 } 00464 00465 static DWORD registry_write_credential(HKEY hkey, const CREDENTIALW *credential, 00466 const BYTE key_data[KEY_SIZE], BOOL preserve_blob) 00467 { 00468 DWORD ret; 00469 FILETIME LastWritten; 00470 00471 GetSystemTimeAsFileTime(&LastWritten); 00472 00473 ret = RegSetValueExW(hkey, wszFlagsValue, 0, REG_DWORD, (LPVOID)&credential->Flags, 00474 sizeof(credential->Flags)); 00475 if (ret != ERROR_SUCCESS) return ret; 00476 ret = RegSetValueExW(hkey, wszTypeValue, 0, REG_DWORD, (LPVOID)&credential->Type, 00477 sizeof(credential->Type)); 00478 if (ret != ERROR_SUCCESS) return ret; 00479 ret = RegSetValueExW(hkey, NULL, 0, REG_SZ, (LPVOID)credential->TargetName, 00480 sizeof(WCHAR)*(strlenW(credential->TargetName)+1)); 00481 if (ret != ERROR_SUCCESS) return ret; 00482 if (credential->Comment) 00483 { 00484 ret = RegSetValueExW(hkey, wszCommentValue, 0, REG_SZ, (LPVOID)credential->Comment, 00485 sizeof(WCHAR)*(strlenW(credential->Comment)+1)); 00486 if (ret != ERROR_SUCCESS) return ret; 00487 } 00488 ret = RegSetValueExW(hkey, wszLastWrittenValue, 0, REG_BINARY, (LPVOID)&LastWritten, 00489 sizeof(LastWritten)); 00490 if (ret != ERROR_SUCCESS) return ret; 00491 ret = RegSetValueExW(hkey, wszPersistValue, 0, REG_DWORD, (LPVOID)&credential->Persist, 00492 sizeof(credential->Persist)); 00493 if (ret != ERROR_SUCCESS) return ret; 00494 /* FIXME: Attributes */ 00495 if (credential->TargetAlias) 00496 { 00497 ret = RegSetValueExW(hkey, wszTargetAliasValue, 0, REG_SZ, (LPVOID)credential->TargetAlias, 00498 sizeof(WCHAR)*(strlenW(credential->TargetAlias)+1)); 00499 if (ret != ERROR_SUCCESS) return ret; 00500 } 00501 if (credential->UserName) 00502 { 00503 ret = RegSetValueExW(hkey, wszUserNameValue, 0, REG_SZ, (LPVOID)credential->UserName, 00504 sizeof(WCHAR)*(strlenW(credential->UserName)+1)); 00505 if (ret != ERROR_SUCCESS) return ret; 00506 } 00507 if (!preserve_blob) 00508 { 00509 ret = write_credential_blob(hkey, credential->TargetName, credential->Type, 00510 key_data, credential->CredentialBlob, 00511 credential->CredentialBlobSize); 00512 } 00513 return ret; 00514 } 00515 00516 #ifdef __APPLE__ 00517 static DWORD mac_write_credential(const CREDENTIALW *credential, BOOL preserve_blob) 00518 { 00519 OSStatus status; 00520 SecKeychainItemRef keychain_item; 00521 char *username; 00522 char *domain = NULL; 00523 char *password; 00524 char *servername; 00525 UInt32 userlen; 00526 UInt32 domainlen = 0; 00527 UInt32 pwlen; 00528 UInt32 serverlen; 00529 LPCWSTR p; 00530 SecKeychainAttribute attrs[1]; 00531 SecKeychainAttributeList attr_list; 00532 00533 if (credential->Flags) 00534 FIXME("Flags 0x%x not written\n", credential->Flags); 00535 if (credential->Type != CRED_TYPE_DOMAIN_PASSWORD) 00536 FIXME("credential type of %d not supported\n", credential->Type); 00537 if (credential->Persist != CRED_PERSIST_LOCAL_MACHINE) 00538 FIXME("persist value of %d not supported\n", credential->Persist); 00539 if (credential->AttributeCount) 00540 FIXME("custom attributes not supported\n"); 00541 00542 p = strchrW(credential->UserName, '\\'); 00543 if (p) 00544 { 00545 domainlen = WideCharToMultiByte(CP_UTF8, 0, credential->UserName, 00546 p - credential->UserName, NULL, 0, NULL, NULL); 00547 domain = HeapAlloc(GetProcessHeap(), 0, (domainlen + 1) * sizeof(*domain)); 00548 WideCharToMultiByte(CP_UTF8, 0, credential->UserName, p - credential->UserName, 00549 domain, domainlen, NULL, NULL); 00550 domain[domainlen] = '\0'; 00551 p++; 00552 } 00553 else 00554 p = credential->UserName; 00555 userlen = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL); 00556 username = HeapAlloc(GetProcessHeap(), 0, userlen * sizeof(*username)); 00557 WideCharToMultiByte(CP_UTF8, 0, p, -1, username, userlen, NULL, NULL); 00558 00559 serverlen = WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, NULL, 0, NULL, NULL); 00560 servername = HeapAlloc(GetProcessHeap(), 0, serverlen * sizeof(*servername)); 00561 WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, servername, serverlen, NULL, NULL); 00562 pwlen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob, 00563 credential->CredentialBlobSize / sizeof(WCHAR), NULL, 0, NULL, NULL); 00564 password = HeapAlloc(GetProcessHeap(), 0, pwlen * sizeof(*domain)); 00565 WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob, 00566 credential->CredentialBlobSize / sizeof(WCHAR), password, pwlen, NULL, NULL); 00567 00568 TRACE("adding server %s, domain %s, username %s using Keychain\n", servername, domain, username); 00569 status = SecKeychainAddInternetPassword(NULL, strlen(servername), servername, 00570 strlen(domain), domain, strlen(username), 00571 username, 0, NULL, 0, 00572 0 /* no protocol */, 00573 kSecAuthenticationTypeDefault, 00574 strlen(password), password, &keychain_item); 00575 if (status != noErr) 00576 ERR("SecKeychainAddInternetPassword returned %ld\n", status); 00577 if (status == errSecDuplicateItem) 00578 { 00579 SecKeychainItemRef keychain_item; 00580 00581 status = SecKeychainFindInternetPassword(NULL, strlen(servername), servername, 00582 strlen(domain), domain, 00583 strlen(username), username, 00584 0, NULL /* any path */, 0, 00585 0 /* any protocol */, 00586 0 /* any authentication type */, 00587 0, NULL, &keychain_item); 00588 if (status != noErr) 00589 ERR("SecKeychainFindInternetPassword returned %ld\n", status); 00590 } 00591 HeapFree(GetProcessHeap(), 0, domain); 00592 HeapFree(GetProcessHeap(), 0, username); 00593 HeapFree(GetProcessHeap(), 0, servername); 00594 if (status != noErr) 00595 { 00596 HeapFree(GetProcessHeap(), 0, password); 00597 return ERROR_GEN_FAILURE; 00598 } 00599 if (credential->Comment) 00600 { 00601 attr_list.count = 1; 00602 attr_list.attr = attrs; 00603 attrs[0].tag = kSecCommentItemAttr; 00604 attrs[0].length = WideCharToMultiByte(CP_UTF8, 0, credential->Comment, -1, NULL, 0, NULL, NULL); 00605 if (attrs[0].length) attrs[0].length--; 00606 attrs[0].data = HeapAlloc(GetProcessHeap(), 0, attrs[0].length); 00607 WideCharToMultiByte(CP_UTF8, 0, credential->Comment, -1, attrs[0].data, attrs[0].length, NULL, NULL); 00608 } 00609 else 00610 { 00611 attr_list.count = 0; 00612 attr_list.attr = NULL; 00613 } 00614 status = SecKeychainItemModifyAttributesAndData(keychain_item, &attr_list, 00615 preserve_blob ? 0 : strlen(password), 00616 preserve_blob ? NULL : password); 00617 if (credential->Comment) 00618 HeapFree(GetProcessHeap(), 0, attrs[0].data); 00619 HeapFree(GetProcessHeap(), 0, password); 00620 /* FIXME: set TargetAlias attribute */ 00621 CFRelease(keychain_item); 00622 return ERROR_SUCCESS; 00623 } 00624 #endif 00625 00626 static DWORD open_cred_mgr_key(HKEY *hkey, BOOL open_for_write) 00627 { 00628 return RegCreateKeyExW(HKEY_CURRENT_USER, wszCredentialManagerKey, 0, 00629 NULL, REG_OPTION_NON_VOLATILE, 00630 KEY_READ | (open_for_write ? KEY_WRITE : 0), NULL, hkey, NULL); 00631 } 00632 00633 static DWORD get_cred_mgr_encryption_key(HKEY hkeyMgr, BYTE key_data[KEY_SIZE]) 00634 { 00635 static const BYTE my_key_data[KEY_SIZE] = { 0 }; 00636 DWORD type; 00637 DWORD count; 00638 FILETIME ft; 00639 ULONG seed; 00640 ULONG value; 00641 DWORD ret; 00642 00643 memcpy(key_data, my_key_data, KEY_SIZE); 00644 00645 count = KEY_SIZE; 00646 ret = RegQueryValueExW(hkeyMgr, wszEncryptionKeyValue, NULL, &type, key_data, 00647 &count); 00648 if (ret == ERROR_SUCCESS) 00649 { 00650 if (type != REG_BINARY) 00651 return ERROR_REGISTRY_CORRUPT; 00652 else 00653 return ERROR_SUCCESS; 00654 } 00655 if (ret != ERROR_FILE_NOT_FOUND) 00656 return ret; 00657 00658 GetSystemTimeAsFileTime(&ft); 00659 seed = ft.dwLowDateTime; 00660 value = RtlUniform(&seed); 00661 *(DWORD *)key_data = value; 00662 seed = ft.dwHighDateTime; 00663 value = RtlUniform(&seed); 00664 *(DWORD *)(key_data + 4) = value; 00665 00666 ret = RegSetValueExW(hkeyMgr, wszEncryptionKeyValue, 0, REG_BINARY, 00667 key_data, KEY_SIZE); 00668 if (ret == ERROR_ACCESS_DENIED) 00669 { 00670 ret = open_cred_mgr_key(&hkeyMgr, TRUE); 00671 if (ret == ERROR_SUCCESS) 00672 { 00673 ret = RegSetValueExW(hkeyMgr, wszEncryptionKeyValue, 0, REG_BINARY, 00674 key_data, KEY_SIZE); 00675 RegCloseKey(hkeyMgr); 00676 } 00677 } 00678 return ret; 00679 } 00680 00681 static LPWSTR get_key_name_for_target(LPCWSTR target_name, DWORD type) 00682 { 00683 static const WCHAR wszGenericPrefix[] = {'G','e','n','e','r','i','c',':',' ',0}; 00684 static const WCHAR wszDomPasswdPrefix[] = {'D','o','m','P','a','s','s','w','d',':',' ',0}; 00685 INT len; 00686 LPCWSTR prefix = NULL; 00687 LPWSTR key_name, p; 00688 00689 len = strlenW(target_name); 00690 if (type == CRED_TYPE_GENERIC) 00691 { 00692 prefix = wszGenericPrefix; 00693 len += sizeof(wszGenericPrefix)/sizeof(wszGenericPrefix[0]); 00694 } 00695 else 00696 { 00697 prefix = wszDomPasswdPrefix; 00698 len += sizeof(wszDomPasswdPrefix)/sizeof(wszDomPasswdPrefix[0]); 00699 } 00700 00701 key_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00702 if (!key_name) return NULL; 00703 00704 strcpyW(key_name, prefix); 00705 strcatW(key_name, target_name); 00706 00707 for (p = key_name; *p; p++) 00708 if (*p == '\\') *p = '_'; 00709 00710 return key_name; 00711 } 00712 00713 static BOOL credential_matches_filter(HKEY hkeyCred, LPCWSTR filter) 00714 { 00715 LPWSTR target_name; 00716 DWORD ret; 00717 DWORD type; 00718 DWORD count; 00719 LPCWSTR p; 00720 00721 if (!filter) return TRUE; 00722 00723 ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, NULL, &count); 00724 if (ret != ERROR_SUCCESS) 00725 return FALSE; 00726 else if (type != REG_SZ) 00727 return FALSE; 00728 00729 target_name = HeapAlloc(GetProcessHeap(), 0, count); 00730 if (!target_name) 00731 return FALSE; 00732 ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, (LPVOID)target_name, &count); 00733 if (ret != ERROR_SUCCESS || type != REG_SZ) 00734 { 00735 HeapFree(GetProcessHeap(), 0, target_name); 00736 return FALSE; 00737 } 00738 00739 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter), 00740 debugstr_w(target_name)); 00741 00742 p = strchrW(filter, '*'); 00743 ret = CompareStringW(GetThreadLocale(), 0, filter, 00744 (p && !p[1] ? p - filter : -1), target_name, 00745 (p && !p[1] ? p - filter : -1)) == CSTR_EQUAL; 00746 00747 HeapFree(GetProcessHeap(), 0, target_name); 00748 return ret; 00749 } 00750 00751 static DWORD registry_enumerate_credentials(HKEY hkeyMgr, LPCWSTR filter, 00752 LPWSTR target_name, 00753 DWORD target_name_len, BYTE key_data[KEY_SIZE], 00754 PCREDENTIALW *credentials, char **buffer, 00755 DWORD *len, DWORD *count) 00756 { 00757 DWORD i; 00758 DWORD ret; 00759 for (i = 0;; i++) 00760 { 00761 HKEY hkeyCred; 00762 ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1); 00763 if (ret == ERROR_NO_MORE_ITEMS) 00764 { 00765 ret = ERROR_SUCCESS; 00766 break; 00767 } 00768 else if (ret != ERROR_SUCCESS) 00769 { 00770 ret = ERROR_SUCCESS; 00771 continue; 00772 } 00773 TRACE("target_name = %s\n", debugstr_w(target_name)); 00774 ret = RegOpenKeyExW(hkeyMgr, target_name, 0, KEY_QUERY_VALUE, &hkeyCred); 00775 if (ret != ERROR_SUCCESS) 00776 { 00777 ret = ERROR_SUCCESS; 00778 continue; 00779 } 00780 if (!credential_matches_filter(hkeyCred, filter)) 00781 { 00782 RegCloseKey(hkeyCred); 00783 continue; 00784 } 00785 if (buffer) 00786 { 00787 *len = sizeof(CREDENTIALW); 00788 credentials[*count] = (PCREDENTIALW)*buffer; 00789 } 00790 else 00791 *len += sizeof(CREDENTIALW); 00792 ret = registry_read_credential(hkeyCred, buffer ? credentials[*count] : NULL, 00793 key_data, buffer ? *buffer + sizeof(CREDENTIALW) : NULL, 00794 len); 00795 RegCloseKey(hkeyCred); 00796 if (ret != ERROR_SUCCESS) break; 00797 if (buffer) *buffer += *len; 00798 (*count)++; 00799 } 00800 return ret; 00801 } 00802 00803 #ifdef __APPLE__ 00804 static DWORD mac_enumerate_credentials(LPCWSTR filter, PCREDENTIALW *credentials, 00805 char *buffer, DWORD *len, DWORD *count) 00806 { 00807 SecKeychainSearchRef search; 00808 SecKeychainItemRef item; 00809 OSStatus status; 00810 Boolean saved_user_interaction_allowed; 00811 DWORD ret; 00812 00813 SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed); 00814 SecKeychainSetUserInteractionAllowed(false); 00815 00816 status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search); 00817 if (status == noErr) 00818 { 00819 while (SecKeychainSearchCopyNext(search, &item) == noErr) 00820 { 00821 SecKeychainAttributeInfo info; 00822 SecKeychainAttributeList *attr_list; 00823 UInt32 info_tags[] = { kSecServerItemAttr }; 00824 info.count = sizeof(info_tags)/sizeof(info_tags[0]); 00825 info.tag = info_tags; 00826 info.format = NULL; 00827 status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL); 00828 if (status != noErr) 00829 { 00830 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status); 00831 continue; 00832 } 00833 if (buffer) 00834 { 00835 *len = sizeof(CREDENTIALW); 00836 credentials[*count] = (PCREDENTIALW)buffer; 00837 } 00838 else 00839 *len += sizeof(CREDENTIALW); 00840 if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr) continue; 00841 TRACE("server item: %.*s\n", (int)attr_list->attr[0].length, (char *)attr_list->attr[0].data); 00842 /* FIXME: filter based on attr_list->attr[0].data */ 00843 SecKeychainItemFreeAttributesAndData(attr_list, NULL); 00844 ret = mac_read_credential_from_item(item, FALSE, 00845 buffer ? credentials[*count] : NULL, 00846 buffer ? buffer + sizeof(CREDENTIALW) : NULL, 00847 len); 00848 CFRelease(item); 00849 if (ret == ERROR_SUCCESS) 00850 { 00851 (*count)++; 00852 if (buffer) buffer += *len; 00853 } 00854 } 00855 CFRelease(search); 00856 } 00857 else 00858 ERR("SecKeychainSearchCreateFromAttributes returned status %ld\n", status); 00859 SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed); 00860 return ERROR_SUCCESS; 00861 } 00862 00863 static DWORD mac_delete_credential(LPCWSTR TargetName) 00864 { 00865 OSStatus status; 00866 SecKeychainSearchRef search; 00867 status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search); 00868 if (status == noErr) 00869 { 00870 SecKeychainItemRef item; 00871 while (SecKeychainSearchCopyNext(search, &item) == noErr) 00872 { 00873 SecKeychainAttributeInfo info; 00874 SecKeychainAttributeList *attr_list; 00875 UInt32 info_tags[] = { kSecServerItemAttr }; 00876 LPWSTR target_name; 00877 INT str_len; 00878 info.count = sizeof(info_tags)/sizeof(info_tags[0]); 00879 info.tag = info_tags; 00880 info.format = NULL; 00881 status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL); 00882 if (status != noErr) 00883 { 00884 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status); 00885 continue; 00886 } 00887 if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr) 00888 { 00889 CFRelease(item); 00890 continue; 00891 } 00892 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, NULL, 0); 00893 target_name = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR)); 00894 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, target_name, str_len); 00895 /* nul terminate */ 00896 target_name[str_len] = '\0'; 00897 if (strcmpiW(TargetName, target_name)) 00898 { 00899 CFRelease(item); 00900 HeapFree(GetProcessHeap(), 0, target_name); 00901 continue; 00902 } 00903 HeapFree(GetProcessHeap(), 0, target_name); 00904 SecKeychainItemFreeAttributesAndData(attr_list, NULL); 00905 SecKeychainItemDelete(item); 00906 CFRelease(item); 00907 CFRelease(search); 00908 00909 return ERROR_SUCCESS; 00910 } 00911 CFRelease(search); 00912 } 00913 return ERROR_NOT_FOUND; 00914 } 00915 #endif 00916 00917 /****************************************************************************** 00918 * convert_PCREDENTIALW_to_PCREDENTIALA [internal] 00919 * 00920 * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes 00921 * 00922 */ 00923 00924 static INT convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW *CredentialW, PCREDENTIALA CredentialA, INT len) 00925 { 00926 char *buffer; 00927 INT string_len; 00928 INT needed = sizeof(CREDENTIALA); 00929 00930 if (!CredentialA) 00931 { 00932 if (CredentialW->TargetName) 00933 needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, NULL, 0, NULL, NULL); 00934 if (CredentialW->Comment) 00935 needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, NULL, 0, NULL, NULL); 00936 needed += CredentialW->CredentialBlobSize; 00937 if (CredentialW->TargetAlias) 00938 needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, NULL, 0, NULL, NULL); 00939 if (CredentialW->UserName) 00940 needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, NULL, 0, NULL, NULL); 00941 00942 return needed; 00943 } 00944 00945 00946 buffer = (char *)CredentialA + sizeof(CREDENTIALA); 00947 len -= sizeof(CREDENTIALA); 00948 CredentialA->Flags = CredentialW->Flags; 00949 CredentialA->Type = CredentialW->Type; 00950 00951 if (CredentialW->TargetName) 00952 { 00953 CredentialA->TargetName = buffer; 00954 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, buffer, len, NULL, NULL); 00955 buffer += string_len; 00956 needed += string_len; 00957 len -= string_len; 00958 } 00959 else 00960 CredentialA->TargetName = NULL; 00961 if (CredentialW->Comment) 00962 { 00963 CredentialA->Comment = buffer; 00964 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, buffer, len, NULL, NULL); 00965 buffer += string_len; 00966 needed += string_len; 00967 len -= string_len; 00968 } 00969 else 00970 CredentialA->Comment = NULL; 00971 CredentialA->LastWritten = CredentialW->LastWritten; 00972 CredentialA->CredentialBlobSize = CredentialW->CredentialBlobSize; 00973 if (CredentialW->CredentialBlobSize && (CredentialW->CredentialBlobSize <= len)) 00974 { 00975 CredentialA->CredentialBlob =(LPBYTE)buffer; 00976 memcpy(CredentialA->CredentialBlob, CredentialW->CredentialBlob, 00977 CredentialW->CredentialBlobSize); 00978 buffer += CredentialW->CredentialBlobSize; 00979 needed += CredentialW->CredentialBlobSize; 00980 len -= CredentialW->CredentialBlobSize; 00981 } 00982 else 00983 CredentialA->CredentialBlob = NULL; 00984 CredentialA->Persist = CredentialW->Persist; 00985 CredentialA->AttributeCount = 0; 00986 CredentialA->Attributes = NULL; /* FIXME */ 00987 if (CredentialW->TargetAlias) 00988 { 00989 CredentialA->TargetAlias = buffer; 00990 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, buffer, len, NULL, NULL); 00991 buffer += string_len; 00992 needed += string_len; 00993 len -= string_len; 00994 } 00995 else 00996 CredentialA->TargetAlias = NULL; 00997 if (CredentialW->UserName) 00998 { 00999 CredentialA->UserName = buffer; 01000 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, buffer, len, NULL, NULL); 01001 needed += string_len; 01002 } 01003 else 01004 CredentialA->UserName = NULL; 01005 01006 return needed; 01007 } 01008 01009 /****************************************************************************** 01010 * convert_PCREDENTIALA_to_PCREDENTIALW [internal] 01011 * 01012 * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes 01013 * 01014 */ 01015 static INT convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA *CredentialA, PCREDENTIALW CredentialW, INT len) 01016 { 01017 char *buffer; 01018 INT string_len; 01019 INT needed = sizeof(CREDENTIALW); 01020 01021 if (!CredentialW) 01022 { 01023 if (CredentialA->TargetName) 01024 needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, NULL, 0); 01025 if (CredentialA->Comment) 01026 needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, NULL, 0); 01027 needed += CredentialA->CredentialBlobSize; 01028 if (CredentialA->TargetAlias) 01029 needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, NULL, 0); 01030 if (CredentialA->UserName) 01031 needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, NULL, 0); 01032 01033 return needed; 01034 } 01035 01036 buffer = (char *)CredentialW + sizeof(CREDENTIALW); 01037 len -= sizeof(CREDENTIALW); 01038 CredentialW->Flags = CredentialA->Flags; 01039 CredentialW->Type = CredentialA->Type; 01040 if (CredentialA->TargetName) 01041 { 01042 CredentialW->TargetName = (LPWSTR)buffer; 01043 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, CredentialW->TargetName, len / sizeof(WCHAR)); 01044 buffer += sizeof(WCHAR) * string_len; 01045 needed += sizeof(WCHAR) * string_len; 01046 len -= sizeof(WCHAR) * string_len; 01047 } 01048 else 01049 CredentialW->TargetName = NULL; 01050 if (CredentialA->Comment) 01051 { 01052 CredentialW->Comment = (LPWSTR)buffer; 01053 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, CredentialW->Comment, len / sizeof(WCHAR)); 01054 buffer += sizeof(WCHAR) * string_len; 01055 needed += sizeof(WCHAR) * string_len; 01056 len -= sizeof(WCHAR) * string_len; 01057 } 01058 else 01059 CredentialW->Comment = NULL; 01060 CredentialW->LastWritten = CredentialA->LastWritten; 01061 CredentialW->CredentialBlobSize = CredentialA->CredentialBlobSize; 01062 if (CredentialA->CredentialBlobSize) 01063 { 01064 CredentialW->CredentialBlob =(LPBYTE)buffer; 01065 memcpy(CredentialW->CredentialBlob, CredentialA->CredentialBlob, 01066 CredentialA->CredentialBlobSize); 01067 buffer += CredentialA->CredentialBlobSize; 01068 needed += CredentialA->CredentialBlobSize; 01069 len -= CredentialA->CredentialBlobSize; 01070 } 01071 else 01072 CredentialW->CredentialBlob = NULL; 01073 CredentialW->Persist = CredentialA->Persist; 01074 CredentialW->AttributeCount = 0; 01075 CredentialW->Attributes = NULL; /* FIXME */ 01076 if (CredentialA->TargetAlias) 01077 { 01078 CredentialW->TargetAlias = (LPWSTR)buffer; 01079 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, CredentialW->TargetAlias, len / sizeof(WCHAR)); 01080 buffer += sizeof(WCHAR) * string_len; 01081 needed += sizeof(WCHAR) * string_len; 01082 len -= sizeof(WCHAR) * string_len; 01083 } 01084 else 01085 CredentialW->TargetAlias = NULL; 01086 if (CredentialA->UserName) 01087 { 01088 CredentialW->UserName = (LPWSTR)buffer; 01089 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, CredentialW->UserName, len / sizeof(WCHAR)); 01090 needed += sizeof(WCHAR) * string_len; 01091 } 01092 else 01093 CredentialW->UserName = NULL; 01094 01095 return needed; 01096 } 01097 01098 /****************************************************************************** 01099 * CredDeleteA [ADVAPI32.@] 01100 */ 01101 BOOL WINAPI CredDeleteA(LPCSTR TargetName, DWORD Type, DWORD Flags) 01102 { 01103 LPWSTR TargetNameW; 01104 DWORD len; 01105 BOOL ret; 01106 01107 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName), Type, Flags); 01108 01109 if (!TargetName) 01110 { 01111 SetLastError(ERROR_INVALID_PARAMETER); 01112 return FALSE; 01113 } 01114 01115 len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0); 01116 TargetNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 01117 if (!TargetNameW) 01118 { 01119 SetLastError(ERROR_OUTOFMEMORY); 01120 return FALSE; 01121 } 01122 MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len); 01123 01124 ret = CredDeleteW(TargetNameW, Type, Flags); 01125 01126 HeapFree(GetProcessHeap(), 0, TargetNameW); 01127 01128 return ret; 01129 } 01130 01131 /****************************************************************************** 01132 * CredDeleteW [ADVAPI32.@] 01133 */ 01134 BOOL WINAPI CredDeleteW(LPCWSTR TargetName, DWORD Type, DWORD Flags) 01135 { 01136 HKEY hkeyMgr; 01137 DWORD ret; 01138 LPWSTR key_name; 01139 01140 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName), Type, Flags); 01141 01142 if (!TargetName) 01143 { 01144 SetLastError(ERROR_INVALID_PARAMETER); 01145 return FALSE; 01146 } 01147 01148 if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD) 01149 { 01150 FIXME("unhandled type %d\n", Type); 01151 SetLastError(ERROR_INVALID_PARAMETER); 01152 return FALSE; 01153 } 01154 01155 if (Flags) 01156 { 01157 FIXME("unhandled flags 0x%x\n", Flags); 01158 SetLastError(ERROR_INVALID_FLAGS); 01159 return FALSE; 01160 } 01161 01162 #ifdef __APPLE__ 01163 if (Type == CRED_TYPE_DOMAIN_PASSWORD) 01164 { 01165 ret = mac_delete_credential(TargetName); 01166 if (ret == ERROR_SUCCESS) 01167 return TRUE; 01168 } 01169 #endif 01170 01171 ret = open_cred_mgr_key(&hkeyMgr, TRUE); 01172 if (ret != ERROR_SUCCESS) 01173 { 01174 WARN("couldn't open/create manager key, error %d\n", ret); 01175 SetLastError(ERROR_NO_SUCH_LOGON_SESSION); 01176 return FALSE; 01177 } 01178 01179 key_name = get_key_name_for_target(TargetName, Type); 01180 ret = RegDeleteKeyW(hkeyMgr, key_name); 01181 HeapFree(GetProcessHeap(), 0, key_name); 01182 RegCloseKey(hkeyMgr); 01183 if (ret != ERROR_SUCCESS) 01184 { 01185 SetLastError(ERROR_NOT_FOUND); 01186 return FALSE; 01187 } 01188 01189 return TRUE; 01190 } 01191 01192 /****************************************************************************** 01193 * CredEnumerateA [ADVAPI32.@] 01194 */ 01195 BOOL WINAPI CredEnumerateA(LPCSTR Filter, DWORD Flags, DWORD *Count, 01196 PCREDENTIALA **Credentials) 01197 { 01198 LPWSTR FilterW; 01199 PCREDENTIALW *CredentialsW; 01200 DWORD i; 01201 INT len; 01202 INT needed; 01203 char *buffer; 01204 01205 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter), Flags, Count, Credentials); 01206 01207 if (Filter) 01208 { 01209 len = MultiByteToWideChar(CP_ACP, 0, Filter, -1, NULL, 0); 01210 FilterW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 01211 if (!FilterW) 01212 { 01213 SetLastError(ERROR_OUTOFMEMORY); 01214 return FALSE; 01215 } 01216 MultiByteToWideChar(CP_ACP, 0, Filter, -1, FilterW, len); 01217 } 01218 else 01219 FilterW = NULL; 01220 01221 if (!CredEnumerateW(FilterW, Flags, Count, &CredentialsW)) 01222 { 01223 HeapFree(GetProcessHeap(), 0, FilterW); 01224 return FALSE; 01225 } 01226 HeapFree(GetProcessHeap(), 0, FilterW); 01227 01228 len = *Count * sizeof(PCREDENTIALA); 01229 for (i = 0; i < *Count; i++) 01230 len += convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, 0); 01231 01232 *Credentials = HeapAlloc(GetProcessHeap(), 0, len); 01233 if (!*Credentials) 01234 { 01235 CredFree(CredentialsW); 01236 SetLastError(ERROR_OUTOFMEMORY); 01237 return FALSE; 01238 } 01239 01240 buffer = (char *)&(*Credentials)[*Count]; 01241 len -= *Count * sizeof(PCREDENTIALA); 01242 for (i = 0; i < *Count; i++) 01243 { 01244 (*Credentials)[i] = (PCREDENTIALA)buffer; 01245 needed = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], len); 01246 buffer += needed; 01247 len -= needed; 01248 } 01249 01250 CredFree(CredentialsW); 01251 01252 return TRUE; 01253 } 01254 01255 /****************************************************************************** 01256 * CredEnumerateW [ADVAPI32.@] 01257 */ 01258 BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count, 01259 PCREDENTIALW **Credentials) 01260 { 01261 HKEY hkeyMgr; 01262 DWORD ret; 01263 LPWSTR target_name; 01264 DWORD target_name_len; 01265 DWORD len; 01266 char *buffer; 01267 BYTE key_data[KEY_SIZE]; 01268 01269 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter), Flags, Count, Credentials); 01270 01271 if (Flags) 01272 { 01273 SetLastError(ERROR_INVALID_FLAGS); 01274 return FALSE; 01275 } 01276 01277 ret = open_cred_mgr_key(&hkeyMgr, FALSE); 01278 if (ret != ERROR_SUCCESS) 01279 { 01280 WARN("couldn't open/create manager key, error %d\n", ret); 01281 SetLastError(ERROR_NO_SUCH_LOGON_SESSION); 01282 return FALSE; 01283 } 01284 01285 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data); 01286 if (ret != ERROR_SUCCESS) 01287 { 01288 RegCloseKey(hkeyMgr); 01289 SetLastError(ret); 01290 return FALSE; 01291 } 01292 01293 ret = RegQueryInfoKeyW(hkeyMgr, NULL, NULL, NULL, NULL, &target_name_len, NULL, NULL, NULL, NULL, NULL, NULL); 01294 if (ret != ERROR_SUCCESS) 01295 { 01296 RegCloseKey(hkeyMgr); 01297 SetLastError(ret); 01298 return FALSE; 01299 } 01300 01301 target_name = HeapAlloc(GetProcessHeap(), 0, (target_name_len+1)*sizeof(WCHAR)); 01302 if (!target_name) 01303 { 01304 RegCloseKey(hkeyMgr); 01305 SetLastError(ERROR_OUTOFMEMORY); 01306 return FALSE; 01307 } 01308 01309 *Count = 0; 01310 len = 0; 01311 ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, target_name_len, 01312 key_data, NULL, NULL, &len, Count); 01313 #ifdef __APPLE__ 01314 if (ret == ERROR_SUCCESS) 01315 ret = mac_enumerate_credentials(Filter, NULL, NULL, &len, Count); 01316 #endif 01317 if (ret == ERROR_SUCCESS && *Count == 0) 01318 ret = ERROR_NOT_FOUND; 01319 if (ret != ERROR_SUCCESS) 01320 { 01321 HeapFree(GetProcessHeap(), 0, target_name); 01322 RegCloseKey(hkeyMgr); 01323 SetLastError(ret); 01324 return FALSE; 01325 } 01326 len += *Count * sizeof(PCREDENTIALW); 01327 01328 if (ret == ERROR_SUCCESS) 01329 { 01330 buffer = HeapAlloc(GetProcessHeap(), 0, len); 01331 *Credentials = (PCREDENTIALW *)buffer; 01332 if (buffer) 01333 { 01334 buffer += *Count * sizeof(PCREDENTIALW); 01335 *Count = 0; 01336 ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, 01337 target_name_len, key_data, 01338 *Credentials, &buffer, &len, 01339 Count); 01340 #ifdef __APPLE__ 01341 if (ret == ERROR_SUCCESS) 01342 ret = mac_enumerate_credentials(Filter, *Credentials, 01343 buffer, &len, Count); 01344 #endif 01345 } 01346 else 01347 ret = ERROR_OUTOFMEMORY; 01348 } 01349 01350 HeapFree(GetProcessHeap(), 0, target_name); 01351 RegCloseKey(hkeyMgr); 01352 01353 if (ret != ERROR_SUCCESS) 01354 { 01355 SetLastError(ret); 01356 return FALSE; 01357 } 01358 return TRUE; 01359 } 01360 01361 /****************************************************************************** 01362 * CredFree [ADVAPI32.@] 01363 */ 01364 VOID WINAPI CredFree(PVOID Buffer) 01365 { 01366 HeapFree(GetProcessHeap(), 0, Buffer); 01367 } 01368 01369 /****************************************************************************** 01370 * CredReadA [ADVAPI32.@] 01371 */ 01372 BOOL WINAPI CredReadA(LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *Credential) 01373 { 01374 LPWSTR TargetNameW; 01375 PCREDENTIALW CredentialW; 01376 INT len; 01377 01378 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName), Type, Flags, Credential); 01379 01380 if (!TargetName) 01381 { 01382 SetLastError(ERROR_INVALID_PARAMETER); 01383 return FALSE; 01384 } 01385 01386 len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0); 01387 TargetNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 01388 if (!TargetNameW) 01389 { 01390 SetLastError(ERROR_OUTOFMEMORY); 01391 return FALSE; 01392 } 01393 MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len); 01394 01395 if (!CredReadW(TargetNameW, Type, Flags, &CredentialW)) 01396 { 01397 HeapFree(GetProcessHeap(), 0, TargetNameW); 01398 return FALSE; 01399 } 01400 HeapFree(GetProcessHeap(), 0, TargetNameW); 01401 01402 len = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, NULL, 0); 01403 *Credential = HeapAlloc(GetProcessHeap(), 0, len); 01404 if (!*Credential) 01405 { 01406 SetLastError(ERROR_OUTOFMEMORY); 01407 return FALSE; 01408 } 01409 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, *Credential, len); 01410 01411 CredFree(CredentialW); 01412 01413 return TRUE; 01414 } 01415 01416 /****************************************************************************** 01417 * CredReadW [ADVAPI32.@] 01418 */ 01419 BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential) 01420 { 01421 HKEY hkeyMgr; 01422 HKEY hkeyCred; 01423 DWORD ret; 01424 LPWSTR key_name; 01425 DWORD len; 01426 BYTE key_data[KEY_SIZE]; 01427 01428 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName), Type, Flags, Credential); 01429 01430 if (!TargetName) 01431 { 01432 SetLastError(ERROR_INVALID_PARAMETER); 01433 return FALSE; 01434 } 01435 01436 if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD) 01437 { 01438 FIXME("unhandled type %d\n", Type); 01439 SetLastError(ERROR_INVALID_PARAMETER); 01440 return FALSE; 01441 } 01442 01443 if (Flags) 01444 { 01445 FIXME("unhandled flags 0x%x\n", Flags); 01446 SetLastError(ERROR_INVALID_FLAGS); 01447 return FALSE; 01448 } 01449 01450 #ifdef __APPLE__ 01451 if (Type == CRED_TYPE_DOMAIN_PASSWORD) 01452 { 01453 OSStatus status; 01454 SecKeychainSearchRef search; 01455 status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search); 01456 if (status == noErr) 01457 { 01458 SecKeychainItemRef item; 01459 while (SecKeychainSearchCopyNext(search, &item) == noErr) 01460 { 01461 SecKeychainAttributeInfo info; 01462 SecKeychainAttributeList *attr_list; 01463 UInt32 info_tags[] = { kSecServerItemAttr }; 01464 LPWSTR target_name; 01465 INT str_len; 01466 info.count = sizeof(info_tags)/sizeof(info_tags[0]); 01467 info.tag = info_tags; 01468 info.format = NULL; 01469 status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL); 01470 len = sizeof(**Credential); 01471 if (status != noErr) 01472 { 01473 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status); 01474 continue; 01475 } 01476 if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr) 01477 { 01478 CFRelease(item); 01479 continue; 01480 } 01481 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, NULL, 0); 01482 target_name = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR)); 01483 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, target_name, str_len); 01484 /* nul terminate */ 01485 target_name[str_len] = '\0'; 01486 if (strcmpiW(TargetName, target_name)) 01487 { 01488 CFRelease(item); 01489 HeapFree(GetProcessHeap(), 0, target_name); 01490 continue; 01491 } 01492 HeapFree(GetProcessHeap(), 0, target_name); 01493 SecKeychainItemFreeAttributesAndData(attr_list, NULL); 01494 ret = mac_read_credential_from_item(item, TRUE, NULL, NULL, &len); 01495 if (ret == ERROR_SUCCESS) 01496 { 01497 *Credential = HeapAlloc(GetProcessHeap(), 0, len); 01498 if (*Credential) 01499 { 01500 len = sizeof(**Credential); 01501 ret = mac_read_credential_from_item(item, TRUE, *Credential, 01502 (char *)(*Credential + 1), &len); 01503 } 01504 else 01505 ret = ERROR_OUTOFMEMORY; 01506 CFRelease(item); 01507 CFRelease(search); 01508 if (ret != ERROR_SUCCESS) 01509 { 01510 SetLastError(ret); 01511 return FALSE; 01512 } 01513 return TRUE; 01514 } 01515 CFRelease(item); 01516 } 01517 CFRelease(search); 01518 } 01519 } 01520 #endif 01521 01522 ret = open_cred_mgr_key(&hkeyMgr, FALSE); 01523 if (ret != ERROR_SUCCESS) 01524 { 01525 WARN("couldn't open/create manager key, error %d\n", ret); 01526 SetLastError(ERROR_NO_SUCH_LOGON_SESSION); 01527 return FALSE; 01528 } 01529 01530 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data); 01531 if (ret != ERROR_SUCCESS) 01532 { 01533 RegCloseKey(hkeyMgr); 01534 SetLastError(ret); 01535 return FALSE; 01536 } 01537 01538 key_name = get_key_name_for_target(TargetName, Type); 01539 ret = RegOpenKeyExW(hkeyMgr, key_name, 0, KEY_QUERY_VALUE, &hkeyCred); 01540 HeapFree(GetProcessHeap(), 0, key_name); 01541 if (ret != ERROR_SUCCESS) 01542 { 01543 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName)); 01544 SetLastError(ERROR_NOT_FOUND); 01545 return FALSE; 01546 } 01547 01548 len = sizeof(**Credential); 01549 ret = registry_read_credential(hkeyCred, NULL, key_data, NULL, &len); 01550 if (ret == ERROR_SUCCESS) 01551 { 01552 *Credential = HeapAlloc(GetProcessHeap(), 0, len); 01553 if (*Credential) 01554 { 01555 len = sizeof(**Credential); 01556 ret = registry_read_credential(hkeyCred, *Credential, key_data, 01557 (char *)(*Credential + 1), &len); 01558 } 01559 else 01560 ret = ERROR_OUTOFMEMORY; 01561 } 01562 01563 RegCloseKey(hkeyCred); 01564 RegCloseKey(hkeyMgr); 01565 01566 if (ret != ERROR_SUCCESS) 01567 { 01568 SetLastError(ret); 01569 return FALSE; 01570 } 01571 return TRUE; 01572 } 01573 01574 /****************************************************************************** 01575 * CredReadDomainCredentialsA [ADVAPI32.@] 01576 */ 01577 BOOL WINAPI CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation, 01578 DWORD Flags, DWORD *Size, PCREDENTIALA **Credentials) 01579 { 01580 PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW; 01581 INT len, i; 01582 WCHAR *buffer, *end; 01583 BOOL ret; 01584 PCREDENTIALW* CredentialsW; 01585 01586 TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation, Flags, Size, Credentials); 01587 01588 /* follow Windows behavior - do not test for NULL, initialize early */ 01589 *Size = 0; 01590 *Credentials = NULL; 01591 01592 if (!TargetInformation) 01593 { 01594 SetLastError(ERROR_INVALID_PARAMETER); 01595 return FALSE; 01596 } 01597 01598 len = sizeof(*TargetInformationW); 01599 if (TargetInformation->TargetName) 01600 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->TargetName, -1, NULL, 0) * sizeof(WCHAR); 01601 if (TargetInformation->NetbiosServerName) 01602 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosServerName, -1, NULL, 0) * sizeof(WCHAR); 01603 if (TargetInformation->DnsServerName) 01604 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsServerName, -1, NULL, 0) * sizeof(WCHAR); 01605 if (TargetInformation->NetbiosDomainName) 01606 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosDomainName, -1, NULL, 0) * sizeof(WCHAR); 01607 if (TargetInformation->DnsDomainName) 01608 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsDomainName, -1, NULL, 0) * sizeof(WCHAR); 01609 if (TargetInformation->DnsTreeName) 01610 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsTreeName, -1, NULL, 0) * sizeof(WCHAR); 01611 if (TargetInformation->PackageName) 01612 len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->PackageName, -1, NULL, 0) * sizeof(WCHAR); 01613 01614 TargetInformationW = HeapAlloc(GetProcessHeap(), 0, len); 01615 if (!TargetInformationW) 01616 { 01617 SetLastError(ERROR_OUTOFMEMORY); 01618 return FALSE; 01619 } 01620 buffer = (WCHAR*)(TargetInformationW + 1); 01621 end = (WCHAR *)((char *)TargetInformationW + len); 01622 01623 if (TargetInformation->TargetName) 01624 { 01625 TargetInformationW->TargetName = buffer; 01626 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->TargetName, -1, 01627 TargetInformationW->TargetName, end - buffer); 01628 } else 01629 TargetInformationW->TargetName = NULL; 01630 01631 if (TargetInformation->NetbiosServerName) 01632 { 01633 TargetInformationW->NetbiosServerName = buffer; 01634 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosServerName, -1, 01635 TargetInformationW->NetbiosServerName, end - buffer); 01636 } else 01637 TargetInformationW->NetbiosServerName = NULL; 01638 01639 if (TargetInformation->DnsServerName) 01640 { 01641 TargetInformationW->DnsServerName = buffer; 01642 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsServerName, -1, 01643 TargetInformationW->DnsServerName, end - buffer); 01644 } else 01645 TargetInformationW->DnsServerName = NULL; 01646 01647 if (TargetInformation->NetbiosDomainName) 01648 { 01649 TargetInformationW->NetbiosDomainName = buffer; 01650 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosDomainName, -1, 01651 TargetInformationW->NetbiosDomainName, end - buffer); 01652 } else 01653 TargetInformationW->NetbiosDomainName = NULL; 01654 01655 if (TargetInformation->DnsDomainName) 01656 { 01657 TargetInformationW->DnsDomainName = buffer; 01658 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsDomainName, -1, 01659 TargetInformationW->DnsDomainName, end - buffer); 01660 } else 01661 TargetInformationW->DnsDomainName = NULL; 01662 01663 if (TargetInformation->DnsTreeName) 01664 { 01665 TargetInformationW->DnsTreeName = buffer; 01666 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsTreeName, -1, 01667 TargetInformationW->DnsTreeName, end - buffer); 01668 } else 01669 TargetInformationW->DnsTreeName = NULL; 01670 01671 if (TargetInformation->PackageName) 01672 { 01673 TargetInformationW->PackageName = buffer; 01674 buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->PackageName, -1, 01675 TargetInformationW->PackageName, end - buffer); 01676 } else 01677 TargetInformationW->PackageName = NULL; 01678 01679 TargetInformationW->Flags = TargetInformation->Flags; 01680 TargetInformationW->CredTypeCount = TargetInformation->CredTypeCount; 01681 TargetInformationW->CredTypes = TargetInformation->CredTypes; 01682 01683 ret = CredReadDomainCredentialsW(TargetInformationW, Flags, Size, &CredentialsW); 01684 01685 HeapFree(GetProcessHeap(), 0, TargetInformationW); 01686 01687 if (ret) 01688 { 01689 char *buf; 01690 INT needed; 01691 01692 len = *Size * sizeof(PCREDENTIALA); 01693 for (i = 0; i < *Size; i++) 01694 len += convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, 0); 01695 01696 *Credentials = HeapAlloc(GetProcessHeap(), 0, len); 01697 if (!*Credentials) 01698 { 01699 CredFree(CredentialsW); 01700 SetLastError(ERROR_OUTOFMEMORY); 01701 return FALSE; 01702 } 01703 01704 buf = (char *)&(*Credentials)[*Size]; 01705 len -= *Size * sizeof(PCREDENTIALA); 01706 for (i = 0; i < *Size; i++) 01707 { 01708 (*Credentials)[i] = (PCREDENTIALA)buf; 01709 needed = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], len); 01710 buf += needed; 01711 len -= needed; 01712 } 01713 01714 CredFree(CredentialsW); 01715 } 01716 return ret; 01717 } 01718 01719 /****************************************************************************** 01720 * CredReadDomainCredentialsW [ADVAPI32.@] 01721 */ 01722 BOOL WINAPI CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation, DWORD Flags, 01723 DWORD *Size, PCREDENTIALW **Credentials) 01724 { 01725 FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation, Flags, Size, Credentials); 01726 01727 /* follow Windows behavior - do not test for NULL, initialize early */ 01728 *Size = 0; 01729 *Credentials = NULL; 01730 if (!TargetInformation) 01731 { 01732 SetLastError(ERROR_INVALID_PARAMETER); 01733 return FALSE; 01734 } 01735 01736 SetLastError(ERROR_NOT_FOUND); 01737 return FALSE; 01738 } 01739 01740 /****************************************************************************** 01741 * CredWriteA [ADVAPI32.@] 01742 */ 01743 BOOL WINAPI CredWriteA(PCREDENTIALA Credential, DWORD Flags) 01744 { 01745 BOOL ret; 01746 INT len; 01747 PCREDENTIALW CredentialW; 01748 01749 TRACE("(%p, 0x%x)\n", Credential, Flags); 01750 01751 if (!Credential || !Credential->TargetName) 01752 { 01753 SetLastError(ERROR_INVALID_PARAMETER); 01754 return FALSE; 01755 } 01756 01757 len = convert_PCREDENTIALA_to_PCREDENTIALW(Credential, NULL, 0); 01758 CredentialW = HeapAlloc(GetProcessHeap(), 0, len); 01759 if (!CredentialW) 01760 { 01761 SetLastError(ERROR_OUTOFMEMORY); 01762 return FALSE; 01763 } 01764 01765 convert_PCREDENTIALA_to_PCREDENTIALW(Credential, CredentialW, len); 01766 01767 ret = CredWriteW(CredentialW, Flags); 01768 01769 HeapFree(GetProcessHeap(), 0, CredentialW); 01770 01771 return ret; 01772 } 01773 01774 /****************************************************************************** 01775 * CredWriteW [ADVAPI32.@] 01776 */ 01777 BOOL WINAPI CredWriteW(PCREDENTIALW Credential, DWORD Flags) 01778 { 01779 HKEY hkeyMgr; 01780 HKEY hkeyCred; 01781 DWORD ret; 01782 LPWSTR key_name; 01783 BYTE key_data[KEY_SIZE]; 01784 01785 TRACE("(%p, 0x%x)\n", Credential, Flags); 01786 01787 if (!Credential || !Credential->TargetName) 01788 { 01789 SetLastError(ERROR_INVALID_PARAMETER); 01790 return FALSE; 01791 } 01792 01793 if (Flags & ~CRED_PRESERVE_CREDENTIAL_BLOB) 01794 { 01795 FIXME("unhandled flags 0x%x\n", Flags); 01796 SetLastError(ERROR_INVALID_FLAGS); 01797 return FALSE; 01798 } 01799 01800 if (Credential->Type != CRED_TYPE_GENERIC && Credential->Type != CRED_TYPE_DOMAIN_PASSWORD) 01801 { 01802 FIXME("unhandled type %d\n", Credential->Type); 01803 SetLastError(ERROR_INVALID_PARAMETER); 01804 return FALSE; 01805 } 01806 01807 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential->TargetName)); 01808 TRACE("Credential->UserName = %s\n", debugstr_w(Credential->UserName)); 01809 01810 if (Credential->Type == CRED_TYPE_DOMAIN_PASSWORD) 01811 { 01812 if (!Credential->UserName || 01813 (!strchrW(Credential->UserName, '\\') && !strchrW(Credential->UserName, '@'))) 01814 { 01815 ERR("bad username %s\n", debugstr_w(Credential->UserName)); 01816 SetLastError(ERROR_BAD_USERNAME); 01817 return FALSE; 01818 } 01819 } 01820 01821 #ifdef __APPLE__ 01822 if (!Credential->AttributeCount && 01823 Credential->Type == CRED_TYPE_DOMAIN_PASSWORD && 01824 (Credential->Persist == CRED_PERSIST_LOCAL_MACHINE || Credential->Persist == CRED_PERSIST_ENTERPRISE)) 01825 { 01826 ret = mac_write_credential(Credential, Flags & CRED_PRESERVE_CREDENTIAL_BLOB); 01827 if (ret != ERROR_SUCCESS) 01828 { 01829 SetLastError(ret); 01830 return FALSE; 01831 } 01832 return TRUE; 01833 } 01834 #endif 01835 01836 ret = open_cred_mgr_key(&hkeyMgr, FALSE); 01837 if (ret != ERROR_SUCCESS) 01838 { 01839 WARN("couldn't open/create manager key, error %d\n", ret); 01840 SetLastError(ERROR_NO_SUCH_LOGON_SESSION); 01841 return FALSE; 01842 } 01843 01844 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data); 01845 if (ret != ERROR_SUCCESS) 01846 { 01847 RegCloseKey(hkeyMgr); 01848 SetLastError(ret); 01849 return FALSE; 01850 } 01851 01852 key_name = get_key_name_for_target(Credential->TargetName, Credential->Type); 01853 ret = RegCreateKeyExW(hkeyMgr, key_name, 0, NULL, 01854 Credential->Persist == CRED_PERSIST_SESSION ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE, 01855 KEY_READ|KEY_WRITE, NULL, &hkeyCred, NULL); 01856 HeapFree(GetProcessHeap(), 0, key_name); 01857 if (ret != ERROR_SUCCESS) 01858 { 01859 TRACE("credentials for target name %s not found\n", 01860 debugstr_w(Credential->TargetName)); 01861 SetLastError(ERROR_NOT_FOUND); 01862 return FALSE; 01863 } 01864 01865 ret = registry_write_credential(hkeyCred, Credential, key_data, 01866 Flags & CRED_PRESERVE_CREDENTIAL_BLOB); 01867 01868 RegCloseKey(hkeyCred); 01869 RegCloseKey(hkeyMgr); 01870 01871 if (ret != ERROR_SUCCESS) 01872 { 01873 SetLastError(ret); 01874 return FALSE; 01875 } 01876 return TRUE; 01877 } 01878 01879 /****************************************************************************** 01880 * CredGetSessionTypes [ADVAPI32.@] 01881 */ 01882 BOOL WINAPI CredGetSessionTypes(DWORD persistCount, LPDWORD persists) 01883 { 01884 TRACE("(%u, %p)\n", persistCount, persists); 01885 01886 memset(persists, CRED_PERSIST_NONE, persistCount*sizeof(*persists)); 01887 if (CRED_TYPE_GENERIC < persistCount) 01888 { 01889 persists[CRED_TYPE_GENERIC] = CRED_PERSIST_ENTERPRISE; 01890 01891 if (CRED_TYPE_DOMAIN_PASSWORD < persistCount) 01892 { 01893 persists[CRED_TYPE_DOMAIN_PASSWORD] = CRED_PERSIST_ENTERPRISE; 01894 } 01895 } 01896 return TRUE; 01897 } 01898 01899 BOOL 01900 WINAPI 01901 CredWriteDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInfo, 01902 PCREDENTIALW Credential, 01903 DWORD Flags) 01904 { 01905 WARN("Not implemented\n"); 01906 return FALSE; 01907 } 01908 01909 BOOL 01910 WINAPI 01911 CredWriteDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInfo, 01912 PCREDENTIALA Credential, 01913 DWORD Flags) 01914 { 01915 WARN("Not implemented\n"); 01916 return FALSE; 01917 } 01918 01919 BOOL 01920 WINAPI 01921 CredUnmarshalCredentialW(LPCWSTR MarshaledCredential, 01922 PCRED_MARSHAL_TYPE CredType, 01923 PVOID *Credential) 01924 { 01925 WARN("Not implemented\n"); 01926 return FALSE; 01927 } 01928 01929 BOOL 01930 WINAPI 01931 CredUnmarshalCredentialA(LPCSTR MarshaledCredential, 01932 PCRED_MARSHAL_TYPE CredType, 01933 PVOID *Credential) 01934 { 01935 WARN("Not implemented\n"); 01936 return FALSE; 01937 } Generated on Sat May 26 2012 04:21:12 for ReactOS by
1.7.6.1
|