summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/x509
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/x509')
-rw-r--r--src/libstrongswan/plugins/x509/Makefile.in1
-rw-r--r--src/libstrongswan/plugins/x509/x509_ac.c383
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c15
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_request.c2
-rw-r--r--src/libstrongswan/plugins/x509/x509_plugin.c4
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),