peer_cfg now knows about group memberships
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 13 Sep 2007 15:33:17 +0000 (15:33 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 13 Sep 2007 15:33:17 +0000 (15:33 -0000)
src/charon/config/backends/local_backend.c
src/charon/config/peer_cfg.c
src/charon/config/peer_cfg.h
src/charon/control/interfaces/stroke_interface.c
src/libstrongswan/Makefile.am
src/libstrongswan/crypto/ac.c
src/libstrongswan/crypto/ac.h
src/libstrongswan/crypto/ietf_attr_list.c [new file with mode: 0644]
src/libstrongswan/crypto/ietf_attr_list.h [new file with mode: 0644]

index 2e80cc8..b579509 100644 (file)
@@ -146,6 +146,13 @@ static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
                        int prio = (wc1 + wc2) * (MAX_CA_PATH_LEN + 1);
                        int pathlen = 0;
                        identification_t *other_candidate_ca = current->get_other_ca(current);
+                       linked_list_t *groups = current->get_groups(current);
+
+                       /* is a group membership required? */
+                       if (groups->get_count(groups) > 0)
+                       {
+                               DBG1(DBG_CFG, "  group membership required");
+                       }
 
                        /* are there any ca constraints? */
                        if (other_candidate_ca->get_type(other_candidate_ca) != ID_ANY)
index 4a802d5..6733df0 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <utils/linked_list.h>
 #include <utils/identification.h>
+#include <crypto/ietf_attr_list.h>
 
 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
        "CERT_ALWAYS_SEND",
@@ -105,6 +106,11 @@ struct private_peer_cfg_t {
        identification_t *other_ca;
        
        /**
+        * we require the other end to belong to at least one group
+        */
+       linked_list_t *groups;
+       
+       /**
         * should we send a certificate
         */
        cert_policy_t cert_policy;
@@ -279,10 +285,21 @@ static identification_t *get_my_ca(private_peer_cfg_t *this)
        return this->my_ca;
 }
 
+/**
+ * Implementation of peer_cfg_t.get_other_ca
+ */
 static identification_t *get_other_ca(private_peer_cfg_t *this)
 {
        return this->other_ca;
-}      
+}
+
+/**
+ * Implementation of peer_cfg_t.get_groups
+ */
+static linked_list_t *get_groups(private_peer_cfg_t *this)
+{
+       return this->groups;
+}
 
 /**
  * Implementation of peer_cfg_t.get_cert_policy.
@@ -417,9 +434,9 @@ static void destroy(private_peer_cfg_t *this)
                this->other_id->destroy(this->other_id);
                DESTROY_IF(this->my_ca);
                DESTROY_IF(this->other_ca);
-               
                DESTROY_IF(this->my_virtual_ip);
                DESTROY_IF(this->other_virtual_ip);
+               ietfAttr_list_destroy(this->groups);
                free(this->name);
                free(this);
        }
@@ -431,10 +448,11 @@ static void destroy(private_peer_cfg_t *this)
 peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
                                                        identification_t *my_id, identification_t *other_id,
                                                        identification_t *my_ca, identification_t *other_ca,
-                                                       cert_policy_t cert_policy, auth_method_t auth_method,
-                                                       eap_type_t eap_type, u_int32_t keyingtries,
-                                                       u_int32_t lifetime, u_int32_t rekeytime,
-                                                       u_int32_t jitter, bool reauth, bool mobike,
+                                                       linked_list_t *groups, cert_policy_t cert_policy,
+                                                       auth_method_t auth_method, eap_type_t eap_type,
+                                                       u_int32_t keyingtries, u_int32_t lifetime,
+                                                       u_int32_t rekeytime, u_int32_t jitter,
+                                                       bool reauth, bool mobike,
                                                        u_int32_t dpd_delay, dpd_action_t dpd_action,
                                                        host_t *my_virtual_ip, host_t *other_virtual_ip)
 {
@@ -451,6 +469,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
        this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id;
        this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca;
        this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca;
+       this->public.get_groups = (linked_list_t* (*)(peer_cfg_t *))get_groups;
        this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
        this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method;
        this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *))get_eap_type;
@@ -475,6 +494,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
        this->other_id = other_id;
        this->my_ca = my_ca;
        this->other_ca = other_ca;
+       this->groups = groups;
        this->cert_policy = cert_policy;
        this->auth_method = auth_method;
        this->eap_type = eap_type;
index edbcd95..1c6051f 100644 (file)
@@ -30,6 +30,7 @@ typedef struct peer_cfg_t peer_cfg_t;
 
 #include <library.h>
 #include <utils/identification.h>
+#include <utils/linked_list.h>
 #include <config/traffic_selector.h>
 #include <config/proposal.h>
 #include <config/ike_cfg.h>
@@ -194,7 +195,7 @@ struct peer_cfg_t {
        identification_t* (*get_my_ca)(peer_cfg_t *this);
 
        /**
-        * @brief Get peers CA.
+        * @brief Get peer CA.
         * 
         * @param this                  calling object
         * @return                              other ca
@@ -202,6 +203,14 @@ struct peer_cfg_t {
        identification_t* (*get_other_ca)(peer_cfg_t *this);
        
        /**
+        * @brief Get list of group attributes.
+        * 
+        * @param this                  calling object
+        * @return                              linked list of group attributes
+        */
+       linked_list_t* (*get_groups)(peer_cfg_t *this);
+
+       /**
         * @brief Should be sent a certificate for this connection?
         *
         * @param this          calling object
@@ -347,6 +356,7 @@ struct peer_cfg_t {
  * @param other_id                     identification_t for the remote guy
  * @param my_ca                                CA to use for us
  * @param other_ca                     CA to use for other
+ * @param groups                       list of group memberships
  * @param cert_policy          should we send a certificate payload?
  * @param auth_method          auth method to use to authenticate us
  * @param eap_type                     EAP type to use for peer authentication
@@ -367,10 +377,11 @@ struct peer_cfg_t {
 peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
                                                        identification_t *my_id, identification_t *other_id,
                                                        identification_t *my_ca, identification_t *other_ca,
-                                                       cert_policy_t cert_policy, auth_method_t auth_method,
-                                                       eap_type_t eap_type, u_int32_t keyingtries,
-                                                       u_int32_t lifetime, u_int32_t rekeytime,
-                                                       u_int32_t jitter, bool use_reauth, bool use_mobike,
+                                                       linked_list_t *groups, cert_policy_t cert_policy,
+                                                       auth_method_t auth_method, eap_type_t eap_type,
+                                                       u_int32_t keyingtries, u_int32_t lifetime,
+                                                       u_int32_t rekeytime, u_int32_t jitter,
+                                                       bool reauth, bool mobike,
                                                        u_int32_t dpd_delay, dpd_action_t dpd_action,
                                                        host_t *my_virtual_ip, host_t *other_virtual_ip);
 
index 7350c11..0da6465 100755 (executable)
@@ -38,6 +38,7 @@
 #include <stroke.h>
 #include <daemon.h>
 #include <crypto/x509.h>
+#include <crypto/ietf_attr_list.h>
 #include <crypto/ac.h>
 #include <crypto/ca.h>
 #include <crypto/crl.h>
@@ -238,6 +239,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
        bool other_ca_same =FALSE;
        host_t *my_host, *other_host, *my_subnet, *other_subnet;
        host_t *my_vip = NULL, *other_vip = NULL;
+       linked_list_t *my_groups = linked_list_create();
+       linked_list_t *other_groups = linked_list_create();
        proposal_t *proposal;
        traffic_selector_t *my_ts, *other_ts;
        char *interface;
@@ -475,6 +478,11 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
        DBG2(DBG_CFG, "  my ca:   '%D'", my_ca);
        DBG2(DBG_CFG, "  other ca:'%D'", other_ca);
 
+       if (msg->add_conn.other.groups)
+       {
+               ietfAttr_list_create_from_string(msg->add_conn.other.groups, other_groups);
+       }
+
        /* have a look for an (almost) identical peer config to reuse */
        iterator = charon->backends->create_iterator(charon->backends);
        while (iterator->iterate(iterator, (void**)&peer_cfg))
@@ -485,6 +493,7 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
                &&      my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg))
                &&      other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg))
                &&      other_ca->equals(other_ca, peer_cfg->get_other_ca(peer_cfg))
+               &&  ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg))
                &&      peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
                &&      peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
                &&      peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type)
@@ -507,6 +516,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
                other_host->destroy(other_host);
                other_id->destroy(other_id);
                other_ca->destroy(other_ca);
+               ietfAttr_list_destroy(my_groups);
+               ietfAttr_list_destroy(other_groups);
        }
        else
        {
@@ -554,7 +565,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
                
                
                peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
-                                       ike_cfg, my_id, other_id, my_ca, other_ca, msg->add_conn.me.sendcert, 
+                                       ike_cfg, my_id, other_id, my_ca, other_ca, other_groups,
+                                       msg->add_conn.me.sendcert,
                                        msg->add_conn.auth_method, msg->add_conn.eap_type,
                                        msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
                                        msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
@@ -1251,6 +1263,7 @@ static void stroke_status(stroke_msg_t *msg, FILE *out, bool all)
                        {
                                identification_t *my_ca = peer_cfg->get_my_ca(peer_cfg);
                                identification_t *other_ca = peer_cfg->get_other_ca(peer_cfg);
+                               linked_list_t *groups = peer_cfg->get_groups(peer_cfg);
 
                                if (my_ca->get_type(my_ca) != ID_ANY
                                ||  other_ca->get_type(other_ca) != ID_ANY)
@@ -1258,6 +1271,13 @@ static void stroke_status(stroke_msg_t *msg, FILE *out, bool all)
                                        fprintf(out, "%12s:    CAs: '%D'...'%D'\n", peer_cfg->get_name(peer_cfg),
                                                        my_ca, other_ca);
                                }
+                               if (groups->get_count(groups) > 0)
+                               {
+                                       fprintf(out, "%12s:    groups: ", peer_cfg->get_name(peer_cfg));
+                                       ietfAttr_list_list(groups, out);
+                                       fprintf(out, "\n");
+                               }
+                               
                        }
                        children = peer_cfg->create_child_cfg_iterator(peer_cfg);
                        while (children->iterate(children, (void**)&child_cfg))
index c7de8b3..d84e9da 100644 (file)
@@ -32,6 +32,7 @@ crypto/hashers/sha1_hasher.c crypto/hashers/sha1_hasher.h \
 crypto/hashers/sha2_hasher.c crypto/hashers/sha2_hasher.h \
 crypto/hashers/md5_hasher.c  crypto/hashers/md5_hasher.h \
 crypto/hmac.c crypto/hmac.h \
+crypto/ietf_attr_list.c crypto/ietf_attr_list.h \
 crypto/ocsp.c crypto/ocsp.h \
 crypto/prfs/fips_prf.c crypto/prfs/fips_prf.h \
 crypto/prfs/hmac_prf.c crypto/prfs/hmac_prf.h \
index 7ecf235..277b7cc 100644 (file)
 #include <asn1/asn1.h>
 #include <asn1/pem.h>
 #include <crypto/x509.h>
+#include <crypto/ietf_attr_list.h>
 #include <utils/identification.h>
 #include <utils/linked_list.h>
+#include <utils/lexparser.h>
 
 #include "ac.h"
 
@@ -145,219 +147,6 @@ struct private_x509ac_t {
 };
 
 /**
- * definition of ietfAttribute kinds
- */
-typedef enum {
-       IETF_ATTRIBUTE_OCTETS = 0,
-       IETF_ATTRIBUTE_OID =    1,
-       IETF_ATTRIBUTE_STRING = 2
-} ietfAttribute_t;
-
-/**
- * access structure for an ietfAttribute
- */
-typedef struct ietfAttr_t ietfAttr_t;
-
-struct ietfAttr_t {
-       /**
-        * IETF attribute kind
-        */
-       ietfAttribute_t kind;
-
-       /**
-        * IETF attribute valuse
-        */
-       chunk_t value;
-
-       /**
-        * Compares two ietfAttributes
-        *      
-        * 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 this          calling object
-        * @param other         other object
-        */
-       int (*compare) (const ietfAttr_t *this ,const ietfAttr_t *other);
-
-       /**
-        * Destroys the ietfAttr_t object.
-        * 
-        * @param this                  ietfAttr_t to destroy
-        */
-       void (*destroy) (ietfAttr_t *this);
-};
-
-/**
- * Implements ietfAttr_t.compare.
- */
-static int ietfAttr_compare(const ietfAttr_t *this ,const ietfAttr_t *other)
-{
-       int cmp_len, len, cmp_value;
-
-       /* OID attributes are appended after STRING and OCTETS attributes */
-       if (this->kind != IETF_ATTRIBUTE_OID && other->kind == IETF_ATTRIBUTE_OID)
-       {
-               return -1;
-       }
-       if (this->kind == IETF_ATTRIBUTE_OID && other->kind != IETF_ATTRIBUTE_OID)
-       {
-               return 1;
-       }
-       
-    cmp_len = this->value.len - other->value.len;
-    len = (cmp_len < 0)? this->value.len : other->value.len;
-    cmp_value = memcmp(this->value.ptr, other->value.ptr, len);
-
-    return (cmp_value == 0)? cmp_len : cmp_value;
-}
-
-/**
- * Adds an ietfAttr_t object to a sorted linked list
- */
-static void ietfAttr_add(linked_list_t *list, ietfAttr_t *attr)
-{
-       iterator_t *iterator = list->create_iterator(list, TRUE);
-       ietfAttr_t *current_attr;
-       bool found = FALSE;
-
-       while (iterator->iterate(iterator, (void **)&current_attr))
-       {
-               int cmp = attr->compare(attr, current_attr);
-
-               if (cmp > 0)
-               {
-                        continue;
-               }
-               if (cmp == 0)
-               {
-                       attr->destroy(attr);
-               }
-               else
-               {
-                       iterator->insert_before(iterator, attr);
-               }
-               found = TRUE;
-               break;
-       }
-       iterator->destroy(iterator);
-       if (!found)
-       {
-               list->insert_last(list, attr);
-       }
-}
-
-/**
- * Create a linked list of ietfAttr_t objects from a string
- */
-static void ietfAttr_create_from_string(linked_list_t *list, const char *msg)
-{
-
-}
-
-/**
- * Lists a linked list of ietfAttr_t objects
- */
-static void ietfAttr_list(linked_list_t *list, FILE *out)
-{
-       iterator_t *iterator = list->create_iterator(list, TRUE);
-       ietfAttr_t *attr;
-       bool first = TRUE;
-
-       while (iterator->iterate(iterator, (void **)&attr))
-       {
-               if (first)
-               {
-                       first = FALSE;
-               }
-               else
-               {
-                       fprintf(out, ", ");
-               }
-
-               switch (attr->kind)
-               {
-                       case IETF_ATTRIBUTE_OCTETS:
-                       case IETF_ATTRIBUTE_STRING:
-                               fprintf(out, "%.*s", (int)attr->value.len, attr->value.ptr);
-                               break;
-                       case IETF_ATTRIBUTE_OID:
-                               {
-                                       int oid = known_oid(attr->value);
-
-                                       if (oid == OID_UNKNOWN)
-                                       {
-                                               fprintf(out, "0x#B", &attr->value);
-                                       }
-                                       else
-                                       {
-                                               fprintf(out, "%s", oid_names[oid]);
-                                       }
-                               }
-                       break;
-                       default:
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-}
-
-/**
- * Destroys an ietfAttr_t object
- */
-static void ietfAttr_destroy(ietfAttr_t *this)
-{
-       free(this->value.ptr);
-       free(this);
-}
-
-/**
- * Creates an ietfAttr_t object.
- */
-ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value)
-{
-       ietfAttr_t *this = malloc_thing(ietfAttr_t);
-
-       /* initialize */
-       this->kind = kind;
-       this->value = chunk_clone(value);
-
-       /* function */
-       this->compare = ietfAttr_compare;
-       this->destroy = ietfAttr_destroy;
-
-       return this;
-}
-
-/**
- * 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 */
-};
-
-#define IETF_ATTR_OCTETS        4
-#define IETF_ATTR_OID           6
-#define IETF_ATTR_STRING        8
-#define IETF_ATTR_ROOF         11
-
-/**
  * ASN.1 definition of roleSyntax
  */
 static const asn1Object_t roleSyntaxObjects[] =
