x509: Replace fixed acert group string getter by a more dynamic group enumerator
authorMartin Willi <martin@revosec.ch>
Tue, 4 Feb 2014 14:41:09 +0000 (15:41 +0100)
committerMartin Willi <martin@revosec.ch>
Mon, 31 Mar 2014 09:14:58 +0000 (11:14 +0200)
src/libcharon/plugins/stroke/stroke_list.c
src/libstrongswan/credentials/certificates/ac.h
src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c
src/libstrongswan/credentials/ietf_attributes/ietf_attributes.h
src/libstrongswan/plugins/x509/x509_ac.c

index ea16805..991bed1 100644 (file)
@@ -31,8 +31,9 @@
 #include <credentials/certificates/ac.h>
 #include <credentials/certificates/crl.h>
 #include <credentials/certificates/pgp_certificate.h>
-#include <credentials/ietf_attributes/ietf_attributes.h>
 #include <config/peer_cfg.h>
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
 
 /* warning intervals for list functions */
 #define CERT_WARNING_INTERVAL  30      /* days */
@@ -1027,16 +1028,19 @@ static void stroke_list_certs(linked_list_t *list, char *label,
 static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
 {
        bool first = TRUE;
-       time_t thisUpdate, nextUpdate, now = time(NULL);
-       enumerator_t *enumerator = list->create_enumerator(list);
+       time_t notBefore, notAfter, now = time(NULL);
+       enumerator_t *enumerator;
        certificate_t *cert;
 
-       while (enumerator->enumerate(enumerator, (void**)&cert))
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &cert))
        {
                ac_t *ac = (ac_t*)cert;
+               ac_group_type_t type;
                identification_t *id;
-               ietf_attributes_t *groups;
+               enumerator_t *groups;
                chunk_t chunk;
+               bool firstgroup = TRUE;
 
                if (first)
                {
@@ -1061,30 +1065,78 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
                {
                        fprintf(out, "  hserial:   %#B\n", &chunk);
                }
-               groups = ac->get_groups(ac);
-               if (groups)
+               groups = ac->create_group_enumerator(ac);
+               while (groups->enumerate(groups, &type, &chunk))
                {
-                       fprintf(out, "  groups:    %s\n", groups->get_string(groups));
-                       groups->destroy(groups);
+                       int oid;
+                       char *str;
+
+                       if (firstgroup)
+                       {
+                               fprintf(out, "  groups:    ");
+                               firstgroup = FALSE;
+                       }
+                       else
+                       {
+                               fprintf(out, "             ");
+                       }
+                       switch (type)
+                       {
+                               case AC_GROUP_TYPE_STRING:
+                                       fprintf(out, "%.*s", (int)chunk.len, chunk.ptr);
+                                       break;
+                               case AC_GROUP_TYPE_OID:
+                                       oid = asn1_known_oid(chunk);
+                                       if (oid == OID_UNKNOWN)
+                                       {
+                                               str = asn1_oid_to_string(chunk);
+                                               if (str)
+                                               {
+                                                       fprintf(out, "%s", str);
+                                               }
+                                               else
+                                               {
+                                                       fprintf(out, "OID:%#B", &chunk);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               fprintf(out, "%s", oid_names[oid].name);
+                                       }
+                                       break;
+                               case AC_GROUP_TYPE_OCTETS:
+                                       fprintf(out, "%#B", &chunk);
+                                       break;
+                       }
+                       fprintf(out, "\n");
                }
+               groups->destroy(groups);
                fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
                chunk  = chunk_skip_zero(ac->get_serial(ac));
                fprintf(out, "  serial:    %#B\n", &chunk);
 
                /* list validity */
-               cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
-               fprintf(out, "  updates:   this %T\n",  &thisUpdate, utc);
-               fprintf(out, "             next %T, ", &nextUpdate, utc);
-               if (now > nextUpdate)
+               cert->get_validity(cert, &now, &notBefore, &notAfter);
+               fprintf(out, "  validity:  not before %T, ", &notBefore, utc);
+               if (now < notBefore)
                {
-                       fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
+                       fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
+               }
+               else
+               {
+                       fprintf(out, "ok\n");
+               }
+               fprintf(out, "             not after  %T, ", &notAfter, utc);
+               if (now > notAfter)
+               {
+                       fprintf(out, "expired (%V ago)\n", &now, &notAfter);
                }
                else
                {
                        fprintf(out, "ok");
-                       if (now > nextUpdate - AC_WARNING_INTERVAL * 60 * 60 * 24)
+                       if (now > notAfter - AC_WARNING_INTERVAL * 60 * 60 * 24)
                        {
-                               fprintf(out, " (expires in %V)", &now, &nextUpdate);
+                               fprintf(out, " (expires in %V)", &now, &notAfter);
                        }
                        fprintf(out, " \n");
                }
index 0bf7620..1094cdc 100644 (file)
 #include <credentials/ietf_attributes/ietf_attributes.h>
 
 typedef struct ac_t ac_t;
+typedef enum ac_group_type_t ac_group_type_t;
+
+/**
+ * Common group types, from IETF Attributes Syntax
+ */
+enum ac_group_type_t {
+       AC_GROUP_TYPE_OCTETS,
+       AC_GROUP_TYPE_STRING,
+       AC_GROUP_TYPE_OID,
+};
 
 /**
  * X.509 attribute certificate interface.
@@ -70,11 +80,11 @@ struct ac_t {
        chunk_t (*get_authKeyIdentifier)(ac_t *this);
 
        /**
-        * Get the group memberships as a list of IETF attributes
+        * Create an enumerator of contained Group memberships.
         *
-        * @return                      object containing a list of IETF attributes
+        * @return                      enumerator over (ac_group_type_t, chunk_t)
         */
-       ietf_attributes_t* (*get_groups)(ac_t *this);
+       enumerator_t* (*create_group_enumerator)(ac_t *this);
 };
 
 #endif /** AC_H_ @}*/
index 49af5a0..6efbfb7 100644 (file)
 #include <asn1/asn1_parser.h>
 #include <collections/linked_list.h>
 #include <utils/lexparser.h>
+#include <credentials/certificates/ac.h>
 
 #include "ietf_attributes.h"
 
-/**
- * Private definition of IETF attribute types
- */
-typedef enum {
-       IETF_ATTRIBUTE_OCTETS = 0,
-       IETF_ATTRIBUTE_OID =    1,
-       IETF_ATTRIBUTE_STRING = 2
-} ietf_attribute_type_t;
-
 typedef struct ietf_attr_t ietf_attr_t;
 
 /**
  * Private definition of an IETF attribute
  */
 struct ietf_attr_t {
+
        /**
         * IETF attribute type
         */
-       ietf_attribute_type_t type;
+       ac_group_type_t type;
 
        /**
         * IETF attribute value
         */
        chunk_t value;
-
-       /**
-        * Compares two IETF attributes
-        *
-        * return -1 if this is earlier in the alphabet than other
-        * return  0 if this equals other
-        * return +1 if this is later in the alphabet than other
-        *
-        * @param other         other object
-        */
-       int (*compare) (ietf_attr_t *this, ietf_attr_t *other);
-
-       /**
-        * Destroys an ietf_attr_t object.
-        */
-       void (*destroy) (ietf_attr_t *this);
 };
 
 /**
@@ -72,11 +49,11 @@ static int ietf_attr_compare(ietf_attr_t *this, ietf_attr_t *other)
        int cmp_len, len, cmp_value;
 
        /* OID attributes are appended after STRING and OCTETS attributes */
-       if (this->type != IETF_ATTRIBUTE_OID && other->type == IETF_ATTRIBUTE_OID)
+       if (this->type != AC_GROUP_TYPE_OID && other->type == AC_GROUP_TYPE_OID)
        {
                return -1;
        }
-       if (this->type == IETF_ATTRIBUTE_OID && other->type != IETF_ATTRIBUTE_OID)
+       if (this->type == AC_GROUP_TYPE_OID && other->type != AC_GROUP_TYPE_OID)
        {
                return 1;
        }
@@ -100,13 +77,11 @@ static void ietf_attr_destroy(ietf_attr_t *this)
 /**
  * Creates an ietf_attr_t object.
  */
-static ietf_attr_t* ietf_attr_create(ietf_attribute_type_t type, chunk_t value)
+static ietf_attr_t* ietf_attr_create(ac_group_type_t type, chunk_t value)
 {
        ietf_attr_t *this;
 
        INIT(this,
-               .compare = ietf_attr_compare,
-               .destroy = ietf_attr_destroy,
                .type = type,
                .value = chunk_clone(value),
        );
@@ -175,12 +150,12 @@ METHOD(ietf_attributes_t, get_string, char*,
 
                        switch (attr->type)
                        {
-                               case IETF_ATTRIBUTE_OCTETS:
-                               case IETF_ATTRIBUTE_STRING:
+                               case AC_GROUP_TYPE_OCTETS:
+                               case AC_GROUP_TYPE_STRING:
                                        written = snprintf(pos, len, "%.*s", (int)attr->value.len,
                                                                                                                 attr->value.ptr);
                                        break;
-                               case IETF_ATTRIBUTE_OID:
+                               case AC_GROUP_TYPE_OID:
                                {
                                        int oid = asn1_known_oid(attr->value);
 
@@ -214,6 +189,24 @@ METHOD(ietf_attributes_t, get_string, char*,
        return this->string;
 }
 
+/**
+ * Filter function for attribute enumeration
+ */
+static bool attr_filter(void *null, ietf_attr_t **in, ac_group_type_t *type,
+                                               void *in2, chunk_t *out)
+{
+       *type = (*in)->type;
+       *out = (*in)->value;
+       return TRUE;
+}
+
+METHOD(ietf_attributes_t, create_enumerator, enumerator_t*,
+       private_ietf_attributes_t *this)
+{
+       return enumerator_create_filter(this->list->create_enumerator(this->list),
+                                                               (void*)attr_filter, NULL, NULL);
+}
+
 METHOD(ietf_attributes_t, get_encoding, chunk_t,
        private_ietf_attributes_t *this)
 {
@@ -243,13 +236,13 @@ METHOD(ietf_attributes_t, get_encoding, chunk_t,
 
                switch (attr->type)
                {
-                       case IETF_ATTRIBUTE_OCTETS:
+                       case AC_GROUP_TYPE_OCTETS:
                                type = ASN1_OCTET_STRING;
                                break;
-                       case IETF_ATTRIBUTE_STRING:
+                       case AC_GROUP_TYPE_STRING:
                                type = ASN1_UTF8STRING;
                                break;
-                       case IETF_ATTRIBUTE_OID:
+                       case AC_GROUP_TYPE_OID:
                                type = ASN1_OID;
                                break;
                }
@@ -290,7 +283,7 @@ static bool equals(private_ietf_attributes_t *this,
                while (enum_a->enumerate(enum_a, &attr_a) &&
                           enum_b->enumerate(enum_b, &attr_b))
                {
-                       if (attr_a->compare(attr_a, attr_b) != 0)
+                       if (ietf_attr_compare(attr_a, attr_b) != 0)
                        {
                                /* we have a mismatch */
                                result = FALSE;
@@ -334,8 +327,9 @@ static bool matches(private_ietf_attributes_t *this,
        /* look for at least one common attribute */
        while (TRUE)
        {
-               int cmp = attr_a->compare(attr_a, attr_b);
+               int cmp;
 
+               cmp = ietf_attr_compare(attr_a, attr_b);
                if (cmp == 0)
                {
                        /* we have a match */
@@ -379,7 +373,7 @@ METHOD(ietf_attributes_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
-               this->list->destroy_offset(this->list, offsetof(ietf_attr_t, destroy));
+               this->list->destroy_function(this->list, (void*)ietf_attr_destroy);
                free(this->string);
                free(this);
        }
@@ -392,6 +386,7 @@ static private_ietf_attributes_t* create_empty(void)
        INIT(this,
                .public = {
                        .get_string = _get_string,
+                       .create_enumerator = _create_enumerator,
                        .get_encoding = _get_encoding,
                        .equals = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))equals,
                        .matches = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))matches,
@@ -417,13 +412,13 @@ static void ietf_attributes_add(private_ietf_attributes_t *this,
 
        enumerator = this->list->create_enumerator(this->list);
        while (enumerator->enumerate(enumerator, (void **)&current_attr) &&
-                 (cmp = attr->compare(attr, current_attr)) > 0)
+                 (cmp = ietf_attr_compare(attr, current_attr)) > 0)
        {
                continue;
        }
        if (cmp == 0)
        {
-               attr->destroy(attr);
+               ietf_attr_destroy(attr);
        }
        else
        {       /* the enumerator either points to the end or to the attribute > attr */
@@ -461,7 +456,7 @@ ietf_attributes_t *ietf_attributes_create_from_string(char *string)
                /* add the group attribute to the list */
                if (group.len > 0)
                {
-                       ietf_attr_t *attr = ietf_attr_create(IETF_ATTRIBUTE_STRING, group);
+                       ietf_attr_t *attr = ietf_attr_create(AC_GROUP_TYPE_STRING, group);
 
                        ietf_attributes_add(this, attr);
                }
@@ -515,7 +510,7 @@ ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded)
                        case IETF_ATTR_OID:
                        case IETF_ATTR_STRING:
                                {
-                                       ietf_attribute_type_t type;
+                                       ac_group_type_t type;
                                        ietf_attr_t *attr;
 
                                        type = (objectID - IETF_ATTR_OCTETS) / 2;
@@ -531,4 +526,3 @@ ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded)
 
        return &(this->public);
 }
-
index ab6bae9..a34b23a 100644 (file)
@@ -41,6 +41,13 @@ struct ietf_attributes_t {
        char* (*get_string) (ietf_attributes_t *this);
 
        /**
+        * Create an enumerator over attributes.
+        *
+        * @return                      enumerator over (ac_group_type_t, chunk_t)
+        */
+       enumerator_t* (*create_enumerator)(ietf_attributes_t *this);
+
+       /**
         * Get the ASN.1 encoding of the IETF attributes.
         *
         * @return                      allocated chunk containing the encoded bytes
@@ -58,7 +65,7 @@ struct ietf_attributes_t {
        /**
         * Check for common attributes between two lists.
         *
-        * @param other         attribute list to be matched 
+        * @param other         attribute list to be matched
         * @return                      TRUE if there is at least a common attribute
         */
        bool (*matches) (ietf_attributes_t *this, ietf_attributes_t *other);
@@ -89,4 +96,3 @@ ietf_attributes_t *ietf_attributes_create_from_string(char *string);
 ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded);
 
 #endif /** IETF_ATTRIBUTES_H_ @}*/
-
index b7da97d..9845b21 100644 (file)
@@ -655,10 +655,10 @@ METHOD(ac_t, get_authKeyIdentifier, chunk_t,
        return this->authKeyIdentifier;
 }
 
-METHOD(ac_t, get_groups, ietf_attributes_t*,
+METHOD(ac_t, create_group_enumerator, enumerator_t*,
        private_x509_ac_t *this)
 {
-       return this->groups ? this->groups->get_ref(this->groups) : NULL;
+       return this->groups->create_enumerator(this->groups);
 }
 
 METHOD(certificate_t, get_type, certificate_type_t,
@@ -866,7 +866,7 @@ 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,
                        },
                },
                .ref = 1,