diff options
Diffstat (limited to 'src/libstrongswan/plugins/x509')
-rw-r--r-- | src/libstrongswan/plugins/x509/Makefile.in | 1 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ac.c | 383 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_cert.c | 15 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_request.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_plugin.c | 4 |
5 files changed, 300 insertions, 105 deletions
diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in index 74552e00b..154fc5ccd 100644 --- a/src/libstrongswan/plugins/x509/Makefile.in +++ b/src/libstrongswan/plugins/x509/Makefile.in @@ -372,7 +372,6 @@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ -openac_plugins = @openac_plugins@ pcsclite_CFLAGS = @pcsclite_CFLAGS@ pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index 7d83e48ea..30b871d42 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -29,7 +29,6 @@ #include <utils/identification.h> #include <collections/linked_list.h> #include <credentials/certificates/x509.h> -#include <credentials/ietf_attributes/ietf_attributes.h> #include <credentials/keys/private_key.h> extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, @@ -75,7 +74,7 @@ struct private_x509_ac_t { /** * Serial number of the holder certificate */ - chunk_t holderSerial; + identification_t *holderSerial; /** * ID representing the holder @@ -98,14 +97,9 @@ struct private_x509_ac_t { time_t notAfter; /** - * List of charging attributes + * List of group attributes, as group_t */ - ietf_attributes_t *charging; - - /** - * List of groub attributes - */ - ietf_attributes_t *groups; + linked_list_t *groups; /** * Authority Key Identifier @@ -153,6 +147,25 @@ struct private_x509_ac_t { refcount_t ref; }; +/** + * Group definition, an IETF attribute + */ +typedef struct { + /** Attribute type */ + ac_group_type_t type; + /* attribute value */ + chunk_t value; +} group_t; + +/** + * Clean up a group entry + */ +static void group_destroy(group_t *group) +{ + free(group->value.ptr); + free(group); +} + static chunk_t ASN1_noRevAvail_ext = chunk_from_chars( 0x30, 0x09, 0x06, 0x03, @@ -169,42 +182,41 @@ extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, /** * parses a directoryName */ -static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name) +static bool parse_directoryName(chunk_t blob, int level, bool implicit, + identification_t **name) { - bool has_directoryName; - linked_list_t *list = linked_list_create(); + identification_t *directoryName; + enumerator_t *enumerator; + bool first = TRUE; + linked_list_t *list; + list = linked_list_create(); x509_parse_generalNames(blob, level, implicit, list); - has_directoryName = list->get_count(list) > 0; - if (has_directoryName) + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &directoryName)) { - enumerator_t *enumerator = list->create_enumerator(list); - identification_t *directoryName; - bool first = TRUE; - - while (enumerator->enumerate(enumerator, (void**)&directoryName)) + if (first) { - if (first) - { - *name = directoryName; - first = FALSE; - } - else - { - DBG1(DBG_ASN, "more than one directory name - first selected"); - directoryName->destroy(directoryName); - } + *name = directoryName; + first = FALSE; + } + else + { + DBG1(DBG_ASN, "more than one directory name - first selected"); + directoryName->destroy(directoryName); + break; } - enumerator->destroy(enumerator); } - else + enumerator->destroy(enumerator); + list->destroy(list); + + if (first) { DBG1(DBG_ASN, "no directoryName found"); + return FALSE; } - - list->destroy(list); - return has_directoryName; + return TRUE; } /** @@ -244,63 +256,131 @@ static void parse_roleSyntax(chunk_t blob, int level0) } /** + * ASN.1 definition of ietfAttrSyntax + */ +static const asn1Object_t ietfAttrSyntaxObjects[] = +{ + { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_BODY }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ + { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | + ASN1_BODY }, /* 4 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ + { 2, "oid", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 6 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 2, "string", ASN1_UTF8STRING, ASN1_OPT | + ASN1_BODY }, /* 8 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define IETF_ATTR_OCTETS 4 +#define IETF_ATTR_OID 6 +#define IETF_ATTR_STRING 8 + +/** + * Parse group memberships, IETF attributes + */ +static bool parse_groups(private_x509_ac_t *this, chunk_t encoded, int level0) +{ + ac_group_type_t type; + group_t *group; + asn1_parser_t *parser; + chunk_t object; + int objectID; + bool success; + + parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded); + parser->set_top_level(parser, level0); + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case IETF_ATTR_OCTETS: + type = AC_GROUP_TYPE_OCTETS; + break; + case IETF_ATTR_OID: + type = AC_GROUP_TYPE_OID; + break; + case IETF_ATTR_STRING: + type = AC_GROUP_TYPE_STRING; + break; + default: + continue; + } + INIT(group, + .type = type, + .value = chunk_clone(object), + ); + this->groups->insert_last(this->groups, group); + } + success = parser->success(parser); + parser->destroy(parser); + + return success; +} + +/** * ASN.1 definition of an X509 attribute certificate */ static const asn1Object_t acObjects[] = { { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_DEF | + { 2, "version", ASN1_INTEGER, ASN1_DEF | ASN1_BODY }, /* 2 */ - { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | ASN1_BODY }, /* 7 */ { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | + { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | ASN1_OBJ }, /* 10 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ - { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */ - { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ + { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */ + { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | ASN1_BODY }, /* 14 */ { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ - { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | + { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ + { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | ASN1_OBJ }, /* 19 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ - { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ - { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ + { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ + { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ + { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | ASN1_BODY }, /* 25 */ { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ - { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ - { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ - { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ + { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ + { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | ASN1_BODY }, /* 31 */ { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ - { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ - { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ - { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ - { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ + { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ + { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ + { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ + { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ + { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ + { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ @@ -368,22 +448,26 @@ static bool parse_certificate(private_x509_ac_t *this) } break; case AC_OBJ_HOLDER_ISSUER: - if (!parse_directoryName(object, level, FALSE, &this->holderIssuer)) + if (!parse_directoryName(object, level, FALSE, + &this->holderIssuer)) { goto end; } break; case AC_OBJ_HOLDER_SERIAL: - this->holderSerial = object; + this->holderSerial = identification_create_from_encoding( + ID_KEY_ID, object); break; case AC_OBJ_ENTITY_NAME: - if (!parse_directoryName(object, level, TRUE, &this->entityName)) + if (!parse_directoryName(object, level, TRUE, + &this->entityName)) { goto end; } break; case AC_OBJ_ISSUER_NAME: - if (!parse_directoryName(object, level, FALSE, &this->issuerName)) + if (!parse_directoryName(object, level, FALSE, + &this->issuerName)) { goto end; } @@ -414,13 +498,14 @@ static bool parse_certificate(private_x509_ac_t *this) DBG2(DBG_ASN, " need to parse accessIdentity"); break; case OID_CHARGING_IDENTITY: - DBG2(DBG_ASN, "-- > --"); - this->charging = ietf_attributes_create_from_encoding(object); - DBG2(DBG_ASN, "-- < --"); + DBG2(DBG_ASN, " need to parse chargingIdentity"); break; case OID_GROUP: DBG2(DBG_ASN, "-- > --"); - this->groups = ietf_attributes_create_from_encoding(object); + if (!parse_groups(this, object, level)) + { + goto end; + } DBG2(DBG_ASN, "-- < --"); break; case OID_ROLE: @@ -446,8 +531,9 @@ static bool parse_certificate(private_x509_ac_t *this) DBG2(DBG_ASN, " need to parse crlDistributionPoints"); break; case OID_AUTHORITY_KEY_ID: - this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object, - level, &this->authKeySerialNumber); + this->authKeyIdentifier = + x509_parse_authorityKeyIdentifier(object, + level, &this->authKeySerialNumber); break; case OID_TARGET_INFORMATION: DBG2(DBG_ASN, " need to parse targetInformation"); @@ -490,7 +576,7 @@ end: static chunk_t build_directoryName(asn1_t tag, chunk_t name) { return asn1_wrap(tag, "m", - asn1_simple_object(ASN1_CONTEXT_C_4, name)); + asn1_simple_object(ASN1_CONTEXT_C_4, name)); } /** @@ -499,14 +585,15 @@ static chunk_t build_directoryName(asn1_t tag, chunk_t name) static chunk_t build_holder(private_x509_ac_t *this) { x509_t* x509 = (x509_t*)this->holderCert; - identification_t *issuer = this->holderCert->get_issuer(this->holderCert); - identification_t *subject = this->holderCert->get_subject(this->holderCert); + identification_t *issuer, *subject; + + issuer = this->holderCert->get_issuer(this->holderCert); + subject = this->holderCert->get_subject(this->holderCert); return asn1_wrap(ASN1_SEQUENCE, "mm", asn1_wrap(ASN1_CONTEXT_C_0, "mm", build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)), - asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509)) - ), + asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))), build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject))); } @@ -515,10 +602,12 @@ static chunk_t build_holder(private_x509_ac_t *this) */ static chunk_t build_v2_form(private_x509_ac_t *this) { - identification_t *subject = this->signerCert->get_subject(this->signerCert); + identification_t *subject; + subject = this->signerCert->get_subject(this->signerCert); return asn1_wrap(ASN1_CONTEXT_C_0, "m", - build_directoryName(ASN1_SEQUENCE, subject->get_encoding(subject))); + build_directoryName(ASN1_SEQUENCE, + subject->get_encoding(subject))); } /** @@ -531,7 +620,6 @@ static chunk_t build_attr_cert_validity(private_x509_ac_t *this) asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME)); } - /** * build attribute type */ @@ -547,8 +635,55 @@ static chunk_t build_attribute_type(int type, chunk_t content) */ static chunk_t build_attributes(private_x509_ac_t *this) { + enumerator_t *enumerator; + group_t *group; + chunk_t values; + size_t size = 0, len; + u_char *pos; + + /* precalculate the total size of all values */ + enumerator = this->groups->create_enumerator(this->groups); + while (enumerator->enumerate(enumerator, &group)) + { + len = group->value.len; + size += 1 + (len > 0) + (len >= 128) + + (len >= 256) + (len >= 65536) + len; + } + enumerator->destroy(enumerator); + + pos = asn1_build_object(&values, ASN1_SEQUENCE, size); + + enumerator = this->groups->create_enumerator(this->groups); + while (enumerator->enumerate(enumerator, &group)) + { + chunk_t attr; + asn1_t type; + + switch (group->type) + { + case AC_GROUP_TYPE_OCTETS: + type = ASN1_OCTET_STRING; + break; + case AC_GROUP_TYPE_STRING: + type = ASN1_UTF8STRING; + break; + case AC_GROUP_TYPE_OID: + type = ASN1_OID; + break; + default: + continue; + } + attr = asn1_simple_object(type, group->value); + + memcpy(pos, attr.ptr, attr.len); + pos += attr.len; + free(attr.ptr); + } + enumerator->destroy(enumerator); + return asn1_wrap(ASN1_SEQUENCE, "m", - build_attribute_type(OID_GROUP, this->groups->get_encoding(this->groups))); + build_attribute_type(OID_GROUP, + asn1_wrap(ASN1_SEQUENCE, "m", values))); } /** @@ -621,14 +756,11 @@ static chunk_t build_attr_cert_info(private_x509_ac_t *this) */ static chunk_t build_ac(private_x509_ac_t *this) { - chunk_t signatureValue; - chunk_t attributeCertificateInfo; + chunk_t signatureValue, attributeCertificateInfo; attributeCertificateInfo = build_attr_cert_info(this); - this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1, attributeCertificateInfo, &signatureValue); - return asn1_wrap(ASN1_SEQUENCE, "mmm", attributeCertificateInfo, asn1_algorithmIdentifier(OID_SHA1_WITH_RSA), @@ -644,7 +776,11 @@ METHOD(ac_t, get_serial, chunk_t, METHOD(ac_t, get_holderSerial, chunk_t, private_x509_ac_t *this) { - return this->holderSerial; + if (this->holderSerial) + { + return this->holderSerial->get_encoding(this->holderSerial); + } + return chunk_empty; } METHOD(ac_t, get_holderIssuer, identification_t*, @@ -659,10 +795,28 @@ METHOD(ac_t, get_authKeyIdentifier, chunk_t, return this->authKeyIdentifier; } -METHOD(ac_t, get_groups, ietf_attributes_t*, +/** + * Filter function for attribute enumeration + */ +static bool attr_filter(void *null, group_t **in, ac_group_type_t *type, + void *in2, chunk_t *out) +{ + if ((*in)->type == AC_GROUP_TYPE_STRING && + !chunk_printable((*in)->value, NULL, 0)) + { /* skip non-printable strings */ + return FALSE; + } + *type = (*in)->type; + *out = (*in)->value; + return TRUE; +} + +METHOD(ac_t, create_group_enumerator, enumerator_t*, private_x509_ac_t *this) { - return this->groups ? this->groups->get_ref(this->groups) : NULL; + return enumerator_create_filter( + this->groups->create_enumerator(this->groups), + (void*)attr_filter, NULL, NULL); } METHOD(certificate_t, get_type, certificate_type_t, @@ -674,7 +828,11 @@ METHOD(certificate_t, get_type, certificate_type_t, METHOD(certificate_t, get_subject, identification_t*, private_x509_ac_t *this) { - return this->entityName; + if (this->entityName) + { + return this->entityName; + } + return this->holderSerial; } METHOD(certificate_t, get_issuer, identification_t*, @@ -686,13 +844,24 @@ METHOD(certificate_t, get_issuer, identification_t*, METHOD(certificate_t, has_subject, id_match_t, private_x509_ac_t *this, identification_t *subject) { - return ID_MATCH_NONE; + id_match_t entity = ID_MATCH_NONE, serial = ID_MATCH_NONE; + + if (this->entityName) + { + entity = this->entityName->matches(this->entityName, subject); + } + if (this->holderSerial) + { + serial = this->holderSerial->matches(this->holderSerial, subject); + } + return max(entity, serial); } METHOD(certificate_t, has_issuer, id_match_t, private_x509_ac_t *this, identification_t *issuer) { - if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr && + if (issuer->get_type(issuer) == ID_KEY_ID && + this->authKeyIdentifier.ptr && chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer))) { return ID_MATCH_PERFECT; @@ -808,9 +977,10 @@ METHOD(certificate_t, equals, bool, { return TRUE; } - if (other->equals == (void*)equals) + if (other->equals == _equals) { /* skip allocation if we have the same implementation */ - return chunk_equals(this->encoding, ((private_x509_ac_t*)other)->encoding); + return chunk_equals(this->encoding, + ((private_x509_ac_t*)other)->encoding); } if (!other->get_encoding(other, CERT_ASN1_DER, &encoding)) { @@ -827,13 +997,13 @@ METHOD(certificate_t, destroy, void, if (ref_put(&this->ref)) { DESTROY_IF(this->holderIssuer); + DESTROY_IF(this->holderSerial); DESTROY_IF(this->entityName); DESTROY_IF(this->issuerName); DESTROY_IF(this->holderCert); DESTROY_IF(this->signerCert); DESTROY_IF(this->signerKey); - DESTROY_IF(this->charging); - DESTROY_IF(this->groups); + this->groups->destroy_function(this->groups, (void*)group_destroy); free(this->serialNumber.ptr); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); @@ -869,9 +1039,10 @@ static private_x509_ac_t *create_empty(void) .get_holderSerial = _get_holderSerial, .get_holderIssuer = _get_holderIssuer, .get_authKeyIdentifier = _get_authKeyIdentifier, - .get_groups = _get_groups, + .create_group_enumerator = _create_group_enumerator, }, }, + .groups = linked_list_create(), .ref = 1, ); @@ -914,6 +1085,27 @@ x509_ac_t *x509_ac_load(certificate_type_t type, va_list args) } /** + * Add groups from a list into AC group memberships + */ +static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list) +{ + enumerator_t *enumerator; + group_t *group; + char *name; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &name)) + { + INIT(group, + .type = AC_GROUP_TYPE_STRING, + .value = chunk_clone(chunk_from_str(name)), + ); + this->groups->insert_last(this->groups, group); + } + enumerator->destroy(enumerator); +} + +/** * See header. */ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) @@ -934,8 +1126,8 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) case BUILD_SERIAL: ac->serialNumber = chunk_clone(va_arg(args, chunk_t)); continue; - case BUILD_IETF_GROUP_ATTR: - ac->groups = ietf_attributes_create_from_string(va_arg(args, char*)); + case BUILD_AC_GROUP_STRINGS: + add_groups_from_list(ac, va_arg(args, linked_list_t*)); continue; case BUILD_CERT: ac->holderCert = va_arg(args, certificate_t*); @@ -968,4 +1160,3 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) destroy(ac); return NULL; } - diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index ed850e8f5..9fd869e77 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -758,6 +758,9 @@ static void parse_extendedKeyUsage(chunk_t blob, int level0, case OID_OCSP_SIGNING: this->flags |= X509_OCSP_SIGNER; break; + case OID_MS_SMARTCARD_LOGON: + this->flags |= X509_MS_SMARTCARD_LOGON; + break; default: break; } @@ -2008,7 +2011,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty; chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty; chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty; - chunk_t ikeIntermediate = chunk_empty; + chunk_t ikeIntermediate = chunk_empty, msSmartcardLogon = chunk_empty; identification_t *issuer, *subject; chunk_t key_info; signature_scheme_t scheme; @@ -2139,6 +2142,10 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, { ocspSigning = asn1_build_known_oid(OID_OCSP_SIGNING); } + if (cert->flags & X509_MS_SMARTCARD_LOGON) + { + msSmartcardLogon = asn1_build_known_oid(OID_MS_SMARTCARD_LOGON); + } if (serverAuth.ptr || clientAuth.ptr || ikeIntermediate.ptr || ocspSigning.ptr) @@ -2146,9 +2153,9 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_EXTENDED_KEY_USAGE), asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_wrap(ASN1_SEQUENCE, "mmmm", + asn1_wrap(ASN1_SEQUENCE, "mmmmm", serverAuth, clientAuth, ikeIntermediate, - ocspSigning))); + ocspSigning, msSmartcardLogon))); } /* add subjectKeyIdentifier to CA and OCSP signer certificates */ @@ -2167,7 +2174,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, } /* add the keyid authKeyIdentifier for non self-signed certificates */ - if (sign_key) + if (sign_cert) { chunk_t keyid; diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index 09c5a8539..ff0f0231f 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -252,7 +252,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this, { int oid; signature_scheme_t scheme; - chunk_t certs, signature, encoding; + chunk_t certs = chunk_empty, signature, encoding; switch (this->key->get_type(this->key)) { diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c index 15fea7ee0..54bef7357 100644 --- a/src/libstrongswan/plugins/x509/x509_plugin.c +++ b/src/libstrongswan/plugins/x509/x509_plugin.c @@ -52,9 +52,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_REGISTER(CERT_DECODE, x509_cert_load, TRUE), PLUGIN_PROVIDE(CERT_DECODE, CERT_X509), PLUGIN_DEPENDS(HASHER, HASH_SHA1), - PLUGIN_SDEPEND(PUBKEY, KEY_RSA), - PLUGIN_SDEPEND(PUBKEY, KEY_ECDSA), - PLUGIN_SDEPEND(PUBKEY, KEY_DSA), + PLUGIN_DEPENDS(PUBKEY, KEY_ANY), PLUGIN_REGISTER(CERT_ENCODE, x509_ac_gen, FALSE), PLUGIN_PROVIDE(CERT_ENCODE, CERT_X509_AC), |