diff options
-rw-r--r-- | src/libstrongswan/credentials/certificates/certificate.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/plugins/attr_sql/.gitignore | 1 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pem/pem_plugin.c | 2 | ||||
-rw-r--r-- | src/pluto/ac.c | 294 | ||||
-rw-r--r-- | src/pluto/ac.h | 24 | ||||
-rw-r--r-- | src/pluto/builder.c | 43 | ||||
-rw-r--r-- | src/pluto/connections.c | 10 | ||||
-rw-r--r-- | src/pluto/constants.h | 2 | ||||
-rw-r--r-- | src/pluto/plutomain.c | 5 | ||||
-rw-r--r-- | src/pluto/rcv_whack.c | 4 |
10 files changed, 147 insertions, 240 deletions
diff --git a/src/libstrongswan/credentials/certificates/certificate.h b/src/libstrongswan/credentials/certificates/certificate.h index 0399d92e6..a4f9aa3e0 100644 --- a/src/libstrongswan/credentials/certificates/certificate.h +++ b/src/libstrongswan/credentials/certificates/certificate.h @@ -53,8 +53,6 @@ enum certificate_type_t { CERT_GPG, /** Pluto cert_t (not a certificate_t), either x509 or PGP */ CERT_PLUTO_CERT, - /** Pluto x509acert_t (not a certificate_t), attribute certificate */ - CERT_PLUTO_AC, /** Pluto x509crl_t (not a certificate_t), certificate revocation list */ CERT_PLUTO_CRL, }; diff --git a/src/libstrongswan/plugins/attr_sql/.gitignore b/src/libstrongswan/plugins/attr_sql/.gitignore new file mode 100644 index 000000000..eae4e6ad0 --- /dev/null +++ b/src/libstrongswan/plugins/attr_sql/.gitignore @@ -0,0 +1 @@ +pool diff --git a/src/libstrongswan/plugins/pem/pem_plugin.c b/src/libstrongswan/plugins/pem/pem_plugin.c index 1afab2cf6..5a5149ca8 100644 --- a/src/libstrongswan/plugins/pem/pem_plugin.c +++ b/src/libstrongswan/plugins/pem/pem_plugin.c @@ -97,8 +97,6 @@ plugin_t *plugin_create() /* register pluto specific certificate formats */ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT, (builder_function_t)pem_certificate_load); - lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_AC, - (builder_function_t)pem_certificate_load); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL, (builder_function_t)pem_certificate_load); diff --git a/src/pluto/ac.c b/src/pluto/ac.c index ce0c26f89..608453923 100644 --- a/src/pluto/ac.c +++ b/src/pluto/ac.c @@ -14,164 +14,88 @@ * for more details. */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <dirent.h> -#include <sys/types.h> +#include <sys/stat.h> #include <time.h> -#include <freeswan.h> - -#include <utils.h> +#include <debug.h> +#include <utils/enumerator.h> +#include <utils/linked_list.h> #include <credentials/certificates/ac.h> #include "ac.h" -#include "x509.h" -#include "crl.h" #include "ca.h" #include "certs.h" -#include "log.h" -#include "whack.h" #include "fetch.h" -#include "builder.h" +#include "log.h" /** * Chained list of X.509 attribute certificates */ -static x509acert_t *x509acerts = NULL; - -/** - * Free a X.509 attribute certificate - */ -void free_acert(x509acert_t *ac) -{ - if (ac) - { - DESTROY_IF(ac->ac); - free(ac); - } -} +static linked_list_t *acerts = NULL; /** - * Free first X.509 attribute certificate in the chained list + * Initialize the linked list of attribute certificates */ -static void free_first_acert(void) +void ac_initialize(void) { - x509acert_t *first = x509acerts; - x509acerts = first->next; - free_acert(first); + acerts = linked_list_create(); } /** - * Free all attribute certificates in the chained list + * Free the linked list of attribute certificates */ -void free_acerts(void) +void ac_finalize(void) { - while (x509acerts != NULL) - { - free_first_acert(); - } + acerts->destroy_offset(acerts, offsetof(certificate_t, destroy)); + free(acerts); } /** * Get a X.509 attribute certificate for a given holder */ -x509acert_t* get_x509acert(identification_t *issuer, chunk_t serial) +certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial) { - x509acert_t *x509ac = x509acerts; - x509acert_t *prev_ac = NULL; + enumerator_t *enumerator; + certificate_t *cert, *found = NULL; - while (x509ac != NULL) + enumerator = acerts->create_enumerator(acerts); + while (enumerator->enumerate(enumerator, &cert)) { - ac_t *ac = (ac_t*)x509ac->ac; - identification_t *holderIssuer = ac->get_holderIssuer(ac); - chunk_t holderSerial = ac->get_holderSerial(ac); - - if (issuer->equals(issuer, holderIssuer) && - chunk_equals(serial, holderSerial)) - { - if (x509ac!= x509acerts) - { - /* bring the certificate up front */ - prev_ac->next = x509ac->next; - x509ac->next = x509acerts; - x509acerts = x509ac; - } - return x509ac; - } - prev_ac = x509ac; - x509ac = x509ac->next; - } - return NULL; -} + ac_t *ac = (ac_t*)cert; -/** - * Add a X.509 attribute certificate to the chained list - */ -static void add_acert(x509acert_t *x509ac) -{ - certificate_t *cert_ac = x509ac->ac; - ac_t *ac = (ac_t*)cert_ac; - identification_t *holderIssuer = ac->get_holderIssuer(ac); - chunk_t holderSerial = ac->get_serial(ac); - x509acert_t *old_ac; - - old_ac = get_x509acert(holderIssuer, holderSerial); - if (old_ac != NULL) - { - if (cert_ac->is_newer(cert_ac, old_ac->ac)) + if (issuer->equals(issuer, ac->get_holderIssuer(ac)) && + chunk_equals(serial, ac->get_holderSerial(ac))) { - /* delete the old attribute cert */ - free_first_acert(); - DBG(DBG_CONTROL, - DBG_log("attribute cert is newer - existing cert deleted") - ) - } - else - { - DBG(DBG_CONTROL, - DBG_log("attribute cert is not newer - existing cert kept"); - ) - free_acert(x509ac); - return; + found = cert; + break; } } - plog("attribute cert added"); - - /* insert new attribute cert at the root of the chain */ - x509ac->next = x509acerts; - x509acerts = x509ac; + enumerator->destroy(enumerator); + return found; } /** - * verifies a X.509 attribute certificate + * Verifies a X.509 attribute certificate */ -bool verify_x509acert(x509acert_t *x509ac, bool strict) +bool ac_verify_cert(certificate_t *cert, bool strict) { - certificate_t *cert_ac = x509ac->ac; - ac_t *ac = (ac_t*)cert_ac; - identification_t *subject = cert_ac->get_subject(cert_ac); - identification_t *issuer = cert_ac->get_issuer(cert_ac); + ac_t *ac = (ac_t*)cert; + identification_t *subject = cert->get_subject(cert); + identification_t *issuer = cert->get_issuer(cert); chunk_t authKeyID = ac->get_authKeyIdentifier(ac); x509cert_t *aacert; time_t notBefore, valid_until; - DBG(DBG_CONTROL, - DBG_log("holder: '%Y'", subject); - DBG_log("issuer: '%Y'", issuer); - ) + DBG1("holder: '%Y'", subject); + DBG1("issuer: '%Y'", issuer); - if (!cert_ac->get_validity(cert_ac, NULL, NULL, &valid_until)) + if (!cert->get_validity(cert, NULL, NULL, &valid_until)) { - plog("attribute certificate is invalid (valid from %T to %T)", + DBG1("attribute certificate is invalid (valid from %T to %T)", ¬Before, FALSE, &valid_until, FALSE); return FALSE; } - DBG(DBG_CONTROL, - DBG_log("attribute certificate is valid until %T", &valid_until, FALSE) - ) + DBG1("attribute certificate is valid until %T", &valid_until, FALSE); lock_authcert_list("verify_x509acert"); aacert = get_authcert(issuer, authKeyID, X509_AA); @@ -179,26 +103,65 @@ bool verify_x509acert(x509acert_t *x509ac, bool strict) if (aacert == NULL) { - plog("issuer aacert not found"); + DBG1("issuer aacert not found"); return FALSE; } - DBG(DBG_CONTROL, - DBG_log("issuer aacert found") - ) + DBG2("issuer aacert found"); - if (!cert_ac->issued_by(cert_ac, aacert->cert)) + if (!cert->issued_by(cert, aacert->cert)) { - plog("attribute certificate signature is invalid"); + DBG1("attribute certificate signature is invalid"); return FALSE; } - DBG(DBG_CONTROL, - DBG_log("attribute certificate signature is valid"); - ) + DBG1("attribute certificate signature is valid"); return verify_x509cert(aacert, strict, &valid_until); } /** + * Add a X.509 attribute certificate to the chained list + */ +static void ac_add_cert(certificate_t *cert) +{ + ac_t *ac = (ac_t*)cert; + identification_t *issuer = ac->get_holderIssuer(ac); + chunk_t serial = ac->get_serial(ac); + + enumerator_t *enumerator; + certificate_t *cert_old; + + enumerator = acerts->create_enumerator(acerts); + while (enumerator->enumerate(enumerator, &cert_old)) + { + ac_t *ac_old = (ac_t*)cert_old; + + if (issuer->equals(issuer, ac_old->get_holderIssuer(ac_old)) && + chunk_equals(serial, ac_old->get_serial(ac_old))) + { + if (cert->is_newer(cert, cert_old)) + { + DBG1(" attribute cert is newer - existing cert deleted"); + acerts->remove_at(acerts, enumerator); + cert_old->destroy(cert_old); + } + else + { + DBG1(" attribute cert is not newer - existing cert kept"); + cert->destroy(cert); + cert = NULL; + } + break; + } + } + enumerator->destroy(enumerator); + + if (cert) + { + acerts->insert_last(acerts, cert); + } +} + +/** * Check if at least one peer attribute matches a connection attribute */ bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn, @@ -212,80 +175,73 @@ bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn, } match = conn_attributes->matches(conn_attributes, peer_attributes); - DBG(DBG_CONTROL, - DBG_log("%s: peer with attributes '%s' is %sa member of the groups '%s'", - conn, - peer_attributes->get_string(peer_attributes), - match ? "" : "not ", - conn_attributes->get_string(conn_attributes)) - ) - return match; + DBG1("%s: peer with attributes '%s' is %sa member of the groups '%s'", + conn, peer_attributes->get_string(peer_attributes), + match ? "" : "not ", conn_attributes->get_string(conn_attributes)); + return match; } /** * Loads X.509 attribute certificates */ -void load_acerts(void) +void ac_load_certs(void) { - u_char buf[BUF_LEN]; + enumerator_t *enumerator; + struct stat st; + char *file; - /* change directory to specified path */ - u_char *save_dir = getcwd(buf, BUF_LEN); + DBG1("Loading attribute certificates:"); - if (!chdir(A_CERT_PATH)) + enumerator = enumerator_create_directory(A_CERT_PATH); + if (!enumerator) { - struct dirent **filelist; - int n; + DBG1(" reading directory '%s' failed"); + return; + } - plog("Changing to directory '%s'",A_CERT_PATH); - n = scandir(A_CERT_PATH, &filelist, file_select, alphasort); + while (enumerator->enumerate(enumerator, NULL, &file, &st)) + { + certificate_t *cert; - if (n > 0) + if (!S_ISREG(st.st_mode)) { - while (n--) - { - char *filename = filelist[n]->d_name; - x509acert_t *ac; - - ac = lib->creds->create(lib->creds, CRED_CERTIFICATE, - CERT_PLUTO_AC, BUILD_FROM_FILE, filename, - BUILD_END); - if (ac) - { - plog(" loaded attribute certificate from '%s'", filename); - add_acert(ac); - } - free(filelist[n]); - } - free(filelist); + /* skip special file */ + continue; + } + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, + BUILD_FROM_FILE, file, BUILD_END); + if (cert) + { + DBG1(" loaded attribute certificate from '%s'", file); + ac_add_cert(cert); } } - /* restore directory path */ - ignore_result(chdir(save_dir)); + enumerator->destroy(enumerator); } /** - * list all X.509 attribute certificates in the chained list + * List all X.509 attribute certificates in the chained list */ -void list_acerts(bool utc) +void ac_list_certs(bool utc) { - x509acert_t *x509ac = x509acerts; + enumerator_t *enumerator; + certificate_t *cert; time_t now; /* determine the current time */ time(&now); - if (x509ac) + if (acerts->get_count(acerts) > 0) { whack_log(RC_COMMENT, " "); whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:"); } - while (x509ac) + enumerator = acerts->create_enumerator(acerts); + while (enumerator->enumerate(enumerator, &cert)) { - certificate_t *cert_ac = x509ac->ac; - ac_t *ac = (ac_t*)cert_ac; + ac_t *ac = (ac_t*)cert; identification_t *entityName, *holderIssuer, *issuer; chunk_t holderSerial, serial, authKeyID; time_t notBefore, notAfter; @@ -293,7 +249,7 @@ void list_acerts(bool utc) whack_log(RC_COMMENT, " "); - entityName = cert_ac->get_subject(cert_ac); + entityName = cert->get_subject(cert); if (entityName) { whack_log(RC_COMMENT, " holder: \"%Y\"", entityName); @@ -314,18 +270,17 @@ void list_acerts(bool utc) groups = ac->get_groups(ac); if (groups) { - whack_log(RC_COMMENT, " groups: %s", - groups->get_string(groups)); + whack_log(RC_COMMENT, " groups: %s", groups->get_string(groups)); groups->destroy(groups); } - issuer = cert_ac->get_issuer(cert_ac); + issuer = cert->get_issuer(cert); whack_log(RC_COMMENT, " issuer: \"%Y\"", issuer); serial = ac->get_serial(ac); whack_log(RC_COMMENT, " serial: %#B", &serial); - cert_ac->get_validity(cert_ac, &now, ¬Before, ¬After); + cert->get_validity(cert, &now, ¬Before, ¬After); whack_log(RC_COMMENT, " validity: not before %T %s", ¬Before, utc, (notBefore < now)?"ok":"fatal (not valid yet)"); @@ -337,8 +292,7 @@ void list_acerts(bool utc) { whack_log(RC_COMMENT, " authkey: %#B", &authKeyID); } - - x509ac = x509ac->next; } + enumerator->destroy(enumerator); } diff --git a/src/pluto/ac.h b/src/pluto/ac.h index 46902429e..d4e0c1590 100644 --- a/src/pluto/ac.h +++ b/src/pluto/ac.h @@ -2,7 +2,6 @@ * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter * Copyright (C) 2009 Andreas Steffen - * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -24,20 +23,17 @@ /* access structure for an X.509 attribute certificate */ -typedef struct x509acert x509acert_t; +extern void ac_initialize(void); +extern void ac_finalize(void); +extern void ac_load_certs(void); +extern void ac_list_certs(bool utc); + +extern certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial); -struct x509acert { - certificate_t *ac; - x509acert_t *next; -}; +extern bool ac_verify_cert(certificate_t *ac, bool strict); -extern bool verify_x509acert(x509acert_t *ac, bool strict); -extern bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn, +extern bool match_group_membership(ietf_attributes_t *peer_attributes, + char *conn, ietf_attributes_t *conn_attributes); -extern x509acert_t* get_x509acert(identification_t *issuer, chunk_t serial); -extern void load_acerts(void); -extern void free_acert(x509acert_t *ac); -extern void free_acerts(void); -extern void list_acerts(bool utc); -#endif /* _AH_H */ +#endif /* _AC_H */ diff --git a/src/pluto/builder.c b/src/pluto/builder.c index 39a85eddb..6c7cde547 100644 --- a/src/pluto/builder.c +++ b/src/pluto/builder.c @@ -31,7 +31,6 @@ #include "defs.h" #include "log.h" #include "certs.h" -#include "ac.h" #include "crl.h" /** @@ -107,45 +106,6 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args) } /** - * Load a attribute certificate - */ -static x509acert_t *builder_load_ac(certificate_type_t type, va_list args) -{ - chunk_t blob = chunk_empty; - x509acert_t *ac; - - while (TRUE) - { - switch (va_arg(args, builder_part_t)) - { - case BUILD_BLOB_ASN1_DER: - blob = va_arg(args, chunk_t); - continue; - case BUILD_END: - break; - default: - return NULL; - } - break; - } - if (blob.ptr) - { - ac = malloc_thing(x509acert_t); - ac->next = NULL; - ac->ac = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_AC, - BUILD_BLOB_ASN1_DER, blob, BUILD_END); - if (ac->ac && verify_x509acert(ac, FALSE)) - { - return ac; - } - plog(" error in X.509 AC"); - free_acert(ac); - } - return NULL; -} - -/** * Load a CRL */ static x509crl_t *builder_load_crl(certificate_type_t type, va_list args) @@ -190,8 +150,6 @@ void init_builder(void) { lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT, (builder_function_t)builder_load_cert); - lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_AC, - (builder_function_t)builder_load_ac); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL, (builder_function_t)builder_load_crl); } @@ -199,7 +157,6 @@ void init_builder(void) void free_builder(void) { lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_cert); - lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_ac); lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_crl); } diff --git a/src/pluto/connections.c b/src/pluto/connections.c index 12585364c..528e40897 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -3836,13 +3836,13 @@ void get_peer_ca_and_groups(connection_t *c, p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); if (p1st && p1st->st_peer_pubkey && p1st->st_peer_pubkey->issuer) { - x509acert_t *x509ac; + certificate_t *cert; - x509ac = get_x509acert(p1st->st_peer_pubkey->issuer, - p1st->st_peer_pubkey->serial); - if (x509ac && verify_x509acert(x509ac, strict_crl_policy)) + cert = ac_get_cert(p1st->st_peer_pubkey->issuer, + p1st->st_peer_pubkey->serial); + if (cert && ac_verify_cert(cert, strict_crl_policy)) { - ac_t * ac = (ac_t*)x509ac->ac; + ac_t *ac = (ac_t*)cert; *peer_attributes = ac->get_groups(ac); } diff --git a/src/pluto/constants.h b/src/pluto/constants.h index 010c1c410..38fa0f2c7 100644 --- a/src/pluto/constants.h +++ b/src/pluto/constants.h @@ -16,6 +16,8 @@ #ifndef _CONSTANTS_H #define _CONSTANTS_H +#include <freeswan.h> + #include <utils.h> #include <utils/identification.h> #include <crypto/hashers/hasher.h> diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 982f99109..6e594aa9a 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(); + ac_initialize(); /* drop unneeded capabilities and change UID/GID */ prctl(PR_SET_KEEPCAPS, 1); @@ -728,7 +729,7 @@ int main(int argc, char **argv) /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ - load_acerts(); + ac_load_certs(); daily_log_event(); call_server(); @@ -753,10 +754,10 @@ void exit_pluto(int status) 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_acerts(); /* free chain of X.509 attribute certificates */ 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 */ scx_finalize(); /* finalize and unload PKCS #11 module */ xauth_finalize(); /* finalize and unload XAUTH module */ stop_adns(); diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c index 29de2e93c..620940675 100644 --- a/src/pluto/rcv_whack.c +++ b/src/pluto/rcv_whack.c @@ -455,7 +455,7 @@ void whack_handle(int whackctlfd) if (msg.whack_reread & REREAD_ACERTS) { - load_acerts(); + ac_load_certs(); } if (msg.whack_reread & REREAD_CRLS) @@ -496,7 +496,7 @@ void whack_handle(int whackctlfd) if (msg.whack_list & LIST_ACERTS) { - list_acerts(msg.whack_utc); + ac_list_certs(msg.whack_utc); } if (msg.whack_list & LIST_CAINFOS) |