📄 x509.c
字号:
same_x509cert(const x509cert_t *a, const x509cert_t *b){ return same_chunk(a->signature, b->signature);}/* for each link pointing to the certificate " increase the count by one */voidshare_x509cert(x509cert_t *cert){ if (cert != NULL) cert->count++;}/* * add a X.509 user/host certificate to the chained list */x509cert_t*add_x509cert(x509cert_t *cert){ x509cert_t *c = x509certs; while (c != NULL) { if (same_x509cert(c, cert)) /* already in chain, free cert */ { free_x509cert(cert); return c; } c = c->next; } /* insert new cert at the root of the chain */ lock_certs_and_keys("add_x509cert"); cert->next = x509certs; x509certs = cert; unlock_certs_and_keys("add_x509cert"); return cert;}/* * choose either subject DN or a subjectAltName as connection end ID */voidselect_x509cert_id(x509cert_t *cert, struct id *end_id){ bool copy_subject_dn = TRUE; /* ID is subject DN */ if (end_id->kind != ID_NONE) /* check for matching subjectAltName */ { generalName_t *gn = cert->subjectAltName; while (gn != NULL) { struct id id = empty_id; gntoid(&id, gn); if (same_id(&id, end_id)) { copy_subject_dn = FALSE; /* take subjectAltName instead */ break; } gn = gn->next; } } if (copy_subject_dn) { if (end_id->kind != ID_NONE && end_id->kind != ID_DER_ASN1_DN) { char buf[IDTOA_BUF]; idtoa(end_id, buf, IDTOA_BUF); openswan_log(" no subjectAltName matches ID '%s', replaced by subject DN", buf); } end_id->kind = ID_DER_ASN1_DN; end_id->name.len = cert->subject.len; end_id->name.ptr = temporary_cyclic_buffer(); memcpy(end_id->name.ptr, cert->subject.ptr, cert->subject.len); }}/* * check for equality between two key identifiers */boolsame_keyid(chunk_t a, chunk_t b){ if (a.ptr == NULL || b.ptr == NULL) return FALSE; return same_chunk(a, b);}/* * check for equality between two serial numbers */boolsame_serial(chunk_t a, chunk_t b){ /* do not compare serial numbers if one of them is not defined */ if (a.ptr == NULL || b.ptr == NULL) return TRUE; return same_chunk(a, b);}/* * get a X.509 certificate with a given issuer found at a certain position */x509cert_t*get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid, x509cert_t *chain){ x509cert_t *cert = (chain != NULL)? chain->next : x509certs; while (cert != NULL) { if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->authKeyID) : (same_dn(issuer, cert->issuer) && same_serial(serial, cert->authKeySerialNumber))) { return cert; } cert = cert->next; } return NULL;}/* * get a X.509 authority certificate with a given subject or keyid */x509cert_t*get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags){ x509cert_t *cert = x509authcerts; x509cert_t *prev_cert = NULL; while (cert != NULL) { if (cert->authority_flags & auth_flags && ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) : (same_dn(subject, cert->subject) && same_serial(serial, cert->serialNumber)))) { if (cert != x509authcerts) { /* bring the certificate up front */ prev_cert->next = cert->next; cert->next = x509authcerts; x509authcerts = cert; } return cert; } prev_cert = cert; cert = cert->next; } return NULL;}/* * Checks if CA a is trusted by CA b */booltrusted_ca(chunk_t a, chunk_t b, int *pathlen){ bool match = FALSE; char abuf[BUF_LEN], bbuf[BUF_LEN]; dntoa(abuf, BUF_LEN, a); dntoa(bbuf, BUF_LEN, b); DBG(DBG_X509 | DBG_CONTROLMORE , DBG_log(" trusted_ca called with a=%s b=%s" , abuf, bbuf)); /* no CA b specified -> any CA a is accepted */ if (b.ptr == NULL) { *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN; return TRUE; } /* no CA a specified -> trust cannot be established */ if (a.ptr == NULL) { *pathlen = MAX_CA_PATH_LEN; return FALSE; } *pathlen = 0; /* CA a equals CA b -> we have a match */ if (same_dn(a, b)) return TRUE; /* CA a might be a subordinate CA of b */ lock_authcert_list("trusted_ca"); while ((*pathlen)++ < MAX_CA_PATH_LEN) { x509cert_t *cacert = get_authcert(a, empty_chunk, empty_chunk, AUTH_CA); /* cacert not found or self-signed root cacert-> exit */ if (cacert == NULL || same_dn(cacert->issuer, a)) break; /* does the issuer of CA a match CA b? */ match = same_dn(cacert->issuer, b); /* we have a match and exit the loop */ if (match) break; /* go one level up in the CA chain */ a = cacert->issuer; } unlock_authcert_list("trusted_ca"); DBG(DBG_X509 | DBG_CONTROLMORE , DBG_log(" trusted_ca returning with %s", match ? "match" : "failed")); return match;}/* * does our CA match one of the requested CAs? */boolmatch_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen){ /* if no ca is requested than any ca will match */ if (requested_ca == NULL) { *our_pathlen = 0; return TRUE; } *our_pathlen = MAX_CA_PATH_LEN + 1; while (requested_ca != NULL) { int pathlen; if (trusted_ca(our_ca, requested_ca->name, &pathlen) && pathlen < *our_pathlen) *our_pathlen = pathlen; requested_ca = requested_ca->next; } return *our_pathlen <= MAX_CA_PATH_LEN;}/* * get the X.509 CRL with a given issuer */static x509crl_t*get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid){ x509crl_t *crl = x509crls; x509crl_t *prev_crl = NULL; while(crl != NULL) { if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL) ? same_keyid(keyid, crl->authKeyID) : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber))) { if (crl != x509crls) { /* bring the CRL up front */ prev_crl->next = crl->next; crl->next = x509crls; x509crls = crl; } return crl; } prev_crl = crl; crl = crl->next; } return NULL;}/* * free the dynamic memory used to store generalNames */voidfree_generalNames(generalName_t* gn, bool free_name){ while (gn != NULL) { generalName_t *gn_top = gn; if (free_name) { pfree(gn->name.ptr); } gn = gn->next; pfree(gn_top); }}/* * free a X.509 certificate */voidfree_x509cert(x509cert_t *cert){ if (cert != NULL) { free_generalNames(cert->subjectAltName, FALSE); free_generalNames(cert->crlDistributionPoints, FALSE); pfreeany(cert->certificate.ptr); pfree(cert); cert = NULL; }}/* release of a certificate decreases the count by one " the certificate is freed when the counter reaches zero */voidrelease_x509cert(x509cert_t *cert){ if (cert != NULL && --cert->count == 0) { x509cert_t **pp = &x509certs; while (*pp != cert) pp = &(*pp)->next; lock_certs_and_keys("release_x509cert"); *pp = cert->next; unlock_certs_and_keys("release_x509cert"); free_x509cert(cert); }}/* * free the first authority certificate in the chain */static voidfree_first_authcert(void){ x509cert_t *first = x509authcerts; x509authcerts = first->next; free_x509cert(first);}/* * free all CA certificates */voidfree_authcerts(void){ lock_authcert_list("free_authcerts"); while (x509authcerts != NULL) free_first_authcert(); unlock_authcert_list("free_authcerts");}/* * free the dynamic memory used to store revoked certificates */static voidfree_revoked_certs(revokedCert_t* revokedCerts){ while (revokedCerts != NULL) { revokedCert_t * revokedCert = revokedCerts; revokedCerts = revokedCert->next; pfree(revokedCert); }}/* * free the dynamic memory used to store CRLs */voidfree_crl(x509crl_t *crl){ free_revoked_certs(crl->revokedCertificates); free_generalNames(crl->distributionPoints, TRUE); pfree(crl->certificateList.ptr); pfree(crl);}static voidfree_first_crl(void){ x509crl_t *crl = x509crls; x509crls = crl->next; free_crl(crl);}voidfree_crls(void){ lock_crl_list("free_crls"); while (x509crls != NULL) free_first_crl(); unlock_crl_list("free_crls");}/* * add an authority certificate to the chained list */voidadd_authcert(x509cert_t *cert, u_char auth_flags){ x509cert_t *old_cert; /* set authority flags */ cert->authority_flags |= auth_flags; lock_authcert_list("add_authcert"); old_cert = get_authcert(cert->subject, cert->serialNumber , cert->subjectKeyID, auth_flags); if (old_cert != NULL) { if (same_x509cert(cert, old_cert)) { /* cert is already present, just add additional authority flags */ old_cert->authority_flags |= cert->authority_flags; DBG(DBG_X509 | DBG_PARSING , DBG_log(" authcert is already present and identical") ) unlock_authcert_list("add_authcert"); free_x509cert(cert); return; } else { /* cert is already present but will be replaced by new cert */ free_first_authcert(); DBG(DBG_X509 | DBG_PARSING , DBG_log(" existing authcert deleted") ) } } /* add new authcert to chained list */ cert->next = x509authcerts; x509authcerts = cert; share_x509cert(cert); /* set count to one */ DBG(DBG_X509 | DBG_PARSING, DBG_log(" authcert inserted") ) unlock_authcert_list("add_authcert");}/* * Loads authority certificates */voidload_authcerts(const char *type, const char *path, u_char auth_flags){ struct dirent **filelist; u_char buf[BUF_LEN]; u_char *save_dir; int n; /* change directory to specified path */ save_dir = getcwd(buf, BUF_LEN); if (chdir(path)) { openswan_log("Could not change to directory '%s'", path); } else { openswan_log("Changing to directory '%s'", path); n = scandir(path, &filelist, file_select, alphasort); if (n < 0) openswan_log(" scandir() error"); else { while (n--) { cert_t cert; if (load_cert(CERT_NONE, filelist[n]->d_name, type, &cert)) add_authcert(cert.u.x509, auth_flags); free(filelist[n]); } free(filelist); } } /* restore directory path */ chdir(save_dir);}/* * stores a chained list of end certs and CA certs */voidstore_x509certs(x509cert_t **firstcert, bool strict){ x509cert_t *cacerts = NULL; x509cert_t **pp = firstcert; /* first extract CA certs, discarding root CA certs */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -