Beispiel #1
0
int
hx509_name_cmp(hx509_name n1, hx509_name n2)
{
    int ret, diff;
    ret = _hx509_name_cmp(&n1->der_name, &n2->der_name, &diff);
    if (ret)
	return ret;
    return diff;
}
Beispiel #2
0
int
hx509_name_cmp(hx509_name n1, hx509_name n2)
{
    return _hx509_name_cmp(&n1->der_name, &n2->der_name);
}
Beispiel #3
0
int
hx509_revoke_verify(hx509_context context,
		    hx509_revoke_ctx ctx,
		    hx509_certs certs,
		    time_t now,
		    hx509_cert cert,
		    hx509_cert parent_cert)
{
    const Certificate *c = _hx509_get_cert(cert);
    const Certificate *p = _hx509_get_cert(parent_cert);
    unsigned long i, j, k;
    int ret;

    hx509_clear_error_string(context);

    for (i = 0; i < ctx->ocsps.len; i++) {
	struct revoke_ocsp *ocsp = &ctx->ocsps.val[i];
	struct stat sb;

	/* check this ocsp apply to this cert */

	/* check if there is a newer version of the file */
	ret = stat(ocsp->path, &sb);
	if (ret == 0 && ocsp->last_modfied != sb.st_mtime) {
	    ret = load_ocsp(context, ocsp);
	    if (ret)
		continue;
	}

	/* verify signature in ocsp if not already done */
	if (ocsp->signer == NULL) {
	    ret = verify_ocsp(context, ocsp, now, certs, parent_cert);
	    if (ret)
		continue;
	}

	for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) {
	    heim_octet_string os;

	    ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber,
				   &c->tbsCertificate.serialNumber);
	    if (ret != 0)
		continue;

	    /* verify issuer hashes hash */
	    ret = _hx509_verify_signature(context,
					  NULL,
					  &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
					  &c->tbsCertificate.issuer._save,
					  &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash);
	    if (ret != 0)
		continue;

	    os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
	    os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;

	    ret = _hx509_verify_signature(context,
					  NULL,
					  &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm,
					  &os,
					  &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash);
	    if (ret != 0)
		continue;

	    switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) {
	    case choice_OCSPCertStatus_good:
		break;
	    case choice_OCSPCertStatus_revoked:
		hx509_set_error_string(context, 0,
				       HX509_CERT_REVOKED,
				       "Certificate revoked by issuer in OCSP");
		return HX509_CERT_REVOKED;
	    case choice_OCSPCertStatus_unknown:
		continue;
	    }

	    /* don't allow the update to be in the future */
	    if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate >
		now + context->ocsp_time_diff)
		continue;

	    /* don't allow the next update to be in the past */
	    if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) {
		if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now)
		    continue;
	    } /* else should force a refetch, but can we ? */

	    return 0;
	}
    }

    for (i = 0; i < ctx->crls.len; i++) {
	struct revoke_crl *crl = &ctx->crls.val[i];
	struct stat sb;
	int diff;

	/* check if cert.issuer == crls.val[i].crl.issuer */
	ret = _hx509_name_cmp(&c->tbsCertificate.issuer,
			      &crl->crl.tbsCertList.issuer, &diff);
	if (ret || diff)
	    continue;

	ret = stat(crl->path, &sb);
	if (ret == 0 && crl->last_modfied != sb.st_mtime) {
	    CRLCertificateList cl;

	    ret = load_crl(crl->path, &crl->last_modfied, &cl);
	    if (ret == 0) {
		free_CRLCertificateList(&crl->crl);
		crl->crl = cl;
		crl->verified = 0;
		crl->failed_verify = 0;
	    }
	}
	if (crl->failed_verify)
	    continue;

	/* verify signature in crl if not already done */
	if (crl->verified == 0) {
	    ret = verify_crl(context, ctx, &crl->crl, now, certs, parent_cert);
	    if (ret) {
		crl->failed_verify = 1;
		continue;
	    }
	    crl->verified = 1;
	}

	if (crl->crl.tbsCertList.crlExtensions) {
	    for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++) {
		if (crl->crl.tbsCertList.crlExtensions->val[j].critical) {
		    hx509_set_error_string(context, 0,
					   HX509_CRL_UNKNOWN_EXTENSION,
					   "Unknown CRL extension");
		    return HX509_CRL_UNKNOWN_EXTENSION;
		}
	    }
	}

	if (crl->crl.tbsCertList.revokedCertificates == NULL)
	    return 0;

	/* check if cert is in crl */
	for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) {
	    time_t t;

	    ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate,
				       &c->tbsCertificate.serialNumber);
	    if (ret != 0)
		continue;

	    t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate);
	    if (t > now)
		continue;

	    if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions)
		for (k = 0; k < crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->len; k++)
		    if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical)
			return HX509_CRL_UNKNOWN_EXTENSION;

	    hx509_set_error_string(context, 0,
				   HX509_CERT_REVOKED,
				   "Certificate revoked by issuer in CRL");
	    return HX509_CERT_REVOKED;
	}

	return 0;
    }


    if (context->flags & HX509_CTX_VERIFY_MISSING_OK)
	return 0;
    hx509_set_error_string(context, HX509_ERROR_APPEND,
			   HX509_REVOKE_STATUS_MISSING,
			   "No revoke status found for "
			   "certificates");
    return HX509_REVOKE_STATUS_MISSING;
}