merged pluto's PGP certificate parsing with charon's
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
@@ -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));
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user