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>
25 #include "identification.h"
28 #include <asn1/asn1.h>
30 ENUM_BEGIN(id_match_names
, ID_MATCH_NONE
, ID_MATCH_MAX_WILDCARDS
,
33 "MATCH_MAX_WILDCARDS");
34 ENUM_NEXT(id_match_names
, ID_MATCH_PERFECT
, ID_MATCH_PERFECT
, ID_MATCH_MAX_WILDCARDS
,
36 ENUM_END(id_match_names
, ID_MATCH_PERFECT
);
38 ENUM_BEGIN(id_type_names
, ID_ANY
, ID_KEY_ID
,
43 "ID_IPV4_ADDR_SUBNET",
45 "ID_IPV6_ADDR_SUBNET",
51 ENUM_NEXT(id_type_names
, ID_DER_ASN1_GN_URI
, ID_CERT_DER_SHA1
, ID_KEY_ID
,
53 "ID_PUBKEY_INFO_SHA1",
56 ENUM_END(id_type_names
, ID_CERT_DER_SHA1
);
59 * coding of X.501 distinguished name
67 static const x501rdn_t x501rdns
[] = {
68 {"ND", OID_NAME_DISTINGUISHER
, ASN1_PRINTABLESTRING
},
69 {"UID", OID_PILOT_USERID
, ASN1_PRINTABLESTRING
},
70 {"DC", OID_PILOT_DOMAIN_COMPONENT
, ASN1_PRINTABLESTRING
},
71 {"CN", OID_COMMON_NAME
, ASN1_PRINTABLESTRING
},
72 {"S", OID_SURNAME
, ASN1_PRINTABLESTRING
},
73 {"SN", OID_SERIAL_NUMBER
, ASN1_PRINTABLESTRING
},
74 {"serialNumber", OID_SERIAL_NUMBER
, ASN1_PRINTABLESTRING
},
75 {"C", OID_COUNTRY
, ASN1_PRINTABLESTRING
},
76 {"L", OID_LOCALITY
, ASN1_PRINTABLESTRING
},
77 {"ST", OID_STATE_OR_PROVINCE
, ASN1_PRINTABLESTRING
},
78 {"O", OID_ORGANIZATION
, ASN1_PRINTABLESTRING
},
79 {"OU", OID_ORGANIZATION_UNIT
, ASN1_PRINTABLESTRING
},
80 {"T", OID_TITLE
, ASN1_PRINTABLESTRING
},
81 {"D", OID_DESCRIPTION
, ASN1_PRINTABLESTRING
},
82 {"N", OID_NAME
, ASN1_PRINTABLESTRING
},
83 {"G", OID_GIVEN_NAME
, ASN1_PRINTABLESTRING
},
84 {"I", OID_INITIALS
, ASN1_PRINTABLESTRING
},
85 {"ID", OID_UNIQUE_IDENTIFIER
, ASN1_PRINTABLESTRING
},
86 {"EN", OID_EMPLOYEE_NUMBER
, ASN1_PRINTABLESTRING
},
87 {"employeeNumber", OID_EMPLOYEE_NUMBER
, ASN1_PRINTABLESTRING
},
88 {"E", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
89 {"Email", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
90 {"emailAddress", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
91 {"UN", OID_UNSTRUCTURED_NAME
, ASN1_IA5STRING
},
92 {"unstructuredName",OID_UNSTRUCTURED_NAME
, ASN1_IA5STRING
},
93 {"TCGID", OID_TCGID
, ASN1_PRINTABLESTRING
}
97 * maximum number of RDNs in atodn()
102 typedef struct private_identification_t private_identification_t
;
105 * Private data of an identification_t object.
107 struct private_identification_t
{
111 identification_t
public;
114 * Encoded representation of this ID.
125 * Enumerator over RDNs
128 /* implements enumerator interface */
130 /* RDNs left to parse */
135 * Implementation of rdn_enumerator_t.enumerate
137 static bool rdn_enumerate(rdn_enumerator_t
*this, chunk_t
*oid
,
138 u_char
*type
, chunk_t
*data
)
142 /* a RDN is a SET of attribute-values, each is a SEQUENCE ... */
143 if (asn1_unwrap(&this->left
, &rdn
) == ASN1_SET
&&
144 asn1_unwrap(&rdn
, &rdn
) == ASN1_SEQUENCE
)
147 if (asn1_unwrap(&rdn
, oid
) == ASN1_OID
)
149 /* and a specific string type */
150 *type
= asn1_unwrap(&rdn
, data
);
151 if (*type
!= ASN1_INVALID
)
161 * Create an enumerator over all RDNs (oid, string type, data) of a DN
163 static enumerator_t
* create_rdn_enumerator(chunk_t dn
)
165 rdn_enumerator_t
*e
= malloc_thing(rdn_enumerator_t
);
167 e
->public.enumerate
= (void*)rdn_enumerate
;
168 e
->public.destroy
= (void*)free
;
170 /* a DN is a sequence of RDNs */
171 if (asn1_unwrap(&dn
, &e
->left
) == ASN1_SEQUENCE
)
176 return enumerator_create_empty();
180 * Part enumerator over RDNs
183 /* implements enumerator interface */
185 /* inner RDN enumerator */
187 } rdn_part_enumerator_t
;
190 * Implementation of rdn_part_enumerator_t.enumerate().
192 static bool rdn_part_enumerate(rdn_part_enumerator_t
*this,
193 id_part_t
*type
, chunk_t
*data
)
195 int i
, known_oid
, strtype
;
196 chunk_t oid
, inner_data
;
197 static const struct {
201 {OID_COMMON_NAME
, ID_PART_RDN_CN
},
202 {OID_SURNAME
, ID_PART_RDN_S
},
203 {OID_SERIAL_NUMBER
, ID_PART_RDN_SN
},
204 {OID_COUNTRY
, ID_PART_RDN_C
},
205 {OID_LOCALITY
, ID_PART_RDN_L
},
206 {OID_STATE_OR_PROVINCE
, ID_PART_RDN_ST
},
207 {OID_ORGANIZATION
, ID_PART_RDN_O
},
208 {OID_ORGANIZATION_UNIT
, ID_PART_RDN_OU
},
209 {OID_TITLE
, ID_PART_RDN_T
},
210 {OID_DESCRIPTION
, ID_PART_RDN_D
},
211 {OID_NAME
, ID_PART_RDN_N
},
212 {OID_GIVEN_NAME
, ID_PART_RDN_G
},
213 {OID_INITIALS
, ID_PART_RDN_I
},
214 {OID_UNIQUE_IDENTIFIER
, ID_PART_RDN_ID
},
215 {OID_EMAIL_ADDRESS
, ID_PART_RDN_E
},
216 {OID_EMPLOYEE_NUMBER
, ID_PART_RDN_EN
},
219 while (this->inner
->enumerate(this->inner
, &oid
, &strtype
, &inner_data
))
221 known_oid
= asn1_known_oid(oid
);
222 for (i
= 0; i
< countof(oid2part
); i
++)
224 if (oid2part
[i
].oid
== known_oid
)
226 *type
= oid2part
[i
].type
;
236 * Implementation of rdn_part_enumerator_t.destroy().
238 static void rdn_part_enumerator_destroy(rdn_part_enumerator_t
*this)
240 this->inner
->destroy(this->inner
);
245 * Implementation of identification_t.create_part_enumerator
247 static enumerator_t
* create_part_enumerator(private_identification_t
*this)
253 rdn_part_enumerator_t
*e
= malloc_thing(rdn_part_enumerator_t
);
255 e
->inner
= create_rdn_enumerator(this->encoded
);
256 e
->public.enumerate
= (void*)rdn_part_enumerate
;
257 e
->public.destroy
= (void*)rdn_part_enumerator_destroy
;
266 return enumerator_create_empty();
271 * Pointer is set to the first RDN in a DN
273 static bool init_rdn(chunk_t dn
, chunk_t
*rdn
, chunk_t
*attribute
, bool *next
)
276 *attribute
= chunk_empty
;
278 /* a DN is a SEQUENCE OF RDNs */
279 if (*dn
.ptr
!= ASN1_SEQUENCE
)
281 /* DN is not a SEQUENCE */
285 rdn
->len
= asn1_length(&dn
);
287 if (rdn
->len
== ASN1_INVALID_LENGTH
)
289 /* Invalid RDN length */
295 /* are there any RDNs ? */
296 *next
= rdn
->len
> 0;
302 * Fetches the next RDN in a DN
304 static bool get_next_rdn(chunk_t
*rdn
, chunk_t
* attribute
, chunk_t
*oid
,
305 chunk_t
*value
, asn1_t
*type
, bool *next
)
309 /* initialize return values */
311 *value
= chunk_empty
;
313 /* if all attributes have been parsed, get next rdn */
314 if (attribute
->len
<= 0)
316 /* an RDN is a SET OF attributeTypeAndValue */
317 if (*rdn
->ptr
!= ASN1_SET
)
319 /* RDN is not a SET */
322 attribute
->len
= asn1_length(rdn
);
323 if (attribute
->len
== ASN1_INVALID_LENGTH
)
325 /* Invalid attribute length */
328 attribute
->ptr
= rdn
->ptr
;
329 /* advance to start of next RDN */
330 rdn
->ptr
+= attribute
->len
;
331 rdn
->len
-= attribute
->len
;
334 /* an attributeTypeAndValue is a SEQUENCE */
335 if (*attribute
->ptr
!= ASN1_SEQUENCE
)
337 /* attributeTypeAndValue is not a SEQUENCE */
341 /* extract the attribute body */
342 body
.len
= asn1_length(attribute
);
344 if (body
.len
== ASN1_INVALID_LENGTH
)
346 /* Invalid attribute body length */
350 body
.ptr
= attribute
->ptr
;
352 /* advance to start of next attribute */
353 attribute
->ptr
+= body
.len
;
354 attribute
->len
-= body
.len
;
356 /* attribute type is an OID */
357 if (*body
.ptr
!= ASN1_OID
)
359 /* attributeType is not an OID */
363 oid
->len
= asn1_length(&body
);
365 if (oid
->len
== ASN1_INVALID_LENGTH
)
367 /* Invalid attribute OID length */
372 /* advance to the attribute value */
373 body
.ptr
+= oid
->len
;
374 body
.len
-= oid
->len
;
376 /* extract string type */
379 /* extract string value */
380 value
->len
= asn1_length(&body
);
382 if (value
->len
== ASN1_INVALID_LENGTH
)
384 /* Invalid attribute string length */
387 value
->ptr
= body
.ptr
;
389 /* are there any RDNs left? */
390 *next
= rdn
->len
> 0 || attribute
->len
> 0;
395 * Print a DN with all its RDN in a buffer to present it to the user
397 static void dntoa(chunk_t dn
, char *buf
, size_t len
)
400 chunk_t oid_data
, data
;
403 bool finished
= FALSE
;
405 e
= create_rdn_enumerator(dn
);
406 while (e
->enumerate(e
, &oid_data
, &type
, &data
))
408 oid
= asn1_known_oid(oid_data
);
410 if (oid
== OID_UNKNOWN
)
412 written
= snprintf(buf
, len
, "%#B=", &oid_data
);
416 written
= snprintf(buf
, len
,"%s=", oid_names
[oid
].name
);
421 if (chunk_printable(data
, NULL
, '?'))
423 written
= snprintf(buf
, len
, "%.*s", data
.len
, data
.ptr
);
427 written
= snprintf(buf
, len
, "%#B", &data
);
432 if (data
.ptr
+ data
.len
!= dn
.ptr
+ dn
.len
)
434 written
= snprintf(buf
, len
, " ");
446 snprintf(buf
, len
, "(invalid ID_DER_ASN1_DN)");
452 * Converts an LDAP-style human-readable ASCII-encoded
453 * ASN.1 distinguished name into binary DER-encoded format
455 static status_t
atodn(char *src
, chunk_t
*dn
)
457 /* finite state machine for atodn */
466 chunk_t oid
= chunk_empty
;
467 chunk_t name
= chunk_empty
;
468 chunk_t rdns
[RDN_MAX
];
474 state_t state
= SEARCH_OID
;
475 status_t status
= SUCCESS
;
482 if (*src
!= ' ' && *src
!= '/' && *src
!= ',')
490 if (*src
!= ' ' && *src
!= '=')
498 for (i
= 0; i
< countof(x501rdns
); i
++)
500 if (strlen(x501rdns
[i
].name
) == oid
.len
&&
501 strncasecmp(x501rdns
[i
].name
, oid
.ptr
, oid
.len
) == 0)
509 status
= NOT_SUPPORTED
;
513 /* reset oid and change state */
519 if (*src
!= ' ' && *src
!= '=')
528 if (*src
!= ',' && *src
!= '/' && *src
!= '\0')
538 name
.len
-= whitespace
;
539 rdn_type
= (x501rdns
[i
].type
== ASN1_PRINTABLESTRING
540 && !asn1_is_printablestring(name
))
541 ? ASN1_T61STRING
: x501rdns
[i
].type
;
543 if (rdn_count
< RDN_MAX
)
547 rdn_oid
= asn1_build_known_oid(x501rdns
[i
].oid
);
551 asn1_wrap(ASN1_SET
, "m",
552 asn1_wrap(ASN1_SEQUENCE
, "mm",
554 asn1_wrap(rdn_type
, "c", name
)
557 dn_len
+= rdns
[rdn_count
++].len
;
561 status
= INVALID_ARG
;
568 /* reset name and change state */
576 } while (*src
++ != '\0');
578 /* build the distinguished name sequence */
581 u_char
*pos
= asn1_build_object(dn
, ASN1_SEQUENCE
, dn_len
);
583 for (i
= 0; i
< rdn_count
; i
++)
585 memcpy(pos
, rdns
[i
].ptr
, rdns
[i
].len
);
591 if (status
!= SUCCESS
)
600 * Implementation of identification_t.get_encoding.
602 static chunk_t
get_encoding(private_identification_t
*this)
604 return this->encoded
;
608 * Implementation of identification_t.get_type.
610 static id_type_t
get_type(private_identification_t
*this)
616 * Implementation of identification_t.contains_wildcards fro ID_DER_ASN1_DN.
618 static bool contains_wildcards_dn(private_identification_t
*this)
620 enumerator_t
*enumerator
;
621 bool contains
= FALSE
;
625 enumerator
= create_part_enumerator(this);
626 while (enumerator
->enumerate(enumerator
, &type
, &data
))
628 if (data
.len
== 1 && data
.ptr
[0] == '*')
634 enumerator
->destroy(enumerator
);
639 * Implementation of identification_t.contains_wildcards.
641 static bool contains_wildcards(private_identification_t
*this)
649 return memchr(this->encoded
.ptr
, '*', this->encoded
.len
) != NULL
;
651 return contains_wildcards_dn(this);
658 * Default implementation of identification_t.equals.
659 * compares encoded chunk for equality.
661 static bool equals_binary(private_identification_t
*this, private_identification_t
*other
)
663 if (this->type
== other
->type
)
665 if (this->type
== ID_ANY
)
669 return chunk_equals(this->encoded
, other
->encoded
);
675 * Compare to DNs, for equality if wc == NULL, for match otherwise
677 static bool compare_dn(chunk_t t_dn
, chunk_t o_dn
, int *wc
)
680 chunk_t t_oid
, o_oid
, t_data
, o_data
;
681 u_char t_type
, o_type
;
682 bool t_next
, o_next
, finished
= FALSE
;
690 if (t_dn
.len
!= o_dn
.len
)
695 /* try a binary compare */
696 if (memeq(t_dn
.ptr
, o_dn
.ptr
, t_dn
.len
))
701 t
= create_rdn_enumerator(t_dn
);
702 o
= create_rdn_enumerator(o_dn
);
705 t_next
= t
->enumerate(t
, &t_oid
, &t_type
, &t_data
);
706 o_next
= o
->enumerate(o
, &o_oid
, &o_type
, &o_data
);
708 if (!o_next
&& !t_next
)
713 if (o_next
!= t_next
)
717 if (!chunk_equals(t_oid
, o_oid
))
721 if (wc
&& o_data
.len
== 1 && o_data
.ptr
[0] == '*')
727 if (t_data
.len
!= o_data
.len
)
731 if (t_type
== o_type
&&
732 (t_type
== ASN1_PRINTABLESTRING
||
733 (t_type
== ASN1_IA5STRING
&&
734 (asn1_known_oid(t_oid
) == OID_PKCS9_EMAIL
||
735 asn1_known_oid(t_oid
) == OID_EMAIL_ADDRESS
))))
736 { /* ignore case for printableStrings and email RDNs */
737 if (strncasecmp(t_data
.ptr
, o_data
.ptr
, t_data
.len
) != 0)
743 { /* respect case and length for everything else */
744 if (!memeq(t_data
.ptr
, o_data
.ptr
, t_data
.len
))
750 /* the enumerator returns FALSE on parse error, we are finished
751 * if we have reached the end of the DN only */
752 if ((t_data
.ptr
+ t_data
.len
== t_dn
.ptr
+ t_dn
.len
) &&
753 (o_data
.ptr
+ o_data
.len
== o_dn
.ptr
+ o_dn
.len
))
764 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
766 static bool equals_dn(private_identification_t
*this,
767 private_identification_t
*other
)
769 return compare_dn(this->encoded
, other
->encoded
, NULL
);
773 * Special implementation of identification_t.equals for RFC822 and FQDN.
775 static bool equals_strcasecmp(private_identification_t
*this,
776 private_identification_t
*other
)
778 /* we do some extra sanity checks to check for invalid IDs with a
779 * terminating null in it. */
780 if (this->encoded
.len
== other
->encoded
.len
&&
781 memchr(this->encoded
.ptr
, 0, this->encoded
.len
) == NULL
&&
782 memchr(other
->encoded
.ptr
, 0, other
->encoded
.len
) == NULL
&&
783 strncasecmp(this->encoded
.ptr
, other
->encoded
.ptr
, this->encoded
.len
) == 0)
791 * Default implementation of identification_t.matches.
793 static id_match_t
matches_binary(private_identification_t
*this,
794 private_identification_t
*other
)
796 if (other
->type
== ID_ANY
)
800 if (this->type
== other
->type
&&
801 chunk_equals(this->encoded
, other
->encoded
))
803 return ID_MATCH_PERFECT
;
805 return ID_MATCH_NONE
;
809 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
810 * Checks for a wildcard in other-string, and compares it against this-string.
812 static id_match_t
matches_string(private_identification_t
*this,
813 private_identification_t
*other
)
815 u_int len
= other
->encoded
.len
;
817 if (other
->type
== ID_ANY
)
821 if (this->type
!= other
->type
)
823 return ID_MATCH_NONE
;
825 /* try a equals check first */
826 if (equals_strcasecmp(this, other
))
828 return ID_MATCH_PERFECT
;
830 if (len
== 0 || this->encoded
.len
< len
)
832 return ID_MATCH_NONE
;
835 /* check for single wildcard at the head of the string */
836 if (*other
->encoded
.ptr
== '*')
838 /* single asterisk matches any string */
840 { /* not better than ID_ANY */
843 if (strncasecmp(this->encoded
.ptr
+ this->encoded
.len
- len
,
844 other
->encoded
.ptr
+ 1, len
) == 0)
846 return ID_MATCH_ONE_WILDCARD
;
849 return ID_MATCH_NONE
;
853 * Special implementation of identification_t.matches for ID_ANY.
854 * ANY matches only another ANY, but nothing other
856 static id_match_t
matches_any(private_identification_t
*this,
857 private_identification_t
*other
)
859 if (other
->type
== ID_ANY
)
863 return ID_MATCH_NONE
;
867 * Special implementation of identification_t.matches for ID_DER_ASN1_DN
869 static id_match_t
matches_dn(private_identification_t
*this,
870 private_identification_t
*other
)
874 if (other
->type
== ID_ANY
)
879 if (this->type
== other
->type
)
881 if (compare_dn(this->encoded
, other
->encoded
, &wc
))
883 wc
= min(wc
, ID_MATCH_ONE_WILDCARD
- ID_MATCH_MAX_WILDCARDS
);
884 return ID_MATCH_PERFECT
- wc
;
887 return ID_MATCH_NONE
;
891 * Described in header.
893 int identification_printf_hook(char *dst
, size_t len
, printf_hook_spec_t
*spec
,
894 const void *const *args
)
896 private_identification_t
*this = *((private_identification_t
**)(args
[0]));
902 return print_in_hook(dst
, len
, "%*s", spec
->width
, "(null)");
908 snprintf(buf
, sizeof(buf
), "%%any");
911 if (this->encoded
.len
< sizeof(struct in_addr
) ||
912 inet_ntop(AF_INET
, this->encoded
.ptr
, buf
, sizeof(buf
)) == NULL
)
914 snprintf(buf
, sizeof(buf
), "(invalid ID_IPV4_ADDR)");
918 if (this->encoded
.len
< sizeof(struct in6_addr
) ||
919 inet_ntop(AF_INET6
, this->encoded
.ptr
, buf
, INET6_ADDRSTRLEN
) == NULL
)
921 snprintf(buf
, sizeof(buf
), "(invalid ID_IPV6_ADDR)");
926 case ID_DER_ASN1_GN_URI
:
927 case ID_IETF_ATTR_STRING
:
928 chunk_printable(this->encoded
, &proper
, '?');
929 snprintf(buf
, sizeof(buf
), "%.*s", proper
.len
, proper
.ptr
);
933 dntoa(this->encoded
, buf
, sizeof(buf
));
936 snprintf(buf
, sizeof(buf
), "(ASN.1 general Name");
939 if (chunk_printable(this->encoded
, NULL
, '?'))
940 { /* fully printable, use ascii version */
941 snprintf(buf
, sizeof(buf
), "%.*s",
942 this->encoded
.len
, this->encoded
.ptr
);
945 { /* not printable, hex dump */
946 snprintf(buf
, sizeof(buf
), "%#B", &this->encoded
);
950 case ID_PUBKEY_INFO_SHA1
:
952 case ID_CERT_DER_SHA1
:
953 snprintf(buf
, sizeof(buf
), "%#B", &this->encoded
);
956 snprintf(buf
, sizeof(buf
), "(unknown ID type: %d)", this->type
);
961 return print_in_hook(dst
, len
, "%-*s", spec
->width
, buf
);
963 return print_in_hook(dst
, len
, "%*s", spec
->width
, buf
);
966 * Implementation of identification_t.clone.
968 static identification_t
*clone_(private_identification_t
*this)
970 private_identification_t
*clone
= malloc_thing(private_identification_t
);
972 memcpy(clone
, this, sizeof(private_identification_t
));
973 if (this->encoded
.len
)
975 clone
->encoded
= chunk_clone(this->encoded
);
977 return &clone
->public;
981 * Implementation of identification_t.destroy.
983 static void destroy(private_identification_t
*this)
985 chunk_free(&this->encoded
);
990 * Generic constructor used for the other constructors.
992 static private_identification_t
*identification_create(void)
994 private_identification_t
*this = malloc_thing(private_identification_t
);
996 this->public.get_encoding
= (chunk_t (*) (identification_t
*))get_encoding
;
997 this->public.get_type
= (id_type_t (*) (identification_t
*))get_type
;
998 this->public.contains_wildcards
= (bool (*) (identification_t
*this))contains_wildcards
;
999 this->public.create_part_enumerator
= (enumerator_t
*(*)(identification_t
*))create_part_enumerator
;
1000 this->public.clone
= (identification_t
* (*) (identification_t
*))clone_
;
1001 this->public.destroy
= (void (*) (identification_t
*))destroy
;
1002 /* we use these as defaults, the may be overloaded for special ID types */
1003 this->public.equals
= (bool (*) (identification_t
*,identification_t
*))equals_binary
;
1004 this->public.matches
= (id_match_t (*) (identification_t
*,identification_t
*))matches_binary
;
1006 this->encoded
= chunk_empty
;
1012 * Described in header.
1014 identification_t
*identification_create_from_string(char *string
)
1016 private_identification_t
*this = identification_create();
1022 if (strchr(string
, '=') != NULL
)
1024 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1025 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1027 if (atodn(string
, &this->encoded
) != SUCCESS
)
1029 this->type
= ID_KEY_ID
;
1030 this->encoded
= chunk_clone(chunk_create(string
, strlen(string
)));
1031 return &this->public;
1033 this->type
= ID_DER_ASN1_DN
;
1034 this->public.equals
= (bool (*) (identification_t
*,identification_t
*))equals_dn
;
1035 this->public.matches
= (id_match_t (*) (identification_t
*,identification_t
*))matches_dn
;
1036 return &this->public;
1038 else if (strchr(string
, '@') == NULL
)
1040 if (streq(string
, "%any")
1041 || streq(string
, "%any6")
1042 || streq(string
, "0.0.0.0")
1043 || streq(string
, "*")
1044 || streq(string
, "::")
1045 || streq(string
, "0::0"))
1047 /* any ID will be accepted */
1048 this->type
= ID_ANY
;
1049 this->public.matches
= (id_match_t (*)
1050 (identification_t
*,identification_t
*))matches_any
;
1051 return &this->public;
1055 if (strchr(string
, ':') == NULL
)
1058 struct in_addr address
;
1059 chunk_t chunk
= {(void*)&address
, sizeof(address
)};
1061 if (inet_pton(AF_INET
, string
, &address
) <= 0)
1063 /* not IPv4, mostly FQDN */
1064 this->type
= ID_FQDN
;
1065 this->encoded
.ptr
= strdup(string
);
1066 this->encoded
.len
= strlen(string
);
1067 this->public.matches
= (id_match_t (*)
1068 (identification_t
*,identification_t
*))matches_string
;
1069 this->public.equals
= (bool (*)
1070 (identification_t
*,identification_t
*))equals_strcasecmp
;
1071 return &this->public;
1073 this->encoded
= chunk_clone(chunk
);
1074 this->type
= ID_IPV4_ADDR
;
1075 return &this->public;
1080 struct in6_addr address
;
1081 chunk_t chunk
= {(void*)&address
, sizeof(address
)};
1083 if (inet_pton(AF_INET6
, string
, &address
) <= 0)
1085 this->type
= ID_KEY_ID
;
1086 this->encoded
= chunk_clone(chunk_create(string
,
1088 return &this->public;
1090 this->encoded
= chunk_clone(chunk
);
1091 this->type
= ID_IPV6_ADDR
;
1092 return &this->public;
1100 if (*(string
+ 1) == '#')
1103 this->type
= ID_KEY_ID
;
1104 this->encoded
= chunk_from_hex(
1105 chunk_create(string
, strlen(string
)), NULL
);
1106 return &this->public;
1110 this->type
= ID_FQDN
;
1111 this->encoded
.ptr
= strdup(string
+ 1);
1112 this->encoded
.len
= strlen(string
+ 1);
1113 this->public.matches
= (id_match_t (*)
1114 (identification_t
*,identification_t
*))matches_string
;
1115 this->public.equals
= (bool (*)
1116 (identification_t
*,identification_t
*))equals_strcasecmp
;
1117 return &this->public;
1122 this->type
= ID_RFC822_ADDR
;
1123 this->encoded
.ptr
= strdup(string
);
1124 this->encoded
.len
= strlen(string
);
1125 this->public.matches
= (id_match_t (*)
1126 (identification_t
*,identification_t
*))matches_string
;
1127 this->public.equals
= (bool (*)
1128 (identification_t
*,identification_t
*))equals_strcasecmp
;
1129 return &this->public;
1135 * Described in header.
1137 identification_t
*identification_create_from_encoding(id_type_t type
, chunk_t encoded
)
1139 private_identification_t
*this = identification_create();
1145 this->public.matches
= (id_match_t (*)
1146 (identification_t
*,identification_t
*))matches_any
;
1149 case ID_RFC822_ADDR
:
1150 this->public.matches
= (id_match_t (*)
1151 (identification_t
*,identification_t
*))matches_string
;
1152 this->public.equals
= (bool (*)
1153 (identification_t
*,identification_t
*))equals_strcasecmp
;
1155 case ID_DER_ASN1_DN
:
1156 this->public.equals
= (bool (*)
1157 (identification_t
*,identification_t
*))equals_dn
;
1158 this->public.matches
= (id_match_t (*)
1159 (identification_t
*,identification_t
*))matches_dn
;
1163 case ID_DER_ASN1_GN
:
1165 case ID_DER_ASN1_GN_URI
:
1166 case ID_PUBKEY_INFO_SHA1
:
1167 case ID_PUBKEY_SHA1
:
1168 case ID_CERT_DER_SHA1
:
1169 case ID_IETF_ATTR_STRING
:
1174 /* apply encoded chunk */
1177 this->encoded
= chunk_clone(encoded
);
1179 return &(this->public);