summaryrefslogtreecommitdiff
path: root/src/pluto/ca.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/ca.c')
-rw-r--r--src/pluto/ca.c923
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;
- }
}