updated XML interface to new schema
[strongswan.git] / src / libstrongswan / utils / identification.c
index 55eef6c..b842a8c 100644 (file)
@@ -30,7 +30,6 @@
 #include <ctype.h>
 #include <printf.h>
 
-#include "definitions.h"
 #include "identification.h"
 
 #include <asn1/asn1.h>
@@ -225,17 +224,19 @@ static chunk_t sanitize_chunk(chunk_t chunk)
        {
                switch (*pos)
                {
-                       case 'a' ... 'z':
-                       case 'A' ... 'Z':
-                       case '0' ... '9':
+                       case '\0':
+                       case ' ':
+                       case '*':
                        case '-':
-                       case '_':
                        case '.':
-                       case '=':
-                       case ':':
                        case '/':
+                       case '0' ... '9':
+                       case ':':
+                       case '=':
                        case '@':
-                       case '\0':
+                       case 'A' ... 'Z':
+                       case '_':
+                       case 'a' ... 'z':
                                break;
                        default:
                                *pos = '?';
@@ -249,8 +250,8 @@ static chunk_t sanitize_chunk(chunk_t chunk)
  */
 static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
 {
-       *rdn = CHUNK_INITIALIZER;
-       *attribute = CHUNK_INITIALIZER;
+       *rdn = chunk_empty;
+       *attribute = chunk_empty;
        
        /* a DN is a SEQUENCE OF RDNs */
        if (*dn.ptr != ASN1_SEQUENCE)
@@ -283,8 +284,8 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch
        chunk_t body;
 
        /* initialize return values */
-       *oid   = CHUNK_INITIALIZER;
-       *value = CHUNK_INITIALIZER;
+       *oid   = chunk_empty;
+       *value = chunk_empty;
 
        /* if all attributes have been parsed, get next rdn */
        if (attribute->len <= 0)
@@ -496,7 +497,10 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards)
        bool next_a, next_b;
 
        /* initialize wildcard counter */
-       *wildcards = 0;
+       if (wildcards)
+       {
+               *wildcards = 0;
+       }
 
        /* initialize DN parsing */
        if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS
@@ -521,7 +525,10 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards)
                /* does rdn_b contain a wildcard? */
                if (value_b.len == 1 && *value_b.ptr == '*')
                {
-                       (*wildcards)++;
+                       if (wildcards)
+                       {
+                               (*wildcards)++;
+                       }
                        continue;
                }
                /* same lengths for values */
@@ -548,7 +555,10 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards)
        }
 
        /* the two DNs match! */
-       *wildcards = min(*wildcards, MAX_WILDCARDS);
+       if (wildcards)
+       {
+               *wildcards = min(*wildcards, MAX_WILDCARDS);
+       }
        return TRUE;
 }
 
@@ -567,8 +577,8 @@ static status_t atodn(char *src, chunk_t *dn)
                UNKNOWN_OID =   4
        } state_t;
        
-       chunk_t oid  = CHUNK_INITIALIZER;
-       chunk_t name = CHUNK_INITIALIZER;
+       chunk_t oid  = chunk_empty;
+       chunk_t name = chunk_empty;
        chunk_t rdns[RDN_MAX];
        int rdn_count = 0;
        int dn_len = 0;
@@ -612,7 +622,7 @@ static status_t atodn(char *src, chunk_t *dn)
                                                break;
                                        }
                                        /* reset oid and change state */
-                                       oid = CHUNK_INITIALIZER;
+                                       oid = chunk_empty;
                                        state = SEARCH_NAME;
                                }
                                break;
@@ -656,7 +666,7 @@ static status_t atodn(char *src, chunk_t *dn)
                                                status = OUT_OF_RES;
                                        }
                                        /* reset name and change state */
-                                       name = CHUNK_INITIALIZER;
+                                       name = chunk_empty;
                                        state = SEARCH_OID;
                                }
                                break;
@@ -681,7 +691,7 @@ static status_t atodn(char *src, chunk_t *dn)
        if (status != SUCCESS)
        {
                free(dn->ptr);
-               *dn = CHUNK_INITIALIZER;
+               *dn = chunk_empty;
        }
        return status;
 }
