pluto and scepclient now use the x509 plugin for certificates

This commit is contained in:
Andreas Steffen
2009-09-27 23:09:30 +02:00
parent 727b0f11e2
commit 0eff9f6539
27 changed files with 1136 additions and 1640 deletions
+4 -5
View File
@@ -669,8 +669,8 @@ x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial)
while (ac != NULL)
{
if (same_dn(issuer, ac->holderIssuer)
&& same_serial(serial, ac->holderSerial))
if (same_dn(issuer, ac->holderIssuer) &&
chunk_equals(serial, ac->holderSerial))
{
if (ac!= x509acerts)
{
@@ -772,8 +772,7 @@ bool verify_x509acert(x509acert_t *ac, bool strict)
)
lock_authcert_list("verify_x509acert");
aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber
, ac->authKeyID, AUTH_AA);
aacert = get_authcert(ac->issuerName, ac->authKeyID, AUTH_AA);
unlock_authcert_list("verify_x509acert");
if (aacert == NULL)
@@ -786,7 +785,7 @@ bool verify_x509acert(x509acert_t *ac, bool strict)
)
if (!x509_check_signature(ac->certificateInfo, ac->signature, ac->algorithm,
aacert))
aacert->cert))
{
plog("attribute certificate signature is invalid");
return FALSE;
+11 -1
View File
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <freeswan.h>
@@ -79,13 +80,20 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args)
else
{
x509cert_t *x509cert = malloc_thing(x509cert_t);
*x509cert = empty_x509cert;
if (parse_x509cert(chunk_clone(blob), 0, x509cert))
x509cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (x509cert->cert)
{
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
cert->type = CERT_X509_SIGNATURE;
cert->u.x509 = x509cert;
time(&x509cert->installed);
return cert;
}
plog(" error in X.509 certificate");
@@ -158,6 +166,8 @@ static x509crl_t *builder_load_crl(certificate_type_t type, va_list args)
{
crl = malloc_thing(x509crl_t);
*crl = empty_x509crl;
crl->distributionPoints = linked_list_create();
if (parse_x509crl(chunk_clone(blob), 0, crl))
{
return crl;
+182 -143
View File
@@ -20,6 +20,8 @@
#include <time.h>
#include <sys/types.h>
#include <utils/identification.h>
#include <freeswan.h>
#include "constants.h"
@@ -36,20 +38,6 @@
static x509cert_t *x509authcerts = NULL;
const ca_info_t empty_ca_info = {
NULL , /* next */
NULL , /* name */
UNDEFINED_TIME,
{ NULL, 0 } , /* authName */
{ NULL, 0 } , /* authKeyID */
{ NULL, 0 } , /* authKey SerialNumber */
NULL , /* ldaphost */
NULL , /* ldapbase */
NULL , /* ocspori */
NULL , /* crluri */
FALSE /* strictcrlpolicy */
};
/* chained list of X.509 certification authority information records */
static ca_info_t *ca_infos = NULL;
@@ -57,8 +45,7 @@ static ca_info_t *ca_infos = NULL;
/*
* Checks if CA a is trusted by CA b
*/
bool
trusted_ca(chunk_t a, chunk_t b, int *pathlen)
bool trusted_ca(chunk_t a, chunk_t b, int *pathlen)
{
bool match = FALSE;
@@ -80,28 +67,49 @@ trusted_ca(chunk_t a, chunk_t b, int *pathlen)
/* CA a equals CA b -> we have a match */
if (same_dn(a, b))
{
return TRUE;
}
/* CA a might be a subordinate CA of b */
lock_authcert_list("trusted_ca");
while ((*pathlen)++ < MAX_CA_PATH_LEN)
{
x509cert_t *cacert = get_authcert(a, chunk_empty, chunk_empty, AUTH_CA);
certificate_t *certificate;
identification_t *issuer;
chunk_t issuer_dn;
x509cert_t *cacert;
/* cacert not found or self-signed root cacert-> exit */
if (cacert == NULL || same_dn(cacert->issuer, a))
cacert = get_authcert(a, chunk_empty, AUTH_CA);
if (cacert == NULL)
{
break;
}
certificate = cacert->cert;
/* is the certificate self-signed? */
{
x509_t *x509 = (x509_t*)certificate;
if (x509->get_flags(x509) & X509_SELF_SIGNED)
{
break;
}
}
/* does the issuer of CA a match CA b? */
match = same_dn(cacert->issuer, b);
issuer = certificate->get_issuer(certificate);
issuer_dn = issuer->get_encoding(issuer);
match = same_dn(issuer_dn, b);
/* we have a match and exit the loop */
if (match)
{
break;
}
/* go one level up in the CA chain */
a = cacert->issuer;
a = issuer_dn;
}
unlock_authcert_list("trusted_ca");
@@ -111,8 +119,8 @@ trusted_ca(chunk_t a, chunk_t b, int *pathlen)
/*
* does our CA match one of the requested CAs?
*/
bool
match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen)
bool match_requested_ca(generalName_t *requested_ca, chunk_t our_ca,
int *our_pathlen)
{
/* if no ca is requested than any ca will match */
if (requested_ca == NULL)
@@ -149,8 +157,7 @@ match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen
/*
* free the first authority certificate in the chain
*/
static void
free_first_authcert(void)
static void free_first_authcert(void)
{
x509cert_t *first = x509authcerts;
x509authcerts = first->next;
@@ -160,8 +167,7 @@ free_first_authcert(void)
/*
* free all CA certificates
*/
void
free_authcerts(void)
void free_authcerts(void)
{
lock_authcert_list("free_authcerts");
@@ -174,30 +180,58 @@ free_authcerts(void)
/*
* get a X.509 authority certificate with a given subject or keyid
*/
x509cert_t*
get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags)
x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags)
{
x509cert_t *cert = x509authcerts;
x509cert_t *prev_cert = NULL;
x509cert_t *cert, *prev_cert = NULL;
while (cert != NULL)
/* the authority certificate list is empty */
if (x509authcerts == NULL)
{
if (cert->authority_flags & auth_flags
&& ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
: (same_dn(subject, cert->subject)
&& same_serial(serial, cert->serialNumber))))
return NULL;
}
for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
{
certificate_t *certificate = cert->cert;
identification_t *cert_subject;
chunk_t cert_subject_dn;
/* skip non-matching types of authority certificates */
if (!(cert->authority_flags & auth_flags))
{
if (cert != x509authcerts)
{
/* bring the certificate up front */
prev_cert->next = cert->next;
cert->next = x509authcerts;
x509authcerts = cert;
}
return cert;
continue;
}
prev_cert = cert;
cert = cert->next;
/* compare the keyid with the certificate's subjectKeyIdentifier */
if (keyid.ptr)
{
x509_t *x509 = (x509_t*)certificate;
chunk_t subjectKeyId;
subjectKeyId = x509->get_subjectKeyIdentifier(x509);
if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
{
continue;
}
}
/* compare the subjectDistinguishedNames */
cert_subject = certificate->get_subject(certificate);
cert_subject_dn = cert_subject->get_encoding(cert_subject);
if (!same_dn(subject, cert_subject_dn))
{
continue;
}
/* found the authcert */
if (cert != x509authcerts)
{
/* bring the certificate up front */
prev_cert->next = cert->next;
cert->next = x509authcerts;
x509authcerts = cert;
}
return cert;
}
return NULL;
}
@@ -205,9 +239,12 @@ get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags)
/*
* add an authority certificate to the chained list
*/
x509cert_t*
add_authcert(x509cert_t *cert, u_char auth_flags)
x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *cert_subject = certificate->get_subject(certificate);
chunk_t cert_subject_dn = cert_subject->get_encoding(cert_subject);
x509cert_t *old_cert;
/* set authority flags */
@@ -215,12 +252,12 @@ add_authcert(x509cert_t *cert, u_char auth_flags)
lock_authcert_list("add_authcert");
old_cert = get_authcert(cert->subject, cert->serialNumber
, cert->subjectKeyID, auth_flags);
old_cert = get_authcert(cert_subject_dn,
x509->get_subjectKeyIdentifier(x509),
auth_flags);
if (old_cert != NULL)
{
if (same_x509cert(cert, old_cert))
if (certificate->equals(certificate, old_cert->cert))
{
/* cert is already present, just add additional authority flags */
old_cert->authority_flags |= cert->authority_flags;
@@ -256,8 +293,7 @@ add_authcert(x509cert_t *cert, u_char auth_flags)
/*
* Loads authority certificates
*/
void
load_authcerts(const char *type, const char *path, u_char auth_flags)
void load_authcerts(const char *type, const char *path, u_char auth_flags)
{
struct dirent **filelist;
u_char buf[BUF_LEN];
@@ -299,8 +335,7 @@ load_authcerts(const char *type, const char *path, u_char auth_flags)
/*
* list all X.509 authcerts with given auth flags in a chained list
*/
void
list_authcerts(const char *caption, u_char auth_flags, bool utc)
void list_authcerts(const char *caption, u_char auth_flags, bool utc)
{
lock_authcert_list("list_authcerts");
list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
@@ -310,19 +345,43 @@ list_authcerts(const char *caption, u_char auth_flags, bool utc)
/*
* get a cacert with a given subject or keyid from an alternative list
*/
static const x509cert_t*
get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid
, const x509cert_t *cert)
static const x509cert_t* get_alt_cacert(chunk_t subject, chunk_t keyid,
const x509cert_t *cert)
{
while (cert != NULL)
if (cert == NULL)
{
if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
: (same_dn(subject, cert->subject)
&& same_serial(serial, cert->serialNumber)))
return NULL;
}
for (; cert != NULL; cert = cert->next)
{
certificate_t *certificate = cert->cert;
identification_t *cert_subject;
chunk_t cert_subject_dn;
/* compare the keyid with the certificate's subjectKeyIdentifier */
if (keyid.ptr)
{
return cert;
x509_t *x509 = (x509_t*)certificate;
chunk_t subjectKeyId;
subjectKeyId = x509->get_subjectKeyIdentifier(x509);
if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
{
continue;
}
}
cert = cert->next;
/* compare the subjectDistinguishedNames */
cert_subject = certificate->get_subject(certificate);
cert_subject_dn = cert_subject->get_encoding(cert_subject);
if (!same_dn(subject, cert_subject_dn))
{
continue;
}
/* we found the cacert */
return cert;
}
return NULL;
}
@@ -330,8 +389,7 @@ get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid
/* establish trust into a candidate authcert by going up the trust chain.
* validity and revocation status are not checked.
*/
bool
trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
{
int pathlen;
@@ -339,25 +397,25 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
chunk_t issuer_dn = issuer->get_encoding(issuer);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
const x509cert_t *authcert = NULL;
u_char buf[BUF_LEN];
DBG(DBG_CONTROL,
dntoa(buf, BUF_LEN, cert->subject);
DBG_log("subject: '%s'",buf);
dntoa(buf, BUF_LEN, cert->issuer);
DBG_log("issuer: '%s'",buf);
if (cert->authKeyID.ptr != NULL)
DBG_log("subject: '%Y'", subject);
DBG_log("issuer: '%Y'", issuer);
if (authKeyID.ptr != NULL)
{
datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
, buf, BUF_LEN);
DBG_log("authkey: %s", buf);
DBG_log("authkey: %#B", &authKeyID);
}
)
/* search in alternative chain first */
authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber
, cert->authKeyID, alt_chain);
authcert = get_alt_cacert(issuer_dn, authKeyID, alt_chain);
if (authcert != NULL)
{
@@ -368,8 +426,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
else
{
/* search in trusted chain */
authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
, cert->authKeyID, AUTH_CA);
authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
if (authcert != NULL)
{
@@ -385,8 +442,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
}
}
if (!x509_check_signature(cert->tbsCertificate, cert->signature,
cert->algorithm, authcert))
if (!certificate->issued_by(certificate, authcert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("trust_authcert_candidate");
@@ -397,7 +453,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
)
/* check if cert is a self-signed root ca */
if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
if (pathlen > 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
{
DBG(DBG_CONTROL,
DBG_log("reached self-signed root ca")
@@ -417,16 +473,14 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
/*
* get a CA info record with a given authName or authKeyID
*/
ca_info_t*
get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid)
ca_info_t* get_ca_info(chunk_t authname, chunk_t keyid)
{
ca_info_t *ca= ca_infos;
while (ca!= NULL)
{
if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID)
: (same_dn(authname, ca->authName)
&& same_serial(serial, ca->authKeySerialNumber)))
: same_dn(authname, ca->authName))
{
return ca;
}
@@ -443,24 +497,23 @@ static void
free_ca_info(ca_info_t* ca_info)
{
if (ca_info == NULL)
{
return;
}
ca_info->crluris->destroy_function(ca_info->crluris, free);
free(ca_info->name);
free(ca_info->ldaphost);
free(ca_info->ldapbase);
free(ca_info->ocspuri);
free(ca_info->authName.ptr);
free(ca_info->authKeyID.ptr);
free(ca_info->authKeySerialNumber.ptr);
free_generalNames(ca_info->crluri, TRUE);
free(ca_info);
}
/*
* free all CA certificates
*/
void
free_ca_infos(void)
void free_ca_infos(void)
{
while (ca_infos != NULL)
{
@@ -474,8 +527,7 @@ free_ca_infos(void)
/*
* find a CA information record by name and optionally delete it
*/
bool
find_ca_info_by_name(const char *name, bool delete)
bool find_ca_info_by_name(const char *name, bool delete)
{
ca_info_t **ca_p = &ca_infos;
ca_info_t *ca = *ca_p;
@@ -501,12 +553,23 @@ find_ca_info_by_name(const char *name, bool delete)
return FALSE;
}
/*
* adds a CA description to a chained list
/*
* Create an empty ca_info_t record
*/
void
add_ca_info(const whack_message_t *msg)
ca_info_t* create_ca_info(void)
{
ca_info_t *ca_info = malloc_thing(ca_info_t);
memset(ca_info, 0, sizeof(ca_info_t));
ca_info->crluris = linked_list_create();
return ca_info;
}
/**
* Adds a CA description to a chained list
*/
void add_ca_info(const whack_message_t *msg)
{
smartcard_t *sc = NULL;
cert_t cert;
@@ -532,13 +595,16 @@ add_ca_info(const whack_message_t *msg)
if (valid_cert)
{
char buf[BUF_LEN];
x509cert_t *cacert = cert.u.x509;
certificate_t *certificate = cacert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
chunk_t subject_dn = subject->get_encoding(subject);
chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
ca_info_t *ca = NULL;
/* does the authname already exist? */
ca = get_ca_info(cacert->subject, cacert->serialNumber
, cacert->subjectKeyID);
ca = get_ca_info(subject_dn, subjectKeyID);
if (ca != NULL)
{
@@ -552,30 +618,23 @@ add_ca_info(const whack_message_t *msg)
plog("added ca description \"%s\"", msg->name);
/* create and initialize new ca_info record */
ca = malloc_thing(ca_info_t);
*ca = empty_ca_info;
ca = create_ca_info();
/* name */
ca->name = clone_str(msg->name);
/* authName */
ca->authName = chunk_clone(cacert->subject);
dntoa(buf, BUF_LEN, ca->authName);
ca->authName = chunk_clone(subject_dn);
DBG(DBG_CONTROL,
DBG_log("authname: '%s'", buf)
DBG_log("authname: '%Y'", subject)
)
/* authSerialNumber */
ca->authKeySerialNumber = chunk_clone(cacert->serialNumber);
/* authKeyID */
if (cacert->subjectKeyID.ptr != NULL)
if (subjectKeyID.ptr)
{
ca->authKeyID = chunk_clone(cacert->subjectKeyID);
datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':'
, buf, BUF_LEN);
ca->authKeyID = chunk_clone(subjectKeyID);
DBG(DBG_CONTROL | DBG_PARSING ,
DBG_log("authkey: %s", buf)
DBG_log("authkey: %#B", &subjectKeyID)
)
}
@@ -594,23 +653,9 @@ add_ca_info(const whack_message_t *msg)
plog(" ignoring ocspuri with unkown protocol");
}
/* crluri2*/
if (msg->crluri2 != NULL)
{
generalName_t gn =
{ NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} };
add_distribution_points(&gn, &ca->crluri);
}
/* crluri */
if (msg->crluri != NULL)
{
generalName_t gn =
{ NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} };
add_distribution_points(&gn, &ca->crluri);
}
/* add crl uris */
add_distribution_point(ca->crluris, msg->crluri);
add_distribution_point(ca->crluris, msg->crluri2);
/* strictrlpolicy */
ca->strictcrlpolicy = msg->whack_strict;
@@ -625,11 +670,12 @@ add_ca_info(const whack_message_t *msg)
unlock_ca_info_list("add_ca_info");
/* add cacert to list of authcerts */
cacert = add_authcert(cacert, AUTH_CA);
if (!cached_cert && sc != NULL)
{
if (sc->last_cert.type == CERT_X509_SIGNATURE)
sc->last_cert.u.x509->count--;
sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA);
sc->last_cert.u.x509 = cacert;
share_cert(sc->last_cert);
}
if (sc != NULL)
@@ -640,8 +686,7 @@ add_ca_info(const whack_message_t *msg)
/*
* list all ca_info records in the chained list
*/
void
list_ca_infos(bool utc)
void list_ca_infos(bool utc)
{
ca_info_t *ca = ca_infos;
@@ -672,7 +717,7 @@ list_ca_infos(bool utc)
if (ca->ocspuri != NULL)
whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
list_distribution_points(ca->crluri);
list_distribution_points(ca->crluris);
if (ca->authKeyID.ptr != NULL)
{
@@ -680,12 +725,6 @@ list_ca_infos(bool utc)
, buf, BUF_LEN);
whack_log(RC_COMMENT, " authkey: %s", buf);
}
if (ca->authKeySerialNumber.ptr != NULL)
{
datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':'
, buf, BUF_LEN);
whack_log(RC_COMMENT, " aserial: %s", buf);
}
ca = ca->next;
}
}
+6 -5
View File
@@ -15,6 +15,8 @@
#ifndef _CA_H
#define _CA_H
#include <utils/linked_list.h>
#include "x509.h"
#include "whack.h"
@@ -37,19 +39,18 @@ struct ca_info {
time_t installed;
chunk_t authName;
chunk_t authKeyID;
chunk_t authKeySerialNumber;
char *ldaphost;
char *ldapbase;
char *ocspuri;
generalName_t *crluri;
linked_list_t *crluris;
bool strictcrlpolicy;
};
extern bool trusted_ca(chunk_t a, chunk_t b, int *pathlen);
extern bool match_requested_ca(generalName_t *requested_ca
, chunk_t our_ca, int *our_pathlen);
extern x509cert_t* get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid
, u_char auth_flags);
extern x509cert_t* get_authcert(chunk_t subject, chunk_t keyid,
u_char auth_flags);
extern void load_authcerts(const char *type, const char *path
, u_char auth_flags);
extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags);
@@ -57,7 +58,7 @@ extern void free_authcerts(void);
extern void list_authcerts(const char *caption, u_char auth_flags, bool utc);
extern bool trust_authcert_candidate(const x509cert_t *cert
, const x509cert_t *alt_chain);
extern ca_info_t* get_ca_info(chunk_t name, chunk_t serial, chunk_t keyid);
extern ca_info_t* get_ca_info(chunk_t name, chunk_t keyid);
extern bool find_ca_info_by_name(const char *name, bool delete);
extern void add_ca_info(const whack_message_t *msg);
extern void delete_ca_info(const char *name);
+12 -6
View File
@@ -46,9 +46,9 @@ chunk_t cert_get_encoding(cert_t cert)
switch (cert.type)
{
case CERT_PGP:
return cert.u.pgp->certificate;
return chunk_clone(cert.u.pgp->certificate);
case CERT_X509_SIGNATURE:
return cert.u.x509->certificate;
return cert.u.x509->cert->get_encoding(cert.u.x509->cert);
default:
return chunk_empty;
}
@@ -59,11 +59,17 @@ public_key_t* cert_get_public_key(const cert_t cert)
switch (cert.type)
{
case CERT_PGP:
return cert.u.pgp->public_key;
break;
{
public_key_t *public_key = cert.u.pgp->public_key;
return public_key->get_ref(public_key);
}
case CERT_X509_SIGNATURE:
return cert.u.x509->public_key;
break;
{
certificate_t *certificate = cert.u.x509->cert;
return certificate->get_public_key(certificate);
}
default:
return NULL;
}
+137 -192
View File
@@ -92,17 +92,17 @@ static struct host_pair *host_pairs = NULL;
static struct connection *unoriented_connections = NULL;
/* check to see that Ids of peers match */
bool
same_peer_ids(const struct connection *c, const struct connection *d
, const struct id *his_id)
bool same_peer_ids(const struct connection *c, const struct connection *d,
const struct id *his_id)
{
return same_id(&c->spd.this.id, &d->spd.this.id)
&& same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);
}
static struct host_pair *
find_host_pair(const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport)
static struct host_pair *find_host_pair(const ip_address *myaddr,
u_int16_t myport,
const ip_address *hisaddr,
u_int16_t hisport)
{
struct host_pair *p, *prev;
@@ -138,9 +138,10 @@ find_host_pair(const ip_address *myaddr, u_int16_t myport
}
/* find head of list of connections with this pair of hosts */
static struct connection *
find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport)
static struct connection *find_host_pair_connections(const ip_address *myaddr,
u_int16_t myport,
const ip_address *hisaddr,
u_int16_t hisport)
{
struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
@@ -158,8 +159,7 @@ find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
return hp == NULL? NULL : hp->connections;
}
static void
connect_to_host_pair(struct connection *c)
static void connect_to_host_pair(struct connection *c)
{
if (oriented(*c))
{
@@ -206,8 +206,7 @@ connect_to_host_pair(struct connection *c)
* Move the winner (if any) to the front.
* If none is found, and strict, a diagnostic is logged to whack.
*/
struct connection *
con_by_name(const char *nm, bool strict)
struct connection *con_by_name(const char *nm, bool strict)
{
struct connection *p, *prev;
@@ -235,8 +234,7 @@ con_by_name(const char *nm, bool strict)
return p;
}
void
release_connection(struct connection *c, bool relations)
void release_connection(struct connection *c, bool relations)
{
if (c->kind == CK_INSTANCE)
{
@@ -264,8 +262,7 @@ release_connection(struct connection *c, bool relations)
}
void
delete_connection(struct connection *c, bool relations)
void delete_connection(struct connection *c, bool relations)
{
struct connection *old_cur_connection
= cur_connection == c? NULL : cur_connection;
@@ -361,8 +358,7 @@ delete_connection(struct connection *c, bool relations)
}
/* Delete connections with the specified name */
void
delete_connections_by_name(const char *name, bool strict)
void delete_connections_by_name(const char *name, bool strict)
{
struct connection *c = con_by_name(name, strict);
@@ -370,15 +366,13 @@ delete_connections_by_name(const char *name, bool strict)
delete_connection(c, FALSE);
}
void
delete_every_connection(void)
void delete_every_connection(void)
{
while (connections != NULL)
delete_connection(connections, TRUE);
}
void
release_dead_interfaces(void)
void release_dead_interfaces(void)
{
struct host_pair *hp;
@@ -427,8 +421,7 @@ release_dead_interfaces(void)
}
/* adjust orientations of connections to reflect newly added interfaces */
void
check_orientations(void)
void check_orientations(void)
{
/* try to orient all the unoriented connections */
{
@@ -491,8 +484,7 @@ check_orientations(void)
}
}
static err_t
default_end(struct end *e, ip_address *dflt_nexthop)
static err_t default_end(struct end *e, ip_address *dflt_nexthop)
{
err_t ugh = NULL;
const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr));
@@ -527,13 +519,8 @@ default_end(struct end *e, ip_address *dflt_nexthop)
* Note: if that==NULL, skip nexthop
* Returns strlen of formated result (length excludes NUL at end).
*/
size_t
format_end(char *buf
, size_t buf_len
, const struct end *this
, const struct end *that
, bool is_left
, lset_t policy)
size_t format_end(char *buf, size_t buf_len, const struct end *this,
const struct end *that, bool is_left, lset_t policy)
{
char client[SUBNETTOT_BUF];
const char *client_sep = "";
@@ -668,10 +655,9 @@ format_end(char *buf
*/
#define CONNECTION_BUF (2 * (END_BUF - 1) + 4)
static size_t
format_connection(char *buf, size_t buf_len
, const struct connection *c
, struct spd_route *sr)
static size_t format_connection(char *buf, size_t buf_len,
const struct connection *c,
struct spd_route *sr)
{
size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
@@ -679,8 +665,7 @@ format_connection(char *buf, size_t buf_len
return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
}
static void
unshare_connection_strings(struct connection *c)
static void unshare_connection_strings(struct connection *c)
{
c->name = clone_str(c->name);
@@ -755,8 +740,9 @@ static void load_end_certificate(char *filename, struct end *dst)
dst->cert = cert;
else
{
time_t valid_until = 0;
/* check validity of cert */
valid_until = cert.u.x509->notAfter;
ugh = check_validity(cert.u.x509, &valid_until);
if (ugh != NULL)
{
@@ -772,9 +758,15 @@ static void load_end_certificate(char *filename, struct end *dst)
dst->cert.type = cert.type;
dst->cert.u.x509 = add_x509cert(cert.u.x509);
}
/* if no CA is defined, use issuer as default */
if (dst->ca.ptr == NULL)
dst->ca = dst->cert.u.x509->issuer;
{
certificate_t *certificate = dst->cert.u.x509->cert;
identification_t *issuer = certificate->get_issuer(certificate);
dst->ca = issuer->get_encoding(issuer);
}
break;
default:
break;
@@ -796,8 +788,8 @@ static void load_end_certificate(char *filename, struct end *dst)
}
}
static bool
extract_end(struct end *dst, const whack_end_t *src, const char *which)
static bool extract_end(struct end *dst, const whack_end_t *src,
const char *which)
{
bool same_ca = FALSE;
@@ -884,9 +876,9 @@ extract_end(struct end *dst, const whack_end_t *src, const char *which)
return same_ca;
}
static bool
check_connection_end(const whack_end_t *this, const whack_end_t *that
, const whack_message_t *wm)
static bool check_connection_end(const whack_end_t *this,
const whack_end_t *that,
const whack_message_t *wm)
{
if (wm->addr_family != addrtypeof(&this->host_addr)
|| wm->addr_family != addrtypeof(&this->host_nexthop)
@@ -921,8 +913,7 @@ check_connection_end(const whack_end_t *this, const whack_end_t *that
return TRUE; /* happy */
}
struct connection *
find_connection_by_reqid(uint32_t reqid)
struct connection *find_connection_by_reqid(uint32_t reqid)
{
struct connection *c;
@@ -936,8 +927,7 @@ find_connection_by_reqid(uint32_t reqid)
return NULL;
}
static uint32_t
gen_reqid(void)
static uint32_t gen_reqid(void)
{
uint32_t start;
static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
@@ -955,8 +945,7 @@ gen_reqid(void)
return 0; /* never reached ... */
}
void
add_connection(const whack_message_t *wm)
void add_connection(const whack_message_t *wm)
{
if (con_by_name(wm->name, FALSE) != NULL)
{
@@ -1172,8 +1161,7 @@ add_connection(const whack_message_t *wm)
* Returns name of new connection. May be NULL.
* Caller is responsible for freeing.
*/
char *
add_group_instance(struct connection *group, const ip_subnet *target)
char *add_group_instance(struct connection *group, const ip_subnet *target)
{
char namebuf[100]
, targetbuf[SUBNETTOT_BUF];
@@ -1234,9 +1222,8 @@ add_group_instance(struct connection *group, const ip_subnet *target)
}
/* an old target has disappeared for a group: delete instance */
void
remove_group_instance(const struct connection *group USED_BY_DEBUG
, const char *name)
void remove_group_instance(const struct connection *group USED_BY_DEBUG,
const char *name)
{
passert(group->kind == CK_GROUP);
passert(oriented(*group));
@@ -1254,10 +1241,9 @@ remove_group_instance(const struct connection *group USED_BY_DEBUG
*
* Note that instantiate can only deal with a single SPD/eroute.
*/
static struct connection *
instantiate(struct connection *c, const ip_address *him
, u_int16_t his_port
, const struct id *his_id)
static struct connection *instantiate(struct connection *c,
const ip_address *him, u_int16_t his_port,
const struct id *his_id)
{
struct connection *d;
int wildcards;
@@ -1318,9 +1304,9 @@ instantiate(struct connection *c, const ip_address *him
}
}
struct connection *
rw_instantiate(struct connection *c, const ip_address *him, u_int16_t his_port
, const ip_subnet *his_net, const struct id *his_id)
struct connection *rw_instantiate(struct connection *c, const ip_address *him,
u_int16_t his_port, const ip_subnet *his_net,
const struct id *his_id)
{
struct connection *d = instantiate(c, him, his_port, his_id);
@@ -1345,13 +1331,10 @@ rw_instantiate(struct connection *c, const ip_address *him, u_int16_t his_port
return d;
}
struct connection *
oppo_instantiate(struct connection *c
, const ip_address *him
, const struct id *his_id
, struct gw_info *gw
, const ip_address *our_client USED_BY_DEBUG
, const ip_address *peer_client)
struct connection *oppo_instantiate(struct connection *c, const ip_address *him,
const struct id *his_id, struct gw_info *gw,
const ip_address *our_client USED_BY_DEBUG,
const ip_address *peer_client)
{
struct connection *d = instantiate(c, him, 0, his_id);
@@ -1416,8 +1399,7 @@ oppo_instantiate(struct connection *c
}
/* priority formatting */
void
fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
{
if (pp == BOTTOM_PRIO)
snprintf(buf, POLICY_PRIO_BUF, "0");
@@ -1431,8 +1413,8 @@ fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
* Road Warrior: peer's IP address
* Opportunistic: [" " myclient "==="] " ..." peer ["===" hisclient] '\0'
*/
static size_t
fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, char buf[ADDRTOT_BUF])
static size_t fmt_client(const ip_subnet *client, const ip_address *gw,
const char *prefix, char buf[ADDRTOT_BUF])
{
if (subnetisaddr(client, gw))
{
@@ -1452,8 +1434,7 @@ fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, ch
return strlen(buf);
}
void
fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
void fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
{
char *p = buf;
@@ -1510,11 +1491,10 @@ fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
*
* See also build_outgoing_opportunistic_connection.
*/
struct connection *
find_connection_for_clients(struct spd_route **srp,
const ip_address *our_client,
const ip_address *peer_client,
int transport_proto)
struct connection *find_connection_for_clients(struct spd_route **srp,
const ip_address *our_client,
const ip_address *peer_client,
int transport_proto)
{
struct connection *c = connections, *best = NULL;
policy_prio_t best_prio = BOTTOM_PRIO;
@@ -1654,10 +1634,9 @@ find_connection_for_clients(struct spd_route **srp,
* find_connection_for_clients. In this case, we know the gateways
* that we need to instantiate an opportunistic connection.
*/
struct connection *
build_outgoing_opportunistic_connection(struct gw_info *gw
,const ip_address *our_client
,const ip_address *peer_client)
struct connection *build_outgoing_opportunistic_connection(struct gw_info *gw,
const ip_address *our_client,
const ip_address *peer_client)
{
struct iface *p;
struct connection *best = NULL;
@@ -1733,8 +1712,7 @@ build_outgoing_opportunistic_connection(struct gw_info *gw
, our_client, peer_client);
}
bool
orient(struct connection *c)
bool orient(struct connection *c)
{
struct spd_route *sr;
@@ -1796,8 +1774,7 @@ orient(struct connection *c)
return oriented(*c);
}
void
initiate_connection(const char *name, int whackfd)
void initiate_connection(const char *name, int whackfd)
{
struct connection *c = con_by_name(name, TRUE);
@@ -1928,10 +1905,8 @@ struct find_oppo_continuation {
struct find_oppo_bundle b;
};
static void
cannot_oppo(struct connection *c
, struct find_oppo_bundle *b
, err_t ugh)
static void cannot_oppo(struct connection *c, struct find_oppo_bundle *b,
err_t ugh)
{
char pcb[ADDRTOT_BUF];
char ocb[ADDRTOT_BUF];
@@ -2048,12 +2023,9 @@ cannot_oppo(struct connection *c
static void initiate_opportunistic_body(struct find_oppo_bundle *b
, struct adns_continuation *ac, err_t ac_ugh); /* forward */
void
initiate_opportunistic(const ip_address *our_client
, const ip_address *peer_client
, int transport_proto
, bool held
, int whackfd)
void initiate_opportunistic(const ip_address *our_client,
const ip_address *peer_client, int transport_proto,
bool held, int whackfd)
{
struct find_oppo_bundle b;
@@ -2070,8 +2042,7 @@ initiate_opportunistic(const ip_address *our_client
initiate_opportunistic_body(&b, NULL, NULL);
}
static void
continue_oppo(struct adns_continuation *acr, err_t ugh)
static void continue_oppo(struct adns_continuation *acr, err_t ugh)
{
struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
struct connection *c;
@@ -2145,10 +2116,9 @@ continue_oppo(struct adns_continuation *acr, err_t ugh)
}
#ifdef USE_KEYRR
static err_t
check_key_recs(enum myid_state try_state
, const struct connection *c
, struct adns_continuation *ac)
static err_t check_key_recs(enum myid_state try_state,
const struct connection *c,
struct adns_continuation *ac)
{
/* Check if KEY lookup yielded good results.
* Looking up based on our ID. Used if
@@ -2260,10 +2230,9 @@ static err_t check_txt_recs(enum myid_state try_state,
/* note: gateways_from_dns must be NULL iff this is the first call */
static void
initiate_opportunistic_body(struct find_oppo_bundle *b
, struct adns_continuation *ac
, err_t ac_ugh)
static void initiate_opportunistic_body(struct find_oppo_bundle *b,
struct adns_continuation *ac,
err_t ac_ugh)
{
struct connection *c;
struct spd_route *sr;
@@ -2964,8 +2933,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
close_any(b->whackfd);
}
void
terminate_connection(const char *nm)
void terminate_connection(const char *nm)
{
/* Loop because more than one may match (master and instances)
* But at least one is required (enforced by con_by_name).
@@ -3002,8 +2970,7 @@ terminate_connection(const char *nm)
*/
bool uniqueIDs = FALSE; /* --uniqueids? */
void
ISAKMP_SA_established(struct connection *c, so_serial_t serial)
void ISAKMP_SA_established(struct connection *c, so_serial_t serial)
{
c->newest_isakmp_sa = serial;
@@ -3047,11 +3014,8 @@ ISAKMP_SA_established(struct connection *c, so_serial_t serial)
* The return value is used to find other connections sharing a route.
* *erop is used to find other connections sharing an eroute.
*/
struct connection *
route_owner(struct connection *c
, struct spd_route **srp
, struct connection **erop
, struct spd_route **esrp)
struct connection *route_owner(struct connection *c, struct spd_route **srp,
struct connection **erop, struct spd_route **esrp)
{
struct connection *d
, *best_ro = c
@@ -3157,8 +3121,7 @@ route_owner(struct connection *c
* There ought to be only one.
* This might get to be a bottleneck -- try hashing if it does.
*/
struct connection *
shunt_owner(const ip_subnet *ours, const ip_subnet *his)
struct connection *shunt_owner(const ip_subnet *ours, const ip_subnet *his)
{
struct connection *c;
struct spd_route *sr;
@@ -3180,9 +3143,9 @@ shunt_owner(const ip_subnet *ours, const ip_subnet *his)
* We don't know enough to chose amongst those available.
* ??? no longer usefully different from find_host_pair_connections
*/
struct connection *
find_host_connection(const ip_address *me, u_int16_t my_port
, const ip_address *him, u_int16_t his_port, lset_t policy)
struct connection *find_host_connection(const ip_address *me, u_int16_t my_port,
const ip_address *him, u_int16_t his_port,
lset_t policy)
{
struct connection *c = find_host_pair_connections(me, my_port, him, his_port);
@@ -3266,9 +3229,9 @@ find_host_connection(const ip_address *me, u_int16_t my_port
*/
#define PRIO_NO_MATCH_FOUND 2048
struct connection *
refine_host_connection(const struct state *st, const struct id *peer_id
, chunk_t peer_ca)
struct connection *refine_host_connection(const struct state *st,
const struct id *peer_id,
chunk_t peer_ca)
{
struct connection *c = st->st_connection;
struct connection *d;
@@ -3456,8 +3419,8 @@ refine_host_connection(const struct state *st, const struct id *peer_id
* With virtual addressing, we must not allow someone to use an already
* used (by another id) addr/net.
*/
static bool
is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
static bool is_virtual_net_used(const ip_subnet *peer_net,
const struct id *peer_id)
{
struct connection *d;
@@ -3520,18 +3483,17 @@ is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
/* fc_try: a helper function for find_client_connection */
static struct connection *
fc_try(const struct connection *c
, struct host_pair *hp
, const struct id *peer_id
, const ip_subnet *our_net
, const ip_subnet *peer_net
, const u_int8_t our_protocol
, const u_int16_t our_port
, const u_int8_t peer_protocol
, const u_int16_t peer_port
, chunk_t peer_ca
, const ietfAttrList_t *peer_list)
static struct connection *fc_try(const struct connection *c,
struct host_pair *hp,
const struct id *peer_id,
const ip_subnet *our_net,
const ip_subnet *peer_net,
const u_int8_t our_protocol,
const u_int16_t our_port,
const u_int8_t peer_protocol,
const u_int16_t peer_port,
chunk_t peer_ca,
const ietfAttrList_t *peer_list)
{
struct connection *d;
struct connection *best = NULL;
@@ -3650,17 +3612,16 @@ fc_try(const struct connection *c
return best;
}
static struct connection *
fc_try_oppo(const struct connection *c
, struct host_pair *hp
, const ip_subnet *our_net
, const ip_subnet *peer_net
, const u_int8_t our_protocol
, const u_int16_t our_port
, const u_int8_t peer_protocol
, const u_int16_t peer_port
, chunk_t peer_ca
, const ietfAttrList_t *peer_list)
static struct connection *fc_try_oppo(const struct connection *c,
struct host_pair *hp,
const ip_subnet *our_net,
const ip_subnet *peer_net,
const u_int8_t our_protocol,
const u_int16_t our_port,
const u_int8_t peer_protocol,
const u_int16_t peer_port,
chunk_t peer_ca,
const ietfAttrList_t *peer_list)
{
struct connection *d;
struct connection *best = NULL;
@@ -3754,8 +3715,8 @@ fc_try_oppo(const struct connection *c
/*
* get the peer's CA and group attributes
*/
chunk_t
get_peer_ca_and_groups(struct connection *c, const ietfAttrList_t **peer_list)
chunk_t get_peer_ca_and_groups(struct connection *c,
const ietfAttrList_t **peer_list)
{
struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
@@ -3781,11 +3742,13 @@ get_peer_ca_and_groups(struct connection *c, const ietfAttrList_t **peer_list)
return chunk_empty;
}
struct connection *
find_client_connection(struct connection *c
, const ip_subnet *our_net, const ip_subnet *peer_net
, const u_int8_t our_protocol, const u_int16_t our_port
, const u_int8_t peer_protocol, const u_int16_t peer_port)
struct connection *find_client_connection(struct connection *c,
const ip_subnet *our_net,
const ip_subnet *peer_net,
const u_int8_t our_protocol,
const u_int16_t our_port,
const u_int8_t peer_protocol,
const u_int16_t peer_port)
{
struct connection *d;
struct spd_route *sr;
@@ -3919,9 +3882,7 @@ find_client_connection(struct connection *c
return d;
}
int
connection_compare(const struct connection *ca
, const struct connection *cb)
int connection_compare(const struct connection *ca, const struct connection *cb)
{
int ret;
@@ -3950,15 +3911,13 @@ connection_compare(const struct connection *ca
}
}
static int
connection_compare_qsort(const void *a, const void *b)
static int connection_compare_qsort(const void *a, const void *b)
{
return connection_compare(*(const struct connection *const *)a
, *(const struct connection *const *)b);
}
void
show_connections_status(bool all, const char *name)
void show_connections_status(bool all, const char *name)
{
struct connection *c;
int count, i;
@@ -4125,13 +4084,8 @@ struct pending {
};
/* queue a Quick Mode negotiation pending completion of a suitable Main Mode */
void
add_pending(int whack_sock
, struct state *isakmp_sa
, struct connection *c
, lset_t policy
, unsigned long try
, so_serial_t replacing)
void add_pending(int whack_sock, struct state *isakmp_sa, struct connection *c,
lset_t policy, unsigned long try, so_serial_t replacing)
{
bool already_queued = FALSE;
struct pending *p = c->host_pair->pending;
@@ -4169,8 +4123,7 @@ add_pending(int whack_sock
* This is accomplished by closing all the whack socket file descriptors.
* We go to a lot of trouble to tell each whack, but to not tell it twice.
*/
void
release_pending_whacks(struct state *st, err_t story)
void release_pending_whacks(struct state *st, err_t story)
{
struct pending *p;
struct stat stst;
@@ -4202,8 +4155,7 @@ release_pending_whacks(struct state *st, err_t story)
}
}
static void
delete_pending(struct pending **pp)
static void delete_pending(struct pending **pp)
{
struct pending *p = *pp;
@@ -4214,8 +4166,7 @@ delete_pending(struct pending **pp)
free(p);
}
void
unpend(struct state *st)
void unpend(struct state *st)
{
struct pending **pp
, *p;
@@ -4241,8 +4192,7 @@ unpend(struct state *st)
}
/* a Main Mode negotiation has been replaced; update any pending */
void
update_pending(struct state *os, struct state *ns)
void update_pending(struct state *os, struct state *ns)
{
struct pending *p;
@@ -4259,8 +4209,7 @@ update_pending(struct state *os, struct state *ns)
}
/* a Main Mode negotiation has failed; discard any pending */
void
flush_pending_by_state(struct state *st)
void flush_pending_by_state(struct state *st)
{
struct host_pair *hp = st->st_connection->host_pair;
@@ -4280,8 +4229,7 @@ flush_pending_by_state(struct state *st)
}
/* a connection has been deleted; discard any related pending */
static void
flush_pending_by_connection(struct connection *c)
static void flush_pending_by_connection(struct connection *c)
{
if (c->host_pair != NULL)
{
@@ -4303,8 +4251,7 @@ flush_pending_by_connection(struct connection *c)
}
}
void
show_pending_phase2(const struct host_pair *hp, const struct state *st)
void show_pending_phase2(const struct host_pair *hp, const struct state *st)
{
const struct pending *p;
@@ -4329,8 +4276,7 @@ show_pending_phase2(const struct host_pair *hp, const struct state *st)
* We must be careful to avoid circularity:
* we don't touch it if it is CK_GOING_AWAY.
*/
void
connection_discard(struct connection *c)
void connection_discard(struct connection *c)
{
if (c->kind == CK_INSTANCE)
{
@@ -4354,8 +4300,7 @@ connection_discard(struct connection *c)
long eclipse_count = 0;
struct connection *
eclipsed(struct connection *c, struct spd_route **esrp)
struct connection *eclipsed(struct connection *c, struct spd_route **esrp)
{
struct connection *ue;
struct spd_route *sr1 = &c->spd;
+71 -77
View File
@@ -133,7 +133,7 @@ const x509crl_t empty_x509crl = {
/**
* Get the X.509 CRL with a given issuer
*/
static x509crl_t* get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid)
static x509crl_t* get_x509crl(chunk_t issuer, chunk_t keyid)
{
x509crl_t *crl = x509crls;
x509crl_t *prev_crl = NULL;
@@ -142,7 +142,7 @@ static x509crl_t* get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid)
{
if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL)
? same_keyid(keyid, crl->authKeyID)
: (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber)))
: (same_dn(crl->issuer, issuer)))
{
if (crl != x509crls)
{
@@ -177,8 +177,8 @@ static void free_revoked_certs(revokedCert_t* revokedCerts)
*/
void free_crl(x509crl_t *crl)
{
crl->distributionPoints->destroy_function(crl->distributionPoints, free);
free_revoked_certs(crl->revokedCertificates);
free_generalNames(crl->distributionPoints, TRUE);
free(crl->certificateList.ptr);
free(crl);
}
@@ -204,24 +204,19 @@ void free_crls(void)
/**
* Insert X.509 CRL into chained list
*/
bool insert_crl(x509crl_t *crl, chunk_t crl_uri, bool cache_crl)
bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl)
{
x509cert_t *issuer_cert;
x509crl_t *oldcrl;
bool valid_sig;
generalName_t *gn;
/* add distribution point */
gn = malloc_thing(generalName_t);
gn->kind = GN_URI;
gn->name = crl_uri;
gn->next = crl->distributionPoints;
crl->distributionPoints = gn;
add_distribution_point(crl->distributionPoints, crl_uri);
lock_authcert_list("insert_crl");
/* get the issuer cacert */
issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
crl->authKeyID, AUTH_CA);
issuer_cert = get_authcert(crl->issuer, crl->authKeyID, AUTH_CA);
if (issuer_cert == NULL)
{
plog("crl issuer cacert not found");
@@ -235,7 +230,7 @@ bool insert_crl(x509crl_t *crl, chunk_t crl_uri, bool cache_crl)
/* check the issuer's signature of the crl */
valid_sig = x509_check_signature(crl->tbsCertList, crl->signature,
crl->algorithm, issuer_cert);
crl->algorithm, issuer_cert->cert);
unlock_authcert_list("insert_crl");
if (!valid_sig)
@@ -248,16 +243,15 @@ bool insert_crl(x509crl_t *crl, chunk_t crl_uri, bool cache_crl)
)
lock_crl_list("insert_crl");
oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
, crl->authKeyID);
oldcrl = get_x509crl(crl->issuer, crl->authKeyID);
if (oldcrl != NULL)
{
if (crl->thisUpdate > oldcrl->thisUpdate)
{
/* keep any known CRL distribution points */
add_distribution_points(oldcrl->distributionPoints
, &crl->distributionPoints);
add_distribution_points(crl->distributionPoints,
oldcrl->distributionPoints);
/* now delete the old CRL */
free_first_crl();
@@ -286,23 +280,15 @@ bool insert_crl(x509crl_t *crl, chunk_t crl_uri, bool cache_crl)
* Only http or ldap URIs are cached but not local file URIs.
* The issuer's subjectKeyID is used as a unique filename
*/
if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
if (cache_crl && strncasecmp(crl_uri, "file", 4) != 0)
{
char path[BUF_LEN], buf[BUF_LEN];
char digest_buf[HASH_SIZE_SHA1];
chunk_t subjectKeyID = chunk_create(digest_buf, sizeof(digest_buf));
bool has_keyID;
certificate_t *certificate = issuer_cert->cert;
x509_t *x509 = (x509_t*)certificate;
chunk_t subjectKeyID;
if (issuer_cert->subjectKeyID.ptr == NULL)
{
has_keyID = compute_subjectKeyID(issuer_cert, subjectKeyID);
}
else
{
subjectKeyID = issuer_cert->subjectKeyID;
has_keyID = TRUE;
}
if (has_keyID)
subjectKeyID = x509->get_subjectKeyIdentifier(x509);
if (subjectKeyID.ptr)
{
datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN);
snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf);
@@ -348,16 +334,10 @@ void load_crls(void)
CERT_PLUTO_CRL, BUILD_FROM_FILE, filename, BUILD_END);
if (crl)
{
chunk_t crl_uri;
char crl_uri[BUF_LEN];
plog(" loaded crl from '%s'", filename);
crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename);
crl_uri.ptr = malloc(crl_uri.len + 1);
/* build CRL file URI */
snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s"
, CRL_PATH, filename);
snprintf(crl_uri, BUF_LEN, "file://%s/%s", CRL_PATH, filename);
insert_crl(crl, crl_uri, FALSE);
}
free(filelist[n]);
@@ -543,8 +523,7 @@ check_revocation(const x509crl_t *crl, chunk_t serial
/*
* check if any crls are about to expire
*/
void
check_crls(void)
void check_crls(void)
{
x509crl_t *crl;
@@ -569,9 +548,9 @@ check_crls(void)
)
if (time_left < 2*crl_check_interval)
{
fetch_req_t *req = build_crl_fetch_request(crl->issuer
, crl->authKeySerialNumber
, crl->authKeyID, crl->distributionPoints);
fetch_req_t *req = build_crl_fetch_request(crl->issuer,
crl->authKeyID,
crl->distributionPoints);
add_crl_fetch_request(req);
}
crl = crl->next;
@@ -582,51 +561,63 @@ check_crls(void)
/*
* verify if a cert hasn't been revoked by a crl
*/
cert_status_t
verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
, crl_reason_t *revocationReason)
cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
time_t *revocationDate,
crl_reason_t *revocationReason)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *issuer = certificate->get_issuer(certificate);
chunk_t issuer_dn = issuer->get_encoding(issuer);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
x509crl_t *crl;
ca_info_t *ca;
enumerator_t *enumerator;
char *point;
ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
, cert->authKeyID);
generalName_t *crluri = (ca == NULL)? NULL : ca->crluri;
ca = get_ca_info(issuer_dn, authKeyID);
*revocationDate = UNDEFINED_TIME;
*revocationReason = CRL_REASON_UNSPECIFIED;
lock_crl_list("verify_by_crl");
crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID);
crl = get_x509crl(issuer_dn, authKeyID);
if (crl == NULL)
{
linked_list_t *crluris;
unlock_crl_list("verify_by_crl");
plog("crl not found");
if (cert->crlDistributionPoints != NULL)
crluris = linked_list_create();
if (ca)
{
fetch_req_t *req = build_crl_fetch_request(cert->issuer
, cert->authKeySerialNumber
, cert->authKeyID, cert->crlDistributionPoints);
add_crl_fetch_request(req);
add_distribution_points(crluris, ca->crluris);
}
if (crluri != NULL)
enumerator = x509->create_crl_uri_enumerator(x509);
while (enumerator->enumerate(enumerator, &point))
{
fetch_req_t *req = build_crl_fetch_request(cert->issuer
, cert->authKeySerialNumber
, cert->authKeyID, crluri);
add_crl_fetch_request(req);
add_distribution_point(crluris, point);
}
enumerator->destroy(enumerator);
if (cert->crlDistributionPoints != 0 || crluri != NULL)
if (crluris->get_count(crluris) > 0)
{
fetch_req_t *req;
req = build_crl_fetch_request(issuer_dn, authKeyID, crluris);
crluris->destroy_function(crluris, free);
add_crl_fetch_request(req);
wake_fetch_thread("verify_by_crl");
return CERT_UNKNOWN;
}
else
{
crluris->destroy(crluris);
return CERT_UNDEFINED;
}
}
else
{
@@ -637,18 +628,23 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
DBG_log("crl found")
)
add_distribution_points(cert->crlDistributionPoints
, &crl->distributionPoints);
if (ca)
{
add_distribution_points(crl->distributionPoints, ca->crluris);
}
add_distribution_points(crluri
, &crl->distributionPoints);
enumerator = x509->create_crl_uri_enumerator(x509);
while (enumerator->enumerate(enumerator, &point))
{
add_distribution_point(crl->distributionPoints, point);
}
enumerator->destroy(enumerator);
lock_authcert_list("verify_by_crl");
issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber
, crl->authKeyID, AUTH_CA);
issuer_cert = get_authcert(crl->issuer, crl->authKeyID, AUTH_CA);
valid = x509_check_signature(crl->tbsCertList, crl->signature,
crl->algorithm, issuer_cert);
crl->algorithm, issuer_cert->cert);
unlock_authcert_list("verify_by_crl");
@@ -663,7 +659,7 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
*until = crl->nextUpdate;
/* has the certificate been revoked? */
status = check_revocation(crl, cert->serialNumber, revocationDate
status = check_revocation(crl, x509->get_serial(x509), revocationDate
, revocationReason);
if (*until < time(NULL))
@@ -673,9 +669,8 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
plog("crl update is overdue since %T", until, TRUE);
/* try to fetch a crl update */
req = build_crl_fetch_request(crl->issuer
, crl->authKeySerialNumber
, crl->authKeyID, crl->distributionPoints);
req = build_crl_fetch_request(crl->issuer, crl->authKeyID,
crl->distributionPoints);
unlock_crl_list("verify_by_crl");
add_crl_fetch_request(req);
@@ -702,8 +697,7 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
/*
* list all X.509 crls in the chained list
*/
void
list_crls(bool utc, bool strict)
void list_crls(bool utc, bool strict)
{
x509crl_t *crl;
+3 -2
View File
@@ -14,6 +14,7 @@
#include "constants.h"
#include <utils/linked_list.h>
#include <credentials/certificates/crl.h>
/* access structure for a revoked serial number */
@@ -34,7 +35,7 @@ typedef struct x509crl x509crl_t;
struct x509crl {
x509crl_t *next;
time_t installed;
generalName_t *distributionPoints;
linked_list_t *distributionPoints;
chunk_t certificateList;
chunk_t tbsCertList;
u_int version;
@@ -80,7 +81,7 @@ extern const x509crl_t empty_x509crl;
extern bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl);
extern void load_crls(void);
extern void check_crls(void);
extern bool insert_crl(x509crl_t *crl, chunk_t 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
, time_t *revocationDate, crl_reason_t *revocationReason);
extern void list_crls(bool utc, bool strict);
+115 -104
View File
@@ -48,7 +48,6 @@ fetch_req_t empty_fetch_req = {
0 , /* trials */
{ NULL, 0}, /* issuer */
{ NULL, 0}, /* authKeyID */
{ NULL, 0}, /* authKeySerialNumber */
NULL /* distributionPoints */
};
@@ -251,10 +250,9 @@ void wake_fetch_thread(const char *who)
*/
static void free_fetch_request(fetch_req_t *req)
{
req->distributionPoints->destroy_function(req->distributionPoints, free);
free(req->issuer.ptr);
free(req->authKeySerialNumber.ptr);
free(req->authKeyID.ptr);
free_generalNames(req->distributionPoints, TRUE);
free(req);
}
@@ -286,47 +284,39 @@ x509crl_t* fetch_crl(char *url)
/**
* Complete a distributionPoint URI with ca information
*/
static char* complete_uri(chunk_t distPoint, const char *ldaphost)
static char* complete_uri(char *distPoint, const char *ldaphost)
{
char *uri;
char *ptr = distPoint.ptr;
size_t len = distPoint.len;
char *symbol = strchr(distPoint, ':');
char *symbol = memchr(ptr, ':', len);
if (symbol != NULL)
if (symbol)
{
size_t type_len = symbol - ptr;
int type_len = symbol - distPoint;
if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0)
if (type_len >= 4 && strncasecmp(distPoint, "ldap", 4) == 0)
{
ptr = symbol + 1;
len -= (type_len + 1);
char *ptr = symbol + 1;
int len = strlen(distPoint) - (type_len + 1);
if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
{
len -= 2;
symbol = memchr(ptr, '/', len);
symbol = strchr(ptr, '/');
if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL)
if (symbol && symbol - ptr == 0 && ldaphost)
{
uri = malloc(distPoint.len + strlen(ldaphost) + 1);
char uri[BUF_LEN];
/* insert the ldaphost into the uri */
sprintf(uri, "%.*s%s%.*s"
, (int)(distPoint.len - len), distPoint.ptr
, ldaphost
, (int)len, symbol);
return uri;
snprintf(uri, BUF_LEN, "%.*s%s%.*s", strlen(distPoint)-len,
distPoint, ldaphost, len, symbol);
return strdup(uri);
}
}
}
}
/* default action: copy distributionPoint without change */
uri = malloc(distPoint.len + 1);
sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr);
return uri;
return strdup(distPoint);
}
/**
@@ -343,40 +333,40 @@ static void fetch_crls(bool cache_crls)
while (req != NULL)
{
enumerator_t *enumerator;
char *point;
bool valid_crl = FALSE;
generalName_t *gn = req->distributionPoints;
const char *ldaphost;
ca_info_t *ca;
lock_ca_info_list("fetch_crls");
ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID);
ca = get_ca_info(req->issuer, req->authKeyID);
ldaphost = (ca == NULL)? NULL : ca->ldaphost;
while (gn != NULL)
enumerator = req->distributionPoints->create_enumerator(req->distributionPoints);
while (enumerator->enumerate(enumerator, &point))
{
char *uri = complete_uri(gn->name, ldaphost);
x509crl_t *crl;
char *uri;
uri = complete_uri(point, ldaphost);
crl = fetch_crl(uri);
free(uri);
if (crl)
{
chunk_t crl_uri = chunk_clone(gn->name);
if (insert_crl(crl, crl_uri, cache_crls))
if (insert_crl(crl, point, cache_crls))
{
DBG(DBG_CONTROL,
DBG_log("we have a valid crl")
)
valid_crl = TRUE;
free(uri);
break;
}
}
free(uri);
gn = gn->next;
}
enumerator->destroy(enumerator);
unlock_ca_info_list("fetch_crls");
if (valid_crl)
@@ -401,19 +391,11 @@ static void fetch_crls(bool cache_crls)
static void fetch_ocsp_status(ocsp_location_t* location)
{
chunk_t request, response;
char *uri;
chunk_t request = build_ocsp_request(location);
chunk_t response = chunk_empty;
request = build_ocsp_request(location);
response = chunk_empty;
/* we need a null terminated string for curl */
uri = malloc(location->uri.len + 1);
memcpy(uri, location->uri.ptr, location->uri.len);
*(uri + location->uri.len) = '\0';
DBG1(" requesting ocsp status from '%s' ...", uri);
if (lib->fetcher->fetch(lib->fetcher, uri, &response,
DBG1(" requesting ocsp status from '%s' ...", location->uri);
if (lib->fetcher->fetch(lib->fetcher, location->uri, &response,
FETCH_REQUEST_DATA, request,
FETCH_REQUEST_TYPE, "application/ocsp-request",
FETCH_END) == SUCCESS)
@@ -422,10 +404,9 @@ static void fetch_ocsp_status(ocsp_location_t* location)
}
else
{
DBG1("ocsp request to %s failed", uri);
DBG1("ocsp request to %s failed", location->uri);
}
free(uri);
free(request.ptr);
chunk_free(&location->nonce);
@@ -554,62 +535,95 @@ void free_ocsp_fetch(void)
/**
* Add additional distribution points
* Add an additional distribution point
*/
void add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints)
void add_distribution_point(linked_list_t *points, char *new_point)
{
while (newPoints != NULL)
char *point;
bool add = TRUE;
enumerator_t *enumerator;
if (new_point == NULL || *new_point == '\0')
{
/* skip empty distribution point */
if (newPoints->name.len > 0)
return;
}
enumerator = points->create_enumerator(points);
while (enumerator->enumerate(enumerator, &point))
{
if (streq(point, new_point))
{
bool add = TRUE;
generalName_t *gn = *distributionPoints;
while (gn != NULL)
{
if (gn->kind == newPoints->kind
&& gn->name.len == newPoints->name.len
&& memeq(gn->name.ptr, newPoints->name.ptr, gn->name.len))
{
/* skip if the distribution point is already present */
add = FALSE;
break;
}
gn = gn->next;
}
if (add)
{
/* clone additional distribution point */
gn = clone_thing(*newPoints);
gn->name = chunk_clone(newPoints->name);
/* insert additional CRL distribution point */
gn->next = *distributionPoints;
*distributionPoints = gn;
}
add = FALSE;
break;
}
newPoints = newPoints->next;
}
enumerator->destroy(enumerator);
if (add)
{
points->insert_last(points, strdup(new_point));
}
}
fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber,
chunk_t authKeyID, const generalName_t *gn)
/**
* Add additional distribution points
*/
void add_distribution_points(linked_list_t *points, linked_list_t *new_points)
{
char *new_point;
enumerator_t *enumerator;
enumerator = new_points->create_enumerator(new_points);
while (enumerator->enumerate(enumerator, &new_point))
{
bool add = TRUE;
char *point;
enumerator_t *enumerator;
enumerator = points->create_enumerator(points);
while (enumerator->enumerate(enumerator, &point))
{
if (streq(point, new_point))
{
add = FALSE;
break;
}
}
enumerator->destroy(enumerator);
if (add)
{
points->insert_last(points, strdup(new_point));
}
}
enumerator->destroy(enumerator);
}
fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeyID,
linked_list_t *distributionPoints)
{
char *point;
enumerator_t *enumerator;
fetch_req_t *req = malloc_thing(fetch_req_t);
*req = empty_fetch_req;
memset(req, 0, sizeof(fetch_req_t));
req->distributionPoints = linked_list_create();
/* note current time */
req->installed = time(NULL);
/* clone fields */
req->issuer = chunk_clone(issuer);
req->authKeySerialNumber = chunk_clone(authKeySerialNumber);
req->authKeyID = chunk_clone(authKeyID);
/* copy distribution points */
add_distribution_points(gn, &req->distributionPoints);
enumerator = distributionPoints->create_enumerator(distributionPoints);
while (enumerator->enumerate(enumerator, &point))
{
req->distributionPoints->insert_last(req->distributionPoints,
strdup(point));
}
enumerator->destroy(enumerator);
return req;
}
@@ -626,9 +640,8 @@ void add_crl_fetch_request(fetch_req_t *req)
while (r != NULL)
{
if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID)
: (same_dn(req->issuer, r->issuer)
&& same_serial(req->authKeySerialNumber, r->authKeySerialNumber)))
if (req->authKeyID.ptr ? same_keyid(req->authKeyID, r->authKeyID) :
same_dn(req->issuer, r->issuer))
{
/* there is already a fetch request */
DBG(DBG_CONTROL,
@@ -636,7 +649,8 @@ void add_crl_fetch_request(fetch_req_t *req)
)
/* there might be new distribution points */
add_distribution_points(req->distributionPoints, &r->distributionPoints);
add_distribution_points(r->distributionPoints,
req->distributionPoints);
unlock_crl_fetch_list("add_crl_fetch_request");
free_fetch_request(req);
@@ -672,17 +686,20 @@ void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
/**
* List all distribution points
*/
void list_distribution_points(const generalName_t *gn)
void list_distribution_points(linked_list_t *distributionPoints)
{
bool first_gn = TRUE;
char *point;
bool first_point = TRUE;
enumerator_t *enumerator;
while (gn != NULL)
enumerator = distributionPoints->create_enumerator(distributionPoints);
while (enumerator->enumerate(enumerator, &point))
{
whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: "
:" ", (int)gn->name.len, gn->name.ptr);
first_gn = FALSE;
gn = gn->next;
whack_log(RC_COMMENT, " %s '%s'",
(first_point)? "distPts: " : " ", point);
first_point = FALSE;
}
enumerator->destroy(enumerator);
}
/**
@@ -716,12 +733,6 @@ void list_crl_fetch_requests(bool utc)
, buf, BUF_LEN);
whack_log(RC_COMMENT, " authkey: %s", buf);
}
if (req->authKeySerialNumber.ptr != NULL)
{
datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':'
, buf, BUF_LEN);
whack_log(RC_COMMENT, " aserial: %s", buf);
}
list_distribution_points(req->distributionPoints);
req = req->next;
}
+11 -8
View File
@@ -13,6 +13,8 @@
* for more details.
*/
#include <utils/linked_list.h>
#include "x509.h"
#define FETCH_CMD_TIMEOUT 10 /* seconds */
@@ -32,8 +34,7 @@ struct fetch_req {
int trials;
chunk_t issuer;
chunk_t authKeyID;
chunk_t authKeySerialNumber;
generalName_t *distributionPoints;
linked_list_t *distributionPoints;
};
#ifdef THREADS
@@ -64,13 +65,15 @@ extern void wake_fetch_thread(const char *who);
extern void init_fetch(void);
extern void free_crl_fetch(void);
extern void free_ocsp_fetch(void);
extern void add_distribution_points(const generalName_t *newPoints
, generalName_t **distributionPoints);
extern fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber
, chunk_t authKeyID, const generalName_t *gn);
extern void add_distribution_point(linked_list_t *points, char* new_point);
extern void add_distribution_points(linked_list_t *points,
linked_list_t *new_points);
extern fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeyID,
linked_list_t *distributionPoints);
extern void add_crl_fetch_request(fetch_req_t *req);
extern void add_ocsp_fetch_request(struct ocsp_location *location, chunk_t serialNumber);
extern void list_distribution_points(const generalName_t *gn);
extern void add_ocsp_fetch_request(struct ocsp_location *location,
chunk_t serialNumber);
extern void list_distribution_points(linked_list_t *distributionPoints);
extern void list_crl_fetch_requests(bool utc);
extern void list_ocsp_fetch_requests(bool utc);
extern size_t write_buffer(void *ptr, size_t size, size_t nmemb, void *data);
+48 -34
View File
@@ -44,8 +44,7 @@ char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */
/* initialize id module
* Fills in myid from environment variable IPSECmyid or defaultrouteaddr
*/
void
init_id(void)
void init_id(void)
{
passert(empty_id.kind == ID_ANY);
myid_state = MYID_UNKNOWN;
@@ -66,8 +65,7 @@ init_id(void)
/*
* free id module
*/
void
free_id(void)
void free_id(void)
{
enum myid_state s;
@@ -78,8 +76,7 @@ free_id(void)
}
}
static void
calc_myid_str(enum myid_state s)
static void calc_myid_str(enum myid_state s)
{
/* preformat the ID name */
char buf[BUF_LEN];
@@ -89,8 +86,7 @@ calc_myid_str(enum myid_state s)
}
void
set_myid(enum myid_state s, char *idstr)
void set_myid(enum myid_state s, char *idstr)
{
if (idstr != NULL)
{
@@ -114,8 +110,7 @@ set_myid(enum myid_state s, char *idstr)
}
}
void
set_myFQDN(void)
void set_myFQDN(void)
{
char FQDN[HOST_NAME_MAX + 1];
int r = gethostname(FQDN, sizeof(FQDN));
@@ -151,8 +146,7 @@ set_myFQDN(void)
}
}
void
show_myid_status(void)
void show_myid_status(void)
{
char idstr[BUF_LEN];
@@ -163,8 +157,7 @@ show_myid_status(void)
/* Convert textual form of id into a (temporary) struct id.
* Note that if the id is to be kept, unshare_id_content will be necessary.
*/
err_t
atoid(char *src, struct id *id, bool myid_ok)
err_t atoid(char *src, struct id *id, bool myid_ok)
{
err_t ugh = NULL;
@@ -252,15 +245,13 @@ atoid(char *src, struct id *id, bool myid_ok)
/*
* Converts a binary key ID into hexadecimal format
*/
int
keyidtoa(char *dst, size_t dstlen, chunk_t keyid)
int keyidtoa(char *dst, size_t dstlen, chunk_t keyid)
{
int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen);
return (((size_t)n < dstlen)? n : dstlen) - 1;
}
void
iptoid(const ip_address *ip, struct id *id)
void iptoid(const ip_address *ip, struct id *id)
{
*id = empty_id;
@@ -278,8 +269,7 @@ iptoid(const ip_address *ip, struct id *id)
id->ip_addr = *ip;
}
int
idtoa(const struct id *id, char *dst, size_t dstlen)
int idtoa(const struct id *id, char *dst, size_t dstlen)
{
int n;
@@ -326,8 +316,7 @@ idtoa(const struct id *id, char *dst, size_t dstlen)
/* Replace the shell metacharacters ', \, ", `, and $ in a character string
* by escape sequences consisting of their octal values
*/
void
escape_metachar(const char *src, char *dst, size_t dstlen)
void escape_metachar(const char *src, char *dst, size_t dstlen)
{
while (*src != '\0' && dstlen > 4)
{
@@ -355,8 +344,7 @@ escape_metachar(const char *src, char *dst, size_t dstlen)
/* Make private copy of string in struct id.
* This is needed if the result of atoid is to be kept.
*/
void
unshare_id_content(struct id *id)
void unshare_id_content(struct id *id)
{
switch (id->kind)
{
@@ -376,8 +364,7 @@ unshare_id_content(struct id *id)
}
}
void
free_id_content(struct id *id)
void free_id_content(struct id *id)
{
switch (id->kind)
{
@@ -398,8 +385,7 @@ free_id_content(struct id *id)
}
/* compare two struct id values */
bool
same_id(const struct id *a, const struct id *b)
bool same_id(const struct id *a, const struct id *b)
{
a = resolve_myid(a);
b = resolve_myid(b);
@@ -446,8 +432,7 @@ same_id(const struct id *a, const struct id *b)
}
/* compare two struct id values, DNs can contain wildcards */
bool
match_id(const struct id *a, const struct id *b, int *wildcards)
bool match_id(const struct id *a, const struct id *b, int *wildcards)
{
if (b->kind == ID_ANY)
{
@@ -466,8 +451,7 @@ match_id(const struct id *a, const struct id *b, int *wildcards)
}
/* count the numer of wildcards in an id */
int
id_count_wildcards(const struct id *id)
int id_count_wildcards(const struct id *id)
{
switch (id->kind)
{
@@ -485,8 +469,7 @@ id_count_wildcards(const struct id *id)
* We assume it will end up being a pointer into a sufficiently
* stable datastructure. It only needs to last a short time.
*/
void
build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
{
const struct id *id = resolve_myid(&end->id);
@@ -515,6 +498,37 @@ build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
}
}
/**
* Converts libstrongswan's identification_t type into pluto's struct id
*/
void id_from_identification(struct id *id, identification_t *identification)
{
chunk_t encoding;
encoding = identification->get_encoding(identification);
id->kind = identification->get_type(identification);
switch (id->kind)
{
case ID_FQDN:
case ID_USER_FQDN:
case ID_DER_ASN1_DN:
case ID_KEY_ID:
id->name = encoding;
break;
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
initaddr(encoding.ptr, encoding.len,
(id->kind == ID_IPV4_ADDR) ? AF_INET : AF_INET6,
&id->ip_addr);
break;
case ID_ANY:
default:
id->kind = ID_ANY;
id->name = chunk_empty;
}
}
/*
* Local Variables:
* c-basic-offset:4
+6 -3
View File
@@ -15,6 +15,8 @@
#ifndef _ID_H
#define _ID_H
#include <utils/identification.h>
#include "defs.h"
struct id {
@@ -26,7 +28,7 @@ struct id {
extern void init_id(void);
extern void free_id(void);
extern const struct id empty_id; /* ID_NONE */
extern const struct id empty_id; /* ID_ANY */
enum myid_state {
MYID_UNKNOWN, /* not yet figured out */
@@ -59,7 +61,8 @@ extern int id_count_wildcards(const struct id *id);
#define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR)
struct isakmp_ipsec_id; /* forward declaration of tag (defined in packet.h) */
extern void
build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end);
extern void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl,
struct end *end);
extern void id_from_identification(struct id *id, identification_t *identification);
#endif /* _ID_H */
+22 -8
View File
@@ -2149,8 +2149,14 @@ static void decode_cert(struct msg_digest *md)
if (cert->isacert_type == CERT_X509_SIGNATURE)
{
x509cert_t cert = empty_x509cert;
if (parse_x509cert(blob, 0, &cert))
cert.cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (cert.cert)
{
time(&cert.installed);
if (verify_x509cert(&cert, strict_crl_policy, &valid_until))
{
DBG(DBG_PARSING,
@@ -2162,9 +2168,7 @@ static void decode_cert(struct msg_digest *md)
{
plog("X.509 certificate rejected");
}
DESTROY_IF(cert.public_key);
free_generalNames(cert.subjectAltName, FALSE);
free_generalNames(cert.crlDistributionPoints, FALSE);
DESTROY_IF(cert.cert);
}
else
{
@@ -3556,6 +3560,8 @@ stf_status main_inR2_outI3(struct msg_digest *md)
}
if (send_cert)
{
bool success;
chunk_t cert_encoding;
pb_stream cert_pbs;
struct isakmp_cert cert_hd;
@@ -3566,7 +3572,10 @@ stf_status main_inR2_outI3(struct msg_digest *md)
{
return STF_INTERNAL_ERROR;
}
if (!out_chunk(cert_get_encoding(mycert), &cert_pbs, "CERT"))
cert_encoding = cert_get_encoding(mycert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr);
if (!success)
{
return STF_INTERNAL_ERROR;
}
@@ -3996,9 +4005,11 @@ main_inI3_outR3_tail(struct msg_digest *md
}
if (send_cert)
{
bool success;
chunk_t cert_encoding;
pb_stream cert_pbs;
struct isakmp_cert cert_hd;
cert_hd.isacert_np = ISAKMP_NEXT_SIG;
cert_hd.isacert_type = mycert.type;
@@ -4006,8 +4017,11 @@ main_inI3_outR3_tail(struct msg_digest *md
{
return STF_INTERNAL_ERROR;
}
if (!out_chunk(cert_get_encoding(mycert), &cert_pbs, "CERT"))
{
cert_encoding = cert_get_encoding(mycert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr);
if (!success)
{
return STF_INTERNAL_ERROR;
}
close_output_pbs(&cert_pbs);
+34 -22
View File
@@ -127,6 +127,7 @@ static const secret_t* get_secret(const struct connection *c,
break; /* we have found the private key - no sense in searching further */
}
}
pub_key->destroy(pub_key);
return best;
}
@@ -277,6 +278,7 @@ bool has_private_key(cert_t cert)
break;
}
}
pub_key->destroy(pub_key);
return has_key;
}
@@ -285,17 +287,22 @@ bool has_private_key(cert_t cert)
*/
private_key_t* get_x509_private_key(const x509cert_t *cert)
{
public_key_t *public_key = cert->cert->get_public_key(cert->cert);
private_key_t *private_key = NULL;
secret_t *s;
for (s = secrets; s != NULL; s = s->next)
{
if (s->kind == PPK_PUBKEY &&
s->u.private_key->belongs_to(s->u.private_key, cert->public_key))
s->u.private_key->belongs_to(s->u.private_key, public_key))
{
return s->u.private_key;
private_key = s->u.private_key;
break;
}
}
return NULL;
public_key->destroy(public_key);
return private_key;
}
/* find the appropriate private key (see get_secret).
@@ -1231,7 +1238,7 @@ void delete_public_keys(const struct id *id, key_type_t type,
if (same_id(id, &pk->id) && pk_type == type
&& (issuer.ptr == NULL || pk->issuer.ptr == NULL
|| same_dn(issuer, pk->issuer))
&& same_serial(serial, pk->serial))
&& (serial.ptr == NULL || chunk_equals(serial, pk->serial)))
{
*pp = free_public_keyentry(p);
}
@@ -1317,46 +1324,50 @@ bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
void add_x509_public_key(x509cert_t *cert , time_t until,
enum dns_auth_level dns_auth_level)
{
generalName_t *gn;
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
identification_t *id;
chunk_t issuer_dn = issuer->get_encoding(issuer);
chunk_t serialNumber = x509->get_serial(x509);
pubkey_t *pk;
key_type_t pk_type;
enumerator_t *enumerator;
/* ID type: ID_DER_ASN1_DN (X.509 subject field) */
pk = malloc_thing(pubkey_t);
zero(pk);
pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->public_key = cert->cert->get_public_key(cert->cert);
pk->id.kind = ID_DER_ASN1_DN;
pk->id.name = cert->subject;
pk->id.name = subject->get_encoding(subject);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = cert->issuer;
pk->serial = cert->serialNumber;
pk->issuer = issuer_dn;
pk->serial = serialNumber;
pk_type = pk->public_key->get_type(pk->public_key);
delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
gn = cert->subjectAltName;
while (gn != NULL) /* insert all subjectAltNames */
/* insert all subjectAltNames */
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &id))
{
struct id id = empty_id;
gntoid(&id, gn);
if (id.kind != ID_ANY)
if (id->get_type(id) != ID_ANY)
{
pk = malloc_thing(pubkey_t);
zero(pk);
pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->id = id;
id_from_identification(&pk->id, id);
pk->public_key = cert->cert->get_public_key(cert->cert);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = cert->issuer;
pk->serial = cert->serialNumber;
pk->issuer = issuer_dn;
pk->serial = serialNumber;
delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
}
gn = gn->next;
}
enumerator->destroy(enumerator);
}
/* extract id and public key from OpenPGP certificate and
@@ -1385,7 +1396,7 @@ void add_pgp_public_key(pgpcert_t *cert , time_t until,
*/
void remove_x509_public_key(const x509cert_t *cert)
{
public_key_t *revoked_key = cert->public_key;
public_key_t *revoked_key = cert->cert->get_public_key(cert->cert);
pubkey_list_t *p, **pp;
p = pubkeys;
@@ -1405,6 +1416,7 @@ void remove_x509_public_key(const x509cert_t *cert)
}
p =*pp;
}
revoked_key->destroy(revoked_key);
}
/*
+83 -68
View File
@@ -283,18 +283,29 @@ static const asn1Object_t singleResponseObjects[] = {
*/
static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location)
{
certificate_t *certificate = cert->cert;
identification_t *issuer = certificate->get_issuer(certificate);
x509_t *x509 = (x509_t*)certificate;
chunk_t issuer_dn = issuer->get_encoding(issuer);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
hasher_t *hasher;
static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */
location->uri = cert->accessLocation;
enumerator_t *enumerator = x509->create_ocsp_uri_enumerator(x509);
if (location->uri.ptr == NULL)
location->uri = NULL;
while (enumerator->enumerate(enumerator, &location->uri))
{
ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
, cert->authKeyID);
break;
}
enumerator->destroy(enumerator);
if (location->uri == NULL)
{
ca_info_t *ca = get_ca_info(issuer_dn, authKeyID);
if (ca != NULL && ca->ocspuri != NULL)
{
location->uri = chunk_create(ca->ocspuri, strlen(ca->ocspuri));
location->uri = ca->ocspuri;
}
else
{ /* abort if no ocsp location uri is defined */
@@ -309,23 +320,22 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
{
return FALSE;
}
hasher->get_hash(hasher, cert->issuer, digest);
hasher->get_hash(hasher, issuer_dn, digest);
hasher->destroy(hasher);
location->next = NULL;
location->issuer = cert->issuer;
location->authKeyID = cert->authKeyID;
location->authKeySerialNumber = cert->authKeySerialNumber;
location->issuer = issuer_dn;
location->authKeyID = authKeyID;
if (cert->authKeyID.ptr == NULL)
if (authKeyID.ptr == NULL)
{
x509cert_t *authcert = get_authcert(cert->issuer
, cert->authKeySerialNumber, cert->authKeyID, AUTH_CA);
x509cert_t *authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
if (authcert != NULL)
{
location->authKeyID = authcert->subjectKeyID;
location->authKeySerialNumber = authcert->serialNumber;
x509_t *x509 = (x509_t*)authcert->cert;
location->authKeyID = x509->get_subjectKeyIdentifier(x509);
}
}
@@ -342,9 +352,8 @@ static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *
{
return ((a->authKeyID.ptr != NULL)
? same_keyid(a->authKeyID, b->authKeyID)
: (same_dn(a->issuer, b->issuer)
&& same_serial(a->authKeySerialNumber, b->authKeySerialNumber)))
&& chunk_equals(a->uri, b->uri);
: same_dn(a->issuer, b->issuer))
&& streq(a->uri, b->uri);
}
/**
@@ -411,6 +420,8 @@ cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until,
time_t *revocationDate,
crl_reason_t *revocationReason)
{
x509_t *x509 = (x509_t*)cert->cert;
chunk_t serialNumber = x509->get_serial(x509);
cert_status_t status;
ocsp_location_t location;
time_t nextUpdate = 0;
@@ -420,17 +431,19 @@ cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until,
/* is an ocsp location defined? */
if (!build_ocsp_location(cert, &location))
{
return CERT_UNDEFINED;
}
lock_ocsp_cache("verify_by_ocsp");
status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate
status = get_ocsp_status(&location, serialNumber, &nextUpdate
, revocationDate, revocationReason);
unlock_ocsp_cache("verify_by_ocsp");
if (status == CERT_UNDEFINED || nextUpdate < time(NULL))
{
plog("ocsp status is stale or not in cache");
add_ocsp_fetch_request(&location, cert->serialNumber);
add_ocsp_fetch_request(&location, serialNumber);
/* inititate fetching of ocsp status */
wake_fetch_thread("verify_by_ocsp");
@@ -521,8 +534,7 @@ static void free_ocsp_location(ocsp_location_t* location)
free(location->issuer.ptr);
free(location->authNameID.ptr);
free(location->authKeyID.ptr);
free(location->authKeySerialNumber.ptr);
free(location->uri.ptr);
free(location->uri);
free_certinfos(location->certinfo);
free(location);
}
@@ -588,8 +600,7 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests,
dntoa(buf, BUF_LEN, location->issuer);
whack_log(RC_COMMENT, " issuer: '%s'", buf);
}
whack_log(RC_COMMENT, " uri: '%.*s'", (int)location->uri.len
, location->uri.ptr);
whack_log(RC_COMMENT, " uri: '%s'", location->uri);
if (location->authNameID.ptr != NULL)
{
datatot(location->authNameID.ptr, location->authNameID.len, ':'
@@ -602,12 +613,6 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests,
, buf, BUF_LEN);
whack_log(RC_COMMENT, " authkey: %s", buf);
}
if (location->authKeySerialNumber.ptr != NULL)
{
datatot(location->authKeySerialNumber.ptr
, location->authKeySerialNumber.len, ':', buf, BUF_LEN);
whack_log(RC_COMMENT, " aserial: %s", buf);
}
while (certinfo != NULL)
{
char thisUpdate[BUF_LEN];
@@ -662,17 +667,17 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
for (;;)
{
char buf[BUF_LEN];
certificate_t *certificate;
/* looking for a certificate from the same issuer */
cert = get_x509cert(location->issuer, location->authKeySerialNumber
,location->authKeyID, cert);
cert = get_x509cert(location->issuer, location->authKeyID, cert);
if (cert == NULL)
{
break;
}
certificate = cert->cert;
DBG(DBG_CONTROL,
dntoa(buf, BUF_LEN, cert->subject);
DBG_log("candidate: '%s'", buf);
DBG_log("candidate: '%Y'", certificate->get_subject(certificate));
)
if (cert->smartcard)
@@ -774,7 +779,7 @@ static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
*/
static chunk_t build_signature(chunk_t tbsRequest)
{
chunk_t sigdata, certs;
chunk_t sigdata, cert, certs;
if (ocsp_requestor_sc != NULL)
{
@@ -793,11 +798,9 @@ static chunk_t build_signature(chunk_t tbsRequest)
}
/* include our certificate */
certs = asn1_wrap(ASN1_CONTEXT_C_0, "m"
, asn1_simple_object(ASN1_SEQUENCE
, ocsp_requestor_cert->certificate
)
);
cert = ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert);
certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
asn1_wrap(ASN1_SEQUENCE, "m", cert));
/* build signature comprising algorithm, signature and cert */
return asn1_wrap(ASN1_CONTEXT_C_0, "m"
@@ -872,9 +875,12 @@ static chunk_t build_request_list(ocsp_location_t *location)
*/
static chunk_t build_requestor_name(void)
{
certificate_t *certificate = ocsp_requestor_cert->cert;
identification_t *subject = certificate->get_subject(certificate);
return asn1_wrap(ASN1_CONTEXT_C_1, "m"
, asn1_simple_object(ASN1_CONTEXT_C_4
, ocsp_requestor_cert->subject));
, subject->get_encoding(subject)));
}
/**
@@ -976,9 +982,8 @@ static bool valid_ocsp_response(response_t *res)
lock_authcert_list("valid_ocsp_response");
authcert = get_authcert(res->responder_id_name, chunk_empty
, res->responder_id_key, AUTH_OCSP | AUTH_CA);
authcert = get_authcert(res->responder_id_name, res->responder_id_key,
AUTH_OCSP | AUTH_CA);
if (authcert == NULL)
{
plog("no matching ocsp signer cert found");
@@ -989,7 +994,8 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("ocsp signer cert found")
)
if (!x509_check_signature(res->tbs, res->signature, res->algorithm, authcert))
if (!x509_check_signature(res->tbs, res->signature, res->algorithm,
authcert->cert))
{
plog("signature of ocsp response is invalid");
unlock_authcert_list("valid_ocsp_response");
@@ -1002,22 +1008,22 @@ static bool valid_ocsp_response(response_t *res)
for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
{
u_char buf[BUF_LEN];
err_t ugh = NULL;
time_t until;
x509cert_t *cert = authcert;
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
DBG(DBG_CONTROL,
dntoa(buf, BUF_LEN, cert->subject);
DBG_log("subject: '%s'",buf);
dntoa(buf, BUF_LEN, cert->issuer);
DBG_log("issuer: '%s'",buf);
if (cert->authKeyID.ptr != NULL)
DBG_log("subject: '%Y'", subject);
DBG_log("issuer: '%Y'", issuer);
if (authKeyID.ptr != NULL)
{
datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
, buf, BUF_LEN);
DBG_log("authkey: %s", buf);
DBG_log("authkey: %#B", &authKeyID);
}
)
@@ -1034,9 +1040,7 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("certificate is valid")
)
authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
, cert->authKeyID, AUTH_CA);
authcert = get_authcert(issuer->get_encoding(issuer), authKeyID, AUTH_CA);
if (authcert == NULL)
{
plog("issuer cacert not found");
@@ -1047,8 +1051,7 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("issuer cacert found")
)
if (!x509_check_signature(cert->tbsCertificate, cert->signature,
cert->algorithm, authcert))
if (!certificate->issued_by(certificate, authcert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("valid_ocsp_response");
@@ -1059,7 +1062,7 @@ static bool valid_ocsp_response(response_t *res)
)
/* check if cert is self-signed */
if (same_dn(cert->issuer, cert->subject))
if (x509->get_flags(x509) & X509_SELF_SIGNED)
{
DBG(DBG_CONTROL,
DBG_log("reached self-signed root ca")
@@ -1143,14 +1146,27 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
break;
case BASIC_RESPONSE_CERTIFICATE:
{
chunk_t blob = chunk_clone(object);
x509cert_t *cert = malloc_thing(x509cert_t);
x509_t *x509;
*cert = empty_x509cert;
if (parse_x509cert(blob, parser->get_level(parser)+1, cert)
&& cert->isOcspSigner
&& trust_authcert_candidate(cert, NULL))
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object,
BUILD_END);
if (cert->cert == NULL)
{
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("parsing of embedded ocsp certificate failed")
)
free_x509cert(cert);
break;
}
time(&cert->installed);
x509 = (x509_t*)cert->cert;
if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
trust_authcert_candidate(cert, NULL))
{
add_authcert(cert, AUTH_OCSP);
}
@@ -1322,8 +1338,7 @@ ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc,
location->issuer = chunk_clone(loc->issuer);
location->authNameID = chunk_clone(loc->authNameID);
location->authKeyID = chunk_clone(loc->authKeyID);
location->authKeySerialNumber = chunk_clone(loc->authKeySerialNumber);
location->uri = chunk_clone(loc->uri);
location->uri = strdup(loc->uri);
location->certinfo = NULL;
/* insert new ocsp location in front of chain */
+1 -2
View File
@@ -57,9 +57,8 @@ struct ocsp_location {
chunk_t issuer;
chunk_t authNameID;
chunk_t authKeyID;
chunk_t authKeySerialNumber;
chunk_t uri;
chunk_t nonce;
char *uri;
ocsp_certinfo_t *certinfo;
};
+53 -25
View File
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <freeswan.h>
@@ -202,7 +203,7 @@ end:
* Parse a PKCS#7 signedData object
*/
bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert,
chunk_t *attributes, const x509cert_t *cacert)
chunk_t *attributes, certificate_t *cacert)
{
u_char buf[BUF_LEN];
asn1_parser_t *parser;
@@ -252,14 +253,17 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
case PKCS7_SIGNED_CERT:
if (cert != NULL)
{
chunk_t cert_blob = chunk_clone(object);
x509cert_t *newcert = malloc_thing(x509cert_t);
*newcert = empty_x509cert;
DBG2(" parsing pkcs7-wrapped certificate");
if (parse_x509cert(cert_blob, level+1, newcert))
*newcert = empty_x509cert;
newcert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object,
BUILD_END);
if (newcert->cert)
{
time(&newcert->installed);
newcert->next = *cert;
*cert = newcert;
}
@@ -308,9 +312,15 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
/* check the signature only if a cacert is available */
if (cacert != NULL)
{
public_key_t *key = cacert->public_key;
signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
public_key_t *key;
signature_scheme_t scheme;
scheme = signature_scheme_from_oid(digest_alg);
if (scheme == SIGN_UNKNOWN)
{
DBG1("unsupported signature scheme");
return FALSE;
}
if (signerInfos == 0)
{
DBG1("no signerInfo object found");
@@ -332,11 +342,11 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
return FALSE;
}
/* determine signature scheme */
scheme = signature_scheme_from_oid(digest_alg);
if (scheme == SIGN_UNKNOWN)
/* verify the signature */
key = cacert->get_public_key(cacert);
if (key == NULL)
{
DBG1("no public key found in CA certificate");
return FALSE;
}
if (key->verify(key, scheme, *attributes, encrypted_digest))
@@ -346,10 +356,11 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
else
{
DBG1("invalid signature");
return FALSE;
success = FALSE;
}
key->destroy(key);
}
return TRUE;
return success;
}
/**
@@ -629,18 +640,21 @@ static chunk_t pkcs7_build_contentInfo(contentInfo_t *cInfo)
/**
* build issuerAndSerialNumber object
*/
chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert)
chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
{
return asn1_wrap(ASN1_SEQUENCE, "cm"
, cert->issuer
, asn1_integer("c", cert->serialNumber));
identification_t *issuer = cert->get_issuer(cert);
x509_t *x509 = (x509_t*)cert;
return asn1_wrap(ASN1_SEQUENCE, "cm",
issuer->get_encoding(issuer),
asn1_integer("c", x509->get_serial(x509)));
}
/**
* create a signed pkcs7 contentInfo object
*/
chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
const x509cert_t *cert, int digest_alg,
certificate_t *cert, int digest_alg,
private_key_t *key)
{
contentInfo_t pkcs7Data, signedData;
@@ -677,7 +691,7 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
, ASN1_INTEGER_1
, asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg))
, pkcs7_build_contentInfo(&pkcs7Data)
, asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate)
, asn1_wrap(ASN1_CONTEXT_C_0, "m", cert->get_encoding(cert))
, asn1_wrap(ASN1_SET, "m", signerInfo));
cInfo = pkcs7_build_contentInfo(&signedData);
@@ -691,7 +705,7 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
/**
* create a symmetrically encrypted pkcs7 contentInfo object
*/
chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_alg)
chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg)
{
encryption_algorithm_t alg;
size_t alg_key_size;
@@ -744,9 +758,24 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
crypter->set_key(crypter, symmetricKey);
crypter->encrypt(crypter, in, iv, &out);
crypter->destroy(crypter);
chunk_clear(&in);
DBG3("encrypted data %B", &out);
cert->public_key->encrypt(cert->public_key, symmetricKey, &protectedKey);
/* protect symmetric key by public key encryption */
{
public_key_t *key = cert->get_public_key(cert);
if (key == NULL)
{
DBG1("public key not found in encryption certificate");
chunk_clear(&symmetricKey);
chunk_free(&iv);
chunk_free(&out);
return chunk_empty;
}
key->encrypt(key, symmetricKey, &protectedKey);
key->destroy(key);
}
/* build pkcs7 enveloped data object */
{
@@ -781,10 +810,9 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
cInfo = pkcs7_build_contentInfo(&envelopedData);
DBG3("envelopedData %B", &cInfo);
free(envelopedData.content.ptr);
free(symmetricKey.ptr);
free(in.ptr);
free(iv.ptr);
chunk_free(&envelopedData.content);
chunk_free(&iv);
chunk_clear(&symmetricKey);
return cInfo;
}
}
+10 -7
View File
@@ -20,6 +20,7 @@
#include <crypto/crypters/crypter.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/certificate.h>
#include "defs.h"
#include "x509.h"
@@ -35,17 +36,19 @@ struct contentInfo {
extern const contentInfo_t empty_contentInfo;
extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
contentInfo_t *cInfo);
contentInfo_t *cInfo);
extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert);
x509cert_t **cert, chunk_t *attributes,
certificate_t *cacert);
extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
chunk_t serialNumber, private_key_t *key);
chunk_t serialNumber, private_key_t *key);
extern chunk_t pkcs7_contentType_attribute(void);
extern chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg);
extern chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert);
extern chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert);
extern chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
const x509cert_t *cert, int digest_alg, private_key_t *key);
extern chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert,
int enc_alg);
certificate_t *cert, int digest_alg,
private_key_t *key);
extern chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert,
int enc_alg);
#endif /* _PKCS7_H */
+45 -76
View File
@@ -386,8 +386,7 @@ static enum_names pkcs11_return_names =
* The calling application is responsible for cleaning up
* and calling C_Finalize()
*/
static CK_RV
scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
static CK_RV scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
{
if (!mod || mod->_magic != SCX_MAGIC)
return CKR_ARGUMENTS_BAD;
@@ -400,8 +399,8 @@ scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
return CKR_OK;
}
static scx_pkcs11_module_t*
scx_load_pkcs11_module(const char *name, CK_FUNCTION_LIST_PTR_PTR funcs)
static scx_pkcs11_module_t* scx_load_pkcs11_module(const char *name,
CK_FUNCTION_LIST_PTR_PTR funcs)
{
CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
scx_pkcs11_module_t *mod;
@@ -437,9 +436,9 @@ failed: scx_unload_pkcs11_module(mod);
/*
* retrieve a certificate object
*/
static bool
scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
, smartcard_t *sc, cert_t *cert)
static bool scx_find_cert_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object,
smartcard_t *sc, cert_t *cert)
{
size_t hex_len, label_len;
u_char *hex_id = NULL;
@@ -518,8 +517,7 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
/*
* search a given slot for PKCS#11 certificate objects
*/
static void
scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
CK_RV rv;
CK_OBJECT_CLASS class = CKO_CERTIFICATE;
@@ -616,8 +614,7 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
/*
* search all slots for PKCS#11 certificate objects
*/
static void
scx_find_all_cert_objects(void)
static void scx_find_all_cert_objects(void)
{
CK_RV rv;
CK_SLOT_ID_PTR slots = NULL_PTR;
@@ -696,8 +693,7 @@ scx_find_all_cert_objects(void)
* init_args should be unused when we have a PKCS#11 compliant module,
* but NSS softoken breaks that API.
*/
void
scx_init(const char* module, const char *init_args)
void scx_init(const char* module, const char *init_args)
{
#ifdef SMARTCARD
CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, };
@@ -752,8 +748,7 @@ scx_init(const char* module, const char *init_args)
/*
* finalize and unload PKCS#11 cryptoki module
*/
void
scx_finalize(void)
void scx_finalize(void)
{
#ifdef SMARTCARD
while (smartcards != NULL)
@@ -783,8 +778,7 @@ scx_finalize(void)
/*
* does a filename contain the token %smartcard?
*/
bool
scx_on_smartcard(const char *filename)
bool scx_on_smartcard(const char *filename)
{
return strneq(filename, SCX_TOKEN, strlen(SCX_TOKEN));
}
@@ -793,11 +787,9 @@ scx_on_smartcard(const char *filename)
/*
* find a specific object on the smartcard
*/
static bool
scx_pkcs11_find_object( CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE_PTR object,
CK_OBJECT_CLASS class,
const char* id)
static bool scx_pkcs11_find_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE_PTR object,
CK_OBJECT_CLASS class, const char* id)
{
size_t len;
char buf[BUF_LEN];
@@ -848,8 +840,7 @@ scx_pkcs11_find_object( CK_SESSION_HANDLE session,
/*
* check if a given certificate object id is found in a slot
*/
static bool
scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
static bool scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
{
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE object;
@@ -905,8 +896,7 @@ scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
/*
* Connect to the smart card in the reader and select the correct slot
*/
bool
scx_establish_context(smartcard_t *sc)
bool scx_establish_context(smartcard_t *sc)
{
#ifdef SMARTCARD
bool id_found = FALSE;
@@ -983,8 +973,7 @@ scx_establish_context(smartcard_t *sc)
/*
* log in to a session
*/
bool
scx_login(smartcard_t *sc)
bool scx_login(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1031,8 +1020,7 @@ scx_login(smartcard_t *sc)
/*
* logout from a session
*/
static void
scx_logout(smartcard_t *sc)
static void scx_logout(smartcard_t *sc)
{
CK_RV rv;
@@ -1052,8 +1040,7 @@ scx_logout(smartcard_t *sc)
/*
* Release context and disconnect from card
*/
void
scx_release_context(smartcard_t *sc)
void scx_release_context(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1083,9 +1070,8 @@ scx_release_context(smartcard_t *sc)
/*
* Load host certificate from smartcard
*/
bool
scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert
, bool *cached)
bool scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert,
bool *cached)
{
#ifdef SMARTCARD /* compile with smartcard support */
CK_OBJECT_HANDLE object;
@@ -1158,8 +1144,7 @@ scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert
* %smartcard:45 - - 45
* %smartcard0:45 - 0 45
*/
smartcard_t*
scx_parse_number_slot_id(const char *number_slot_id)
smartcard_t* scx_parse_number_slot_id(const char *number_slot_id)
{
int len = strlen(number_slot_id);
smartcard_t *sc = malloc_thing(smartcard_t);
@@ -1218,8 +1203,7 @@ scx_parse_number_slot_id(const char *number_slot_id)
/*
* Verify pin on card
*/
bool
scx_verify_pin(smartcard_t *sc)
bool scx_verify_pin(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1270,9 +1254,8 @@ scx_verify_pin(smartcard_t *sc)
/*
* Sign hash on smartcard
*/
bool
scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
, u_char *out, size_t outlen)
bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
size_t outlen)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1380,9 +1363,8 @@ scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
/*
* encrypt data block with an RSA public key
*/
bool
scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
, u_char *out, size_t *outlen)
bool scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
size_t *outlen)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1530,9 +1512,8 @@ scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
/*
* decrypt a data block with an RSA private key
*/
bool
scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
, u_char *out, size_t *outlen)
bool scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
size_t *outlen)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1606,9 +1587,8 @@ scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
* decrypt it using a private RSA key and
* return the decrypted data block via whack
*/
bool
scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
, const char* keyid, int whackfd)
bool scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op,
const char* keyid, int whackfd)
{
char inbuf[RSA_MAX_OCTETS];
char outbuf[2*RSA_MAX_OCTETS + 1];
@@ -1701,8 +1681,7 @@ scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
/*
* get length of RSA key in bytes
*/
size_t
scx_get_keylength(smartcard_t *sc)
size_t scx_get_keylength(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1737,8 +1716,7 @@ scx_get_keylength(smartcard_t *sc)
/*
* prompt for pin and verify it
*/
bool
scx_get_pin(smartcard_t *sc, int whackfd)
bool scx_get_pin(smartcard_t *sc, int whackfd)
{
#ifdef SMARTCARD
char pin[BUF_LEN];
@@ -1796,8 +1774,7 @@ scx_get_pin(smartcard_t *sc, int whackfd)
/*
* free the pin code
*/
void
scx_free_pin(chunk_t *pin)
void scx_free_pin(chunk_t *pin)
{
if (pin->ptr != NULL)
{
@@ -1811,8 +1788,7 @@ scx_free_pin(chunk_t *pin)
/*
* frees a smartcard record
*/
void
scx_free(smartcard_t *sc)
void scx_free(smartcard_t *sc)
{
if (sc != NULL)
{
@@ -1827,8 +1803,7 @@ scx_free(smartcard_t *sc)
/* release of a smartcard record decreases the count by one
" the record is freed when the counter reaches zero
*/
void
scx_release(smartcard_t *sc)
void scx_release(smartcard_t *sc)
{
if (sc != NULL && --sc->count == 0)
{
@@ -1844,8 +1819,7 @@ scx_release(smartcard_t *sc)
/*
* compare two smartcard records by comparing their slots and ids
*/
static bool
scx_same(smartcard_t *a, smartcard_t *b)
static bool scx_same(smartcard_t *a, smartcard_t *b)
{
if (a->number && b->number)
{
@@ -1863,8 +1837,7 @@ scx_same(smartcard_t *a, smartcard_t *b)
/* for each link pointing to the smartcard record
" increase the count by one
*/
void
scx_share(smartcard_t *sc)
void scx_share(smartcard_t *sc)
{
if (sc != NULL)
sc->count++;
@@ -1873,8 +1846,7 @@ scx_share(smartcard_t *sc)
/*
* adds a smartcard record to the chained list
*/
smartcard_t*
scx_add(smartcard_t *smartcard)
smartcard_t* scx_add(smartcard_t *smartcard)
{
smartcard_t *sc = smartcards;
smartcard_t **psc = &smartcards;
@@ -1903,8 +1875,7 @@ scx_add(smartcard_t *smartcard)
/*
* get the smartcard that belongs to an X.509 certificate
*/
smartcard_t*
scx_get(x509cert_t *cert)
smartcard_t* scx_get(x509cert_t *cert)
{
smartcard_t *sc = smartcards;
@@ -1920,8 +1891,7 @@ scx_get(x509cert_t *cert)
/*
* prints either the slot number or 'any slot'
*/
char *
scx_print_slot(smartcard_t *sc, const char *whitespace)
char *scx_print_slot(smartcard_t *sc, const char *whitespace)
{
char *buf = temporary_cyclic_buffer();
@@ -1935,8 +1905,7 @@ scx_print_slot(smartcard_t *sc, const char *whitespace)
/*
* list all smartcard info records in a chained list
*/
void
scx_list(bool utc)
void scx_list(bool utc)
{
smartcard_t *sc = smartcards;
@@ -1966,10 +1935,10 @@ scx_list(bool utc)
whack_log(RC_COMMENT, " label: '%s'", sc->label);
if (sc->last_cert.type == CERT_X509_SIGNATURE)
{
char buf[BUF_LEN];
certificate_t *certificate = sc->last_cert.u.x509->cert;
dntoa(buf, BUF_LEN, sc->last_cert.u.x509->subject);
whack_log(RC_COMMENT, " subject: '%s'", buf);
whack_log(RC_COMMENT, " subject: '%Y'",
certificate->get_subject(certificate));
}
sc = sc->next;
}
+121 -673
View File
@@ -48,18 +48,6 @@
*/
static x509cert_t *x509certs = NULL;
/**
* ASN.1 definition of a basicConstraints extension
*/
static const asn1Object_t basicConstraintsObjects[] = {
{ 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "CA", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 1 */
{ 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 2 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define BASIC_CONSTRAINTS_CA 1
/**
* ASN.1 definition of a authorityKeyIdentifier extension
*/
@@ -77,31 +65,6 @@ static const asn1Object_t authKeyIdentifierObjects[] = {
#define AUTH_KEY_ID_CERT_ISSUER 3
#define AUTH_KEY_ID_CERT_SERIAL 5
/**
* ASN.1 definition of a authorityInfoAccess extension
*/
static const asn1Object_t authInfoAccessObjects[] = {
{ 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
{ 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
{ 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */
{ 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define AUTH_INFO_ACCESS_METHOD 2
#define AUTH_INFO_ACCESS_LOCATION 3
/**
* ASN.1 definition of a extendedKeyUsage extension
*/
static const asn1Object_t extendedKeyUsageObjects[] = {
{ 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
{ 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define EXT_KEY_USAGE_PURPOSE_ID 1
/**
* ASN.1 definition of generalNames
*/
@@ -158,109 +121,13 @@ static const asn1Object_t otherNameObjects[] = {
#define ON_OBJ_ID_TYPE 0
#define ON_OBJ_VALUE 1
/**
* ASN.1 definition of crlDistributionPoints
*/
static const asn1Object_t crlDistributionPointsObjects[] = {
{ 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
{ 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
{ 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 2 */
{ 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
{ 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
{ 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
{ 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_BODY }, /* 10 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define CRL_DIST_POINTS_FULLNAME 3
/**
* ASN.1 definition of an X.509v3 x509_cert
*/
static const asn1Object_t certObjects[] = {
{ 0, "x509", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
{ 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */
{ 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
{ 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */
{ 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */
{ 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
{ 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */
{ 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */
{ 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */
{ 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
{ 2, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_RAW }, /* 11 */
{ 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
{ 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 14 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
{ 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 16 */
{ 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 17 */
{ 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 18 */
{ 5, "extnID", ASN1_OID, ASN1_BODY }, /* 19 */
{ 5, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 20 */
{ 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 21 */
{ 3, "end loop", ASN1_EOC, ASN1_END }, /* 22 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 23 */
{ 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 24 */
{ 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 25 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define X509_OBJ_CERTIFICATE 0
#define X509_OBJ_TBS_CERTIFICATE 1
#define X509_OBJ_VERSION 3
#define X509_OBJ_SERIAL_NUMBER 4
#define X509_OBJ_SIG_ALG 5
#define X509_OBJ_ISSUER 6
#define X509_OBJ_NOT_BEFORE 8
#define X509_OBJ_NOT_AFTER 9
#define X509_OBJ_SUBJECT 10
#define X509_OBJ_SUBJECT_PUBLIC_KEY_INFO 11
#define X509_OBJ_EXTN_ID 19
#define X509_OBJ_CRITICAL 20
#define X509_OBJ_EXTN_VALUE 21
#define X509_OBJ_ALGORITHM 24
#define X509_OBJ_SIGNATURE 25
const x509cert_t empty_x509cert = {
NULL , /* cert */
NULL , /* *next */
UNDEFINED_TIME, /* installed */
0 , /* count */
FALSE , /* smartcard */
AUTH_NONE , /* authority_flags */
{ NULL, 0 } , /* certificate */
{ NULL, 0 } , /* tbsCertificate */
1 , /* version */
{ NULL, 0 } , /* serialNumber */
OID_UNKNOWN , /* sigAlg */
{ NULL, 0 } , /* issuer */
/* validity */
0 , /* notBefore */
0 , /* notAfter */
{ NULL, 0 } , /* subject */
NULL , /* public_key */
/* issuerUniqueID */
/* subjectUniqueID */
/* extensions */
/* extension */
/* extnID */
/* critical */
/* extnValue */
FALSE , /* isCA */
FALSE , /* isOcspSigner */
{ NULL, 0 } , /* subjectKeyID */
{ NULL, 0 } , /* authKeyID */
{ NULL, 0 } , /* authKeySerialNumber */
{ NULL, 0 } , /* accessLocation */
NULL , /* subjectAltName */
NULL , /* crlDistributionPoints */
OID_UNKNOWN , /* algorithm */
{ NULL, 0 } /* signature */
};
/* coding of X.501 distinguished name */
@@ -333,10 +200,6 @@ static const x501rdn_t x501rdns[] = {
#define X501_RDN_ROOF 26
static chunk_t ASN1_subjectAltName_oid = chunk_from_chars(
0x06, 0x03, 0x55, 0x1D, 0x11
);
static void update_chunk(chunk_t *ch, int n)
{
n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
@@ -946,14 +809,6 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards)
return TRUE;
}
/**
* Compare two X.509 certificates by comparing their signatures
*/
bool same_x509cert(const x509cert_t *a, const x509cert_t *b)
{
return chunk_equals(a->signature, b->signature);
}
/**
* For each link pointing to the certificate increase the count by one
*/
@@ -970,11 +825,12 @@ void share_x509cert(x509cert_t *cert)
*/
x509cert_t* add_x509cert(x509cert_t *cert)
{
certificate_t *certificate = cert->cert;
x509cert_t *c = x509certs;
while (c != NULL)
{
if (same_x509cert(c, cert)) /* already in chain, free cert */
if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
{
free_x509cert(cert);
return c;
@@ -998,39 +854,47 @@ x509cert_t* add_x509cert(x509cert_t *cert)
*/
void select_x509cert_id(x509cert_t *cert, struct id *end_id)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subjectAltName;
bool copy_subject_dn = TRUE; /* ID is subject DN */
if (end_id->kind != ID_ANY) /* check for matching subjectAltName */
{
generalName_t *gn = cert->subjectAltName;
enumerator_t *enumerator;
while (gn != NULL)
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &subjectAltName))
{
struct id id = empty_id;
gntoid(&id, gn);
id_from_identification(&id, subjectAltName);
if (same_id(&id, end_id))
{
copy_subject_dn = FALSE; /* take subjectAltName instead */
break;
}
gn = gn->next;
}
enumerator->destroy(enumerator);
}
if (copy_subject_dn)
{
identification_t *subject = certificate->get_subject(certificate);
chunk_t subject_dn = subject->get_encoding(subject);
if (end_id->kind != ID_ANY && end_id->kind != ID_DER_ASN1_DN)
{
char buf[BUF_LEN];
char buf[BUF_LEN];
idtoa(end_id, buf, BUF_LEN);
plog(" no subjectAltName matches ID '%s', replaced by subject DN", buf);
idtoa(end_id, buf, BUF_LEN);
plog(" no subjectAltName matches ID '%s', replaced by subject DN", buf);
}
end_id->kind = ID_DER_ASN1_DN;
end_id->name.len = cert->subject.len;
end_id->name.len = subject_dn.len;
end_id->name.ptr = temporary_cyclic_buffer();
memcpy(end_id->name.ptr, cert->subject.ptr, cert->subject.len);
memcpy(end_id->name.ptr, subject_dn.ptr, subject_dn.len);
}
}
@@ -1046,32 +910,23 @@ bool same_keyid(chunk_t a, chunk_t b)
return chunk_equals(a, b);
}
/**
* Check for equality between two serial numbers
*/
bool same_serial(chunk_t a, chunk_t b)
{
/* do not compare serial numbers if one of them is not defined */
if (a.ptr == NULL || b.ptr == NULL)
{
return TRUE;
}
return chunk_equals(a, b);
}
/**
* Get a X.509 certificate with a given issuer found at a certain position
*/
x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid,
x509cert_t *chain)
x509cert_t* get_x509cert(chunk_t issuer, chunk_t keyid, x509cert_t *chain)
{
x509cert_t *cert = (chain != NULL)? chain->next : x509certs;
while (cert != NULL)
{
if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->authKeyID)
: (same_dn(issuer, cert->issuer)
&& same_serial(serial, cert->authKeySerialNumber)))
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *cert_issuer = certificate->get_issuer(certificate);
chunk_t cert_issuer_dn = cert_issuer->get_encoding(cert_issuer);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
if ((keyid.ptr != NULL) ? same_keyid(keyid, authKeyID)
: same_dn(issuer, cert_issuer_dn))
{
return cert;
}
@@ -1080,92 +935,6 @@ x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid,
return NULL;
}
/**
* Encode a linked list of subjectAltNames
*/
chunk_t build_subjectAltNames(generalName_t *subjectAltNames)
{
u_char *pos;
chunk_t names;
size_t len = 0;
generalName_t *gn = subjectAltNames;
/* compute the total size of the ASN.1 attributes object */
while (gn != NULL)
{
len += gn->name.len;
gn = gn->next;
}
pos = asn1_build_object(&names, ASN1_SEQUENCE, len);
gn = subjectAltNames;
while (gn != NULL)
{
chunkcpy(pos, gn->name);
gn = gn->next;
}
return asn1_wrap(ASN1_SEQUENCE, "cm"
, ASN1_subjectAltName_oid
, asn1_wrap(ASN1_OCTET_STRING, "m", names));
}
/**
* Build a to-be-signed X.509 certificate body
*/
static chunk_t build_tbs_x509cert(x509cert_t *cert, public_key_t *rsa)
{
/* version is always X.509v3 */
chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2);
chunk_t key = chunk_empty;
chunk_t extensions = chunk_empty;
rsa->get_encoding(rsa, KEY_PUB_ASN1_DER, &key);
chunk_t keyInfo = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
asn1_bitstring("m", key));
if (cert->subjectAltName != NULL)
{
extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m"
, asn1_wrap(ASN1_SEQUENCE, "m"
, build_subjectAltNames(cert->subjectAltName)));
}
return asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm"
, version
, asn1_integer("c", cert->serialNumber)
, asn1_algorithmIdentifier(cert->sigAlg)
, cert->issuer
, asn1_wrap(ASN1_SEQUENCE, "mm"
, asn1_from_time(&cert->notBefore, ASN1_UTCTIME)
, asn1_from_time(&cert->notAfter, ASN1_UTCTIME)
)
, cert->subject
, keyInfo
, extensions
);
}
/**
* Build a DER-encoded X.509 certificate
*/
void build_x509cert(x509cert_t *cert, public_key_t *cert_key,
private_key_t *signer_key)
{
chunk_t tbs_cert = build_tbs_x509cert(cert, cert_key);
chunk_t signature = x509_build_signature(tbs_cert, cert->sigAlg
, signer_key, TRUE);
cert->certificate = asn1_wrap(ASN1_SEQUENCE, "mmm"
, tbs_cert
, asn1_algorithmIdentifier(cert->sigAlg)
, signature);
}
/**
* Free the dynamic memory used to store generalNames
*/
@@ -1190,10 +959,12 @@ void free_x509cert(x509cert_t *cert)
{
if (cert != NULL)
{
DESTROY_IF(cert->public_key);
free_generalNames(cert->subjectAltName, FALSE);
free_generalNames(cert->crlDistributionPoints, FALSE);
free(cert->certificate.ptr);
certificate_t *certificate = cert->cert;
if (certificate)
{
certificate->destroy(certificate);
}
free(cert);
cert = NULL;
}
@@ -1230,13 +1001,16 @@ void store_x509certs(x509cert_t **firstcert, bool strict)
while (*pp != NULL)
{
x509cert_t *cert = *pp;
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
x509_flag_t flags = x509->get_flags(x509);
if (cert->isCA)
if (flags & X509_CA)
{
*pp = cert->next;
/* we don't accept self-signed CA certs */
if (same_dn(cert->issuer, cert->subject))
if (flags & X509_SELF_SIGNED)
{
plog("self-signed cacert rejected");
free_x509cert(cert);
@@ -1302,16 +1076,27 @@ void store_x509certs(x509cert_t **firstcert, bool strict)
* Check if a signature over binary blob is genuine
*/
bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
const x509cert_t *issuer_cert)
certificate_t *issuer_cert)
{
public_key_t *key = issuer_cert->public_key;
signature_scheme_t scheme = signature_scheme_from_oid(algorithm);
bool success;
public_key_t *key;
signature_scheme_t scheme;
scheme = signature_scheme_from_oid(algorithm);
if (scheme == SIGN_UNKNOWN)
{
return FALSE;
}
return key->verify(key, scheme, tbs, sig);
key = issuer_cert->get_public_key(issuer_cert);
if (key == NULL)
{
return FALSE;
}
success = key->verify(key, scheme, tbs, sig);
key->destroy(key);
return success;
}
/**
@@ -1331,82 +1116,6 @@ chunk_t x509_build_signature(chunk_t tbs, int algorithm, private_key_t *key,
: asn1_wrap(ASN1_OCTET_STRING, "m", signature);
}
/**
* Extracts the basicConstraints extension
*/
static bool parse_basicConstraints(chunk_t blob, int level0)
{
asn1_parser_t *parser;
chunk_t object;
int objectID;
bool isCA = FALSE;
parser = asn1_parser_create(basicConstraintsObjects, blob);
parser->set_top_level(parser, level0);
while (parser->iterate(parser, &objectID, &object))
{
if (objectID == BASIC_CONSTRAINTS_CA)
{
isCA = object.len && *object.ptr;
DBG(DBG_PARSING,
DBG_log(" %s",(isCA)?"TRUE":"FALSE");
)
}
}
parser->destroy(parser);
return isCA;
}
/**
* Converts a X.500 generalName into an ID
*/
void gntoid(struct id *id, const generalName_t *gn)
{
switch(gn->kind)
{
case GN_DNS_NAME: /* ID type: ID_FQDN */
id->kind = ID_FQDN;
id->name = gn->name;
break;
case GN_IP_ADDRESS: /* ID type: ID_IPV4_ADDR */
{
const struct af_info *afi = &af_inet4_info;
err_t ugh = NULL;
id->kind = afi->id_addr;
ugh = initaddr(gn->name.ptr, gn->name.len, afi->af, &id->ip_addr);
}
break;
case GN_RFC822_NAME: /* ID type: ID_USER_FQDN */
id->kind = ID_USER_FQDN;
id->name = gn->name;
break;
default:
id->kind = ID_ANY;
id->name = chunk_empty;
}
}
/**
* Compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280
* as the 160 bit SHA-1 hash of the public key
*/
bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID)
{
chunk_t fingerprint;
if (!cert->public_key->get_fingerprint(cert->public_key, KEY_ID_PUBKEY_SHA1,
&fingerprint))
{
plog(" unable to compute subjectKeyID");
return FALSE;
}
memcpy(subjectKeyID.ptr, fingerprint.ptr, subjectKeyID.len);
return TRUE;
}
/**
* Extracts an otherName
*/
@@ -1607,295 +1316,32 @@ void parse_authorityKeyIdentifier(chunk_t blob, int level0,
parser->destroy(parser);
}
/**
* Extracts an authorityInfoAcess location
*/
static void parse_authorityInfoAccess(chunk_t blob, int level0,
chunk_t *accessLocation)
{
asn1_parser_t *parser;
chunk_t object;
int objectID;
int accessMethod = OID_UNKNOWN;
parser = asn1_parser_create(authInfoAccessObjects, blob);
parser->set_top_level(parser, level0);
while (parser->iterate(parser, &objectID, &object))
{
switch (objectID)
{
case AUTH_INFO_ACCESS_METHOD:
accessMethod = asn1_known_oid(object);
break;
case AUTH_INFO_ACCESS_LOCATION:
{
switch (accessMethod)
{
case OID_OCSP:
if (*object.ptr == ASN1_CONTEXT_S_6)
{
if (asn1_length(&object) == ASN1_INVALID_LENGTH)
{
goto end;
}
DBG(DBG_PARSING,
DBG_log(" '%.*s'",(int)object.len, object.ptr)
)
/* only HTTP(S) URIs accepted */
if (strncasecmp(object.ptr, "http", 4) == 0)
{
*accessLocation = object;
goto end;
}
}
plog("warning: ignoring OCSP InfoAccessLocation with unkown protocol");
break;
default:
/* unkown accessMethod, ignoring */
break;
}
}
break;
default:
break;
}
}
end:
parser->destroy(parser);
}
/**
* Extracts extendedKeyUsage OIDs
*/
static bool parse_extendedKeyUsage(chunk_t blob, int level0)
{
asn1_parser_t *parser;
chunk_t object;
int objectID;
bool ocsp_signing = FALSE;
parser = asn1_parser_create(extendedKeyUsageObjects, blob);
parser->set_top_level(parser, level0);
while (parser->iterate(parser, &objectID, &object))
{
if (objectID == EXT_KEY_USAGE_PURPOSE_ID
&& asn1_known_oid(object) == OID_OCSP_SIGNING)
{
ocsp_signing = TRUE;
}
}
parser->destroy(parser);
return ocsp_signing;
}
/**
* Extracts one or several crlDistributionPoints
* and puts them into a chained list
*/
static generalName_t* parse_crlDistributionPoints(chunk_t blob, int level0)
{
asn1_parser_t *parser;
chunk_t object;
int objectID;
generalName_t *top_gn = NULL; /* top of the chained list */
generalName_t **tail_gn = &top_gn; /* tail of the chained list */
parser = asn1_parser_create(crlDistributionPointsObjects, blob);
parser->set_top_level(parser, level0);
while (parser->iterate(parser, &objectID, &object))
{
if (objectID == CRL_DIST_POINTS_FULLNAME)
{
generalName_t *gn;
gn = parse_generalNames(object, parser->get_level(parser)+1, TRUE);
/* append extracted generalNames to existing chained list */
*tail_gn = gn;
/* find new tail of the chained list */
while (gn != NULL)
{
tail_gn = &gn->next; gn = gn->next;
}
}
}
parser->destroy(parser);
return top_gn;
}
/**
* Parses an X.509v3 certificate
*/
bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
{
u_char buf[BUF_LEN];
asn1_parser_t *parser;
chunk_t object;
int objectID;
int extn_oid = OID_UNKNOWN;
bool critical;
bool success = FALSE;
parser = asn1_parser_create(certObjects, blob);
parser->set_top_level(parser, level0);
while (parser->iterate(parser, &objectID, &object))
{
u_int level = parser->get_level(parser) + 1;
switch (objectID) {
case X509_OBJ_CERTIFICATE:
cert->certificate = object;
break;
case X509_OBJ_TBS_CERTIFICATE:
cert->tbsCertificate = object;
break;
case X509_OBJ_VERSION:
cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
DBG(DBG_PARSING,
DBG_log(" v%d", cert->version);
)
break;
case X509_OBJ_SERIAL_NUMBER:
cert->serialNumber = object;
break;
case X509_OBJ_SIG_ALG:
cert->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL);
break;
case X509_OBJ_ISSUER:
cert->issuer = object;
DBG(DBG_PARSING,
dntoa(buf, BUF_LEN, object);
DBG_log(" '%s'",buf)
)
break;
case X509_OBJ_NOT_BEFORE:
cert->notBefore = asn1_parse_time(object, level);
break;
case X509_OBJ_NOT_AFTER:
cert->notAfter = asn1_parse_time(object, level);
break;
case X509_OBJ_SUBJECT:
cert->subject = object;
DBG(DBG_PARSING,
dntoa(buf, BUF_LEN, object);
DBG_log(" '%s'",buf)
)
break;
case X509_OBJ_SUBJECT_PUBLIC_KEY_INFO:
cert->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
if (cert->public_key == NULL)
{
goto end;
}
break;
case X509_OBJ_EXTN_ID:
extn_oid = asn1_known_oid(object);
break;
case X509_OBJ_CRITICAL:
critical = object.len && *object.ptr;
DBG(DBG_PARSING,
DBG_log(" %s",(critical)?"TRUE":"FALSE");
)
break;
case X509_OBJ_EXTN_VALUE:
{
switch (extn_oid) {
case OID_SUBJECT_KEY_ID:
if (!asn1_parse_simple_object(&object, ASN1_OCTET_STRING,
level, "keyIdentifier"))
{
goto end;
}
cert->subjectKeyID = object;
break;
case OID_SUBJECT_ALT_NAME:
cert->subjectAltName =
parse_generalNames(object, level, FALSE);
break;
case OID_BASIC_CONSTRAINTS:
cert->isCA =
parse_basicConstraints(object, level);
break;
case OID_CRL_DISTRIBUTION_POINTS:
cert->crlDistributionPoints =
parse_crlDistributionPoints(object, level);
break;
case OID_AUTHORITY_KEY_ID:
parse_authorityKeyIdentifier(object, level
, &cert->authKeyID, &cert->authKeySerialNumber);
break;
case OID_AUTHORITY_INFO_ACCESS:
parse_authorityInfoAccess(object, level, &cert->accessLocation);
break;
case OID_EXTENDED_KEY_USAGE:
cert->isOcspSigner = parse_extendedKeyUsage(object, level);
break;
case OID_NS_REVOCATION_URL:
case OID_NS_CA_REVOCATION_URL:
case OID_NS_CA_POLICY_URL:
case OID_NS_COMMENT:
if (!asn1_parse_simple_object(&object, ASN1_IA5STRING
, level, oid_names[extn_oid].name))
{
goto end;
}
break;
default:
break;
}
}
break;
case X509_OBJ_ALGORITHM:
cert->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
break;
case X509_OBJ_SIGNATURE:
cert->signature = object;
break;
default:
break;
}
}
success = parser->success(parser);
time(&cert->installed);
end:
parser->destroy(parser);
return success;
}
/**
* Verify the validity of a certificate by
* checking the notBefore and notAfter dates
*/
err_t check_validity(const x509cert_t *cert, time_t *until)
{
time_t current_time;
time_t current_time, notBefore, notAfter;
certificate_t *certificate = cert->cert;
time(&current_time);
certificate->get_validity(certificate, &current_time, &notBefore, &notAfter);
DBG(DBG_CONTROL | DBG_PARSING ,
DBG_log(" not before : %T", &cert->notBefore, TRUE);
DBG_log(" not before : %T", &notBefore, TRUE);
DBG_log(" current time: %T", &current_time, TRUE);
DBG_log(" not after : %T", &cert->notAfter, TRUE);
DBG_log(" not after : %T", &notAfter, TRUE);
)
if (cert->notAfter < *until)
if (*until == 0 || notAfter < *until)
{
*until = cert->notAfter;
*until = notAfter;
}
if (current_time < cert->notBefore)
if (current_time < notBefore)
{
return "certificate is not valid yet";
}
if (current_time > cert->notAfter)
if (current_time > notAfter)
{
return "certificate has expired";
}
@@ -1912,24 +1358,24 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
{
int pathlen;
*until = cert->notAfter;
*until = 0;
for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
{
certificate_t *certificate = cert->cert;
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
x509_t *x509 = (x509_t*)certificate;
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
x509cert_t *issuer_cert;
u_char buf[BUF_LEN];
err_t ugh = NULL;
DBG(DBG_CONTROL,
dntoa(buf, BUF_LEN, cert->subject);
DBG_log("subject: '%s'",buf);
dntoa(buf, BUF_LEN, cert->issuer);
DBG_log("issuer: '%s'",buf);
if (cert->authKeyID.ptr != NULL)
DBG_log("subject: '%Y'", subject);
DBG_log("issuer: '%Y'", issuer);
if (authKeyID.ptr != NULL)
{
datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
, buf, BUF_LEN);
DBG_log("authkey: %s", buf);
DBG_log("authkey: %#B", &authKeyID);
}
)
@@ -1946,9 +1392,8 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
)
lock_authcert_list("verify_x509cert");
issuer_cert = get_authcert(cert->issuer, cert->authKeySerialNumber
, cert->authKeyID, AUTH_CA);
issuer_cert = get_authcert(issuer->get_encoding(issuer),
authKeyID, AUTH_CA);
if (issuer_cert == NULL)
{
plog("issuer cacert not found");
@@ -1959,8 +1404,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
DBG_log("issuer cacert found")
)
if (!x509_check_signature(cert->tbsCertificate, cert->signature,
cert->algorithm, issuer_cert))
if (!certificate->issued_by(certificate, issuer_cert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("verify_x509cert");
@@ -1972,7 +1416,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
unlock_authcert_list("verify_x509cert");
/* check if cert is a self-signed root ca */
if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
if (pathlen > 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
{
DBG(DBG_CONTROL,
DBG_log("reached self-signed root ca")
@@ -2063,11 +1507,13 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
{
if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags))
{
u_char buf[BUF_LEN];
public_key_t *key = cert->public_key;
chunk_t keyid;
time_t notBefore, notAfter;
public_key_t *key;
chunk_t serial, keyid, subjkey, authkey;
cert_t c;
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
c.type = CERT_X509_SIGNATURE;
c.u.x509 = cert;
@@ -2081,45 +1527,47 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc,
cert->count);
dntoa(buf, BUF_LEN, cert->subject);
whack_log(RC_COMMENT, " subject: '%s'", buf);
dntoa(buf, BUF_LEN, cert->issuer);
whack_log(RC_COMMENT, " issuer: '%s'", buf);
datatot(cert->serialNumber.ptr, cert->serialNumber.len, ':',
buf, BUF_LEN);
whack_log(RC_COMMENT, " serial: %s", buf);
whack_log(RC_COMMENT, " subject: '%Y'",
certificate->get_subject(certificate));
whack_log(RC_COMMENT, " issuer: '%Y'",
certificate->get_issuer(certificate));
serial = x509->get_serial(x509);
whack_log(RC_COMMENT, " serial: %#B", &serial);
/* list validity */
certificate->get_validity(certificate, &now, &notBefore, &notAfter);
whack_log(RC_COMMENT, " validity: not before %T %s",
&cert->notBefore, utc,
(cert->notBefore < now)?"ok":"fatal (not valid yet)");
&notBefore, utc,
(notBefore < now)?"ok":"fatal (not valid yet)");
whack_log(RC_COMMENT, " not after %T %s",
&cert->notAfter, utc,
check_expiry(cert->notAfter, 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,
cert->smartcard ? ", on smartcard" :
(has_private_key(c)? ", has private key" : ""));
if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
&notAfter, utc,
check_expiry(notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
key = certificate->get_public_key(certificate);
if (key);
{
whack_log(RC_COMMENT, " keyid: %#B", &keyid);
whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
key_type_names, key->get_type(key),
key->get_keysize(key) * BITS_PER_BYTE,
cert->smartcard ? ", on smartcard" :
(has_private_key(c)? ", has private key" : ""));
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, &subjkey))
{
whack_log(RC_COMMENT, " subjkey: %#B", &subjkey);
}
key->destroy(key);
}
if (cert->subjectKeyID.ptr != NULL)
/* list optional authorityKeyIdentifier */
authkey = x509->get_authKeyIdentifier(x509);
if (authkey.ptr)
{
datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':',
buf, BUF_LEN);
whack_log(RC_COMMENT, " subjkey: %s", buf);
}
if (cert->authKeyID.ptr != NULL)
{
datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':',
buf, BUF_LEN);
whack_log(RC_COMMENT, " authkey: %s", buf);
}
if (cert->authKeySerialNumber.ptr != NULL)
{
datatot(cert->authKeySerialNumber.ptr,
cert->authKeySerialNumber.len, ':', buf, BUF_LEN);
whack_log(RC_COMMENT, " aserial: %s", buf);
whack_log(RC_COMMENT, " authkey: %#B", &authkey);
}
}
cert = cert->next;
+11 -52
View File
@@ -20,7 +20,7 @@
#include <credentials/keys/public_key.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/x509.h>
#include "constants.h"
#include "id.h"
@@ -53,80 +53,39 @@ struct generalName {
typedef struct x509cert x509cert_t;
struct x509cert {
certificate_t *cert;
x509cert_t *next;
time_t installed;
int count;
bool smartcard;
u_char authority_flags;
chunk_t certificate;
chunk_t tbsCertificate;
u_int version;
chunk_t serialNumber;
/* signature */
int sigAlg;
chunk_t issuer;
/* validity */
time_t notBefore;
time_t notAfter;
chunk_t subject;
public_key_t *public_key;
/* issuerUniqueID */
/* subjectUniqueID */
/* v3 extensions */
/* extension */
/* extension */
/* extnID */
/* critical */
/* extnValue */
bool isCA;
bool isOcspSigner; /* ocsp */
chunk_t subjectKeyID;
chunk_t authKeyID;
chunk_t authKeySerialNumber;
chunk_t accessLocation; /* ocsp */
generalName_t *subjectAltName;
generalName_t *crlDistributionPoints;
/* signatureAlgorithm */
int algorithm;
chunk_t signature;
time_t installed;
int count;
bool smartcard;
u_char authority_flags;
};
/* used for initialization */
extern const x509cert_t empty_x509cert;
extern bool same_serial(chunk_t a, chunk_t b);
extern bool same_keyid(chunk_t a, chunk_t b);
extern bool same_dn(chunk_t a, chunk_t b);
extern bool match_dn(chunk_t a, chunk_t b, int *wildcards);
extern bool same_x509cert(const x509cert_t *a, const x509cert_t *b);
extern void hex_str(chunk_t bin, chunk_t *str);
extern int dn_count_wildcards(chunk_t dn);
extern int dntoa(char *dst, size_t dstlen, chunk_t dn);
extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn,
const char* null_dn);
extern err_t atodn(char *src, chunk_t *dn);
extern void gntoid(struct id *id, const generalName_t *gn);
extern bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID);
extern void select_x509cert_id(x509cert_t *cert, struct id *end_id);
extern bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert);
extern time_t parse_time(chunk_t blob, int level0);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0
, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0,
chunk_t *authKeyID,
chunk_t *authKeySerialNumber);
extern chunk_t get_directoryName(chunk_t blob, int level, bool implicit);
extern err_t check_validity(const x509cert_t *cert, time_t *until);
extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
const x509cert_t *issuer_cert);
certificate_t *issuer_cert);
extern chunk_t x509_build_signature(chunk_t tbs, int algorithm,
private_key_t *key, bool bit_string);
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until);
extern x509cert_t* add_x509cert(x509cert_t *cert);
extern x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid,
x509cert_t* chain);
extern void build_x509cert(x509cert_t *cert, public_key_t *cert_key,
private_key_t *signer_key);
extern chunk_t build_subjectAltNames(generalName_t *subjectAltNames);
extern x509cert_t* get_x509cert(chunk_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);
+1 -1
View File
@@ -1,5 +1,5 @@
ipsec_PROGRAMS = scepclient
scepclient_SOURCES = scepclient.c pkcs10.c pkcs10.h scep.c scep.h loglite.c
scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c
PLUTODIR=$(top_srcdir)/src/pluto
OPENACDIR=$(top_srcdir)/src/openac
+15 -19
View File
@@ -45,15 +45,14 @@ static const chunk_t ASN1_extensionRequest_oid = chunk_from_chars(
);
/**
* @brief Adds a subjectAltName in DER-coded form to a linked list
* Adds a subjectAltName in DER-coded form to a linked list
*
* @param[in,out] subjectAltNames head of the linked list of subjectAltNames
* @param[in] kind type of the subjectAltName (which is a generalName)
* @param[in] value value of the subjectAltName as an ASCII string
* @param[in] subjectAltNames linked list of subjectAltNames
* @param[in] kind type of the subjectAltName (which is a generalName)
* @param[in] value value of the subjectAltName as an ASCII string
*/
void
pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind
, char *value)
void pkcs10_add_subjectAltName(linked_list_t *subjectAltNames,
generalNames_t kind, char *value)
{
generalName_t *gn;
asn1_t asn1_type = ASN1_EOC;
@@ -96,16 +95,15 @@ pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind
}
/**
* @brief Builds the requestInfoAttributes of the certificationRequestInfo-field
* Builds the requestInfoAttributes of the certificationRequestInfo-field
*
* challenge password ans subjectAltNames are only included,
* when avaiable in given #pkcs10_t structure
*
* @param[in] pkcs10 Pointer to a #pkcs10_t structure
* @return 1 if succeeded, 0 otherwise
* @return 1 if succeeded, 0 otherwise
*/
static chunk_t
build_req_info_attributes(pkcs10_t* pkcs10)
static chunk_t build_req_info_attributes(pkcs10_t* pkcs10)
{
chunk_t subjectAltNames = chunk_empty;
@@ -143,13 +141,12 @@ build_req_info_attributes(pkcs10_t* pkcs10)
}
/**
* @brief Builds a DER-code pkcs#10 certificate request
* Builds a DER-code pkcs#10 certificate request
*
* @param[in] pkcs10 pointer to a pkcs10_t struct
* @return DER-code pkcs10 request
*/
static chunk_t
pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
static chunk_t pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
{
chunk_t key = chunk_empty;
@@ -175,7 +172,7 @@ pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
}
/**
* @brief Creates a pkcs#10 certificate request object
* Creates a pkcs#10 certificate request object
*
* To create a certificate request, the RSA key and the
* names to be included as subject in the certificate request
@@ -190,7 +187,7 @@ pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
*/
pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public,
chunk_t subject, chunk_t challengePassword,
generalName_t *subjectAltNames, int signature_alg)
linked_list_t *subjectAltNames, int signature_alg)
{
pkcs10_t *pkcs10 = malloc_thing(pkcs10_t);
@@ -205,12 +202,11 @@ pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public,
}
/**
* @brief Frees the resources used by an #pkcs10_t object
* Frees the resources used by an #pkcs10_t object
*
* @param[in] pkcs10 #pkcs10_t to free
*/
void
pkcs10_free(pkcs10_t *pkcs10)
void pkcs10_free(pkcs10_t *pkcs10)
{
if (pkcs10 != NULL)
{
+4 -3
View File
@@ -23,6 +23,7 @@
#ifndef _PKCS10_H
#define _PKCS10_H
#include <utils/linked_list.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
@@ -45,16 +46,16 @@ struct pkcs10_struct {
chunk_t request;
chunk_t subject;
chunk_t challengePassword;
generalName_t *subjectAltNames;
linked_list_t *subjectAltNames;
};
extern const pkcs10_t empty_pkcs10;
extern void pkcs10_add_subjectAltName(generalName_t **subjectAltNames,
extern void pkcs10_add_subjectAltName(linked_list_t *subjectAltNames,
generalNames_t kind, char *value);
extern pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public,
chunk_t subject, chunk_t challengePassword,
generalName_t *subjectAltNames, int signature_alg);
linked_list_t *subjectAltNames, int signature_alg);
extern void pkcs10_free(pkcs10_t *pkcs10);
#endif /* _PKCS10_H */
+3 -3
View File
@@ -370,8 +370,8 @@ chunk_t scep_senderNonce_attribute(void)
* Builds a pkcs7 enveloped and signed scep request
*/
chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
const x509cert_t *enc_cert, int enc_alg,
const x509cert_t *signer_cert, int digest_alg,
certificate_t *enc_cert, int enc_alg,
certificate_t *signer_cert, int digest_alg,
private_key_t *private_key)
{
chunk_t envelopedData, attributes, request;
@@ -525,7 +525,7 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
}
err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data,
scep_attributes_t *attrs, x509cert_t *signer_cert)
scep_attributes_t *attrs, certificate_t *signer_cert)
{
chunk_t attributes;
+5 -3
View File
@@ -23,6 +23,8 @@
#ifndef _SCEP_H
#define _SCEP_H
#include <credentials/certificates/certificate.h>
#include "../pluto/defs.h"
#include "../pluto/pkcs7.h"
@@ -81,13 +83,13 @@ extern chunk_t scep_transId_attribute(chunk_t transaction_id);
extern chunk_t scep_messageType_attribute(scep_msg_t m);
extern chunk_t scep_senderNonce_attribute(void);
extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
const x509cert_t *enc_cert, int enc_alg,
const x509cert_t *signer_cert, int digest_alg,
certificate_t *enc_cert, int enc_alg,
certificate_t *signer_cert, int digest_alg,
private_key_t *private_key);
extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
bool http_get_request, chunk_t *response);
extern err_t scep_parse_response(chunk_t response, chunk_t transID,
contentInfo_t *data, scep_attributes_t *attrs,
x509cert_t *signer_cert);
certificate_t *signer_cert);
#endif /* _SCEP_H */
+122 -98
View File
@@ -41,10 +41,15 @@
#include <asn1/oid.h>
#include <utils/optionsfrom.h>
#include <utils/enumerator.h>
#include <utils/linked_list.h>
#include <crypto/hashers/hasher.h>
#include <crypto/crypters/crypter.h>
#include <crypto/proposal/proposal_keywords.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/x509.h>
#include <credentials/certificates/pkcs10.h>
#include "../pluto/constants.h"
#include "../pluto/defs.h"
@@ -52,7 +57,6 @@
#include "../pluto/pkcs7.h"
#include "../pluto/certs.h"
#include "pkcs10.h"
#include "scep.h"
/*
@@ -121,26 +125,27 @@ options_t *options;
* Global variables
*/
private_key_t *private_key = NULL;
public_key_t *public_key = NULL;
chunk_t pkcs1;
chunk_t pkcs7;
chunk_t subject;
chunk_t challengePassword;
chunk_t serialNumber;
chunk_t transID;
chunk_t fingerprint;
chunk_t encoding;
chunk_t pkcs10_encoding;
chunk_t issuerAndSubject;
chunk_t getCertInitial;
chunk_t scep_response;
cert_t cert;
x509cert_t *x509_signer = NULL;
x509cert_t *x509_ca_enc = NULL;
x509cert_t *x509_ca_sig = NULL;
generalName_t *subjectAltNames = NULL;
pkcs10_t *pkcs10 = NULL;
linked_list_t *subjectAltNames;
identification_t *subject = NULL;
private_key_t *private_key = NULL;
public_key_t *public_key = NULL;
certificate_t *x509_signer = NULL;
certificate_t *x509_ca_enc = NULL;
certificate_t *x509_ca_sig = NULL;
certificate_t *pkcs10_req = NULL;
/**
* @brief exit scepclient
@@ -152,27 +157,25 @@ exit_scepclient(err_t message, ...)
{
int status = 0;
DESTROY_IF(subject);
DESTROY_IF(private_key);
DESTROY_IF(public_key);
DESTROY_IF(x509_signer);
DESTROY_IF(x509_ca_enc);
DESTROY_IF(x509_ca_sig);
DESTROY_IF(pkcs10_req);
subjectAltNames->destroy_offset(subjectAltNames,
offsetof(identification_t, destroy));
free(pkcs1.ptr);
free(pkcs7.ptr);
free(subject.ptr);
free(serialNumber.ptr);
free(transID.ptr);
free(fingerprint.ptr);
free(encoding.ptr);
free(pkcs10_encoding.ptr);
free(issuerAndSubject.ptr);
free(getCertInitial.ptr);
free(scep_response.ptr);
free_generalNames(subjectAltNames, TRUE);
if (x509_signer != NULL)
{
x509_signer->subjectAltName = NULL;
}
free_x509cert(x509_signer);
free_x509cert(x509_ca_enc);
free_x509cert(x509_ca_sig);
pkcs10_free(pkcs10);
options->destroy(options);
/* print any error message to stderr */
@@ -357,8 +360,8 @@ int main(int argc, char **argv)
/* digest algorithm used by pkcs7, default is SHA-1 */
int pkcs7_digest_alg = OID_SHA1;
/* signature algorithm used by pkcs10, default is SHA-1 with RSA encryption */
int pkcs10_signature_alg = OID_SHA1;
/* signature algorithm used by pkcs10, default is SHA-1 */
hash_algorithm_t pkcs10_signature_alg = HASH_SHA1;
/* URL of the SCEP-Server */
char *scep_url = NULL;
@@ -374,18 +377,6 @@ int main(int argc, char **argv)
err_t ugh = NULL;
/* initialize global variables */
pkcs1 = chunk_empty;
pkcs7 = chunk_empty;
serialNumber = chunk_empty;
transID = chunk_empty;
fingerprint = chunk_empty;
issuerAndSubject = chunk_empty;
challengePassword = chunk_empty;
getCertInitial = chunk_empty;
scep_response = chunk_empty;
log_to_stderr = TRUE;
/* initialize library */
if (!library_init(NULL))
{
@@ -400,8 +391,21 @@ int main(int argc, char **argv)
exit(SS_RC_DAEMON_INTEGRITY);
}
/* initialize optionsfrom */
options = options_create();
/* initialize global variables */
pkcs1 = chunk_empty;
pkcs7 = chunk_empty;
serialNumber = chunk_empty;
transID = chunk_empty;
fingerprint = chunk_empty;
encoding = chunk_empty;
pkcs10_encoding = chunk_empty;
issuerAndSubject = chunk_empty;
challengePassword = chunk_empty;
getCertInitial = chunk_empty;
scep_response = chunk_empty;
subjectAltNames = linked_list_create();
options = options_create();
log_to_stderr = TRUE;
for (;;)
{
@@ -614,7 +618,6 @@ int main(int argc, char **argv)
case 's': /* --subjectAltName */
{
generalNames_t kind;
char *value = strstr(optarg, "=");
if (value)
@@ -625,25 +628,19 @@ int main(int argc, char **argv)
value++;
}
if (strcaseeq("email", optarg))
if (strcaseeq("email", optarg) ||
strcaseeq("dns", optarg) ||
strcaseeq("ip", optarg))
{
kind = GN_RFC822_NAME;
}
else if (strcaseeq("dns", optarg))
{
kind = GN_DNS_NAME;
}
else if (strcaseeq("ip", optarg))
{
kind = GN_IP_ADDRESS;
subjectAltNames->insert_last(subjectAltNames,
identification_create_from_string(value));
continue;
}
else
{
usage("invalid --subjectAltName type");
continue;
}
pkcs10_add_subjectAltName(&subjectAltNames, kind, value);
continue;
}
case 'p': /* --password */
@@ -831,11 +828,6 @@ int main(int argc, char **argv)
}
else
{
char buf[IDTOA_BUF];
chunk_t dn = chunk_empty;
dn.ptr = buf;
if (distinguishedName == NULL)
{
char buf[BUF_LEN];
@@ -853,21 +845,29 @@ int main(int argc, char **argv)
DBG(DBG_CONTROL,
DBG_log("dn: '%s'", distinguishedName);
)
ugh = atodn(distinguishedName, &dn);
if (ugh != NULL)
subject = identification_create_from_string(distinguishedName);
if (subject->get_type(subject) != ID_DER_ASN1_DN)
{
exit_scepclient(ugh);
exit_scepclient("parsing of distinguished name failed");
}
subject = chunk_clone(dn);
DBG(DBG_CONTROL,
DBG_log("building pkcs10 object:")
)
pkcs10 = pkcs10_build(private_key, public_key, subject,
challengePassword, subjectAltNames,
pkcs10_signature_alg);
fingerprint = scep_generate_pkcs10_fingerprint(pkcs10->request);
pkcs10_req = lib->creds->create(lib->creds, CRED_CERTIFICATE,
CERT_PKCS10_REQUEST,
BUILD_SIGNING_KEY, private_key,
BUILD_SUBJECT, subject,
BUILD_SUBJECT_ALTNAMES, subjectAltNames,
BUILD_PASSPHRASE, challengePassword,
BUILD_DIGEST_ALG, pkcs10_signature_alg,
BUILD_END);
if (!pkcs10_req)
{
exit_scepclient("generating pkcs10 request failed");
}
pkcs10_encoding = pkcs10_req->get_encoding(pkcs10_req);
fingerprint = scep_generate_pkcs10_fingerprint(pkcs10_encoding);
plog(" fingerprint: %s", fingerprint.ptr);
}
@@ -878,9 +878,10 @@ int main(int argc, char **argv)
{
char *path = concatenate_paths(REQ_PATH, file_out_pkcs10);
if (!chunk_write(pkcs10->request, path, "pkcs10", 0022, force))
if (!chunk_write(pkcs10_encoding, path, "pkcs10", 0022, force))
{
exit_scepclient("could not write pkcs10 file '%s'", path);
}
filetype_out &= ~PKCS10; /* delete PKCS10 flag */
}
@@ -901,8 +902,9 @@ int main(int argc, char **argv)
)
if (!private_key->get_encoding(private_key, KEY_PRIV_ASN1_DER, &pkcs1) ||
!chunk_write(pkcs1, path, "pkcs1", 0066, force))
{
exit_scepclient("could not write pkcs1 file '%s'", path);
}
filetype_out &= ~PKCS1; /* delete PKCS1 flag */
}
@@ -914,19 +916,23 @@ int main(int argc, char **argv)
scep_generate_transaction_id(public_key, &transID, &serialNumber);
plog(" transaction ID: %.*s", (int)transID.len, transID.ptr);
notBefore = notBefore ? notBefore : time(NULL);
notAfter = notAfter ? notAfter : (notBefore + validity);
/* generate a self-signed X.509 certificate */
x509_signer = malloc_thing(x509cert_t);
*x509_signer = empty_x509cert;
x509_signer->serialNumber = serialNumber;
x509_signer->sigAlg = OID_SHA1_WITH_RSA;
x509_signer->issuer = subject;
x509_signer->notBefore = (notBefore)? notBefore
: time(NULL);
x509_signer->notAfter = (notAfter)? notAfter
: x509_signer->notBefore + validity;
x509_signer->subject = subject;
x509_signer->subjectAltName = subjectAltNames;
build_x509cert(x509_signer, public_key, private_key);
x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_SIGNING_KEY, private_key,
BUILD_PUBLIC_KEY, public_key,
BUILD_SUBJECT, subject,
BUILD_NOT_BEFORE_TIME, notBefore,
BUILD_NOT_AFTER_TIME, notAfter,
BUILD_SERIAL, serialNumber,
BUILD_SUBJECT_ALTNAMES, subjectAltNames,
BUILD_END);
if (!x509_signer)
{
exit_scepclient("generating certificate failed");
}
/*
* output of self-signed X.509 certificate file
@@ -935,9 +941,16 @@ int main(int argc, char **argv)
{
char *path = concatenate_paths(HOST_CERT_PATH, file_out_cert_self);
if (!chunk_write(x509_signer->certificate, path, "self-signed cert", 0022, force))
encoding = x509_signer->get_encoding(x509_signer);
if (!encoding.ptr)
{
exit_scepclient("encoding certificate failed");
}
if (!chunk_write(encoding, path, "self-signed cert", 0022, force))
{
exit_scepclient("could not write self-signed cert file '%s'", path);
;
}
chunk_free(&encoding);
filetype_out &= ~CERT_SELF; /* delete CERT_SELF flag */
}
@@ -951,13 +964,13 @@ int main(int argc, char **argv)
*/
{
char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_enc);
cert_t cert;
if (!load_cert(path, "encryption cacert", &cert))
x509_ca_enc = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, path, BUILD_END);
if (!x509_ca_enc)
{
exit_scepclient("could not load encryption cacert file '%s'", path);
}
x509_ca_enc = cert.u.x509;
}
/*
@@ -978,10 +991,10 @@ int main(int argc, char **argv)
DBG(DBG_CONTROL,
DBG_log("building pkcs7 request")
)
pkcs7 = scep_build_request(pkcs10->request
, transID, SCEP_PKCSReq_MSG
, x509_ca_enc, pkcs7_symmetric_cipher
, x509_signer, pkcs7_digest_alg, private_key);
pkcs7 = scep_build_request(pkcs10_encoding,
transID, SCEP_PKCSReq_MSG,
x509_ca_enc, pkcs7_symmetric_cipher,
x509_signer, pkcs7_digest_alg, private_key);
}
/*
@@ -1008,7 +1021,6 @@ int main(int argc, char **argv)
if (filetype_out & CERT)
{
char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig);
cert_t cert;
time_t poll_start = 0;
x509cert_t *certs = NULL;
@@ -1017,9 +1029,12 @@ int main(int argc, char **argv)
contentInfo_t data = empty_contentInfo;
scep_attributes_t attrs = empty_scep_attributes;
if (!load_cert(path, "signature cacert", &cert))
x509_ca_sig = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, path, BUILD_END);
if (!x509_ca_sig)
{
exit_scepclient("could not load signature cacert file '%s'", path);
x509_ca_sig = cert.u.x509;
}
if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION,
http_get_request, &scep_response))
@@ -1036,12 +1051,14 @@ int main(int argc, char **argv)
/* in case of manual mode, we are going into a polling loop */
if (attrs.pkiStatus == SCEP_PENDING)
{
identification_t *issuer = x509_ca_sig->get_subject(x509_ca_sig);
plog(" scep request pending, polling every %d seconds"
, poll_interval);
poll_start = time_monotonic(NULL);
issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc"
, x509_ca_sig->subject
, subject);
issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc",
issuer->get_encoding(issuer),
subject);
}
while (attrs.pkiStatus == SCEP_PENDING)
{
@@ -1110,13 +1127,20 @@ int main(int argc, char **argv)
{
bool stored = FALSE;
x509cert_t *cert = certs;
x509_t *x509 = (x509_t*)cert->cert;
if (!cert->isCA)
if (!(x509->get_flags(x509) & X509_CA))
{
if (stored)
{
exit_scepclient("multiple certs received, only first stored");
if (!chunk_write(cert->certificate, path, "requested cert", 0022, force))
}
encoding = cert->cert->get_encoding(cert->cert);
if (!chunk_write(encoding, path, "requested cert", 0022, force))
{
exit_scepclient("could not write cert file '%s'", path);
}
chunk_free(&encoding);
stored = TRUE;
}
certs = certs->next;