2 * Copyright (C) 2009 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
26 #include "identification.h"
29 #include <asn1/asn1.h>
31 ENUM_BEGIN(id_match_names
, ID_MATCH_NONE
, ID_MATCH_MAX_WILDCARDS
,
34 "MATCH_MAX_WILDCARDS");
35 ENUM_NEXT(id_match_names
, ID_MATCH_PERFECT
, ID_MATCH_PERFECT
, ID_MATCH_MAX_WILDCARDS
,
37 ENUM_END(id_match_names
, ID_MATCH_PERFECT
);
39 ENUM_BEGIN(id_type_names
, ID_ANY
, ID_KEY_ID
,
44 "ID_IPV4_ADDR_SUBNET",
46 "ID_IPV6_ADDR_SUBNET",
52 ENUM_NEXT(id_type_names
, ID_DER_ASN1_GN_URI
, ID_CERT_DER_SHA1
, ID_KEY_ID
,
54 "ID_PUBKEY_INFO_SHA1",
57 ENUM_END(id_type_names
, ID_CERT_DER_SHA1
);
60 * coding of X.501 distinguished name
68 static const x501rdn_t x501rdns
[] = {
69 {"ND", OID_NAME_DISTINGUISHER
, ASN1_PRINTABLESTRING
},
70 {"UID", OID_PILOT_USERID
, ASN1_PRINTABLESTRING
},
71 {"DC", OID_PILOT_DOMAIN_COMPONENT
, ASN1_PRINTABLESTRING
},
72 {"CN", OID_COMMON_NAME
, ASN1_PRINTABLESTRING
},
73 {"S", OID_SURNAME
, ASN1_PRINTABLESTRING
},
74 {"SN", OID_SERIAL_NUMBER
, ASN1_PRINTABLESTRING
},
75 {"serialNumber", OID_SERIAL_NUMBER
, ASN1_PRINTABLESTRING
},
76 {"C", OID_COUNTRY
, ASN1_PRINTABLESTRING
},
77 {"L", OID_LOCALITY
, ASN1_PRINTABLESTRING
},
78 {"ST", OID_STATE_OR_PROVINCE
, ASN1_PRINTABLESTRING
},
79 {"O", OID_ORGANIZATION
, ASN1_PRINTABLESTRING
},
80 {"OU", OID_ORGANIZATION_UNIT
, ASN1_PRINTABLESTRING
},
81 {"T", OID_TITLE
, ASN1_PRINTABLESTRING
},
82 {"D", OID_DESCRIPTION
, ASN1_PRINTABLESTRING
},
83 {"N", OID_NAME
, ASN1_PRINTABLESTRING
},
84 {"G", OID_GIVEN_NAME
, ASN1_PRINTABLESTRING
},
85 {"I", OID_INITIALS
, ASN1_PRINTABLESTRING
},
86 {"ID", OID_UNIQUE_IDENTIFIER
, ASN1_PRINTABLESTRING
},
87 {"EN", OID_EMPLOYEE_NUMBER
, ASN1_PRINTABLESTRING
},
88 {"employeeNumber", OID_EMPLOYEE_NUMBER
, ASN1_PRINTABLESTRING
},
89 {"E", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
90 {"Email", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
91 {"emailAddress", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
92 {"UN", OID_UNSTRUCTURED_NAME
, ASN1_IA5STRING
},
93 {"unstructuredName",OID_UNSTRUCTURED_NAME
, ASN1_IA5STRING
},
94 {"TCGID", OID_TCGID
, ASN1_PRINTABLESTRING
}
98 * maximum number of RDNs in atodn()
103 typedef struct private_identification_t private_identification_t
;
106 * Private data of an identification_t object.
108 struct private_identification_t
{
112 identification_t
public;
115 * Encoded representation of this ID.
126 * Enumerator over RDNs
129 /* implements enumerator interface */
131 /* RDNs left to parse */
136 * Implementation of rdn_enumerator_t.enumerate
138 static bool rdn_enumerate(rdn_enumerator_t
*this, chunk_t
*oid
,
139 u_char
*type
, chunk_t
*data
)
143 /* a RDN is a SET of attribute-values, each is a SEQUENCE ... */
144 if (asn1_unwrap(&this->left
, &rdn
) == ASN1_SET
&&
145 asn1_unwrap(&rdn
, &rdn
) == ASN1_SEQUENCE
)
148 if (asn1_unwrap(&rdn
, oid
) == ASN1_OID
)
150 /* and a specific string type */
151 *type
= asn1_unwrap(&rdn
, data
);
152 if (*type
!= ASN1_INVALID
)
162 * Create an enumerator over all RDNs (oid, string type, data) of a DN
164 static enumerator_t
* create_rdn_enumerator(chunk_t dn
)
166 rdn_enumerator_t
*e
= malloc_thing(rdn_enumerator_t
);
168 e
->public.enumerate
= (void*)rdn_enumerate
;
169 e
->public.destroy
= (void*)free
;
171 /* a DN is a sequence of RDNs */
172 if (asn1_unwrap(&dn
, &e
->left
) == ASN1_SEQUENCE
)
177 return enumerator_create_empty();
181 * Part enumerator over RDNs
184 /* implements enumerator interface */
186 /* inner RDN enumerator */
188 } rdn_part_enumerator_t
;
191 * Implementation of rdn_part_enumerator_t.enumerate().
193 static bool rdn_part_enumerate(rdn_part_enumerator_t
*this,
194 id_part_t
*type
, chunk_t
*data
)
196 int i
, known_oid
, strtype
;
197 chunk_t oid
, inner_data
;
198 static const struct {
202 {OID_COMMON_NAME
, ID_PART_RDN_CN
},
203 {OID_SURNAME
, ID_PART_RDN_S
},
204 {OID_SERIAL_NUMBER
, ID_PART_RDN_SN
},
205 {OID_COUNTRY
, ID_PART_RDN_C
},
206 {OID_LOCALITY
, ID_PART_RDN_L
},
207 {OID_STATE_OR_PROVINCE
, ID_PART_RDN_ST
},
208 {OID_ORGANIZATION
, ID_PART_RDN_O
},
209 {OID_ORGANIZATION_UNIT
, ID_PART_RDN_OU
},
210 {OID_TITLE
, ID_PART_RDN_T
},
211 {OID_DESCRIPTION
, ID_PART_RDN_D
},
212 {OID_NAME
, ID_PART_RDN_N
},
213 {OID_GIVEN_NAME
, ID_PART_RDN_G
},
214 {OID_INITIALS
, ID_PART_RDN_I
},
215 {OID_UNIQUE_IDENTIFIER
, ID_PART_RDN_ID
},
216 {OID_EMAIL_ADDRESS
, ID_PART_RDN_E
},
217 {OID_EMPLOYEE_NUMBER
, ID_PART_RDN_EN
},
220 while (this->inner
->enumerate(this->inner
, &oid
, &strtype
, &inner_data
))
222 known_oid
= asn1_known_oid(oid
);
223 for (i
= 0; i
< countof(oid2part
); i
++)
225 if (oid2part
[i
].oid
== known_oid
)
227 *type
= oid2part
[i
].type
;
237 * Implementation of rdn_part_enumerator_t.destroy().
239 static void rdn_part_enumerator_destroy(rdn_part_enumerator_t
*this)
241 this->inner
->destroy(this->inner
);
246 * Implementation of identification_t.create_part_enumerator
248 static enumerator_t
* create_part_enumerator(private_identification_t
*this)
254 rdn_part_enumerator_t
*e
= malloc_thing(rdn_part_enumerator_t
);
256 e
->inner
= create_rdn_enumerator(this->encoded
);
257 e
->public.enumerate
= (void*)rdn_part_enumerate
;
258 e
->public.destroy
= (void*)rdn_part_enumerator_destroy
;
267 return enumerator_create_empty();
272 * updates a chunk (!????)
273 * TODO: We should reconsider this stuff, its not really clear
275 static void update_chunk(chunk_t
*ch
, int n
)
277 n
= (n
> -1 && n
< (int)ch
->len
)? n
: (int)ch
->len
-1;
278 ch
->ptr
+= n
; ch
->len
-= n
;
282 * Remove any malicious characters from a chunk. We are very restrictive, but
283 * whe use these strings only to present it to the user.
285 static bool sanitize_chunk(chunk_t chunk
, chunk_t
*clone
)
288 bool all_printable
= TRUE
;
290 *clone
= chunk_clone(chunk
);
292 for (pos
= clone
->ptr
; pos
< (char*)(clone
->ptr
+ clone
->len
); pos
++)
297 all_printable
= FALSE
;
300 return all_printable
;
304 * Pointer is set to the first RDN in a DN
306 static bool init_rdn(chunk_t dn
, chunk_t
*rdn
, chunk_t
*attribute
, bool *next
)
309 *attribute
= chunk_empty
;
311 /* a DN is a SEQUENCE OF RDNs */
312 if (*dn
.ptr
!= ASN1_SEQUENCE
)
314 /* DN is not a SEQUENCE */
318 rdn
->len
= asn1_length(&dn
);
320 if (rdn
->len
== ASN1_INVALID_LENGTH
)
322 /* Invalid RDN length */
328 /* are there any RDNs ? */
329 *next
= rdn
->len
> 0;
335 * Fetches the next RDN in a DN
337 static bool get_next_rdn(chunk_t
*rdn
, chunk_t
* attribute
, chunk_t
*oid
,
338 chunk_t
*value
, asn1_t
*type
, bool *next
)
342 /* initialize return values */
344 *value
= chunk_empty
;
346 /* if all attributes have been parsed, get next rdn */
347 if (attribute
->len
<= 0)
349 /* an RDN is a SET OF attributeTypeAndValue */
350 if (*rdn
->ptr
!= ASN1_SET
)
352 /* RDN is not a SET */
355 attribute
->len
= asn1_length(rdn
);
356 if (attribute
->len
== ASN1_INVALID_LENGTH
)
358 /* Invalid attribute length */
361 attribute
->ptr
= rdn
->ptr
;
362 /* advance to start of next RDN */
363 rdn
->ptr
+= attribute
->len
;
364 rdn
->len
-= attribute
->len
;
367 /* an attributeTypeAndValue is a SEQUENCE */
368 if (*attribute
->ptr
!= ASN1_SEQUENCE
)
370 /* attributeTypeAndValue is not a SEQUENCE */
374 /* extract the attribute body */
375 body
.len
= asn1_length(attribute
);
377 if (body
.len
== ASN1_INVALID_LENGTH
)
379 /* Invalid attribute body length */
383 body
.ptr
= attribute
->ptr
;
385 /* advance to start of next attribute */
386 attribute
->ptr
+= body
.len
;
387 attribute
->len
-= body
.len
;
389 /* attribute type is an OID */
390 if (*body
.ptr
!= ASN1_OID
)
392 /* attributeType is not an OID */
396 oid
->len
= asn1_length(&body
);
398 if (oid
->len
== ASN1_INVALID_LENGTH
)
400 /* Invalid attribute OID length */
405 /* advance to the attribute value */
406 body
.ptr
+= oid
->len
;
407 body
.len
-= oid
->len
;
409 /* extract string type */
412 /* extract string value */
413 value
->len
= asn1_length(&body
);
415 if (value
->len
== ASN1_INVALID_LENGTH
)
417 /* Invalid attribute string length */
420 value
->ptr
= body
.ptr
;
422 /* are there any RDNs left? */
423 *next
= rdn
->len
> 0 || attribute
->len
> 0;
428 * Parses an ASN.1 distinguished name int its OID/value pairs
430 static bool dntoa(chunk_t dn
, chunk_t
*str
)
432 chunk_t rdn
, oid
, attribute
, value
, proper
;
438 if (!init_rdn(dn
, &rdn
, &attribute
, &next
))
445 if (!get_next_rdn(&rdn
, &attribute
, &oid
, &value
, &type
, &next
))
451 { /* first OID/value pair */
455 { /* separate OID/value pair by a comma */
456 update_chunk(str
, snprintf(str
->ptr
,str
->len
,", "));
460 oid_code
= asn1_known_oid(oid
);
461 if (oid_code
== OID_UNKNOWN
)
463 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"0x#B", &oid
));
467 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"%s", oid_names
[oid_code
].name
));
470 sanitize_chunk(value
, &proper
);
471 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"=%.*s", (int)proper
.len
, proper
.ptr
));
478 * Converts an LDAP-style human-readable ASCII-encoded
479 * ASN.1 distinguished name into binary DER-encoded format
481 static status_t
atodn(char *src
, chunk_t
*dn
)
483 /* finite state machine for atodn */
492 chunk_t oid
= chunk_empty
;
493 chunk_t name
= chunk_empty
;
494 chunk_t rdns
[RDN_MAX
];
500 state_t state
= SEARCH_OID
;
501 status_t status
= SUCCESS
;
508 if (*src
!= ' ' && *src
!= '/' && *src
!= ',')
516 if (*src
!= ' ' && *src
!= '=')
524 for (i
= 0; i
< countof(x501rdns
); i
++)
526 if (strlen(x501rdns
[i
].name
) == oid
.len
&&
527 strncasecmp(x501rdns
[i
].name
, oid
.ptr
, oid
.len
) == 0)
535 status
= NOT_SUPPORTED
;
539 /* reset oid and change state */
545 if (*src
!= ' ' && *src
!= '=')
554 if (*src
!= ',' && *src
!= '/' && *src
!= '\0')
564 name
.len
-= whitespace
;
565 rdn_type
= (x501rdns
[i
].type
== ASN1_PRINTABLESTRING
566 && !asn1_is_printablestring(name
))
567 ? ASN1_T61STRING
: x501rdns
[i
].type
;
569 if (rdn_count
< RDN_MAX
)
573 rdn_oid
= asn1_build_known_oid(x501rdns
[i
].oid
);
577 asn1_wrap(ASN1_SET
, "m",
578 asn1_wrap(ASN1_SEQUENCE
, "mm",
580 asn1_wrap(rdn_type
, "c", name
)
583 dn_len
+= rdns
[rdn_count
++].len
;
587 status
= INVALID_ARG
;
594 /* reset name and change state */
602 } while (*src
++ != '\0');
604 /* build the distinguished name sequence */
607 u_char
*pos
= asn1_build_object(dn
, ASN1_SEQUENCE
, dn_len
);
609 for (i
= 0; i
< rdn_count
; i
++)
611 memcpy(pos
, rdns
[i
].ptr
, rdns
[i
].len
);
617 if (status
!= SUCCESS
)
626 * Implementation of identification_t.get_encoding.
628 static chunk_t
get_encoding(private_identification_t
*this)
630 return this->encoded
;
634 * Implementation of identification_t.get_type.
636 static id_type_t
get_type(private_identification_t
*this)
642 * Implementation of identification_t.contains_wildcards fro ID_DER_ASN1_DN.
644 static bool contains_wildcards_dn(private_identification_t
*this)
646 enumerator_t
*enumerator
;
647 bool contains
= FALSE
;
651 enumerator
= create_part_enumerator(this);
652 while (enumerator
->enumerate(enumerator
, &type
, &data
))
654 if (data
.len
== 1 && data
.ptr
[0] == '*')
660 enumerator
->destroy(enumerator
);
665 * Implementation of identification_t.contains_wildcards.
667 static bool contains_wildcards(private_identification_t
*this)
675 return memchr(this->encoded
.ptr
, '*', this->encoded
.len
) != NULL
;
677 return contains_wildcards_dn(this);
684 * Default implementation of identification_t.equals.
685 * compares encoded chunk for equality.
687 static bool equals_binary(private_identification_t
*this, private_identification_t
*other
)
689 if (this->type
== other
->type
)
691 if (this->type
== ID_ANY
)
695 return chunk_equals(this->encoded
, other
->encoded
);
701 * Compare to DNs, for equality if wc == NULL, for match otherwise
703 static bool compare_dn(chunk_t t_dn
, chunk_t o_dn
, int *wc
)
706 chunk_t t_oid
, o_oid
, t_data
, o_data
;
707 u_char t_type
, o_type
;
708 bool t_next
, o_next
, finished
= FALSE
;
716 if (t_dn
.len
!= o_dn
.len
)
721 /* try a binary compare */
722 if (memeq(t_dn
.ptr
, o_dn
.ptr
, t_dn
.len
))
727 t
= create_rdn_enumerator(t_dn
);
728 o
= create_rdn_enumerator(o_dn
);
731 t_next
= t
->enumerate(t
, &t_oid
, &t_type
, &t_data
);
732 o_next
= o
->enumerate(o
, &o_oid
, &o_type
, &o_data
);
734 if (!o_next
&& !t_next
)
739 if (o_next
!= t_next
)
743 if (!chunk_equals(t_oid
, o_oid
))
747 if (wc
&& o_data
.len
== 1 && o_data
.ptr
[0] == '*')
753 if (t_data
.len
!= o_data
.len
)
757 if (t_type
== o_type
&&
758 (t_type
== ASN1_PRINTABLESTRING
||
759 (t_type
== ASN1_IA5STRING
&&
760 (asn1_known_oid(t_oid
) == OID_PKCS9_EMAIL
||
761 asn1_known_oid(t_oid
) == OID_EMAIL_ADDRESS
))))
762 { /* ignore case for printableStrings and email RDNs */
763 if (strncasecmp(t_data
.ptr
, o_data
.ptr
, t_data
.len
) != 0)
769 { /* respect case and length for everything else */
770 if (!memeq(t_data
.ptr
, o_data
.ptr
, t_data
.len
))
776 /* the enumerator returns FALSE on parse error, we are finished
777 * if we have reached the end of the DN only */
778 if ((t_data
.ptr
+ t_data
.len
== t_dn
.ptr
+ t_dn
.len
) &&
779 (o_data
.ptr
+ o_data
.len
== o_dn
.ptr
+ o_dn
.len
))
790 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
792 static bool equals_dn(private_identification_t
*this,
793 private_identification_t
*other
)
795 return compare_dn(this->encoded
, other
->encoded
, NULL
);
799 * Special implementation of identification_t.equals for RFC822 and FQDN.
801 static bool equals_strcasecmp(private_identification_t
*this,
802 private_identification_t
*other
)
804 /* we do some extra sanity checks to check for invalid IDs with a
805 * terminating null in it. */
806 if (this->encoded
.len
== other
->encoded
.len
&&
807 memchr(this->encoded
.ptr
, 0, this->encoded
.len
) == NULL
&&
808 memchr(other
->encoded
.ptr
, 0, other
->encoded
.len
) == NULL
&&
809 strncasecmp(this->encoded
.ptr
, other
->encoded
.ptr
, this->encoded
.len
) == 0)
817 * Default implementation of identification_t.matches.
819 static id_match_t
matches_binary(private_identification_t
*this,
820 private_identification_t
*other
)
822 if (other
->type
== ID_ANY
)
826 if (this->type
== other
->type
&&
827 chunk_equals(this->encoded
, other
->encoded
))
829 return ID_MATCH_PERFECT
;
831 return ID_MATCH_NONE
;
835 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
836 * Checks for a wildcard in other-string, and compares it against this-string.
838 static id_match_t
matches_string(private_identification_t
*this,
839 private_identification_t
*other
)
841 u_int len
= other
->encoded
.len
;
843 if (other
->type
== ID_ANY
)
847 if (this->type
!= other
->type
)
849 return ID_MATCH_NONE
;
851 /* try a equals check first */
852 if (equals_strcasecmp(this, other
))
854 return ID_MATCH_PERFECT
;
856 if (len
== 0 || this->encoded
.len
< len
)
858 return ID_MATCH_NONE
;
861 /* check for single wildcard at the head of the string */
862 if (*other
->encoded
.ptr
== '*')
864 /* single asterisk matches any string */
866 { /* not better than ID_ANY */
869 if (strncasecmp(this->encoded
.ptr
+ this->encoded
.len
- len
,
870 other
->encoded
.ptr
+ 1, len
) == 0)
872 return ID_MATCH_ONE_WILDCARD
;
875 return ID_MATCH_NONE
;
879 * Special implementation of identification_t.matches for ID_ANY.
880 * ANY matches only another ANY, but nothing other
882 static id_match_t
matches_any(private_identification_t
*this,
883 private_identification_t
*other
)
885 if (other
->type
== ID_ANY
)
889 return ID_MATCH_NONE
;
893 * Special implementation of identification_t.matches for ID_DER_ASN1_DN
895 static id_match_t
matches_dn(private_identification_t
*this,
896 private_identification_t
*other
)
900 if (other
->type
== ID_ANY
)
905 if (this->type
== other
->type
)
907 if (compare_dn(this->encoded
, other
->encoded
, &wc
))
909 wc
= min(wc
, ID_MATCH_ONE_WILDCARD
- ID_MATCH_MAX_WILDCARDS
);
910 return ID_MATCH_PERFECT
- wc
;
913 return ID_MATCH_NONE
;
917 * Described in header.
919 int identification_printf_hook(char *dst
, size_t len
, printf_hook_spec_t
*spec
,
920 const void *const *args
)
922 private_identification_t
*this = *((private_identification_t
**)(args
[0]));
924 chunk_t proper
, buf_chunk
= chunk_from_buf(buf
);
928 return print_in_hook(dst
, len
, "%*s", spec
->width
, "(null)");
934 snprintf(buf
, sizeof(buf
), "%%any");
937 if (this->encoded
.len
< sizeof(struct in_addr
) ||
938 inet_ntop(AF_INET
, this->encoded
.ptr
, buf
, sizeof(buf
)) == NULL
)
940 snprintf(buf
, sizeof(buf
), "(invalid ID_IPV4_ADDR)");
944 if (this->encoded
.len
< sizeof(struct in6_addr
) ||
945 inet_ntop(AF_INET6
, this->encoded
.ptr
, buf
, INET6_ADDRSTRLEN
) == NULL
)
947 snprintf(buf
, sizeof(buf
), "(invalid ID_IPV6_ADDR)");
952 case ID_DER_ASN1_GN_URI
:
953 case ID_IETF_ATTR_STRING
:
954 sanitize_chunk(this->encoded
, &proper
);
955 snprintf(buf
, sizeof(buf
), "%.*s", proper
.len
, proper
.ptr
);
959 if (!dntoa(this->encoded
, &buf_chunk
))
961 snprintf(buf
, sizeof(buf
), "(invalid ID_DER_ASN1_DN)");
965 snprintf(buf
, sizeof(buf
), "(ASN.1 general Name");
968 if (sanitize_chunk(this->encoded
, &proper
))
969 { /* fully printable, use ascii version */
970 snprintf(buf
, sizeof(buf
), "%.*s", proper
.len
, proper
.ptr
);
973 { /* not printable, hex dump */
974 snprintf(buf
, sizeof(buf
), "%#B", &this->encoded
);
978 case ID_PUBKEY_INFO_SHA1
:
980 case ID_CERT_DER_SHA1
:
981 snprintf(buf
, sizeof(buf
), "%#B", &this->encoded
);
984 snprintf(buf
, sizeof(buf
), "(unknown ID type: %d)", this->type
);
989 return print_in_hook(dst
, len
, "%-*s", spec
->width
, buf
);
991 return print_in_hook(dst
, len
, "%*s", spec
->width
, buf
);
994 * Implementation of identification_t.clone.
996 static identification_t
*clone_(private_identification_t
*this)
998 private_identification_t
*clone
= malloc_thing(private_identification_t
);
1000 memcpy(clone
, this, sizeof(private_identification_t
));
1001 if (this->encoded
.len
)
1003 clone
->encoded
= chunk_clone(this->encoded
);
1005 return &clone
->public;
1009 * Implementation of identification_t.destroy.
1011 static void destroy(private_identification_t
*this)
1013 chunk_free(&this->encoded
);
1018 * Generic constructor used for the other constructors.
1020 static private_identification_t
*identification_create(void)
1022 private_identification_t
*this = malloc_thing(private_identification_t
);
1024 this->public.get_encoding
= (chunk_t (*) (identification_t
*))get_encoding
;
1025 this->public.get_type
= (id_type_t (*) (identification_t
*))get_type
;
1026 this->public.contains_wildcards
= (bool (*) (identification_t
*this))contains_wildcards
;
1027 this->public.create_part_enumerator
= (enumerator_t
*(*)(identification_t
*))create_part_enumerator
;
1028 this->public.clone
= (identification_t
* (*) (identification_t
*))clone_
;
1029 this->public.destroy
= (void (*) (identification_t
*))destroy
;
1030 /* we use these as defaults, the may be overloaded for special ID types */
1031 this->public.equals
= (bool (*) (identification_t
*,identification_t
*))equals_binary
;
1032 this->public.matches
= (id_match_t (*) (identification_t
*,identification_t
*))matches_binary
;
1034 this->encoded
= chunk_empty
;
1040 * Described in header.
1042 identification_t
*identification_create_from_string(char *string
)
1044 private_identification_t
*this = identification_create();
1050 if (strchr(string
, '=') != NULL
)
1052 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1053 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1055 if (atodn(string
, &this->encoded
) != SUCCESS
)
1057 this->type
= ID_KEY_ID
;
1058 this->encoded
= chunk_clone(chunk_create(string
, strlen(string
)));
1059 return &this->public;
1061 this->type
= ID_DER_ASN1_DN
;
1062 this->public.equals
= (bool (*) (identification_t
*,identification_t
*))equals_dn
;
1063 this->public.matches
= (id_match_t (*) (identification_t
*,identification_t
*))matches_dn
;
1064 return &this->public;
1066 else if (strchr(string
, '@') == NULL
)
1068 if (streq(string
, "%any")
1069 || streq(string
, "%any6")
1070 || streq(string
, "0.0.0.0")
1071 || streq(string
, "*")
1072 || streq(string
, "::")
1073 || streq(string
, "0::0"))
1075 /* any ID will be accepted */
1076 this->type
= ID_ANY
;
1077 this->public.matches
= (id_match_t (*)
1078 (identification_t
*,identification_t
*))matches_any
;
1079 return &this->public;
1083 if (strchr(string
, ':') == NULL
)
1086 struct in_addr address
;
1087 chunk_t chunk
= {(void*)&address
, sizeof(address
)};
1089 if (inet_pton(AF_INET
, string
, &address
) <= 0)
1091 /* not IPv4, mostly FQDN */
1092 this->type
= ID_FQDN
;
1093 this->encoded
.ptr
= strdup(string
);
1094 this->encoded
.len
= strlen(string
);
1095 this->public.matches
= (id_match_t (*)
1096 (identification_t
*,identification_t
*))matches_string
;
1097 this->public.equals
= (bool (*)
1098 (identification_t
*,identification_t
*))equals_strcasecmp
;
1099 return &this->public;
1101 this->encoded
= chunk_clone(chunk
);
1102 this->type
= ID_IPV4_ADDR
;
1103 return &this->public;
1108 struct in6_addr address
;
1109 chunk_t chunk
= {(void*)&address
, sizeof(address
)};
1111 if (inet_pton(AF_INET6
, string
, &address
) <= 0)
1113 this->type
= ID_KEY_ID
;
1114 this->encoded
= chunk_clone(chunk_create(string
,
1116 return &this->public;
1118 this->encoded
= chunk_clone(chunk
);
1119 this->type
= ID_IPV6_ADDR
;
1120 return &this->public;
1128 if (*(string
+ 1) == '#')
1131 this->type
= ID_KEY_ID
;
1132 this->encoded
= chunk_from_hex(
1133 chunk_create(string
, strlen(string
)), NULL
);
1134 return &this->public;
1138 this->type
= ID_FQDN
;
1139 this->encoded
.ptr
= strdup(string
+ 1);
1140 this->encoded
.len
= strlen(string
+ 1);
1141 this->public.matches
= (id_match_t (*)
1142 (identification_t
*,identification_t
*))matches_string
;
1143 this->public.equals
= (bool (*)
1144 (identification_t
*,identification_t
*))equals_strcasecmp
;
1145 return &this->public;
1150 this->type
= ID_RFC822_ADDR
;
1151 this->encoded
.ptr
= strdup(string
);
1152 this->encoded
.len
= strlen(string
);
1153 this->public.matches
= (id_match_t (*)
1154 (identification_t
*,identification_t
*))matches_string
;
1155 this->public.equals
= (bool (*)
1156 (identification_t
*,identification_t
*))equals_strcasecmp
;
1157 return &this->public;
1163 * Described in header.
1165 identification_t
*identification_create_from_encoding(id_type_t type
, chunk_t encoded
)
1167 private_identification_t
*this = identification_create();
1173 this->public.matches
= (id_match_t (*)
1174 (identification_t
*,identification_t
*))matches_any
;
1177 case ID_RFC822_ADDR
:
1178 this->public.matches
= (id_match_t (*)
1179 (identification_t
*,identification_t
*))matches_string
;
1180 this->public.equals
= (bool (*)
1181 (identification_t
*,identification_t
*))equals_strcasecmp
;
1183 case ID_DER_ASN1_DN
:
1184 this->public.equals
= (bool (*)
1185 (identification_t
*,identification_t
*))equals_dn
;
1186 this->public.matches
= (id_match_t (*)
1187 (identification_t
*,identification_t
*))matches_dn
;
1191 case ID_DER_ASN1_GN
:
1193 case ID_DER_ASN1_GN_URI
:
1194 case ID_PUBKEY_INFO_SHA1
:
1195 case ID_PUBKEY_SHA1
:
1196 case ID_CERT_DER_SHA1
:
1197 case ID_IETF_ATTR_STRING
:
1202 /* apply encoded chunk */
1205 this->encoded
= chunk_clone(encoded
);
1207 return &(this->public);