Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensip.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2002 Mike McCormack for CodeWeavers 00003 * Copyright 2005-2008 Juan Lang 00004 * Copyright 2006 Paul Vriens 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 <stdarg.h> 00022 #include <stdio.h> 00023 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "wincrypt.h" 00027 #include "winreg.h" 00028 #include "winnls.h" 00029 #include "mssip.h" 00030 #include "winuser.h" 00031 00032 #include "wine/debug.h" 00033 #include "wine/list.h" 00034 00035 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00036 00037 static const WCHAR szOID[] = { 00038 'S','o','f','t','w','a','r','e','\\', 00039 'M','i','c','r','o','s','o','f','t','\\', 00040 'C','r','y','p','t','o','g','r','a','p','h','y','\\', 00041 'O','I','D','\\', 00042 'E','n','c','o','d','i','n','g','T','y','p','e',' ','0','\\', 00043 'C','r','y','p','t','S','I','P','D','l','l', 0 }; 00044 00045 static const WCHAR szPutSigned[] = { 00046 'P','u','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0}; 00047 static const WCHAR szGetSigned[] = { 00048 'G','e','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0}; 00049 static const WCHAR szRemoveSigned[] = { 00050 'R','e','m','o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0}; 00051 static const WCHAR szCreate[] = { 00052 'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a','\\',0}; 00053 static const WCHAR szVerify[] = { 00054 'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a','\\',0}; 00055 static const WCHAR szIsMyFile[] = { 00056 'I','s','M','y','F','i','l','e','T','y','p','e','\\',0}; 00057 static const WCHAR szIsMyFile2[] = { 00058 'I','s','M','y','F','i','l','e','T','y','p','e','2','\\',0}; 00059 00060 static const WCHAR szDllName[] = { 'D','l','l',0 }; 00061 static const WCHAR szFuncName[] = { 'F','u','n','c','N','a','m','e',0 }; 00062 00063 /* convert a guid to a wide character string */ 00064 static void CRYPT_guid2wstr( const GUID *guid, LPWSTR wstr ) 00065 { 00066 char str[40]; 00067 00068 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 00069 guid->Data1, guid->Data2, guid->Data3, 00070 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 00071 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); 00072 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, 40 ); 00073 } 00074 00075 /*********************************************************************** 00076 * CRYPT_SIPDeleteFunction 00077 * 00078 * Helper function for CryptSIPRemoveProvider 00079 */ 00080 static LONG CRYPT_SIPDeleteFunction( const GUID *guid, LPCWSTR szKey ) 00081 { 00082 WCHAR szFullKey[ 0x100 ]; 00083 LONG r = ERROR_SUCCESS; 00084 00085 /* max length of szFullKey depends on our code only, so we won't overrun */ 00086 lstrcpyW( szFullKey, szOID ); 00087 lstrcatW( szFullKey, szKey ); 00088 CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] ); 00089 00090 r = RegDeleteKeyW(HKEY_LOCAL_MACHINE, szFullKey); 00091 00092 return r; 00093 } 00094 00095 /*********************************************************************** 00096 * CryptSIPRemoveProvider (CRYPT32.@) 00097 * 00098 * Remove a SIP provider and its functions from the registry. 00099 * 00100 * PARAMS 00101 * pgProv [I] Pointer to a GUID for this SIP provider 00102 * 00103 * RETURNS 00104 * Success: TRUE. 00105 * Failure: FALSE. (Look at GetLastError()). 00106 * 00107 * NOTES 00108 * Registry errors are always reported via SetLastError(). Every registry 00109 * deletion will be tried. 00110 */ 00111 BOOL WINAPI CryptSIPRemoveProvider(GUID *pgProv) 00112 { 00113 LONG r = ERROR_SUCCESS; 00114 LONG remove_error = ERROR_SUCCESS; 00115 00116 TRACE("%s\n", debugstr_guid(pgProv)); 00117 00118 if (!pgProv) 00119 { 00120 SetLastError(ERROR_INVALID_PARAMETER); 00121 return FALSE; 00122 } 00123 00124 00125 #define CRYPT_SIPREMOVEPROV( key ) \ 00126 r = CRYPT_SIPDeleteFunction( pgProv, key); \ 00127 if (r != ERROR_SUCCESS) remove_error = r 00128 00129 CRYPT_SIPREMOVEPROV( szPutSigned); 00130 CRYPT_SIPREMOVEPROV( szGetSigned); 00131 CRYPT_SIPREMOVEPROV( szRemoveSigned); 00132 CRYPT_SIPREMOVEPROV( szCreate); 00133 CRYPT_SIPREMOVEPROV( szVerify); 00134 CRYPT_SIPREMOVEPROV( szIsMyFile); 00135 CRYPT_SIPREMOVEPROV( szIsMyFile2); 00136 00137 #undef CRYPT_SIPREMOVEPROV 00138 00139 if (remove_error != ERROR_SUCCESS) 00140 { 00141 SetLastError(remove_error); 00142 return FALSE; 00143 } 00144 00145 return TRUE; 00146 } 00147 00148 /* 00149 * Helper for CryptSIPAddProvider 00150 * 00151 * Add a registry key containing a dll name and function under 00152 * "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\<func>\<guid>" 00153 */ 00154 static LONG CRYPT_SIPWriteFunction( const GUID *guid, LPCWSTR szKey, 00155 LPCWSTR szDll, LPCWSTR szFunction ) 00156 { 00157 WCHAR szFullKey[ 0x100 ]; 00158 LONG r = ERROR_SUCCESS; 00159 HKEY hKey; 00160 00161 if( !szFunction ) 00162 return ERROR_SUCCESS; 00163 00164 /* max length of szFullKey depends on our code only, so we won't overrun */ 00165 lstrcpyW( szFullKey, szOID ); 00166 lstrcatW( szFullKey, szKey ); 00167 CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] ); 00168 00169 TRACE("key is %s\n", debugstr_w( szFullKey ) ); 00170 00171 r = RegCreateKeyW( HKEY_LOCAL_MACHINE, szFullKey, &hKey ); 00172 if( r != ERROR_SUCCESS ) goto error_close_key; 00173 00174 /* write the values */ 00175 r = RegSetValueExW( hKey, szFuncName, 0, REG_SZ, (const BYTE*) szFunction, 00176 ( lstrlenW( szFunction ) + 1 ) * sizeof (WCHAR) ); 00177 if( r != ERROR_SUCCESS ) goto error_close_key; 00178 r = RegSetValueExW( hKey, szDllName, 0, REG_SZ, (const BYTE*) szDll, 00179 ( lstrlenW( szDll ) + 1) * sizeof (WCHAR) ); 00180 00181 error_close_key: 00182 00183 RegCloseKey( hKey ); 00184 00185 return r; 00186 } 00187 00188 /*********************************************************************** 00189 * CryptSIPAddProvider (CRYPT32.@) 00190 * 00191 * Add a SIP provider and its functions to the registry. 00192 * 00193 * PARAMS 00194 * psNewProv [I] Pointer to a structure with information about 00195 * the functions this SIP provider can perform. 00196 * 00197 * RETURNS 00198 * Success: TRUE. 00199 * Failure: FALSE. (Look at GetLastError()). 00200 * 00201 * NOTES 00202 * Registry errors are always reported via SetLastError(). If a 00203 * registry error occurs the rest of the registry write operations 00204 * will be skipped. 00205 */ 00206 BOOL WINAPI CryptSIPAddProvider(SIP_ADD_NEWPROVIDER *psNewProv) 00207 { 00208 LONG r = ERROR_SUCCESS; 00209 00210 TRACE("%p\n", psNewProv); 00211 00212 if (!psNewProv || 00213 psNewProv->cbStruct != sizeof(SIP_ADD_NEWPROVIDER) || 00214 !psNewProv->pwszGetFuncName || 00215 !psNewProv->pwszPutFuncName || 00216 !psNewProv->pwszCreateFuncName || 00217 !psNewProv->pwszVerifyFuncName || 00218 !psNewProv->pwszRemoveFuncName) 00219 { 00220 SetLastError(ERROR_INVALID_PARAMETER); 00221 return FALSE; 00222 } 00223 00224 TRACE("%s %s %s %s %s\n", 00225 debugstr_guid( psNewProv->pgSubject ), 00226 debugstr_w( psNewProv->pwszDLLFileName ), 00227 debugstr_w( psNewProv->pwszMagicNumber ), 00228 debugstr_w( psNewProv->pwszIsFunctionName ), 00229 debugstr_w( psNewProv->pwszIsFunctionNameFmt2 ) ); 00230 00231 #define CRYPT_SIPADDPROV( key, field ) \ 00232 r = CRYPT_SIPWriteFunction( psNewProv->pgSubject, key, \ 00233 psNewProv->pwszDLLFileName, psNewProv->field); \ 00234 if (r != ERROR_SUCCESS) goto end_function 00235 00236 CRYPT_SIPADDPROV( szPutSigned, pwszPutFuncName ); 00237 CRYPT_SIPADDPROV( szGetSigned, pwszGetFuncName ); 00238 CRYPT_SIPADDPROV( szRemoveSigned, pwszRemoveFuncName ); 00239 CRYPT_SIPADDPROV( szCreate, pwszCreateFuncName ); 00240 CRYPT_SIPADDPROV( szVerify, pwszVerifyFuncName ); 00241 CRYPT_SIPADDPROV( szIsMyFile, pwszIsFunctionName ); 00242 CRYPT_SIPADDPROV( szIsMyFile2, pwszIsFunctionNameFmt2 ); 00243 00244 #undef CRYPT_SIPADDPROV 00245 00246 end_function: 00247 00248 if (r != ERROR_SUCCESS) 00249 { 00250 SetLastError(r); 00251 return FALSE; 00252 } 00253 00254 return TRUE; 00255 } 00256 00257 static void *CRYPT_LoadSIPFuncFromKey(HKEY key, HMODULE *pLib) 00258 { 00259 LONG r; 00260 DWORD size; 00261 WCHAR dllName[MAX_PATH]; 00262 char functionName[MAX_PATH]; 00263 HMODULE lib; 00264 void *func = NULL; 00265 00266 /* Read the DLL entry */ 00267 size = sizeof(dllName); 00268 r = RegQueryValueExW(key, szDllName, NULL, NULL, (LPBYTE)dllName, &size); 00269 if (r) goto end; 00270 00271 /* Read the Function entry */ 00272 size = sizeof(functionName); 00273 r = RegQueryValueExA(key, "FuncName", NULL, NULL, (LPBYTE)functionName, 00274 &size); 00275 if (r) goto end; 00276 00277 lib = LoadLibraryW(dllName); 00278 if (!lib) 00279 goto end; 00280 func = GetProcAddress(lib, functionName); 00281 if (func) 00282 *pLib = lib; 00283 else 00284 FreeLibrary(lib); 00285 00286 end: 00287 return func; 00288 } 00289 00290 /*********************************************************************** 00291 * CryptSIPRetrieveSubjectGuid (CRYPT32.@) 00292 * 00293 * Determine the right SIP GUID for the given file. 00294 * 00295 * PARAMS 00296 * FileName [I] Filename. 00297 * hFileIn [I] Optional handle to the file. 00298 * pgSubject [O] The SIP's GUID. 00299 * 00300 * RETURNS 00301 * Success: TRUE. pgSubject contains the SIP GUID. 00302 * Failure: FALSE. (Look at GetLastError()). 00303 * 00304 * NOTES 00305 * On failure pgSubject will contain a NULL GUID. 00306 * The handle is always preferred above the filename. 00307 */ 00308 BOOL WINAPI CryptSIPRetrieveSubjectGuid 00309 (LPCWSTR FileName, HANDLE hFileIn, GUID *pgSubject) 00310 { 00311 HANDLE hFile; 00312 BOOL bRet = FALSE; 00313 DWORD count; 00314 LARGE_INTEGER zero, oldPos; 00315 /* FIXME, find out if there is a name for this GUID */ 00316 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; 00317 static const GUID cabGUID = { 0xc689aaba, 0x8e78, 0x11d0, {0x8c,0x47,0x00,0xc0,0x4f,0xc2,0x95,0xee }}; 00318 static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; 00319 static const WORD dosHdr = IMAGE_DOS_SIGNATURE; 00320 static const BYTE cabHdr[] = { 'M','S','C','F' }; 00321 BYTE hdr[SIP_MAX_MAGIC_NUMBER]; 00322 WCHAR szFullKey[ 0x100 ]; 00323 LONG r = ERROR_SUCCESS; 00324 HKEY key; 00325 00326 TRACE("(%s %p %p)\n", wine_dbgstr_w(FileName), hFileIn, pgSubject); 00327 00328 if (!pgSubject || (!FileName && !hFileIn)) 00329 { 00330 SetLastError(ERROR_INVALID_PARAMETER); 00331 return FALSE; 00332 } 00333 00334 /* Set pgSubject to zero's */ 00335 memset(pgSubject, 0 , sizeof(GUID)); 00336 00337 if (hFileIn) 00338 /* Use the given handle, make sure not to close this one ourselves */ 00339 hFile = hFileIn; 00340 else 00341 { 00342 hFile = CreateFileW(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00343 /* Last error is set by CreateFile */ 00344 if (hFile == INVALID_HANDLE_VALUE) return FALSE; 00345 } 00346 00347 zero.QuadPart = 0; 00348 SetFilePointerEx(hFile, zero, &oldPos, FILE_CURRENT); 00349 SetFilePointer(hFile, 0, NULL, FILE_BEGIN); 00350 if (!ReadFile(hFile, hdr, sizeof(hdr), &count, NULL)) 00351 goto cleanup; 00352 00353 if (count < SIP_MAX_MAGIC_NUMBER) 00354 { 00355 SetLastError(ERROR_INVALID_PARAMETER); 00356 goto cleanup; 00357 } 00358 00359 TRACE("file magic = 0x%02x%02x%02x%02x\n", hdr[0], hdr[1], hdr[2], hdr[3]); 00360 /* As everything is in place now we start looking at the file header */ 00361 if (!memcmp(hdr, &dosHdr, sizeof(dosHdr))) 00362 { 00363 *pgSubject = unknown; 00364 SetLastError(S_OK); 00365 bRet = TRUE; 00366 goto cleanup; 00367 } 00368 /* Quick-n-dirty check for a cab file. */ 00369 if (!memcmp(hdr, cabHdr, sizeof(cabHdr))) 00370 { 00371 *pgSubject = cabGUID; 00372 SetLastError(S_OK); 00373 bRet = TRUE; 00374 goto cleanup; 00375 } 00376 /* If it's asn.1-encoded, it's probably a .cat file. */ 00377 if (hdr[0] == 0x30) 00378 { 00379 DWORD fileLen = GetFileSize(hFile, NULL); 00380 00381 TRACE("fileLen = %d\n", fileLen); 00382 /* Sanity-check length */ 00383 if (hdr[1] < 0x80 && fileLen == 2 + hdr[1]) 00384 { 00385 *pgSubject = catGUID; 00386 SetLastError(S_OK); 00387 bRet = TRUE; 00388 goto cleanup; 00389 } 00390 else if (hdr[1] == 0x80) 00391 { 00392 /* Indefinite length, can't verify with just the header, assume it 00393 * is. 00394 */ 00395 *pgSubject = catGUID; 00396 SetLastError(S_OK); 00397 bRet = TRUE; 00398 goto cleanup; 00399 } 00400 else 00401 { 00402 BYTE lenBytes = hdr[1] & 0x7f; 00403 00404 if (lenBytes == 1 && fileLen == 2 + lenBytes + hdr[2]) 00405 { 00406 *pgSubject = catGUID; 00407 SetLastError(S_OK); 00408 bRet = TRUE; 00409 goto cleanup; 00410 } 00411 else if (lenBytes == 2 && fileLen == 2 + lenBytes + 00412 (hdr[2] << 8 | hdr[3])) 00413 { 00414 *pgSubject = catGUID; 00415 SetLastError(S_OK); 00416 bRet = TRUE; 00417 goto cleanup; 00418 } 00419 else if (fileLen > 0xffff) 00420 { 00421 /* The file size must be greater than 2 bytes in length, so 00422 * assume it is a .cat file 00423 */ 00424 *pgSubject = catGUID; 00425 SetLastError(S_OK); 00426 bRet = TRUE; 00427 goto cleanup; 00428 } 00429 } 00430 } 00431 00432 /* Check for supported functions using CryptSIPDllIsMyFileType */ 00433 /* max length of szFullKey depends on our code only, so we won't overrun */ 00434 lstrcpyW(szFullKey, szOID); 00435 lstrcatW(szFullKey, szIsMyFile); 00436 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key); 00437 if (r == ERROR_SUCCESS) 00438 { 00439 DWORD index = 0, size; 00440 WCHAR subKeyName[MAX_PATH]; 00441 00442 do { 00443 size = sizeof(subKeyName) / sizeof(subKeyName[0]); 00444 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, 00445 NULL, NULL); 00446 if (r == ERROR_SUCCESS) 00447 { 00448 HKEY subKey; 00449 00450 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); 00451 if (r == ERROR_SUCCESS) 00452 { 00453 HMODULE lib; 00454 pfnIsFileSupported isMy = CRYPT_LoadSIPFuncFromKey(subKey, 00455 &lib); 00456 00457 if (isMy) 00458 { 00459 bRet = isMy(hFile, pgSubject); 00460 FreeLibrary(lib); 00461 } 00462 RegCloseKey(subKey); 00463 } 00464 } 00465 } while (!bRet && r == ERROR_SUCCESS); 00466 RegCloseKey(key); 00467 } 00468 00469 /* Check for supported functions using CryptSIPDllIsMyFileType2 */ 00470 if (!bRet) 00471 { 00472 lstrcpyW(szFullKey, szOID); 00473 lstrcatW(szFullKey, szIsMyFile2); 00474 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key); 00475 if (r == ERROR_SUCCESS) 00476 { 00477 DWORD index = 0, size; 00478 WCHAR subKeyName[MAX_PATH]; 00479 00480 do { 00481 size = sizeof(subKeyName) / sizeof(subKeyName[0]); 00482 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, 00483 NULL, NULL); 00484 if (r == ERROR_SUCCESS) 00485 { 00486 HKEY subKey; 00487 00488 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); 00489 if (r == ERROR_SUCCESS) 00490 { 00491 HMODULE lib; 00492 pfnIsFileSupportedName isMy2 = 00493 CRYPT_LoadSIPFuncFromKey(subKey, &lib); 00494 00495 if (isMy2) 00496 { 00497 bRet = isMy2((LPWSTR)FileName, pgSubject); 00498 FreeLibrary(lib); 00499 } 00500 RegCloseKey(subKey); 00501 } 00502 } 00503 } while (!bRet && r == ERROR_SUCCESS); 00504 RegCloseKey(key); 00505 } 00506 } 00507 00508 if (!bRet) 00509 SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN); 00510 00511 cleanup: 00512 /* If we didn't open this one we shouldn't close it (hFile is a copy), 00513 * but we should reset the file pointer to its original position. 00514 */ 00515 if (!hFileIn) 00516 CloseHandle(hFile); 00517 else 00518 SetFilePointerEx(hFile, oldPos, NULL, FILE_BEGIN); 00519 00520 return bRet; 00521 } 00522 00523 static LONG CRYPT_OpenSIPFunctionKey(const GUID *guid, LPCWSTR function, 00524 HKEY *key) 00525 { 00526 WCHAR szFullKey[ 0x100 ]; 00527 00528 lstrcpyW(szFullKey, szOID); 00529 lstrcatW(szFullKey, function); 00530 CRYPT_guid2wstr(guid, &szFullKey[lstrlenW(szFullKey)]); 00531 return RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, key); 00532 } 00533 00534 /* Loads the function named function for the SIP specified by pgSubject, and 00535 * returns it if found. Returns NULL on error. If the function is loaded, 00536 * *pLib is set to the library in which it is found. 00537 */ 00538 static void *CRYPT_LoadSIPFunc(const GUID *pgSubject, LPCWSTR function, 00539 HMODULE *pLib) 00540 { 00541 LONG r; 00542 HKEY key; 00543 void *func = NULL; 00544 00545 TRACE("(%s, %s)\n", debugstr_guid(pgSubject), debugstr_w(function)); 00546 00547 r = CRYPT_OpenSIPFunctionKey(pgSubject, function, &key); 00548 if (!r) 00549 { 00550 func = CRYPT_LoadSIPFuncFromKey(key, pLib); 00551 RegCloseKey(key); 00552 } 00553 TRACE("returning %p\n", func); 00554 return func; 00555 } 00556 00557 typedef struct _WINE_SIP_PROVIDER { 00558 GUID subject; 00559 SIP_DISPATCH_INFO info; 00560 struct list entry; 00561 } WINE_SIP_PROVIDER; 00562 00563 static struct list providers = { &providers, &providers }; 00564 static CRITICAL_SECTION providers_cs; 00565 static CRITICAL_SECTION_DEBUG providers_cs_debug = 00566 { 00567 0, 0, &providers_cs, 00568 { &providers_cs_debug.ProcessLocksList, 00569 &providers_cs_debug.ProcessLocksList }, 00570 0, 0, { (DWORD_PTR)(__FILE__ ": providers_cs") } 00571 }; 00572 static CRITICAL_SECTION providers_cs = { &providers_cs_debug, -1, 0, 0, 0, 0 }; 00573 00574 static void CRYPT_CacheSIP(const GUID *pgSubject, SIP_DISPATCH_INFO *info) 00575 { 00576 WINE_SIP_PROVIDER *prov = CryptMemAlloc(sizeof(WINE_SIP_PROVIDER)); 00577 00578 if (prov) 00579 { 00580 prov->subject = *pgSubject; 00581 prov->info = *info; 00582 EnterCriticalSection(&providers_cs); 00583 list_add_tail(&providers, &prov->entry); 00584 LeaveCriticalSection(&providers_cs); 00585 } 00586 } 00587 00588 static WINE_SIP_PROVIDER *CRYPT_GetCachedSIP(const GUID *pgSubject) 00589 { 00590 WINE_SIP_PROVIDER *provider = NULL, *ret = NULL; 00591 00592 EnterCriticalSection(&providers_cs); 00593 LIST_FOR_EACH_ENTRY(provider, &providers, WINE_SIP_PROVIDER, entry) 00594 { 00595 if (IsEqualGUID(pgSubject, &provider->subject)) 00596 break; 00597 } 00598 if (provider && IsEqualGUID(pgSubject, &provider->subject)) 00599 ret = provider; 00600 LeaveCriticalSection(&providers_cs); 00601 return ret; 00602 } 00603 00604 static inline BOOL CRYPT_IsSIPCached(const GUID *pgSubject) 00605 { 00606 return CRYPT_GetCachedSIP(pgSubject) != NULL; 00607 } 00608 00609 void crypt_sip_free(void) 00610 { 00611 WINE_SIP_PROVIDER *prov, *next; 00612 00613 LIST_FOR_EACH_ENTRY_SAFE(prov, next, &providers, WINE_SIP_PROVIDER, entry) 00614 { 00615 list_remove(&prov->entry); 00616 FreeLibrary(prov->info.hSIP); 00617 CryptMemFree(prov); 00618 } 00619 DeleteCriticalSection(&providers_cs); 00620 } 00621 00622 /* Loads the SIP for pgSubject into the global cache. Returns FALSE if the 00623 * SIP isn't registered or is invalid. 00624 */ 00625 static BOOL CRYPT_LoadSIP(const GUID *pgSubject) 00626 { 00627 SIP_DISPATCH_INFO sip = { 0 }; 00628 HMODULE lib = NULL, temp = NULL; 00629 00630 sip.pfGet = CRYPT_LoadSIPFunc(pgSubject, szGetSigned, &lib); 00631 if (!sip.pfGet) 00632 goto error; 00633 sip.pfPut = CRYPT_LoadSIPFunc(pgSubject, szPutSigned, &temp); 00634 if (!sip.pfPut || temp != lib) 00635 goto error; 00636 FreeLibrary(temp); 00637 sip.pfCreate = CRYPT_LoadSIPFunc(pgSubject, szCreate, &temp); 00638 if (!sip.pfCreate || temp != lib) 00639 goto error; 00640 FreeLibrary(temp); 00641 sip.pfVerify = CRYPT_LoadSIPFunc(pgSubject, szVerify, &temp); 00642 if (!sip.pfVerify || temp != lib) 00643 goto error; 00644 FreeLibrary(temp); 00645 sip.pfRemove = CRYPT_LoadSIPFunc(pgSubject, szRemoveSigned, &temp); 00646 if (!sip.pfRemove || temp != lib) 00647 goto error; 00648 FreeLibrary(temp); 00649 sip.hSIP = lib; 00650 CRYPT_CacheSIP(pgSubject, &sip); 00651 return TRUE; 00652 00653 error: 00654 FreeLibrary(lib); 00655 FreeLibrary(temp); 00656 SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN); 00657 return FALSE; 00658 } 00659 00660 /*********************************************************************** 00661 * CryptSIPLoad (CRYPT32.@) 00662 * 00663 * Load some internal crypt32 functions into a SIP_DISPATCH_INFO structure. 00664 * 00665 * PARAMS 00666 * pgSubject [I] The GUID. 00667 * dwFlags [I] Flags. 00668 * pSipDispatch [I] The loaded functions. 00669 * 00670 * RETURNS 00671 * Success: TRUE. pSipDispatch contains the functions. 00672 * Failure: FALSE. (Look at GetLastError()). 00673 * 00674 * NOTES 00675 * CryptSIPLoad uses caching for the list of GUIDs and whether a SIP is 00676 * already loaded. 00677 * 00678 * An application calls CryptSipLoad which will return a structure with the 00679 * function addresses of some internal crypt32 functions. The application will 00680 * then call these functions which will be forwarded to the appropriate SIP. 00681 * 00682 * CryptSIPLoad will load the needed SIP but doesn't unload this dll. The unloading 00683 * is done when crypt32 is unloaded. 00684 */ 00685 BOOL WINAPI CryptSIPLoad 00686 (const GUID *pgSubject, DWORD dwFlags, SIP_DISPATCH_INFO *pSipDispatch) 00687 { 00688 TRACE("(%s %d %p)\n", debugstr_guid(pgSubject), dwFlags, pSipDispatch); 00689 00690 if (!pgSubject || dwFlags != 0 || !pSipDispatch) 00691 { 00692 SetLastError(ERROR_INVALID_PARAMETER); 00693 return FALSE; 00694 } 00695 if (!CRYPT_IsSIPCached(pgSubject) && !CRYPT_LoadSIP(pgSubject)) 00696 return FALSE; 00697 00698 pSipDispatch->hSIP = NULL; 00699 pSipDispatch->pfGet = CryptSIPGetSignedDataMsg; 00700 pSipDispatch->pfPut = CryptSIPPutSignedDataMsg; 00701 pSipDispatch->pfCreate = CryptSIPCreateIndirectData; 00702 pSipDispatch->pfVerify = CryptSIPVerifyIndirectData; 00703 pSipDispatch->pfRemove = CryptSIPRemoveSignedDataMsg; 00704 00705 return TRUE; 00706 } 00707 00708 /*********************************************************************** 00709 * CryptSIPCreateIndirectData (CRYPT32.@) 00710 */ 00711 BOOL WINAPI CryptSIPCreateIndirectData(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pcbIndirectData, 00712 SIP_INDIRECT_DATA* pIndirectData) 00713 { 00714 WINE_SIP_PROVIDER *sip; 00715 BOOL ret = FALSE; 00716 00717 TRACE("(%p %p %p)\n", pSubjectInfo, pcbIndirectData, pIndirectData); 00718 00719 if (!pSubjectInfo || !pSubjectInfo->pgSubjectType || !pcbIndirectData) 00720 { 00721 SetLastError(ERROR_INVALID_PARAMETER); 00722 return FALSE; 00723 } 00724 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 00725 ret = sip->info.pfCreate(pSubjectInfo, pcbIndirectData, pIndirectData); 00726 TRACE("returning %d\n", ret); 00727 return ret; 00728 } 00729 00730 /*********************************************************************** 00731 * CryptSIPGetSignedDataMsg (CRYPT32.@) 00732 */ 00733 BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEncodingType, 00734 DWORD dwIndex, DWORD* pcbSignedDataMsg, BYTE* pbSignedDataMsg) 00735 { 00736 WINE_SIP_PROVIDER *sip; 00737 BOOL ret = FALSE; 00738 00739 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, 00740 pcbSignedDataMsg, pbSignedDataMsg); 00741 00742 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 00743 ret = sip->info.pfGet(pSubjectInfo, pdwEncodingType, dwIndex, 00744 pcbSignedDataMsg, pbSignedDataMsg); 00745 TRACE("returning %d\n", ret); 00746 return ret; 00747 } 00748 00749 /*********************************************************************** 00750 * CryptSIPPutSignedDataMsg (CRYPT32.@) 00751 */ 00752 BOOL WINAPI CryptSIPPutSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType, 00753 DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) 00754 { 00755 WINE_SIP_PROVIDER *sip; 00756 BOOL ret = FALSE; 00757 00758 TRACE("(%p %d %p %d %p)\n", pSubjectInfo, pdwEncodingType, pdwIndex, 00759 cbSignedDataMsg, pbSignedDataMsg); 00760 00761 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 00762 ret = sip->info.pfPut(pSubjectInfo, pdwEncodingType, pdwIndex, 00763 cbSignedDataMsg, pbSignedDataMsg); 00764 TRACE("returning %d\n", ret); 00765 return ret; 00766 } 00767 00768 /*********************************************************************** 00769 * CryptSIPRemoveSignedDataMsg (CRYPT32.@) 00770 */ 00771 BOOL WINAPI CryptSIPRemoveSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, 00772 DWORD dwIndex) 00773 { 00774 WINE_SIP_PROVIDER *sip; 00775 BOOL ret = FALSE; 00776 00777 TRACE("(%p %d)\n", pSubjectInfo, dwIndex); 00778 00779 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 00780 ret = sip->info.pfRemove(pSubjectInfo, dwIndex); 00781 TRACE("returning %d\n", ret); 00782 return ret; 00783 } 00784 00785 /*********************************************************************** 00786 * CryptSIPVerifyIndirectData (CRYPT32.@) 00787 */ 00788 BOOL WINAPI CryptSIPVerifyIndirectData(SIP_SUBJECTINFO* pSubjectInfo, 00789 SIP_INDIRECT_DATA* pIndirectData) 00790 { 00791 WINE_SIP_PROVIDER *sip; 00792 BOOL ret = FALSE; 00793 00794 TRACE("(%p %p)\n", pSubjectInfo, pIndirectData); 00795 00796 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 00797 ret = sip->info.pfVerify(pSubjectInfo, pIndirectData); 00798 TRACE("returning %d\n", ret); 00799 return ret; 00800 } Generated on Sat May 26 2012 04:21:55 for ReactOS by
1.7.6.1
|