/* * Verify a chain of DER-encoded certs. * First cert in a chain is root; this must also be present * in ctx->trustedCerts. * * If arePeerCerts is true, host name verification is enabled and we * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise * we're just validating our own certs; no host name checking and * peerSecTrust is transient. */ OSStatus sslVerifyCertChain( SSLContext *ctx, const SSLCertificate *certChain, bool arePeerCerts) { OSStatus ortn = noErr; assert(certChain); /* No point checking our own certs, our clients can do that. */ if (!arePeerCerts) return noErr; CertVerifyReturn cvrtn; /* @@@ Add real cert checking. */ if (certChain->next) { DERItem subject, issuer; issuer.data = certChain->derCert.data; issuer.length = certChain->derCert.length; subject.data = certChain->next->derCert.data; subject.length = certChain->next->derCert.length; cvrtn = certVerify(&subject, &issuer); if (cvrtn != CVR_Success) ortn = errSSLBadCert; } else { sslErrorLog("***sslVerifyCertChain: only one cert in chain\n"); } return ortn; }
int SslOcspStapling::verifyRespFile(int iNeedVerify) { int iResult = -1; BIO *pBio; OCSP_RESPONSE *pResponse; OCSP_BASICRESP *pBasicResp; X509_STORE *pXstore; if (iNeedVerify) pBio = BIO_new_file(m_sRespfileTmp.c_str(), "r"); else pBio = BIO_new_file(m_sRespfile.c_str(), "r"); if (pBio == NULL) return LS_FAIL; pResponse = d2i_OCSP_RESPONSE_bio(pBio, NULL); BIO_free(pBio); if (pResponse == NULL) return LS_FAIL; if (OCSP_response_status(pResponse) == OCSP_RESPONSE_STATUS_SUCCESSFUL) { if (iNeedVerify) { pBasicResp = OCSP_response_get1_basic(pResponse); if (pBasicResp != NULL) { pXstore = SSL_CTX_get_cert_store(m_pCtx); if (pXstore) iResult = certVerify(pResponse, pBasicResp, pXstore); OCSP_BASICRESP_free(pBasicResp); } } else { updateRespData(pResponse); iResult = 0; } } OCSP_RESPONSE_free(pResponse); return iResult; }
/* * A slightly simplified version of certVerify: * -- no CRLs (includes allowUnverified = CSSM_FALSE) * -- revokePOlicy = None * -- no DlDbs * -- no net fetch * -- time = now. */ int certVerifySimple( CSSM_TP_HANDLE tpHand, CSSM_CL_HANDLE clHand, CSSM_CSP_HANDLE cspHand, BlobList &certs, BlobList &roots, CSSM_BOOL useSystemAnchors, CSSM_BOOL leafCertIsCA, CSSM_BOOL allowExpiredRoot, CertVerifyPolicy vfyPolicy, const char *sslHost, // optional, SSL policy CSSM_BOOL sslClient, // normally server side const char *senderEmail, // optional, SMIME CE_KeyUsage intendedKeyUse, // optional, SMIME only const char *expectedErrStr,// e.g., // "CSSMERR_APPLETP_CRL_NOT_TRUSTED" /* * expected per-cert errors * format is certNum:errorString * e.g., "1:CSSMERR_APPLETP_CRL_NOT_TRUSTED" */ unsigned numCertErrors, const char **certErrors, // per-cert status /* * Expected per-cert status (CSSM_TP_APPLE_EVIDENCE_INFO.StatusBits) * format is certNum:status_in_hex * e.g., "1:0x18", leading 0x optional */ unsigned numCertStatus, const char **certStatus, CSSM_BOOL useTrustSettings, CSSM_BOOL quiet, CSSM_BOOL verbose) { CertVerifyArgs vfyArgs; memset(&vfyArgs, 0, sizeof(vfyArgs)); vfyArgs.version = CERT_VFY_ARGS_VERS; vfyArgs.tpHand = tpHand; vfyArgs.clHand = clHand; vfyArgs.cspHand = cspHand; vfyArgs.certs = &certs; vfyArgs.roots = &roots; vfyArgs.useSystemAnchors = useSystemAnchors; vfyArgs.useTrustSettings = useTrustSettings; vfyArgs.leafCertIsCA = leafCertIsCA; vfyArgs.allowExpiredRoot = allowExpiredRoot; vfyArgs.vfyPolicy = vfyPolicy; vfyArgs.sslHost = sslHost; vfyArgs.sslClient = sslClient; vfyArgs.senderEmail = senderEmail; vfyArgs.intendedKeyUse = intendedKeyUse; vfyArgs.allowUnverified = CSSM_TRUE; vfyArgs.expectedErrStr = expectedErrStr; vfyArgs.numCertErrors = numCertErrors; vfyArgs.certErrors = certErrors; vfyArgs.numCertStatus = numCertStatus; vfyArgs.certStatus = certStatus; vfyArgs.quiet = quiet; vfyArgs.verbose = verbose; return certVerify(&vfyArgs); }
int main(int argc, char **argv) { BlobList certs; BlobList roots; BlobList crls; int rtn; CSSM_DL_HANDLE dlHand; int loop; int arg; char *argp; CSSM_DL_DB_HANDLE_PTR crlDbHandPtr = NULL; CSSM_DL_DB_LIST dlDbList; CSSM_DL_DB_HANDLE dlDbHandles[2]; CSSM_RETURN crtn; CSSM_RETURN silent = CSSM_FALSE; CSSM_BOOL scriptPause = CSSM_FALSE; CertVerifyArgs vfyArgs; memset(&vfyArgs, 0, sizeof(vfyArgs)); vfyArgs.version = CERT_VFY_ARGS_VERS; vfyArgs.certs = &certs; vfyArgs.roots = &roots; vfyArgs.crls = &crls; /* for historical reasons the defaults for these are true */ vfyArgs.crlNetFetchEnable = CSSM_TRUE; vfyArgs.certNetFetchEnable = CSSM_TRUE; /* user-specd variables */ int loops = 1; const char *crlDbName = NULL; const char *certDbName = NULL; char *scriptFile = NULL; if(argc < 2) { usage(argv); } for(arg=1; arg<argc; arg++) { argp = argv[arg]; if(argp[0] != '-') { usage(argv); } switch(argp[1]) { case 'l': loops = atoi(&argp[3]); break; case 'r': arg++; gatherFiles(crls, argv, argc, arg); break; case 'c': arg++; gatherFiles(certs, argv, argc, arg); break; case 'C': arg++; gatherFiles(roots, argv, argc, arg); break; case 'v': vfyArgs.verbose = CSSM_TRUE; break; case 'q': vfyArgs.quiet = CSSM_TRUE; break; case 's': vfyArgs.useSystemAnchors = CSSM_TRUE; break; case 'g': vfyArgs.useTrustSettings = CSSM_TRUE; break; case 'i': vfyArgs.implicitAnchors = CSSM_TRUE; break; case 'a': vfyArgs.allowUnverified = CSSM_TRUE; break; case 'e': vfyArgs.expectedErrStr = &argp[3]; break; case 'n': vfyArgs.crlNetFetchEnable = CSSM_FALSE; break; case 'N': vfyArgs.certNetFetchEnable = CSSM_FALSE; break; case 'f': vfyArgs.leafCertIsCA = CSSM_TRUE; break; case 'd': arg++; if(arg == argc) { usage(argv); } certDbName = argv[arg]; break; case 'D': arg++; if(arg == argc) { usage(argv); } crlDbName = argv[arg]; break; case 'S': arg++; if(arg == argc) { usage(argv); } scriptFile = argv[arg]; break; case 'h': arg++; if(arg == argc) { usage(argv); } vfyArgs.sslHost= argv[arg]; vfyArgs.vfyPolicy = CVP_SSL; break; case 'E': arg++; if(arg == argc) { usage(argv); } if(vfyArgs.vfyPolicy == CVP_Basic) { /* user hasn't specified; now default to SMIME - still * can override (e.g., for iChat) */ vfyArgs.vfyPolicy = CVP_SMIME; } vfyArgs.senderEmail = argv[arg]; break; case 'k': arg++; if(arg == argc) { usage(argv); } vfyArgs.intendedKeyUse = hexToBin(argv[arg]); break; case 't': vfyArgs.sslClient = CSSM_TRUE; vfyArgs.vfyPolicy = CVP_SSL; break; case 'y': arg++; if(arg == argc) { usage(argv); } argp = argv[arg]; if(parsePolicyString(argp, &vfyArgs.vfyPolicy)) { printf("Bogus policyValue (%s)\n", argp); printPolicyStrings(); exit(1); } break; case 'R': arg++; if(arg == argc) { usage(argv); } argp = argv[arg]; if(!strcmp(argp, "none")) { vfyArgs.revokePolicy = CRP_None; } else if(!strcmp(argp, "crl")) { vfyArgs.revokePolicy = CRP_CRL; } else if(!strcmp(argp, "ocsp")) { vfyArgs.revokePolicy = CRP_OCSP; } else if(!strcmp(argp, "both")) { vfyArgs.revokePolicy = CRP_CRL_OCSP; } else { usage(argv); } break; case 'u': arg++; if(arg == argc) { usage(argv); } vfyArgs.responderURI = argv[arg]; /* no implied policy yet - could be CRP_OCSP or CRP_CRL_OCSP */ break; case 'U': if(readFile(argv[arg], (unsigned char **)vfyArgs.responderCert, &vfyArgs.responderCertLen)) { printf("***Error reading responderCert from %s. Aborting.\n", argv[arg]); exit(1); } /* no implied policy yet - could be CRP_OCSP or CRP_CRL_OCSP */ break; case 'H': vfyArgs.disableCache = CSSM_TRUE; break; case 'W': vfyArgs.disableOcspNet = CSSM_TRUE; break; case 'Q': vfyArgs.requireOcspIfPresent = CSSM_TRUE; break; case '5': vfyArgs.requireOcspForAll = CSSM_TRUE; break; case 'o': vfyArgs.generateOcspNonce = CSSM_TRUE; break; case 'O': vfyArgs.requireOcspRespNonce = CSSM_TRUE; break; case 'A': vfyArgs.requireCrlIfPresent = CSSM_TRUE; break; case '4': vfyArgs.requireCrlForAll = CSSM_TRUE; break; case 'T': arg++; if(arg == argc) { usage(argv); } vfyArgs.vfyTime = argv[arg]; break; case 'p': printScriptVars(); exit(0); case 'P': scriptPause = CSSM_TRUE; break; case 'L': silent = CSSM_TRUE; // inhibits start banner vfyArgs.quiet = CSSM_TRUE; // inhibits stdout from certVerify break; default: usage(argv); } } if((vfyArgs.responderCert != NULL) || (vfyArgs.responderURI != NULL)) { switch(vfyArgs.revokePolicy) { case CRP_None: vfyArgs.revokePolicy = CRP_OCSP; break; case CRP_OCSP: case CRP_CRL_OCSP: break; case CRP_CRL: printf("*** OCSP options (responderURI, responderCert) only valid " "with OCSP policy\n"); usage(argv); } } vfyArgs.clHand = clStartup(); if(vfyArgs.clHand == CSSM_INVALID_HANDLE) { return 1; } vfyArgs.tpHand = tpStartup(); if(vfyArgs.tpHand == CSSM_INVALID_HANDLE) { return 1; } vfyArgs.cspHand = cspStartup(); if(vfyArgs.cspHand == CSSM_INVALID_HANDLE) { return 1; } dlHand = dlStartup(); if(dlHand == CSSM_INVALID_HANDLE) { return 1; } if(!silent) { testStartBanner("certcrl", argc, argv); } if(scriptFile) { ScriptVars vars; vars.allowUnverified = vfyArgs.allowUnverified; vars.requireCrlIfPresent = vfyArgs.requireCrlIfPresent; vars.requireOcspIfPresent = vfyArgs.requireOcspIfPresent; vars.crlNetFetchEnable = vfyArgs.crlNetFetchEnable; vars.certNetFetchEnable = vfyArgs.certNetFetchEnable; vars.useSystemAnchors = vfyArgs.useSystemAnchors; vars.useTrustSettings = vfyArgs.useTrustSettings; vars.leafCertIsCA = vfyArgs.leafCertIsCA; vars.cacheDisable = vfyArgs.disableCache; vars.ocspNetFetchDisable = vfyArgs.disableOcspNet; vars.requireCrlForAll = vfyArgs.requireCrlForAll; vars.requireOcspForAll = vfyArgs.requireOcspForAll; return runScript(scriptFile, vfyArgs.tpHand, vfyArgs.clHand, vfyArgs.cspHand, dlHand, &vars, vfyArgs.quiet, vfyArgs.verbose, scriptPause); } /* open DlDbs if enabled */ dlDbList.NumHandles = 0; dlDbList.DLDBHandle = &dlDbHandles[0]; dlDbList.DLDBHandle[0].DLHandle = dlHand; dlDbList.DLDBHandle[1].DLHandle = dlHand; if(certDbName != NULL) { crtn = CSSM_DL_DbOpen(dlHand, certDbName, NULL, // DbLocation CSSM_DB_ACCESS_READ, NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred NULL, // void *OpenParameters &dlDbList.DLDBHandle[0].DBHandle); if(crtn) { printError("CSSM_DL_DbOpen", crtn); printf("***Error opening DB %s. Aborting.\n", certDbName); return 1; } dlDbList.NumHandles++; vfyArgs.dlDbList = &dlDbList; } if(crlDbName != NULL) { vfyArgs.crlDlDb = &dlDbList.DLDBHandle[dlDbList.NumHandles]; crtn = CSSM_DL_DbOpen(dlHand, crlDbName, NULL, // DbLocation CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred NULL, // void *OpenParameters &crlDbHandPtr->DBHandle); if(crtn) { printError("CSSM_DL_DbOpen", crtn); printf("***Error opening DB %s. Aborting.\n", crlDbName); return 1; } dlDbList.NumHandles++; vfyArgs.dlDbList = &dlDbList; } for(loop=0; loop<loops; loop++) { rtn = certVerify(&vfyArgs); if(rtn) { break; } if(loops != 1) { fpurge(stdin); printf("CR to continue, q to quit: "); char c = getchar(); if(c == 'q') { break; } } } return rtn; }