pluto and scepclient now use the x509 plugin for certificates
This commit is contained in:
+83
-68
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user