Example #1
0
/*
 * 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;
}
Example #2
0
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;
}