2 * Copyright (C) 2016 Andreas Steffen
3 * Copyright (C) 2009-2015 Tobias Brunner
4 * Copyright (C) 2005-2009 Martin Willi
5 * Copyright (C) 2005 Jan Hutter
6 * HSR Hochschule fuer Technik Rapperswil
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include "identification.h"
25 #include <utils/utils.h>
27 #include <asn1/asn1.h>
28 #include <crypto/hashers/hasher.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_DER_ASN1_GN_URI
, ID_KEY_ID
,
52 "ID_DER_ASN1_GN_URI");
53 ENUM_END(id_type_names
, ID_DER_ASN1_GN_URI
);
56 * coding of X.501 distinguished name
64 static const x501rdn_t x501rdns
[] = {
65 {"ND", OID_NAME_DISTINGUISHER
, ASN1_PRINTABLESTRING
},
66 {"UID", OID_PILOT_USERID
, ASN1_PRINTABLESTRING
},
67 {"DC", OID_PILOT_DOMAIN_COMPONENT
, ASN1_PRINTABLESTRING
},
68 {"CN", OID_COMMON_NAME
, ASN1_PRINTABLESTRING
},
69 {"S", OID_SURNAME
, ASN1_PRINTABLESTRING
},
70 {"SN", OID_SERIAL_NUMBER
, ASN1_PRINTABLESTRING
},
71 {"serialNumber", OID_SERIAL_NUMBER
, ASN1_PRINTABLESTRING
},
72 {"C", OID_COUNTRY
, ASN1_PRINTABLESTRING
},
73 {"L", OID_LOCALITY
, ASN1_PRINTABLESTRING
},
74 {"ST", OID_STATE_OR_PROVINCE
, ASN1_PRINTABLESTRING
},
75 {"O", OID_ORGANIZATION
, ASN1_PRINTABLESTRING
},
76 {"OU", OID_ORGANIZATION_UNIT
, ASN1_PRINTABLESTRING
},
77 {"T", OID_TITLE
, ASN1_PRINTABLESTRING
},
78 {"D", OID_DESCRIPTION
, ASN1_PRINTABLESTRING
},
79 {"N", OID_NAME
, ASN1_PRINTABLESTRING
},
80 {"G", OID_GIVEN_NAME
, ASN1_PRINTABLESTRING
},
81 {"I", OID_INITIALS
, ASN1_PRINTABLESTRING
},
82 {"dnQualifier", OID_DN_QUALIFIER
, ASN1_PRINTABLESTRING
},
83 {"pseudonym", OID_PSEUDONYM
, ASN1_PRINTABLESTRING
},
84 {"ID", OID_UNIQUE_IDENTIFIER
, ASN1_PRINTABLESTRING
},
85 {"EN", OID_EMPLOYEE_NUMBER
, ASN1_PRINTABLESTRING
},
86 {"employeeNumber", OID_EMPLOYEE_NUMBER
, ASN1_PRINTABLESTRING
},
87 {"E", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
88 {"Email", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
89 {"emailAddress", OID_EMAIL_ADDRESS
, ASN1_IA5STRING
},
90 {"UN", OID_UNSTRUCTURED_NAME
, ASN1_IA5STRING
},
91 {"unstructuredName", OID_UNSTRUCTURED_NAME
, ASN1_IA5STRING
},
92 {"UA", OID_UNSTRUCTURED_ADDRESS
, ASN1_PRINTABLESTRING
},
93 {"unstructuredAddress", OID_UNSTRUCTURED_ADDRESS
, ASN1_PRINTABLESTRING
},
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 /* next set to parse, if any */
133 /* next sequence in set, if any */
137 METHOD(enumerator_t
, rdn_enumerate
, bool,
138 rdn_enumerator_t
*this, chunk_t
*oid
, u_char
*type
, chunk_t
*data
)
142 /* a DN contains one or more SET, each containing one or more SEQUENCES,
143 * each containing a OID/value RDN */
146 /* no SEQUENCEs in current SET, parse next SET */
147 if (asn1_unwrap(&this->sets
, &this->seqs
) != ASN1_SET
)
152 if (asn1_unwrap(&this->seqs
, &rdn
) == ASN1_SEQUENCE
&&
153 asn1_unwrap(&rdn
, oid
) == ASN1_OID
)
155 int t
= asn1_unwrap(&rdn
, data
);
157 if (t
!= ASN1_INVALID
)
167 * Create an enumerator over all RDNs (oid, string type, data) of a DN
169 static enumerator_t
* create_rdn_enumerator(chunk_t dn
)
175 .enumerate
= (void*)_rdn_enumerate
,
176 .destroy
= (void*)free
,
180 /* a DN is a SEQUENCE, get the first SET of it */
181 if (asn1_unwrap(&dn
, &e
->sets
) == ASN1_SEQUENCE
)
183 e
->seqs
= chunk_empty
;
187 return enumerator_create_empty();
191 * Part enumerator over RDNs
194 /* implements enumerator interface */
196 /* inner RDN enumerator */
198 } rdn_part_enumerator_t
;
200 METHOD(enumerator_t
, rdn_part_enumerate
, bool,
201 rdn_part_enumerator_t
*this, id_part_t
*type
, chunk_t
*data
)
203 int i
, known_oid
, strtype
;
204 chunk_t oid
, inner_data
;
205 static const struct {
209 {OID_COMMON_NAME
, ID_PART_RDN_CN
},
210 {OID_SURNAME
, ID_PART_RDN_S
},
211 {OID_SERIAL_NUMBER
, ID_PART_RDN_SN
},
212 {OID_COUNTRY
, ID_PART_RDN_C
},
213 {OID_LOCALITY
, ID_PART_RDN_L
},
214 {OID_STATE_OR_PROVINCE
, ID_PART_RDN_ST
},
215 {OID_ORGANIZATION
, ID_PART_RDN_O
},
216 {OID_ORGANIZATION_UNIT
, ID_PART_RDN_OU
},
217 {OID_TITLE
, ID_PART_RDN_T
},
218 {OID_DESCRIPTION
, ID_PART_RDN_D
},
219 {OID_NAME
, ID_PART_RDN_N
},
220 {OID_GIVEN_NAME
, ID_PART_RDN_G
},
221 {OID_INITIALS
, ID_PART_RDN_I
},
222 {OID_DN_QUALIFIER
, ID_PART_RDN_DNQ
},
223 {OID_PSEUDONYM
, ID_PART_RDN_PN
},
224 {OID_UNIQUE_IDENTIFIER
, ID_PART_RDN_ID
},
225 {OID_EMAIL_ADDRESS
, ID_PART_RDN_E
},
226 {OID_EMPLOYEE_NUMBER
, ID_PART_RDN_EN
},
229 while (this->inner
->enumerate(this->inner
, &oid
, &strtype
, &inner_data
))
231 known_oid
= asn1_known_oid(oid
);
232 for (i
= 0; i
< countof(oid2part
); i
++)
234 if (oid2part
[i
].oid
== known_oid
)
236 *type
= oid2part
[i
].type
;
245 METHOD(enumerator_t
, rdn_part_enumerator_destroy
, void,
246 rdn_part_enumerator_t
*this)
248 this->inner
->destroy(this->inner
);
252 METHOD(identification_t
, create_part_enumerator
, enumerator_t
*,
253 private_identification_t
*this)
259 rdn_part_enumerator_t
*e
;
262 .inner
= create_rdn_enumerator(this->encoded
),
264 .enumerate
= (void*)_rdn_part_enumerate
,
265 .destroy
= _rdn_part_enumerator_destroy
,
275 return enumerator_create_empty();
280 * Print a separator between two RDNs
282 static inline bool print_separator(char **buf
, size_t *len
)
286 written
= snprintf(*buf
, *len
, ", ");
287 if (written
< 0 || written
>= *len
)
297 * Print a DN with all its RDN in a buffer to present it to the user
299 static void dntoa(chunk_t dn
, char *buf
, size_t len
)
302 chunk_t oid_data
, data
, printable
;
305 bool finished
= FALSE
, empty
= TRUE
;
307 e
= create_rdn_enumerator(dn
);
308 while (e
->enumerate(e
, &oid_data
, &type
, &data
))
312 /* previous RDN was empty but it wasn't the last one */
313 if (finished
&& !print_separator(&buf
, &len
))
319 oid
= asn1_known_oid(oid_data
);
320 if (oid
== OID_UNKNOWN
)
322 written
= snprintf(buf
, len
, "%#B=", &oid_data
);
326 written
= snprintf(buf
, len
,"%s=", oid_names
[oid
].name
);
328 if (written
< 0 || written
>= len
)
336 chunk_printable(data
, &printable
, '?');
339 written
= snprintf(buf
, len
, "%.*s", (int)printable
.len
,
342 chunk_free(&printable
);
343 if (written
< 0 || written
>= len
)
351 { /* we can't calculate if we're finished, assume we are */
354 else if (data
.ptr
+ data
.len
== dn
.ptr
+ dn
.len
)
359 else if (!print_separator(&buf
, &len
))
366 snprintf(buf
, len
, "");
370 snprintf(buf
, len
, "(invalid ID_DER_ASN1_DN)");
376 * Converts an LDAP-style human-readable ASCII-encoded
377 * ASN.1 distinguished name into binary DER-encoded format
379 static status_t
atodn(char *src
, chunk_t
*dn
)
381 /* finite state machine for atodn */
390 chunk_t oid
= chunk_empty
;
391 chunk_t name
= chunk_empty
;
392 chunk_t rdns
[RDN_MAX
];
398 state_t state
= SEARCH_OID
;
399 status_t status
= SUCCESS
;
407 if (!sep
&& *src
== '/')
408 { /* use / as separator if the string starts with a slash */
412 if (*src
!= ' ' && *src
!= '\0')
415 { /* use , as separator by default */
424 if (*src
!= ' ' && *src
!= '=')
432 for (i
= 0; i
< countof(x501rdns
); i
++)
434 if (strlen(x501rdns
[i
].name
) == oid
.len
&&
435 strncasecmp(x501rdns
[i
].name
, oid
.ptr
, oid
.len
) == 0)
443 status
= NOT_SUPPORTED
;
447 /* reset oid and change state */
453 if (*src
== ' ' || *src
== '=')
457 else if (*src
!= sep
&& *src
!= '\0')
470 if (*src
!= sep
&& *src
!= '\0')
480 name
.len
-= whitespace
;
481 rdn_type
= (x501rdns
[i
].type
== ASN1_PRINTABLESTRING
482 && !asn1_is_printablestring(name
))
483 ? ASN1_UTF8STRING
: x501rdns
[i
].type
;
485 if (rdn_count
< RDN_MAX
)
489 rdn_oid
= asn1_build_known_oid(x501rdns
[i
].oid
);
493 asn1_wrap(ASN1_SET
, "m",
494 asn1_wrap(ASN1_SEQUENCE
, "mm",
496 asn1_wrap(rdn_type
, "c", name
)
499 dn_len
+= rdns
[rdn_count
++].len
;
503 status
= INVALID_ARG
;
510 /* reset name and change state */
518 } while (*src
++ != '\0');
520 if (state
== READ_OID
)
521 { /* unterminated OID */
522 status
= INVALID_ARG
;
525 /* build the distinguished name sequence */
528 u_char
*pos
= asn1_build_object(dn
, ASN1_SEQUENCE
, dn_len
);
530 for (i
= 0; i
< rdn_count
; i
++)
532 memcpy(pos
, rdns
[i
].ptr
, rdns
[i
].len
);
537 if (status
!= SUCCESS
)
545 METHOD(identification_t
, get_encoding
, chunk_t
,
546 private_identification_t
*this)
548 return this->encoded
;
551 METHOD(identification_t
, get_type
, id_type_t
,
552 private_identification_t
*this)
557 METHOD(identification_t
, contains_wildcards_dn
, bool,
558 private_identification_t
*this)
560 enumerator_t
*enumerator
;
561 bool contains
= FALSE
;
565 enumerator
= create_part_enumerator(this);
566 while (enumerator
->enumerate(enumerator
, &type
, &data
))
568 if (data
.len
== 1 && data
.ptr
[0] == '*')
574 enumerator
->destroy(enumerator
);
578 METHOD(identification_t
, contains_wildcards_memchr
, bool,
579 private_identification_t
*this)
581 return memchr(this->encoded
.ptr
, '*', this->encoded
.len
) != NULL
;
584 METHOD(identification_t
, hash_binary
, u_int
,
585 private_identification_t
*this, u_int inc
)
589 hash
= chunk_hash_inc(chunk_from_thing(this->type
), inc
);
590 if (this->type
!= ID_ANY
)
592 hash
= chunk_hash_inc(this->encoded
, hash
);
597 METHOD(identification_t
, equals_binary
, bool,
598 private_identification_t
*this, identification_t
*other
)
600 if (this->type
== other
->get_type(other
))
602 if (this->type
== ID_ANY
)
606 return chunk_equals(this->encoded
, other
->get_encoding(other
));
612 * Compare to DNs, for equality if wc == NULL, for match otherwise
614 static bool compare_dn(chunk_t t_dn
, chunk_t o_dn
, int *wc
)
617 chunk_t t_oid
, o_oid
, t_data
, o_data
;
618 u_char t_type
, o_type
;
619 bool t_next
, o_next
, finished
= FALSE
;
627 if (t_dn
.len
!= o_dn
.len
)
632 /* try a binary compare */
633 if (chunk_equals(t_dn
, o_dn
))
638 t
= create_rdn_enumerator(t_dn
);
639 o
= create_rdn_enumerator(o_dn
);
642 t_next
= t
->enumerate(t
, &t_oid
, &t_type
, &t_data
);
643 o_next
= o
->enumerate(o
, &o_oid
, &o_type
, &o_data
);
645 if (!o_next
&& !t_next
)
650 if (o_next
!= t_next
)
654 if (!chunk_equals(t_oid
, o_oid
))
658 if (wc
&& o_data
.len
== 1 && o_data
.ptr
[0] == '*')
664 if (t_data
.len
!= o_data
.len
)
668 if (t_type
== o_type
&&
669 (t_type
== ASN1_PRINTABLESTRING
||
670 (t_type
== ASN1_IA5STRING
&&
671 asn1_known_oid(t_oid
) == OID_EMAIL_ADDRESS
)))
672 { /* ignore case for printableStrings and email RDNs */
673 if (strncasecmp(t_data
.ptr
, o_data
.ptr
, t_data
.len
) != 0)
679 { /* respect case and length for everything else */
680 if (!memeq(t_data
.ptr
, o_data
.ptr
, t_data
.len
))
686 /* the enumerator returns FALSE on parse error, we are finished
687 * if we have reached the end of the DN only */
688 if ((t_data
.ptr
+ t_data
.len
== t_dn
.ptr
+ t_dn
.len
) &&
689 (o_data
.ptr
+ o_data
.len
== o_dn
.ptr
+ o_dn
.len
))
699 METHOD(identification_t
, equals_dn
, bool,
700 private_identification_t
*this, identification_t
*other
)
702 return compare_dn(this->encoded
, other
->get_encoding(other
), NULL
);
705 METHOD(identification_t
, hash_dn
, u_int
,
706 private_identification_t
*this, u_int inc
)
713 hash
= chunk_hash_inc(chunk_from_thing(this->type
), inc
);
714 rdns
= create_rdn_enumerator(this->encoded
);
715 while (rdns
->enumerate(rdns
, &oid
, &type
, &data
))
717 hash
= chunk_hash_inc(data
, chunk_hash_inc(oid
, hash
));
723 METHOD(identification_t
, equals_strcasecmp
, bool,
724 private_identification_t
*this, identification_t
*other
)
726 chunk_t encoded
= other
->get_encoding(other
);
728 /* we do some extra sanity checks to check for invalid IDs with a
729 * terminating null in it. */
730 if (this->encoded
.len
== encoded
.len
&&
731 memchr(this->encoded
.ptr
, 0, this->encoded
.len
) == NULL
&&
732 memchr(encoded
.ptr
, 0, encoded
.len
) == NULL
&&
733 strncasecmp(this->encoded
.ptr
, encoded
.ptr
, this->encoded
.len
) == 0)
740 METHOD(identification_t
, matches_binary
, id_match_t
,
741 private_identification_t
*this, identification_t
*other
)
743 if (other
->get_type(other
) == ID_ANY
)
747 if (this->type
== other
->get_type(other
) &&
748 chunk_equals(this->encoded
, other
->get_encoding(other
)))
750 return ID_MATCH_PERFECT
;
752 return ID_MATCH_NONE
;
755 METHOD(identification_t
, matches_string
, id_match_t
,
756 private_identification_t
*this, identification_t
*other
)
758 chunk_t encoded
= other
->get_encoding(other
);
759 u_int len
= encoded
.len
;
761 if (other
->get_type(other
) == ID_ANY
)
765 if (this->type
!= other
->get_type(other
))
767 return ID_MATCH_NONE
;
769 /* try a equals check first */
770 if (equals_strcasecmp(this, other
))
772 return ID_MATCH_PERFECT
;
774 if (len
== 0 || this->encoded
.len
< len
)
776 return ID_MATCH_NONE
;
779 /* check for single wildcard at the head of the string */
780 if (*encoded
.ptr
== '*')
782 /* single asterisk matches any string */
784 { /* not better than ID_ANY */
787 if (strncasecmp(this->encoded
.ptr
+ this->encoded
.len
- len
,
788 encoded
.ptr
+ 1, len
) == 0)
790 return ID_MATCH_ONE_WILDCARD
;
793 return ID_MATCH_NONE
;
796 METHOD(identification_t
, matches_any
, id_match_t
,
797 private_identification_t
*this, identification_t
*other
)
799 if (other
->get_type(other
) == ID_ANY
)
803 return ID_MATCH_NONE
;
806 METHOD(identification_t
, matches_dn
, id_match_t
,
807 private_identification_t
*this, identification_t
*other
)
811 if (other
->get_type(other
) == ID_ANY
)
816 if (this->type
== other
->get_type(other
))
818 if (compare_dn(this->encoded
, other
->get_encoding(other
), &wc
))
820 wc
= min(wc
, ID_MATCH_ONE_WILDCARD
- ID_MATCH_MAX_WILDCARDS
);
821 return ID_MATCH_PERFECT
- wc
;
824 return ID_MATCH_NONE
;
828 * Transform netmask to CIDR bits
830 static int netmask_to_cidr(char *netmask
, size_t address_size
)
835 for (i
= 0; i
< address_size
; i
++)
859 METHOD(identification_t
, matches_range
, id_match_t
,
860 private_identification_t
*this, identification_t
*other
)
862 chunk_t other_encoding
;
863 uint8_t *address
, *from
, *to
, *network
, *netmask
;
864 size_t address_size
= 0;
865 int netbits
, range_sign
, i
;
867 if (other
->get_type(other
) == ID_ANY
)
871 if (this->type
== other
->get_type(other
) &&
872 chunk_equals(this->encoded
, other
->get_encoding(other
)))
874 return ID_MATCH_PERFECT
;
876 if ((this->type
== ID_IPV4_ADDR
&&
877 other
->get_type(other
) == ID_IPV4_ADDR_SUBNET
))
879 address_size
= sizeof(struct in_addr
);
881 else if ((this->type
== ID_IPV6_ADDR
&&
882 other
->get_type(other
) == ID_IPV6_ADDR_SUBNET
))
884 address_size
= sizeof(struct in6_addr
);
888 other_encoding
= other
->get_encoding(other
);
889 if (this->encoded
.len
!= address_size
||
890 other_encoding
.len
!= 2 * address_size
)
892 return ID_MATCH_NONE
;
894 address
= this->encoded
.ptr
;
895 network
= other_encoding
.ptr
;
896 netmask
= other_encoding
.ptr
+ address_size
;
897 netbits
= netmask_to_cidr(netmask
, address_size
);
901 return ID_MATCH_MAX_WILDCARDS
;
903 if (netbits
== 8 * address_size
)
905 return memeq(address
, network
, address_size
) ?
906 ID_MATCH_PERFECT
: ID_MATCH_NONE
;
908 for (i
= 0; i
< (netbits
+ 7)/8; i
++)
910 if ((address
[i
] ^ network
[i
]) & netmask
[i
])
912 return ID_MATCH_NONE
;
915 return ID_MATCH_ONE_WILDCARD
;
917 if ((this->type
== ID_IPV4_ADDR
&&
918 other
->get_type(other
) == ID_IPV4_ADDR_RANGE
))
920 address_size
= sizeof(struct in_addr
);
922 else if ((this->type
== ID_IPV6_ADDR
&&
923 other
->get_type(other
) == ID_IPV6_ADDR_RANGE
))
925 address_size
= sizeof(struct in6_addr
);
929 other_encoding
= other
->get_encoding(other
);
930 if (this->encoded
.len
!= address_size
||
931 other_encoding
.len
!= 2 * address_size
)
933 return ID_MATCH_NONE
;
935 address
= this->encoded
.ptr
;
936 from
= other_encoding
.ptr
;
937 to
= other_encoding
.ptr
+ address_size
;
939 range_sign
= memcmp(to
, from
, address_size
);
941 { /* to is smaller than from */
942 return ID_MATCH_NONE
;
945 /* check lower bound */
946 for (i
= 0; i
< address_size
; i
++)
948 if (address
[i
] != from
[i
])
950 if (address
[i
] < from
[i
])
952 return ID_MATCH_NONE
;
958 /* check upper bound */
959 for (i
= 0; i
< address_size
; i
++)
961 if (address
[i
] != to
[i
])
963 if (address
[i
] > to
[i
])
965 return ID_MATCH_NONE
;
970 return range_sign ? ID_MATCH_ONE_WILDCARD
: ID_MATCH_PERFECT
;
972 return ID_MATCH_NONE
;
976 * Described in header.
978 int identification_printf_hook(printf_hook_data_t
*data
,
979 printf_hook_spec_t
*spec
, const void *const *args
)
981 private_identification_t
*this = *((private_identification_t
**)(args
[0]));
985 size_t written
, len
, address_size
;
989 return print_in_hook(data
, "%*s", spec
->width
, "(null)");
995 snprintf(buf
, BUF_LEN
, "%%any");
998 if (this->encoded
.len
< sizeof(struct in_addr
) ||
999 inet_ntop(AF_INET
, this->encoded
.ptr
, buf
, BUF_LEN
) == NULL
)
1001 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV4_ADDR)");
1004 case ID_IPV4_ADDR_SUBNET
:
1005 address_size
= sizeof(struct in_addr
);
1006 if (this->encoded
.len
< 2 * address_size
||
1007 inet_ntop(AF_INET
, this->encoded
.ptr
, buf
, BUF_LEN
) == NULL
)
1009 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV4_ADDR_SUBNET)");
1012 written
= strlen(buf
);
1013 snprintf(buf
+ written
, BUF_LEN
- written
, "/%d",
1014 netmask_to_cidr(this->encoded
.ptr
+ address_size
,
1017 case ID_IPV4_ADDR_RANGE
:
1018 address_size
= sizeof(struct in_addr
);
1019 if (this->encoded
.len
< 2 * address_size
||
1020 inet_ntop(AF_INET
, this->encoded
.ptr
, buf
, BUF_LEN
) == NULL
)
1022 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV4_ADDR_RANGE)");
1025 written
= strlen(buf
);
1026 pos
= buf
+ written
;
1027 len
= BUF_LEN
- written
;
1028 written
= snprintf(pos
, len
, "-");
1029 if (written
< 0 || written
>= len
||
1030 inet_ntop(AF_INET
, this->encoded
.ptr
+ address_size
,
1031 pos
+ written
, len
- written
) == NULL
)
1033 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV4_ADDR_RANGE)");
1037 if (this->encoded
.len
< sizeof(struct in6_addr
) ||
1038 inet_ntop(AF_INET6
, this->encoded
.ptr
, buf
, BUF_LEN
) == NULL
)
1040 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV6_ADDR)");
1043 case ID_IPV6_ADDR_SUBNET
:
1044 address_size
= sizeof(struct in6_addr
);
1045 if (this->encoded
.len
< 2 * address_size
||
1046 inet_ntop(AF_INET6
, this->encoded
.ptr
, buf
, BUF_LEN
) == NULL
)
1048 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV6_ADDR_SUBNET)");
1052 written
= strlen(buf
);
1053 snprintf(buf
+ written
, BUF_LEN
- written
, "/%d",
1054 netmask_to_cidr(this->encoded
.ptr
+ address_size
,
1058 case ID_IPV6_ADDR_RANGE
:
1059 address_size
= sizeof(struct in6_addr
);
1060 if (this->encoded
.len
< 2 * address_size
||
1061 inet_ntop(AF_INET6
, this->encoded
.ptr
, buf
, BUF_LEN
) == NULL
)
1063 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV6_ADDR_RANGE)");
1066 written
= strlen(buf
);
1067 pos
= buf
+ written
;
1068 len
= BUF_LEN
- written
;
1069 written
= snprintf(pos
, len
, "-");
1070 if (written
< 0 || written
>= len
||
1071 inet_ntop(AF_INET6
, this->encoded
.ptr
+ address_size
,
1072 pos
+ written
, len
- written
) == NULL
)
1074 snprintf(buf
, BUF_LEN
, "(invalid ID_IPV6_ADDR_RANGE)");
1078 case ID_RFC822_ADDR
:
1079 case ID_DER_ASN1_GN_URI
:
1080 chunk_printable(this->encoded
, &proper
, '?');
1081 snprintf(buf
, BUF_LEN
, "%.*s", (int)proper
.len
, proper
.ptr
);
1082 chunk_free(&proper
);
1084 case ID_DER_ASN1_DN
:
1085 dntoa(this->encoded
, buf
, BUF_LEN
);
1087 case ID_DER_ASN1_GN
:
1088 snprintf(buf
, BUF_LEN
, "(ASN.1 general name)");
1091 if (chunk_printable(this->encoded
, NULL
, '?') &&
1092 this->encoded
.len
!= HASH_SIZE_SHA1
)
1093 { /* fully printable, use ascii version */
1094 snprintf(buf
, BUF_LEN
, "%.*s", (int)this->encoded
.len
,
1098 { /* not printable, hex dump */
1099 snprintf(buf
, BUF_LEN
, "%#B", &this->encoded
);
1103 snprintf(buf
, BUF_LEN
, "(unknown ID type: %d)", this->type
);
1108 return print_in_hook(data
, "%-*s", spec
->width
, buf
);
1110 return print_in_hook(data
, "%*s", spec
->width
, buf
);
1113 METHOD(identification_t
, clone_
, identification_t
*,
1114 private_identification_t
*this)
1116 private_identification_t
*clone
= malloc_thing(private_identification_t
);
1118 memcpy(clone
, this, sizeof(private_identification_t
));
1119 if (this->encoded
.len
)
1121 clone
->encoded
= chunk_clone(this->encoded
);
1123 return &clone
->public;
1126 METHOD(identification_t
, destroy
, void,
1127 private_identification_t
*this)
1129 chunk_free(&this->encoded
);
1134 * Generic constructor used for the other constructors.
1136 static private_identification_t
*identification_create(id_type_t type
)
1138 private_identification_t
*this;
1142 .get_encoding
= _get_encoding
,
1143 .get_type
= _get_type
,
1144 .create_part_enumerator
= _create_part_enumerator
,
1146 .destroy
= _destroy
,
1154 this->public.hash
= _hash_binary
;
1155 this->public.matches
= _matches_any
;
1156 this->public.equals
= _equals_binary
;
1157 this->public.contains_wildcards
= return_true
;
1160 case ID_RFC822_ADDR
:
1161 this->public.hash
= _hash_binary
;
1162 this->public.matches
= _matches_string
;
1163 this->public.equals
= _equals_strcasecmp
;
1164 this->public.contains_wildcards
= _contains_wildcards_memchr
;
1166 case ID_DER_ASN1_DN
:
1167 this->public.hash
= _hash_dn
;
1168 this->public.equals
= _equals_dn
;
1169 this->public.matches
= _matches_dn
;
1170 this->public.contains_wildcards
= _contains_wildcards_dn
;
1174 this->public.hash
= _hash_binary
;
1175 this->public.equals
= _equals_binary
;
1176 this->public.matches
= _matches_range
;
1177 this->public.contains_wildcards
= return_false
;
1180 this->public.hash
= _hash_binary
;
1181 this->public.equals
= _equals_binary
;
1182 this->public.matches
= _matches_binary
;
1183 this->public.contains_wildcards
= return_false
;
1190 * Create an identity for a specific type, determined by prefix
1192 static private_identification_t
* create_from_string_with_prefix_type(char *str
)
1198 { "ipv4:", ID_IPV4_ADDR
},
1199 { "ipv6:", ID_IPV6_ADDR
},
1200 { "ipv4net:", ID_IPV4_ADDR_SUBNET
},
1201 { "ipv6net:", ID_IPV6_ADDR_SUBNET
},
1202 { "ipv4range:", ID_IPV4_ADDR_RANGE
},
1203 { "ipv6range:", ID_IPV6_ADDR_RANGE
},
1204 { "rfc822:", ID_RFC822_ADDR
},
1205 { "email:", ID_RFC822_ADDR
},
1206 { "userfqdn:", ID_USER_FQDN
},
1207 { "fqdn:", ID_FQDN
},
1208 { "dns:", ID_FQDN
},
1209 { "asn1dn:", ID_DER_ASN1_DN
},
1210 { "asn1gn:", ID_DER_ASN1_GN
},
1211 { "keyid:", ID_KEY_ID
},
1213 private_identification_t
*this;
1216 for (i
= 0; i
< countof(prefixes
); i
++)
1218 if (strcasepfx(str
, prefixes
[i
].str
))
1220 this = identification_create(prefixes
[i
].type
);
1221 str
+= strlen(prefixes
[i
].str
);
1224 this->encoded
= chunk_from_hex(chunk_from_str(str
+ 1), NULL
);
1228 this->encoded
= chunk_clone(chunk_from_str(str
));
1237 * Create an identity for a specific type, determined by a numerical prefix
1239 * The prefix is of the form "{x}:", where x denotes the numerical identity
1242 static private_identification_t
* create_from_string_with_num_type(char *str
)
1244 private_identification_t
*this;
1252 type
= strtoul(str
, &str
, 0);
1253 if (errno
|| *str
++ != '}' || *str
++ != ':')
1257 this = identification_create(type
);
1260 this->encoded
= chunk_from_hex(chunk_from_str(str
+ 1), NULL
);
1264 this->encoded
= chunk_clone(chunk_from_str(str
));
1270 * Convert to an IPv4/IPv6 host address, subnet or address range
1272 static private_identification_t
* create_ip_address_from_string(char *string
,
1275 private_identification_t
*this;
1276 uint8_t encoding
[32];
1277 uint8_t *str
, *pos
, *address
, *to_address
, *netmask
;
1278 size_t address_size
;
1280 bool has_subnet
= FALSE
, has_range
= FALSE
;
1283 address_size
= is_ipv4 ?
sizeof(struct in_addr
) : sizeof(struct in6_addr
);
1285 str
= strdup(string
);
1286 pos
= strchr(str
, '/');
1288 { /* separate IP address from optional netmask */
1295 pos
= strchr(str
, '-');
1297 { /* separate lower address from upper address of IP range */
1303 if (inet_pton(is_ipv4 ? AF_INET
: AF_INET6
, str
, address
) != 1)
1310 { /* is IP subnet */
1311 bits
= atoi(pos
+ 1);
1312 if (bits
> 8 * address_size
)
1319 netmask
= encoding
+ address_size
;
1321 for (i
= 0; i
< address_size
; i
++)
1330 *netmask
= 0xff << (8 - bits
);
1337 *address
++ &= *netmask
++;
1339 this = identification_create(is_ipv4 ? ID_IPV4_ADDR_SUBNET
:
1340 ID_IPV6_ADDR_SUBNET
);
1341 this->encoded
= chunk_clone(chunk_create(encoding
, 2 * address_size
));
1345 to_address
= encoding
+ address_size
;
1347 if (inet_pton(is_ipv4 ? AF_INET
: AF_INET6
, pos
+ 1, to_address
) != 1)
1352 for (i
= 0; i
< address_size
; i
++)
1354 if (address
[i
] != to_address
[i
])
1356 if (address
[i
] > to_address
[i
])
1364 this = identification_create(is_ipv4 ? ID_IPV4_ADDR_RANGE
:
1365 ID_IPV6_ADDR_RANGE
);
1366 this->encoded
= chunk_clone(chunk_create(encoding
, 2 * address_size
));
1369 { /* is IP host address */
1370 this = identification_create(is_ipv4 ? ID_IPV4_ADDR
: ID_IPV6_ADDR
);
1371 this->encoded
= chunk_clone(chunk_create(encoding
, address_size
));
1379 * Described in header.
1381 identification_t
*identification_create_from_string(char *string
)
1383 private_identification_t
*this;
1390 this = create_from_string_with_prefix_type(string
);
1393 return &this->public;
1395 this = create_from_string_with_num_type(string
);
1398 return &this->public;
1400 if (strchr(string
, '=') != NULL
)
1402 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1403 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1405 if (atodn(string
, &encoded
) == SUCCESS
)
1407 this = identification_create(ID_DER_ASN1_DN
);
1408 this->encoded
= encoded
;
1412 this = identification_create(ID_KEY_ID
);
1413 this->encoded
= chunk_from_str(strdup(string
));
1415 return &this->public;
1417 else if (strchr(string
, '@') == NULL
)
1419 if (streq(string
, "")
1420 || streq(string
, "%any")
1421 || streq(string
, "%any6")
1422 || streq(string
, "0.0.0.0")
1423 || streq(string
, "*")
1424 || streq(string
, "::")
1425 || streq(string
, "0::0"))
1427 /* any ID will be accepted */
1428 this = identification_create(ID_ANY
);
1429 return &this->public;
1433 if (strchr(string
, ':') == NULL
)
1435 /* IPv4 address or subnet */
1436 this = create_ip_address_from_string(string
, TRUE
);
1438 { /* not IPv4, mostly FQDN */
1439 this = identification_create(ID_FQDN
);
1440 this->encoded
= chunk_from_str(strdup(string
));
1442 return &this->public;
1446 /* IPv6 address or subnet */
1447 this = create_ip_address_from_string(string
, FALSE
);
1449 { /* not IPv4/6 fallback to KEY_ID */
1450 this = identification_create(ID_KEY_ID
);
1451 this->encoded
= chunk_from_str(strdup(string
));
1453 return &this->public;
1464 this = identification_create(ID_KEY_ID
);
1465 this->encoded
= chunk_from_hex(chunk_from_str(string
+ 1), NULL
);
1466 return &this->public;
1468 else if (*string
== '@')
1470 this = identification_create(ID_USER_FQDN
);
1471 this->encoded
= chunk_clone(chunk_from_str(string
+ 1));
1472 return &this->public;
1476 this = identification_create(ID_FQDN
);
1477 this->encoded
= chunk_clone(chunk_from_str(string
));
1478 return &this->public;
1483 this = identification_create(ID_RFC822_ADDR
);
1484 this->encoded
= chunk_from_str(strdup(string
));
1485 return &this->public;
1491 * Described in header.
1493 identification_t
* identification_create_from_data(chunk_t data
)
1495 char buf
[data
.len
+ 1];
1499 return identification_create_from_encoding(ID_DER_ASN1_DN
, data
);
1503 /* use string constructor */
1504 snprintf(buf
, sizeof(buf
), "%.*s", (int)data
.len
, data
.ptr
);
1505 return identification_create_from_string(buf
);
1510 * Described in header.
1512 identification_t
*identification_create_from_encoding(id_type_t type
,
1515 private_identification_t
*this = identification_create(type
);
1517 /* apply encoded chunk */
1520 this->encoded
= chunk_clone(encoded
);
1522 return &(this->public);
1526 * Described in header.
1528 identification_t
*identification_create_from_sockaddr(sockaddr_t
*sockaddr
)
1530 switch (sockaddr
->sa_family
)
1534 struct in_addr
*addr
= &(((struct sockaddr_in
*)sockaddr
)->sin_addr
);
1536 return identification_create_from_encoding(ID_IPV4_ADDR
,
1537 chunk_create((u_char
*)addr
, sizeof(struct in_addr
)));
1541 struct in6_addr
*addr
= &(((struct sockaddr_in6
*)sockaddr
)->sin6_addr
);
1543 return identification_create_from_encoding(ID_IPV6_ADDR
,
1544 chunk_create((u_char
*)addr
, sizeof(struct in6_addr
)));
1548 private_identification_t
*this = identification_create(ID_ANY
);
1550 return &(this->public);