@@ -549,43 +338,6 @@ static bool parse_directoryName(chunk_t blob, int level, bool implicit, identifi
 }
 
 /**
- * parses ietfAttrSyntax
- */
-static void parse_ietfAttrSyntax(chunk_t blob, int level0, linked_list_t *list)
-{
-       asn1_ctx_t ctx;
-       chunk_t object;
-       u_int level;
-       int objectID = 0;
-
-       asn1_init(&ctx, blob, level0, FALSE, FALSE);
-
-       while (objectID < IETF_ATTR_ROOF)
-       {
-               if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
-               {
-                       return;
-               }
-
-               switch (objectID)
-               {
-                       case IETF_ATTR_OCTETS:
-                       case IETF_ATTR_OID:
-                       case IETF_ATTR_STRING:
-                               {
-                                       ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2;
-                                       ietfAttr_t *attr   = ietfAttr_create(kind, object);
-                                       ietfAttr_add(list, attr);
-                               }
-                               break;
-                       default:
-                               break;
-               }
-               objectID++;
-       }
-}
-
-/**
  * parses roleSyntax
  */
 static void parse_roleSyntax(chunk_t blob, int level0)
@@ -700,10 +452,10 @@ static bool parse_certificate(chunk_t blob, private_x509ac_t *this)
                                                        DBG2("  need to parse accessIdentity");
                                                        break;
                                                case OID_CHARGING_IDENTITY:
