diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2010-03-07 20:51:34 +0100 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2010-03-07 20:51:34 +0100 |
commit | ceeb9bac8bf2c95cecf430c41591f63ed00dc6e9 (patch) | |
tree | c500a3a63a29129f6fd5933088d7ba8f154502c1 | |
parent | 469d448333dc47592869af4e6a98ef444db1a301 (diff) | |
download | strongswan-ceeb9bac8bf2c95cecf430c41591f63ed00dc6e9.tar.bz2 strongswan-ceeb9bac8bf2c95cecf430c41591f63ed00dc6e9.tar.xz |
critical keyUsage extension must be parsed
-rw-r--r-- | ca.diff | 542 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_cert.c | 3 | ||||
-rw-r--r-- | strongswan-4.4.0dr1.tar.bz2 | bin | 0 -> 2853715 bytes |
4 files changed, 546 insertions, 1 deletions
diff --git a/ca.diff b/ca.diff new file mode 100644 index 000000000..a262ccf5b --- /dev/null +++ b/ca.diff @@ -0,0 +1,542 @@ +diff --git a/src/pluto/ca.c b/src/pluto/ca.c +index 2f59a90..d9db082 100644 +--- a/src/pluto/ca.c ++++ b/src/pluto/ca.c +@@ -27,7 +27,6 @@ + #include "constants.h" + #include "defs.h" + #include "log.h" +-#include "x509.h" + #include "ca.h" + #include "certs.h" + #include "whack.h" +@@ -36,13 +35,180 @@ + + /* chained list of X.509 authority certificates (ca, aa, and ocsp) */ + +-static x509cert_t *x509authcerts = NULL; ++static linked_list_t *authcerts = NULL; + + /* chained list of X.509 certification authority information records */ + + static ca_info_t *ca_infos = NULL; + ++/** ++ * Initialize the linked list of authority certificates ++ */ ++void ca_initialize(void) ++{ ++ authcerts = linked_list_create(); ++} ++ ++/** ++ * Free the linked list of authority certificates ++ */ ++void ca_finalize(void) ++{ ++ lock_authcert_list("free_authcerts"); ++ authcerts->destroy_offset(authcerts, offsetof(certificate_t, destroy)); ++ unlock_authcert_list("free_authcerts"); ++} ++ + /* ++ * get a X.509 authority certificate with a given subject or keyid ++ */ ++certificate_t* ca_get_cert(identification_t *subject, chunk_t keyid, ++ x509_flag_t auth_flags) ++{ ++ enumerator_t *enumerator; ++ certificate_t *cert, *found = NULL; ++ ++ enumerator = authcerts->create_enumerator(authcerts); ++ while (enumerator->enumerate(enumerator, &cert)) ++ { ++ x509_t *x509 = (x509_t*)cert; ++ ++ /* skip non-matching types of authority certificates */ ++ if (!(x509->get_flags(x509) & auth_flags)) ++ { ++ continue; ++ } ++ ++ /* compare the keyid with the certificate's subjectKeyIdentifier */ ++ if (keyid.ptr) ++ { ++ chunk_t subjectKeyId; ++ ++ subjectKeyId = x509->get_subjectKeyIdentifier(x509); ++ if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId)) ++ { ++ continue; ++ } ++ } ++ ++ /* compare the subjectDistinguishedNames */ ++ if (cert->has_subject(cert, subject)) ++ { ++ found = cert; ++ break; ++ } ++ } ++ enumerator->destroy(enumerator); ++ return found; ++} ++ ++/** ++ * Add an authority certificate to the chained list ++ */ ++certificate_t* ca_add_cert(certificate_t *cert) ++{ ++ identification_t *subject = cert->get_subject(cert); ++ x509_t *x509 = (x509_t*)cert; ++ x509_flag_t flags = x509->get_flags(x509); ++ chunk_t keyid = x509->get_subjectKeyIdentifier(x509); ++ ++ certificate_t *old_cert; ++ enumerator_t *enumerator; ++ bool add = TRUE; ++ ++ lock_authcert_list("add_authcert"); ++ ++ enumerator = acerts->create_enumerator(acerts); ++ while (enumerator->enumerate(enumerator, &cert_old)) ++ { ++ x509_t *x509_old = (x509_t*)cert_old; ++ ++ /* skip non-matching types of authority certificates */ ++ if (!(x509_old->get_flags(x509_old) & flags)) ++ { ++ continue; ++ } ++ ++ /* compare the keyid with the certificate's subjectKeyIdentifier */ ++ if (keyid.ptr) ++ { ++ chunk_t subjectKeyId; ++ ++ subjectKeyId = x509_old->get_subjectKeyIdentifier(x509_old); ++ if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId)) ++ { ++ continue; ++ } ++ } ++ ++ /* compare the subjectDistinguishedNames */ ++ if (!cert_old->has_subject(cert_old, subject)) ++ { ++ continue, ++ } ++ ++ if (cert->equals(cert, cert_old)) ++ { ++ DBG1(" authcert is already present and identical") ++ ++ cert->destroy(cert); ++ cert = cert_old; ++ add = FALSE; ++ } ++ else ++ { ++ authcerts->remove_at(authcerts, enumerator); ++ DBG1(" existing authcert replaced"); ++ } ++ break; ++ } ++ enumerator->destroy(enumerator); ++ ++ if (add) ++ { ++ authcerts->insert_last(authcerts, cert); ++ } ++ unlock_authcert_list("add_authcert"); ++ ++ return cert; ++} ++ ++/** ++ * Loads authority certificates ++ */ ++void ca_load_authcerts(char *type, char *path, x509_flag_t auth_flags) ++{ ++ enumerator_t *enumerator; ++ struct stat st; ++ char *file; ++ ++ DBG1("loading %s certificates from '%s'", type, path); ++ ++ enumerator = enumerator_create_directory(path); ++ if (!enumerator) ++ { ++ DBG1(" reading directory '%s' failed"); ++ return; ++ } ++ ++ while (enumerator->enumerate(enumerator, NULL, &file, &st)) ++ { ++ cert_t cert; ++ ++ if (!S_ISREG(st.st_mode)) ++ { ++ /* skip special file */ ++ continue; ++ } ++ if (load_cert(file, type, auth_flags, &cert)) ++ { ++ add_authcert(cert.u.x509, auth_flags); ++ } ++ } ++ enumerator->destroy(enumerator); ++} ++ ++/** + * Checks if CA a is trusted by CA b + */ + bool trusted_ca(identification_t *a, identification_t *b, int *pathlen) +@@ -76,20 +242,18 @@ bool trusted_ca(identification_t *a, identification_t *b, int *pathlen) + + while ((*pathlen)++ < MAX_CA_PATH_LEN) + { +- certificate_t *certificate; ++ certificate_t *cacert; + identification_t *issuer; +- x509cert_t *cacert; + +- cacert = get_authcert(a, chunk_empty, X509_CA); ++ cacert = ca_get_cert(a, chunk_empty, X509_CA); + if (cacert == NULL) + { + break; + } +- certificate = cacert->cert; + + /* is the certificate self-signed? */ + { +- x509_t *x509 = (x509_t*)certificate; ++ x509_t *x509 = (x509_t*)cacert; + + if (x509->get_flags(x509) & X509_SELF_SIGNED) + { +@@ -98,7 +262,7 @@ bool trusted_ca(identification_t *a, identification_t *b, int *pathlen) + } + + /* does the issuer of CA a match CA b? */ +- issuer = certificate->get_issuer(certificate); ++ issuer = cert->get_issuer(cert); + match = b->equals(b, issuer); + + /* we have a match and exit the loop */ +@@ -114,8 +278,8 @@ bool trusted_ca(identification_t *a, identification_t *b, int *pathlen) + return match; + } + +-/* +- * does our CA match one of the requested CAs? ++/** ++ * Does our CA match one of the requested CAs? + */ + bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca, + int *our_pathlen) +@@ -156,167 +320,6 @@ bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca, + } + + /* +- * free the first authority certificate in the chain +- */ +-static void free_first_authcert(void) +-{ +- x509cert_t *first = x509authcerts; +- x509authcerts = first->next; +- free_x509cert(first); +-} +- +-/* +- * free all CA certificates +- */ +-void free_authcerts(void) +-{ +- lock_authcert_list("free_authcerts"); +- +- while (x509authcerts != NULL) +- free_first_authcert(); +- +- unlock_authcert_list("free_authcerts"); +-} +- +-/* +- * get a X.509 authority certificate with a given subject or keyid +- */ +-x509cert_t* get_authcert(identification_t *subject, chunk_t keyid, +- x509_flag_t auth_flags) +-{ +- x509cert_t *cert, *prev_cert = NULL; +- +- /* the authority certificate list is empty */ +- if (x509authcerts == NULL) +- { +- return NULL; +- } +- +- for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next) +- { +- certificate_t *certificate = cert->cert; +- x509_t *x509 = (x509_t*)certificate; +- +- /* skip non-matching types of authority certificates */ +- if (!(x509->get_flags(x509) & auth_flags)) +- { +- continue; +- } +- +- /* compare the keyid with the certificate's subjectKeyIdentifier */ +- if (keyid.ptr) +- { +- chunk_t subjectKeyId; +- +- subjectKeyId = x509->get_subjectKeyIdentifier(x509); +- if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId)) +- { +- continue; +- } +- } +- +- /* compare the subjectDistinguishedNames */ +- if (!certificate->has_subject(certificate, subject)) +- { +- continue; +- } +- +- /* found the authcert */ +- if (cert != x509authcerts) +- { +- /* bring the certificate up front */ +- prev_cert->next = cert->next; +- cert->next = x509authcerts; +- x509authcerts = cert; +- } +- return cert; +- } +- return NULL; +-} +- +-/* +- * add an authority certificate to the chained list +- */ +-x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags) +-{ +- certificate_t *certificate = cert->cert; +- x509_t *x509 = (x509_t*)certificate; +- x509cert_t *old_cert; +- +- lock_authcert_list("add_authcert"); +- +- old_cert = get_authcert(certificate->get_subject(certificate), +- x509->get_subjectKeyIdentifier(x509), +- auth_flags); +- if (old_cert) +- { +- if (certificate->equals(certificate, old_cert->cert)) +- { +- 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; +-} +- +-/* +- * Loads authority certificates +- */ +-void load_authcerts(char *type, char *path, x509_flag_t auth_flags) +-{ +- enumerator_t *enumerator; +- struct stat st; +- char *file; +- +- DBG1("loading %s certificates from '%s'", type, path); +- +- enumerator = enumerator_create_directory(path); +- if (!enumerator) +- { +- DBG1(" reading directory '%s' failed"); +- return; +- } +- +- while (enumerator->enumerate(enumerator, NULL, &file, &st)) +- { +- cert_t cert; +- +- if (!S_ISREG(st.st_mode)) +- { +- /* skip special file */ +- continue; +- } +- if (load_cert(file, type, auth_flags, &cert)) +- { +- add_authcert(cert.u.x509, auth_flags); +- } +- } +- enumerator->destroy(enumerator); +-} +- +-/* + * list all X.509 authcerts with given auth flags in a chained list + */ + void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc) +@@ -368,7 +371,7 @@ static const x509cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid + /* establish trust into a candidate authcert by going up the trust chain. + * validity and revocation status are not checked. + */ +-bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) ++bool trust_authcert_candidate(certificate_t *cert, linked_list_t *alt_chain) + { + int pathlen; + +@@ -448,8 +451,8 @@ bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chai + return FALSE; + } + +-/* +- * get a CA info record with a given authName or authKeyID ++/** ++ * Get a CA info record with a given authName or authKeyID + */ + ca_info_t* get_ca_info(identification_t *name, chunk_t keyid) + { +@@ -468,11 +471,10 @@ ca_info_t* get_ca_info(identification_t *name, chunk_t keyid) + } + + +-/* +- * free the dynamic memory used by a ca_info record ++/** ++ * Free the dynamic memory used by a ca_info record + */ +-static void +-free_ca_info(ca_info_t* ca_info) ++static void free_ca_info(ca_info_t* ca_info) + { + if (ca_info == NULL) + { +@@ -502,8 +504,8 @@ void free_ca_infos(void) + } + } + +-/* +- * find a CA information record by name and optionally delete it ++/** ++ * Find a CA information record by name and optionally delete it + */ + bool find_ca_info_by_name(const char *name, bool delete) + { +@@ -531,7 +533,7 @@ bool find_ca_info_by_name(const char *name, bool delete) + return FALSE; + } + +-/* ++/** + * Create an empty ca_info_t record + */ + ca_info_t* create_ca_info(void) +@@ -659,8 +661,8 @@ void add_ca_info(const whack_message_t *msg) + } + } + +-/* +- * list all ca_info records in the chained list ++/** ++ * List all ca_info records in the chained list + */ + void list_ca_infos(bool utc) + { +diff --git a/src/pluto/ca.h b/src/pluto/ca.h +index 77dfe33..3b9e4c9 100644 +--- a/src/pluto/ca.h ++++ b/src/pluto/ca.h +@@ -17,8 +17,8 @@ + + #include <utils/linked_list.h> + #include <utils/identification.h> ++#include <credentials/certificates/certificate.h> + +-#include "x509.h" + #include "whack.h" + + #define MAX_CA_PATH_LEN 7 +@@ -39,17 +39,21 @@ struct ca_info { + bool strictcrlpolicy; + }; + ++extern void ca_initialize(void); ++extern void ca_finalize(void); ++extern void ca_load_certs(char *type, char *path, x509_flag_t auth_flags); ++extern void ca_list_certs(const char *caption, x509_flag_t auth_flags, bool utc); ++ ++extern certificate_t* ca_add_cert(certificate_t *cert); ++ ++extern certificate_t* ca_get_cert(identification_t *subject, chunk_t keyid, ++ x509_flag_t auth_flags) ++ + extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen); + extern bool match_requested_ca(linked_list_t *requested_ca, + identification_t *our_ca, int *our_pathlen); +-extern x509cert_t* get_authcert(identification_t *subject, chunk_t keyid, +- x509_flag_t auth_flags); +-extern void load_authcerts(char *type, char *path, x509_flag_t auth_flags); +-extern x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags); +-extern void free_authcerts(void); +-extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc); +-extern bool trust_authcert_candidate(const x509cert_t *cert, +- const x509cert_t *alt_chain); ++extern bool trust_authcert_candidate(certificate_t *cert, ++ linked_list_t *alt_chain); + extern ca_info_t* get_ca_info(identification_t *name, chunk_t keyid); + extern bool find_ca_info_by_name(const char *name, bool delete); + extern void add_ca_info(const whack_message_t *msg); +diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c +index 0471d26..a9e3aa0 100644 +--- a/src/pluto/plutomain.c ++++ b/src/pluto/plutomain.c +@@ -675,6 +675,7 @@ int main(int argc, char **argv) + init_adns(); + init_myid(); + init_fetch(); ++ ca_initialize(); + ac_initialize(); + + /* drop unneeded capabilities and change UID/GID */ +@@ -752,12 +753,12 @@ void exit_pluto(int status) + delete_every_connection(); + free_crl_fetch(); /* free chain of crl fetch requests */ + free_ocsp_fetch(); /* free chain of ocsp fetch requests */ +- free_authcerts(); /* free chain of X.509 authority certificates */ + free_crls(); /* free chain of X.509 CRLs */ + free_ca_infos(); /* free chain of X.509 CA information records */ + free_ocsp(); /* free ocsp cache */ + free_ifaces(); + ac_finalize(); /* free X.509 attribute certificates */ ++ ca_finalize(); /* free X.509 authority certificates */ + scx_finalize(); /* finalize and unload PKCS #11 module */ + xauth_finalize(); /* finalize and unload XAUTH module */ + stop_adns(); diff --git a/configure.in b/configure.in index 81249920f..f500ebc92 100644 --- a/configure.in +++ b/configure.in @@ -16,7 +16,7 @@ dnl =========================== dnl initialize & set some vars dnl =========================== -AC_INIT(strongSwan,4.4.0) +AC_INIT(strongSwan,4.4.0dr1) AM_INIT_AUTOMAKE(tar-ustar) AC_CONFIG_MACRO_DIR([m4/config]) PKG_PROG_PKG_CONFIG diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 698903456..4c8456c6b 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -974,6 +974,9 @@ static bool parse_certificate(private_x509_cert_t *this) case OID_AUTHORITY_INFO_ACCESS: parse_authorityInfoAccess(object, level, this); break; + case OID_KEY_USAGE: + /* TODO parse the flags */ + break; case OID_EXTENDED_KEY_USAGE: parse_extendedKeyUsage(object, level, this); break; diff --git a/strongswan-4.4.0dr1.tar.bz2 b/strongswan-4.4.0dr1.tar.bz2 Binary files differnew file mode 100644 index 000000000..25e14cc15 --- /dev/null +++ b/strongswan-4.4.0dr1.tar.bz2 |