PCCRL_CONTEXT WINAPI CertGetCRLFromStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pIssuerContext, PCCRL_CONTEXT pPrevCrlContext, DWORD *pdwFlags) { static const DWORD supportedFlags = CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG | CERT_STORE_BASE_CRL_FLAG | CERT_STORE_DELTA_CRL_FLAG; PCCRL_CONTEXT ret; TRACE("(%p, %p, %p, %08x)\n", hCertStore, pIssuerContext, pPrevCrlContext, *pdwFlags); if (*pdwFlags & ~supportedFlags) { SetLastError(E_INVALIDARG); return NULL; } if (pIssuerContext) ret = CertFindCRLInStore(hCertStore, pIssuerContext->dwCertEncodingType, 0, CRL_FIND_ISSUED_BY, pIssuerContext, pPrevCrlContext); else ret = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_ANY, NULL, pPrevCrlContext); if (ret) { if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG) { if (0 == CertVerifyCRLTimeValidity(NULL, ret->pCrlInfo)) *pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG; } if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG) { if (CryptVerifyCertificateSignatureEx(0, ret->dwCertEncodingType, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL, (void *)ret, CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)pIssuerContext, 0, NULL)) *pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG; } } return ret; }
BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition, PCCRL_CONTEXT* ppStoreContext) { PWINECRYPT_CERTSTORE store = hCertStore; BOOL ret = TRUE; PCCRL_CONTEXT toAdd = NULL, existing = NULL; TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext, dwAddDisposition, ppStoreContext); /* Weird case to pass a test */ if (dwAddDisposition == 0) { SetLastError(STATUS_ACCESS_VIOLATION); return FALSE; } if (dwAddDisposition != CERT_STORE_ADD_ALWAYS) { existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING, pCrlContext, NULL); } switch (dwAddDisposition) { case CERT_STORE_ADD_ALWAYS: toAdd = CertDuplicateCRLContext(pCrlContext); break; case CERT_STORE_ADD_NEW: if (existing) { TRACE("found matching CRL, not adding\n"); SetLastError(CRYPT_E_EXISTS); ret = FALSE; } else toAdd = CertDuplicateCRLContext(pCrlContext); break; case CERT_STORE_ADD_NEWER: if (existing) { LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate, &pCrlContext->pCrlInfo->ThisUpdate); if (newer < 0) toAdd = CertDuplicateCRLContext(pCrlContext); else { TRACE("existing CRL is newer, not adding\n"); SetLastError(CRYPT_E_EXISTS); ret = FALSE; } } else toAdd = CertDuplicateCRLContext(pCrlContext); break; case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES: if (existing) { LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate, &pCrlContext->pCrlInfo->ThisUpdate); if (newer < 0) { toAdd = CertDuplicateCRLContext(pCrlContext); CrlContext_CopyProperties(toAdd, existing); } else { TRACE("existing CRL is newer, not adding\n"); SetLastError(CRYPT_E_EXISTS); ret = FALSE; } } else toAdd = CertDuplicateCRLContext(pCrlContext); break; case CERT_STORE_ADD_REPLACE_EXISTING: toAdd = CertDuplicateCRLContext(pCrlContext); break; case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES: toAdd = CertDuplicateCRLContext(pCrlContext); if (existing) CrlContext_CopyProperties(toAdd, existing); break; case CERT_STORE_ADD_USE_EXISTING: if (existing) { CrlContext_CopyProperties(existing, pCrlContext); if (ppStoreContext) *ppStoreContext = CertDuplicateCRLContext(existing); } else toAdd = CertDuplicateCRLContext(pCrlContext); break; default: FIXME("Unimplemented add disposition %d\n", dwAddDisposition); ret = FALSE; } if (toAdd) { if (store) ret = store->crls.addContext(store, (void *)toAdd, (void *)existing, (const void **)ppStoreContext); else if (ppStoreContext) *ppStoreContext = CertDuplicateCRLContext(toAdd); CertFreeCRLContext(toAdd); } CertFreeCRLContext(existing); TRACE("returning %d\n", ret); return ret; }
static int op_capi_get_by_subject(X509_LOOKUP *_lu,int _type,X509_NAME *_name, X509_OBJECT *_ret) { HCERTSTORE h_store; if(_name==NULL)return 0; if(_name->bytes==NULL||_name->bytes->length<=0||_name->modified) { if(i2d_X509_NAME(_name,NULL)<0)return 0; OP_ASSERT(_name->bytes->length>0); } h_store=(HCERTSTORE)_lu->method_data; switch(_type) { case X509_LU_X509: { CERT_NAME_BLOB find_para; PCCERT_CONTEXT cert; X509 *x; int ret; /*Although X509_NAME contains a canon_enc field, that "canonical" [1] encoding was just made up by OpenSSL. It doesn't correspond to any actual standard, and since it drops the initial sequence header, won't be recognized by the Crypto API. The assumption here is that CertFindCertificateInStore() will allow any appropriate variations in the encoding when it does its comparison. This is, however, emphatically not true under Wine, which just compares the encodings with memcmp(). Most of the time things work anyway, though, and there isn't really anything we can do to make the situation better. [1] A "canonical form" is defined as the one where, if you locked 10 mathematicians in a room and asked them to come up with a representation for something, it's the answer that 9 of them would give you back. I don't think OpenSSL's encoding qualifies.*/ find_para.cbData=_name->bytes->length; find_para.pbData=(unsigned char *)_name->bytes->data; cert=CertFindCertificateInStore(h_store,X509_ASN_ENCODING,0, CERT_FIND_SUBJECT_NAME,&find_para,NULL); if(cert==NULL)return 0; x=d2i_X509(NULL,(const unsigned char **)&cert->pbCertEncoded, cert->cbCertEncoded); CertFreeCertificateContext(cert); if(x==NULL)return 0; ret=X509_STORE_add_cert(_lu->store_ctx,x); X509_free(x); if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret); } break; case X509_LU_CRL: { CERT_INFO cert_info; CERT_CONTEXT find_para; PCCRL_CONTEXT crl; X509_CRL *x; int ret; ret=op_capi_retrieve_by_subject(_lu,_type,_name,_ret); if(ret>0)return ret; memset(&cert_info,0,sizeof(cert_info)); cert_info.Issuer.cbData=_name->bytes->length; cert_info.Issuer.pbData=(unsigned char *)_name->bytes->data; memset(&find_para,0,sizeof(find_para)); find_para.pCertInfo=&cert_info; crl=CertFindCRLInStore(h_store,0,0,CRL_FIND_ISSUED_BY,&find_para,NULL); if(crl==NULL)return 0; x=d2i_X509_CRL(NULL,(const unsigned char **)&crl->pbCrlEncoded, crl->cbCrlEncoded); CertFreeCRLContext(crl); if(x==NULL)return 0; ret=X509_STORE_add_crl(_lu->store_ctx,x); X509_CRL_free(x); if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret); } break; } return 0; }