@@ -728,8 +738,15 @@ static bool contains_wildcards(private_identification_t *this)
  */
 static bool equals_binary(private_identification_t *this, private_identification_t *other)
 {
-       return this->type == other->type && 
-                                                       chunk_equals(this->encoded, other->encoded);
+       if (this->type == other->type)
+       {
+               if (this->type == ID_ANY)
+               {
+                       return TRUE;
+               }
+               return chunk_equals(this->encoded, other->encoded);
+       }
+       return FALSE;                                           
 }
 
 /**
@@ -742,6 +759,24 @@ static bool equals_dn(private_identification_t *this,
 }
 
 /**
+ * Special implementation of identification_t.equals for RFC822 and FQDN.
+ */
+static bool equals_strcasecmp(private_identification_t *this,
+                                                         private_identification_t *other)
+{
+       /* we do some extra sanity checks to check for invalid IDs with a 
+        * terminating null in it. */
+       if (this->encoded.len == other->encoded.len &&
+               memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
+               memchr(other->encoded.ptr, 0, other->encoded.len) == NULL &&
+               strncasecmp(this->encoded.ptr, other->encoded.ptr, this->encoded.len) == 0)
+       {
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/**
  * Default implementation of identification_t.matches.
  */
 static bool matches_binary(private_identification_t *this, 
@@ -749,10 +784,16 @@ static bool matches_binary(private_identification_t *this,
 {
        if (other->type == ID_ANY)
        {
-               *wildcards = MAX_WILDCARDS;
+               if (wildcards)
+               {
+                       *wildcards = MAX_WILDCARDS;
+               }
                return TRUE;
        }
-       *wildcards = 0;
+       if (wildcards)
+       {
+               *wildcards = 0;
+       }
        return this->type == other->type &&
                                                        chunk_equals(this->encoded, other->encoded);
 }
@@ -768,7 +809,10 @@ static bool matches_string(private_identification_t *this,
        
        if (other->type == ID_ANY)
        {
-               *wildcards = MAX_WILDCARDS;
+               if (wildcards)
+               {
+                       *wildcards = MAX_WILDCARDS;
+               }
                return TRUE;
        }
        
@@ -778,7 +822,10 @@ static bool matches_string(private_identification_t *this,
        /* try a binary comparison first */
        if (equals_binary(this, other))
        {
-               *wildcards = 0;
+               if (wildcards)
+               {
+                       *wildcards = 0;
+               }
                return TRUE;
        }
        
@@ -788,7 +835,10 @@ static bool matches_string(private_identification_t *this,
        /* check for single wildcard at the head of the string */
        if (*other->encoded.ptr == '*')
        {
-               *wildcards = 1;
+               if (wildcards)
+               {
+                       *wildcards = 1;
+               }
 
                /* single asterisk matches any string */
                if (len-- == 1)
@@ -808,7 +858,10 @@ static bool matches_string(private_identification_t *this,
 static bool matches_any(private_identification_t *this,
                                                private_identification_t *other, int *wildcards)
 {
-       *wildcards = 0;
+       if (wildcards)
+       {
+               *wildcards = 0;
+       }
        return other->type == ID_ANY;
 }
 
@@ -821,7 +874,10 @@ static bool matches_dn(private_identification_t *this,
 {
        if (other->type == ID_ANY)
        {
-               *wildcards = MAX_WILDCARDS;
+               if (wildcards)
+               {
+                       *wildcards = MAX_WILDCARDS;
+               }
                return TRUE;
        }
        
@@ -875,7 +931,7 @@ static int print(FILE *stream, const struct printf_info *info,
                case ID_FQDN:
                {
                        proper = sanitize_chunk(this->encoded);
-                       written = fprintf(stream, "@%.*s", proper.len, proper.ptr);
+                       written = fprintf(stream, "%.*s", proper.len, proper.ptr);
                        chunk_free(&proper);
                        return written;
                }
@@ -910,34 +966,25 @@ static int print(FILE *stream, const struct printf_info *info,
 }
 
 /**
- * arginfo handler in printf()
- */
-static int print_arginfo(const struct printf_info *info, size_t n, int *argtypes)
-{
-       if (n > 0)
-       {
-               argtypes[0] = PA_POINTER;
-       }
-       return 1;
-}
-
-/**
  * register printf() handlers
  */
 static void __attribute__ ((constructor))print_register()
 {
-       register_printf_function(IDENTIFICATION_PRINTF_SPEC, print, print_arginfo);
+       register_printf_function(PRINTF_IDENTIFICATION, print, arginfo_ptr);
 }
 
 /**
  * Implementation of identification_t.clone.
  */
-static identification_t *clone(private_identification_t *this)
+static identification_t *clone_(private_identification_t *this)
 {
        private_identification_t *clone = identification_create();
        
        clone->type = this->type;
-       clone->encoded = chunk_clone(this->encoded);
+       if (this->encoded.len)
+       {
+               clone->encoded = chunk_clone(this->encoded);
+       }
        clone->public.equals = this->public.equals;
        clone->public.matches = this->public.matches;
        
@@ -963,13 +1010,13 @@ static private_identification_t *identification_create(void)
        this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
        this->public.get_type = (id_type_t (*) (identification_t*))get_type;
        this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards;
-       this->public.clone = (identification_t* (*) (identification_t*))clone;
+       this->public.clone = (identification_t* (*) (identification_t*))clone_;
        this->public.destroy = (void (*) (identification_t*))destroy;
        /* we use these as defaults, the may be overloaded for special ID types */
        this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
        this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_binary;
        
-       this->encoded = CHUNK_INITIALIZER;
+       this->encoded = chunk_empty;
        
        return this;
 }
@@ -1065,6 +1112,8 @@ identification_t *identification_create_from_string(char *string)
                                this->encoded.len = strlen(string + 1);
                                this->public.matches = (bool (*) 
                                                (identification_t*,identification_t*,int*))matches_string;
+                               this->public.equals = (bool (*)
+                                                       (identification_t*,identification_t*))equals_strcasecmp;
                                return &(this->public);
                        }
                }
@@ -1075,6 +1124,8 @@ identification_t *identification_create_from_string(char *string)
                        this->encoded.len = strlen(string);
                        this->public.matches = (bool (*) 
                                        (identification_t*,identification_t*,int*))matches_string;
+                       this->public.equals = (bool (*)
+                                               (identification_t*,identification_t*))equals_strcasecmp;
                        return &(this->public);
                }
        }
@@ -1094,12 +1145,11 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
                                        (identification_t*,identification_t*,int*))matches_any;
                        break;
                case ID_FQDN:
-                       this->public.matches = (bool (*)
-                                       (identification_t*,identification_t*,int*))matches_string;
-                       break;
                case ID_RFC822_ADDR:
                        this->public.matches = (bool (*)
                                        (identification_t*,identification_t*,int*))matches_string;
+                       this->public.equals = (bool (*)
+                                               (identification_t*,identification_t*))equals_strcasecmp;
                        break;
                case ID_DER_ASN1_DN:
                        this->public.equals = (bool (*)
@@ -1123,3 +1173,4 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
        }
        return &(this->public);
 }
+