5bbf5312d3562647b6073e5364c6adb3f6e3f847
1 /* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
2 * Copyright (C) 1999-2001 D. Hugh Redelmeier
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
25 #ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
26 # define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
28 #include <sys/queue.h>
31 #include <ipsec_policy.h>
33 #include "constants.h"
37 #include "connections.h"
41 const struct id empty_id
; /* ID_NONE */
43 enum myid_state myid_state
= MYID_UNKNOWN
;
44 struct id myids
[MYID_SPECIFIED
+1]; /* %myid */
45 char *myid_str
[MYID_SPECIFIED
+1]; /* string form of IDs */
47 /* initialize id module
48 * Fills in myid from environment variable IPSECmyid or defaultrouteaddr
53 passert(empty_id
.kind
== ID_NONE
);
54 myid_state
= MYID_UNKNOWN
;
58 for (s
= MYID_UNKNOWN
; s
<= MYID_SPECIFIED
; s
++)
64 set_myid(MYID_SPECIFIED
, getenv("IPSECmyid"));
65 set_myid(MYID_IP
, getenv("defaultrouteaddr"));
77 for (s
= MYID_UNKNOWN
; s
<= MYID_SPECIFIED
; s
++)
79 free_id_content(&myids
[s
]);
85 calc_myid_str(enum myid_state s
)
87 /* preformat the ID name */
90 idtoa(&myids
[s
], buf
, BUF_LEN
);
91 replace(myid_str
[s
], clone_str(buf
, "myid string"));
96 set_myid(enum myid_state s
, char *idstr
)
101 err_t ugh
= atoid(idstr
, &id
, FALSE
);
105 loglog(RC_BADID
, "myid malformed: %s \"%s\"", ugh
, idstr
);
109 free_id_content(&myids
[s
]);
110 unshare_id_content(&id
);
112 if (s
== MYID_SPECIFIED
)
113 myid_state
= MYID_SPECIFIED
;
123 char FQDN
[HOST_NAME_MAX
+ 1];
124 int r
= gethostname(FQDN
, sizeof(FQDN
));
126 free_id_content(&myids
[MYID_HOSTNAME
]);
127 myids
[MYID_HOSTNAME
] = empty_id
;
130 log_errno((e
, "gethostname() failed in set_myFQDN"));
134 FQDN
[sizeof(FQDN
) - 1] = '\0'; /* insurance */
137 size_t len
= strlen(FQDN
);
139 if (len
> 0 && FQDN
[len
-1] == '.')
141 /* nuke trailing . */
146 if (!strcaseeq(FQDN
, "localhost.localdomain"))
148 clonetochunk(myids
[MYID_HOSTNAME
].name
, FQDN
, strlen(FQDN
), "my FQDN");
149 myids
[MYID_HOSTNAME
].kind
= ID_FQDN
;
150 calc_myid_str(MYID_HOSTNAME
);
156 show_myid_status(void)
160 (void)idtoa(&myids
[myid_state
], idstr
, sizeof(idstr
));
161 whack_log(RC_COMMENT
, "%%myid = %s", idstr
);
164 /* Convert textual form of id into a (temporary) struct id.
165 * Note that if the id is to be kept, unshare_id_content will be necessary.
168 atoid(char *src
, struct id
*id
, bool myid_ok
)
174 if (myid_ok
&& streq("%myid", src
))
178 else if (strchr(src
, '=') != NULL
)
180 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */
181 id
->kind
= ID_DER_ASN1_DN
;
182 id
->name
.ptr
= temporary_cyclic_buffer(); /* assign temporary buffer */
184 /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN
185 * discard optional @ character in front of DN
187 ugh
= atodn((*src
== '@')?src
+1:src
, &id
->name
);
189 else if (strchr(src
, '@') == NULL
)
191 if (streq(src
, "%any") || streq(src
, "0.0.0.0"))
193 /* any ID will be accepted */
198 /* !!! this test is not sufficient for distinguishing address families.
199 * We need a notation to specify that a FQDN is to be resolved to IPv6.
201 const struct af_info
*afi
= strchr(src
, ':') == NULL
202 ?
&af_inet4_info
: &af_inet6_info
;
204 id
->kind
= afi
->id_addr
;
205 ugh
= ttoaddr(src
, 0, afi
->af
, &id
->ip_addr
);
214 /* if there is a second specifier (#) on the line
215 * we interprete this as ID_KEY_ID
217 id
->kind
= ID_KEY_ID
;
219 /* discard @~, convert from hex to bin */
220 ugh
= ttodata(src
+2, 0, 16, id
->name
.ptr
, strlen(src
), &id
->name
.len
);
222 else if (*(src
+1) == '~')
224 /* if there is a second specifier (~) on the line
225 * we interprete this as a binary ID_DER_ASN1_DN
227 id
->kind
= ID_DER_ASN1_DN
;
229 /* discard @~, convert from hex to bin */
230 ugh
= ttodata(src
+2, 0, 16, id
->name
.ptr
, strlen(src
), &id
->name
.len
);
235 id
->name
.ptr
= src
+1; /* discard @ */
236 id
->name
.len
= strlen(src
)-1;
241 /* We leave in @, as per DOI 4.6.2.4
242 * (but DNS wants . instead).
244 id
->kind
= ID_USER_FQDN
;
246 id
->name
.len
= strlen(src
);
254 * Converts a binary key ID into hexadecimal format
257 keyidtoa(char *dst
, size_t dstlen
, chunk_t keyid
)
259 int n
= datatot(keyid
.ptr
, keyid
.len
, 'x', dst
, dstlen
);
260 return (((size_t)n
< dstlen
)? n
: dstlen
) - 1;
264 iptoid(const ip_address
*ip
, struct id
*id
)
268 switch (addrtypeof(ip
))
271 id
->kind
= ID_IPV4_ADDR
;
274 id
->kind
= ID_IPV6_ADDR
;
277 bad_case(addrtypeof(ip
));
283 idtoa(const struct id
*id
, char *dst
, size_t dstlen
)
287 id
= resolve_myid(id
);
291 n
= snprintf(dst
, dstlen
, "(none)");
295 n
= (int)addrtot(&id
->ip_addr
, 0, dst
, dstlen
) - 1;
298 n
= snprintf(dst
, dstlen
, "@%.*s", (int)id
->name
.len
, id
->name
.ptr
);
301 n
= snprintf(dst
, dstlen
, "%.*s", (int)id
->name
.len
, id
->name
.ptr
);
304 n
= dntoa(dst
, dstlen
, id
->name
);
307 n
= keyidtoa(dst
, dstlen
, id
->name
);
310 n
= snprintf(dst
, dstlen
, "unknown id kind %d", id
->kind
);
314 /* "Sanitize" string so that log isn't endangered:
315 * replace unprintable characters with '?'.
319 for ( ; *dst
!= '\0'; dst
++)
327 /* Replace the shell metacharacters ', \, ", `, and $ in a character string
328 * by escape sequences consisting of their octal values
331 escape_metachar(const char *src
, char *dst
, size_t dstlen
)
333 while (*src
!= '\0' && dstlen
> 4)
342 sprintf(dst
,"\\%s%o", (*src
< 64)?
"0":"", *src
);
356 /* Make private copy of string in struct id.
357 * This is needed if the result of atoid is to be kept.
360 unshare_id_content(struct id
*id
)
368 id
->name
.ptr
= clone_bytes(id
->name
.ptr
, id
->name
.len
, "keep id name");
381 free_id_content(struct id
*id
)
389 freeanychunk(id
->name
);
401 /* compare two struct id values */
403 same_id(const struct id
*a
, const struct id
*b
)
407 if (a
->kind
!= b
->kind
)
412 return TRUE
; /* kind of vacuous */
416 return sameaddr(&a
->ip_addr
, &b
->ip_addr
);
421 * - case should be ignored
422 * - trailing "." should be ignored (even if the only character?)
425 size_t al
= a
->name
.len
428 while (al
> 0 && a
->name
.ptr
[al
- 1] == '.')
430 while (bl
> 0 && b
->name
.ptr
[bl
- 1] == '.')
433 && strncasecmp(a
->name
.ptr
, b
->name
.ptr
, al
) == 0;
437 return same_dn(a
->name
, b
->name
);
440 return a
->name
.len
== b
->name
.len
441 && memeq(a
->name
.ptr
, b
->name
.ptr
, a
->name
.len
);
449 /* compare two struct id values, DNs can contain wildcards */
451 match_id(const struct id
*a
, const struct id
*b
, int *wildcards
)
453 if (b
->kind
== ID_NONE
)
455 *wildcards
= MAX_WILDCARDS
;
458 if (a
->kind
!= b
->kind
)
460 if (a
->kind
== ID_DER_ASN1_DN
)
461 return match_dn(a
->name
, b
->name
, wildcards
);
465 return same_id(a
, b
);
469 /* count the numer of wildcards in an id */
471 id_count_wildcards(const struct id
*id
)
476 return MAX_WILDCARDS
;
478 return dn_count_wildcards(id
->name
);
484 /* build an ID payload
485 * Note: no memory is allocated for the body of the payload (tl->ptr).
486 * We assume it will end up being a pointer into a sufficiently
487 * stable datastructure. It only needs to last a short time.
490 build_id_payload(struct isakmp_ipsec_id
*hd
, chunk_t
*tl
, struct end
*end
)
492 const struct id
*id
= resolve_myid(&end
->id
);
495 hd
->isaiid_idtype
= id
->kind
;
499 hd
->isaiid_idtype
= aftoinfo(addrtypeof(&end
->host_addr
))->id_addr
;
500 tl
->len
= addrbytesptr(&end
->host_addr
501 , (const unsigned char **)&tl
->ptr
); /* sets tl->ptr too */
511 tl
->len
= addrbytesptr(&id
->ip_addr
512 , (const unsigned char **)&tl
->ptr
); /* sets tl->ptr too */