diff options
author | Martin Willi <martin@strongswan.org> | 2009-09-09 16:24:06 +0200 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2009-09-10 16:20:21 +0200 |
commit | d73f453c29cec10392fddfe08c899d2d5238d661 (patch) | |
tree | f9f16536ea93c2bd69944f786223e64d24ea00b3 /src/libstrongswan/plugins/x509 | |
parent | 91ef5c66ab82e3694f18a3a91b8b199a180e171c (diff) | |
download | strongswan-d73f453c29cec10392fddfe08c899d2d5238d661.tar.bz2 strongswan-d73f453c29cec10392fddfe08c899d2d5238d661.tar.xz |
Updated x509 plugin to the new builder API
Diffstat (limited to 'src/libstrongswan/plugins/x509')
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ac.c | 182 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ac.h | 30 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_cert.c | 400 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_cert.h | 27 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_crl.c | 86 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_crl.h | 11 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_request.c | 135 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_request.h | 12 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_response.c | 82 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_response.h | 11 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_plugin.c | 30 |
11 files changed, 405 insertions, 601 deletions
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index 219b0cbac..0b73a3791 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -2,6 +2,7 @@ * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter * Copyright (C) 2002-2008 Andreas Steffen + * Copyright (C) 2009 Martin Willi * * Hochschule fuer Technik Rapperswil * @@ -940,140 +941,93 @@ static private_x509_ac_t *create_empty(void) } /** - * create X.509 attribute certificate from a chunk + * See header. */ -static private_x509_ac_t* create_from_chunk(chunk_t chunk) +x509_ac_t *x509_ac_load(certificate_type_t type, va_list args) { - private_x509_ac_t *this = create_empty(); + chunk_t blob = chunk_empty; - this->encoding = chunk; - if (!parse_certificate(this)) + while (TRUE) { - destroy(this); - return NULL; + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_ASN1_DER: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; } - return this; -} - -typedef struct private_builder_t private_builder_t; -/** - * Builder implementation for certificate loading - */ -struct private_builder_t { - /** implements the builder interface */ - builder_t public; - /** X.509 attribute certificate to build */ - private_x509_ac_t *ac; -}; - -/** - * Implementation of builder_t.build - */ -static private_x509_ac_t* build(private_builder_t *this) -{ - private_x509_ac_t *ac = this->ac; - - free(this); - - /* synthesis if encoding does not exist */ - if (ac && ac->encoding.ptr == NULL) + if (blob.ptr) { - if (ac->holderCert && ac->signerCert && ac->signerKey) + private_x509_ac_t *ac = create_empty(); + + ac->encoding = chunk_clone(blob); + if (parse_certificate(ac)) { - ac->encoding = build_ac(ac); - return ac; + return &ac->public; } destroy(ac); - return NULL; - } - else - { - return ac; } + return NULL; } /** - * Implementation of builder_t.add + * See header. */ -static void add(private_builder_t *this, builder_part_t part, ...) +x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) { - va_list args; - certificate_t *cert; - chunk_t chunk; + private_x509_ac_t *ac; - va_start(args, part); - switch (part) + ac = create_empty(); + while (TRUE) { - case BUILD_BLOB_ASN1_DER: - if (this->ac) - { - destroy(this->ac); - } - chunk = va_arg(args, chunk_t); - this->ac = create_from_chunk(chunk_clone(chunk)); - break; - case BUILD_NOT_BEFORE_TIME: - this->ac->notBefore = va_arg(args, time_t); - break; - case BUILD_NOT_AFTER_TIME: - this->ac->notAfter = va_arg(args, time_t); - break; - case BUILD_SERIAL: - chunk = va_arg(args, chunk_t); - this->ac->serialNumber = chunk_clone(chunk); - break; - case BUILD_IETF_GROUP_ATTR: - ietfAttr_list_create_from_string(va_arg(args, char*), - this->ac->groups); - break; - case BUILD_CERT: - cert = va_arg(args, certificate_t*); - if (cert->get_type(cert) == CERT_X509) - { - this->ac->holderCert = cert->get_ref(cert); - } - break; - case BUILD_SIGNING_CERT: - cert = va_arg(args, certificate_t*); - if (cert->get_type(cert) == CERT_X509) - { - this->ac->signerCert = cert->get_ref(cert); - } - break; - case BUILD_SIGNING_KEY: - this->ac->signerKey = va_arg(args, private_key_t*); - this->ac->signerKey->get_ref(this->ac->signerKey); - break; - default: - /* abort if unsupported option */ - if (this->ac) - { - destroy(this->ac); - } - builder_cancel(&this->public); - break; + switch (va_arg(args, builder_part_t)) + { + case BUILD_NOT_BEFORE_TIME: + ac->notBefore = va_arg(args, time_t); + continue; + case BUILD_NOT_AFTER_TIME: + ac->notAfter = va_arg(args, time_t); + continue; + case BUILD_SERIAL: + ac->serialNumber = chunk_clone(va_arg(args, chunk_t)); + continue; + case BUILD_IETF_GROUP_ATTR: + ietfAttr_list_create_from_string(va_arg(args, char*), ac->groups); + continue; + case BUILD_CERT: + ac->holderCert = va_arg(args, certificate_t*); + ac->holderCert->get_ref(ac->holderCert); + continue; + case BUILD_SIGNING_CERT: + ac->signerCert = va_arg(args, certificate_t*); + ac->signerCert->get_ref(ac->signerCert); + continue; + case BUILD_SIGNING_KEY: + ac->signerKey = va_arg(args, private_key_t*); + ac->signerKey->get_ref(ac->signerKey); + continue; + case BUILD_END: + break; + default: + destroy(ac); + return NULL; + } + break; } - va_end(args); -} -/** - * Builder construction function - */ -builder_t *x509_ac_builder(certificate_type_t type) -{ - private_builder_t *this; - - if (type != CERT_X509_AC) + if (ac->signerKey && ac->holderCert && ac->signerCert && + ac->holderCert->get_type(ac->holderCert) == CERT_X509 && + ac->signerCert->get_type(ac->signerCert) == CERT_X509) { - return NULL; + ac->encoding = build_ac(ac); + return &ac->public; } - - this = malloc_thing(private_builder_t); - - this->ac = create_empty(); - this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; - this->public.build = (void*(*)(builder_t *this))build; - - return &this->public; + destroy(ac); + return NULL; } diff --git a/src/libstrongswan/plugins/x509/x509_ac.h b/src/libstrongswan/plugins/x509/x509_ac.h index 958d5c57a..da0988c6e 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.h +++ b/src/libstrongswan/plugins/x509/x509_ac.h @@ -2,6 +2,7 @@ * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter * Copyright (C) 2002-2008 Andreas Steffen + * Copyright (C) 2009 Martin Willi * * Hochschule fuer Technik Rapperswil * @@ -24,6 +25,7 @@ #ifndef X509_AC_H_ #define X509_AC_H_ +#include <credentials/builder.h> #include <credentials/certificates/ac.h> typedef struct x509_ac_t x509_ac_t; @@ -40,18 +42,28 @@ struct x509_ac_t { }; /** - * Create the building facility for X.509 attribute certificates. + * Load a X.509 attribute certificate. * - * The resulting builder accepts: - * BUILD_USER_CERT: user certificate, exactly one - * BUILD_SIGNER_CERT: signer certificate, exactly one - * BUILD_SIGNER_KEY: signer private key, exactly one - * BUILD_SERIAL: serial number, exactly one - * BUILD_GROUP_ATTR: group attribute, optional, several possible + * @param type certificate type, CERT_X509_AC only + * @param args builder_part_t argument list + * @return X.509 Attribute certificate, NULL on failure + */ +x509_ac_t *x509_ac_load(certificate_type_t type, va_list args); + +/** + * Generate a X.509 attribute certificate. + * + * Accepted build parts: + * BUILD_USER_CERT: user certificate + * BUILD_SIGNER_CERT: signer certificate + * BUILD_SIGNER_KEY: signer private key + * BUILD_SERIAL: serial number + * BUILD_GROUP_ATTR: group attribute, several possible * * @param type certificate type, CERT_X509_AC only - * @return builder instance to build X.509 attribute certificates + * @param args builder_part_t argument list + * @return X.509 Attribute certificate, NULL on failure */ -builder_t *x509_ac_builder(certificate_type_t type); +x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args); #endif /** X509_AC_H_ @}*/ diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index ae2ba19f7..c68bd1d20 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -3,7 +3,7 @@ * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss * Copyright (C) 2002 Mario Strasser * Copyright (C) 2000-2006 Andreas Steffen - * Copyright (C) 2006-2008 Martin Willi + * Copyright (C) 2006-2009 Martin Willi * Copyright (C) 2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * @@ -676,6 +676,11 @@ static const asn1Object_t certObjects[] = { #define X509_OBJ_SIGNATURE 25 /** + * forward declaration + */ +static bool issued_by(private_x509_cert_t *this, certificate_t *issuer); + +/** * Parses an X.509v3 certificate */ static bool parse_certificate(private_x509_cert_t *this) @@ -810,6 +815,25 @@ static bool parse_certificate(private_x509_cert_t *this) end: parser->destroy(parser); + if (success) + { + hasher_t *hasher; + + /* check if the certificate is self-signed */ + if (issued_by(this, &this->public.interface.interface)) + { + this->flags |= X509_SELF_SIGNED; + } + /* create certificate hash */ + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1(" unable to create hash of certificate, SHA1 not supported"); + return NULL; + } + hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash); + hasher->destroy(hasher); + } return success; } @@ -910,17 +934,18 @@ static bool issued_by(private_x509_cert_t *this, certificate_t *issuer) return FALSE; } - /* get the public key of the issuer */ - key = issuer->get_public_key(issuer); - /* determine signature scheme */ scheme = signature_scheme_from_oid(this->algorithm); - - if (scheme == SIGN_UNKNOWN || key == NULL) + if (scheme == SIGN_UNKNOWN) + { + return FALSE; + } + /* get the public key of the issuer */ + key = issuer->get_public_key(issuer); + if (!key) { return FALSE; } - /* TODO: add a lightweight check option (comparing auth/subject keyids only) */ valid = key->verify(key, scheme, this->tbsCertificate, this->signature); key->destroy(key); return valid; @@ -1150,63 +1175,10 @@ static private_x509_cert_t* create_empty(void) } /** - * create an X.509 certificate from a chunk - */ -static private_x509_cert_t *create_from_chunk(chunk_t chunk) -{ - hasher_t *hasher; - private_x509_cert_t *this = create_empty(); - - this->encoding = chunk; - this->parsed = TRUE; - if (!parse_certificate(this)) - { - destroy(this); - return NULL; - } - - /* check if the certificate is self-signed */ - if (issued_by(this, &this->public.interface.interface)) - { - this->flags |= X509_SELF_SIGNED; - } - - hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (hasher == NULL) - { - DBG1(" unable to create hash of certificate, SHA1 not supported"); - destroy(this); - return NULL; - } - hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash); - hasher->destroy(hasher); - - return this; -} - -typedef struct private_builder_t private_builder_t; -/** - * Builder implementation for certificate loading - */ -struct private_builder_t { - /** implements the builder interface */ - builder_t public; - /** loaded certificate */ - private_x509_cert_t *cert; - /** additional flags to enforce */ - x509_flag_t flags; - /** certificate to sign, if we generate a new cert */ - certificate_t *sign_cert; - /** private key to sign, if we generate a new cert */ - private_key_t *sign_key; - /** digest algorithm to be used for signature */ - hash_algorithm_t digest_alg; -}; - -/** * Generate and sign a new certificate */ -static bool generate(private_builder_t *this) +static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, + private_key_t *sign_key, int digest_alg) { chunk_t extensions = chunk_empty; chunk_t basicConstraints = chunk_empty, subjectAltNames = chunk_empty; @@ -1218,11 +1190,11 @@ static bool generate(private_builder_t *this) enumerator_t *enumerator; identification_t *id; - subject = this->cert->subject; - if (this->sign_cert) + subject = cert->subject; + if (sign_cert) { - issuer = this->sign_cert->get_subject(this->sign_cert); - if (!this->cert->public_key) + issuer = sign_cert->get_subject(sign_cert); + if (!cert->public_key) { return FALSE; } @@ -1230,65 +1202,64 @@ static bool generate(private_builder_t *this) else { /* self signed */ issuer = subject; - if (!this->cert->public_key) + if (!cert->public_key) { - this->cert->public_key = this->sign_key->get_public_key(this->sign_key); + cert->public_key = sign_key->get_public_key(sign_key); } - this->flags |= X509_SELF_SIGNED; + cert->flags |= X509_SELF_SIGNED; } - this->cert->issuer = issuer->clone(issuer); - if (!this->cert->notBefore) + cert->issuer = issuer->clone(issuer); + if (!cert->notBefore) { - this->cert->notBefore = time(NULL); + cert->notBefore = time(NULL); } - if (!this->cert->notAfter) + if (!cert->notAfter) { /* defaults to 1 year from now */ - this->cert->notAfter = this->cert->notBefore + 60 * 60 * 24 * 365; + cert->notAfter = cert->notBefore + 60 * 60 * 24 * 365; } - this->cert->flags = this->flags; /* select signature scheme */ - switch (this->sign_key->get_type(this->sign_key)) + switch (sign_key->get_type(sign_key)) { case KEY_RSA: - switch (this->digest_alg) + switch (digest_alg) { case HASH_MD5: - this->cert->algorithm = OID_MD5_WITH_RSA; + cert->algorithm = OID_MD5_WITH_RSA; break; case HASH_SHA1: - this->cert->algorithm = OID_SHA1_WITH_RSA; + cert->algorithm = OID_SHA1_WITH_RSA; break; case HASH_SHA224: - this->cert->algorithm = OID_SHA224_WITH_RSA; + cert->algorithm = OID_SHA224_WITH_RSA; break; case HASH_SHA256: - this->cert->algorithm = OID_SHA256_WITH_RSA; + cert->algorithm = OID_SHA256_WITH_RSA; break; case HASH_SHA384: - this->cert->algorithm = OID_SHA384_WITH_RSA; + cert->algorithm = OID_SHA384_WITH_RSA; break; case HASH_SHA512: - this->cert->algorithm = OID_SHA512_WITH_RSA; + cert->algorithm = OID_SHA512_WITH_RSA; break; default: return FALSE; } break; case KEY_ECDSA: - switch (this->digest_alg) + switch (digest_alg) { case HASH_SHA1: - this->cert->algorithm = OID_ECDSA_WITH_SHA1; + cert->algorithm = OID_ECDSA_WITH_SHA1; break; case HASH_SHA256: - this->cert->algorithm = OID_ECDSA_WITH_SHA256; + cert->algorithm = OID_ECDSA_WITH_SHA256; break; case HASH_SHA384: - this->cert->algorithm = OID_ECDSA_WITH_SHA384; + cert->algorithm = OID_ECDSA_WITH_SHA384; break; case HASH_SHA512: - this->cert->algorithm = OID_ECDSA_WITH_SHA512; + cert->algorithm = OID_ECDSA_WITH_SHA512; break; default: return FALSE; @@ -1297,16 +1268,15 @@ static bool generate(private_builder_t *this) default: return FALSE; } - scheme = signature_scheme_from_oid(this->cert->algorithm); + scheme = signature_scheme_from_oid(cert->algorithm); - if (!this->cert->public_key->get_encoding(this->cert->public_key, - KEY_PUB_SPKI_ASN1_DER, &key_info)) + if (!cert->public_key->get_encoding(cert->public_key, + KEY_PUB_SPKI_ASN1_DER, &key_info)) { return FALSE; } - enumerator = this->cert->subjectAltNames->create_enumerator( - this->cert->subjectAltNames); + enumerator = cert->subjectAltNames->create_enumerator(cert->subjectAltNames); while (enumerator->enumerate(enumerator, &id)) { int context; @@ -1344,7 +1314,7 @@ static bool generate(private_builder_t *this) asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames))); } - if (this->flags & X509_CA) + if (cert->flags & X509_CA) { chunk_t yes, keyid; @@ -1357,8 +1327,8 @@ static bool generate(private_builder_t *this) asn1_wrap(ASN1_SEQUENCE, "m", asn1_wrap(ASN1_BOOLEAN, "c", yes)))); /* add subjectKeyIdentifier to CA certificates */ - if (this->cert->public_key->get_fingerprint(this->cert->public_key, - KEY_ID_PUBKEY_SHA1, &keyid)) + if (cert->public_key->get_fingerprint(cert->public_key, + KEY_ID_PUBKEY_SHA1, &keyid)) { subjectKeyIdentifier = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_SUBJECT_KEY_ID), @@ -1366,12 +1336,11 @@ static bool generate(private_builder_t *this) asn1_wrap(ASN1_OCTET_STRING, "c", keyid))); } } - if (this->sign_key) + if (sign_key) { /* add the keyid authKeyIdentifier for non self-signed certificates */ chunk_t keyid; - if (this->sign_key->get_fingerprint(this->sign_key, - KEY_ID_PUBKEY_SHA1, &keyid)) + if (sign_key->get_fingerprint(sign_key, KEY_ID_PUBKEY_SHA1, &keyid)) { authKeyIdentifier = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_AUTHORITY_KEY_ID), @@ -1388,181 +1357,146 @@ static bool generate(private_builder_t *this) authKeyIdentifier, subjectAltNames)); } - this->cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm", + cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm", asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2), - asn1_integer("c", this->cert->serialNumber), - asn1_algorithmIdentifier(this->cert->algorithm), + asn1_integer("c", cert->serialNumber), + asn1_algorithmIdentifier(cert->algorithm), issuer->get_encoding(issuer), asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_from_time(&this->cert->notBefore, ASN1_UTCTIME), - asn1_from_time(&this->cert->notAfter, ASN1_UTCTIME)), + asn1_from_time(&cert->notBefore, ASN1_UTCTIME), + asn1_from_time(&cert->notAfter, ASN1_UTCTIME)), subject->get_encoding(subject), key_info, extensions); - if (!this->sign_key->sign(this->sign_key, scheme, - this->cert->tbsCertificate, &this->cert->signature)) + if (!sign_key->sign(sign_key, scheme, cert->tbsCertificate, &cert->signature)) { return FALSE; } - this->cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm", - this->cert->tbsCertificate, - asn1_algorithmIdentifier(this->cert->algorithm), - asn1_bitstring("c", this->cert->signature)); + cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm", cert->tbsCertificate, + asn1_algorithmIdentifier(cert->algorithm), + asn1_bitstring("c", cert->signature)); hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); if (!hasher) { return FALSE; } - hasher->allocate_hash(hasher, this->cert->encoding, - &this->cert->encoding_hash); + hasher->allocate_hash(hasher, cert->encoding, &cert->encoding_hash); hasher->destroy(hasher); return TRUE; } /** - * Implementation of builder_t.build + * See header. */ -static private_x509_cert_t *build(private_builder_t *this) +x509_cert_t *x509_cert_load(certificate_type_t type, va_list args) { - private_x509_cert_t *cert; + chunk_t blob = chunk_empty; - if (this->cert) + while (TRUE) { - this->cert->flags |= this->flags; - if (!this->cert->encoding.ptr) - { /* generate a new certificate */ - if (!this->sign_key || !generate(this)) - { - destroy(this->cert); - free(this); + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_ASN1_DER: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: return NULL; - } } + break; } - cert = this->cert; - free(this); - return cert; -} -/** - * Implementation of builder_t.add - */ -static void add(private_builder_t *this, builder_part_t part, ...) -{ - va_list args; - chunk_t chunk; - bool handled = TRUE; - - va_start(args, part); - switch (part) - { - case BUILD_BLOB_ASN1_DER: - chunk = va_arg(args, chunk_t); - this->cert = create_from_chunk(chunk_clone(chunk)); - break; - case BUILD_X509_FLAG: - this->flags = va_arg(args, x509_flag_t); - break; - case BUILD_SIGNING_KEY: - this->sign_key = va_arg(args, private_key_t*); - break; - case BUILD_SIGNING_CERT: - this->sign_cert = va_arg(args, certificate_t*); - break; - default: - /* all other parts need an empty cert */ - if (!this->cert) - { - this->cert = create_empty(); - } - handled = FALSE; - break; - } - if (handled) - { - va_end(args); - return; - } - - switch (part) + if (blob.ptr) { - case BUILD_PUBLIC_KEY: - { - public_key_t *key = va_arg(args, public_key_t*); - this->cert->public_key = key->get_ref(key); - break; - } - case BUILD_SUBJECT: - { - identification_t *id = va_arg(args, identification_t*); - this->cert->subject = id->clone(id); - break; - } - case BUILD_SUBJECT_ALTNAMES: - { - identification_t *id; - enumerator_t *enumerator; - linked_list_t *list = va_arg(args, linked_list_t*); + private_x509_cert_t *cert = create_empty(); - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &id)) - { - this->cert->subjectAltNames->insert_last( - this->cert->subjectAltNames, id->clone(id)); - } - enumerator->destroy(enumerator); - break; - } - case BUILD_NOT_BEFORE_TIME: - this->cert->notBefore = va_arg(args, time_t); - break; - case BUILD_NOT_AFTER_TIME: - this->cert->notAfter = va_arg(args, time_t); - break; - case BUILD_SERIAL: + cert->encoding = chunk_clone(blob); + if (parse_certificate(cert)) { - chunk_t serial = va_arg(args, chunk_t); - this->cert->serialNumber = chunk_clone(serial); - break; + cert->parsed = TRUE; + return &cert->public; } - case BUILD_DIGEST_ALG: - this->digest_alg = va_arg(args, int); - break; - default: - /* abort if unsupported option */ - if (this->cert) - { - destroy(this->cert); - } - builder_cancel(&this->public); - break; + destroy(cert); } - va_end(args); + return NULL; } /** - * Builder construction function + * See header. */ -builder_t *x509_cert_builder(certificate_type_t type) +x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) { - private_builder_t *this; + private_x509_cert_t *cert; + certificate_t *sign_cert = NULL; + private_key_t *sign_key = NULL; + hash_algorithm_t digest_alg = HASH_SHA1; - if (type != CERT_X509) + cert = create_empty(); + while (TRUE) { - return NULL; - } - - this = malloc_thing(private_builder_t); + switch (va_arg(args, builder_part_t)) + { + case BUILD_X509_FLAG: + cert->flags |= va_arg(args, x509_flag_t); + continue; + case BUILD_SIGNING_KEY: + sign_key = va_arg(args, private_key_t*); + continue; + case BUILD_SIGNING_CERT: + sign_cert = va_arg(args, certificate_t*); + continue; + case BUILD_PUBLIC_KEY: + cert->public_key = va_arg(args, public_key_t*); + cert->public_key->get_ref(cert->public_key); + continue; + case BUILD_SUBJECT: + cert->subject = va_arg(args, identification_t*); + cert->subject = cert->subject->clone(cert->subject); + continue; + case BUILD_SUBJECT_ALTNAMES: + { + enumerator_t *enumerator; + identification_t *id; + linked_list_t *list; - this->cert = NULL; - this->flags = 0; - this->sign_cert = NULL; - this->sign_key = NULL; - this->digest_alg = HASH_SHA1; - this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; - this->public.build = (void*(*)(builder_t *this))build; + list = va_arg(args, linked_list_t*); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &id)) + { + cert->subjectAltNames->insert_last( + cert->subjectAltNames, id->clone(id)); + } + enumerator->destroy(enumerator); + continue; + } + case BUILD_NOT_BEFORE_TIME: + cert->notBefore = va_arg(args, time_t); + continue; + case BUILD_NOT_AFTER_TIME: + cert->notAfter = va_arg(args, time_t); + continue; + case BUILD_SERIAL: + cert->serialNumber = chunk_clone(va_arg(args, chunk_t)); + continue; + case BUILD_DIGEST_ALG: + digest_alg = va_arg(args, int); + continue; + case BUILD_END: + break; + default: + destroy(cert); + return NULL; + } + break; + } - return &this->public; + if (sign_key && generate(cert, sign_cert, sign_key, digest_alg)) + { + return &cert->public; + } + destroy(cert); + return NULL; } diff --git a/src/libstrongswan/plugins/x509/x509_cert.h b/src/libstrongswan/plugins/x509/x509_cert.h index 5ebe1567d..772117f1c 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.h +++ b/src/libstrongswan/plugins/x509/x509_cert.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ typedef struct x509_cert_t x509_cert_t; +#include <credentials/builder.h> #include <credentials/certificates/x509.h> /** @@ -37,11 +38,29 @@ struct x509_cert_t { }; /** - * Create the building facility for x509 certificates + * Load a X.509 certificate. + * + * This function takes a BUILD_BLOB_ASN1_DER. + * + * @param type certificate type, CERT_X509 only + * @param args builder_part_t argument list + * @return X.509 certificate, NULL on failure + */ +x509_cert_t *x509_cert_load(certificate_type_t type, va_list args); + +/** + * Generate a X.509 certificate. + * + * To issue a self-signed certificate, the function takes: + * BUILD_SUBJECT, BUILD_SUBJECT_ALTNAMES, BUILD_SIGNING_KEY, BUILD_X509_FLAG, + * BUILD_NOT_BEFORE_TIME, BUILD_NOT_AFTER_TIME, BUILD_SERIAL, BUILD_DIGEST_ALG. + * To issue certificates from a CA, additionally pass: + * BUILD_SIGNING_CERT and BUILD_PUBLIC_KEY. * * @param type certificate type, CERT_X509 only - * @return builder instance to build certificate + * @param args builder_part_t argument list + * @return X.509 certificate, NULL on failure */ -builder_t *x509_cert_builder(certificate_type_t type); +x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args); #endif /** X509_CERT_H_ @}*/ diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index cd1d3c6e6..643f809c7 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -593,78 +593,38 @@ static private_x509_crl_t* create_empty(void) return this; } -typedef struct private_builder_t private_builder_t; /** - * Builder implementation for certificate loading + * See header. */ -struct private_builder_t { - /** implements the builder interface */ - builder_t public; - /** CRL chunk to build from */ - chunk_t blob; -}; - -/** - * Implementation of builder_t.build - */ -static private_x509_crl_t *build(private_builder_t *this) +x509_crl_t *x509_crl_load(certificate_type_t type, va_list args) { - private_x509_crl_t *crl = NULL; + chunk_t blob = chunk_empty; - if (this->blob.len && this->blob.ptr) + while (TRUE) { - crl = create_empty(); - crl->encoding = chunk_clone(this->blob); - if (!parse(crl)) + switch (va_arg(args, builder_part_t)) { - destroy(crl); - crl = NULL; + case BUILD_BLOB_ASN1_DER: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; } + break; } - free(this); - return crl; -} - -/** - * Implementation of builder_t.add - */ -static void add(private_builder_t *this, builder_part_t part, ...) -{ - va_list args; - - switch (part) + if (blob.ptr) { - case BUILD_BLOB_ASN1_DER: + private_x509_crl_t *crl = create_empty(); + + crl->encoding = chunk_clone(blob); + if (parse(crl)) { - va_start(args, part); - this->blob = va_arg(args, chunk_t); - va_end(args); - return; + return &crl->public; } - default: - break; + destroy(crl); } - builder_cancel(&this->public); -} - -/** - * Builder construction function - */ -builder_t *x509_crl_builder(certificate_type_t type) -{ - private_builder_t *this; - - if (type != CERT_X509_CRL) - { - return NULL; - } - this = malloc_thing(private_builder_t); - - this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; - this->public.build = (void*(*)(builder_t *this))build; - - this->blob = chunk_empty; - - return &this->public; -} + return NULL; +}; diff --git a/src/libstrongswan/plugins/x509/x509_crl.h b/src/libstrongswan/plugins/x509/x509_crl.h index daa8e4846..890650162 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.h +++ b/src/libstrongswan/plugins/x509/x509_crl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ typedef struct x509_crl_t x509_crl_t; +#include <credentials/builder.h> #include <credentials/certificates/crl.h> /** @@ -36,13 +37,13 @@ struct x509_crl_t { crl_t crl; }; - /** - * Create the building facility for x509 certificate revocation lists. + * Load a X.509 CRL. * * @param type certificate type, CERT_X509_CRL only - * @return builder instance to build certificate + * @param args builder_part_t argument list + * @return X.509 CRL, NULL on failure */ -builder_t *x509_crl_builder(certificate_type_t type); +x509_crl_t *x509_crl_load(certificate_type_t type, va_list args); #endif /** X509_CRL_H_ @}*/ diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index baed7fe3b..e0d9905f1 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Copyright (C) 2007 Andreas Steffen * Hochschule fuer Technik Rapperswil * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen @@ -508,26 +508,56 @@ static private_x509_ocsp_request_t *create_empty() return this; } -typedef struct private_builder_t private_builder_t; /** - * Builder implementation for certificate loading + * See header. */ -struct private_builder_t { - /** implements the builder interface */ - builder_t public; - /** OCSP request to build */ - private_x509_ocsp_request_t *req; -}; - -/** - * Implementation of builder_t.build - */ -static x509_ocsp_request_t *build(private_builder_t *this) +x509_ocsp_request_t *x509_ocsp_request_gen(certificate_type_t type, va_list args) { private_x509_ocsp_request_t *req; + certificate_t *cert; + private_key_t *private; + identification_t *subject; - req = this->req; - free(this); + req = create_empty(); + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_CA_CERT: + cert = va_arg(args, certificate_t*); + if (cert->get_type(cert) == CERT_X509) + { + req->ca = (x509_t*)cert->get_ref(cert); + } + continue; + case BUILD_CERT: + cert = va_arg(args, certificate_t*); + if (cert->get_type(cert) == CERT_X509) + { + req->candidates->insert_last(req->candidates, + cert->get_ref(cert)); + } + continue; + case BUILD_SIGNING_CERT: + cert = va_arg(args, certificate_t*); + req->cert = cert->get_ref(cert); + continue; + case BUILD_SIGNING_KEY: + private = va_arg(args, private_key_t*); + req->key = private->get_ref(private); + continue; + case BUILD_SUBJECT: + subject = va_arg(args, identification_t*); + req->requestor = subject->clone(subject); + continue; + case BUILD_END: + break; + default: + destroy(req); + return NULL; + } + break; + } if (req->ca) { req->encoding = build_OCSPRequest(req); @@ -537,76 +567,3 @@ static x509_ocsp_request_t *build(private_builder_t *this) return NULL; } -/** - * Implementation of builder_t.add - */ -static void add(private_builder_t *this, builder_part_t part, ...) -{ - va_list args; - certificate_t *cert; - identification_t *subject; - private_key_t *private; - - va_start(args, part); - switch (part) - { - case BUILD_CA_CERT: - cert = va_arg(args, certificate_t*); - if (cert->get_type(cert) == CERT_X509) - { - this->req->ca = (x509_t*)cert->get_ref(cert); - } - break; - case BUILD_CERT: - cert = va_arg(args, certificate_t*); - if (cert->get_type(cert) == CERT_X509) - { - this->req->candidates->insert_last(this->req->candidates, - cert->get_ref(cert)); - } - break; - case BUILD_SIGNING_CERT: - cert = va_arg(args, certificate_t*); - this->req->cert = cert->get_ref(cert); - break; - case BUILD_SIGNING_KEY: - private = va_arg(args, private_key_t*); - this->req->key = private->get_ref(private); - break; - case BUILD_SUBJECT: - subject = va_arg(args, identification_t*); - this->req->requestor = subject->clone(subject); - break; - default: - /* cancel if option not supported */ - if (this->req) - { - destroy(this->req); - } - builder_cancel(&this->public); - break; - } - va_end(args); -} - -/** - * Builder construction function - */ -builder_t *x509_ocsp_request_builder(certificate_type_t type) -{ - private_builder_t *this; - - if (type != CERT_X509_OCSP_REQUEST) - { - return NULL; - } - - this = malloc_thing(private_builder_t); - - this->req = create_empty(); - this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; - this->public.build = (void*(*)(builder_t *this))build; - - return &this->public; -} - diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.h b/src/libstrongswan/plugins/x509/x509_ocsp_request.h index ffaa3c634..4c0e4b8f2 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.h +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ #ifndef X509_OCSP_REQUEST_H_ #define X509_OCSP_REQUEST_H_ +#include <credentials/builder.h> #include <credentials/certificates/ocsp_request.h> typedef struct x509_ocsp_request_t x509_ocsp_request_t; @@ -37,7 +38,7 @@ struct x509_ocsp_request_t { }; /** - * Create the building facility for OCSP requests. + * Generate a X.509 OCSP request. * * The resulting builder accepts: * BUILD_CA_CERT: CA of the checked certificates, exactly one @@ -46,9 +47,10 @@ struct x509_ocsp_request_t { * BUILD_SIGNING_CERT: certificate to create requestor signature, optional * BUILD_SIGNING_KEY: private key to create requestor signature, optional * - * @param type certificate type, CERT_X509_OCSP_REQUEST only - * @return builder instance to build OCSP requests + * @param type certificate type, CERT_X509_OCSP_REQUEST only + * @param args builder_part_t argument list + * @return OCSP request, NULL on failure */ -builder_t *x509_ocsp_request_builder(certificate_type_t type); +x509_ocsp_request_t *x509_ocsp_request_gen(certificate_type_t type, va_list args); #endif /** X509_OCSP_REQUEST_H_ @}*/ diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index f3ee5c82c..2b60df323 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Copyright (C) 2007 Andreas Steffen * Hochschule fuer Technik Rapperswil * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen @@ -853,7 +853,7 @@ static void destroy(private_x509_ocsp_response_t *this) /** * load an OCSP response */ -static x509_ocsp_response_t *load(chunk_t data) +static x509_ocsp_response_t *load(chunk_t blob) { private_x509_ocsp_response_t *this; @@ -876,7 +876,7 @@ static x509_ocsp_response_t *load(chunk_t data) this->public.interface.create_cert_enumerator = (enumerator_t*(*)(ocsp_response_t*))create_cert_enumerator; this->ref = 1; - this->encoding = data; + this->encoding = chunk_clone(blob); this->tbsResponseData = chunk_empty; this->responderId = NULL; this->producedAt = UNDEFINED_TIME; @@ -895,78 +895,32 @@ static x509_ocsp_response_t *load(chunk_t data) return &this->public; } - -typedef struct private_builder_t private_builder_t; -/** - * Builder implementation for certificate loading - */ -struct private_builder_t { - /** implements the builder interface */ - builder_t public; - /** loaded response */ - x509_ocsp_response_t *res; -}; - /** - * Implementation of builder_t.build + * See header. */ -static x509_ocsp_response_t *build(private_builder_t *this) +x509_ocsp_response_t *x509_ocsp_response_load(certificate_type_t type, + va_list args) { - x509_ocsp_response_t *res = this->res; - - free(this); - return res; -} + chunk_t blob = chunk_empty; -/** - * Implementation of builder_t.add - */ -static void add(private_builder_t *this, builder_part_t part, ...) -{ - if (!this->res) + while (TRUE) { - va_list args; - chunk_t chunk; - - switch (part) + switch (va_arg(args, builder_part_t)) { case BUILD_BLOB_ASN1_DER: - { - va_start(args, part); - chunk = va_arg(args, chunk_t); - this->res = load(chunk_clone(chunk)); - va_end(args); - return; - } - default: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: break; + default: + return NULL; } + break; } - if (this->res) + if (blob.ptr) { - destroy((private_x509_ocsp_response_t*)this->res); + return load(blob); } - builder_cancel(&this->public); -} - -/** - * Builder construction function - */ -builder_t *x509_ocsp_response_builder(certificate_type_t type) -{ - private_builder_t *this; - - if (type != CERT_X509_OCSP_RESPONSE) - { - return NULL; - } - - this = malloc_thing(private_builder_t); - - this->res = NULL; - this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; - this->public.build = (void*(*)(builder_t *this))build; - - return &this->public; + return NULL; } diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.h b/src/libstrongswan/plugins/x509/x509_ocsp_response.h index 06a9fd3c7..7a525626e 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.h +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ #ifndef X509_OCSP_RESPONSE_H_ #define X509_OCSP_RESPONSE_H_ +#include <credentials/builder.h> #include <credentials/certificates/ocsp_response.h> typedef struct x509_ocsp_response_t x509_ocsp_response_t; @@ -37,11 +38,13 @@ struct x509_ocsp_response_t { }; /** - * Create the building facility for OCSP responses. + * Load a X.509 OCSP response. * * @param type certificate type, CERT_X509_OCSP_RESPONSE only - * @return builder instance to build OCSP responses + * @param args builder_part_t argument list + * @return OCSP response, NULL on failure */ -builder_t *x509_ocsp_response_builder(certificate_type_t type); +x509_ocsp_response_t *x509_ocsp_response_load(certificate_type_t type, + va_list args); #endif /** X509_OCSP_RESPONSE_H_ @}*/ diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c index b7e8b5bd3..1c5a33b41 100644 --- a/src/libstrongswan/plugins/x509/x509_plugin.c +++ b/src/libstrongswan/plugins/x509/x509_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -41,15 +41,19 @@ struct private_x509_plugin_t { static void destroy(private_x509_plugin_t *this) { lib->creds->remove_builder(lib->creds, - (builder_constructor_t)x509_cert_builder); + (builder_function_t)x509_cert_gen); lib->creds->remove_builder(lib->creds, - (builder_constructor_t)x509_ac_builder); + (builder_function_t)x509_cert_load); lib->creds->remove_builder(lib->creds, - (builder_constructor_t)x509_crl_builder); + (builder_function_t)x509_ac_gen); lib->creds->remove_builder(lib->creds, - (builder_constructor_t)x509_ocsp_request_builder); + (builder_function_t)x509_ac_load); lib->creds->remove_builder(lib->creds, - (builder_constructor_t)x509_ocsp_response_builder); + (builder_function_t)x509_crl_load); + lib->creds->remove_builder(lib->creds, + (builder_function_t)x509_ocsp_request_gen); + lib->creds->remove_builder(lib->creds, + (builder_function_t)x509_ocsp_response_load); free(this); } @@ -63,15 +67,19 @@ plugin_t *plugin_create() this->public.plugin.destroy = (void(*)(plugin_t*))destroy; lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509, - (builder_constructor_t)x509_cert_builder); + (builder_function_t)x509_cert_gen); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509, + (builder_function_t)x509_cert_load); + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, + (builder_function_t)x509_ac_gen); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, - (builder_constructor_t)x509_ac_builder); + (builder_function_t)x509_ac_load); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, - (builder_constructor_t)x509_crl_builder); + (builder_function_t)x509_crl_load); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, - (builder_constructor_t)x509_ocsp_request_builder); + (builder_function_t)x509_ocsp_request_gen); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, - (builder_constructor_t)x509_ocsp_response_builder); + (builder_function_t)x509_ocsp_response_load); return &this->public.plugin; } |