diff options
Diffstat (limited to 'src/pluto/ca.c')
-rw-r--r-- | src/pluto/ca.c | 923 |
1 files changed, 457 insertions, 466 deletions
diff --git a/src/pluto/ca.c b/src/pluto/ca.c index 816db53a8..4fdb8cfe7 100644 --- a/src/pluto/ca.c +++ b/src/pluto/ca.c @@ -10,8 +10,6 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * RCSID $Id: ca.c 4709 2008-11-27 10:20:25Z martin $ */ #include <stdlib.h> @@ -23,7 +21,6 @@ #include <sys/types.h> #include <freeswan.h> -#include <ipsec_policy.h> #include "constants.h" #include "defs.h" @@ -40,17 +37,17 @@ static x509cert_t *x509authcerts = NULL; const ca_info_t empty_ca_info = { - NULL , /* next */ - NULL , /* name */ - UNDEFINED_TIME, - { NULL, 0 } , /* authName */ - { NULL, 0 } , /* authKeyID */ - { NULL, 0 } , /* authKey SerialNumber */ - NULL , /* ldaphost */ - NULL , /* ldapbase */ - NULL , /* ocspori */ - NULL , /* crluri */ - FALSE /* strictcrlpolicy */ + NULL , /* next */ + NULL , /* name */ + UNDEFINED_TIME, + { NULL, 0 } , /* authName */ + { NULL, 0 } , /* authKeyID */ + { NULL, 0 } , /* authKey SerialNumber */ + NULL , /* ldaphost */ + NULL , /* ldapbase */ + NULL , /* ocspori */ + NULL , /* crluri */ + FALSE /* strictcrlpolicy */ }; /* chained list of X.509 certification authority information records */ @@ -63,52 +60,52 @@ static ca_info_t *ca_infos = NULL; bool trusted_ca(chunk_t a, chunk_t b, int *pathlen) { - bool match = FALSE; - - /* 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; - } + bool match = FALSE; + + /* 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; + *pathlen = 0; - /* CA a equals CA b -> we have a match */ - if (same_dn(a, b)) - return TRUE; + /* 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"); + /* 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); + while ((*pathlen)++ < MAX_CA_PATH_LEN) + { + x509cert_t *cacert = get_authcert(a, chunk_empty, chunk_empty, AUTH_CA); - /* cacert not found or self-signed root cacert-> exit */ - if (cacert == NULL || same_dn(cacert->issuer, a)) - break; + /* 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); + /* 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; + /* 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"); - return match; + /* go one level up in the CA chain */ + a = cacert->issuer; + } + + unlock_authcert_list("trusted_ca"); + return match; } /* @@ -117,36 +114,36 @@ trusted_ca(chunk_t a, chunk_t b, int *pathlen) bool match_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; + /* if no ca is requested than any ca will match */ + if (requested_ca == NULL) + { + *our_pathlen = 0; + return TRUE; + } - while (requested_ca != NULL) - { - int pathlen; + *our_pathlen = MAX_CA_PATH_LEN + 1; - if (trusted_ca(our_ca, requested_ca->name, &pathlen) - && pathlen < *our_pathlen) + while (requested_ca != NULL) { - *our_pathlen = pathlen; + int pathlen; + + if (trusted_ca(our_ca, requested_ca->name, &pathlen) + && pathlen < *our_pathlen) + { + *our_pathlen = pathlen; + } + requested_ca = requested_ca->next; } - requested_ca = requested_ca->next; - } - if (*our_pathlen > MAX_CA_PATH_LEN) - { - *our_pathlen = MAX_CA_PATH_LEN; - return FALSE; - } - else - { - return TRUE; - } + if (*our_pathlen > MAX_CA_PATH_LEN) + { + *our_pathlen = MAX_CA_PATH_LEN; + return FALSE; + } + else + { + return TRUE; + } } /* @@ -155,9 +152,9 @@ match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen static void free_first_authcert(void) { - x509cert_t *first = x509authcerts; - x509authcerts = first->next; - free_x509cert(first); + x509cert_t *first = x509authcerts; + x509authcerts = first->next; + free_x509cert(first); } /* @@ -166,12 +163,12 @@ free_first_authcert(void) void free_authcerts(void) { - lock_authcert_list("free_authcerts"); + lock_authcert_list("free_authcerts"); - while (x509authcerts != NULL) - free_first_authcert(); + while (x509authcerts != NULL) + free_first_authcert(); - unlock_authcert_list("free_authcerts"); + unlock_authcert_list("free_authcerts"); } /* @@ -180,29 +177,29 @@ free_authcerts(void) 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)))) + x509cert_t *cert = x509authcerts; + x509cert_t *prev_cert = NULL; + + while (cert != NULL) { - if (cert != x509authcerts) - { - /* bring the certificate up front */ - prev_cert->next = cert->next; - cert->next = x509authcerts; - x509authcerts = cert; - } - return cert; + 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; } - prev_cert = cert; - cert = cert->next; - } - return NULL; + return NULL; } /* @@ -211,49 +208,49 @@ get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags) x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags) { - x509cert_t *old_cert; + x509cert_t *old_cert; - /* set authority flags */ - cert->authority_flags |= auth_flags; + /* set authority flags */ + cert->authority_flags |= auth_flags; - lock_authcert_list("add_authcert"); + lock_authcert_list("add_authcert"); - old_cert = get_authcert(cert->subject, cert->serialNumber - , cert->subjectKeyID, auth_flags); + 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_CONTROL | DBG_PARSING , - DBG_log(" authcert is already present and identical") - ) - unlock_authcert_list("add_authcert"); - - free_x509cert(cert); - return old_cert; - } - else + if (old_cert != NULL) { - /* cert is already present but will be replaced by new cert */ - free_first_authcert(); - DBG(DBG_CONTROL | DBG_PARSING , - DBG_log(" existing authcert deleted") - ) + if (same_x509cert(cert, old_cert)) + { + /* cert is already present, just add additional authority flags */ + old_cert->authority_flags |= cert->authority_flags; + DBG(DBG_CONTROL | DBG_PARSING , + DBG_log(" authcert is already present and identical") + ) + unlock_authcert_list("add_authcert"); + + free_x509cert(cert); + return old_cert; + } + else + { + /* cert is already present but will be replaced by new cert */ + free_first_authcert(); + DBG(DBG_CONTROL | 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_CONTROL | DBG_PARSING, - DBG_log(" authcert inserted") - ) - unlock_authcert_list("add_authcert"); - return cert; + + /* add new authcert to chained list */ + cert->next = x509authcerts; + x509authcerts = cert; + share_x509cert(cert); /* set count to one */ + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log(" authcert inserted") + ) + unlock_authcert_list("add_authcert"); + return cert; } /* @@ -262,41 +259,41 @@ add_authcert(x509cert_t *cert, u_char auth_flags) void load_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)) - { - plog("Could not change to directory '%s'", path); - } - else - { - plog("Changing to directory '%s'", path); - n = scandir(path, &filelist, file_select, alphasort); - - if (n < 0) - plog(" scandir() error"); - else - { - while (n--) - { - cert_t cert; + struct dirent **filelist; + u_char buf[BUF_LEN]; + u_char *save_dir; + int n; - if (load_cert(filelist[n]->d_name, type, &cert)) - add_authcert(cert.u.x509, auth_flags); + /* change directory to specified path */ + save_dir = getcwd(buf, BUF_LEN); - free(filelist[n]); - } - free(filelist); + if (chdir(path)) + { + plog("Could not change to directory '%s'", path); } - } - /* restore directory path */ - ignore_result(chdir(save_dir)); + else + { + plog("Changing to directory '%s'", path); + n = scandir(path, &filelist, file_select, alphasort); + + if (n < 0) + plog(" scandir() error"); + else + { + while (n--) + { + cert_t cert; + + if (load_cert(filelist[n]->d_name, type, &cert)) + add_authcert(cert.u.x509, auth_flags); + + free(filelist[n]); + } + free(filelist); + } + } + /* restore directory path */ + ignore_result(chdir(save_dir)); } /* @@ -305,9 +302,9 @@ load_authcerts(const char *type, const char *path, u_char auth_flags) void list_authcerts(const char *caption, u_char auth_flags, bool utc) { - lock_authcert_list("list_authcerts"); - list_x509cert_chain(caption, x509authcerts, auth_flags, utc); - unlock_authcert_list("list_authcerts"); + lock_authcert_list("list_authcerts"); + list_x509cert_chain(caption, x509authcerts, auth_flags, utc); + unlock_authcert_list("list_authcerts"); } /* @@ -315,19 +312,19 @@ list_authcerts(const char *caption, u_char auth_flags, bool utc) */ static const x509cert_t* get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid - , const x509cert_t *cert) + , const x509cert_t *cert) { - while (cert != NULL) - { - if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) - : (same_dn(subject, cert->subject) - && same_serial(serial, cert->serialNumber))) + while (cert != NULL) { - return cert; + if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) + : (same_dn(subject, cert->subject) + && same_serial(serial, cert->serialNumber))) + { + return cert; + } + cert = cert->next; } - cert = cert->next; - } - return NULL; + return NULL; } /* establish trust into a candidate authcert by going up the trust chain. @@ -336,85 +333,85 @@ get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) { - int pathlen; - - lock_authcert_list("trust_authcert_candidate"); - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - const x509cert_t *authcert = NULL; - u_char buf[BUF_LEN]; - - 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) - { - datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' - , buf, BUF_LEN); - DBG_log("authkey: %s", buf); - } - ) + int pathlen; - /* search in alternative chain first */ - authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID, alt_chain); + lock_authcert_list("trust_authcert_candidate"); - if (authcert != NULL) + for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { - DBG(DBG_CONTROL, - DBG_log("issuer cacert found in alternative chain") - ) - } - else - { - /* search in trusted chain */ - authcert = get_authcert(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID, AUTH_CA); + const x509cert_t *authcert = NULL; + u_char buf[BUF_LEN]; - if (authcert != NULL) - { DBG(DBG_CONTROL, - DBG_log("issuer cacert found") + 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) + { + datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' + , buf, BUF_LEN); + DBG_log("authkey: %s", buf); + } ) - } - else - { - plog("issuer cacert not found"); - unlock_authcert_list("trust_authcert_candidate"); - return FALSE; - } - } - if (!check_signature(cert->tbsCertificate, cert->signature - , cert->algorithm, cert->algorithm, authcert)) - { - plog("certificate signature is invalid"); - unlock_authcert_list("trust_authcert_candidate"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("certificate signature is valid") - ) + /* search in alternative chain first */ + authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID, alt_chain); + + if (authcert != NULL) + { + DBG(DBG_CONTROL, + DBG_log("issuer cacert found in alternative chain") + ) + } + else + { + /* search in trusted chain */ + authcert = get_authcert(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID, AUTH_CA); + + if (authcert != NULL) + { + DBG(DBG_CONTROL, + DBG_log("issuer cacert found") + ) + } + else + { + plog("issuer cacert not found"); + unlock_authcert_list("trust_authcert_candidate"); + return FALSE; + } + } + + if (!x509_check_signature(cert->tbsCertificate, cert->signature, + cert->algorithm, authcert)) + { + plog("certificate signature is invalid"); + unlock_authcert_list("trust_authcert_candidate"); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("certificate signature is valid") + ) - /* check if cert is a self-signed root ca */ - if (pathlen > 0 && same_dn(cert->issuer, cert->subject)) - { - DBG(DBG_CONTROL, - DBG_log("reached self-signed root ca") - ) - unlock_authcert_list("trust_authcert_candidate"); - return TRUE; + /* check if cert is a self-signed root ca */ + if (pathlen > 0 && same_dn(cert->issuer, cert->subject)) + { + DBG(DBG_CONTROL, + DBG_log("reached self-signed root ca") + ) + unlock_authcert_list("trust_authcert_candidate"); + return TRUE; + } + + /* go up one step in the trust chain */ + cert = authcert; } - - /* go up one step in the trust chain */ - cert = authcert; - } - plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); - unlock_authcert_list("trust_authcert_candidate"); - return FALSE; + plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); + unlock_authcert_list("trust_authcert_candidate"); + return FALSE; } /* @@ -423,19 +420,19 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) ca_info_t* get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid) { - ca_info_t *ca= ca_infos; + ca_info_t *ca= ca_infos; - while (ca!= NULL) - { - if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID) - : (same_dn(authname, ca->authName) - && same_serial(serial, ca->authKeySerialNumber))) + while (ca!= NULL) { - return ca; + if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID) + : (same_dn(authname, ca->authName) + && same_serial(serial, ca->authKeySerialNumber))) + { + return ca; + } + ca = ca->next; } - ca = ca->next; - } - return NULL; + return NULL; } @@ -445,21 +442,18 @@ get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid) static void free_ca_info(ca_info_t* ca_info) { - if (ca_info == NULL) - return; - - pfreeany(ca_info->name); - pfreeany(ca_info->ldaphost); - pfreeany(ca_info->ldapbase); - pfreeany(ca_info->ocspuri); - - freeanychunk(ca_info->authName); - freeanychunk(ca_info->authKeyID); - freeanychunk(ca_info->authKeySerialNumber); - - free_generalNames(ca_info->crluri, TRUE); - - pfree(ca_info); + if (ca_info == NULL) + return; + + free(ca_info->name); + free(ca_info->ldaphost); + free(ca_info->ldapbase); + free(ca_info->ocspuri); + free(ca_info->authName.ptr); + free(ca_info->authKeyID.ptr); + free(ca_info->authKeySerialNumber.ptr); + free_generalNames(ca_info->crluri, TRUE); + free(ca_info); } /* @@ -468,13 +462,13 @@ free_ca_info(ca_info_t* ca_info) void free_ca_infos(void) { - while (ca_infos != NULL) - { - ca_info_t *ca = ca_infos; + while (ca_infos != NULL) + { + ca_info_t *ca = ca_infos; - ca_infos = ca_infos->next; - free_ca_info(ca); - } + ca_infos = ca_infos->next; + free_ca_info(ca); + } } /* @@ -483,28 +477,28 @@ free_ca_infos(void) bool find_ca_info_by_name(const char *name, bool delete) { - ca_info_t **ca_p = &ca_infos; - ca_info_t *ca = *ca_p; + ca_info_t **ca_p = &ca_infos; + ca_info_t *ca = *ca_p; - while (ca != NULL) - { - /* is there already an entry? */ - if (streq(name, ca->name)) + while (ca != NULL) { - if (delete) - { - lock_ca_info_list("find_ca_info_by_name"); - *ca_p = ca->next; - free_ca_info(ca); - plog("deleting ca description \"%s\"", name); - unlock_ca_info_list("find_ca_info_by_name"); - } - return TRUE; + /* is there already an entry? */ + if (streq(name, ca->name)) + { + if (delete) + { + lock_ca_info_list("find_ca_info_by_name"); + *ca_p = ca->next; + free_ca_info(ca); + plog("deleting ca description \"%s\"", name); + unlock_ca_info_list("find_ca_info_by_name"); + } + return TRUE; + } + ca_p = &ca->next; + ca = *ca_p; } - ca_p = &ca->next; - ca = *ca_p; - } - return FALSE; + return FALSE; } @@ -514,136 +508,133 @@ find_ca_info_by_name(const char *name, bool delete) void add_ca_info(const whack_message_t *msg) { - smartcard_t *sc = NULL; - cert_t cert; - bool valid_cert = FALSE; - bool cached_cert = FALSE; - - if (find_ca_info_by_name(msg->name, FALSE)) - { - loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name); - return; - } - - if (scx_on_smartcard(msg->cacert)) - { - /* load CA cert from smartcard */ - valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert); - } - else - { - /* load CA cert from file */ - valid_cert = load_ca_cert(msg->cacert, &cert); - } - - if (valid_cert) - { - char buf[BUF_LEN]; - x509cert_t *cacert = cert.u.x509; - ca_info_t *ca = NULL; - - /* does the authname already exist? */ - ca = get_ca_info(cacert->subject, cacert->serialNumber - , cacert->subjectKeyID); - - if (ca != NULL) - { - /* ca_info is already present */ - loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found," - "ignoring \"%s\"", ca->name, msg->name); - free_x509cert(cacert); - return; - } + smartcard_t *sc = NULL; + cert_t cert; + bool valid_cert = FALSE; + bool cached_cert = FALSE; - plog("added ca description \"%s\"", msg->name); - - /* create and initialize new ca_info record */ - ca = alloc_thing(ca_info_t, "ca info"); - *ca = empty_ca_info; - - /* name */ - ca->name = clone_str(msg->name, "ca name"); - - /* authName */ - clonetochunk(ca->authName, cacert->subject.ptr - , cacert->subject.len, "authName"); - dntoa(buf, BUF_LEN, ca->authName); - DBG(DBG_CONTROL, - DBG_log("authname: '%s'", buf) - ) - - /* authSerialNumber */ - clonetochunk(ca->authKeySerialNumber, cacert->serialNumber.ptr - , cacert->serialNumber.len, "authKeySerialNumber"); - - /* authKeyID */ - if (cacert->subjectKeyID.ptr != NULL) + if (find_ca_info_by_name(msg->name, FALSE)) { - clonetochunk(ca->authKeyID, cacert->subjectKeyID.ptr - , cacert->subjectKeyID.len, "authKeyID"); - datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':' - , buf, BUF_LEN); - DBG(DBG_CONTROL | DBG_PARSING , - DBG_log("authkey: %s", buf) - ) + loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name); + return; } - /* ldaphost */ - ca->ldaphost = clone_str(msg->ldaphost, "ldaphost"); - - /* ldapbase */ - ca->ldapbase = clone_str(msg->ldapbase, "ldapbase"); - - /* ocspuri */ - if (msg->ocspuri != NULL) + if (scx_on_smartcard(msg->cacert)) { - if (strncasecmp(msg->ocspuri, "http", 4) == 0) - ca->ocspuri = clone_str(msg->ocspuri, "ocspuri"); - else - plog(" ignoring ocspuri with unkown protocol"); + /* load CA cert from smartcard */ + valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert); } - - /* crluri2*/ - if (msg->crluri2 != NULL) + else { - generalName_t gn = - { NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} }; - - add_distribution_points(&gn, &ca->crluri); + /* load CA cert from file */ + valid_cert = load_ca_cert(msg->cacert, &cert); } - /* crluri */ - if (msg->crluri != NULL) + if (valid_cert) { - generalName_t gn = - { NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} }; - - add_distribution_points(&gn, &ca->crluri); - } - - /* strictrlpolicy */ - ca->strictcrlpolicy = msg->whack_strict; - - /* insert ca_info record into the chained list */ - lock_ca_info_list("add_ca_info"); - - ca->next = ca_infos; - ca_infos = ca; - ca->installed = time(NULL); - - unlock_ca_info_list("add_ca_info"); + char buf[BUF_LEN]; + x509cert_t *cacert = cert.u.x509; + ca_info_t *ca = NULL; + + /* does the authname already exist? */ + ca = get_ca_info(cacert->subject, cacert->serialNumber + , cacert->subjectKeyID); + + if (ca != NULL) + { + /* ca_info is already present */ + loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found," + "ignoring \"%s\"", ca->name, msg->name); + free_x509cert(cacert); + return; + } + + plog("added ca description \"%s\"", msg->name); + + /* create and initialize new ca_info record */ + ca = malloc_thing(ca_info_t); + *ca = empty_ca_info; + + /* name */ + ca->name = clone_str(msg->name); + + /* authName */ + ca->authName = chunk_clone(cacert->subject); + dntoa(buf, BUF_LEN, ca->authName); + DBG(DBG_CONTROL, + DBG_log("authname: '%s'", buf) + ) - /* add cacert to list of authcerts */ - if (!cached_cert && sc != NULL) - { - if (sc->last_cert.type == CERT_X509_SIGNATURE) - sc->last_cert.u.x509->count--; - sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA); - share_cert(sc->last_cert); + /* authSerialNumber */ + ca->authKeySerialNumber = chunk_clone(cacert->serialNumber); + + /* authKeyID */ + if (cacert->subjectKeyID.ptr != NULL) + { + ca->authKeyID = chunk_clone(cacert->subjectKeyID); + datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':' + , buf, BUF_LEN); + DBG(DBG_CONTROL | DBG_PARSING , + DBG_log("authkey: %s", buf) + ) + } + + /* ldaphost */ + ca->ldaphost = clone_str(msg->ldaphost); + + /* ldapbase */ + ca->ldapbase = clone_str(msg->ldapbase); + + /* ocspuri */ + if (msg->ocspuri != NULL) + { + if (strncasecmp(msg->ocspuri, "http", 4) == 0) + ca->ocspuri = clone_str(msg->ocspuri); + else + plog(" ignoring ocspuri with unkown protocol"); + } + + /* crluri2*/ + if (msg->crluri2 != NULL) + { + generalName_t gn = + { NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} }; + + add_distribution_points(&gn, &ca->crluri); + } + + /* crluri */ + if (msg->crluri != NULL) + { + generalName_t gn = + { NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} }; + + add_distribution_points(&gn, &ca->crluri); + } + + /* strictrlpolicy */ + ca->strictcrlpolicy = msg->whack_strict; + + /* insert ca_info record into the chained list */ + lock_ca_info_list("add_ca_info"); + + ca->next = ca_infos; + ca_infos = ca; + ca->installed = time(NULL); + + unlock_ca_info_list("add_ca_info"); + + /* add cacert to list of authcerts */ + if (!cached_cert && sc != NULL) + { + if (sc->last_cert.type == CERT_X509_SIGNATURE) + sc->last_cert.u.x509->count--; + sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA); + share_cert(sc->last_cert); + } + if (sc != NULL) + time(&sc->last_load); } - if (sc != NULL) - time(&sc->last_load); - } } /* @@ -652,51 +643,51 @@ add_ca_info(const whack_message_t *msg) void list_ca_infos(bool utc) { - ca_info_t *ca = ca_infos; - - if (ca != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of X.509 CA Information Records:"); - whack_log(RC_COMMENT, " "); - } - - while (ca != NULL) - { - u_char buf[BUF_LEN]; - - /* strictpolicy per CA not supported yet - * - whack_log(RC_COMMENT, "%s, \"%s\", strictcrlpolicy: %s" - , timetoa(&ca->installed, utc), ca->name - , ca->strictcrlpolicy? "yes":"no"); - */ - whack_log(RC_COMMENT, "%s, \"%s\"", timetoa(&ca->installed, utc), ca->name); - dntoa(buf, BUF_LEN, ca->authName); - whack_log(RC_COMMENT, " authname: '%s'", buf); - if (ca->ldaphost != NULL) - whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost); - if (ca->ldapbase != NULL) - whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase); - if (ca->ocspuri != NULL) - whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri); - - list_distribution_points(ca->crluri); - - if (ca->authKeyID.ptr != NULL) + ca_info_t *ca = ca_infos; + + if (ca != NULL) { - datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of X.509 CA Information Records:"); + whack_log(RC_COMMENT, " "); } - if (ca->authKeySerialNumber.ptr != NULL) + + while (ca != NULL) { - datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + u_char buf[BUF_LEN]; + + /* strictpolicy per CA not supported yet + * + whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s" + , &ca->installed, utc, ca->name + , ca->strictcrlpolicy? "yes":"no"); + */ + whack_log(RC_COMMENT, "%T, \"%s\"", &ca->installed, utc, ca->name); + dntoa(buf, BUF_LEN, ca->authName); + whack_log(RC_COMMENT, " authname: '%s'", buf); + if (ca->ldaphost != NULL) + whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost); + if (ca->ldapbase != NULL) + whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase); + if (ca->ocspuri != NULL) + whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri); + + list_distribution_points(ca->crluri); + + if (ca->authKeyID.ptr != NULL) + { + datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (ca->authKeySerialNumber.ptr != NULL) + { + datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + ca = ca->next; } - ca = ca->next; - } } |