void Context_CopyProperties(const void *to, const void *from) { CONTEXT_PROPERTY_LIST *toProperties, *fromProperties; toProperties = context_from_ptr(to)->properties; fromProperties = context_from_ptr(from)->properties; assert(toProperties && fromProperties); ContextPropertyList_Copy(toProperties, fromProperties); }
static BOOL CRYPT_SerializeContextsToStream(SerializedOutputFunc output, void *handle, const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE store) { const void *context = NULL; BOOL ret; do { context = contextInterface->enumContextsInStore(store, context); if (context) { DWORD size = 0; LPBYTE buf = NULL; ret = contextInterface->serialize(context, 0, NULL, &size); if (size) buf = CryptMemAlloc(size); if (buf) { ret = contextInterface->serialize(context, 0, buf, &size); if (ret) ret = output(handle, buf, size); } CryptMemFree(buf); } else ret = TRUE; } while (ret && context != NULL); if (context) Context_Release(context_from_ptr(context)); return ret; }
BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore, const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags, DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext) { const void *context; DWORD type; BOOL ret; TRACE("(%p, %p, %d, %08x, %08x, %08x, %p, %p)\n", hCertStore, pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags, pdwContentType, ppvContext); /* Call the internal function, then delete the hashes. Tests show this * function uses real hash values, not whatever's stored in the hash * property. */ context = CRYPT_ReadSerializedElement(pbElement, cbElement, dwContextTypeFlags, &type); if (context) { const WINE_CONTEXT_INTERFACE *contextInterface = NULL; switch (type) { case CERT_STORE_CERTIFICATE_CONTEXT: contextInterface = pCertInterface; break; case CERT_STORE_CRL_CONTEXT: contextInterface = pCRLInterface; break; case CERT_STORE_CTL_CONTEXT: contextInterface = pCTLInterface; break; default: SetLastError(E_INVALIDARG); } if (contextInterface) { contextInterface->setProp(context, CERT_HASH_PROP_ID, 0, NULL); contextInterface->setProp(context, CERT_MD5_HASH_PROP_ID, 0, NULL); contextInterface->setProp(context, CERT_SIGNATURE_HASH_PROP_ID, 0, NULL); if (pdwContentType) *pdwContentType = type; ret = contextInterface->addContextToStore(hCertStore, context, dwAddDisposition, ppvContext); Context_Release(context_from_ptr(context)); } else ret = FALSE; } else ret = FALSE; return ret; }
BOOL CRYPT_SerializeContextsToReg(HKEY key, DWORD flags, const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE memStore) { const void *context = NULL; BOOL ret; do { context = contextInterface->enumContextsInStore(memStore, context); if (context) { BYTE hash[20]; DWORD hashSize = sizeof(hash); ret = contextInterface->getProp(context, CERT_HASH_PROP_ID, hash, &hashSize); if (ret) { DWORD size = 0; LPBYTE buf = NULL; ret = contextInterface->serialize(context, 0, NULL, &size); if (size) buf = CryptMemAlloc(size); if (buf) { ret = contextInterface->serialize(context, 0, buf, &size); if (ret) ret = CRYPT_WriteSerializedToReg(key, flags, hash, buf, size); } CryptMemFree(buf); } } else ret = TRUE; } while (ret && context != NULL); if (context) Context_Release(context_from_ptr(context)); return ret; }
static void CRYPT_RegReadSerializedFromReg(HKEY key, DWORD contextType, HCERTSTORE store) { LONG rc; DWORD index = 0; WCHAR subKeyName[MAX_PATH]; do { DWORD size = sizeof(subKeyName) / sizeof(WCHAR); rc = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, NULL, NULL); if (!rc) { HKEY subKey; rc = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); if (!rc) { LPBYTE buf = NULL; size = 0; rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, NULL, &size); if (!rc) buf = CryptMemAlloc(size); if (buf) { rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, buf, &size); if (!rc) { const void *context; DWORD addedType; TRACE("Adding cert with hash %s\n", debugstr_w(subKeyName)); context = CRYPT_ReadSerializedElement(buf, size, contextType, &addedType); if (context) { const WINE_CONTEXT_INTERFACE *contextInterface; BYTE hash[20]; switch (addedType) { case CERT_STORE_CERTIFICATE_CONTEXT: contextInterface = pCertInterface; break; case CERT_STORE_CRL_CONTEXT: contextInterface = pCRLInterface; break; case CERT_STORE_CTL_CONTEXT: contextInterface = pCTLInterface; break; default: contextInterface = NULL; } if (contextInterface) { size = sizeof(hash); if (contextInterface->getProp(context, CERT_HASH_PROP_ID, hash, &size)) { WCHAR asciiHash[20 * 2 + 1]; CRYPT_HashToStr(hash, asciiHash); TRACE("comparing %s\n", debugstr_w(asciiHash)); TRACE("with %s\n", debugstr_w(subKeyName)); if (!lstrcmpW(asciiHash, subKeyName)) { TRACE("hash matches, adding\n"); contextInterface->addContextToStore( store, context, CERT_STORE_ADD_REPLACE_EXISTING, NULL); } else TRACE("hash doesn't match, ignoring\n"); } Context_Release(context_from_ptr(context)); } } } CryptMemFree(buf); } RegCloseKey(subKey); } /* Ignore intermediate errors, continue enumerating */ rc = ERROR_SUCCESS; } } while (!rc); }
static BOOL CRYPT_ReadSerializedStore(void *handle, read_serialized_func read_func, HCERTSTORE store) { BYTE fileHeaderBuf[sizeof(fileHeader)]; DWORD read; BOOL ret; /* Failure reading is non-critical, we'll leave the store empty */ ret = read_func(handle, fileHeaderBuf, sizeof(fileHeaderBuf), &read); if (ret) { if (!read) ; /* an empty file is okay */ else if (read != sizeof(fileHeaderBuf)) ret = FALSE; else if (!memcmp(fileHeaderBuf, fileHeader, read)) { WINE_CERT_PROP_HEADER propHdr; const void *context = NULL; const WINE_CONTEXT_INTERFACE *contextInterface = NULL; LPBYTE buf = NULL; DWORD bufSize = 0; do { ret = read_func(handle, &propHdr, sizeof(propHdr), &read); if (ret && read == sizeof(propHdr)) { if (contextInterface && context && (propHdr.propID == CERT_CERT_PROP_ID || propHdr.propID == CERT_CRL_PROP_ID || propHdr.propID == CERT_CTL_PROP_ID)) { /* We have a new context, so free the existing one */ Context_Release(context_from_ptr(context)); } if (propHdr.cb > bufSize) { /* Not reusing realloc, because the old data aren't * needed any longer. */ CryptMemFree(buf); buf = CryptMemAlloc(propHdr.cb); bufSize = propHdr.cb; } if (!propHdr.cb) ; /* Property is empty, nothing to do */ else if (buf) { ret = read_func(handle, buf, propHdr.cb, &read); if (ret && read == propHdr.cb) { if (propHdr.propID == CERT_CERT_PROP_ID) { contextInterface = pCertInterface; ret = contextInterface->addEncodedToStore(store, X509_ASN_ENCODING, buf, read, CERT_STORE_ADD_NEW, &context); } else if (propHdr.propID == CERT_CRL_PROP_ID) { contextInterface = pCRLInterface; ret = contextInterface->addEncodedToStore(store, X509_ASN_ENCODING, buf, read, CERT_STORE_ADD_NEW, &context); } else if (propHdr.propID == CERT_CTL_PROP_ID) { contextInterface = pCTLInterface; ret = contextInterface->addEncodedToStore(store, X509_ASN_ENCODING, buf, read, CERT_STORE_ADD_NEW, &context); } else { if (!contextInterface) { WARN("prop id %d before a context id\n", propHdr.propID); ret = FALSE; } else ret = CRYPT_ReadContextProp( contextInterface, context, &propHdr, buf, read); } } } else ret = FALSE; } } while (ret && read > 0 && propHdr.cb); if (contextInterface && context) { /* Free the last context added */ Context_Release(context_from_ptr(context)); } CryptMemFree(buf); ret = TRUE; } else ret = FALSE; } else ret = TRUE; return ret; }
const void *CRYPT_ReadSerializedElement(const BYTE *pbElement, DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType) { const void *context; TRACE("(%p, %d, %08x, %p)\n", pbElement, cbElement, dwContextTypeFlags, pdwContentType); if (!cbElement) { SetLastError(ERROR_END_OF_MEDIA); return NULL; } __TRY { const WINE_CONTEXT_INTERFACE *contextInterface = NULL; const WINE_CERT_PROP_HEADER *hdr = NULL; DWORD type = 0; BOOL ret; ret = TRUE; context = NULL; if (dwContextTypeFlags == CERT_STORE_ALL_CONTEXT_FLAG) { hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID); if (hdr) type = CERT_STORE_CERTIFICATE_CONTEXT; else { hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID); if (hdr) type = CERT_STORE_CRL_CONTEXT; else { hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CTL_PROP_ID); if (hdr) type = CERT_STORE_CTL_CONTEXT; } } } else if (dwContextTypeFlags & CERT_STORE_CERTIFICATE_CONTEXT_FLAG) { hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID); type = CERT_STORE_CERTIFICATE_CONTEXT; } else if (dwContextTypeFlags & CERT_STORE_CRL_CONTEXT_FLAG) { hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID); type = CERT_STORE_CRL_CONTEXT; } else if (dwContextTypeFlags & CERT_STORE_CTL_CONTEXT_FLAG) { hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CTL_PROP_ID); type = CERT_STORE_CTL_CONTEXT; } switch (type) { case CERT_STORE_CERTIFICATE_CONTEXT: contextInterface = pCertInterface; break; case CERT_STORE_CRL_CONTEXT: contextInterface = pCRLInterface; break; case CERT_STORE_CTL_CONTEXT: contextInterface = pCTLInterface; break; default: SetLastError(E_INVALIDARG); ret = FALSE; } if (!hdr) ret = FALSE; if (ret) context = contextInterface->create(X509_ASN_ENCODING, (BYTE *)hdr + sizeof(WINE_CERT_PROP_HEADER), hdr->cb); if (ret && context) { BOOL noMoreProps = FALSE; while (!noMoreProps && ret) { if (cbElement < sizeof(WINE_CERT_PROP_HEADER)) ret = FALSE; else { const WINE_CERT_PROP_HEADER *hdr = (const WINE_CERT_PROP_HEADER *)pbElement; TRACE("prop is %d\n", hdr->propID); cbElement -= sizeof(WINE_CERT_PROP_HEADER); pbElement += sizeof(WINE_CERT_PROP_HEADER); if (!hdr->propID) { /* Like in CRYPT_findPropID, stop if the propID is zero */ noMoreProps = TRUE; } else ret = CRYPT_ReadContextProp(contextInterface, context, hdr, pbElement, cbElement); pbElement += hdr->cb; cbElement -= hdr->cb; if (!cbElement) noMoreProps = TRUE; } } if (ret) { if (pdwContentType) *pdwContentType = type; } else { Context_Release(context_from_ptr(context)); context = NULL; } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); context = NULL; } __ENDTRY return context; }