2 * @file identification.c
4 * @brief Implementation of identification_t.
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
33 #include "identification.h"
35 #include <asn1/asn1.h>
37 ENUM_BEGIN(id_type_names
, ID_ANY
, ID_KEY_ID
,
42 "ID_IPV4_ADDR_SUBNET",
44 "ID_IPV6_ADDR_SUBNET",
50 ENUM_NEXT(id_type_names
, ID_DER_ASN1_GN_URI
, ID_DER_ASN1_GN_URI
, ID_KEY_ID
,
51 "ID_DER_ASN1_GN_URI");
52 ENUM_END(id_type_names
, ID_DER_ASN1_GN_URI
);
56 * X.501 acronyms for well known object identifiers (OIDs)
58 static u_char oid_ND
[] = {
59 0x02, 0x82, 0x06, 0x01, 0x0A, 0x07, 0x14
61 static u_char oid_UID
[] = {
62 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x01
64 static u_char oid_DC
[] = {
65 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19
67 static u_char oid_CN
[] = {
70 static u_char oid_S
[] = {
73 static u_char oid_SN
[] = {
76 static u_char oid_C
[] = {
79 static u_char oid_L
[] = {
82 static u_char oid_ST
[] = {
85 static u_char oid_O
[] = {
88 static u_char oid_OU
[] = {
91 static u_char oid_T
[] = {
94 static u_char oid_D
[] = {
97 static u_char oid_N
[] = {
100 static u_char oid_G
[] = {
103 static u_char oid_I
[] = {
106 static u_char oid_ID
[] = {
109 static u_char oid_EN
[] = {
110 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x42, 0x03, 0x01, 0x03
112 static u_char oid_E
[] = {
113 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01
115 static u_char oid_UN
[] = {
116 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x02
118 static u_char oid_TCGID
[] = {
119 0x2B, 0x06, 0x01, 0x04, 0x01, 0x89, 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B
123 * coding of X.501 distinguished name
131 static const x501rdn_t x501rdns
[] = {
132 {"ND", {oid_ND
, 7}, ASN1_PRINTABLESTRING
},
133 {"UID", {oid_UID
, 10}, ASN1_PRINTABLESTRING
},
134 {"DC", {oid_DC
, 10}, ASN1_PRINTABLESTRING
},
135 {"CN", {oid_CN
, 3}, ASN1_PRINTABLESTRING
},
136 {"S", {oid_S
, 3}, ASN1_PRINTABLESTRING
},
137 {"SN", {oid_SN
, 3}, ASN1_PRINTABLESTRING
},
138 {"serialNumber", {oid_SN
, 3}, ASN1_PRINTABLESTRING
},
139 {"C", {oid_C
, 3}, ASN1_PRINTABLESTRING
},
140 {"L", {oid_L
, 3}, ASN1_PRINTABLESTRING
},
141 {"ST", {oid_ST
, 3}, ASN1_PRINTABLESTRING
},
142 {"O", {oid_O
, 3}, ASN1_PRINTABLESTRING
},
143 {"OU", {oid_OU
, 3}, ASN1_PRINTABLESTRING
},
144 {"T", {oid_T
, 3}, ASN1_PRINTABLESTRING
},
145 {"D", {oid_D
, 3}, ASN1_PRINTABLESTRING
},
146 {"N", {oid_N
, 3}, ASN1_PRINTABLESTRING
},
147 {"G", {oid_G
, 3}, ASN1_PRINTABLESTRING
},
148 {"I", {oid_I
, 3}, ASN1_PRINTABLESTRING
},
149 {"ID", {oid_ID
, 3}, ASN1_PRINTABLESTRING
},
150 {"EN", {oid_EN
, 10}, ASN1_PRINTABLESTRING
},
151 {"employeeNumber", {oid_EN
, 10}, ASN1_PRINTABLESTRING
},
152 {"E", {oid_E
, 9}, ASN1_IA5STRING
},
153 {"Email", {oid_E
, 9}, ASN1_IA5STRING
},
154 {"emailAddress", {oid_E
, 9}, ASN1_IA5STRING
},
155 {"UN", {oid_UN
, 9}, ASN1_IA5STRING
},
156 {"unstructuredName",{oid_UN
, 9}, ASN1_IA5STRING
},
157 {"TCGID", {oid_TCGID
, 12}, ASN1_PRINTABLESTRING
}
159 #define X501_RDN_ROOF 26
162 * maximum number of RDNs in atodn()
167 typedef struct private_identification_t private_identification_t
;
170 * Private data of an identification_t object.
172 struct private_identification_t
{
176 identification_t
public;
179 * Encoded representation of this ID.
189 static private_identification_t
*identification_create(void);
192 * updates a chunk (!????)
193 * TODO: We should reconsider this stuff, its not really clear
195 static void update_chunk(chunk_t
*ch
, int n
)
197 n
= (n
> -1 && n
< (int)ch
->len
)? n
: (int)ch
->len
-1;
198 ch
->ptr
+= n
; ch
->len
-= n
;
202 * Prints a binary string in hexadecimal form
204 void hex_str(chunk_t bin
, chunk_t
*str
)
207 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"0x"));
208 for (i
= 0; i
< bin
.len
; i
++)
210 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"%02X",*bin
.ptr
++));
215 * Remove any malicious characters from a chunk. We are very restrictive, but
216 * whe use these strings only to present it to the user.
218 static chunk_t
sanitize_chunk(chunk_t chunk
)
221 chunk_t clone
= chunk_clone(chunk
);
223 for (pos
= clone
.ptr
; pos
< (char*)(clone
.ptr
+ clone
.len
); pos
++)
249 * Pointer is set to the first RDN in a DN
251 static status_t
init_rdn(chunk_t dn
, chunk_t
*rdn
, chunk_t
*attribute
, bool *next
)
254 *attribute
= chunk_empty
;
256 /* a DN is a SEQUENCE OF RDNs */
257 if (*dn
.ptr
!= ASN1_SEQUENCE
)
259 /* DN is not a SEQUENCE */
263 rdn
->len
= asn1_length(&dn
);
265 if (rdn
->len
== ASN1_INVALID_LENGTH
)
267 /* Invalid RDN length */
273 /* are there any RDNs ? */
274 *next
= rdn
->len
> 0;
280 * Fetches the next RDN in a DN
282 static status_t
get_next_rdn(chunk_t
*rdn
, chunk_t
* attribute
, chunk_t
*oid
, chunk_t
*value
, asn1_t
*type
, bool *next
)
286 /* initialize return values */
288 *value
= chunk_empty
;
290 /* if all attributes have been parsed, get next rdn */
291 if (attribute
->len
<= 0)
293 /* an RDN is a SET OF attributeTypeAndValue */
294 if (*rdn
->ptr
!= ASN1_SET
)
296 /* RDN is not a SET */
299 attribute
->len
= asn1_length(rdn
);
300 if (attribute
->len
== ASN1_INVALID_LENGTH
)
302 /* Invalid attribute length */
305 attribute
->ptr
= rdn
->ptr
;
306 /* advance to start of next RDN */
307 rdn
->ptr
+= attribute
->len
;
308 rdn
->len
-= attribute
->len
;
311 /* an attributeTypeAndValue is a SEQUENCE */
312 if (*attribute
->ptr
!= ASN1_SEQUENCE
)
314 /* attributeTypeAndValue is not a SEQUENCE */
318 /* extract the attribute body */
319 body
.len
= asn1_length(attribute
);
321 if (body
.len
== ASN1_INVALID_LENGTH
)
323 /* Invalid attribute body length */
327 body
.ptr
= attribute
->ptr
;
329 /* advance to start of next attribute */
330 attribute
->ptr
+= body
.len
;
331 attribute
->len
-= body
.len
;
333 /* attribute type is an OID */
334 if (*body
.ptr
!= ASN1_OID
)
336 /* attributeType is not an OID */
340 oid
->len
= asn1_length(&body
);
342 if (oid
->len
== ASN1_INVALID_LENGTH
)
344 /* Invalid attribute OID length */
349 /* advance to the attribute value */
350 body
.ptr
+= oid
->len
;
351 body
.len
-= oid
->len
;
353 /* extract string type */
356 /* extract string value */
357 value
->len
= asn1_length(&body
);
359 if (value
->len
== ASN1_INVALID_LENGTH
)
361 /* Invalid attribute string length */
364 value
->ptr
= body
.ptr
;
366 /* are there any RDNs left? */
367 *next
= rdn
->len
> 0 || attribute
->len
> 0;
372 * Parses an ASN.1 distinguished name int its OID/value pairs
374 static status_t
dntoa(chunk_t dn
, chunk_t
*str
)
376 chunk_t rdn
, oid
, attribute
, value
, proper
;
382 status_t status
= init_rdn(dn
, &rdn
, &attribute
, &next
);
384 if (status
!= SUCCESS
)
389 status
= get_next_rdn(&rdn
, &attribute
, &oid
, &value
, &type
, &next
);
391 if (status
!= SUCCESS
)
395 { /* first OID/value pair */
399 { /* separate OID/value pair by a comma */
400 update_chunk(str
, snprintf(str
->ptr
,str
->len
,", "));
404 oid_code
= known_oid(oid
);
405 if (oid_code
== OID_UNKNOWN
)
406 { /* OID not found in list */
411 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"%s", oid_names
[oid_code
].name
));
414 proper
= sanitize_chunk(value
);
415 update_chunk(str
, snprintf(str
->ptr
,str
->len
,"=%.*s", (int)proper
.len
, proper
.ptr
));
422 * compare two distinguished names by
423 * comparing the individual RDNs
425 static bool same_dn(chunk_t a
, chunk_t b
)
427 chunk_t rdn_a
, rdn_b
, attribute_a
, attribute_b
;
428 chunk_t oid_a
, oid_b
, value_a
, value_b
;
429 asn1_t type_a
, type_b
;
432 /* same lengths for the DNs */
436 /* try a binary comparison first */
437 if (memeq(a
.ptr
, b
.ptr
, b
.len
))
440 /* initialize DN parsing */
441 if (init_rdn(a
, &rdn_a
, &attribute_a
, &next_a
) != SUCCESS
442 || init_rdn(b
, &rdn_b
, &attribute_b
, &next_b
) != SUCCESS
)
447 /* fetch next RDN pair */
448 while (next_a
&& next_b
)
450 /* parse next RDNs and check for errors */
451 if (get_next_rdn(&rdn_a
, &attribute_a
, &oid_a
, &value_a
, &type_a
, &next_a
) != SUCCESS
452 || get_next_rdn(&rdn_b
, &attribute_b
, &oid_b
, &value_b
, &type_b
, &next_b
) != SUCCESS
)
457 /* OIDs must agree */
458 if (oid_a
.len
!= oid_b
.len
|| memcmp(oid_a
.ptr
, oid_b
.ptr
, oid_b
.len
) != 0)
461 /* same lengths for values */
462 if (value_a
.len
!= value_b
.len
)
465 /* printableStrings and email RDNs require uppercase comparison */
466 if (type_a
== type_b
&& (type_a
== ASN1_PRINTABLESTRING
467 || (type_a
== ASN1_IA5STRING
&& known_oid(oid_a
) == OID_PKCS9_EMAIL
)))
469 if (strncasecmp(value_a
.ptr
, value_b
.ptr
, value_b
.len
) != 0)
474 if (strncmp(value_a
.ptr
, value_b
.ptr
, value_b
.len
) != 0)
478 /* both DNs must have same number of RDNs */
479 if (next_a
|| next_b
)
482 /* the two DNs are equal! */
488 * compare two distinguished names by comparing the individual RDNs.
489 * A single'*' character designates a wildcard RDN in DN b.
490 * TODO: Add support for different RDN order in DN !!
492 bool match_dn(chunk_t a
, chunk_t b
, int *wildcards
)
494 chunk_t rdn_a
, rdn_b
, attribute_a
, attribute_b
;
495 chunk_t oid_a
, oid_b
, value_a
, value_b
;
496 asn1_t type_a
, type_b
;
499 /* initialize wildcard counter */
502 /* initialize DN parsing */
503 if (init_rdn(a
, &rdn_a
, &attribute_a
, &next_a
) != SUCCESS
504 || init_rdn(b
, &rdn_b
, &attribute_b
, &next_b
) != SUCCESS
)
509 /* fetch next RDN pair */
510 while (next_a
&& next_b
)
512 /* parse next RDNs and check for errors */
513 if (get_next_rdn(&rdn_a
, &attribute_a
, &oid_a
, &value_a
, &type_a
, &next_a
) != SUCCESS
514 || get_next_rdn(&rdn_b
, &attribute_b
, &oid_b
, &value_b
, &type_b
, &next_b
) != SUCCESS
)
518 /* OIDs must agree */
519 if (oid_a
.len
!= oid_b
.len
|| memcmp(oid_a
.ptr
, oid_b
.ptr
, oid_b
.len
) != 0)
522 /* does rdn_b contain a wildcard? */
523 if (value_b
.len
== 1 && *value_b
.ptr
== '*')
528 /* same lengths for values */
529 if (value_a
.len
!= value_b
.len
)
532 /* printableStrings and email RDNs require uppercase comparison */
533 if (type_a
== type_b
&& (type_a
== ASN1_PRINTABLESTRING
534 || (type_a
== ASN1_IA5STRING
&& known_oid(oid_a
) == OID_PKCS9_EMAIL
)))
536 if (strncasecmp(value_a
.ptr
, value_b
.ptr
, value_b
.len
) != 0)
541 if (strncmp(value_a
.ptr
, value_b
.ptr
, value_b
.len
) != 0)
545 /* both DNs must have same number of RDNs */
546 if (next_a
|| next_b
)
551 /* the two DNs match! */
552 *wildcards
= min(*wildcards
, MAX_WILDCARDS
);
557 * Converts an LDAP-style human-readable ASCII-encoded
558 * ASN.1 distinguished name into binary DER-encoded format
560 static status_t
atodn(char *src
, chunk_t
*dn
)
562 /* finite state machine for atodn */
571 chunk_t oid
= chunk_empty
;
572 chunk_t name
= chunk_empty
;
573 chunk_t rdns
[RDN_MAX
];
579 state_t state
= SEARCH_OID
;
580 status_t status
= SUCCESS
;
587 if (*src
!= ' ' && *src
!= '/' && *src
!= ',')
595 if (*src
!= ' ' && *src
!= '=')
601 for (i
= 0; i
< X501_RDN_ROOF
; i
++)
603 if (strlen(x501rdns
[i
].name
) == oid
.len
604 && strncasecmp(x501rdns
[i
].name
, oid
.ptr
, oid
.len
) == 0)
606 break; /* found a valid OID */
609 if (i
== X501_RDN_ROOF
)
611 status
= NOT_SUPPORTED
;
615 /* reset oid and change state */
621 if (*src
!= ' ' && *src
!= '=')
630 if (*src
!= ',' && *src
!= '/' && *src
!= '\0')
640 name
.len
-= whitespace
;
641 rdn_type
= (x501rdns
[i
].type
== ASN1_PRINTABLESTRING
642 && !is_printablestring(name
))? ASN1_T61STRING
: x501rdns
[i
].type
;
644 if (rdn_count
< RDN_MAX
)
647 asn1_wrap(ASN1_SET
, "m",
648 asn1_wrap(ASN1_SEQUENCE
, "mm",
649 asn1_wrap(ASN1_OID
, "c", x501rdns
[i
].oid
),
650 asn1_wrap(rdn_type
, "c", name
)
653 dn_len
+= rdns
[rdn_count
++].len
;
659 /* reset name and change state */
667 } while (*src
++ != '\0');
669 /* build the distinguished name sequence */
672 u_char
*pos
= build_asn1_object(dn
, ASN1_SEQUENCE
, dn_len
);
674 for (i
= 0; i
< rdn_count
; i
++)
676 memcpy(pos
, rdns
[i
].ptr
, rdns
[i
].len
);
682 if (status
!= SUCCESS
)
691 * Implementation of identification_t.get_encoding.
693 static chunk_t
get_encoding(private_identification_t
*this)
695 return this->encoded
;
699 * Implementation of identification_t.get_type.
701 static id_type_t
get_type(private_identification_t
*this)
707 * Implementation of identification_t.contains_wildcards.
709 static bool contains_wildcards(private_identification_t
*this)
717 return memchr(this->encoded
.ptr
, '*', this->encoded
.len
) != NULL
;
727 * Default implementation of identification_t.equals.
728 * compares encoded chunk for equality.
730 static bool equals_binary(private_identification_t
*this, private_identification_t
*other
)
732 return this->type
== other
->type
&&
733 chunk_equals(this->encoded
, other
->encoded
);
737 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
739 static bool equals_dn(private_identification_t
*this,
740 private_identification_t
*other
)
742 return same_dn(this->encoded
, other
->encoded
);
746 * Default implementation of identification_t.matches.
748 static bool matches_binary(private_identification_t
*this,
749 private_identification_t
*other
, int *wildcards
)
751 if (other
->type
== ID_ANY
)
753 *wildcards
= MAX_WILDCARDS
;
757 return this->type
== other
->type
&&
758 chunk_equals(this->encoded
, other
->encoded
);
762 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
763 * Checks for a wildcard in other-string, and compares it against this-string.
765 static bool matches_string(private_identification_t
*this,
766 private_identification_t
*other
, int *wildcards
)
768 u_int len
= other
->encoded
.len
;
770 if (other
->type
== ID_ANY
)
772 *wildcards
= MAX_WILDCARDS
;
776 if (this->type
!= other
->type
)
779 /* try a binary comparison first */
780 if (equals_binary(this, other
))
786 if (len
== 0 || this->encoded
.len
< len
)
789 /* check for single wildcard at the head of the string */
790 if (*other
->encoded
.ptr
== '*')
794 /* single asterisk matches any string */
798 if (memeq(this->encoded
.ptr
+ this->encoded
.len
- len
, other
->encoded
.ptr
+ 1, len
))
806 * Special implementation of identification_t.matches for ID_ANY.
807 * ANY matches only another ANY, but nothing other
809 static bool matches_any(private_identification_t
*this,
810 private_identification_t
*other
, int *wildcards
)
813 return other
->type
== ID_ANY
;
817 * Special implementation of identification_t.matches for ID_DER_ASN1_DN.
818 * ANY matches any, even ANY, thats why its there...
820 static bool matches_dn(private_identification_t
*this,
821 private_identification_t
*other
, int *wildcards
)
823 if (other
->type
== ID_ANY
)
825 *wildcards
= MAX_WILDCARDS
;
829 if (this->type
== other
->type
)
831 return match_dn(this->encoded
, other
->encoded
, wildcards
);
837 * output handler in printf()
839 static int print(FILE *stream
, const struct printf_info
*info
,
840 const void *const *args
)
842 private_identification_t
*this = *((private_identification_t
**)(args
[0]));
844 chunk_t proper
, buf_chunk
= chunk_from_buf(buf
);
849 return fprintf(stream
, "(null)");
855 return fprintf(stream
, "%%any");
857 if (this->encoded
.len
< sizeof(struct in_addr
) ||
858 inet_ntop(AF_INET
, this->encoded
.ptr
, buf
, sizeof(buf
)) == NULL
)
860 return fprintf(stream
, "(invalid ID_IPV4_ADDR)");
864 return fprintf(stream
, "%s", buf
);
867 if (this->encoded
.len
< sizeof(struct in6_addr
) ||
868 inet_ntop(AF_INET6
, this->encoded
.ptr
, buf
, INET6_ADDRSTRLEN
) == NULL
)
870 return fprintf(stream
, "(invalid ID_IPV6_ADDR)");
874 return fprintf(stream
, "%s", buf
);
878 proper
= sanitize_chunk(this->encoded
);
879 written
= fprintf(stream
, "@%.*s", proper
.len
, proper
.ptr
);
885 proper
= sanitize_chunk(this->encoded
);
886 written
= fprintf(stream
, "%.*s", proper
.len
, proper
.ptr
);
892 snprintf(buf
, sizeof(buf
), "%.*s", this->encoded
.len
, this->encoded
.ptr
);
893 /* TODO: whats returned on failure?*/
894 dntoa(this->encoded
, &buf_chunk
);
895 return fprintf(stream
, "%s", buf
);
898 return fprintf(stream
, "(ASN.1 general Name");
900 return fprintf(stream
, "(KEY_ID)");
901 case ID_DER_ASN1_GN_URI
:
903 proper
= sanitize_chunk(this->encoded
);
904 written
= fprintf(stream
, "%.*s", proper
.len
, proper
.ptr
);
909 return fprintf(stream
, "(unknown ID type: %d)", this->type
);
914 * register printf() handlers
916 static void __attribute__ ((constructor
))print_register()
918 register_printf_function(PRINTF_IDENTIFICATION
, print
, arginfo_ptr
);
922 * Implementation of identification_t.clone.
924 static identification_t
*clone(private_identification_t
*this)
926 private_identification_t
*clone
= identification_create();
928 clone
->type
= this->type
;
929 clone
->encoded
= chunk_clone(this->encoded
);
930 clone
->public.equals
= this->public.equals
;
931 clone
->public.matches
= this->public.matches
;
933 return &clone
->public;
937 * Implementation of identification_t.destroy.
939 static void destroy(private_identification_t
*this)
941 chunk_free(&this->encoded
);
946 * Generic constructor used for the other constructors.
948 static private_identification_t
*identification_create(void)
950 private_identification_t
*this = malloc_thing(private_identification_t
);
952 this->public.get_encoding
= (chunk_t (*) (identification_t
*))get_encoding
;
953 this->public.get_type
= (id_type_t (*) (identification_t
*))get_type
;
954 this->public.contains_wildcards
= (bool (*) (identification_t
*this))contains_wildcards
;
955 this->public.clone
= (identification_t
* (*) (identification_t
*))clone
;
956 this->public.destroy
= (void (*) (identification_t
*))destroy
;
957 /* we use these as defaults, the may be overloaded for special ID types */
958 this->public.equals
= (bool (*) (identification_t
*,identification_t
*))equals_binary
;
959 this->public.matches
= (bool (*) (identification_t
*,identification_t
*,int*))matches_binary
;
961 this->encoded
= chunk_empty
;
967 * Described in header.
969 identification_t
*identification_create_from_string(char *string
)
971 private_identification_t
*this = identification_create();
977 if (strchr(string
, '=') != NULL
)
979 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
980 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
982 if (atodn(string
, &this->encoded
) != SUCCESS
)
987 this->type
= ID_DER_ASN1_DN
;
988 this->public.equals
= (bool (*) (identification_t
*,identification_t
*))equals_dn
;
989 this->public.matches
= (bool (*) (identification_t
*,identification_t
*,int*))matches_dn
;
990 return &this->public;
992 else if (strchr(string
, '@') == NULL
)
994 if (streq(string
, "%any")
995 || streq(string
, "0.0.0.0")
996 || streq(string
, "*")
997 || streq(string
, "::")
998 || streq(string
, "0::0"))
1000 /* any ID will be accepted */
1001 this->type
= ID_ANY
;
1002 this->public.matches
= (bool (*)
1003 (identification_t
*,identification_t
*,int*))matches_any
;
1004 return &this->public;
1008 if (strchr(string
, ':') == NULL
)
1011 struct in_addr address
;
1012 chunk_t chunk
= {(void*)&address
, sizeof(address
)};
1014 if (inet_pton(AF_INET
, string
, &address
) <= 0)
1019 this->encoded
= chunk_clone(chunk
);
1020 this->type
= ID_IPV4_ADDR
;
1021 return &(this->public);
1026 struct in6_addr address
;
1027 chunk_t chunk
= {(void*)&address
, sizeof(address
)};
1029 if (inet_pton(AF_INET6
, string
, &address
) <= 0)
1034 this->encoded
= chunk_clone(chunk
);
1035 this->type
= ID_IPV6_ADDR
;
1036 return &(this->public);
1044 if (*(string
+ 1) == '#')
1046 /* TODO: Pluto handles '#' as hex encoded ID_KEY_ID. */
1052 this->type
= ID_FQDN
;
1053 this->encoded
.ptr
= strdup(string
+ 1);
1054 this->encoded
.len
= strlen(string
+ 1);
1055 this->public.matches
= (bool (*)
1056 (identification_t
*,identification_t
*,int*))matches_string
;
1057 return &(this->public);
1062 this->type
= ID_RFC822_ADDR
;
1063 this->encoded
.ptr
= strdup(string
);
1064 this->encoded
.len
= strlen(string
);
1065 this->public.matches
= (bool (*)
1066 (identification_t
*,identification_t
*,int*))matches_string
;
1067 return &(this->public);
1073 * Described in header.
1075 identification_t
*identification_create_from_encoding(id_type_t type
, chunk_t encoded
)
1077 private_identification_t
*this = identification_create();
1082 this->public.matches
= (bool (*)
1083 (identification_t
*,identification_t
*,int*))matches_any
;
1086 this->public.matches
= (bool (*)
1087 (identification_t
*,identification_t
*,int*))matches_string
;
1089 case ID_RFC822_ADDR
:
1090 this->public.matches
= (bool (*)
1091 (identification_t
*,identification_t
*,int*))matches_string
;
1093 case ID_DER_ASN1_DN
:
1094 this->public.equals
= (bool (*)
1095 (identification_t
*,identification_t
*))equals_dn
;
1096 this->public.matches
= (bool (*)
1097 (identification_t
*,identification_t
*,int*))matches_dn
;
1101 case ID_DER_ASN1_GN
:
1103 case ID_DER_ASN1_GN_URI
:
1108 /* apply encoded chunk */
1111 this->encoded
= chunk_clone(encoded
);
1113 return &(this->public);