diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2009-11-10 23:54:04 +0100 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2009-11-10 23:54:04 +0100 |
commit | f565d0c575f9d7e4a53e10ee447871fea21cb2e3 (patch) | |
tree | 950b57b988a21db56ded2da3892cfad4dea6b9d4 /src/pluto/certs.c | |
parent | cc543182bcf79b306188262b5537bc55f89c0965 (diff) | |
download | strongswan-f565d0c575f9d7e4a53e10ee447871fea21cb2e3.tar.bz2 strongswan-f565d0c575f9d7e4a53e10ee447871fea21cb2e3.tar.xz |
merged pluto's PGP certificate parsing with charon's
Diffstat (limited to 'src/pluto/certs.c')
-rw-r--r-- | src/pluto/certs.c | 205 |
1 files changed, 139 insertions, 66 deletions
diff --git a/src/pluto/certs.c b/src/pluto/certs.c index 89e289b6c..644f65766 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -18,60 +18,83 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#include <time.h> #include <freeswan.h> -#include "library.h" -#include "asn1/asn1.h" -#include "credentials/certificates/certificate.h" +#include <library.h> +#include <asn1/asn1.h> +#include <credentials/certificates/certificate.h> +#include <credentials/certificates/pgp_certificate.h> #include "constants.h" #include "defs.h" #include "log.h" #include "certs.h" #include "whack.h" +#include "fetch.h" +#include "keys.h" #include "builder.h" /** - * used for initializatin of certs + * Initialization */ -const cert_t cert_empty = {CERT_NONE, {NULL}}; +const cert_t cert_empty = { + NULL , /* cert */ + NULL , /* *next */ + 0 , /* count */ + FALSE /* smartcard */ +}; /** - * extracts the certificate to be sent to the peer + * Chained lists of X.509 and PGP end entity certificates */ -chunk_t cert_get_encoding(cert_t cert) +static cert_t *certs = NULL; + +/** + * Free a pluto certificate + */ +void cert_free(cert_t *cert) { - switch (cert.type) + if (cert) { - case CERT_PGP: - return chunk_clone(cert.u.pgp->certificate); - case CERT_X509_SIGNATURE: - return cert.u.x509->cert->get_encoding(cert.u.x509->cert); - default: - return chunk_empty; + certificate_t *certificate = cert->cert; + + if (certificate) + { + certificate->destroy(certificate); + } + free(cert); } } -public_key_t* cert_get_public_key(const cert_t cert) +/** + * Add a pluto end entity certificate to the chained list + */ +cert_t* cert_add(cert_t *cert) { - switch (cert.type) - { - case CERT_PGP: - { - public_key_t *public_key = cert.u.pgp->public_key; + certificate_t *certificate = cert->cert; + cert_t *c = certs; - return public_key->get_ref(public_key); - } - case CERT_X509_SIGNATURE: + while (c != NULL) + { + if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */ { - certificate_t *certificate = cert.u.x509->cert; - - return certificate->get_public_key(certificate); + cert_free(cert); + return c; } - default: - return NULL; + c = c->next; } + + /* insert new cert at the root of the chain */ + lock_certs_and_keys("cert_add"); + cert->next = certs; + certs = cert; + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log(" cert inserted") + ) + unlock_certs_and_keys("cert_add"); + return cert; } /** @@ -161,7 +184,7 @@ private_key_t* load_private_key(char* filename, prompt_pass_t *pass, /** * Loads a X.509 or OpenPGP certificate */ -bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out) +cert_t* load_cert(char *filename, const char *label, x509_flag_t flags) { cert_t *cert; @@ -171,83 +194,133 @@ bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out BUILD_END); if (cert) { - /* the API passes an empty cert_t, we move over and free the built one */ plog(" loaded %s certificate from '%s'", label, filename); - *out = *cert; - free(cert); - return TRUE; } - return FALSE; + return cert; } /** * Loads a host certificate */ -bool load_host_cert(char *filename, cert_t *cert) +cert_t* load_host_cert(char *filename) { char *path = concatenate_paths(HOST_CERT_PATH, filename); - return load_cert(path, "host", X509_NONE, cert); + return load_cert(path, "host", X509_NONE); } /** * Loads a CA certificate */ -bool load_ca_cert(char *filename, cert_t *cert) +cert_t* load_ca_cert(char *filename) { char *path = concatenate_paths(CA_CERT_PATH, filename); - return load_cert(path, "CA", X509_NONE, cert); + return load_cert(path, "CA", X509_NONE); } /** - * establish equality of two certificates + * for each link pointing to the certificate increase the count by one */ -bool same_cert(const cert_t *a, const cert_t *b) +void cert_share(cert_t *cert) { - return a->type == b->type && a->u.x509 == b->u.x509; + if (cert != NULL) + { + cert->count++; + } } -/** - * for each link pointing to the certificate increase the count by one +/* release of a certificate decreases the count by one + * the certificate is freed when the counter reaches zero */ -void share_cert(cert_t cert) +void cert_release(cert_t *cert) { - switch (cert.type) + if (cert && --cert->count == 0) { - case CERT_PGP: - share_pgpcert(cert.u.pgp); - break; - case CERT_X509_SIGNATURE: - share_x509cert(cert.u.x509); - break; - default: - break; + cert_t **pp = &certs; + while (*pp != cert) + { + pp = &(*pp)->next; + } + *pp = cert->next; + cert_free(cert); } } -/* release of a certificate decreases the count by one - * the certificate is freed when the counter reaches zero +/** + * List all PGP end certificates in a chained list */ -void release_cert(cert_t cert) +void list_pgp_end_certs(bool utc) { - switch (cert.type) + cert_t *cert = certs; + time_t now = time(NULL); + bool first = TRUE; + + + while (cert != NULL) { - case CERT_PGP: - release_pgpcert(cert.u.pgp); - break; - case CERT_X509_SIGNATURE: - release_x509cert(cert.u.x509); - break; - default: - break; + certificate_t *certificate = cert->cert; + + if (certificate->get_type(certificate) == CERT_GPG) + { + time_t created, until; + public_key_t *key; + identification_t *userid = certificate->get_subject(certificate); + pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate; + chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert); + + if (first) + { + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of PGP End Entity Certificates:"); + first = false; + } + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, " userid: '%Y'", userid); + whack_log(RC_COMMENT, " digest: %#B", &fingerprint); + + /* list validity */ + certificate->get_validity(certificate, &now, &created, &until); + whack_log(RC_COMMENT, " created: %T", &created, utc); + whack_log(RC_COMMENT, " until: %T %s%s", &until, utc, + check_expiry(until, CA_CERT_WARNING_INTERVAL, TRUE), + (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":""); + + key = certificate->get_public_key(certificate); + if (key) + { + chunk_t keyid; + + whack_log(RC_COMMENT, " pubkey: %N %4d bits%s", + key_type_names, key->get_type(key), + key->get_keysize(key) * BITS_PER_BYTE, + has_private_key(cert)? ", has private key" : ""); + if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) + { + whack_log(RC_COMMENT, " keyid: %#B", &keyid); + } + if (key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid)) + { + whack_log(RC_COMMENT, " subjkey: %#B", &keyid); + } + } + } + cert = cert->next; } } /** + * List all X.509 end certificates in a chained list + */ +void list_x509_end_certs(bool utc) +{ + list_x509cert_chain("End Entity", certs, X509_NONE, utc); +} + +/** * list all X.509 and OpenPGP end certificates */ -void list_certs(bool utc) +void cert_list(bool utc) { list_x509_end_certs(utc); list_pgp_end_certs(utc); |