-                                                       parse_ietfAttrSyntax(object, level, this->charging);
+                                                       ietfAttr_list_create_from_chunk(object, this->charging, level);
                                                        break;
                                                case OID_GROUP:
-                                                       parse_ietfAttrSyntax(object, level, this->groups);
+                                                       ietfAttr_list_create_from_chunk(object, this->groups, level);
                                                        break;
                                                case OID_ROLE:
                                                        parse_roleSyntax(object, level);
@@ -781,7 +533,7 @@ static void list(const private_x509ac_t *this, FILE *out, bool utc)
        
        /* list all group attributes on a single line */
        fprintf(out, "    groups:     ");
-       ietfAttr_list(this->groups, out);
+       ietfAttr_list_list(this->groups, out);
        fprintf(out, "\n");
 
        fprintf(out, "    issuer:    '%D'\n", this->issuerName);
@@ -830,10 +582,8 @@ static void destroy(private_x509ac_t *this)
        DESTROY_IF(this->holderIssuer);
        DESTROY_IF(this->entityName);
        DESTROY_IF(this->issuerName);
-       this->charging->destroy_offset(this->charging, 
-                                                       offsetof(ietfAttr_t, destroy));
-       this->groups->destroy_offset(this->groups,
-                                                 offsetof(ietfAttr_t, destroy));
+       ietfAttr_list_destroy(this->charging);
+       ietfAttr_list_destroy(this->groups);
        free(this->certificate.ptr);
        free(this);
 }
