merged pluto's PGP certificate parsing with charon's
This commit is contained in:
parent
cc543182bc
commit
f565d0c575
|
@ -36,7 +36,6 @@ modecfg.c modecfg.h \
|
|||
nat_traversal.c nat_traversal.h \
|
||||
ocsp.c ocsp.h \
|
||||
packet.c packet.h \
|
||||
pgpcert.c pgpcert.h \
|
||||
pkcs7.c pkcs7.h \
|
||||
plutomain.c \
|
||||
rcv_whack.c rcv_whack.h \
|
||||
|
|
|
@ -85,7 +85,7 @@ bool ac_verify_cert(certificate_t *cert, bool strict)
|
|||
identification_t *subject = cert->get_subject(cert);
|
||||
identification_t *issuer = cert->get_issuer(cert);
|
||||
chunk_t authKeyID = ac->get_authKeyIdentifier(ac);
|
||||
x509cert_t *aacert;
|
||||
cert_t *aacert;
|
||||
time_t notBefore, valid_until;
|
||||
|
||||
DBG1("holder: '%Y'", subject);
|
||||
|
|
|
@ -64,43 +64,31 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args)
|
|||
}
|
||||
if (blob.ptr)
|
||||
{
|
||||
cert_t *cert = malloc_thing(cert_t);
|
||||
|
||||
*cert = cert_empty;
|
||||
|
||||
if (pgp)
|
||||
{
|
||||
pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
|
||||
*pgpcert = pgpcert_empty;
|
||||
if (parse_pgp(chunk_clone(blob), pgpcert))
|
||||
{
|
||||
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);
|
||||
cert->cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_GPG,
|
||||
BUILD_BLOB_PGP, blob,
|
||||
BUILD_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
x509cert_t *x509cert = malloc_thing(x509cert_t);
|
||||
|
||||
*x509cert = empty_x509cert;
|
||||
x509cert->cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
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);
|
||||
cert->cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, blob,
|
||||
BUILD_X509_FLAG, flags,
|
||||
BUILD_END);
|
||||
}
|
||||
if (cert->cert)
|
||||
{
|
||||
return cert;
|
||||
}
|
||||
plog(" error in X.509 certificate");
|
||||
cert_free(cert);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
/* 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 */
|
||||
|
||||
|
@ -79,7 +79,7 @@ bool trusted_ca(identification_t *a, identification_t *b, int *pathlen)
|
|||
{
|
||||
certificate_t *certificate;
|
||||
identification_t *issuer;
|
||||
x509cert_t *cacert;
|
||||
cert_t *cacert;
|
||||
|
||||
cacert = get_authcert(a, chunk_empty, X509_CA);
|
||||
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)
|
||||
{
|
||||
x509cert_t *first = x509authcerts;
|
||||
cert_t *first = x509authcerts;
|
||||
|
||||
x509authcerts = first->next;
|
||||
free_x509cert(first);
|
||||
cert_free(first);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -174,18 +175,19 @@ void free_authcerts(void)
|
|||
lock_authcert_list("free_authcerts");
|
||||
|
||||
while (x509authcerts != NULL)
|
||||
{
|
||||
free_first_authcert();
|
||||
|
||||
}
|
||||
unlock_authcert_list("free_authcerts");
|
||||
}
|
||||
|
||||
/*
|
||||
* get a X.509 authority certificate with a given subject or keyid
|
||||
*/
|
||||
x509cert_t* get_authcert(identification_t *subject, chunk_t keyid,
|
||||
cert_t* get_authcert(identification_t *subject, chunk_t keyid,
|
||||
x509_flag_t auth_flags)
|
||||
{
|
||||
x509cert_t *cert, *prev_cert = NULL;
|
||||
cert_t *cert, *prev_cert = NULL;
|
||||
|
||||
/* the authority certificate list is empty */
|
||||
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
|
||||
*/
|
||||
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;
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
x509cert_t *old_cert;
|
||||
cert_t *old_cert;
|
||||
|
||||
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");
|
||||
|
||||
free_x509cert(cert);
|
||||
cert_free(cert);
|
||||
return old_cert;
|
||||
}
|
||||
else
|
||||
|
@ -274,7 +276,7 @@ x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
|
|||
/* add new authcert to chained list */
|
||||
cert->next = x509authcerts;
|
||||
x509authcerts = cert;
|
||||
share_x509cert(cert); /* set count to one */
|
||||
cert_share(cert); /* set count to one */
|
||||
DBG(DBG_CONTROL | DBG_PARSING,
|
||||
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))
|
||||
{
|
||||
cert_t cert;
|
||||
cert_t *cert;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
{
|
||||
/* skip special file */
|
||||
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);
|
||||
|
@ -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
|
||||
*/
|
||||
static const x509cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
|
||||
const x509cert_t *cert)
|
||||
static const cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
|
||||
const cert_t *cert)
|
||||
{
|
||||
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.
|
||||
* 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;
|
||||
|
||||
|
@ -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 *issuer = certificate->get_issuer(certificate);
|
||||
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
|
||||
const x509cert_t *authcert = NULL;
|
||||
const cert_t *authcert = NULL;
|
||||
|
||||
DBG(DBG_CONTROL,
|
||||
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)
|
||||
{
|
||||
smartcard_t *sc = NULL;
|
||||
cert_t cert;
|
||||
bool valid_cert = FALSE;
|
||||
cert_t *cert = NULL;
|
||||
bool cached_cert = 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))
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
/* 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 = cacert->cert;
|
||||
certificate_t *certificate = cert->cert;
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
identification_t *subject = certificate->get_subject(certificate);
|
||||
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 */
|
||||
loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
|
||||
"ignoring \"%s\"", ca->name, msg->name);
|
||||
free_x509cert(cacert);
|
||||
cert_free(cert);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -647,13 +648,15 @@ void add_ca_info(const whack_message_t *msg)
|
|||
unlock_ca_info_list("add_ca_info");
|
||||
|
||||
/* add cacert to list of authcerts */
|
||||
cacert = add_authcert(cacert, X509_CA);
|
||||
cert = add_authcert(cert, X509_CA);
|
||||
if (!cached_cert && sc != NULL)
|
||||
{
|
||||
if (sc->last_cert.type == CERT_X509_SIGNATURE)
|
||||
sc->last_cert.u.x509->count--;
|
||||
sc->last_cert.u.x509 = cacert;
|
||||
share_cert(sc->last_cert);
|
||||
if (sc->last_cert != NULL)
|
||||
{
|
||||
sc->last_cert->count--;
|
||||
}
|
||||
sc->last_cert = cert;
|
||||
cert_share(sc->last_cert);
|
||||
}
|
||||
if (sc != NULL)
|
||||
time(&sc->last_load);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
#include "x509.h"
|
||||
#include "certs.h"
|
||||
#include "whack.h"
|
||||
|
||||
/* CA info structures */
|
||||
|
@ -40,14 +40,13 @@ struct ca_info {
|
|||
extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen);
|
||||
extern bool match_requested_ca(linked_list_t *requested_ca,
|
||||
identification_t *our_ca, int *our_pathlen);
|
||||
extern x509cert_t* get_authcert(identification_t *subject, chunk_t keyid,
|
||||
extern cert_t* get_authcert(identification_t *subject, chunk_t keyid,
|
||||
x509_flag_t auth_flags);
|
||||
extern void load_authcerts(char *type, char *path, x509_flag_t auth_flags);
|
||||
extern x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags);
|
||||
extern cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags);
|
||||
extern void free_authcerts(void);
|
||||
extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
|
||||
extern bool trust_authcert_candidate(const x509cert_t *cert,
|
||||
const x509cert_t *alt_chain);
|
||||
extern bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain);
|
||||
extern ca_info_t* get_ca_info(identification_t *name, chunk_t keyid);
|
||||
extern bool find_ca_info_by_name(const char *name, bool delete);
|
||||
extern void add_ca_info(const whack_message_t *msg);
|
||||
|
|
|
@ -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)
|
||||
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;
|
||||
|
||||
return public_key->get_ref(public_key);
|
||||
cert_free(cert);
|
||||
return c;
|
||||
}
|
||||
case CERT_X509_SIGNATURE:
|
||||
{
|
||||
certificate_t *certificate = cert.u.x509->cert;
|
||||
|
||||
return certificate->get_public_key(certificate);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
return load_cert(path, "CA", X509_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
share_pgpcert(cert.u.pgp);
|
||||
break;
|
||||
case CERT_X509_SIGNATURE:
|
||||
share_x509cert(cert.u.x509);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
cert->count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* release of a certificate decreases the count by one
|
||||
* 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:
|
||||
release_pgpcert(cert.u.pgp);
|
||||
break;
|
||||
case CERT_X509_SIGNATURE:
|
||||
release_x509cert(cert.u.x509);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
cert_t **pp = &certs;
|
||||
while (*pp != cert)
|
||||
{
|
||||
pp = &(*pp)->next;
|
||||
}
|
||||
*pp = cert->next;
|
||||
cert_free(cert);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void list_certs(bool utc)
|
||||
void cert_list(bool utc)
|
||||
{
|
||||
list_x509_end_certs(utc);
|
||||
list_pgp_end_certs(utc);
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
#define _CERTS_H
|
||||
|
||||
#include <credentials/keys/private_key.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
|
||||
#include "x509.h"
|
||||
#include "pgpcert.h"
|
||||
#include <freeswan.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/* path definitions for private keys, end certs,
|
||||
* cacerts, attribute certs and crls
|
||||
|
@ -43,16 +46,16 @@
|
|||
#define CRL_WARNING_INTERVAL 7 /* days */
|
||||
#define ACERT_WARNING_INTERVAL 1 /* day */
|
||||
|
||||
/* certificate access structure
|
||||
* currently X.509 and OpenPGP certificates are supported
|
||||
*/
|
||||
typedef struct {
|
||||
u_char type;
|
||||
union {
|
||||
x509cert_t *x509;
|
||||
pgpcert_t *pgp;
|
||||
} u;
|
||||
} cert_t;
|
||||
/* access structure for a pluto certificate */
|
||||
|
||||
typedef struct cert_t cert_t;
|
||||
|
||||
struct cert_t {
|
||||
certificate_t *cert;
|
||||
cert_t *next;
|
||||
int count;
|
||||
bool smartcard;
|
||||
};
|
||||
|
||||
/* used for initialization */
|
||||
extern const cert_t cert_empty;
|
||||
|
@ -62,18 +65,16 @@ extern const cert_t cert_empty;
|
|||
*/
|
||||
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,
|
||||
key_type_t type);
|
||||
extern bool load_cert(char *filename, const char *label, x509_flag_t flags,
|
||||
cert_t *cert);
|
||||
extern bool load_host_cert(char *filename, cert_t *cert);
|
||||
extern bool load_ca_cert(char *filename, cert_t *cert);
|
||||
extern bool same_cert(const cert_t *a, const cert_t *b);
|
||||
extern void share_cert(cert_t cert);
|
||||
extern void release_cert(cert_t cert);
|
||||
extern void list_certs(bool utc);
|
||||
extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
|
||||
extern cert_t* load_host_cert(char *filename);
|
||||
extern cert_t* load_ca_cert(char *filename);
|
||||
extern cert_t* cert_add(cert_t *cert);
|
||||
extern void cert_free(cert_t *cert);
|
||||
extern void cert_share(cert_t *cert);
|
||||
extern void cert_release(cert_t *cert);
|
||||
extern void cert_list(bool utc);
|
||||
|
||||
#endif /* _CERTS_H */
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "x509.h"
|
||||
#include "ca.h"
|
||||
#include "crl.h"
|
||||
#include "pgpcert.h"
|
||||
#include "certs.h"
|
||||
#include "ac.h"
|
||||
#include "smartcard.h"
|
||||
|
@ -398,9 +397,9 @@ void delete_connection(connection_t *c, bool relations)
|
|||
gw_delref(&c->gw_info);
|
||||
|
||||
lock_certs_and_keys("delete_connection");
|
||||
release_cert(c->spd.this.cert);
|
||||
cert_release(c->spd.this.cert);
|
||||
scx_release(c->spd.this.sc);
|
||||
release_cert(c->spd.that.cert);
|
||||
cert_release(c->spd.that.cert);
|
||||
scx_release(c->spd.that.sc);
|
||||
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.updown = clone_str(c->spd.this.updown);
|
||||
scx_share(c->spd.this.sc);
|
||||
share_cert(c->spd.this.cert);
|
||||
cert_share(c->spd.this.cert);
|
||||
if (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.updown = clone_str(c->spd.that.updown);
|
||||
scx_share(c->spd.that.sc);
|
||||
share_cert(c->spd.that.cert);
|
||||
cert_share(c->spd.that.cert);
|
||||
if (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)
|
||||
{
|
||||
time_t valid_until;
|
||||
cert_t cert;
|
||||
bool valid_cert = FALSE;
|
||||
cert_t *cert = NULL;
|
||||
certificate_t *certificate;
|
||||
bool cached_cert = FALSE;
|
||||
|
||||
|
||||
/* initialize end certificate */
|
||||
dst->cert.type = CERT_NONE;
|
||||
dst->cert.u.x509 = NULL;
|
||||
dst->cert = NULL;
|
||||
|
||||
/* initialize smartcard info record */
|
||||
dst->sc = NULL;
|
||||
|
@ -783,87 +781,73 @@ static void load_end_certificate(char *filename, struct end *dst)
|
|||
if (scx_on_smartcard(filename))
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
/* 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:
|
||||
dst->id = select_pgpcert_id(cert.u.pgp, dst->id);
|
||||
plog( " id '%Y' not confirmed by certificate, defaulting to '%Y'",
|
||||
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
|
||||
{
|
||||
valid_until = cert.u.pgp->until;
|
||||
add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL);
|
||||
dst->cert.type = cert.type;
|
||||
dst->cert.u.pgp = add_pgpcert(cert.u.pgp);
|
||||
}
|
||||
break;
|
||||
case CERT_X509_SIGNATURE:
|
||||
dst->id = select_x509cert_id(cert.u.x509, dst->id);
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("certificate is valid")
|
||||
)
|
||||
add_public_key_from_cert(cert, valid_until, DAL_LOCAL);
|
||||
dst->cert = cert_add(cert);
|
||||
}
|
||||
certificate = dst->cert->cert;
|
||||
|
||||
if (cached_cert)
|
||||
{
|
||||
dst->cert = cert;
|
||||
}
|
||||
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 */
|
||||
if (dst->ca == NULL && certificate->get_type(certificate) == CERT_X509)
|
||||
{
|
||||
identification_t *issuer;
|
||||
|
||||
/* if no CA is defined, use issuer as default */
|
||||
if (dst->ca == NULL)
|
||||
{
|
||||
certificate_t *certificate = dst->cert.u.x509->cert;
|
||||
identification_t *issuer = certificate->get_issuer(certificate);
|
||||
|
||||
dst->ca = issuer->clone(issuer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
issuer = certificate->get_issuer(certificate);
|
||||
dst->ca = issuer->clone(issuer);
|
||||
}
|
||||
|
||||
/* cache the certificate that was last retrieved from the smartcard */
|
||||
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");
|
||||
release_cert(dst->sc->last_cert);
|
||||
cert_release(dst->sc->last_cert);
|
||||
dst->sc->last_cert = dst->cert;
|
||||
share_cert(dst->cert);
|
||||
cert_share(dst->cert);
|
||||
unlock_certs_and_keys("load_end_certificates");
|
||||
}
|
||||
time(&dst->sc->last_load);
|
||||
}
|
||||
}
|
||||
scx_share(dst->sc);
|
||||
share_cert(dst->cert);
|
||||
cert_share(dst->cert);
|
||||
}
|
||||
|
||||
static bool extract_end(struct end *dst, const whack_end_t *src,
|
||||
|
|
|
@ -147,7 +147,7 @@ struct end {
|
|||
u_int16_t host_port; /* host order */
|
||||
u_int16_t port; /* host order */
|
||||
u_int8_t protocol;
|
||||
cert_t cert; /* end certificate */
|
||||
cert_t *cert; /* end certificate */
|
||||
identification_t *ca; /* CA distinguished name */
|
||||
ietf_attributes_t *groups; /* access control groups */
|
||||
smartcard_t *sc; /* smartcard reader and key info */
|
||||
|
|
|
@ -113,7 +113,7 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
|
|||
crl_t *crl = (crl_t*)cert_crl;
|
||||
identification_t *issuer = cert_crl->get_issuer(cert_crl);
|
||||
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
|
||||
x509cert_t *issuer_cert;
|
||||
cert_t *issuer_cert;
|
||||
x509crl_t *oldcrl;
|
||||
time_t now, nextUpdate;
|
||||
bool valid_sig;
|
||||
|
@ -340,8 +340,7 @@ void check_crls(void)
|
|||
/*
|
||||
* verify if a cert hasn't been revoked by a crl
|
||||
*/
|
||||
cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
|
||||
time_t *revocationDate,
|
||||
cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
|
||||
crl_reason_t *revocationReason)
|
||||
{
|
||||
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;
|
||||
crl_t *crl = (crl_t*)cert_crl;
|
||||
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
|
||||
x509cert_t *issuer_cert;
|
||||
cert_t *issuer_cert;
|
||||
bool trusted, valid;
|
||||
|
||||
DBG(DBG_CONTROL,
|
||||
|
|
|
@ -26,7 +26,6 @@ struct x509crl {
|
|||
certificate_t *crl;
|
||||
x509crl_t *next;
|
||||
linked_list_t *distributionPoints;
|
||||
chunk_t signature;
|
||||
};
|
||||
|
||||
/* apply a strict CRL policy
|
||||
|
@ -46,7 +45,7 @@ extern long crl_check_interval;
|
|||
extern void load_crls(void);
|
||||
extern void check_crls(void);
|
||||
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,
|
||||
crl_reason_t *revocationReason);
|
||||
extern void list_crls(bool utc, bool strict);
|
||||
|
|
|
@ -199,9 +199,10 @@ struct db_context *ike_alg_db_new(connection_t *c, lset_t policy)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -905,7 +905,6 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
|
|||
struct state *st = new_state();
|
||||
pb_stream reply; /* not actually a reply, but you know what I mean */
|
||||
pb_stream rbody;
|
||||
|
||||
int vids_to_send = 0;
|
||||
|
||||
/* set up new state */
|
||||
|
@ -925,7 +924,8 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
|
|||
{
|
||||
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++;
|
||||
}
|
||||
|
@ -1022,7 +1022,8 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
|
|||
/* if we have an OpenPGP certificate we assume an
|
||||
* 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
|
||||
, &rbody, VID_OPENPGP))
|
||||
|
@ -2166,12 +2167,12 @@ static void decode_cert(struct msg_digest *md)
|
|||
blob.len = pbs_left(&p->pbs);
|
||||
if (cert->isacert_type == CERT_X509_SIGNATURE)
|
||||
{
|
||||
x509cert_t x509cert = empty_x509cert;
|
||||
cert_t x509cert = cert_empty;
|
||||
|
||||
x509cert.cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, blob,
|
||||
BUILD_END);
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, blob,
|
||||
BUILD_END);
|
||||
if (x509cert.cert)
|
||||
{
|
||||
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_log("Public key validated")
|
||||
)
|
||||
add_x509_public_key(&x509cert, valid_until, DAL_SIGNED);
|
||||
add_public_key_from_cert(&x509cert, valid_until, DAL_SIGNED);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3518,7 +3519,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
|
||||
connection_t *c = st->st_connection;
|
||||
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 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
|
||||
*/
|
||||
requested = cert_policy == CERT_SEND_IF_ASKED && c->got_certrequest;
|
||||
send_cert = pubkey_auth && mycert.type != CERT_NONE
|
||||
&& (cert_policy == CERT_ALWAYS_SEND || requested);
|
||||
send_cert = pubkey_auth && mycert &&
|
||||
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_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_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 = "";
|
||||
|
||||
|
@ -3623,13 +3625,13 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
|
||||
struct isakmp_cert cert_hd;
|
||||
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))
|
||||
{
|
||||
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");
|
||||
free(cert_encoding.ptr);
|
||||
if (!success)
|
||||
|
@ -3645,7 +3647,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
identification_t *ca = st->st_connection->spd.that.ca;
|
||||
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;
|
||||
}
|
||||
|
@ -3971,7 +3973,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
u_int8_t auth_payload;
|
||||
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
|
||||
certpolicy_t cert_policy;
|
||||
cert_t mycert;
|
||||
cert_t *mycert;
|
||||
bool pubkey_auth, send_cert, requested;
|
||||
|
||||
/* 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
|
||||
&& st->st_connection->got_certrequest;
|
||||
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);
|
||||
|
||||
/*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
|
||||
|
@ -4039,7 +4042,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
DBG(DBG_CONTROL,
|
||||
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 = "";
|
||||
|
||||
|
@ -4063,13 +4066,13 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
struct isakmp_cert cert_hd;
|
||||
|
||||
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))
|
||||
{
|
||||
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");
|
||||
free(cert_encoding.ptr);
|
||||
if (!success)
|
||||
|
|
112
src/pluto/keys.c
112
src/pluto/keys.c
|
@ -36,11 +36,11 @@
|
|||
|
||||
#include <library.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <credentials/certificates/pgp_certificate.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "defs.h"
|
||||
#include "x509.h"
|
||||
#include "pgpcert.h"
|
||||
#include "certs.h"
|
||||
#include "smartcard.h"
|
||||
#include "connections.h"
|
||||
|
@ -111,9 +111,11 @@ static const secret_t* get_secret(const connection_t *c,
|
|||
identification_t *my_id, *his_id;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -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
|
||||
* in an X.509 or OpenPGP certificate
|
||||
*/
|
||||
bool has_private_key(cert_t cert)
|
||||
bool has_private_key(cert_t *cert)
|
||||
{
|
||||
secret_t *s;
|
||||
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)
|
||||
{
|
||||
|
@ -284,7 +286,7 @@ bool has_private_key(cert_t cert)
|
|||
/*
|
||||
* 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);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
enum dns_auth_level dns_auth_level)
|
||||
void add_public_key_from_cert(cert_t *cert , time_t until,
|
||||
enum dns_auth_level dns_auth_level)
|
||||
{
|
||||
certificate_t *certificate = cert->cert;
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
identification_t *subject = certificate->get_subject(certificate);
|
||||
identification_t *issuer = certificate->get_issuer(certificate);
|
||||
identification_t *issuer = NULL;
|
||||
identification_t *id;
|
||||
chunk_t serialNumber = x509->get_serial(x509);
|
||||
chunk_t serialNumber = chunk_empty;
|
||||
pubkey_t *pk;
|
||||
key_type_t pk_type;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
/* ID type: ID_DER_ASN1_DN (X.509 subject field) */
|
||||
pk = malloc_thing(pubkey_t);
|
||||
zero(pk);
|
||||
pk->public_key = certificate->get_public_key(certificate);
|
||||
pk_type = pk->public_key->get_type(pk->public_key);
|
||||
pk->id = subject->clone(subject);
|
||||
pk->dns_auth_level = dns_auth_level;
|
||||
pk->until_time = until;
|
||||
pk->issuer = issuer->clone(issuer);
|
||||
pk->serial = chunk_clone(serialNumber);
|
||||
pk_type = pk->public_key->get_type(pk->public_key);
|
||||
if (certificate->get_type(certificate) == CERT_X509)
|
||||
{
|
||||
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);
|
||||
install_public_key(pk, &pubkeys);
|
||||
|
||||
/* insert all subjectAltNames */
|
||||
enumerator = x509->create_subjectAltName_enumerator(x509);
|
||||
while (enumerator->enumerate(enumerator, &id))
|
||||
if (certificate->get_type(certificate) == CERT_X509)
|
||||
{
|
||||
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);
|
||||
zero(pk);
|
||||
pk->id = id->clone(id);
|
||||
pk->public_key = certificate->get_public_key(certificate);
|
||||
pk->dns_auth_level = dns_auth_level;
|
||||
pk->until_time = until;
|
||||
pk->issuer = issuer->clone(issuer);
|
||||
pk->serial = chunk_clone(serialNumber);
|
||||
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
|
||||
install_public_key(pk, &pubkeys);
|
||||
if (id->get_type(id) != ID_ANY)
|
||||
{
|
||||
pk = malloc_thing(pubkey_t);
|
||||
zero(pk);
|
||||
pk->id = id->clone(id);
|
||||
pk->public_key = certificate->get_public_key(certificate);
|
||||
pk->dns_auth_level = dns_auth_level;
|
||||
pk->until_time = until;
|
||||
pk->issuer = issuer->clone(issuer);
|
||||
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
|
||||
* insert it into a pubkeyrec
|
||||
*/
|
||||
void add_pgp_public_key(pgpcert_t *cert , time_t until,
|
||||
enum dns_auth_level dns_auth_level)
|
||||
{
|
||||
pubkey_t *pk;
|
||||
key_type_t pk_type;
|
||||
|
||||
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);
|
||||
/* add v3 or v4 PGP fingerprint */
|
||||
pk = malloc_thing(pubkey_t);
|
||||
zero(pk);
|
||||
pk->id = identification_create_from_encoding(ID_KEY_ID, fingerprint);
|
||||
pk->public_key = certificate->get_public_key(certificate);
|
||||
pk->dns_auth_level = dns_auth_level;
|
||||
pk->until_time = until;
|
||||
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
|
||||
install_public_key(pk, &pubkeys);
|
||||
}
|
||||
}
|
||||
|
||||
/* when a X.509 certificate gets revoked, all instances of
|
||||
* 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);
|
||||
pubkey_list_t *p, **pp;
|
||||
|
|
|
@ -45,7 +45,7 @@ struct connection;
|
|||
|
||||
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_x509_private_key(const x509cert_t *cert);
|
||||
extern private_key_t *get_x509_private_key(const cert_t *cert);
|
||||
|
||||
/* public key machinery */
|
||||
|
||||
|
@ -84,12 +84,10 @@ extern bool add_public_key(identification_t *id,
|
|||
enum pubkey_alg alg,
|
||||
chunk_t rfc3110_key,
|
||||
pubkey_list_t **head);
|
||||
extern bool has_private_key(cert_t cert);
|
||||
extern void add_x509_public_key(x509cert_t *cert, time_t until
|
||||
, enum dns_auth_level dns_auth_level);
|
||||
extern void add_pgp_public_key(pgpcert_t *cert, time_t until
|
||||
, enum dns_auth_level dns_auth_level);
|
||||
extern void remove_x509_public_key(const x509cert_t *cert);
|
||||
extern bool has_private_key(cert_t *cert);
|
||||
extern void add_public_key_from_cert(cert_t *cert, time_t until,
|
||||
enum dns_auth_level dns_auth_level);
|
||||
extern void remove_x509_public_key(const cert_t *cert);
|
||||
extern void list_public_keys(bool utc);
|
||||
|
||||
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
|
||||
|
|
|
@ -145,7 +145,7 @@ static chunk_t ocsp_default_uri;
|
|||
static ocsp_location_t *ocsp_cache = NULL;
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -281,7 +281,7 @@ static const asn1Object_t singleResponseObjects[] = {
|
|||
* Build an ocsp location from certificate information
|
||||
* 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;
|
||||
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)
|
||||
{
|
||||
x509cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
|
||||
cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
|
||||
|
||||
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
|
||||
*/
|
||||
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,
|
||||
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)
|
||||
{
|
||||
x509cert_t *cert = NULL;
|
||||
cert_t *cert = NULL;
|
||||
|
||||
/* initialize temporary static storage */
|
||||
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)
|
||||
{
|
||||
int pathlen, pathlen_constraint;
|
||||
x509cert_t *authcert;
|
||||
cert_t *authcert;
|
||||
|
||||
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++)
|
||||
{
|
||||
x509cert_t *cert = authcert;
|
||||
cert_t *cert = authcert;
|
||||
certificate_t *certificate = cert->cert;
|
||||
x509_t *x509 = (x509_t*)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;
|
||||
case BASIC_RESPONSE_CERTIFICATE:
|
||||
{
|
||||
x509cert_t *cert = malloc_thing(x509cert_t);
|
||||
cert_t *cert = malloc_thing(cert_t);
|
||||
x509_t *x509;
|
||||
|
||||
*cert = empty_x509cert;
|
||||
*cert = cert_empty;
|
||||
cert->cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
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_log("parsing of embedded ocsp certificate failed")
|
||||
)
|
||||
free_x509cert(cert);
|
||||
cert_free(cert);
|
||||
break;
|
||||
}
|
||||
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_log("embedded ocsp certificate rejected")
|
||||
)
|
||||
free_x509cert(cert);
|
||||
cert_free(cert);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -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
|
||||
, ocsp_location_t **chain, bool request);
|
||||
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);
|
||||
extern bool ocsp_set_request_cert(char* path);
|
||||
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 void parse_ocsp(ocsp_location_t* location, chunk_t blob);
|
||||
extern void list_ocsp_locations(ocsp_location_t *location, bool requests
|
||||
|
|
|
@ -32,476 +32,4 @@
|
|||
#include "whack.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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,40 +17,6 @@
|
|||
#ifndef _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 release_pgpcert(pgpcert_t *cert);
|
||||
extern void free_pgpcert(pgpcert_t *cert);
|
||||
|
||||
#endif /* _PGPCERT_H */
|
||||
|
|
|
@ -476,7 +476,7 @@ void whack_handle(int whackctlfd)
|
|||
|
||||
if (msg.whack_list & LIST_CERTS)
|
||||
{
|
||||
list_certs(msg.whack_utc);
|
||||
cert_list(msg.whack_utc);
|
||||
}
|
||||
|
||||
if (msg.whack_list & LIST_CACERTS)
|
||||
|
|
|
@ -59,21 +59,21 @@ static smartcard_t *smartcards = NULL;
|
|||
static int sc_number = 0;
|
||||
|
||||
const smartcard_t empty_sc = {
|
||||
NULL , /* next */
|
||||
0 , /* last_load */
|
||||
{ CERT_NONE, {NULL} }, /* last_cert */
|
||||
0 , /* count */
|
||||
0 , /* number */
|
||||
999999 , /* slot */
|
||||
NULL , /* id */
|
||||
NULL , /* label */
|
||||
{ NULL, 0 } , /* pin */
|
||||
FALSE , /* pinpad */
|
||||
FALSE , /* valid */
|
||||
FALSE , /* session_opened */
|
||||
FALSE , /* logged_in */
|
||||
TRUE , /* any_slot */
|
||||
0L , /* session */
|
||||
NULL , /* next */
|
||||
0 , /* last_load */
|
||||
NULL , /* last_cert */
|
||||
0 , /* count */
|
||||
0 , /* number */
|
||||
999999 , /* slot */
|
||||
NULL , /* id */
|
||||
NULL , /* label */
|
||||
{ NULL, 0 } , /* pin */
|
||||
FALSE , /* pinpad */
|
||||
FALSE , /* valid */
|
||||
FALSE , /* session_opened */
|
||||
FALSE , /* logged_in */
|
||||
TRUE , /* any_slot */
|
||||
0L , /* session */
|
||||
};
|
||||
|
||||
#ifdef SMARTCARD /* compile with smartcard support */
|
||||
|
@ -437,14 +437,13 @@ failed: scx_unload_pkcs11_module(mod);
|
|||
/*
|
||||
* retrieve a certificate object
|
||||
*/
|
||||
static bool scx_find_cert_object(CK_SESSION_HANDLE session,
|
||||
CK_OBJECT_HANDLE object,
|
||||
smartcard_t *sc, cert_t *cert)
|
||||
static cert_t* scx_find_cert_object(CK_SESSION_HANDLE session,
|
||||
CK_OBJECT_HANDLE object, smartcard_t *sc)
|
||||
{
|
||||
size_t hex_len, label_len;
|
||||
u_char *hex_id = NULL;
|
||||
cert_t *cert;
|
||||
chunk_t blob;
|
||||
x509cert_t *x509cert;
|
||||
|
||||
CK_ATTRIBUTE attr[] = {
|
||||
{ CKA_ID, NULL_PTR, 0L },
|
||||
|
@ -452,16 +451,13 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
|
|||
{ CKA_VALUE, NULL_PTR, 0L }
|
||||
};
|
||||
|
||||
/* initialize the return argument */
|
||||
*cert = cert_empty;
|
||||
|
||||
/* get the length of the attributes first */
|
||||
CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
|
||||
if (rv != CKR_OK)
|
||||
{
|
||||
plog("couldn't read the attribute sizes: %s"
|
||||
, enum_show(&pkcs11_return_names, rv));
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(sc->label);
|
||||
|
@ -486,7 +482,7 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
|
|||
free(hex_id);
|
||||
free(sc->label);
|
||||
free(blob.ptr);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(sc->id);
|
||||
|
@ -500,22 +496,23 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
|
|||
sc->label[label_len] = '\0';
|
||||
|
||||
/* parse the retrieved cert */
|
||||
x509cert = malloc_thing(x509cert_t);
|
||||
*x509cert = empty_x509cert;
|
||||
x509cert->smartcard = TRUE;
|
||||
x509cert->cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, blob,
|
||||
BUILD_END);
|
||||
if (x509cert->cert)
|
||||
|
||||
/* initialize the return argument */
|
||||
cert = malloc_thing(cert_t);
|
||||
*cert = cert_empty;
|
||||
cert->smartcard = TRUE;
|
||||
cert->cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, blob,
|
||||
BUILD_END);
|
||||
if (cert->cert)
|
||||
{
|
||||
cert->type = CERT_X509_SIGNATURE;
|
||||
cert->u.x509 = x509cert;
|
||||
return TRUE;
|
||||
return cert;
|
||||
}
|
||||
|
||||
plog("failed to load cert from smartcard, error in X.509 certificate");
|
||||
free_x509cert(x509cert);
|
||||
return FALSE;
|
||||
cert_free(cert);
|
||||
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;
|
||||
time_t valid_until;
|
||||
smartcard_t *sc;
|
||||
x509cert_t *cert;
|
||||
certificate_t *certificate;
|
||||
x509_t *x509;
|
||||
|
||||
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->any_slot = FALSE;
|
||||
sc->slot = slot;
|
||||
|
||||
if (!scx_find_cert_object(session, object, sc, &sc->last_cert))
|
||||
sc->last_cert = scx_find_cert_object(session, object, sc);
|
||||
if (sc->last_cert == NULL)
|
||||
{
|
||||
scx_free(sc);
|
||||
continue;
|
||||
|
@ -574,10 +571,9 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
|
|||
)
|
||||
|
||||
/* check validity of certificate */
|
||||
cert = sc->last_cert.u.x509;
|
||||
if (!cert->cert->get_validity(cert->cert, NULL, NULL, &valid_until))
|
||||
certificate = sc->last_cert->cert;
|
||||
if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
|
||||
{
|
||||
free_x509cert(cert);
|
||||
scx_free(sc);
|
||||
continue;
|
||||
}
|
||||
|
@ -586,20 +582,20 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
|
|||
)
|
||||
|
||||
sc = scx_add(sc);
|
||||
x509 = (x509_t*)cert->cert;
|
||||
x509 = (x509_t*)certificate;
|
||||
|
||||
/* put end entity and ca certificates into different chains */
|
||||
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
|
||||
{
|
||||
add_x509_public_key(cert, valid_until, DAL_LOCAL);
|
||||
sc->last_cert.u.x509 = add_x509cert(cert);
|
||||
add_public_key_from_cert(sc->last_cert, valid_until, DAL_LOCAL);
|
||||
sc->last_cert = cert_add(sc->last_cert);
|
||||
}
|
||||
|
||||
share_cert(sc->last_cert);
|
||||
cert_share(sc->last_cert);
|
||||
time(&sc->last_load);
|
||||
}
|
||||
|
||||
|
@ -1070,67 +1066,66 @@ void scx_release_context(smartcard_t *sc)
|
|||
/*
|
||||
* Load host certificate from smartcard
|
||||
*/
|
||||
bool scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert,
|
||||
bool *cached)
|
||||
cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached)
|
||||
{
|
||||
#ifdef SMARTCARD /* compile with smartcard support */
|
||||
CK_OBJECT_HANDLE object;
|
||||
|
||||
const char *number_slot_id = filename + strlen(SCX_TOKEN);
|
||||
|
||||
smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id));
|
||||
CK_OBJECT_HANDLE object;
|
||||
smartcard_t *sc;
|
||||
cert_t *cert = NULL;
|
||||
|
||||
/* return the smartcard object */
|
||||
*scp = sc;
|
||||
*scp = sc = scx_add(scx_parse_number_slot_id(number_slot_id));
|
||||
|
||||
/* is there a cached smartcard certificate? */
|
||||
*cached = sc->last_cert.type != CERT_NONE
|
||||
&& (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
|
||||
*cached = sc->last_cert &&
|
||||
(time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
|
||||
|
||||
if (*cached)
|
||||
{
|
||||
*cert = sc->last_cert;
|
||||
plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
|
||||
, sc->number
|
||||
, scx_print_slot(sc, "")
|
||||
, sc->id
|
||||
, sc->label);
|
||||
return TRUE;
|
||||
return sc->last_cert;
|
||||
}
|
||||
|
||||
if (!scx_establish_context(sc))
|
||||
{
|
||||
scx_release_context(sc);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find the certificate object */
|
||||
if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
|
||||
{
|
||||
scx_release_context(sc);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!pkcs11_keep_state)
|
||||
{
|
||||
scx_release_context(sc);
|
||||
|
||||
}
|
||||
plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
|
||||
, sc->number
|
||||
, scx_print_slot(sc, "")
|
||||
, sc->id
|
||||
, sc->label);
|
||||
|
||||
return TRUE;
|
||||
return cert;
|
||||
#else
|
||||
plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1793,6 +1788,7 @@ void scx_free(smartcard_t *sc)
|
|||
if (sc != NULL)
|
||||
{
|
||||
scx_release_context(sc);
|
||||
cert_release(sc->last_cert);
|
||||
free(sc->id);
|
||||
free(sc->label);
|
||||
scx_free_pin(&sc->pin);
|
||||
|
@ -1811,7 +1807,6 @@ void scx_release(smartcard_t *sc)
|
|||
while (*pp != sc)
|
||||
pp = &(*pp)->next;
|
||||
*pp = sc->next;
|
||||
release_cert(sc->last_cert);
|
||||
scx_free(sc);
|
||||
}
|
||||
}
|
||||
|
@ -1875,14 +1870,16 @@ smartcard_t* scx_add(smartcard_t *smartcard)
|
|||
/*
|
||||
* 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;
|
||||
|
||||
while (sc != NULL)
|
||||
{
|
||||
if (sc->last_cert.u.x509 == cert)
|
||||
if (sc->last_cert == cert)
|
||||
{
|
||||
return sc;
|
||||
}
|
||||
sc = sc->next;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1929,9 +1926,9 @@ void scx_list(bool utc)
|
|||
whack_log(RC_COMMENT, " id: %s", sc->id);
|
||||
if (sc->label != NULL)
|
||||
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'",
|
||||
certificate->get_subject(certificate));
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef struct smartcard smartcard_t;
|
|||
struct smartcard {
|
||||
smartcard_t *next;
|
||||
time_t last_load;
|
||||
cert_t last_cert;
|
||||
cert_t *last_cert;
|
||||
int count;
|
||||
int number;
|
||||
unsigned long slot;
|
||||
|
@ -75,8 +75,7 @@ extern void scx_finalize(void);
|
|||
extern bool scx_establish_context(smartcard_t *sc);
|
||||
extern bool scx_login(smartcard_t *sc);
|
||||
extern bool scx_on_smartcard(const char *filename);
|
||||
extern bool scx_load_cert(const char *filename, smartcard_t **scp
|
||||
, cert_t *cert, bool *cached);
|
||||
extern cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached);
|
||||
extern bool scx_verify_pin(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
|
||||
|
@ -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 size_t scx_get_keylength(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_context(smartcard_t *sc);
|
||||
extern void scx_free_pin(chunk_t *pin);
|
||||
|
|
174
src/pluto/x509.c
174
src/pluto/x509.c
|
@ -42,100 +42,6 @@
|
|||
#include "fetch.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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
@ -171,48 +77,12 @@ x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t *ch
|
|||
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
|
||||
*/
|
||||
void store_x509certs(linked_list_t *certs, bool strict)
|
||||
{
|
||||
x509cert_t *x509cert, *cacerts = NULL;
|
||||
cert_t *x509cert, *cacerts = NULL;
|
||||
certificate_t *cert;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
|
@ -235,8 +105,8 @@ void store_x509certs(linked_list_t *certs, bool strict)
|
|||
else
|
||||
{
|
||||
/* insertion into temporary chain of candidate CA certs */
|
||||
x509cert = malloc_thing(x509cert_t);
|
||||
*x509cert = empty_x509cert;
|
||||
x509cert = malloc_thing(cert_t);
|
||||
*x509cert = cert_empty;
|
||||
x509cert->cert = cert->get_ref(cert);
|
||||
x509cert->next = cacerts;
|
||||
cacerts = x509cert;
|
||||
|
@ -249,7 +119,7 @@ void store_x509certs(linked_list_t *certs, bool strict)
|
|||
|
||||
while (cacerts)
|
||||
{
|
||||
x509cert_t *cert = cacerts;
|
||||
cert_t *cert = cacerts;
|
||||
|
||||
cacerts = cacerts->next;
|
||||
|
||||
|
@ -260,7 +130,7 @@ void store_x509certs(linked_list_t *certs, bool strict)
|
|||
else
|
||||
{
|
||||
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))
|
||||
{
|
||||
x509cert = malloc_thing(x509cert_t);
|
||||
*x509cert = empty_x509cert;
|
||||
x509cert = malloc_thing(cert_t);
|
||||
*x509cert = cert_empty;
|
||||
x509cert->cert = cert->get_ref(cert);
|
||||
|
||||
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_log("public key validated")
|
||||
)
|
||||
add_x509_public_key(x509cert, valid_until, DAL_SIGNED);
|
||||
add_public_key_from_cert(x509cert, valid_until, DAL_SIGNED);
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -355,7 +225,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
|
|||
identification_t *issuer = certificate->get_issuer(certificate);
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
|
||||
x509cert_t *issuer_cert;
|
||||
cert_t *issuer_cert;
|
||||
time_t notBefore, notAfter;
|
||||
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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
bool first = TRUE;
|
||||
|
@ -511,7 +381,8 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
|||
certificate_t *certificate = cert->cert;
|
||||
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;
|
||||
char buf[BUF_LEN];
|
||||
|
@ -522,10 +393,6 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
|||
time_t notBefore, notAfter;
|
||||
public_key_t *key;
|
||||
chunk_t serial, keyid, subjkey, authkey;
|
||||
cert_t c;
|
||||
|
||||
c.type = CERT_X509_SIGNATURE;
|
||||
c.u.x509 = cert;
|
||||
|
||||
if (first)
|
||||
{
|
||||
|
@ -581,7 +448,7 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
|||
key_type_names, key->get_type(key),
|
||||
key->get_keysize(key) * BITS_PER_BYTE,
|
||||
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))
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -20,43 +20,21 @@
|
|||
|
||||
#include <utils/identification.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <credentials/keys/public_key.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
|
||||
#include "constants.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;
|
||||
#include "certs.h"
|
||||
|
||||
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,
|
||||
certificate_t *issuer_cert);
|
||||
extern chunk_t x509_build_signature(chunk_t tbs, int algorithm,
|
||||
private_key_t *key, bool bit_string);
|
||||
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until);
|
||||
extern x509cert_t* add_x509cert(x509cert_t *cert);
|
||||
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 bool verify_x509cert(cert_t *cert, bool strict, time_t *until);
|
||||
extern cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t* chain);
|
||||
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);
|
||||
extern void list_x509_end_certs(bool utc);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <freeswan.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <constants.h>
|
||||
|
||||
/* copy of smartcard operations, defined in smartcard.h */
|
||||
#ifndef SC_OP_T
|
||||
|
|
Loading…
Reference in New Issue