void ikev2_decode_cert(struct msg_digest *md) { struct payload_digest *p; for (p = md->chain[ISAKMP_NEXT_v2CERT]; p != NULL; p = p->next) { struct ikev2_cert *const v2cert = &p->payload.v2cert; chunk_t blob; time_t valid_until; blob.ptr = p->pbs.cur; blob.len = pbs_left(&p->pbs); if (v2cert->isac_enc == CERT_X509_SIGNATURE) { x509cert_t cert2 = empty_x509cert; if (parse_x509cert(blob, 0, &cert2)) { if (verify_x509cert(&cert2, strict_crl_policy, &valid_until)) { DBG(DBG_X509 | DBG_PARSING, DBG_log("Public key validated") ) add_x509_public_key(NULL, &cert2, valid_until, DAL_SIGNED); } else { plog("X.509 certificate rejected"); } free_generalNames(cert2.subjectAltName, FALSE); free_generalNames(cert2.crlDistributionPoints, FALSE); } else plog("Syntax error in X.509 certificate"); } else if (v2cert->isac_enc == CERT_PKCS7_WRAPPED_X509) { x509cert_t *cert2 = NULL; if (parse_pkcs7_cert(blob, &cert2)) store_x509certs(&cert2, strict_crl_policy); else plog("Syntax error in PKCS#7 wrapped X.509 certificates"); } else { loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload", enum_show(&ikev2_cert_type_names, v2cert->isac_enc)); DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob); } } }
/* * stores a chained list of end certs and CA certs * * @verified_ca is a copied list of the verified authcerts that have * been placed in the global authcert chain */ void store_x509certs(x509cert_t **firstcert, x509cert_t **verified_ca, bool strict) { x509cert_t *cacerts = NULL; x509cert_t **pp = firstcert; /* first extract CA certs, discarding root CA certs */ while (*pp != NULL) { x509cert_t *cert = *pp; if (cert->isCA) { *pp = cert->next; /* we don't accept self-signed CA certs */ if (same_dn(cert->issuer, cert->subject)) { libreswan_log("self-signed cacert rejected"); free_x509cert(cert); } else { /* insertion into temporary chain of candidate CA certs */ cert->next = cacerts; cacerts = cert; } } else { pp = &cert->next; } } /* now verify the candidate CA certs */ x509cert_t *ver = NULL; while (cacerts != NULL) { realtime_t valid_until; x509cert_t *cert = cacerts; cacerts = cacerts->next; if (trust_authcert_candidate(cert, cacerts) && verify_x509cert(cert, strict, &valid_until, cacerts)) { add_authcert(cert, AUTH_CA); if (ver == NULL) { ver = clone_thing(*cert, "x509cert_t"); *verified_ca = ver; } else { ver->next = clone_thing(*cert, "x509cert_t"); ver = ver->next; } ver->next = NULL; } else { libreswan_log("intermediate cacert rejected"); free_x509cert(cert); } } /* now verify the end certificates */ pp = firstcert; while (*pp != NULL) { realtime_t valid_until; x509cert_t *cert = *pp; if (verify_x509cert(cert, strict, &valid_until, NULL)) { DBG(DBG_X509 | DBG_PARSING, DBG_log("public key validated")); add_x509_public_key(NULL, cert, valid_until, DAL_SIGNED); } else { libreswan_log("X.509 certificate rejected"); } *pp = cert->next; free_x509cert(cert); } }