index dc34429..9ef145e 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef AC_H_
 #define AC_H_
 
+#include <library.h>
+
 typedef struct x509ac_t x509ac_t;
 
 /**
@@ -94,14 +96,13 @@ x509ac_t *x509ac_create_from_chunk(chunk_t chunk);
 
 /**
  * @brief Read a x509 attribute certificate from a DER encoded file.
- * 
+ *
  * @param filename     file containing DER encoded data
- * @return                     created x509ac_t certificate, or NULL if invalid.
- * 
+ * @return             created x509ac_t certificate, or NULL if invalid.
+ *
  * @ingroup crypto
  */
 x509ac_t *x509ac_create_from_file(const char *filename);
 
-
 #endif /* AC_H_ */
 
diff --git a/src/libstrongswan/crypto/ietf_attr_list.c b/src/libstrongswan/crypto/ietf_attr_list.c
new file mode 100644 (file)
index 0000000..55d8bbe
--- /dev/null
@@ -0,0 +1,353 @@
+/**
+ * @file ietf_attr.c
+ * 
+ * @brief Implementation of ietfAttr_t.
+ * 
+ */
+
+/* 
+ * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <debug.h>
+#include <asn1/asn1.h>
+#include <utils/lexparser.h>
+
+#include "ietf_attr_list.h"
+
+/**
+ * Private definition of ietfAttribute kinds
+ */
+typedef enum {
+       IETF_ATTRIBUTE_OCTETS = 0,
+       IETF_ATTRIBUTE_OID =    1,
+       IETF_ATTRIBUTE_STRING = 2
+} ietfAttribute_t;
+
+typedef struct ietfAttr_t ietfAttr_t;
+
+/**
+ * Private definition of an ietfAttribute
+ */
+struct ietfAttr_t {
+       /**
+        * IETF attribute kind
+        */
+       ietfAttribute_t kind;
+
+       /**
+        * IETF attribute valuse
+        */
+       chunk_t value;
+
+       /**
+        * Compares two ietfAttributes
+        *      
+        * 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 this          calling object
+        * @param other         other object
+        */
+       int (*compare) (const ietfAttr_t *this ,const ietfAttr_t *other);
+
+       /**
+        * Destroys the ietfAttr_t object.
+        * 
+        * @param this                  ietfAttr_t to destroy
+        */
+       void (*destroy) (ietfAttr_t *this);
+};
+
+/**
+ * Implements ietfAttr_t.compare.
+ */
+static int ietfAttr_compare(const ietfAttr_t *this ,const ietfAttr_t *other)
+{
+       int cmp_len, len, cmp_value;
+
+       /* OID attributes are appended after STRING and OCTETS attributes */
+       if (this->kind != IETF_ATTRIBUTE_OID && other->kind == IETF_ATTRIBUTE_OID)
+       {
+               return -1;
+       }
+       if (this->kind == IETF_ATTRIBUTE_OID && other->kind != IETF_ATTRIBUTE_OID)
+       {
+               return 1;
+       }
+       
+    cmp_len = this->value.len - other->value.len;
+    len = (cmp_len < 0)? this->value.len : other->value.len;
+    cmp_value = memcmp(this->value.ptr, other->value.ptr, len);
+
+    return (cmp_value == 0)? cmp_len : cmp_value;
+}
+
+/**
+ * Implements ietfAttr_t.destroy.
+ */
+static void ietfAttr_destroy(ietfAttr_t *this)
+{
+       free(this->value.ptr);
+       free(this);
+}
+
+/**
+ * Creates an ietfAttr_t object.
+ */
+static ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value)
+{
+       ietfAttr_t *this = malloc_thing(ietfAttr_t);
+
+       /* initialize */
+       this->kind = kind;
+       this->value = chunk_clone(value);
+
+       /* function */
+       this->compare = ietfAttr_compare;
+       this->destroy = ietfAttr_destroy;
+
+       return this;
+}
+
+/**
+ * Adds an ietfAttr_t object to a sorted linked list
+ */
+static void ietfAttr_add(linked_list_t *list, ietfAttr_t *attr)
+{
+       iterator_t *iterator = list->create_iterator(list, TRUE);
+       ietfAttr_t *current_attr;
+       bool found = FALSE;
+
+       while (iterator->iterate(iterator, (void **)&current_attr))
+       {
+               int cmp = attr->compare(attr, current_attr);
+
+               if (cmp > 0)
+               {
+                        continue;
+               }
+               if (cmp == 0)
+               {
+                       attr->destroy(attr);
+               }
+               else
+               {
+                       iterator->insert_before(iterator, attr);
+               }
+               found = TRUE;
+               break;
+       }
+       iterator->destroy(iterator);
+       if (!found)
+       {
+               list->insert_last(list, attr);
+       }
+}
+
+/*
+ * Described in header.
+ */
+bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b)
+{
+        bool result = TRUE;
+
+       /* lists must have the same number of attributes */
+       if (list_a->get_count(list_a) != list_b->get_count(list_b))
+       {
+               return FALSE;
+       }
+       /* empty lists - no attributes */
+       if (list_a->get_count(list_a) == 0)
+       {
+               return TRUE;
+       }
+
+       /* compare two alphabetically-sorted lists */
+       {
+               iterator_t *iterator_a = list_a->create_iterator(list_a, TRUE);
+               iterator_t *iterator_b = list_b->create_iterator(list_b, TRUE);
+               ietfAttr_t *attr_a, *attr_b;
+
+               while (iterator_a->iterate(iterator_a, (void **)&attr_a) &&
+                          iterator_b->iterate(iterator_b, (void **)&attr_b))
+               {
+                       if (attr_a->compare(attr_a, attr_b) != 0)
+                       {
+                               /* we have a mismatch */
+                               result = FALSE;
+                               break;
+                       }
+               }
+               iterator_a->destroy(iterator_a);
+               iterator_b->destroy(iterator_b);
+       }
+       return result;
+}
+
+/*
+ * Described in header.
+ */
+void ietfAttr_list_list(linked_list_t *list, FILE *out)
+{
+       iterator_t *iterator = list->create_iterator(list, TRUE);
+       ietfAttr_t *attr;
+       bool first = TRUE;
+
+       while (iterator->iterate(iterator, (void **)&attr))
+       {
+               if (first)
+               {
+                       first = FALSE;
+               }
+               else
+               {
+                       fprintf(out, ", ");
+               }
+
+               switch (attr->kind)
+               {
+                       case IETF_ATTRIBUTE_OCTETS:
+                       case IETF_ATTRIBUTE_STRING:
+                               fprintf(out, "%.*s", (int)attr->value.len, attr->value.ptr);
+                               break;
+                       case IETF_ATTRIBUTE_OID:
+                               {
+                                       int oid = known_oid(attr->value);
+
+                                       if (oid == OID_UNKNOWN)
+                                       {
+                                               fprintf(out, "0x#B", &attr->value);
+                                       }
+                                       else
+                                       {
+                                               fprintf(out, "%s", oid_names[oid]);
+                                       }
+                               }
+                       break;
+                       default:
+                       break;
+               }
+       }
+       iterator->destroy(iterator);
+}
+
+/*
+ * Described in header.
+ */
+void ietfAttr_list_create_from_string(char *msg, linked_list_t *list)
+{
+       chunk_t line = { msg, strlen(msg) };
+
+       while (eat_whitespace(&line))
+       {
+               chunk_t group;
+
+               /* extract the next comma-separated group attribute */
+               if (!extract_token(&group, ',', &line))
+               {
+                       group = line;
+                       line.len = 0;
+               }
+
+               /* remove any trailing spaces */
+               while (group.len > 0 && *(group.ptr + group.len - 1) == ' ')
+               {
+                       group.len--;
+               }
+
+               /* add the group attribute to the list */
+               if (group.len > 0)
+               {
+                       ietfAttr_t *attr = ietfAttr_create(IETF_ATTRIBUTE_STRING, group);
+               
+                       ietfAttr_add(list, attr);
+               }
+       }
+}
+
+/**
+ * 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 */
+};
+
+#define IETF_ATTR_OCTETS        4
+#define IETF_ATTR_OID           6
+#define IETF_ATTR_STRING        8
+#define IETF_ATTR_ROOF         11
+
+/*
+ * Described in header.
+ */
+void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0)
+{
+       asn1_ctx_t ctx;
+       chunk_t object;
+       u_int level;
+       int objectID = 0;
+
+       asn1_init(&ctx, chunk, level0, FALSE, FALSE);
+
+       while (objectID < IETF_ATTR_ROOF)
+       {
+               if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
+               {
+                       return;
+               }
+
+               switch (objectID)
+               {
+                       case IETF_ATTR_OCTETS:
+                       case IETF_ATTR_OID:
+                       case IETF_ATTR_STRING:
+                               {
+                                       ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2;
+                                       ietfAttr_t *attr   = ietfAttr_create(kind, object);
+                                       ietfAttr_add(list, attr);
+                               }
+                               break;
+                       default:
+                               break;
+               }
+               objectID++;
+       }
+}
+
+/*
+ * Described in header.
+ */
+void ietfAttr_list_destroy(linked_list_t *list)
+{
+       list->destroy_offset(list, offsetof(ietfAttr_t, destroy));
+}
diff --git a/src/libstrongswan/crypto/ietf_attr_list.h b/src/libstrongswan/crypto/ietf_attr_list.h
new file mode 100644 (file)
index 0000000..8352cad
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * @file ietf_attr_list.h
+ * 
+ * @brief Handling of ietfAttr_t linked lists
+ * 
+ */
+
+/*
+ * Copyright (C) 2007 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef IETF_ATTR_LIST_H_
+#define IETF_ATTR_LIST_H_
+
+#include <library.h>
+#include <utils/linked_list.h>
+
+
+/**
+ * @brief Compare two linked lists of ietfAttr_t objects for equality
+ *
+ * @param list_a       first alphabetically-sorted list
+ * @param list_b       second alphabetically-sorted list
+ * @return                     TRUE if equal   
+ *
+ * @ingroup crypto
+ */
+bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b);
+
+/**
+ * @brief Lists a linked list of ietfAttr_t objects
+ *
+ * @param list         alphabetically-sorted linked list of attributes
+   @param out          output file     
+ *
+ * @ingroup crypto
+ */
+void ietfAttr_list_list(linked_list_t *list, FILE *out);
+
+/**
+ * @brief Create a linked list of ietfAttr_t objects from a string
+ *
+ * @param msg          string with comma-separated group names
+ * @param list         alphabetically-sorted linked list of attributes
+ *
+ * @ingroup crypto
+ */
+void ietfAttr_list_create_from_string(char *msg, linked_list_t *list);
+
+/**
+ * @brief Create a linked list of ietfAttr_t objects from an ASN.1-coded chunk
+ *
+ * @param chunk                chunk containing ASN.1-coded attributes
+ * @param list         alphabetically-sorted linked list of attributes
+ * @param level0       parsing level
+ */
+void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0);
+
+/**
+ * @brief Destroys a linked list of ietfAttr_t objects
+ *
+ * @param list         list to be destroyed
+ *
+ * @ingroup crypto
+ */
+void ietfAttr_list_destroy(linked_list_t *list);
+
+#endif /* IETF_ATTR_LIST_H_ */
+