aboutsummaryrefslogtreecommitdiffstats
path: root/Source/lib/utils/identification.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/lib/utils/identification.c')
-rw-r--r--Source/lib/utils/identification.c1167
1 files changed, 0 insertions, 1167 deletions
diff --git a/Source/lib/utils/identification.c b/Source/lib/utils/identification.c
deleted file mode 100644
index 33f3d92cd..000000000
--- a/Source/lib/utils/identification.c
+++ /dev/null
@@ -1,1167 +0,0 @@
-/**
- * @file identification.c
- *
- * @brief Implementation of identification_t.
- *
- */
-
-/*
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "identification.h"
-
-#include <asn1/asn1.h>
-
-/**
- * String mappings for id_type_t.
- */
-mapping_t id_type_m[] = {
- {ID_IPV4_ADDR, "ID_IPV4_ADDR"},
- {ID_FQDN, "ID_FQDN"},
- {ID_RFC822_ADDR, "ID_RFC822_ADDR"},
- {ID_IPV6_ADDR, "ID_IPV6_ADDR"},
- {ID_DER_ASN1_DN, "ID_DER_ASN1_DN"},
- {ID_DER_ASN1_GN, "ID_DER_ASN1_GN"},
- {ID_KEY_ID, "ID_KEY_ID"},
- {ID_ANY, "ID_ANY"},
- {MAPPING_END, NULL}
-};
-
-
-/**
- * X.501 acronyms for well known object identifiers (OIDs)
- */
-static u_char oid_ND[] = {
- 0x02, 0x82, 0x06, 0x01,
- 0x0A, 0x07, 0x14
-};
-static u_char oid_UID[] = {
- 0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x01
-};
-static u_char oid_DC[] = {
- 0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x19
-};
-static u_char oid_CN[] = {
- 0x55, 0x04, 0x03
-};
-static u_char oid_S[] = {
- 0x55, 0x04, 0x04
-};
-static u_char oid_SN[] = {
- 0x55, 0x04, 0x05
-};
-static u_char oid_C[] = {
- 0x55, 0x04, 0x06
-};
-static u_char oid_L[] = {
- 0x55, 0x04, 0x07
-};
-static u_char oid_ST[] = {
- 0x55, 0x04, 0x08
-};
-static u_char oid_O[] = {
- 0x55, 0x04, 0x0A
-};
-static u_char oid_OU[] = {
- 0x55, 0x04, 0x0B
-};
-static u_char oid_T[] = {
- 0x55, 0x04, 0x0C
-};
-static u_char oid_D[] = {
- 0x55, 0x04, 0x0D
-};
-static u_char oid_N[] = {
- 0x55, 0x04, 0x29
-};
-static u_char oid_G[] = {
- 0x55, 0x04, 0x2A
-};
-static u_char oid_I[] = {
- 0x55, 0x04, 0x2B
-};
-static u_char oid_ID[] = {
- 0x55, 0x04, 0x2D
-};
-static u_char oid_EN[] = {
- 0x60, 0x86, 0x48, 0x01, 0x86,
- 0xF8, 0x42, 0x03, 0x01, 0x03
-};
-static u_char oid_E[] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x01
-};
-static u_char oid_UN[] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x02
-};
-static u_char oid_TCGID[] = {
- 0x2B, 0x06, 0x01, 0x04, 0x01, 0x89,
- 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B
-};
-
-/**
- * coding of X.501 distinguished name
- */
-typedef struct {
- const u_char *name;
- chunk_t oid;
- u_char type;
-} x501rdn_t;
-
-static const x501rdn_t x501rdns[] = {
- {"ND", {oid_ND, 7}, ASN1_PRINTABLESTRING},
- {"UID", {oid_UID, 10}, ASN1_PRINTABLESTRING},
- {"DC", {oid_DC, 10}, ASN1_PRINTABLESTRING},
- {"CN", {oid_CN, 3}, ASN1_PRINTABLESTRING},
- {"S", {oid_S, 3}, ASN1_PRINTABLESTRING},
- {"SN", {oid_SN, 3}, ASN1_PRINTABLESTRING},
- {"serialNumber", {oid_SN, 3}, ASN1_PRINTABLESTRING},
- {"C", {oid_C, 3}, ASN1_PRINTABLESTRING},
- {"L", {oid_L, 3}, ASN1_PRINTABLESTRING},
- {"ST", {oid_ST, 3}, ASN1_PRINTABLESTRING},
- {"O", {oid_O, 3}, ASN1_PRINTABLESTRING},
- {"OU", {oid_OU, 3}, ASN1_PRINTABLESTRING},
- {"T", {oid_T, 3}, ASN1_PRINTABLESTRING},
- {"D", {oid_D, 3}, ASN1_PRINTABLESTRING},
- {"N", {oid_N, 3}, ASN1_PRINTABLESTRING},
- {"G", {oid_G, 3}, ASN1_PRINTABLESTRING},
- {"I", {oid_I, 3}, ASN1_PRINTABLESTRING},
- {"ID", {oid_ID, 3}, ASN1_PRINTABLESTRING},
- {"EN", {oid_EN, 10}, ASN1_PRINTABLESTRING},
- {"employeeNumber", {oid_EN, 10}, ASN1_PRINTABLESTRING},
- {"E", {oid_E, 9}, ASN1_IA5STRING},
- {"Email", {oid_E, 9}, ASN1_IA5STRING},
- {"emailAddress", {oid_E, 9}, ASN1_IA5STRING},
- {"UN", {oid_UN, 9}, ASN1_IA5STRING},
- {"unstructuredName",{oid_UN, 9}, ASN1_IA5STRING},
- {"TCGID", {oid_TCGID, 12}, ASN1_PRINTABLESTRING}
-};
-#define X501_RDN_ROOF 26
-
-/**
- * Different kinds of generalNames
- */
-enum generalNames_t {
- GN_OTHER_NAME = 0,
- GN_RFC822_NAME = 1,
- GN_DNS_NAME = 2,
- GN_X400_ADDRESS = 3,
- GN_DIRECTORY_NAME = 4,
- GN_EDI_PARTY_NAME = 5,
- GN_URI = 6,
- GN_IP_ADDRESS = 7,
- GN_REGISTERED_ID = 8,
-};
-
-/**
- * ASN.1 definition of generalName
- */
-static const asn1Object_t generalNameObjects[] = {
- { 0, "otherName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 0 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 1 */
- { 0, "rfc822Name", ASN1_CONTEXT_S_1, ASN1_OPT|ASN1_BODY }, /* 2 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 3 */
- { 0, "dnsName", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 4 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
- { 0, "x400Address", ASN1_CONTEXT_S_3, ASN1_OPT|ASN1_BODY }, /* 6 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
- { 0, "directoryName", ASN1_CONTEXT_C_4, ASN1_OPT|ASN1_BODY }, /* 8 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
- { 0, "ediPartyName", ASN1_CONTEXT_C_5, ASN1_OPT|ASN1_BODY }, /* 10 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 11 */
- { 0, "URI", ASN1_CONTEXT_S_6, ASN1_OPT|ASN1_BODY }, /* 12 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 13 */
- { 0, "ipAddress", ASN1_CONTEXT_S_7, ASN1_OPT|ASN1_BODY }, /* 14 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 15 */
- { 0, "registeredID", ASN1_CONTEXT_S_8, ASN1_OPT|ASN1_BODY }, /* 16 */
- { 0, "end choice", ASN1_EOC, ASN1_END } /* 17 */
-};
-#define GN_OBJ_OTHER_NAME 0
-#define GN_OBJ_RFC822_NAME 2
-#define GN_OBJ_DNS_NAME 4
-#define GN_OBJ_X400_ADDRESS 6
-#define GN_OBJ_DIRECTORY_NAME 8
-#define GN_OBJ_EDI_PARTY_NAME 10
-#define GN_OBJ_URI 12
-#define GN_OBJ_IP_ADDRESS 14
-#define GN_OBJ_REGISTERED_ID 16
-#define GN_OBJ_ROOF 18
-
-/**
- * ASN.1 definition of otherName
- */
-static const asn1Object_t otherNameObjects[] = {
- {0, "type-id", ASN1_OID, ASN1_BODY }, /* 0 */
- {0, "value", ASN1_CONTEXT_C_0, ASN1_BODY } /* 1 */
-};
-#define ON_OBJ_ID_TYPE 0
-#define ON_OBJ_VALUE 1
-#define ON_OBJ_ROOF 2
-
-typedef struct private_identification_t private_identification_t;
-
-/**
- * Private data of an identification_t object.
- */
-struct private_identification_t {
- /**
- * Public interface.
- */
- identification_t public;
-
- /**
- * String representation of this ID.
- */
- char *string;
-
- /**
- * Encoded representation of this ID.
- */
- chunk_t encoded;
-
- /**
- * Type of this ID.
- */
- id_type_t type;
-};
-
-static private_identification_t *identification_create();
-
-
-/**
- * updates a chunk (!????)
- * TODO: We should reconsider this stuff, its not really clear
- */
-static void update_chunk(chunk_t *ch, int n)
-{
- n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
- ch->ptr += n; ch->len -= n;
-}
-
-/**
- * Prints a binary string in hexadecimal form
- */
-void hex_str(chunk_t bin, chunk_t *str)
-{
- u_int i;
- update_chunk(str, snprintf(str->ptr,str->len,"0x"));
- for (i=0; i < bin.len; i++)
- {
- update_chunk(str, snprintf(str->ptr,str->len,"%02X",*bin.ptr++));
- }
-}
-
-/**
- * Pointer is set to the first RDN in a DN
- */
-static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
-{
- *rdn = CHUNK_INITIALIZER;
- *attribute = CHUNK_INITIALIZER;
-
- /* a DN is a SEQUENCE OF RDNs */
- if (*dn.ptr != ASN1_SEQUENCE)
- {
- /* DN is not a SEQUENCE */
- return FAILED;
- }
-
- rdn->len = asn1_length(&dn);
-
- if (rdn->len == ASN1_INVALID_LENGTH)
- {
- /* Invalid RDN length */
- return FAILED;
- }
-
- rdn->ptr = dn.ptr;
-
- /* are there any RDNs ? */
- *next = rdn->len > 0;
-
- return SUCCESS;
-}
-
-/**
- * Fetches the next RDN in a DN
- */
-static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value, asn1_t *type, bool *next)
-{
- chunk_t body;
-
- /* initialize return values */
- *oid = CHUNK_INITIALIZER;
- *value = CHUNK_INITIALIZER;
-
- /* if all attributes have been parsed, get next rdn */
- if (attribute->len <= 0)
- {
- /* an RDN is a SET OF attributeTypeAndValue */
- if (*rdn->ptr != ASN1_SET)
- {
- /* RDN is not a SET */
- return FAILED;
- }
- attribute->len = asn1_length(rdn);
- if (attribute->len == ASN1_INVALID_LENGTH)
- {
- /* Invalid attribute length */
- return FAILED;
- }
- attribute->ptr = rdn->ptr;
- /* advance to start of next RDN */
- rdn->ptr += attribute->len;
- rdn->len -= attribute->len;
- }
-
- /* an attributeTypeAndValue is a SEQUENCE */
- if (*attribute->ptr != ASN1_SEQUENCE)
- {
- /* attributeTypeAndValue is not a SEQUENCE */
- return FAILED;
- }
-
- /* extract the attribute body */
- body.len = asn1_length(attribute);
-
- if (body.len == ASN1_INVALID_LENGTH)
- {
- /* Invalid attribute body length */
- return FAILED;
- }
-
- body.ptr = attribute->ptr;
-
- /* advance to start of next attribute */
- attribute->ptr += body.len;
- attribute->len -= body.len;
-
- /* attribute type is an OID */
- if (*body.ptr != ASN1_OID)
- {
- /* attributeType is not an OID */
- return FAILED;
- }
- /* extract OID */
- oid->len = asn1_length(&body);
-
- if (oid->len == ASN1_INVALID_LENGTH)
- {
- /* Invalid attribute OID length */
- return FAILED;
- }
- oid->ptr = body.ptr;
-
- /* advance to the attribute value */
- body.ptr += oid->len;
- body.len -= oid->len;
-
- /* extract string type */
- *type = *body.ptr;
-
- /* extract string value */
- value->len = asn1_length(&body);
-
- if (value->len == ASN1_INVALID_LENGTH)
- {
- /* Invalid attribute string length */
- return FAILED;
- }
- value->ptr = body.ptr;
-
- /* are there any RDNs left? */
- *next = rdn->len > 0 || attribute->len > 0;
- return SUCCESS;
-}
-
-/**
- * Parses an ASN.1 distinguished name int its OID/value pairs
- */
-static status_t dntoa(chunk_t dn, chunk_t *str)
-{
- chunk_t rdn, oid, attribute, value;
- asn1_t type;
- int oid_code;
- bool next;
- bool first = TRUE;
-
- status_t status = init_rdn(dn, &rdn, &attribute, &next);
-
- if (status != SUCCESS)
- {/* a parsing error has occured */
- return status;
- }
-
- while (next)
- {
- status = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
-
- if (status != SUCCESS)
- {/* a parsing error has occured */
- return status;
- }
-
- if (first)
- { /* first OID/value pair */
- first = FALSE;
- }
- else
- { /* separate OID/value pair by a comma */
- update_chunk(str, snprintf(str->ptr,str->len,", "));
- }
-
- /* print OID */
- oid_code = known_oid(oid);
- if (oid_code == OID_UNKNOWN)
- { /* OID not found in list */
- hex_str(oid, str);
- }
- else
- {
- update_chunk(str, snprintf(str->ptr,str->len,"%s", oid_names[oid_code].name));
- }
- /* print value */
- update_chunk(str, snprintf(str->ptr,str->len,"=%.*s", (int)value.len,value.ptr));
- }
- return SUCCESS;
-}
-
-/**
- * compare two distinguished names by
- * comparing the individual RDNs
- */
-static bool same_dn(chunk_t a, chunk_t b)
-{
- chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
- chunk_t oid_a, oid_b, value_a, value_b;
- asn1_t type_a, type_b;
- bool next_a, next_b;
-
- /* same lengths for the DNs */
- if (a.len != b.len)
- {
- return FALSE;
- }
- /* try a binary comparison first */
- if (memcmp(a.ptr, b.ptr, b.len) == 0)
- {
- return TRUE;
- }
-
- /* initialize DN parsing */
- if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS ||
- init_rdn(b, &rdn_b, &attribute_b, &next_b) != SUCCESS)
- {
- return FALSE;
- }
-
- /* fetch next RDN pair */
- while (next_a && next_b)
- {
- /* parse next RDNs and check for errors */
- if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != SUCCESS ||
- get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != SUCCESS)
- {
- return FALSE;
- }
- /* OIDs must agree */
- if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
- {
- return FALSE;
- }
- /* same lengths for values */
- if (value_a.len != value_b.len)
- {
- return FALSE;
- }
- /* printableStrings and email RDNs require uppercase comparison */
- if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
- (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
- {
- if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- else
- {
- if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- }
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- return FALSE;
-
- /* the two DNs are equal! */
- return TRUE;
-}
-
-
-/**
- * compare two distinguished names by comparing the individual RDNs.
- * A single'*' character designates a wildcard RDN in DN b.
- * TODO: Add support for different RDN order in DN !!
- */
-bool match_dn(chunk_t a, chunk_t b, int *wildcards)
-{
- chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
- chunk_t oid_a, oid_b, value_a, value_b;
- asn1_t type_a, type_b;
- bool next_a, next_b;
-
- /* initialize wildcard counter */
- *wildcards = 0;
-
- /* initialize DN parsing */
- if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS ||
- init_rdn(b, &rdn_b, &attribute_b, &next_b) != SUCCESS)
- {
- return FALSE;
- }
- /* fetch next RDN pair */
- while (next_a && next_b)
- {
- /* parse next RDNs and check for errors */
- if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != SUCCESS ||
- get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != SUCCESS)
- {
- return FALSE;
- }
- /* OIDs must agree */
- if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
- {
- return FALSE;
- }
- /* does rdn_b contain a wildcard? */
- if (value_b.len == 1 && *value_b.ptr == '*')
- {
- (*wildcards)++;
- continue;
- }
- /* same lengths for values */
- if (value_a.len != value_b.len)
- {
- return FALSE;
- }
- /* printableStrings and email RDNs require uppercase comparison */
- if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
- (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
- {
- if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- else
- {
- if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- }
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- {
- return FALSE;
- }
- /* the two DNs match! */
- return TRUE;
-}
-
-/**
- * get string representation of a general name
- * TODO: Add support for gn types
- */
-static char *gntoa(chunk_t blob)
-{
- asn1_ctx_t ctx;
- chunk_t object;
- int objectID = 0;
- u_int level;
- char buf[128];
-
- asn1_init(&ctx, blob, 0, FALSE);
-
- while (objectID < GN_OBJ_ROOF)
- {
- if (!extract_object(generalNameObjects, &objectID, &object, &level, &ctx))
- {
- return NULL;
- }
- switch (objectID)
- {
- case GN_OBJ_RFC822_NAME:
- case GN_OBJ_DNS_NAME:
- case GN_OBJ_URI:
- snprintf(buf, sizeof(buf), "%.*s", object.len, object.ptr);
- return strdup(buf);
- case GN_OBJ_IP_ADDRESS:
- if (object.len == 4 &&
- inet_ntop(AF_INET, object.ptr, buf, sizeof(buf)))
- {
- return strdup(buf);
- }
- return NULL;
- break;
- case GN_OBJ_OTHER_NAME:
- return strdup("(other name)");
- case GN_OBJ_X400_ADDRESS:
- return strdup("(X400 Address)");
- case GN_OBJ_EDI_PARTY_NAME:
- return strdup("(EDI party name)");
- case GN_OBJ_REGISTERED_ID:
- return strdup("(registered ID)");
- case GN_OBJ_DIRECTORY_NAME:
- return strdup("(directory name)");
- default:
- break;
- }
- objectID++;
- }
- return NULL;
-}
-
-/**
- * Converts an LDAP-style human-readable ASCII-encoded
- * ASN.1 distinguished name into binary DER-encoded format
- */
-static status_t atodn(char *src, chunk_t *dn)
-{
- /* finite state machine for atodn */
- typedef enum {
- SEARCH_OID = 0,
- READ_OID = 1,
- SEARCH_NAME = 2,
- READ_NAME = 3,
- UNKNOWN_OID = 4
- } state_t;
-
- char *wrap_mode;
- chunk_t oid = CHUNK_INITIALIZER;
- chunk_t name = CHUNK_INITIALIZER;
- chunk_t names[25]; /* max to 25 rdns */
- int name_count = 0;
- int whitespace = 0;
- int pos = 0;
- asn1_t rdn_type;
- state_t state = SEARCH_OID;
- status_t status = SUCCESS;
-
- do
- {
- switch (state)
- {
- case SEARCH_OID:
- if (*src != ' ' && *src != '/' && *src != ',')
- {
- oid.ptr = src;
- oid.len = 1;
- state = READ_OID;
- }
- break;
- case READ_OID:
- if (*src != ' ' && *src != '=')
- {
- oid.len++;
- }
- else
- {
- for (pos = 0; pos < X501_RDN_ROOF; pos++)
- {
- if (strlen(x501rdns[pos].name) == oid.len &&
- strncasecmp(x501rdns[pos].name, oid.ptr, oid.len) == 0)
- {
- break; /* found a valid OID */
- }
- }
- if (pos == X501_RDN_ROOF)
- {
- status = NOT_SUPPORTED;
- state = UNKNOWN_OID;
- break;
- }
- /* reset oid and change state */
- oid = CHUNK_INITIALIZER;
- state = SEARCH_NAME;
- }
- break;
- case SEARCH_NAME:
- if (*src != ' ' && *src != '=')
- {
- name.ptr = src;
- name.len = 1;
- whitespace = 0;
- state = READ_NAME;
- }
- break;
- case READ_NAME:
- if (*src != ',' && *src != '/' && *src != '\0')
- {
- name.len++;
- if (*src == ' ')
- {
- whitespace++;
- }
- else
- {
- whitespace = 0;
- }
- }
- else
- {
- name.len -= whitespace;
- rdn_type = (x501rdns[pos].type == ASN1_PRINTABLESTRING
- && !is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type;
-
- if (name_count < 25)
- {
- names[name_count++] =
- asn1_wrap(ASN1_SET, "m",
- asn1_wrap(ASN1_SEQUENCE, "mm",
- asn1_wrap(ASN1_OID, "c", x501rdns[pos].oid),
- asn1_wrap(rdn_type, "c", name)
- )
- );
- }
- else
- {
- status = OUT_OF_RES;
- }
- /* reset name and change state */
- name = CHUNK_INITIALIZER;
- state = SEARCH_OID;
- }
- break;
- case UNKNOWN_OID:
- break;
- }
- } while (*src++ != '\0');
-
-
- /* build the distinguished name sequence */
- wrap_mode = alloca(26);
- memset(wrap_mode, 0, 26);
- memset(wrap_mode, 'm', name_count);
- *dn = asn1_wrap(ASN1_SEQUENCE, wrap_mode,
- names[0], names[1], names[2], names[3], names[4],
- names[5], names[6], names[7], names[8], names[9],
- names[10], names[11], names[12], names[13], names[14],
- names[15], names[16], names[17], names[18], names[19],
- names[20], names[21], names[22], names[23], names[24]);
- if (status != SUCCESS)
- {
- free(dn->ptr);
- *dn = CHUNK_INITIALIZER;
- }
- return status;
-}
-
-/**
- * Implementation of identification_t.get_encoding.
- */
-static chunk_t get_encoding(private_identification_t *this)
-{
- return this->encoded;
-}
-
-/**
- * Implementation of identification_t.get_type.
- */
-static id_type_t get_type(private_identification_t *this)
-{
- return this->type;
-}
-
-/**
- * Implementation of identification_t.get_string.
- */
-static char *get_string(private_identification_t *this)
-{
- return this->string;
-}
-
-/**
- * Implementation of identification_t.contains_wildcards.
- */
-static bool contains_wildcards(private_identification_t *this)
-{
- if (this->type == ID_ANY ||
- memchr(this->encoded.ptr, '*', this->encoded.len) != NULL)
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Default implementation of identification_t.equals and identification_t.belongs_to.
- * compares encoded chunk for equality.
- */
-static bool equals_binary(private_identification_t *this,private_identification_t *other)
-{
- if (this->type == other->type)
- {
- if (this->encoded.len == other->encoded.len &&
- memcmp(this->encoded.ptr, other->encoded.ptr, this->encoded.len) == 0)
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * Special implementation of identification_t.equals for ID_DER_ASN1_DN
- */
-static bool equals_dn(private_identification_t *this, private_identification_t *other)
-{
- return same_dn(this->encoded, other->encoded);
-}
-
-/**
- * Special implementation of identification_t.belongs_to for ID_RFC822_ADDR/ID_FQDN.
- * checks for a wildcard in other-string, and compares it against this-string.
- */
-static bool belongs_to_wc_string(private_identification_t *this, private_identification_t *other)
-{
- char *this_str, *other_str, *pos;
-
- if (other->type == ID_ANY)
- {
- return TRUE;
- }
-
- if (this->type == other->type)
- {
- /* try a binary comparison first */
- if (equals_binary(this, other))
- {
- return TRUE;
- }
- }
- if (other->encoded.len > 0 &&
- *(other->encoded.ptr) == '*')
- {
- if (other->encoded.len == 1)
- {
- /* other contains just a wildcard, and therefore matches anything */
- return TRUE;
- }
- /* We strdup chunks, since they are NOT null-terminated */
- this_str = strndupa(this->encoded.ptr, this->encoded.len);
- other_str = strndupa(other->encoded.ptr + 1, other->encoded.len - 1);
- pos = strstr(this_str, other_str);
- if (pos != NULL)
- {
- /* ok, other is contained in this, but there may be more characters, so check it */
- if (strlen(pos) == strlen(other_str))
- {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-/**
- * Special implementation of identification_t.belongs_to for ID_ANY.
- * ANY matches only another ANY, but nothing other
- */
-static bool belongs_to_any(private_identification_t *this, private_identification_t *other)
-{
- if (other->type == ID_ANY)
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Special implementation of identification_t.belongs_to for ID_DER_ASN1_DN.
- * ANY matches any, even ANY, thats why its there...
- */
-static bool belongs_to_dn(private_identification_t *this, private_identification_t *other)
-{
- int wildcards;
-
- if (other->type == ID_ANY)
- {
- return TRUE;
- }
-
- if (this->type == other->type)
- {
- return match_dn(this->encoded, other->encoded, &wildcards);
- }
- return FALSE;
-}
-
-/**
- * Implementation of identification_t.clone.
- */
-static identification_t *clone(private_identification_t *this)
-{
- private_identification_t *clone = identification_create();
-
- clone->type = this->type;
- clone->encoded = chunk_clone(this->encoded);
- clone->string = malloc(strlen(this->string) + 1);
- strcpy(clone->string, this->string);
-
- return &clone->public;
-}
-
-/**
- * Implementation of identification_t.destroy.
- */
-static void destroy(private_identification_t *this)
-{
- free(this->string);
- free(this->encoded.ptr);
- free(this);
-}
-
-/**
- * Generic constructor used for the other constructors.
- */
-static private_identification_t *identification_create()
-{
- private_identification_t *this = malloc_thing(private_identification_t);
-
- this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
- this->public.get_type = (id_type_t (*) (identification_t*))get_type;
- this->public.get_string = (char* (*) (identification_t*))get_string;
- this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards;
- 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.belongs_to = (bool (*) (identification_t*,identification_t*))equals_binary;
-
- this->string = NULL;
- this->encoded = CHUNK_INITIALIZER;
-
- return this;
-}
-
-/*
- * Described in header.
- */
-identification_t *identification_create_from_string(char *string)
-{
- private_identification_t *this = identification_create();
-
- if (strchr(string, '=') != NULL)
- {
- /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
- * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
- * discard optional @ character in front of DN
- */
- if (atodn((*string == '@') ? string + 1 : string, &this->encoded) != SUCCESS)
- {
- free(this);
- return NULL;
- }
- this->string = strdup(string);
- this->type = ID_DER_ASN1_DN;
- this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_dn;
- return &this->public;
- }
- else if (strchr(string, '@') == NULL)
- {
- if (strcmp(string, "%any") == 0 ||
- strcmp(string, "0.0.0.0") == 0 ||
- strcmp(string, "*") == 0 ||
- strcmp(string, "::") == 0||
- strcmp(string, "0::0") == 0)
- {
- /* any ID will be accepted */
- this->type = ID_ANY;
- this->string = strdup("%any");
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_any;
- return &this->public;
- }
- else
- {
- /* TODO: Pluto resolve domainnames without '@' to IPv4/6 address. Is this really needed? */
-
- if (strchr(string, ':') == NULL)
- {
- /* try IPv4 */
- struct in_addr address;
- chunk_t chunk = {(void*)&address, sizeof(address)};
-
- if (inet_pton(AF_INET, string, &address) <= 0)
- {
- free(this);
- return NULL;
- }
- this->encoded = chunk_clone(chunk);
- this->string = strdup(string);
- this->type = ID_IPV4_ADDR;
- return &(this->public);
- }
- else
- {
- /* try IPv6 */
- struct in6_addr address;
- chunk_t chunk = {(void*)&address, sizeof(address)};
-
- if (inet_pton(AF_INET6, string, &address) <= 0)
- {
- free(this);
- return NULL;
- }
- this->encoded = chunk_clone(chunk);
- this->string = strdup(string);
- this->type = ID_IPV6_ADDR;
- return &(this->public);
- }
- }
- }
- else
- {
- if (*string == '@')
- {
- if (*(string + 1) == '#')
- {
- /* TODO: Pluto handles '#' as hex encoded ASN1/KEY ID. Do we need this, too? */
- free(this);
- return NULL;
- }
- else
- {
- this->type = ID_FQDN;
- this->string = strdup(string + 1); /* discard @ */
- this->encoded.ptr = strdup(string + 1);
- this->encoded.len = strlen(string + 1);
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string;
- return &(this->public);
- }
- }
- else
- {
- this->type = ID_RFC822_ADDR;
- this->string = strdup(string);
- this->encoded.ptr = strdup(string);
- this->encoded.len = strlen(string);
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string;
- return &(this->public);
- }
- }
-}
-
-/*
- * Described in header.
- */
-identification_t *identification_create_from_encoding(id_type_t type, chunk_t encoded)
-{
- private_identification_t *this = identification_create();
- char buf[256];
- chunk_t buf_chunk = chunk_from_buf(buf);
- char *pos;
-
- this->type = type;
- switch (type)
- {
- case ID_ANY:
- this->string = strdup("%any");
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_any;
- break;
- case ID_IPV4_ADDR:
- if (encoded.len < sizeof(struct in_addr) ||
- inet_ntop(AF_INET, encoded.ptr, buf, sizeof(buf)) == NULL)
- {
- this->string = strdup("(invalid ID_IPV4_ADDR)");
- }
- else
- {
- this->string = strdup(buf);
- }
- break;
- case ID_IPV6_ADDR:
- if (encoded.len < sizeof(struct in6_addr) ||
- inet_ntop(AF_INET6, encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL)
- {
- this->string = strdup("(invalid ID_IPV6_ADDR)");
- }
- else
- {
- this->string = strdup(buf);
- }
- break;
- case ID_FQDN:
- snprintf(buf, sizeof(buf), "@%.*s", encoded.len, encoded.ptr);
- this->string = strdup(buf);
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string;
- break;
- case ID_RFC822_ADDR:
- snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
- this->string = strdup(buf);
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string;
- break;
- case ID_DER_ASN1_DN:
- snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
- /* TODO: whats returned on failure */
- dntoa(encoded, &buf_chunk);
- this->string = strdup(buf);
- this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
- this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_dn;
- break;
- case ID_DER_ASN1_GN:
- this->string = gntoa(encoded);
- break;
- case ID_KEY_ID:
- this->string = strdup("(unparsed KEY_ID)");
- break;
- default:
- snprintf(buf, sizeof(buf), "(invalid ID type: %d)", type);
- this->string = strdup(buf);
- break;
- }
-
- /* apply encoded chunk */
- if (type != ID_ANY)
- {
- this->encoded = chunk_clone(encoded);
- }
-
- /* remove unprintable chars in string */
- for (pos = this->string; *pos != '\0'; pos++)
- {
- if (!isprint(*pos))
- {
- *pos = '?';
- }
- }
- return &(this->public);
-}