diff --git a/src/charon/plugins/stroke/stroke.c b/src/charon/plugins/stroke/stroke.c index c2c0dc3aa..ae7817667 100755 --- a/src/charon/plugins/stroke/stroke.c +++ b/src/charon/plugins/stroke/stroke.c @@ -829,8 +829,8 @@ static void add_crl(private_stroke_t *this, crl_t* crl) static void load_peer_cert(private_stroke_t *this, char *filename, identification_t **id) { + certificate_t *cert; char path[PATH_MAX]; - x509_t *x509; identification_t *peerid = *id; if (*filename == '/') @@ -841,12 +841,13 @@ static void load_peer_cert(private_stroke_t *this, { snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename); } - - x509 = x509_create_from_file(path, "end entity cert", 0); - - if (x509) + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, + BUILD_X509_FLAG, 0, + BUILD_END); + if (cert) { - certificate_t *cert = &x509->interface;; identification_t *subject = cert->get_subject(cert); if (!cert->has_subject(cert, peerid)) @@ -856,7 +857,7 @@ static void load_peer_cert(private_stroke_t *this, peerid->destroy(peerid); *id = subject->clone(subject); } - add_x509_cert(this, x509); + add_x509_cert(this, (x509_t*)cert); } } @@ -865,8 +866,8 @@ static void load_peer_cert(private_stroke_t *this, */ static certificate_t* load_ca_cert(private_stroke_t *this, char *filename) { + certificate_t *cert; char path[PATH_MAX]; - x509_t *x509; if (*filename == '/') { @@ -876,12 +877,14 @@ static certificate_t* load_ca_cert(private_stroke_t *this, char *filename) { snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename); } - - x509 = x509_create_from_file(path, "ca cert", X509_CA); - - if (x509) + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, + BUILD_X509_FLAG, X509_CA, + BUILD_END); + if (cert) { - return add_x509_cert(this, x509); + return add_x509_cert(this, (x509_t*)cert); } else { @@ -892,7 +895,7 @@ static certificate_t* load_ca_cert(private_stroke_t *this, char *filename) /** * load trusted certificates from a directory */ -static void load_certdir(private_stroke_t *this, char *path, char* label, +static void load_certdir(private_stroke_t *this, char *path, certificate_type_t type, x509_flag_t flag) { struct stat st; @@ -908,6 +911,8 @@ static void load_certdir(private_stroke_t *this, char *path, char* label, while (enumerator->enumerate(enumerator, NULL, &file, &st)) { + certificate_t *cert; + if (!S_ISREG(st.st_mode)) { /* skip special file */ @@ -916,46 +921,43 @@ static void load_certdir(private_stroke_t *this, char *path, char* label, switch (type) { case CERT_X509: + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, + BUILD_X509_FLAG, flag, + BUILD_END); + if (cert) { - x509_t *x509 = x509_create_from_file(file, label, flag); - - if (x509) - { - add_x509_cert(this, x509); - } + add_x509_cert(this, (x509_t*)cert); } break; case CERT_X509_CRL: + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_CRL, + BUILD_FROM_FILE, file, + BUILD_END); + if (cert) { - crl_t *crl = crl_create_from_file(file); - - if (crl) + /* only trusted crls are added to the store */ + if (verify_crl((crl_t*)cert)) { - certificate_t *cert = &crl->certificate; - - /* only trusted crls are added to the store */ - if (verify_crl(crl)) - { - add_crl(this, crl); - } - else - { - DBG1(DBG_CFG, " crl discarded"); - cert->destroy(cert); - } + add_crl(this, (crl_t*)cert); + } + else + { + DBG1(DBG_CFG, " crl discarded"); + cert->destroy(cert); } } break; case CERT_X509_AC: + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_AC, + BUILD_FROM_FILE, file, + BUILD_END); + if (cert) { - ac_t *ac = ac_create_from_file(file); - - if (ac) - { - certificate_t *cert = &ac->certificate; - cert->destroy(cert); - } } break; default: @@ -2904,32 +2906,32 @@ static void stroke_reread(private_stroke_t *this, { DBG1(DBG_CFG, "rereading ca certificates from '%s'", CA_CERTIFICATE_DIR); - load_certdir(this, CA_CERTIFICATE_DIR, "ca cert", CERT_X509, X509_CA); + load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA); } if (msg->reread.flags & REREAD_OCSPCERTS) { DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'", OCSP_CERTIFICATE_DIR); - load_certdir(this, OCSP_CERTIFICATE_DIR, "ocsp cert", CERT_X509, + load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER); } if (msg->reread.flags & REREAD_AACERTS) { DBG1(DBG_CFG, "rereading aa certificates from '%s'", AA_CERTIFICATE_DIR); - load_certdir(this, AA_CERTIFICATE_DIR, "aa cert", CERT_X509, X509_AA); + load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA); } if (msg->reread.flags & REREAD_ACERTS) { DBG1(DBG_CFG, "rereading attribute certificates from '%s'", ATTR_CERTIFICATE_DIR); - load_certdir(this, ATTR_CERTIFICATE_DIR, "attr cert", CERT_X509_AC, 0); + load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0); } if (msg->reread.flags & REREAD_CRLS) { DBG1(DBG_CFG, "rereading crls from '%s'", CRL_DIR); - load_certdir(this, CRL_DIR, "crl", CERT_X509_CRL, 0); + load_certdir(this, CRL_DIR, CERT_X509_CRL, 0); } } @@ -3201,23 +3203,23 @@ static void load_certs(private_stroke_t *this) { DBG1(DBG_CFG, "loading ca certificates from '%s'", CA_CERTIFICATE_DIR); - load_certdir(this, CA_CERTIFICATE_DIR, "ca cert", CERT_X509, X509_CA); + load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA); DBG1(DBG_CFG, "loading aa certificates from '%s'", AA_CERTIFICATE_DIR); - load_certdir(this, AA_CERTIFICATE_DIR, "aa cert", CERT_X509, X509_AA); + load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA); DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'", OCSP_CERTIFICATE_DIR); - load_certdir(this, OCSP_CERTIFICATE_DIR, "ocsp cert", CERT_X509, X509_OCSP_SIGNER); + load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER); DBG1(DBG_CFG, "loading attribute certificates from '%s'", ATTR_CERTIFICATE_DIR); - load_certdir(this, ATTR_CERTIFICATE_DIR, "attr cert", CERT_X509_AC, 0); + load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0); DBG1(DBG_CFG, "loading crls from '%s'", CRL_DIR); - load_certdir(this, CRL_DIR, "crl", CERT_X509_CRL, 0); + load_certdir(this, CRL_DIR, CERT_X509_CRL, 0); } /* diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 435f8bbba..5f2169cc4 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -34,7 +34,7 @@ credentials/keys/public_key.c credentials/keys/public_key.h \ credentials/keys/shared_key.c credentials/keys/shared_key.h \ credentials/certificates/certificate.c credentials/certificates/certificate.h \ credentials/certificates/x509.h credentials/certificates/x509.c \ -credentials/certificates/ac.h credentials/certificates/ac.c \ +credentials/certificates/ac.h \ credentials/certificates/crl.h credentials/certificates/crl.c \ credentials/certificates/ocsp_request.h credentials/certificates/ocsp_request.c \ credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \ diff --git a/src/libstrongswan/credentials/certificates/ac.c b/src/libstrongswan/credentials/certificates/ac.c deleted file mode 100644 index fb7e29872..000000000 --- a/src/libstrongswan/credentials/certificates/ac.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler - * Copyright (C) 2003 Martin Berner, Lukas Suter - * Copyright (C) 2002-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * $Id: ac.h 3300 2007-10-12 21:53:18Z andreas $ - */ - -#include -#include -#include - -#include "ac.h" - -/* - * Defined in header. - */ -ac_t* ac_create_from_file(char *path) -{ - ac_t *ac; - bool pgp = FALSE; - chunk_t chunk; - - if (!pem_asn1_load_file(path, NULL, &chunk, &pgp)) - { - DBG1(" could not load attr cert file '%s'", path); - return NULL; - } -/* ac = (ac_t*)lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_AC, - BUILD_BLOB_ASN1_DER, chunk, BUILD_END); -*/ - ac = NULL; - if (ac == NULL) - { - DBG1(" could not parse loaded attr cert file '%s'", path); - return NULL; - } - DBG1(" loaded attr cert file '%s'", path); - return ac; -} - - diff --git a/src/libstrongswan/credentials/certificates/ac.h b/src/libstrongswan/credentials/certificates/ac.h index 64d2d8d0b..7a3b747e0 100644 --- a/src/libstrongswan/credentials/certificates/ac.h +++ b/src/libstrongswan/credentials/certificates/ac.h @@ -54,10 +54,5 @@ struct ac_t { bool (*equals_holder) (const ac_t *this, const ac_t *other); }; -/** - * Load and parse an X.509 attribute certificate file - */ -ac_t* ac_create_from_file(char *path); - #endif /* AC_H_ @}*/ diff --git a/src/libstrongswan/credentials/certificates/crl.c b/src/libstrongswan/credentials/certificates/crl.c index 2eda5306d..92ac5319d 100644 --- a/src/libstrongswan/credentials/certificates/crl.c +++ b/src/libstrongswan/credentials/certificates/crl.c @@ -16,9 +16,6 @@ * $Id$ */ -#include -#include -#include #include "crl.h" ENUM(crl_reason_names, CRL_UNSPECIFIED, CRL_REMOVE_FROM_CRL, @@ -32,29 +29,3 @@ ENUM(crl_reason_names, CRL_UNSPECIFIED, CRL_REMOVE_FROM_CRL, "reason #7", "remove from crl", ); - -/* - * Defined in header. - */ -crl_t* crl_create_from_file(char *path) -{ - crl_t *crl; - bool pgp = FALSE; - chunk_t chunk; - - if (!pem_asn1_load_file(path, NULL, &chunk, &pgp)) - { - DBG1(" could not load crl file '%s'", path); - return NULL; - } - crl = (crl_t*)lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_CRL, - BUILD_BLOB_ASN1_DER, chunk, BUILD_END); - if (crl == NULL) - { - DBG1(" could not parse loaded crl file '%s'", path); - return NULL; - } - DBG1(" loaded crl file '%s'", path); - return crl; -} diff --git a/src/libstrongswan/credentials/certificates/crl.h b/src/libstrongswan/credentials/certificates/crl.h index 3fe43916f..78c9d86f9 100644 --- a/src/libstrongswan/credentials/certificates/crl.h +++ b/src/libstrongswan/credentials/certificates/crl.h @@ -85,9 +85,4 @@ struct crl_t { }; -/** - * Load and parse an X.509 crl file - */ -crl_t* crl_create_from_file(char *path); - #endif /* CRL_H_ @}*/ diff --git a/src/libstrongswan/credentials/certificates/x509.c b/src/libstrongswan/credentials/certificates/x509.c index b354d489a..018360165 100644 --- a/src/libstrongswan/credentials/certificates/x509.c +++ b/src/libstrongswan/credentials/certificates/x509.c @@ -15,10 +15,6 @@ * $Id$ */ -#include -#include -#include - #include "x509.h" ENUM(x509_flag_names, X509_CA, X509_SELF_SIGNED, @@ -28,49 +24,3 @@ ENUM(x509_flag_names, X509_CA, X509_SELF_SIGNED, "X509_SELF_SIGNED", ); -/* - * Defined in header. - */ -x509_t* x509_create_from_file(char *path, char *label, x509_flag_t flag) -{ - bool pgp = FALSE; - chunk_t chunk; - x509_t *x509; - certificate_t *cert; - time_t notBefore, notAfter, now; - - if (!pem_asn1_load_file(path, NULL, &chunk, &pgp)) - { - DBG1(" could not load %s file '%s'", label, path); - return NULL; - } - x509 = (x509_t*)lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, chunk, - BUILD_X509_FLAG, flag, - BUILD_END); - if (x509 == NULL) - { - DBG1(" could not parse loaded %s file '%s'",label, path); - return NULL; - } - DBG1(" loaded %s file '%s'", label, path); - - /* check validity */ - cert = &x509->interface; - now = time(NULL); - cert->get_validity(cert, &now, ¬Before, ¬After); - if (now > notAfter) - { - DBG1(" certificate expired at %T, discarded", ¬After); - cert->destroy(cert); - return NULL; - } - if (now < notBefore) - { - DBG1(" certificate not valid before %T", ¬Before); - } - return x509; -} - - diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h index d368a8a56..3a90db53c 100644 --- a/src/libstrongswan/credentials/certificates/x509.h +++ b/src/libstrongswan/credentials/certificates/x509.h @@ -104,9 +104,4 @@ struct x509_t { enumerator_t* (*create_ocsp_uri_enumerator)(x509_t *this); }; -/** - * Load and parse an X.509 certificate file - */ -x509_t* x509_create_from_file(char *path, char *label, x509_flag_t flag); - #endif /* X509_H_ @}*/ diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index 6a2eae418..fb4074c36 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -29,6 +29,9 @@ #include #include +extern identification_t* x509_parse_authorityKeyIdentifier(chunk_t blob, + int level0, chunk_t *authKeySerialNumber); + typedef struct private_x509_ac_t private_x509_ac_t; /** @@ -42,7 +45,7 @@ struct private_x509_ac_t { x509_ac_t public; /** - * X.509 attribute certificate in DER format + * X.509 attribute certificate encoding in ASN.1 DER format */ chunk_t encoding; @@ -81,11 +84,6 @@ struct private_x509_ac_t { */ identification_t *issuerName; - /** - * Signature algorithm - */ - int algorithm; - /** * Start time of certificate validity */ @@ -121,6 +119,11 @@ struct private_x509_ac_t { */ bool noRevAvail; + /** + * Signature algorithm + */ + int algorithm; + /** * Signature */ @@ -256,7 +259,6 @@ static const asn1Object_t acObjects[] = { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */ }; -#define AC_OBJ_CERTIFICATE 0 #define AC_OBJ_CERTIFICATE_INFO 1 #define AC_OBJ_VERSION 2 #define AC_OBJ_HOLDER_ISSUER 5 @@ -277,6 +279,224 @@ static const asn1Object_t acObjects[] = #define AC_OBJ_SIGNATURE 54 #define AC_OBJ_ROOF 55 +/** + * Parses an X.509 attribute certificate + */ +static bool parse(private_x509_ac_t *this) +{ + return FALSE; +} +/** + * parses a directoryName + */ +static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name) +{ + bool has_directoryName; + linked_list_t *list = linked_list_create(); + + x509_parse_generalNames(blob, level, implicit, list); + has_directoryName = list->get_count(list) > 0; + + if (has_directoryName) + { + iterator_t *iterator = list->create_iterator(list, TRUE); + identification_t *directoryName; + bool first = TRUE; + + while (iterator->iterate(iterator, (void**)&directoryName)) + { + if (first) + { + *name = directoryName; + first = FALSE; + } + else + { + DBG1("more than one directory name - first selected"); + directoryName->destroy(directoryName); + } + } + iterator->destroy(iterator); + } + else + { + DBG1("no directoryName found"); + } + + list->destroy(list); + return has_directoryName; +} + +/** + * parses roleSyntax + */ +static void parse_roleSyntax(chunk_t blob, int level0) +{ + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; + + asn1_init(&ctx, blob, level0, FALSE, FALSE); + while (objectID < ROLE_ROOF) + { + if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) + { + return; + } + + switch (objectID) + { + default: + break; + } + objectID++; + } +} + +/** + * Parses an X.509 attribute certificate + */ +static bool parse_certificate(private_x509_ac_t *this) +{ + asn1_ctx_t ctx; + bool critical; + chunk_t object; + u_int level; + int objectID = 0; + int type = OID_UNKNOWN; + int extn_oid = OID_UNKNOWN; + int sig_alg = OID_UNKNOWN; + + asn1_init(&ctx, this->encoding, 0, FALSE, FALSE); + while (objectID < AC_OBJ_ROOF) + { + if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) + { + return FALSE; + } + + /* those objects which will parsed further need the next higher level */ + level++; + + switch (objectID) + { + case AC_OBJ_CERTIFICATE_INFO: + this->certificateInfo = object; + break; + case AC_OBJ_VERSION: + this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; + DBG2(" v%d", this->version); + if (this->version != 2) + { + DBG1("v%d attribute certificates are not supported", this->version); + return FALSE; + } + break; + case AC_OBJ_HOLDER_ISSUER: + if (!parse_directoryName(object, level, FALSE, &this->holderIssuer)) + { + return FALSE; + } + break; + case AC_OBJ_HOLDER_SERIAL: + this->holderSerial = object; + break; + case AC_OBJ_ENTITY_NAME: + if (!parse_directoryName(object, level, TRUE, &this->entityName)) + { + return FALSE; + } + break; + case AC_OBJ_ISSUER_NAME: + if (!parse_directoryName(object, level, FALSE, &this->issuerName)) + { + return FALSE; + } + break; + case AC_OBJ_SIG_ALG: + sig_alg = parse_algorithmIdentifier(object, level, NULL); + break; + case AC_OBJ_SERIAL_NUMBER: + this->serialNumber = object; + break; + case AC_OBJ_NOT_BEFORE: + this->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case AC_OBJ_NOT_AFTER: + this->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case AC_OBJ_ATTRIBUTE_TYPE: + type = known_oid(object); + break; + case AC_OBJ_ATTRIBUTE_VALUE: + { + switch (type) + { + case OID_AUTHENTICATION_INFO: + DBG2(" need to parse authenticationInfo"); + break; + case OID_ACCESS_IDENTITY: + DBG2(" need to parse accessIdentity"); + break; + case OID_CHARGING_IDENTITY: + ietfAttr_list_create_from_chunk(object, this->charging, level); + break; + case OID_GROUP: + ietfAttr_list_create_from_chunk(object, this->groups, level); + break; + case OID_ROLE: + parse_roleSyntax(object, level); + break; + default: + break; + } + } + break; + case AC_OBJ_EXTN_ID: + extn_oid = known_oid(object); + break; + case AC_OBJ_CRITICAL: + critical = object.len && *object.ptr; + DBG2(" %s",(critical)?"TRUE":"FALSE"); + break; + case AC_OBJ_EXTN_VALUE: + { + switch (extn_oid) + { + case OID_CRL_DISTRIBUTION_POINTS: + DBG2(" need to parse crlDistributionPoints"); + break; + case OID_AUTHORITY_KEY_ID: + this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object, + level, &this->authKeySerialNumber); + break; + break; + case OID_TARGET_INFORMATION: + DBG2(" need to parse targetInformation"); + break; + case OID_NO_REV_AVAIL: + this->noRevAvail = TRUE; + break; + default: + break; + } + } + break; + case AC_OBJ_ALGORITHM: + this->algorithm != parse_algorithmIdentifier(object, level, NULL); + break; + case AC_OBJ_SIGNATURE: + this->signature = object; + break; + default: + break; + } + objectID++; + } + return TRUE; +} + /** * build directoryName */ @@ -678,7 +898,7 @@ static void destroy(private_x509_ac_t *this) /** * create an empty but initialized X.509 attribute certificate */ -static private_x509_ac_t *create_empty() +static private_x509_ac_t *create_empty(void) { private_x509_ac_t *this = malloc_thing(private_x509_ac_t); @@ -712,6 +932,47 @@ static private_x509_ac_t *create_empty() return this; } +/** + * create X.509 attribute certificate from a chunk + */ +static private_x509_ac_t* create_from_chunk(chunk_t chunk) +{ + private_x509_ac_t *this = create_empty(); + + this->encoding = chunk; + if (!parse_certificate(this)) + { + destroy(this); + return NULL; + } + return this; +} + +/** + * create X.509 crl from a file + */ +static private_x509_ac_t* create_from_file(char *path) +{ + bool pgp = FALSE; + chunk_t chunk; + private_x509_ac_t *this; + + if (!pem_asn1_load_file(path, NULL, &chunk, &pgp)) + { + return NULL; + } + + this = create_from_chunk(chunk); + + if (this == NULL) + { + DBG1(" could not parse loaded attribute certificate file '%s'", path); + return NULL; + } + DBG1(" loaded attribute certificate file '%s'", path); + return this; +} + typedef struct private_builder_t private_builder_t; /** * Builder implementation for certificate loading @@ -726,19 +987,23 @@ struct private_builder_t { /** * Implementation of builder_t.build */ -static x509_ac_t *build(private_builder_t *this) +static private_x509_ac_t* build(private_builder_t *this) { - private_x509_ac_t *ac; - - ac = this->ac; + private_x509_ac_t *ac = this->ac; + free(this); - if (ac->holderCert && ac->signerCert && ac->signerKey) + + /* synthesis if TRUE or analysis if FALSE */ + if (ac->encoding.ptr == NULL) { - ac->encoding = build_ac(ac); - return &ac->public; + if (ac->holderCert && ac->signerCert && ac->signerKey) + { + ac->encoding = build_ac(ac); + return ac; + } + destroy(ac); + return NULL; } - destroy(ac); - return NULL; } /** @@ -752,6 +1017,20 @@ static void add(private_builder_t *this, builder_part_t part, ...) va_start(args, part); switch (part) { + case BUILD_FROM_FILE: + if (this->ac) + { + destroy(this->ac); + } + this->ac = create_from_file(va_arg(args, char*)); + break; + case BUILD_BLOB_ASN1_DER: + if (this->ac) + { + destroy(this->ac); + } + this->ac = create_from_chunk(va_arg(args, chunk_t)); + break; case BUILD_NOT_BEFORE_TIME: this->ac->notBefore = va_arg(args, time_t); break; diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 3a814a8c0..e52416c51 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -66,7 +66,7 @@ struct private_x509_cert_t { x509_cert_t public; /** - * DER encoded X.509 certificate + * X.509 certificate encoding in ASN.1 DER format */ chunk_t encoding; @@ -735,8 +735,8 @@ static bool parse_certificate(private_x509_cert_t *this) u_int level; int objectID = 0; int extn_oid = OID_UNKNOWN; - int key_alg = 0; - int sig_alg = 0; + int key_alg = OID_UNKNOWN; + int sig_alg = OID_UNKNOWN; chunk_t subjectPublicKey = chunk_empty; asn1_init(&ctx, this->encoding, 0, FALSE, FALSE); @@ -1163,9 +1163,9 @@ static void destroy(private_x509_cert_t *this) } /** - * load x509 certificate from a chunk + * create an empty but initialized X.509 certificate */ -static private_x509_cert_t *load(chunk_t chunk) +static private_x509_cert_t* create_empty(void) { private_x509_cert_t *this = malloc_thing(private_x509_cert_t); @@ -1189,7 +1189,7 @@ static private_x509_cert_t *load(chunk_t chunk) this->public.interface.create_crl_uri_enumerator = (enumerator_t* (*)(x509_t*))create_crl_uri_enumerator; this->public.interface.create_ocsp_uri_enumerator = (enumerator_t* (*)(x509_t*))create_ocsp_uri_enumerator; - this->encoding = chunk; + this->encoding = chunk_empty; this->public_key = NULL; this->subject = NULL; this->issuer = NULL; @@ -1201,13 +1201,24 @@ static private_x509_cert_t *load(chunk_t chunk) this->authKeySerialNumber = chunk_empty; this->flags = 0; this->ref = 1; - + + return this; +} + +/** + * create an X.509 certificate from a chunk + */ +static private_x509_cert_t *create_from_chunk(chunk_t chunk) +{ + private_x509_cert_t *this = create_empty(); + + this->encoding = chunk; if (!parse_certificate(this)) { destroy(this); return NULL; } - + /* check if the certificate is self-signed */ if (issued_by(this, &this->public.interface.interface, TRUE)) { @@ -1216,6 +1227,32 @@ static private_x509_cert_t *load(chunk_t chunk) return this; } +/** + * create an X.509 certificate from a file + */ +static private_x509_cert_t *create_from_file(char *path) +{ + bool pgp = FALSE; + chunk_t chunk; + private_x509_cert_t *this; + + if (!pem_asn1_load_file(path, NULL, &chunk, &pgp)) + { + return NULL; + } + + this = create_from_chunk(chunk); + + if (this == NULL) + { + DBG1(" could not parse loaded certificate file '%s'",path); + return NULL; + } + DBG1(" loaded certificate file '%s'", path); + return this; + +} + typedef struct private_builder_t private_builder_t; /** * Builder implementation for certificate loading @@ -1232,14 +1269,24 @@ struct private_builder_t { /** * Implementation of builder_t.build */ -static x509_cert_t *build(private_builder_t *this) +static private_x509_cert_t *build(private_builder_t *this) { - private_x509_cert_t *cert; - - cert = this->cert; - cert->flags |= this->flags; + private_x509_cert_t *cert = this->cert; + x509_flag_t flags = this->flags; + free(this); - return &cert->public; + if (cert == NULL) + { + return NULL; + } + if ((flags & X509_CA) && !(cert->flags & X509_CA)) + { + DBG1(" ca certificate must have ca basic constraint set, discarded"); + destroy(cert); + return NULL; + } + cert->flags |= flags; + return cert; } /** @@ -1252,12 +1299,11 @@ static void add(private_builder_t *this, builder_part_t part, ...) va_start(args, part); switch (part) { + case BUILD_FROM_FILE: + this->cert = create_from_file(va_arg(args, char*)); + break; case BUILD_BLOB_ASN1_DER: - if (this->cert) - { - destroy(this->cert); - } - this->cert = load(va_arg(args, chunk_t)); + this->cert = create_from_chunk(va_arg(args, chunk_t)); break; case BUILD_X509_FLAG: this->flags = va_arg(args, x509_flag_t); diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index 4c2511be1..c67e87962 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -57,9 +57,9 @@ struct private_x509_crl_t { x509_crl_t public; /** - * X.509 crl in DER format + * X.509 crl encoding in ASN.1 DER format */ - chunk_t certificateList; + chunk_t encoding; /** * X.509 crl body over which signature is computed @@ -201,7 +201,7 @@ static bool parse(private_x509_crl_t *this) u_int level; int objectID = 0; - asn1_init(&ctx, this->certificateList, 0, FALSE, FALSE); + asn1_init(&ctx, this->encoding, 0, FALSE, FALSE); while (objectID < CRL_OBJ_ROOF) { if (!extract_object(crlObjects, &objectID, &object, &level, &ctx)) @@ -567,7 +567,7 @@ static bool is_newer(private_x509_crl_t *this, crl_t *that) */ static chunk_t get_encoding(private_x509_crl_t *this) { - return chunk_clone(this->certificateList); + return chunk_clone(this->encoding); } /** @@ -598,15 +598,15 @@ static void destroy(private_x509_crl_t *this) this->revoked->destroy_function(this->revoked, free); DESTROY_IF(this->issuer); DESTROY_IF(this->authKeyIdentifier); - free(this->certificateList.ptr); + free(this->encoding.ptr); free(this); } } /** - * load a X509 CRL from a chunk of date (ASN1 DER) + * create an empty but initialized X.509 crl */ -static x509_crl_t *load(chunk_t chunk) +static private_x509_crl_t* create_empty(void) { private_x509_crl_t *this = malloc_thing(private_x509_crl_t); @@ -627,7 +627,7 @@ static x509_crl_t *load(chunk_t chunk) this->public.crl.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref; this->public.crl.certificate.destroy = (void (*)(certificate_t *this))destroy; - this->certificateList = chunk; + this->encoding = chunk_empty; this->tbsCertList = chunk_empty; this->issuer = NULL; this->crlNumber = chunk_empty; @@ -636,13 +636,48 @@ static x509_crl_t *load(chunk_t chunk) this->authKeySerialNumber = chunk_empty; this->ref = 1; + return this; +} + +/** + * create an X.509 crl from a chunk + */ +static private_x509_crl_t* create_from_chunk(chunk_t chunk) +{ + private_x509_crl_t *this = create_empty(); + + this->encoding = chunk; if (!parse(this)) { destroy(this); return NULL; } + return this; +} + +/** + * create an X.509 crl from a file + */ +static private_x509_crl_t* create_from_file(char *path) +{ + bool pgp = FALSE; + chunk_t chunk; + private_x509_crl_t *this; - return &this->public; + if (!pem_asn1_load_file(path, NULL, &chunk, &pgp)) + { + return NULL; + } + + this = create_from_chunk(chunk); + + if (this == NULL) + { + DBG1(" could not parse loaded crl file '%s'",path); + return NULL; + } + DBG1(" loaded crl file '%s'", path); + return this; } typedef struct private_builder_t private_builder_t; @@ -653,15 +688,15 @@ struct private_builder_t { /** implements the builder interface */ builder_t public; /** loaded CRL */ - x509_crl_t *crl; + private_x509_crl_t *crl; }; /** * Implementation of builder_t.build */ -static x509_crl_t *build(private_builder_t *this) +static private_x509_crl_t *build(private_builder_t *this) { - x509_crl_t *crl = this->crl; + private_x509_crl_t *crl = this->crl; free(this); return crl; @@ -680,19 +715,22 @@ static void add(private_builder_t *this, builder_part_t part, ...) return; } + va_start(args, part); switch (part) { + case BUILD_FROM_FILE: + this->crl = create_from_file(va_arg(args, char*)); + break; case BUILD_BLOB_ASN1_DER: { - va_start(args, part); - this->crl = load(va_arg(args, chunk_t)); - va_end(args); + this->crl = create_from_chunk(va_arg(args, chunk_t)); break; } default: DBG1("ignoring unsupported build part %N", builder_part_names, part); break; } + va_end(args); } /** diff --git a/src/openac/openac.c b/src/openac/openac.c index b1ac1242d..799299dbd 100755 --- a/src/openac/openac.c +++ b/src/openac/openac.c @@ -488,25 +488,29 @@ int main(int argc, char **argv) /* load the signer's X.509 certificate */ if (certfile != NULL) { - x509_t *x509 = x509_create_from_file(certfile, "signer cert", 0); - - if (x509 == NULL) + signerCert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, certfile, + BUILD_X509_FLAG, 0, + BUILD_END); + if (signerCert == NULL) { goto end; } - signerCert = &x509->interface; } /* load the users's X.509 certificate */ if (usercertfile != NULL) { - x509_t *x509 = x509_create_from_file(usercertfile, "user cert", 0); - - if (x509 == NULL) + userCert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, usercertfile, + BUILD_X509_FLAG, 0, + BUILD_END); + if (userCert == NULL) { goto end; } - userCert = &x509->interface; } /* compute validity interval */