merged pluto's PGP certificate parsing with charon's

This commit is contained in:
Andreas Steffen
2009-11-10 23:54:04 +01:00
parent cc543182bc
commit f565d0c575
25 changed files with 471 additions and 1087 deletions
-1
View File
@@ -36,7 +36,6 @@ modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \ nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \ ocsp.c ocsp.h \
packet.c packet.h \ packet.c packet.h \
pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \ pkcs7.c pkcs7.h \
plutomain.c \ plutomain.c \
rcv_whack.c rcv_whack.h \ rcv_whack.c rcv_whack.h \
+1 -1
View File
@@ -85,7 +85,7 @@ bool ac_verify_cert(certificate_t *cert, bool strict)
identification_t *subject = cert->get_subject(cert); identification_t *subject = cert->get_subject(cert);
identification_t *issuer = cert->get_issuer(cert); identification_t *issuer = cert->get_issuer(cert);
chunk_t authKeyID = ac->get_authKeyIdentifier(ac); chunk_t authKeyID = ac->get_authKeyIdentifier(ac);
x509cert_t *aacert; cert_t *aacert;
time_t notBefore, valid_until; time_t notBefore, valid_until;
DBG1("holder: '%Y'", subject); DBG1("holder: '%Y'", subject);
+19 -31
View File
@@ -64,43 +64,31 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args)
} }
if (blob.ptr) if (blob.ptr)
{ {
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
if (pgp) if (pgp)
{ {
pgpcert_t *pgpcert = malloc_thing(pgpcert_t); cert->cert = lib->creds->create(lib->creds,
*pgpcert = pgpcert_empty; CRED_CERTIFICATE, CERT_GPG,
if (parse_pgp(chunk_clone(blob), pgpcert)) BUILD_BLOB_PGP, blob,
{ BUILD_END);
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
cert->type = CERT_PGP;
cert->u.pgp = pgpcert;
return cert;
}
plog(" error in OpenPGP certificate");
free_pgpcert(pgpcert);
} }
else else
{ {
x509cert_t *x509cert = malloc_thing(x509cert_t); cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
*x509cert = empty_x509cert; BUILD_BLOB_ASN1_DER, blob,
x509cert->cert = lib->creds->create(lib->creds, BUILD_X509_FLAG, flags,
CRED_CERTIFICATE, CERT_X509, BUILD_END);
BUILD_BLOB_ASN1_DER, blob,
BUILD_X509_FLAG, flags,
BUILD_END);
if (x509cert->cert)
{
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
cert->type = CERT_X509_SIGNATURE;
cert->u.x509 = x509cert;
return cert;
}
plog(" error in X.509 certificate");
free_x509cert(x509cert);
} }
if (cert->cert)
{
return cert;
}
plog(" error in X.509 certificate");
cert_free(cert);
} }
return NULL; return NULL;
} }
+34 -31
View File
@@ -37,7 +37,7 @@
/* chained list of X.509 authority certificates (ca, aa, and ocsp) */ /* chained list of X.509 authority certificates (ca, aa, and ocsp) */
static x509cert_t *x509authcerts = NULL; static cert_t *x509authcerts = NULL;
/* chained list of X.509 certification authority information records */ /* chained list of X.509 certification authority information records */
@@ -79,7 +79,7 @@ bool trusted_ca(identification_t *a, identification_t *b, int *pathlen)
{ {
certificate_t *certificate; certificate_t *certificate;
identification_t *issuer; identification_t *issuer;
x509cert_t *cacert; cert_t *cacert;
cacert = get_authcert(a, chunk_empty, X509_CA); cacert = get_authcert(a, chunk_empty, X509_CA);
if (cacert == NULL) if (cacert == NULL)
@@ -161,9 +161,10 @@ bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca,
*/ */
static void free_first_authcert(void) static void free_first_authcert(void)
{ {
x509cert_t *first = x509authcerts; cert_t *first = x509authcerts;
x509authcerts = first->next; x509authcerts = first->next;
free_x509cert(first); cert_free(first);
} }
/* /*
@@ -174,18 +175,19 @@ void free_authcerts(void)
lock_authcert_list("free_authcerts"); lock_authcert_list("free_authcerts");
while (x509authcerts != NULL) while (x509authcerts != NULL)
{
free_first_authcert(); free_first_authcert();
}
unlock_authcert_list("free_authcerts"); unlock_authcert_list("free_authcerts");
} }
/* /*
* get a X.509 authority certificate with a given subject or keyid * get a X.509 authority certificate with a given subject or keyid
*/ */
x509cert_t* get_authcert(identification_t *subject, chunk_t keyid, cert_t* get_authcert(identification_t *subject, chunk_t keyid,
x509_flag_t auth_flags) x509_flag_t auth_flags)
{ {
x509cert_t *cert, *prev_cert = NULL; cert_t *cert, *prev_cert = NULL;
/* the authority certificate list is empty */ /* the authority certificate list is empty */
if (x509authcerts == NULL) if (x509authcerts == NULL)
@@ -238,11 +240,11 @@ x509cert_t* get_authcert(identification_t *subject, chunk_t keyid,
/* /*
* add an authority certificate to the chained list * add an authority certificate to the chained list
*/ */
x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags) cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags)
{ {
certificate_t *certificate = cert->cert; certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate; x509_t *x509 = (x509_t*)certificate;
x509cert_t *old_cert; cert_t *old_cert;
lock_authcert_list("add_authcert"); lock_authcert_list("add_authcert");
@@ -258,7 +260,7 @@ x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
) )
unlock_authcert_list("add_authcert"); unlock_authcert_list("add_authcert");
free_x509cert(cert); cert_free(cert);
return old_cert; return old_cert;
} }
else else
@@ -274,7 +276,7 @@ x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
/* add new authcert to chained list */ /* add new authcert to chained list */
cert->next = x509authcerts; cert->next = x509authcerts;
x509authcerts = cert; x509authcerts = cert;
share_x509cert(cert); /* set count to one */ cert_share(cert); /* set count to one */
DBG(DBG_CONTROL | DBG_PARSING, DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" authcert inserted") DBG_log(" authcert inserted")
) )
@@ -302,16 +304,17 @@ void load_authcerts(char *type, char *path, x509_flag_t auth_flags)
while (enumerator->enumerate(enumerator, NULL, &file, &st)) while (enumerator->enumerate(enumerator, NULL, &file, &st))
{ {
cert_t cert; cert_t *cert;
if (!S_ISREG(st.st_mode)) if (!S_ISREG(st.st_mode))
{ {
/* skip special file */ /* skip special file */
continue; continue;
} }
if (load_cert(file, type, auth_flags, &cert)) cert = load_cert(file, type, auth_flags);
if (cert)
{ {
add_authcert(cert.u.x509, auth_flags); add_authcert(cert, auth_flags);
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
@@ -330,8 +333,8 @@ void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc)
/* /*
* get a cacert with a given subject or keyid from an alternative list * get a cacert with a given subject or keyid from an alternative list
*/ */
static const x509cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid, static const cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
const x509cert_t *cert) const cert_t *cert)
{ {
if (cert == NULL) if (cert == NULL)
{ {
@@ -369,7 +372,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. /* establish trust into a candidate authcert by going up the trust chain.
* validity and revocation status are not checked. * validity and revocation status are not checked.
*/ */
bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain)
{ {
int pathlen; int pathlen;
@@ -382,7 +385,7 @@ bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chai
identification_t *subject = certificate->get_subject(certificate); identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate); identification_t *issuer = certificate->get_issuer(certificate);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509); chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
const x509cert_t *authcert = NULL; const cert_t *authcert = NULL;
DBG(DBG_CONTROL, DBG(DBG_CONTROL,
DBG_log("subject: '%Y'", subject); DBG_log("subject: '%Y'", subject);
@@ -551,8 +554,7 @@ ca_info_t* create_ca_info(void)
void add_ca_info(const whack_message_t *msg) void add_ca_info(const whack_message_t *msg)
{ {
smartcard_t *sc = NULL; smartcard_t *sc = NULL;
cert_t cert; cert_t *cert = NULL;
bool valid_cert = FALSE;
bool cached_cert = FALSE; bool cached_cert = FALSE;
if (find_ca_info_by_name(msg->name, FALSE)) if (find_ca_info_by_name(msg->name, FALSE))
@@ -564,18 +566,17 @@ void add_ca_info(const whack_message_t *msg)
if (scx_on_smartcard(msg->cacert)) if (scx_on_smartcard(msg->cacert))
{ {
/* load CA cert from smartcard */ /* load CA cert from smartcard */
valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert); cert = scx_load_cert(msg->cacert, &sc, &cached_cert);
} }
else else
{ {
/* load CA cert from file */ /* load CA cert from file */
valid_cert = load_ca_cert(msg->cacert, &cert); cert = load_ca_cert(msg->cacert);
} }
if (valid_cert) if (cert)
{ {
x509cert_t *cacert = cert.u.x509; certificate_t *certificate = cert->cert;
certificate_t *certificate = cacert->cert;
x509_t *x509 = (x509_t*)certificate; x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate); identification_t *subject = certificate->get_subject(certificate);
chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509); chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
@@ -589,7 +590,7 @@ void add_ca_info(const whack_message_t *msg)
/* ca_info is already present */ /* ca_info is already present */
loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found," loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
"ignoring \"%s\"", ca->name, msg->name); "ignoring \"%s\"", ca->name, msg->name);
free_x509cert(cacert); cert_free(cert);
return; return;
} }
@@ -647,13 +648,15 @@ void add_ca_info(const whack_message_t *msg)
unlock_ca_info_list("add_ca_info"); unlock_ca_info_list("add_ca_info");
/* add cacert to list of authcerts */ /* add cacert to list of authcerts */
cacert = add_authcert(cacert, X509_CA); cert = add_authcert(cert, X509_CA);
if (!cached_cert && sc != NULL) if (!cached_cert && sc != NULL)
{ {
if (sc->last_cert.type == CERT_X509_SIGNATURE) if (sc->last_cert != NULL)
sc->last_cert.u.x509->count--; {
sc->last_cert.u.x509 = cacert; sc->last_cert->count--;
share_cert(sc->last_cert); }
sc->last_cert = cert;
cert_share(sc->last_cert);
} }
if (sc != NULL) if (sc != NULL)
time(&sc->last_load); time(&sc->last_load);
+4 -5
View File
@@ -18,7 +18,7 @@
#include <utils/linked_list.h> #include <utils/linked_list.h>
#include <utils/identification.h> #include <utils/identification.h>
#include "x509.h" #include "certs.h"
#include "whack.h" #include "whack.h"
/* CA info structures */ /* CA info structures */
@@ -40,14 +40,13 @@ struct ca_info {
extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen); extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen);
extern bool match_requested_ca(linked_list_t *requested_ca, extern bool match_requested_ca(linked_list_t *requested_ca,
identification_t *our_ca, int *our_pathlen); identification_t *our_ca, int *our_pathlen);
extern x509cert_t* get_authcert(identification_t *subject, chunk_t keyid, extern cert_t* get_authcert(identification_t *subject, chunk_t keyid,
x509_flag_t auth_flags); x509_flag_t auth_flags);
extern void load_authcerts(char *type, char *path, 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 cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags);
extern void free_authcerts(void); extern void free_authcerts(void);
extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc); extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
extern bool trust_authcert_candidate(const x509cert_t *cert, extern bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain);
const x509cert_t *alt_chain);
extern ca_info_t* get_ca_info(identification_t *name, chunk_t keyid); 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 bool find_ca_info_by_name(const char *name, bool delete);
extern void add_ca_info(const whack_message_t *msg); extern void add_ca_info(const whack_message_t *msg);
+140 -67
View File
@@ -18,60 +18,83 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <time.h>
#include <freeswan.h> #include <freeswan.h>
#include "library.h" #include <library.h>
#include "asn1/asn1.h" #include <asn1/asn1.h>
#include "credentials/certificates/certificate.h" #include <credentials/certificates/certificate.h>
#include <credentials/certificates/pgp_certificate.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "log.h" #include "log.h"
#include "certs.h" #include "certs.h"
#include "whack.h" #include "whack.h"
#include "fetch.h"
#include "keys.h"
#include "builder.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: certificate_t *certificate = cert->cert;
return chunk_clone(cert.u.pgp->certificate);
case CERT_X509_SIGNATURE: if (certificate)
return cert.u.x509->cert->get_encoding(cert.u.x509->cert); {
default: certificate->destroy(certificate);
return chunk_empty; }
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) certificate_t *certificate = cert->cert;
cert_t *c = certs;
while (c != NULL)
{ {
case CERT_PGP: if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
{ {
public_key_t *public_key = cert.u.pgp->public_key; cert_free(cert);
return c;
return public_key->get_ref(public_key);
} }
case CERT_X509_SIGNATURE: c = c->next;
{
certificate_t *certificate = cert.u.x509->cert;
return certificate->get_public_key(certificate);
}
default:
return NULL;
} }
/* 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 * 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; cert_t *cert;
@@ -171,83 +194,133 @@ bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out
BUILD_END); BUILD_END);
if (cert) 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); plog(" loaded %s certificate from '%s'", label, filename);
*out = *cert;
free(cert);
return TRUE;
} }
return FALSE; return cert;
} }
/** /**
* Loads a host certificate * 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); 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 * 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); 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
*/
bool same_cert(const cert_t *a, const cert_t *b)
{
return a->type == b->type && a->u.x509 == b->u.x509;
} }
/** /**
* for each link pointing to the certificate increase the count by one * for each link pointing to the certificate increase the count by one
*/ */
void share_cert(cert_t cert) void cert_share(cert_t *cert)
{ {
switch (cert.type) if (cert != NULL)
{ {
case CERT_PGP: cert->count++;
share_pgpcert(cert.u.pgp);
break;
case CERT_X509_SIGNATURE:
share_x509cert(cert.u.x509);
break;
default:
break;
} }
} }
/* release of a certificate decreases the count by one /* release of a certificate decreases the count by one
* the certificate is freed when the counter reaches zero * the certificate is freed when the counter reaches zero
*/ */
void release_cert(cert_t cert) void cert_release(cert_t *cert)
{ {
switch (cert.type) if (cert && --cert->count == 0)
{ {
case CERT_PGP: cert_t **pp = &certs;
release_pgpcert(cert.u.pgp); while (*pp != cert)
break; {
case CERT_X509_SIGNATURE: pp = &(*pp)->next;
release_x509cert(cert.u.x509); }
break; *pp = cert->next;
default: cert_free(cert);
break;
} }
} }
/**
* List all PGP end certificates in a chained list
*/
void list_pgp_end_certs(bool utc)
{
cert_t *cert = certs;
time_t now = time(NULL);
bool first = TRUE;
while (cert != NULL)
{
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 * list all X.509 and OpenPGP end certificates
*/ */
void list_certs(bool utc) void cert_list(bool utc)
{ {
list_x509_end_certs(utc); list_x509_end_certs(utc);
list_pgp_end_certs(utc); list_pgp_end_certs(utc);
+23 -22
View File
@@ -18,9 +18,12 @@
#define _CERTS_H #define _CERTS_H
#include <credentials/keys/private_key.h> #include <credentials/keys/private_key.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/x509.h>
#include "x509.h" #include <freeswan.h>
#include "pgpcert.h"
#include "defs.h"
/* path definitions for private keys, end certs, /* path definitions for private keys, end certs,
* cacerts, attribute certs and crls * cacerts, attribute certs and crls
@@ -43,16 +46,16 @@
#define CRL_WARNING_INTERVAL 7 /* days */ #define CRL_WARNING_INTERVAL 7 /* days */
#define ACERT_WARNING_INTERVAL 1 /* day */ #define ACERT_WARNING_INTERVAL 1 /* day */
/* certificate access structure /* access structure for a pluto certificate */
* currently X.509 and OpenPGP certificates are supported
*/ typedef struct cert_t cert_t;
typedef struct {
u_char type; struct cert_t {
union { certificate_t *cert;
x509cert_t *x509; cert_t *next;
pgpcert_t *pgp; int count;
} u; bool smartcard;
} cert_t; };
/* used for initialization */ /* used for initialization */
extern const cert_t cert_empty; extern const cert_t cert_empty;
@@ -62,18 +65,16 @@ extern const cert_t cert_empty;
*/ */
extern bool no_cr_send; extern bool no_cr_send;
extern public_key_t* cert_get_public_key(const cert_t cert);
extern chunk_t cert_get_encoding(cert_t cert);
extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass, extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
key_type_t type); key_type_t type);
extern bool load_cert(char *filename, const char *label, x509_flag_t flags, extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
cert_t *cert); extern cert_t* load_host_cert(char *filename);
extern bool load_host_cert(char *filename, cert_t *cert); extern cert_t* load_ca_cert(char *filename);
extern bool load_ca_cert(char *filename, cert_t *cert); extern cert_t* cert_add(cert_t *cert);
extern bool same_cert(const cert_t *a, const cert_t *b); extern void cert_free(cert_t *cert);
extern void share_cert(cert_t cert); extern void cert_share(cert_t *cert);
extern void release_cert(cert_t cert); extern void cert_release(cert_t *cert);
extern void list_certs(bool utc); extern void cert_list(bool utc);
#endif /* _CERTS_H */ #endif /* _CERTS_H */
+47 -63
View File
@@ -39,7 +39,6 @@
#include "x509.h" #include "x509.h"
#include "ca.h" #include "ca.h"
#include "crl.h" #include "crl.h"
#include "pgpcert.h"
#include "certs.h" #include "certs.h"
#include "ac.h" #include "ac.h"
#include "smartcard.h" #include "smartcard.h"
@@ -398,9 +397,9 @@ void delete_connection(connection_t *c, bool relations)
gw_delref(&c->gw_info); gw_delref(&c->gw_info);
lock_certs_and_keys("delete_connection"); lock_certs_and_keys("delete_connection");
release_cert(c->spd.this.cert); cert_release(c->spd.this.cert);
scx_release(c->spd.this.sc); scx_release(c->spd.this.sc);
release_cert(c->spd.that.cert); cert_release(c->spd.that.cert);
scx_release(c->spd.that.sc); scx_release(c->spd.that.sc);
unlock_certs_and_keys("delete_connection"); unlock_certs_and_keys("delete_connection");
@@ -736,7 +735,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.this.pool = clone_str(c->spd.this.pool); c->spd.this.pool = clone_str(c->spd.this.pool);
c->spd.this.updown = clone_str(c->spd.this.updown); c->spd.this.updown = clone_str(c->spd.this.updown);
scx_share(c->spd.this.sc); scx_share(c->spd.this.sc);
share_cert(c->spd.this.cert); cert_share(c->spd.this.cert);
if (c->spd.this.ca) if (c->spd.this.ca)
{ {
c->spd.this.ca = c->spd.this.ca->clone(c->spd.this.ca); c->spd.this.ca = c->spd.this.ca->clone(c->spd.this.ca);
@@ -749,7 +748,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.that.pool = clone_str(c->spd.that.pool); c->spd.that.pool = clone_str(c->spd.that.pool);
c->spd.that.updown = clone_str(c->spd.that.updown); c->spd.that.updown = clone_str(c->spd.that.updown);
scx_share(c->spd.that.sc); scx_share(c->spd.that.sc);
share_cert(c->spd.that.cert); cert_share(c->spd.that.cert);
if (c->spd.that.ca) if (c->spd.that.ca)
{ {
c->spd.that.ca = c->spd.that.ca->clone(c->spd.that.ca); c->spd.that.ca = c->spd.that.ca->clone(c->spd.that.ca);
@@ -767,13 +766,12 @@ static void unshare_connection_strings(connection_t *c)
static void load_end_certificate(char *filename, struct end *dst) static void load_end_certificate(char *filename, struct end *dst)
{ {
time_t valid_until; time_t valid_until;
cert_t cert; cert_t *cert = NULL;
bool valid_cert = FALSE; certificate_t *certificate;
bool cached_cert = FALSE; bool cached_cert = FALSE;
/* initialize end certificate */ /* initialize end certificate */
dst->cert.type = CERT_NONE; dst->cert = NULL;
dst->cert.u.x509 = NULL;
/* initialize smartcard info record */ /* initialize smartcard info record */
dst->sc = NULL; dst->sc = NULL;
@@ -783,87 +781,73 @@ static void load_end_certificate(char *filename, struct end *dst)
if (scx_on_smartcard(filename)) if (scx_on_smartcard(filename))
{ {
/* load cert from smartcard */ /* load cert from smartcard */
valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert); cert = scx_load_cert(filename, &dst->sc, &cached_cert);
} }
else else
{ {
/* load cert from file */ /* load cert from file */
valid_cert = load_host_cert(filename, &cert); cert = load_host_cert(filename);
} }
} }
if (valid_cert) if (cert)
{ {
switch (cert.type) certificate = cert->cert;
if (dst->id->get_type(dst->id) == ID_ANY ||
!certificate->has_subject(certificate, dst->id))
{ {
case CERT_PGP: plog( " id '%Y' not confirmed by certificate, defaulting to '%Y'",
dst->id = select_pgpcert_id(cert.u.pgp, dst->id); dst->id, certificate->get_subject(certificate));
dst->id->destroy(dst->id);
dst->id = certificate->get_subject(certificate);
dst->id = dst->id->clone(dst->id);
}
if (cached_cert) if (cached_cert)
{
dst->cert = cert;
}
else
{
if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{ {
dst->cert = cert; cert_free(cert);
return;
} }
else DBG(DBG_CONTROL,
{ DBG_log("certificate is valid")
valid_until = cert.u.pgp->until; )
add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL); add_public_key_from_cert(cert, valid_until, DAL_LOCAL);
dst->cert.type = cert.type; dst->cert = cert_add(cert);
dst->cert.u.pgp = add_pgpcert(cert.u.pgp); }
} certificate = dst->cert->cert;
break;
case CERT_X509_SIGNATURE:
dst->id = select_x509cert_id(cert.u.x509, dst->id);
if (cached_cert) /* if no CA is defined, use issuer as default */
{ if (dst->ca == NULL && certificate->get_type(certificate) == CERT_X509)
dst->cert = cert; {
} identification_t *issuer;
else
{
certificate_t *certificate = cert.u.x509->cert;
if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{
free_x509cert(cert.u.x509);
break;
}
DBG(DBG_CONTROL,
DBG_log("certificate is valid")
)
add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL);
dst->cert.type = cert.type;
dst->cert.u.x509 = add_x509cert(cert.u.x509);
}
/* if no CA is defined, use issuer as default */ issuer = certificate->get_issuer(certificate);
if (dst->ca == NULL) dst->ca = issuer->clone(issuer);
{
certificate_t *certificate = dst->cert.u.x509->cert;
identification_t *issuer = certificate->get_issuer(certificate);
dst->ca = issuer->clone(issuer);
}
break;
default:
break;
} }
/* cache the certificate that was last retrieved from the smartcard */ /* cache the certificate that was last retrieved from the smartcard */
if (dst->sc) if (dst->sc)
{ {
if (!same_cert(&dst->sc->last_cert, &dst->cert)) if (!certificate->equals(certificate, dst->sc->last_cert->cert))
{ {
lock_certs_and_keys("load_end_certificates"); lock_certs_and_keys("load_end_certificates");
release_cert(dst->sc->last_cert); cert_release(dst->sc->last_cert);
dst->sc->last_cert = dst->cert; dst->sc->last_cert = dst->cert;
share_cert(dst->cert); cert_share(dst->cert);
unlock_certs_and_keys("load_end_certificates"); unlock_certs_and_keys("load_end_certificates");
} }
time(&dst->sc->last_load); time(&dst->sc->last_load);
} }
} }
scx_share(dst->sc); scx_share(dst->sc);
share_cert(dst->cert); cert_share(dst->cert);
} }
static bool extract_end(struct end *dst, const whack_end_t *src, static bool extract_end(struct end *dst, const whack_end_t *src,
+1 -1
View File
@@ -147,7 +147,7 @@ struct end {
u_int16_t host_port; /* host order */ u_int16_t host_port; /* host order */
u_int16_t port; /* host order */ u_int16_t port; /* host order */
u_int8_t protocol; u_int8_t protocol;
cert_t cert; /* end certificate */ cert_t *cert; /* end certificate */
identification_t *ca; /* CA distinguished name */ identification_t *ca; /* CA distinguished name */
ietf_attributes_t *groups; /* access control groups */ ietf_attributes_t *groups; /* access control groups */
smartcard_t *sc; /* smartcard reader and key info */ smartcard_t *sc; /* smartcard reader and key info */
+3 -4
View File
@@ -113,7 +113,7 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
crl_t *crl = (crl_t*)cert_crl; crl_t *crl = (crl_t*)cert_crl;
identification_t *issuer = cert_crl->get_issuer(cert_crl); identification_t *issuer = cert_crl->get_issuer(cert_crl);
chunk_t authKeyID = crl->get_authKeyIdentifier(crl); chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
x509cert_t *issuer_cert; cert_t *issuer_cert;
x509crl_t *oldcrl; x509crl_t *oldcrl;
time_t now, nextUpdate; time_t now, nextUpdate;
bool valid_sig; bool valid_sig;
@@ -340,8 +340,7 @@ void check_crls(void)
/* /*
* verify if a cert hasn't been revoked by a crl * verify if a cert hasn't been revoked by a crl
*/ */
cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until, cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
time_t *revocationDate,
crl_reason_t *revocationReason) crl_reason_t *revocationReason)
{ {
certificate_t *certificate = cert->cert; certificate_t *certificate = cert->cert;
@@ -402,7 +401,7 @@ cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
certificate_t *cert_crl = x509crl->crl; certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl; crl_t *crl = (crl_t*)cert_crl;
chunk_t authKeyID = crl->get_authKeyIdentifier(crl); chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
x509cert_t *issuer_cert; cert_t *issuer_cert;
bool trusted, valid; bool trusted, valid;
DBG(DBG_CONTROL, DBG(DBG_CONTROL,
+1 -2
View File
@@ -26,7 +26,6 @@ struct x509crl {
certificate_t *crl; certificate_t *crl;
x509crl_t *next; x509crl_t *next;
linked_list_t *distributionPoints; linked_list_t *distributionPoints;
chunk_t signature;
}; };
/* apply a strict CRL policy /* apply a strict CRL policy
@@ -46,7 +45,7 @@ extern long crl_check_interval;
extern void load_crls(void); extern void load_crls(void);
extern void check_crls(void); extern void check_crls(void);
extern bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl); extern bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl);
extern cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until, extern cert_status_t verify_by_crl(cert_t *cert, time_t *until,
time_t *revocationDate, time_t *revocationDate,
crl_reason_t *revocationReason); crl_reason_t *revocationReason);
extern void list_crls(bool utc, bool strict); extern void list_crls(bool utc, bool strict);
+3 -2
View File
@@ -199,9 +199,10 @@ struct db_context *ike_alg_db_new(connection_t *c, lset_t policy)
key_type_t key_type = KEY_ANY; key_type_t key_type = KEY_ANY;
if (c->spd.this.cert.type != CERT_NONE) if (c->spd.this.cert)
{ {
public_key_t *key = cert_get_public_key(c->spd.this.cert); certificate_t *certificate = c->spd.this.cert->cert;
public_key_t *key = certificate->get_public_key(certificate);
if (key == NULL) if (key == NULL)
{ {
+23 -20
View File
@@ -905,7 +905,6 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
struct state *st = new_state(); struct state *st = new_state();
pb_stream reply; /* not actually a reply, but you know what I mean */ pb_stream reply; /* not actually a reply, but you know what I mean */
pb_stream rbody; pb_stream rbody;
int vids_to_send = 0; int vids_to_send = 0;
/* set up new state */ /* set up new state */
@@ -925,7 +924,8 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
{ {
vids_to_send++; vids_to_send++;
} }
if (c->spd.this.cert.type == CERT_PGP) if (c->spd.this.cert &&
c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
{ {
vids_to_send++; vids_to_send++;
} }
@@ -1022,7 +1022,8 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
/* if we have an OpenPGP certificate we assume an /* if we have an OpenPGP certificate we assume an
* OpenPGP peer and have to send the Vendor ID * OpenPGP peer and have to send the Vendor ID
*/ */
if (c->spd.this.cert.type == CERT_PGP) if (c->spd.this.cert &&
c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
{ {
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
, &rbody, VID_OPENPGP)) , &rbody, VID_OPENPGP))
@@ -2166,12 +2167,12 @@ static void decode_cert(struct msg_digest *md)
blob.len = pbs_left(&p->pbs); blob.len = pbs_left(&p->pbs);
if (cert->isacert_type == CERT_X509_SIGNATURE) if (cert->isacert_type == CERT_X509_SIGNATURE)
{ {
x509cert_t x509cert = empty_x509cert; cert_t x509cert = cert_empty;
x509cert.cert = lib->creds->create(lib->creds, x509cert.cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob, BUILD_BLOB_ASN1_DER, blob,
BUILD_END); BUILD_END);
if (x509cert.cert) if (x509cert.cert)
{ {
if (verify_x509cert(&x509cert, strict_crl_policy, &valid_until)) if (verify_x509cert(&x509cert, strict_crl_policy, &valid_until))
@@ -2179,7 +2180,7 @@ static void decode_cert(struct msg_digest *md)
DBG(DBG_PARSING, DBG(DBG_PARSING,
DBG_log("Public key validated") DBG_log("Public key validated")
) )
add_x509_public_key(&x509cert, valid_until, DAL_SIGNED); add_public_key_from_cert(&x509cert, valid_until, DAL_SIGNED);
} }
else else
{ {
@@ -3518,7 +3519,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
connection_t *c = st->st_connection; connection_t *c = st->st_connection;
certpolicy_t cert_policy = c->spd.this.sendcert; certpolicy_t cert_policy = c->spd.this.sendcert;
cert_t mycert = c->spd.this.cert; cert_t *mycert = c->spd.this.cert;
bool requested, send_cert, send_cr; bool requested, send_cert, send_cr;
bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth); bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
@@ -3548,8 +3549,9 @@ stf_status main_inR2_outI3(struct msg_digest *md)
* or are requested to send it * or are requested to send it
*/ */
requested = cert_policy == CERT_SEND_IF_ASKED && c->got_certrequest; requested = cert_policy == CERT_SEND_IF_ASKED && c->got_certrequest;
send_cert = pubkey_auth && mycert.type != CERT_NONE send_cert = pubkey_auth && mycert &&
&& (cert_policy == CERT_ALWAYS_SEND || requested); mycert->cert->get_type(mycert->cert) == CERT_X509 &&
(cert_policy == CERT_ALWAYS_SEND || requested);
/* send certificate request if we don't have a preloaded RSA public key */ /* send certificate request if we don't have a preloaded RSA public key */
send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st); send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
@@ -3599,7 +3601,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
DBG(DBG_CONTROL, DBG(DBG_CONTROL,
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy) DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
) )
if (mycert.type != CERT_NONE) if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
{ {
const char *request_text = ""; const char *request_text = "";
@@ -3623,13 +3625,13 @@ stf_status main_inR2_outI3(struct msg_digest *md)
struct isakmp_cert cert_hd; struct isakmp_cert cert_hd;
cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG; cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG;
cert_hd.isacert_type = mycert.type; cert_hd.isacert_type = CERT_X509_SIGNATURE;
if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs)) if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
{ {
return STF_INTERNAL_ERROR; return STF_INTERNAL_ERROR;
} }
cert_encoding = cert_get_encoding(mycert); cert_encoding = mycert->cert->get_encoding(mycert->cert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT"); success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr); free(cert_encoding.ptr);
if (!success) if (!success)
@@ -3645,7 +3647,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
identification_t *ca = st->st_connection->spd.that.ca; identification_t *ca = st->st_connection->spd.that.ca;
chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty; chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty;
if (!build_and_ship_CR(mycert.type, cr, &md->rbody, ISAKMP_NEXT_SIG)) if (!build_and_ship_CR(CERT_X509_SIGNATURE, cr, &md->rbody, ISAKMP_NEXT_SIG))
{ {
return STF_INTERNAL_ERROR; return STF_INTERNAL_ERROR;
} }
@@ -3971,7 +3973,7 @@ main_inI3_outR3_tail(struct msg_digest *md
u_int8_t auth_payload; u_int8_t auth_payload;
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */ pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
certpolicy_t cert_policy; certpolicy_t cert_policy;
cert_t mycert; cert_t *mycert;
bool pubkey_auth, send_cert, requested; bool pubkey_auth, send_cert, requested;
/* ID and HASH_I or SIG_I in /* ID and HASH_I or SIG_I in
@@ -3996,7 +3998,8 @@ main_inI3_outR3_tail(struct msg_digest *md
requested = cert_policy == CERT_SEND_IF_ASKED requested = cert_policy == CERT_SEND_IF_ASKED
&& st->st_connection->got_certrequest; && st->st_connection->got_certrequest;
pubkey_auth = uses_pubkey_auth(st->st_oakley.auth); pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
send_cert = pubkey_auth && mycert.type != CERT_NONE && send_cert = pubkey_auth && mycert &&
mycert->cert->get_type(mycert->cert) == CERT_X509 &&
(cert_policy == CERT_ALWAYS_SEND || requested); (cert_policy == CERT_ALWAYS_SEND || requested);
/*************** build output packet HDR*;IDir;HASH/SIG_R ***************/ /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
@@ -4039,7 +4042,7 @@ main_inI3_outR3_tail(struct msg_digest *md
DBG(DBG_CONTROL, DBG(DBG_CONTROL,
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy) DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
) )
if (mycert.type != CERT_NONE) if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
{ {
const char *request_text = ""; const char *request_text = "";
@@ -4063,13 +4066,13 @@ main_inI3_outR3_tail(struct msg_digest *md
struct isakmp_cert cert_hd; struct isakmp_cert cert_hd;
cert_hd.isacert_np = ISAKMP_NEXT_SIG; cert_hd.isacert_np = ISAKMP_NEXT_SIG;
cert_hd.isacert_type = mycert.type; cert_hd.isacert_type = CERT_X509_SIGNATURE;
if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs)) if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
{ {
return STF_INTERNAL_ERROR; return STF_INTERNAL_ERROR;
} }
cert_encoding = cert_get_encoding(mycert); cert_encoding = mycert->cert->get_encoding(mycert->cert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT"); success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr); free(cert_encoding.ptr);
if (!success) if (!success)
+60 -52
View File
@@ -36,11 +36,11 @@
#include <library.h> #include <library.h>
#include <asn1/asn1.h> #include <asn1/asn1.h>
#include <credentials/certificates/pgp_certificate.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "x509.h" #include "x509.h"
#include "pgpcert.h"
#include "certs.h" #include "certs.h"
#include "smartcard.h" #include "smartcard.h"
#include "connections.h" #include "connections.h"
@@ -111,9 +111,11 @@ static const secret_t* get_secret(const connection_t *c,
identification_t *my_id, *his_id; identification_t *my_id, *his_id;
/* is there a certificate assigned to this connection? */ /* is there a certificate assigned to this connection? */
if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE) if (kind == PPK_PUBKEY && c->spd.this.cert)
{ {
public_key_t *pub_key = cert_get_public_key(c->spd.this.cert); certificate_t *certificate = c->spd.this.cert->cert;
public_key_t *pub_key = certificate->get_public_key(certificate);
for (s = secrets; s != NULL; s = s->next) for (s = secrets; s != NULL; s = s->next)
{ {
@@ -262,11 +264,11 @@ const chunk_t* get_preshared_secret(const connection_t *c)
/* check the existence of a private key matching a public key contained /* check the existence of a private key matching a public key contained
* in an X.509 or OpenPGP certificate * in an X.509 or OpenPGP certificate
*/ */
bool has_private_key(cert_t cert) bool has_private_key(cert_t *cert)
{ {
secret_t *s; secret_t *s;
bool has_key = FALSE; bool has_key = FALSE;
public_key_t *pub_key = cert_get_public_key(cert); public_key_t *pub_key = cert->cert->get_public_key(cert->cert);
for (s = secrets; s != NULL; s = s->next) for (s = secrets; s != NULL; s = s->next)
{ {
@@ -284,7 +286,7 @@ bool has_private_key(cert_t cert)
/* /*
* get the matching private key belonging to a given X.509 certificate * get the matching private key belonging to a given X.509 certificate
*/ */
private_key_t* get_x509_private_key(const x509cert_t *cert) private_key_t* get_x509_private_key(const cert_t *cert)
{ {
public_key_t *public_key = cert->cert->get_public_key(cert->cert); public_key_t *public_key = cert->cert->get_public_key(cert->cert);
private_key_t *private_key = NULL; private_key_t *private_key = NULL;
@@ -1272,80 +1274,86 @@ bool add_public_key(identification_t *id, enum dns_auth_level dns_auth_level,
return TRUE; return TRUE;
} }
/* extract id and public key from x.509 certificate and /**
* insert it into a pubkeyrec * Extract id and public key a certificate and insert it into a pubkeyrec
*/ */
void add_x509_public_key(x509cert_t *cert , time_t until, void add_public_key_from_cert(cert_t *cert , time_t until,
enum dns_auth_level dns_auth_level) enum dns_auth_level dns_auth_level)
{ {
certificate_t *certificate = cert->cert; certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate); identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate); identification_t *issuer = NULL;
identification_t *id; identification_t *id;
chunk_t serialNumber = x509->get_serial(x509); chunk_t serialNumber = chunk_empty;
pubkey_t *pk; pubkey_t *pk;
key_type_t pk_type; key_type_t pk_type;
enumerator_t *enumerator;
/* ID type: ID_DER_ASN1_DN (X.509 subject field) */ /* ID type: ID_DER_ASN1_DN (X.509 subject field) */
pk = malloc_thing(pubkey_t); pk = malloc_thing(pubkey_t);
zero(pk); zero(pk);
pk->public_key = certificate->get_public_key(certificate); pk->public_key = certificate->get_public_key(certificate);
pk_type = pk->public_key->get_type(pk->public_key);
pk->id = subject->clone(subject); pk->id = subject->clone(subject);
pk->dns_auth_level = dns_auth_level; pk->dns_auth_level = dns_auth_level;
pk->until_time = until; pk->until_time = until;
pk->issuer = issuer->clone(issuer); if (certificate->get_type(certificate) == CERT_X509)
pk->serial = chunk_clone(serialNumber); {
pk_type = pk->public_key->get_type(pk->public_key); x509_t *x509 = (x509_t*)certificate;
issuer = certificate->get_issuer(certificate);
serialNumber = x509->get_serial(x509);
pk->issuer = issuer->clone(issuer);
pk->serial = chunk_clone(serialNumber);
}
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial); delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys); install_public_key(pk, &pubkeys);
/* insert all subjectAltNames */ if (certificate->get_type(certificate) == CERT_X509)
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &id))
{ {
if (id->get_type(id) != ID_ANY) x509_t *x509 = (x509_t*)certificate;
enumerator_t *enumerator;
/* insert all subjectAltNames from X.509 certificates */
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &id))
{ {
pk = malloc_thing(pubkey_t); if (id->get_type(id) != ID_ANY)
zero(pk); {
pk->id = id->clone(id); pk = malloc_thing(pubkey_t);
pk->public_key = certificate->get_public_key(certificate); zero(pk);
pk->dns_auth_level = dns_auth_level; pk->id = id->clone(id);
pk->until_time = until; pk->public_key = certificate->get_public_key(certificate);
pk->issuer = issuer->clone(issuer); pk->dns_auth_level = dns_auth_level;
pk->serial = chunk_clone(serialNumber); pk->until_time = until;
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial); pk->issuer = issuer->clone(issuer);
install_public_key(pk, &pubkeys); pk->serial = chunk_clone(serialNumber);
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
}
} }
enumerator->destroy(enumerator);
} }
enumerator->destroy(enumerator); else
} {
pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
/* extract id and public key from OpenPGP certificate and /* add v3 or v4 PGP fingerprint */
* insert it into a pubkeyrec pk = malloc_thing(pubkey_t);
*/ zero(pk);
void add_pgp_public_key(pgpcert_t *cert , time_t until, pk->id = identification_create_from_encoding(ID_KEY_ID, fingerprint);
enum dns_auth_level dns_auth_level) pk->public_key = certificate->get_public_key(certificate);
{ pk->dns_auth_level = dns_auth_level;
pubkey_t *pk; pk->until_time = until;
key_type_t pk_type; delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
pk = malloc_thing(pubkey_t); }
zero(pk);
pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->id = cert->fingerprint->clone(cert->fingerprint);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk_type = pk->public_key->get_type(pk->public_key);
delete_public_keys(pk->id, pk_type, NULL, chunk_empty);
install_public_key(pk, &pubkeys);
} }
/* when a X.509 certificate gets revoked, all instances of /* when a X.509 certificate gets revoked, all instances of
* the corresponding public key must be removed * the corresponding public key must be removed
*/ */
void remove_x509_public_key(const x509cert_t *cert) void remove_x509_public_key(const cert_t *cert)
{ {
public_key_t *revoked_key = cert->cert->get_public_key(cert->cert); public_key_t *revoked_key = cert->cert->get_public_key(cert->cert);
pubkey_list_t *p, **pp; pubkey_list_t *p, **pp;
+5 -7
View File
@@ -45,7 +45,7 @@ struct connection;
extern const chunk_t *get_preshared_secret(const struct connection *c); extern const chunk_t *get_preshared_secret(const struct connection *c);
extern private_key_t *get_private_key(const struct connection *c); extern private_key_t *get_private_key(const struct connection *c);
extern private_key_t *get_x509_private_key(const x509cert_t *cert); extern private_key_t *get_x509_private_key(const cert_t *cert);
/* public key machinery */ /* public key machinery */
@@ -84,12 +84,10 @@ extern bool add_public_key(identification_t *id,
enum pubkey_alg alg, enum pubkey_alg alg,
chunk_t rfc3110_key, chunk_t rfc3110_key,
pubkey_list_t **head); pubkey_list_t **head);
extern bool has_private_key(cert_t cert); extern bool has_private_key(cert_t *cert);
extern void add_x509_public_key(x509cert_t *cert, time_t until extern void add_public_key_from_cert(cert_t *cert, time_t until,
, enum dns_auth_level dns_auth_level); enum dns_auth_level dns_auth_level);
extern void add_pgp_public_key(pgpcert_t *cert, time_t until extern void remove_x509_public_key(const cert_t *cert);
, enum dns_auth_level dns_auth_level);
extern void remove_x509_public_key(const x509cert_t *cert);
extern void list_public_keys(bool utc); extern void list_public_keys(bool utc);
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */ struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
+11 -11
View File
@@ -145,7 +145,7 @@ static chunk_t ocsp_default_uri;
static ocsp_location_t *ocsp_cache = NULL; static ocsp_location_t *ocsp_cache = NULL;
/* static temporary storage for ocsp requestor information */ /* static temporary storage for ocsp requestor information */
static x509cert_t *ocsp_requestor_cert = NULL; static cert_t *ocsp_requestor_cert = NULL;
static smartcard_t *ocsp_requestor_sc = NULL; static smartcard_t *ocsp_requestor_sc = NULL;
@@ -281,7 +281,7 @@ static const asn1Object_t singleResponseObjects[] = {
* Build an ocsp location from certificate information * Build an ocsp location from certificate information
* without unsharing its contents * without unsharing its contents
*/ */
static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) static bool build_ocsp_location(const cert_t *cert, ocsp_location_t *location)
{ {
certificate_t *certificate = cert->cert; certificate_t *certificate = cert->cert;
identification_t *issuer = certificate->get_issuer(certificate); identification_t *issuer = certificate->get_issuer(certificate);
@@ -329,7 +329,7 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
if (authKeyID.ptr == NULL) if (authKeyID.ptr == NULL)
{ {
x509cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA); cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
if (authcert) if (authcert)
{ {
@@ -416,7 +416,7 @@ static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
/** /**
* Verify the ocsp status of a certificate * Verify the ocsp status of a certificate
*/ */
cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until, cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until,
time_t *revocationDate, time_t *revocationDate,
crl_reason_t *revocationReason) crl_reason_t *revocationReason)
{ {
@@ -646,7 +646,7 @@ void list_ocsp_cache(bool utc, bool strict)
static bool get_ocsp_requestor_cert(ocsp_location_t *location) static bool get_ocsp_requestor_cert(ocsp_location_t *location)
{ {
x509cert_t *cert = NULL; cert_t *cert = NULL;
/* initialize temporary static storage */ /* initialize temporary static storage */
ocsp_requestor_cert = NULL; ocsp_requestor_cert = NULL;
@@ -962,7 +962,7 @@ chunk_t build_ocsp_request(ocsp_location_t *location)
static bool valid_ocsp_response(response_t *res) static bool valid_ocsp_response(response_t *res)
{ {
int pathlen, pathlen_constraint; int pathlen, pathlen_constraint;
x509cert_t *authcert; cert_t *authcert;
lock_authcert_list("valid_ocsp_response"); lock_authcert_list("valid_ocsp_response");
@@ -992,7 +992,7 @@ static bool valid_ocsp_response(response_t *res)
for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++) for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
{ {
x509cert_t *cert = authcert; cert_t *cert = authcert;
certificate_t *certificate = cert->cert; certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate; x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate); identification_t *subject = certificate->get_subject(certificate);
@@ -1133,10 +1133,10 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
break; break;
case BASIC_RESPONSE_CERTIFICATE: case BASIC_RESPONSE_CERTIFICATE:
{ {
x509cert_t *cert = malloc_thing(x509cert_t); cert_t *cert = malloc_thing(cert_t);
x509_t *x509; x509_t *x509;
*cert = empty_x509cert; *cert = cert_empty;
cert->cert = lib->creds->create(lib->creds, cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object, BUILD_BLOB_ASN1_DER, object,
@@ -1146,7 +1146,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
DBG(DBG_CONTROL | DBG_PARSING, DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("parsing of embedded ocsp certificate failed") DBG_log("parsing of embedded ocsp certificate failed")
) )
free_x509cert(cert); cert_free(cert);
break; break;
} }
x509 = (x509_t*)cert->cert; x509 = (x509_t*)cert->cert;
@@ -1161,7 +1161,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
DBG(DBG_CONTROL | DBG_PARSING, DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("embedded ocsp certificate rejected") DBG_log("embedded ocsp certificate rejected")
) )
free_x509cert(cert); cert_free(cert);
} }
} }
break; break;
+2 -2
View File
@@ -69,11 +69,11 @@ extern ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc
extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info
, ocsp_location_t **chain, bool request); , ocsp_location_t **chain, bool request);
extern void check_ocsp(void); extern void check_ocsp(void);
extern cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until extern cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until
, time_t *revocationTime, crl_reason_t *revocationReason); , time_t *revocationTime, crl_reason_t *revocationReason);
extern bool ocsp_set_request_cert(char* path); extern bool ocsp_set_request_cert(char* path);
extern void ocsp_set_default_uri(char* uri); extern void ocsp_set_default_uri(char* uri);
extern void ocsp_cache_add_cert(const x509cert_t* cert); extern void ocsp_cache_add_cert(const cert_t* cert);
extern chunk_t build_ocsp_request(ocsp_location_t* location); extern chunk_t build_ocsp_request(ocsp_location_t* location);
extern void parse_ocsp(ocsp_location_t* location, chunk_t blob); extern void parse_ocsp(ocsp_location_t* location, chunk_t blob);
extern void list_ocsp_locations(ocsp_location_t *location, bool requests extern void list_ocsp_locations(ocsp_location_t *location, bool requests
-472
View File
@@ -32,476 +32,4 @@
#include "whack.h" #include "whack.h"
#include "keys.h" #include "keys.h"
typedef enum pgp_packet_tag_t pgp_packet_tag_t;
/**
* OpenPGP packet tags as defined in section 4.3 of RFC 4880
*/
enum pgp_packet_tag_t {
PGP_PKT_RESERVED = 0,
PGP_PKT_PUBKEY_ENC_SESSION_KEY = 1,
PGP_PKT_SIGNATURE = 2,
PGP_PKT_SYMKEY_ENC_SESSION_KEY = 3,
PGP_PKT_ONE_PASS_SIGNATURE_PKT = 4,
PGP_PKT_SECRET_KEY = 5,
PGP_PKT_PUBLIC_KEY = 6,
PGP_PKT_SECRET_SUBKEY = 7,
PGP_PKT_COMPRESSED_DATA = 8,
PGP_PKT_SYMKEY_ENC_DATA = 9,
PGP_PKT_MARKER = 10,
PGP_PKT_LITERAL_DATA = 11,
PGP_PKT_TRUST = 12,
PGP_PKT_USER_ID = 13,
PGP_PKT_PUBLIC_SUBKEY = 14,
PGP_PKT_USER_ATTRIBUTE = 17,
PGP_PKT_SYM_ENC_INT_PROT_DATA = 18,
PGP_PKT_MOD_DETECT_CODE = 19
};
ENUM_BEGIN(pgp_packet_tag_names, PGP_PKT_RESERVED, PGP_PKT_PUBLIC_SUBKEY,
"Reserved",
"Public-Key Encrypted Session Key Packet",
"Signature Packet",
"Symmetric-Key Encrypted Session Key Packet",
"One-Pass Signature Packet",
"Secret Key Packet",
"Public Key Packet",
"Secret Subkey Packet",
"Compressed Data Packet",
"Symmetrically Encrypted Data Packet",
"Marker Packet",
"Literal Data Packet",
"Trust Packet",
"User ID Packet",
"Public Subkey Packet"
);
ENUM_NEXT(pgp_packet_tag_names, PGP_PKT_USER_ATTRIBUTE, PGP_PKT_MOD_DETECT_CODE, PGP_PKT_PUBLIC_SUBKEY,
"User Attribute Packet",
"Sym. Encrypted and Integrity Protected Data Packet",
"Modification Detection Code Packet"
);
ENUM_END(pgp_packet_tag_names, PGP_PKT_MOD_DETECT_CODE);
/**
* Chained list of OpenPGP end certificates
*/
static pgpcert_t *pgpcerts = NULL;
/**
* Size of PGP Key ID
*/
#define PGP_KEYID_SIZE 8
const pgpcert_t pgpcert_empty = {
NULL , /* next */
0 , /* version */
0 , /* count */
{ NULL, 0 }, /* certificate */
0 , /* created */
0 , /* until */
NULL , /* public key */
NULL /* fingerprint */
};
#define PGP_INVALID_LENGTH 0xffffffff
/**
* Returns the length of an OpenPGP (RFC 4880) packet
* The blob pointer is advanced past the length field.
*/
static size_t pgp_length(chunk_t *blob, size_t len)
{
size_t size = 0;
if (len > blob->len)
{
return PGP_INVALID_LENGTH;
}
blob->len -= len;
while (len-- > 0)
{
size = 256*size + *blob->ptr++;
}
return size;
}
/**
* Extracts the length of a PGP packet
*/
static size_t pgp_old_packet_length(chunk_t *blob)
{
/* bits 0 and 1 define the packet length type */
int len_type = 0x03 & *blob->ptr++;
blob->len--;
/* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
return pgp_length(blob, (len_type == 0)? 1: len_type << 1);
}
/**
* Extracts PGP packet version (V3 or V4)
*/
static u_char pgp_version(chunk_t *blob)
{
u_char version = *blob->ptr++;
blob->len--;
DBG(DBG_PARSING,
DBG_log("L3 - version:");
DBG_log(" V%d", version)
)
return version;
}
/**
* Parse OpenPGP signature packet defined in section 5.2.2 of RFC 4880
*/
static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
{
time_t created;
chunk_t keyid;
u_char sig_type;
u_char version = pgp_version(packet);
/* we parse only V3 signature packets */
if (version != 3)
{
return TRUE;
}
/* size byte must have the value 5 */
if (pgp_length(packet, 1) != 5)
{
plog(" size must be 5");
return FALSE;
}
/* signature type - 1 byte */
sig_type = (u_char)pgp_length(packet, 1);
DBG(DBG_PARSING,
DBG_log("L3 - signature type: 0x%2x", sig_type)
)
/* creation date - 4 bytes */
created = (time_t)pgp_length(packet, 4);
DBG(DBG_PARSING,
DBG_log("L3 - created:");
DBG_log(" %T", &cert->created, TRUE)
)
/* key ID of signer - 8 bytes */
keyid.ptr = packet->ptr;
keyid.len = PGP_KEYID_SIZE;
DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid);
return TRUE;
}
/**
* Parses the version and validity of an OpenPGP public key packet
*/
static bool parse_pgp_pubkey_version_validity(chunk_t *packet, pgpcert_t *cert)
{
cert->version = pgp_version(packet);
if (cert->version < 3 || cert->version > 4)
{
plog("OpenPGP packet version V%d not supported", cert->version);
return FALSE;
}
/* creation date - 4 bytes */
cert->created = (time_t)pgp_length(packet, 4);
DBG(DBG_PARSING,
DBG_log("L3 - created:");
DBG_log(" %T", &cert->created, TRUE)
)
if (cert->version == 3)
{
/* validity in days - 2 bytes */
cert->until = (time_t)pgp_length(packet, 2);
/* validity of 0 days means that the key never expires */
if (cert->until > 0)
{
cert->until = cert->created + 24*3600*cert->until;
}
DBG(DBG_PARSING,
DBG_log("L3 - until:");
DBG_log(" %T", &cert->until, TRUE);
)
}
return TRUE;
}
/**
* Parse OpenPGP public key packet defined in section 5.5.2 of RFC 4880
*/
static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
{
chunk_t pubkey_packet = *packet;
if (!parse_pgp_pubkey_version_validity(packet, cert))
{
return FALSE;
}
cert->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
BUILD_BLOB_PGP, *packet, BUILD_END);
if (cert->public_key == NULL)
{
return FALSE;
}
/* compute V4 or V3 fingerprint according to section 12.2 of RFC 4880 */
if (cert->version == 4)
{
chunk_t pubkey_packet_header = chunk_from_chars(
0x99, pubkey_packet.len / 256, pubkey_packet.len % 256
);
chunk_t hash;
hasher_t *hasher;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (hasher == NULL)
{
plog("no SHA-1 hasher available");
return FALSE;
}
hasher->allocate_hash(hasher, pubkey_packet_header, NULL);
hasher->allocate_hash(hasher, pubkey_packet, &hash);
hasher->destroy(hasher);
cert->fingerprint = identification_create_from_encoding(ID_KEY_ID, hash);
free(hash.ptr);
}
else
{
chunk_t fp;
/* V3 fingerprint is computed by public_key_t class */
if (!cert->public_key->get_fingerprint(cert->public_key, KEY_ID_PGPV3,
&fp))
{
return FALSE;
}
cert->fingerprint = identification_create_from_encoding(ID_KEY_ID, fp);
}
return TRUE;
}
bool parse_pgp(chunk_t blob, pgpcert_t *cert)
{
DBG(DBG_PARSING,
DBG_log("L0 - PGP file:")
)
DBG_cond_dump_chunk(DBG_RAW, "", blob);
if (cert == NULL)
{
/* should not occur, nothing to parse */
return FALSE;
}
/* parse a PGP certificate file */
cert->certificate = blob;
while (blob.len > 0)
{
chunk_t packet = chunk_empty;
u_char packet_tag = *blob.ptr;
DBG(DBG_PARSING,
DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag)
)
/* bit 7 must be set */
if (!(packet_tag & 0x80))
{
plog(" incorrect Packet Tag");
return FALSE;
}
/* bit 6 set defines new packet format */
if (packet_tag & 0x40)
{
plog(" new PGP packet format not supported");
return FALSE;
}
else
{
int packet_type = (packet_tag & 0x3C) >> 2;
packet.len = pgp_old_packet_length(&blob);
packet.ptr = blob.ptr;
blob.ptr += packet.len;
blob.len -= packet.len;
DBG(DBG_PARSING,
DBG_log(" %N (%d), old format, %u bytes",
pgp_packet_tag_names, packet_type,
packet_type, packet.len);
DBG_log("L2 - body:")
)
DBG_cond_dump_chunk(DBG_RAW, "", packet);
/* parse a PGP certificate */
switch (packet_type)
{
case PGP_PKT_PUBLIC_KEY:
if (!parse_pgp_pubkey_packet(&packet, cert))
{
return FALSE;
}
break;
case PGP_PKT_SIGNATURE:
if (!parse_pgp_signature_packet(&packet, cert))
{
return FALSE;
}
break;
case PGP_PKT_USER_ID:
DBG(DBG_PARSING,
DBG_log("L3 - user ID:");
DBG_log(" '%.*s'", (int)packet.len, packet.ptr)
)
break;
default:
break;
}
}
}
return TRUE;
}
/**
* Compare two OpenPGP certificates
*/
static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
{
return a->certificate.len == b->certificate.len &&
memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
}
/**
* For each link pointing to the certificate increase the count by one
*/
void share_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
{
cert->count++;
}
}
/**
* Select the OpenPGP keyid as ID
*/
identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id)
{
id->destroy(id);
return cert->fingerprint->clone(cert->fingerprint);
}
/**
* Add an OpenPGP user/host certificate to the chained list
*/
pgpcert_t* add_pgpcert(pgpcert_t *cert)
{
pgpcert_t *c = pgpcerts;
while (c != NULL)
{
if (same_pgpcert(c, cert)) /* already in chain, free cert */
{
free_pgpcert(cert);
return c;
}
c = c->next;
}
/* insert new cert at the root of the chain */
cert->next = pgpcerts;
pgpcerts = cert;
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" pgp cert inserted")
)
return cert;
}
/**
* Release of a certificate decreases the count by one.
* The certificate is freed when the counter reaches zero
*/
void release_pgpcert(pgpcert_t *cert)
{
if (cert != NULL && --cert->count == 0)
{
pgpcert_t **pp = &pgpcerts;
while (*pp != cert)
{
pp = &(*pp)->next;
}
*pp = cert->next;
free_pgpcert(cert);
}
}
/**
* Free a PGP certificate
*/
void free_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
{
DESTROY_IF(cert->public_key);
DESTROY_IF(cert->fingerprint);
free(cert->certificate.ptr);
free(cert);
}
}
/**
* List all PGP end certificates in a chained list
*/
void list_pgp_end_certs(bool utc)
{
pgpcert_t *cert = pgpcerts;
time_t now;
/* determine the current time */
time(&now);
if (cert != NULL)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
}
while (cert != NULL)
{
public_key_t *key = cert->public_key;
chunk_t keyid;
cert_t c;
c.type = CERT_PGP;
c.u.pgp = cert;
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " digest: %Y", cert->fingerprint);
whack_log(RC_COMMENT, " created: %T", &cert->created, utc);
whack_log(RC_COMMENT, " until: %T %s", &cert->until, utc,
check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
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(c)? ", has private key" : "");
if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
{
whack_log(RC_COMMENT, " keyid: %#B", &keyid);
}
cert = cert->next;
}
}
-34
View File
@@ -17,40 +17,6 @@
#ifndef _PGPCERT_H #ifndef _PGPCERT_H
#define _PGPCERT_H #define _PGPCERT_H
#include <utils/identification.h>
#include <crypto/hashers/hasher.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
/*
* Length of PGP V3 fingerprint
*/
#define PGP_FINGERPRINT_SIZE HASH_SIZE_MD5
typedef char fingerprint_t[PGP_FINGERPRINT_SIZE];
/* access structure for an OpenPGP certificate */
typedef struct pgpcert pgpcert_t;
struct pgpcert {
pgpcert_t *next;
int version;
int count;
chunk_t certificate;
time_t created;
time_t until;
public_key_t *public_key;
identification_t *fingerprint;
};
extern const pgpcert_t pgpcert_empty;
extern bool parse_pgp(chunk_t blob, pgpcert_t *cert);
extern void share_pgpcert(pgpcert_t *cert);
extern identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id);
extern pgpcert_t* add_pgpcert(pgpcert_t *cert);
extern void list_pgp_end_certs(bool utc); extern void list_pgp_end_certs(bool utc);
extern void release_pgpcert(pgpcert_t *cert);
extern void free_pgpcert(pgpcert_t *cert);
#endif /* _PGPCERT_H */ #endif /* _PGPCERT_H */
+1 -1
View File
@@ -476,7 +476,7 @@ void whack_handle(int whackctlfd)
if (msg.whack_list & LIST_CERTS) if (msg.whack_list & LIST_CERTS)
{ {
list_certs(msg.whack_utc); cert_list(msg.whack_utc);
} }
if (msg.whack_list & LIST_CACERTS) if (msg.whack_list & LIST_CACERTS)
+68 -71
View File
@@ -59,21 +59,21 @@ static smartcard_t *smartcards = NULL;
static int sc_number = 0; static int sc_number = 0;
const smartcard_t empty_sc = { const smartcard_t empty_sc = {
NULL , /* next */ NULL , /* next */
0 , /* last_load */ 0 , /* last_load */
{ CERT_NONE, {NULL} }, /* last_cert */ NULL , /* last_cert */
0 , /* count */ 0 , /* count */
0 , /* number */ 0 , /* number */
999999 , /* slot */ 999999 , /* slot */
NULL , /* id */ NULL , /* id */
NULL , /* label */ NULL , /* label */
{ NULL, 0 } , /* pin */ { NULL, 0 } , /* pin */
FALSE , /* pinpad */ FALSE , /* pinpad */
FALSE , /* valid */ FALSE , /* valid */
FALSE , /* session_opened */ FALSE , /* session_opened */
FALSE , /* logged_in */ FALSE , /* logged_in */
TRUE , /* any_slot */ TRUE , /* any_slot */
0L , /* session */ 0L , /* session */
}; };
#ifdef SMARTCARD /* compile with smartcard support */ #ifdef SMARTCARD /* compile with smartcard support */
@@ -437,14 +437,13 @@ failed: scx_unload_pkcs11_module(mod);
/* /*
* retrieve a certificate object * retrieve a certificate object
*/ */
static bool scx_find_cert_object(CK_SESSION_HANDLE session, static cert_t* scx_find_cert_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, CK_OBJECT_HANDLE object, smartcard_t *sc)
smartcard_t *sc, cert_t *cert)
{ {
size_t hex_len, label_len; size_t hex_len, label_len;
u_char *hex_id = NULL; u_char *hex_id = NULL;
cert_t *cert;
chunk_t blob; chunk_t blob;
x509cert_t *x509cert;
CK_ATTRIBUTE attr[] = { CK_ATTRIBUTE attr[] = {
{ CKA_ID, NULL_PTR, 0L }, { CKA_ID, NULL_PTR, 0L },
@@ -452,16 +451,13 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
{ CKA_VALUE, NULL_PTR, 0L } { CKA_VALUE, NULL_PTR, 0L }
}; };
/* initialize the return argument */
*cert = cert_empty;
/* get the length of the attributes first */ /* get the length of the attributes first */
CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3); CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
if (rv != CKR_OK) if (rv != CKR_OK)
{ {
plog("couldn't read the attribute sizes: %s" plog("couldn't read the attribute sizes: %s"
, enum_show(&pkcs11_return_names, rv)); , enum_show(&pkcs11_return_names, rv));
return FALSE; return NULL;
} }
free(sc->label); free(sc->label);
@@ -486,7 +482,7 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
free(hex_id); free(hex_id);
free(sc->label); free(sc->label);
free(blob.ptr); free(blob.ptr);
return FALSE; return NULL;
} }
free(sc->id); free(sc->id);
@@ -500,22 +496,23 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
sc->label[label_len] = '\0'; sc->label[label_len] = '\0';
/* parse the retrieved cert */ /* parse the retrieved cert */
x509cert = malloc_thing(x509cert_t);
*x509cert = empty_x509cert; /* initialize the return argument */
x509cert->smartcard = TRUE; cert = malloc_thing(cert_t);
x509cert->cert = lib->creds->create(lib->creds, *cert = cert_empty;
CRED_CERTIFICATE, CERT_X509, cert->smartcard = TRUE;
BUILD_BLOB_ASN1_DER, blob, cert->cert = lib->creds->create(lib->creds,
BUILD_END); CRED_CERTIFICATE, CERT_X509,
if (x509cert->cert) BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (cert->cert)
{ {
cert->type = CERT_X509_SIGNATURE; return cert;
cert->u.x509 = x509cert;
return TRUE;
} }
plog("failed to load cert from smartcard, error in X.509 certificate"); plog("failed to load cert from smartcard, error in X.509 certificate");
free_x509cert(x509cert); cert_free(cert);
return FALSE; return NULL;
} }
@@ -542,7 +539,7 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
CK_ULONG obj_count = 0; CK_ULONG obj_count = 0;
time_t valid_until; time_t valid_until;
smartcard_t *sc; smartcard_t *sc;
x509cert_t *cert; certificate_t *certificate;
x509_t *x509; x509_t *x509;
rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count); rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count);
@@ -562,8 +559,8 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
*sc = empty_sc; *sc = empty_sc;
sc->any_slot = FALSE; sc->any_slot = FALSE;
sc->slot = slot; sc->slot = slot;
sc->last_cert = scx_find_cert_object(session, object, sc);
if (!scx_find_cert_object(session, object, sc, &sc->last_cert)) if (sc->last_cert == NULL)
{ {
scx_free(sc); scx_free(sc);
continue; continue;
@@ -574,10 +571,9 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
) )
/* check validity of certificate */ /* check validity of certificate */
cert = sc->last_cert.u.x509; certificate = sc->last_cert->cert;
if (!cert->cert->get_validity(cert->cert, NULL, NULL, &valid_until)) if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{ {
free_x509cert(cert);
scx_free(sc); scx_free(sc);
continue; continue;
} }
@@ -586,20 +582,20 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
) )
sc = scx_add(sc); sc = scx_add(sc);
x509 = (x509_t*)cert->cert; x509 = (x509_t*)certificate;
/* put end entity and ca certificates into different chains */ /* put end entity and ca certificates into different chains */
if (x509->get_flags(x509) & X509_CA) if (x509->get_flags(x509) & X509_CA)
{ {
sc->last_cert.u.x509 = add_authcert(cert, X509_CA); sc->last_cert = add_authcert(sc->last_cert, X509_CA);
} }
else else
{ {
add_x509_public_key(cert, valid_until, DAL_LOCAL); add_public_key_from_cert(sc->last_cert, valid_until, DAL_LOCAL);
sc->last_cert.u.x509 = add_x509cert(cert); sc->last_cert = cert_add(sc->last_cert);
} }
share_cert(sc->last_cert); cert_share(sc->last_cert);
time(&sc->last_load); time(&sc->last_load);
} }
@@ -1070,67 +1066,66 @@ void scx_release_context(smartcard_t *sc)
/* /*
* Load host certificate from smartcard * Load host certificate from smartcard
*/ */
bool scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert, cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached)
bool *cached)
{ {
#ifdef SMARTCARD /* compile with smartcard support */ #ifdef SMARTCARD /* compile with smartcard support */
CK_OBJECT_HANDLE object;
const char *number_slot_id = filename + strlen(SCX_TOKEN); const char *number_slot_id = filename + strlen(SCX_TOKEN);
CK_OBJECT_HANDLE object;
smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id)); smartcard_t *sc;
cert_t *cert = NULL;
/* return the smartcard object */ /* return the smartcard object */
*scp = sc; *scp = sc = scx_add(scx_parse_number_slot_id(number_slot_id));
/* is there a cached smartcard certificate? */ /* is there a cached smartcard certificate? */
*cached = sc->last_cert.type != CERT_NONE *cached = sc->last_cert &&
&& (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL; (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
if (*cached) if (*cached)
{ {
*cert = sc->last_cert;
plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')" plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
, sc->number , sc->number
, scx_print_slot(sc, "") , scx_print_slot(sc, "")
, sc->id , sc->id
, sc->label); , sc->label);
return TRUE; return sc->last_cert;
} }
if (!scx_establish_context(sc)) if (!scx_establish_context(sc))
{ {
scx_release_context(sc); scx_release_context(sc);
return FALSE; return NULL;
} }
/* find the certificate object */ /* find the certificate object */
if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id)) if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
{ {
scx_release_context(sc); scx_release_context(sc);
return FALSE; return NULL;
} }
/* retrieve the certificate object */ /* retrieve the certificate object */
if (!scx_find_cert_object(sc->session, object, sc, cert)) cert = scx_find_cert_object(sc->session, object, sc);
if (cert == NULL)
{ {
scx_release_context(sc); scx_release_context(sc);
return FALSE; return NULL;
} }
if (!pkcs11_keep_state) if (!pkcs11_keep_state)
{
scx_release_context(sc); scx_release_context(sc);
}
plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')" plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
, sc->number , sc->number
, scx_print_slot(sc, "") , scx_print_slot(sc, "")
, sc->id , sc->id
, sc->label); , sc->label);
return TRUE; return cert;
#else #else
plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!"); plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
return FALSE; return NULL;
#endif #endif
} }
@@ -1793,6 +1788,7 @@ void scx_free(smartcard_t *sc)
if (sc != NULL) if (sc != NULL)
{ {
scx_release_context(sc); scx_release_context(sc);
cert_release(sc->last_cert);
free(sc->id); free(sc->id);
free(sc->label); free(sc->label);
scx_free_pin(&sc->pin); scx_free_pin(&sc->pin);
@@ -1811,7 +1807,6 @@ void scx_release(smartcard_t *sc)
while (*pp != sc) while (*pp != sc)
pp = &(*pp)->next; pp = &(*pp)->next;
*pp = sc->next; *pp = sc->next;
release_cert(sc->last_cert);
scx_free(sc); scx_free(sc);
} }
} }
@@ -1875,14 +1870,16 @@ smartcard_t* scx_add(smartcard_t *smartcard)
/* /*
* get the smartcard that belongs to an X.509 certificate * get the smartcard that belongs to an X.509 certificate
*/ */
smartcard_t* scx_get(x509cert_t *cert) smartcard_t* scx_get(cert_t *cert)
{ {
smartcard_t *sc = smartcards; smartcard_t *sc = smartcards;
while (sc != NULL) while (sc != NULL)
{ {
if (sc->last_cert.u.x509 == cert) if (sc->last_cert == cert)
{
return sc; return sc;
}
sc = sc->next; sc = sc->next;
} }
return NULL; return NULL;
@@ -1929,9 +1926,9 @@ void scx_list(bool utc)
whack_log(RC_COMMENT, " id: %s", sc->id); whack_log(RC_COMMENT, " id: %s", sc->id);
if (sc->label != NULL) if (sc->label != NULL)
whack_log(RC_COMMENT, " label: '%s'", sc->label); whack_log(RC_COMMENT, " label: '%s'", sc->label);
if (sc->last_cert.type == CERT_X509_SIGNATURE) if (sc->last_cert)
{ {
certificate_t *certificate = sc->last_cert.u.x509->cert; certificate_t *certificate = sc->last_cert->cert;
whack_log(RC_COMMENT, " subject: '%Y'", whack_log(RC_COMMENT, " subject: '%Y'",
certificate->get_subject(certificate)); certificate->get_subject(certificate));
+3 -4
View File
@@ -42,7 +42,7 @@ typedef struct smartcard smartcard_t;
struct smartcard { struct smartcard {
smartcard_t *next; smartcard_t *next;
time_t last_load; time_t last_load;
cert_t last_cert; cert_t *last_cert;
int count; int count;
int number; int number;
unsigned long slot; unsigned long slot;
@@ -75,8 +75,7 @@ extern void scx_finalize(void);
extern bool scx_establish_context(smartcard_t *sc); extern bool scx_establish_context(smartcard_t *sc);
extern bool scx_login(smartcard_t *sc); extern bool scx_login(smartcard_t *sc);
extern bool scx_on_smartcard(const char *filename); extern bool scx_on_smartcard(const char *filename);
extern bool scx_load_cert(const char *filename, smartcard_t **scp extern cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached);
, cert_t *cert, bool *cached);
extern bool scx_verify_pin(smartcard_t *sc); extern bool scx_verify_pin(smartcard_t *sc);
extern void scx_share(smartcard_t *sc); extern void scx_share(smartcard_t *sc);
extern bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen extern bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
@@ -90,7 +89,7 @@ extern bool scx_op_via_whack(const char* msg, int inbase, int outbase
extern bool scx_get_pin(smartcard_t *sc, int whackfd); extern bool scx_get_pin(smartcard_t *sc, int whackfd);
extern size_t scx_get_keylength(smartcard_t *sc); extern size_t scx_get_keylength(smartcard_t *sc);
extern smartcard_t* scx_add(smartcard_t *sc); extern smartcard_t* scx_add(smartcard_t *sc);
extern smartcard_t* scx_get(x509cert_t *cert); extern smartcard_t* scx_get(cert_t *cert);
extern void scx_release(smartcard_t *sc); extern void scx_release(smartcard_t *sc);
extern void scx_release_context(smartcard_t *sc); extern void scx_release_context(smartcard_t *sc);
extern void scx_free_pin(chunk_t *pin); extern void scx_free_pin(chunk_t *pin);
+17 -157
View File
@@ -42,100 +42,6 @@
#include "fetch.h" #include "fetch.h"
#include "ocsp.h" #include "ocsp.h"
/**
* Chained lists of X.509 end certificates
*/
static x509cert_t *x509certs = NULL;
const x509cert_t empty_x509cert = {
NULL , /* cert */
NULL , /* *next */
0 , /* count */
FALSE /* smartcard */
};
/* coding of X.501 distinguished name */
/**
* For each link pointing to the certificate increase the count by one
*/
void share_x509cert(x509cert_t *cert)
{
if (cert != NULL)
{
cert->count++;
}
}
/**
* Add a X.509 user/host certificate to the chained list
*/
x509cert_t* add_x509cert(x509cert_t *cert)
{
certificate_t *certificate = cert->cert;
x509cert_t *c = x509certs;
while (c != NULL)
{
if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
{
free_x509cert(cert);
return c;
}
c = c->next;
}
/* insert new cert at the root of the chain */
lock_certs_and_keys("add_x509cert");
cert->next = x509certs;
x509certs = cert;
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" x509 cert inserted")
)
unlock_certs_and_keys("add_x509cert");
return cert;
}
/**
* Choose either subject DN or a subjectAltName as connection end ID
*/
identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject, *subjectAltName;
bool copy_subject_dn = TRUE; /* ID is subject DN */
if (id->get_type(id) != ID_ANY) /* check for a matching subjectAltName */
{
enumerator_t *enumerator;
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &subjectAltName))
{
if (id->equals(id, subjectAltName))
{
copy_subject_dn = FALSE; /* take subjectAltName instead */
break;
}
}
enumerator->destroy(enumerator);
}
if (copy_subject_dn)
{
id->destroy(id);
subject = certificate->get_subject(certificate);
plog(" no subjectAltName matches ID '%Y', replaced by subject DN", id);
return subject->clone(subject);
}
else
{
return id;
}
}
/** /**
* Check for equality between two key identifiers * Check for equality between two key identifiers
*/ */
@@ -151,9 +57,9 @@ bool same_keyid(chunk_t a, chunk_t b)
/** /**
* Get a X.509 certificate with a given issuer found at a certain position * Get a X.509 certificate with a given issuer found at a certain position
*/ */
x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t *chain) cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t *chain)
{ {
x509cert_t *cert = chain ? chain->next : x509certs; cert_t *cert = chain->next;
while (cert) while (cert)
{ {
@@ -171,48 +77,12 @@ x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t *ch
return NULL; return NULL;
} }
/**
* Free a X.509 certificate
*/
void free_x509cert(x509cert_t *cert)
{
if (cert)
{
certificate_t *certificate = cert->cert;
if (certificate)
{
certificate->destroy(certificate);
}
free(cert);
cert = NULL;
}
}
/**
* Release of a certificate decreases the count by one
* the certificate is freed when the counter reaches zero
*/
void release_x509cert(x509cert_t *cert)
{
if (cert && --cert->count == 0)
{
x509cert_t **pp = &x509certs;
while (*pp != cert)
{
pp = &(*pp)->next;
}
*pp = cert->next;
free_x509cert(cert);
}
}
/** /**
* Stores a chained list of end certs and CA certs * Stores a chained list of end certs and CA certs
*/ */
void store_x509certs(linked_list_t *certs, bool strict) void store_x509certs(linked_list_t *certs, bool strict)
{ {
x509cert_t *x509cert, *cacerts = NULL; cert_t *x509cert, *cacerts = NULL;
certificate_t *cert; certificate_t *cert;
enumerator_t *enumerator; enumerator_t *enumerator;
@@ -235,8 +105,8 @@ void store_x509certs(linked_list_t *certs, bool strict)
else else
{ {
/* insertion into temporary chain of candidate CA certs */ /* insertion into temporary chain of candidate CA certs */
x509cert = malloc_thing(x509cert_t); x509cert = malloc_thing(cert_t);
*x509cert = empty_x509cert; *x509cert = cert_empty;
x509cert->cert = cert->get_ref(cert); x509cert->cert = cert->get_ref(cert);
x509cert->next = cacerts; x509cert->next = cacerts;
cacerts = x509cert; cacerts = x509cert;
@@ -249,7 +119,7 @@ void store_x509certs(linked_list_t *certs, bool strict)
while (cacerts) while (cacerts)
{ {
x509cert_t *cert = cacerts; cert_t *cert = cacerts;
cacerts = cacerts->next; cacerts = cacerts->next;
@@ -260,7 +130,7 @@ void store_x509certs(linked_list_t *certs, bool strict)
else else
{ {
plog("intermediate cacert rejected"); plog("intermediate cacert rejected");
free_x509cert(cert); cert_free(cert);
} }
} }
@@ -274,8 +144,8 @@ void store_x509certs(linked_list_t *certs, bool strict)
if (!(x509->get_flags(x509) & X509_CA)) if (!(x509->get_flags(x509) & X509_CA))
{ {
x509cert = malloc_thing(x509cert_t); x509cert = malloc_thing(cert_t);
*x509cert = empty_x509cert; *x509cert = cert_empty;
x509cert->cert = cert->get_ref(cert); x509cert->cert = cert->get_ref(cert);
if (verify_x509cert(x509cert, strict, &valid_until)) if (verify_x509cert(x509cert, strict, &valid_until))
@@ -283,12 +153,12 @@ void store_x509certs(linked_list_t *certs, bool strict)
DBG(DBG_CONTROL | DBG_PARSING, DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("public key validated") DBG_log("public key validated")
) )
add_x509_public_key(x509cert, valid_until, DAL_SIGNED); add_public_key_from_cert(x509cert, valid_until, DAL_SIGNED);
} }
else else
{ {
plog("X.509 certificate rejected"); plog("X.509 certificate rejected");
free_x509cert(x509cert); cert_free(x509cert);
} }
} }
} }
@@ -342,7 +212,7 @@ chunk_t x509_build_signature(chunk_t tbs, int algorithm, private_key_t *key,
/** /**
* Verifies a X.509 certificate * Verifies a X.509 certificate
*/ */
bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until) bool verify_x509cert(cert_t *cert, bool strict, time_t *until)
{ {
int pathlen, pathlen_constraint; int pathlen, pathlen_constraint;
@@ -355,7 +225,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
identification_t *issuer = certificate->get_issuer(certificate); identification_t *issuer = certificate->get_issuer(certificate);
x509_t *x509 = (x509_t*)certificate; x509_t *x509 = (x509_t*)certificate;
chunk_t authKeyID = x509->get_authKeyIdentifier(x509); chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
x509cert_t *issuer_cert; cert_t *issuer_cert;
time_t notBefore, notAfter; time_t notBefore, notAfter;
bool valid; bool valid;
@@ -497,7 +367,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
/** /**
* List all X.509 certs in a chained list * List all X.509 certs in a chained list
*/ */
void list_x509cert_chain(const char *caption, x509cert_t* cert, void list_x509cert_chain(const char *caption, cert_t* cert,
x509_flag_t flags, bool utc) x509_flag_t flags, bool utc)
{ {
bool first = TRUE; bool first = TRUE;
@@ -511,7 +381,8 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
certificate_t *certificate = cert->cert; certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate; x509_t *x509 = (x509_t*)certificate;
if (flags == X509_NONE || (flags & x509->get_flags(x509))) if (certificate->get_type(certificate) == CERT_X509 &&
(flags == X509_NONE || (flags & x509->get_flags(x509))))
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
char buf[BUF_LEN]; char buf[BUF_LEN];
@@ -522,10 +393,6 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
time_t notBefore, notAfter; time_t notBefore, notAfter;
public_key_t *key; public_key_t *key;
chunk_t serial, keyid, subjkey, authkey; chunk_t serial, keyid, subjkey, authkey;
cert_t c;
c.type = CERT_X509_SIGNATURE;
c.u.x509 = cert;
if (first) if (first)
{ {
@@ -581,7 +448,7 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
key_type_names, key->get_type(key), key_type_names, key->get_type(key),
key->get_keysize(key) * BITS_PER_BYTE, key->get_keysize(key) * BITS_PER_BYTE,
cert->smartcard ? ", on smartcard" : cert->smartcard ? ", on smartcard" :
(has_private_key(c)? ", has private key" : "")); (has_private_key(cert)? ", has private key" : ""));
if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
{ {
@@ -613,10 +480,3 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
} }
} }
/**
* List all X.509 end certificates in a chained list
*/
void list_x509_end_certs(bool utc)
{
list_x509cert_chain("End Entity", x509certs, X509_NONE, utc);
}
+4 -26
View File
@@ -20,43 +20,21 @@
#include <utils/identification.h> #include <utils/identification.h>
#include <utils/linked_list.h> #include <utils/linked_list.h>
#include <credentials/keys/public_key.h>
#include <credentials/keys/private_key.h> #include <credentials/keys/private_key.h>
#include <credentials/certificates/x509.h> #include <credentials/certificates/x509.h>
#include "constants.h" #include "constants.h"
#include "certs.h"
/* access structure for an X.509v3 certificate */
typedef struct x509cert x509cert_t;
struct x509cert {
certificate_t *cert;
x509cert_t *next;
int count;
bool smartcard;
};
/* used for initialization */
extern const x509cert_t empty_x509cert;
extern bool same_keyid(chunk_t a, chunk_t b); extern bool same_keyid(chunk_t a, chunk_t b);
extern identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0,
chunk_t *authKeyID,
chunk_t *authKeySerialNumber);
extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm, extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
certificate_t *issuer_cert); certificate_t *issuer_cert);
extern chunk_t x509_build_signature(chunk_t tbs, int algorithm, extern chunk_t x509_build_signature(chunk_t tbs, int algorithm,
private_key_t *key, bool bit_string); private_key_t *key, bool bit_string);
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until); extern bool verify_x509cert(cert_t *cert, bool strict, time_t *until);
extern x509cert_t* add_x509cert(x509cert_t *cert); extern cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t* chain);
extern x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t* chain);
extern void share_x509cert(x509cert_t *cert);
extern void release_x509cert(x509cert_t *cert);
extern void free_x509cert(x509cert_t *cert);
extern void store_x509certs(linked_list_t *certs, bool strict); extern void store_x509certs(linked_list_t *certs, bool strict);
extern void list_x509cert_chain(const char *caption, x509cert_t* cert, extern void list_x509cert_chain(const char *caption, cert_t* cert,
x509_flag_t flags, bool utc); x509_flag_t flags, bool utc);
extern void list_x509_end_certs(bool utc); extern void list_x509_end_certs(bool utc);
+1
View File
@@ -18,6 +18,7 @@
#include <freeswan.h> #include <freeswan.h>
#include <defs.h> #include <defs.h>
#include <constants.h>
/* copy of smartcard operations, defined in smartcard.h */ /* copy of smartcard operations, defined in smartcard.h */
#ifndef SC_OP_T #ifndef SC_OP_T