diff options
Diffstat (limited to 'src/pluto/ocsp.c')
-rw-r--r-- | src/pluto/ocsp.c | 151 |
1 files changed, 83 insertions, 68 deletions
diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c index da81ce2d8..510667e67 100644 --- a/src/pluto/ocsp.c +++ b/src/pluto/ocsp.c @@ -283,18 +283,29 @@ static const asn1Object_t singleResponseObjects[] = { */ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) { + certificate_t *certificate = cert->cert; + identification_t *issuer = certificate->get_issuer(certificate); + x509_t *x509 = (x509_t*)certificate; + chunk_t issuer_dn = issuer->get_encoding(issuer); + chunk_t authKeyID = x509->get_authKeyIdentifier(x509); hasher_t *hasher; static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */ - location->uri = cert->accessLocation; + enumerator_t *enumerator = x509->create_ocsp_uri_enumerator(x509); - if (location->uri.ptr == NULL) + location->uri = NULL; + while (enumerator->enumerate(enumerator, &location->uri)) { - ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID); + break; + } + enumerator->destroy(enumerator); + + if (location->uri == NULL) + { + ca_info_t *ca = get_ca_info(issuer_dn, authKeyID); if (ca != NULL && ca->ocspuri != NULL) { - location->uri = chunk_create(ca->ocspuri, strlen(ca->ocspuri)); + location->uri = ca->ocspuri; } else { /* abort if no ocsp location uri is defined */ @@ -309,23 +320,22 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio { return FALSE; } - hasher->get_hash(hasher, cert->issuer, digest); + hasher->get_hash(hasher, issuer_dn, digest); hasher->destroy(hasher); location->next = NULL; - location->issuer = cert->issuer; - location->authKeyID = cert->authKeyID; - location->authKeySerialNumber = cert->authKeySerialNumber; + location->issuer = issuer_dn; + location->authKeyID = authKeyID; - if (cert->authKeyID.ptr == NULL) + if (authKeyID.ptr == NULL) { - x509cert_t *authcert = get_authcert(cert->issuer - , cert->authKeySerialNumber, cert->authKeyID, AUTH_CA); + x509cert_t *authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA); if (authcert != NULL) { - location->authKeyID = authcert->subjectKeyID; - location->authKeySerialNumber = authcert->serialNumber; + x509_t *x509 = (x509_t*)authcert->cert; + + location->authKeyID = x509->get_subjectKeyIdentifier(x509); } } @@ -342,9 +352,8 @@ static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t * { return ((a->authKeyID.ptr != NULL) ? same_keyid(a->authKeyID, b->authKeyID) - : (same_dn(a->issuer, b->issuer) - && same_serial(a->authKeySerialNumber, b->authKeySerialNumber))) - && chunk_equals(a->uri, b->uri); + : same_dn(a->issuer, b->issuer)) + && streq(a->uri, b->uri); } /** @@ -411,6 +420,8 @@ cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until, time_t *revocationDate, crl_reason_t *revocationReason) { + x509_t *x509 = (x509_t*)cert->cert; + chunk_t serialNumber = x509->get_serial(x509); cert_status_t status; ocsp_location_t location; time_t nextUpdate = 0; @@ -420,17 +431,19 @@ cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until, /* is an ocsp location defined? */ if (!build_ocsp_location(cert, &location)) + { return CERT_UNDEFINED; + } lock_ocsp_cache("verify_by_ocsp"); - status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate + status = get_ocsp_status(&location, serialNumber, &nextUpdate , revocationDate, revocationReason); unlock_ocsp_cache("verify_by_ocsp"); if (status == CERT_UNDEFINED || nextUpdate < time(NULL)) { plog("ocsp status is stale or not in cache"); - add_ocsp_fetch_request(&location, cert->serialNumber); + add_ocsp_fetch_request(&location, serialNumber); /* inititate fetching of ocsp status */ wake_fetch_thread("verify_by_ocsp"); @@ -521,8 +534,7 @@ static void free_ocsp_location(ocsp_location_t* location) free(location->issuer.ptr); free(location->authNameID.ptr); free(location->authKeyID.ptr); - free(location->authKeySerialNumber.ptr); - free(location->uri.ptr); + free(location->uri); free_certinfos(location->certinfo); free(location); } @@ -588,8 +600,7 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests, dntoa(buf, BUF_LEN, location->issuer); whack_log(RC_COMMENT, " issuer: '%s'", buf); } - whack_log(RC_COMMENT, " uri: '%.*s'", (int)location->uri.len - , location->uri.ptr); + whack_log(RC_COMMENT, " uri: '%s'", location->uri); if (location->authNameID.ptr != NULL) { datatot(location->authNameID.ptr, location->authNameID.len, ':' @@ -602,12 +613,6 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests, , buf, BUF_LEN); whack_log(RC_COMMENT, " authkey: %s", buf); } - if (location->authKeySerialNumber.ptr != NULL) - { - datatot(location->authKeySerialNumber.ptr - , location->authKeySerialNumber.len, ':', buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); - } while (certinfo != NULL) { char thisUpdate[BUF_LEN]; @@ -662,17 +667,17 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location) for (;;) { - char buf[BUF_LEN]; + certificate_t *certificate; /* looking for a certificate from the same issuer */ - cert = get_x509cert(location->issuer, location->authKeySerialNumber - ,location->authKeyID, cert); + cert = get_x509cert(location->issuer, location->authKeyID, cert); if (cert == NULL) + { break; - + } + certificate = cert->cert; DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, cert->subject); - DBG_log("candidate: '%s'", buf); + DBG_log("candidate: '%Y'", certificate->get_subject(certificate)); ) if (cert->smartcard) @@ -774,7 +779,7 @@ static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc) */ static chunk_t build_signature(chunk_t tbsRequest) { - chunk_t sigdata, certs; + chunk_t sigdata, cert, certs; if (ocsp_requestor_sc != NULL) { @@ -793,11 +798,9 @@ static chunk_t build_signature(chunk_t tbsRequest) } /* include our certificate */ - certs = asn1_wrap(ASN1_CONTEXT_C_0, "m" - , asn1_simple_object(ASN1_SEQUENCE - , ocsp_requestor_cert->certificate - ) - ); + cert = ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert); + certs = asn1_wrap(ASN1_CONTEXT_C_0, "m", + asn1_wrap(ASN1_SEQUENCE, "m", cert)); /* build signature comprising algorithm, signature and cert */ return asn1_wrap(ASN1_CONTEXT_C_0, "m" @@ -872,9 +875,12 @@ static chunk_t build_request_list(ocsp_location_t *location) */ static chunk_t build_requestor_name(void) { + certificate_t *certificate = ocsp_requestor_cert->cert; + identification_t *subject = certificate->get_subject(certificate); + return asn1_wrap(ASN1_CONTEXT_C_1, "m" , asn1_simple_object(ASN1_CONTEXT_C_4 - , ocsp_requestor_cert->subject)); + , subject->get_encoding(subject))); } /** @@ -976,9 +982,8 @@ static bool valid_ocsp_response(response_t *res) lock_authcert_list("valid_ocsp_response"); - authcert = get_authcert(res->responder_id_name, chunk_empty - , res->responder_id_key, AUTH_OCSP | AUTH_CA); - + authcert = get_authcert(res->responder_id_name, res->responder_id_key, + AUTH_OCSP | AUTH_CA); if (authcert == NULL) { plog("no matching ocsp signer cert found"); @@ -989,7 +994,8 @@ static bool valid_ocsp_response(response_t *res) DBG_log("ocsp signer cert found") ) - if (!x509_check_signature(res->tbs, res->signature, res->algorithm, authcert)) + if (!x509_check_signature(res->tbs, res->signature, res->algorithm, + authcert->cert)) { plog("signature of ocsp response is invalid"); unlock_authcert_list("valid_ocsp_response"); @@ -1002,22 +1008,22 @@ static bool valid_ocsp_response(response_t *res) for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { - u_char buf[BUF_LEN]; err_t ugh = NULL; time_t until; x509cert_t *cert = authcert; + certificate_t *certificate = cert->cert; + x509_t *x509 = (x509_t*)certificate; + identification_t *subject = certificate->get_subject(certificate); + identification_t *issuer = certificate->get_issuer(certificate); + chunk_t authKeyID = x509->get_authKeyIdentifier(x509); DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, cert->subject); - DBG_log("subject: '%s'",buf); - dntoa(buf, BUF_LEN, cert->issuer); - DBG_log("issuer: '%s'",buf); - if (cert->authKeyID.ptr != NULL) + DBG_log("subject: '%Y'", subject); + DBG_log("issuer: '%Y'", issuer); + if (authKeyID.ptr != NULL) { - datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' - , buf, BUF_LEN); - DBG_log("authkey: %s", buf); + DBG_log("authkey: %#B", &authKeyID); } ) @@ -1034,9 +1040,7 @@ static bool valid_ocsp_response(response_t *res) DBG_log("certificate is valid") ) - authcert = get_authcert(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID, AUTH_CA); - + authcert = get_authcert(issuer->get_encoding(issuer), authKeyID, AUTH_CA); if (authcert == NULL) { plog("issuer cacert not found"); @@ -1047,8 +1051,7 @@ static bool valid_ocsp_response(response_t *res) DBG_log("issuer cacert found") ) - if (!x509_check_signature(cert->tbsCertificate, cert->signature, - cert->algorithm, authcert)) + if (!certificate->issued_by(certificate, authcert->cert)) { plog("certificate signature is invalid"); unlock_authcert_list("valid_ocsp_response"); @@ -1059,7 +1062,7 @@ static bool valid_ocsp_response(response_t *res) ) /* check if cert is self-signed */ - if (same_dn(cert->issuer, cert->subject)) + if (x509->get_flags(x509) & X509_SELF_SIGNED) { DBG(DBG_CONTROL, DBG_log("reached self-signed root ca") @@ -1143,14 +1146,27 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) break; case BASIC_RESPONSE_CERTIFICATE: { - chunk_t blob = chunk_clone(object); x509cert_t *cert = malloc_thing(x509cert_t); + x509_t *x509; *cert = empty_x509cert; - - if (parse_x509cert(blob, parser->get_level(parser)+1, cert) - && cert->isOcspSigner - && trust_authcert_candidate(cert, NULL)) + cert->cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, object, + BUILD_END); + if (cert->cert == NULL) + { + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log("parsing of embedded ocsp certificate failed") + ) + free_x509cert(cert); + break; + } + time(&cert->installed); + x509 = (x509_t*)cert->cert; + + if ((x509->get_flags(x509) & X509_OCSP_SIGNER) && + trust_authcert_candidate(cert, NULL)) { add_authcert(cert, AUTH_OCSP); } @@ -1322,8 +1338,7 @@ ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc, location->issuer = chunk_clone(loc->issuer); location->authNameID = chunk_clone(loc->authNameID); location->authKeyID = chunk_clone(loc->authKeyID); - location->authKeySerialNumber = chunk_clone(loc->authKeySerialNumber); - location->uri = chunk_clone(loc->uri); + location->uri = strdup(loc->uri); location->certinfo = NULL; /* insert new ocsp location in front of chain */ |