diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2009-06-23 11:35:38 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2009-06-23 11:35:38 +0000 |
commit | 7c52c3f35cdbdff58443b994f2f33d13b4d81f57 (patch) | |
tree | e54a27979ea72ec41702bec2984c2eadac3b8862 /src/pluto/id.c | |
parent | 4ef45ba0404dac3773e83af995a5ec584b23d633 (diff) | |
download | vyos-strongswan-7c52c3f35cdbdff58443b994f2f33d13b4d81f57.tar.gz vyos-strongswan-7c52c3f35cdbdff58443b994f2f33d13b4d81f57.zip |
Updated to new upstream version.
Diffstat (limited to 'src/pluto/id.c')
-rw-r--r-- | src/pluto/id.c | 672 |
1 files changed, 343 insertions, 329 deletions
diff --git a/src/pluto/id.c b/src/pluto/id.c index 8db322a5e..f34775e68 100644 --- a/src/pluto/id.c +++ b/src/pluto/id.c @@ -10,8 +10,6 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * RCSID $Id: id.c 3252 2007-10-06 21:24:50Z andreas $ */ #include <stdlib.h> @@ -22,13 +20,12 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> -#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */ -# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */ +#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */ +# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */ #endif #include <sys/queue.h> #include <freeswan.h> -#include <ipsec_policy.h> #include "constants.h" #include "defs.h" @@ -38,10 +35,10 @@ #include "packet.h" #include "whack.h" -const struct id empty_id; /* ID_NONE */ +const struct id empty_id; /* ID_ANY */ enum myid_state myid_state = MYID_UNKNOWN; -struct id myids[MYID_SPECIFIED+1]; /* %myid */ +struct id myids[MYID_SPECIFIED+1]; /* %myid */ char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */ /* initialize id module @@ -50,100 +47,117 @@ char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */ void init_id(void) { - passert(empty_id.kind == ID_NONE); - myid_state = MYID_UNKNOWN; - { + passert(empty_id.kind == ID_ANY); + myid_state = MYID_UNKNOWN; + { + enum myid_state s; + + for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++) + { + myids[s] = empty_id; + myid_str[s] = NULL; + } + } + set_myid(MYID_SPECIFIED, getenv("IPSECmyid")); + set_myid(MYID_IP, getenv("defaultrouteaddr")); + set_myFQDN(); +} + +/* + * free id module + */ +void +free_id(void) +{ enum myid_state s; for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++) { - myids[s] = empty_id; - myid_str[s] = NULL; + free_id_content(&myids[s]); + free(myid_str[s]); } - } - set_myid(MYID_SPECIFIED, getenv("IPSECmyid")); - set_myid(MYID_IP, getenv("defaultrouteaddr")); - set_myFQDN(); } static void calc_myid_str(enum myid_state s) { - /* preformat the ID name */ - char buf[BUF_LEN]; + /* preformat the ID name */ + char buf[BUF_LEN]; - idtoa(&myids[s], buf, BUF_LEN); - replace(myid_str[s], clone_str(buf, "myid string")); + idtoa(&myids[s], buf, BUF_LEN); + replace(myid_str[s], clone_str(buf)); } void set_myid(enum myid_state s, char *idstr) { - if (idstr != NULL) - { - struct id id; - err_t ugh = atoid(idstr, &id, FALSE); - - if (ugh != NULL) - { - loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr); - } - else + if (idstr != NULL) { - free_id_content(&myids[s]); - unshare_id_content(&id); - myids[s] = id; - if (s == MYID_SPECIFIED) - myid_state = MYID_SPECIFIED; - - calc_myid_str(s); + struct id id; + err_t ugh = atoid(idstr, &id, FALSE); + + if (ugh != NULL) + { + loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr); + } + else + { + free_id_content(&myids[s]); + unshare_id_content(&id); + myids[s] = id; + if (s == MYID_SPECIFIED) + myid_state = MYID_SPECIFIED; + + calc_myid_str(s); + } } - } } void set_myFQDN(void) { - char FQDN[HOST_NAME_MAX + 1]; - int r = gethostname(FQDN, sizeof(FQDN)); - - free_id_content(&myids[MYID_HOSTNAME]); - myids[MYID_HOSTNAME] = empty_id; - if (r != 0) - { - log_errno((e, "gethostname() failed in set_myFQDN")); - } - else - { - FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */ + char FQDN[HOST_NAME_MAX + 1]; + int r = gethostname(FQDN, sizeof(FQDN)); + free_id_content(&myids[MYID_HOSTNAME]); + myids[MYID_HOSTNAME] = empty_id; + if (r != 0) { - size_t len = strlen(FQDN); - - if (len > 0 && FQDN[len-1] == '.') - { - /* nuke trailing . */ - FQDN[len-1]='\0'; - } + log_errno((e, "gethostname() failed in set_myFQDN")); } - - if (!strcaseeq(FQDN, "localhost.localdomain")) + else { - clonetochunk(myids[MYID_HOSTNAME].name, FQDN, strlen(FQDN), "my FQDN"); - myids[MYID_HOSTNAME].kind = ID_FQDN; - calc_myid_str(MYID_HOSTNAME); + FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */ + + { + size_t len = strlen(FQDN); + + if (len > 0 && FQDN[len-1] == '.') + { + /* nuke trailing . */ + FQDN[len-1]='\0'; + } + } + + if (!strcaseeq(FQDN, "localhost.localdomain")) + { + chunk_t myid_name = { FQDN, strlen(FQDN) }; + + myids[MYID_HOSTNAME].name = chunk_clone(myid_name); + myids[MYID_HOSTNAME].kind = ID_FQDN; + calc_myid_str(MYID_HOSTNAME); + } } - } } void show_myid_status(void) { - char idstr[BUF_LEN]; + char idstr[BUF_LEN]; - (void)idtoa(&myids[myid_state], idstr, sizeof(idstr)); - whack_log(RC_COMMENT, "%%myid = %s", idstr); + (void)idtoa(&myids[myid_state], idstr, sizeof(idstr)); + whack_log(RC_COMMENT, "%%myid = %s", idstr); } /* Convert textual form of id into a (temporary) struct id. @@ -152,86 +166,86 @@ show_myid_status(void) err_t atoid(char *src, struct id *id, bool myid_ok) { - err_t ugh = NULL; - - *id = empty_id; - - if (myid_ok && streq("%myid", src)) - { - id->kind = ID_MYID; - } - else if (strchr(src, '=') != NULL) - { - /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */ - id->kind = ID_DER_ASN1_DN; - id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */ - id->name.len = 0; - /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN - * discard optional @ character in front of DN - */ - ugh = atodn((*src == '@')?src+1:src, &id->name); - } - else if (strchr(src, '@') == NULL) - { - if (streq(src, "%any") || streq(src, "0.0.0.0")) + err_t ugh = NULL; + + *id = empty_id; + + if (myid_ok && streq("%myid", src)) { - /* any ID will be accepted */ - id->kind = ID_NONE; + id->kind = ID_MYID; } - else + else if (strchr(src, '=') != NULL) { - /* !!! this test is not sufficient for distinguishing address families. - * We need a notation to specify that a FQDN is to be resolved to IPv6. - */ - const struct af_info *afi = strchr(src, ':') == NULL - ? &af_inet4_info: &af_inet6_info; - - id->kind = afi->id_addr; - ugh = ttoaddr(src, 0, afi->af, &id->ip_addr); + /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */ + id->kind = ID_DER_ASN1_DN; + id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */ + id->name.len = 0; + /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN + * discard optional @ character in front of DN + */ + ugh = atodn((*src == '@')?src+1:src, &id->name); } - } - else - { - if (*src == '@') + else if (strchr(src, '@') == NULL) { - if (*(src+1) == '#') - { - /* if there is a second specifier (#) on the line - * we interprete this as ID_KEY_ID - */ - id->kind = ID_KEY_ID; - id->name.ptr = src; - /* discard @~, convert from hex to bin */ - ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); - } - else if (*(src+1) == '~') - { - /* if there is a second specifier (~) on the line - * we interprete this as a binary ID_DER_ASN1_DN - */ - id->kind = ID_DER_ASN1_DN; - id->name.ptr = src; - /* discard @~, convert from hex to bin */ - ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); - } - else - { - id->kind = ID_FQDN; - id->name.ptr = src+1; /* discard @ */ - id->name.len = strlen(src)-1; - } + if (streq(src, "%any") || streq(src, "0.0.0.0")) + { + /* any ID will be accepted */ + id->kind = ID_ANY; + } + else + { + /* !!! this test is not sufficient for distinguishing address families. + * We need a notation to specify that a FQDN is to be resolved to IPv6. + */ + const struct af_info *afi = strchr(src, ':') == NULL + ? &af_inet4_info: &af_inet6_info; + + id->kind = afi->id_addr; + ugh = ttoaddr(src, 0, afi->af, &id->ip_addr); + } } else { - /* We leave in @, as per DOI 4.6.2.4 - * (but DNS wants . instead). - */ - id->kind = ID_USER_FQDN; - id->name.ptr = src; - id->name.len = strlen(src); + if (*src == '@') + { + if (*(src+1) == '#') + { + /* if there is a second specifier (#) on the line + * we interprete this as ID_KEY_ID + */ + id->kind = ID_KEY_ID; + id->name.ptr = src; + /* discard @~, convert from hex to bin */ + ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); + } + else if (*(src+1) == '~') + { + /* if there is a second specifier (~) on the line + * we interprete this as a binary ID_DER_ASN1_DN + */ + id->kind = ID_DER_ASN1_DN; + id->name.ptr = src; + /* discard @~, convert from hex to bin */ + ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); + } + else + { + id->kind = ID_FQDN; + id->name.ptr = src+1; /* discard @ */ + id->name.len = strlen(src)-1; + } + } + else + { + /* We leave in @, as per DOI 4.6.2.4 + * (but DNS wants . instead). + */ + id->kind = ID_USER_FQDN; + id->name.ptr = src; + id->name.len = strlen(src); + } } - } - return ugh; + return ugh; } @@ -241,72 +255,72 @@ atoid(char *src, struct id *id, bool myid_ok) int keyidtoa(char *dst, size_t dstlen, chunk_t keyid) { - int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen); - return (((size_t)n < dstlen)? n : dstlen) - 1; + int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen); + return (((size_t)n < dstlen)? n : dstlen) - 1; } void iptoid(const ip_address *ip, struct id *id) { - *id = empty_id; - - switch (addrtypeof(ip)) - { - case AF_INET: - id->kind = ID_IPV4_ADDR; - break; - case AF_INET6: - id->kind = ID_IPV6_ADDR; - break; - default: - bad_case(addrtypeof(ip)); - } - id->ip_addr = *ip; + *id = empty_id; + + switch (addrtypeof(ip)) + { + case AF_INET: + id->kind = ID_IPV4_ADDR; + break; + case AF_INET6: + id->kind = ID_IPV6_ADDR; + break; + default: + bad_case(addrtypeof(ip)); + } + id->ip_addr = *ip; } int idtoa(const struct id *id, char *dst, size_t dstlen) { - int n; - - id = resolve_myid(id); - switch (id->kind) - { - case ID_NONE: - n = snprintf(dst, dstlen, "(none)"); - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1; - break; - case ID_FQDN: - n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr); - break; - case ID_USER_FQDN: - n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); - break; - case ID_DER_ASN1_DN: - n = dntoa(dst, dstlen, id->name); - break; - case ID_KEY_ID: - n = keyidtoa(dst, dstlen, id->name); - break; - default: - n = snprintf(dst, dstlen, "unknown id kind %d", id->kind); - break; - } - - /* "Sanitize" string so that log isn't endangered: - * replace unprintable characters with '?'. - */ - if (n > 0) - { - for ( ; *dst != '\0'; dst++) - if (!isprint(*dst)) - *dst = '?'; - } - - return n; + int n; + + id = resolve_myid(id); + switch (id->kind) + { + case ID_ANY: + n = snprintf(dst, dstlen, "(none)"); + break; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1; + break; + case ID_FQDN: + n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr); + break; + case ID_USER_FQDN: + n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); + break; + case ID_DER_ASN1_DN: + n = dntoa(dst, dstlen, id->name); + break; + case ID_KEY_ID: + n = keyidtoa(dst, dstlen, id->name); + break; + default: + n = snprintf(dst, dstlen, "unknown id kind %d", id->kind); + break; + } + + /* "Sanitize" string so that log isn't endangered: + * replace unprintable characters with '?'. + */ + if (n > 0) + { + for ( ; *dst != '\0'; dst++) + if (!isprint(*dst)) + *dst = '?'; + } + + return n; } /* Replace the shell metacharacters ', \, ", `, and $ in a character string @@ -315,26 +329,26 @@ idtoa(const struct id *id, char *dst, size_t dstlen) void escape_metachar(const char *src, char *dst, size_t dstlen) { - while (*src != '\0' && dstlen > 4) - { - switch (*src) + while (*src != '\0' && dstlen > 4) { - case '\'': - case '\\': - case '"': - case '`': - case '$': - sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src); - dst += 4; - dstlen -= 4; - break; - default: - *dst++ = *src; - dstlen--; + switch (*src) + { + case '\'': + case '\\': + case '"': + case '`': + case '$': + sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src); + dst += 4; + dstlen -= 4; + break; + default: + *dst++ = *src; + dstlen--; + } + src++; } - src++; - } - *dst = '\0'; + *dst = '\0'; } @@ -344,126 +358,126 @@ escape_metachar(const char *src, char *dst, size_t dstlen) void unshare_id_content(struct id *id) { - switch (id->kind) - { - case ID_FQDN: - case ID_USER_FQDN: - case ID_DER_ASN1_DN: - case ID_KEY_ID: - id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name"); - break; - case ID_MYID: - case ID_NONE: - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - break; - default: - bad_case(id->kind); - } + switch (id->kind) + { + case ID_FQDN: + case ID_USER_FQDN: + case ID_DER_ASN1_DN: + case ID_KEY_ID: + id->name = chunk_clone(id->name); + break; + case ID_MYID: + case ID_ANY: + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + break; + default: + bad_case(id->kind); + } } void free_id_content(struct id *id) { - switch (id->kind) - { - case ID_FQDN: - case ID_USER_FQDN: - case ID_DER_ASN1_DN: - case ID_KEY_ID: - freeanychunk(id->name); - break; - case ID_MYID: - case ID_NONE: - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - break; - default: - bad_case(id->kind); - } + switch (id->kind) + { + case ID_FQDN: + case ID_USER_FQDN: + case ID_DER_ASN1_DN: + case ID_KEY_ID: + free(id->name.ptr); + break; + case ID_MYID: + case ID_ANY: + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + break; + default: + bad_case(id->kind); + } } /* compare two struct id values */ bool same_id(const struct id *a, const struct id *b) { - a = resolve_myid(a); - b = resolve_myid(b); - if (a->kind != b->kind) - return FALSE; - switch (a->kind) - { - case ID_NONE: - return TRUE; /* kind of vacuous */ - - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - return sameaddr(&a->ip_addr, &b->ip_addr); - - case ID_FQDN: - case ID_USER_FQDN: - /* assumptions: - * - case should be ignored - * - trailing "." should be ignored (even if the only character?) - */ + a = resolve_myid(a); + b = resolve_myid(b); + if (a->kind != b->kind) + return FALSE; + switch (a->kind) { - size_t al = a->name.len - , bl = b->name.len; - - while (al > 0 && a->name.ptr[al - 1] == '.') - al--; - while (bl > 0 && b->name.ptr[bl - 1] == '.') - bl--; - return al == bl - && strncasecmp(a->name.ptr, b->name.ptr, al) == 0; - } + case ID_ANY: + return TRUE; /* kind of vacuous */ + + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + return sameaddr(&a->ip_addr, &b->ip_addr); + + case ID_FQDN: + case ID_USER_FQDN: + /* assumptions: + * - case should be ignored + * - trailing "." should be ignored (even if the only character?) + */ + { + size_t al = a->name.len + , bl = b->name.len; + + while (al > 0 && a->name.ptr[al - 1] == '.') + al--; + while (bl > 0 && b->name.ptr[bl - 1] == '.') + bl--; + return al == bl + && strncasecmp(a->name.ptr, b->name.ptr, al) == 0; + } - case ID_DER_ASN1_DN: - return same_dn(a->name, b->name); + case ID_DER_ASN1_DN: + return same_dn(a->name, b->name); - case ID_KEY_ID: - return a->name.len == b->name.len - && memcmp(a->name.ptr, b->name.ptr, a->name.len) == 0; + case ID_KEY_ID: + return a->name.len == b->name.len + && memeq(a->name.ptr, b->name.ptr, a->name.len); - default: - bad_case(a->kind); - } - return FALSE; + default: + bad_case(a->kind); + } + return FALSE; } /* compare two struct id values, DNs can contain wildcards */ bool match_id(const struct id *a, const struct id *b, int *wildcards) { - if (b->kind == ID_NONE) - { - *wildcards = MAX_WILDCARDS; - return TRUE; - } - if (a->kind != b->kind) - return FALSE; - if (a->kind == ID_DER_ASN1_DN) - return match_dn(a->name, b->name, wildcards); - else - { - *wildcards = 0; - return same_id(a, b); - } + if (b->kind == ID_ANY) + { + *wildcards = MAX_WILDCARDS; + return TRUE; + } + if (a->kind != b->kind) + return FALSE; + if (a->kind == ID_DER_ASN1_DN) + return match_dn(a->name, b->name, wildcards); + else + { + *wildcards = 0; + return same_id(a, b); + } } /* count the numer of wildcards in an id */ int id_count_wildcards(const struct id *id) { - switch (id->kind) - { - case ID_NONE: - return MAX_WILDCARDS; - case ID_DER_ASN1_DN: - return dn_count_wildcards(id->name); - default: - return 0; - } + switch (id->kind) + { + case ID_ANY: + return MAX_WILDCARDS; + case ID_DER_ASN1_DN: + return dn_count_wildcards(id->name); + default: + return 0; + } } /* build an ID payload @@ -474,31 +488,31 @@ id_count_wildcards(const struct id *id) void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end) { - const struct id *id = resolve_myid(&end->id); - - zero(hd); - hd->isaiid_idtype = id->kind; - switch (id->kind) - { - case ID_NONE: - hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr; - tl->len = addrbytesptr(&end->host_addr - , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ - break; - case ID_FQDN: - case ID_USER_FQDN: - case ID_DER_ASN1_DN: - case ID_KEY_ID: - *tl = id->name; - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - tl->len = addrbytesptr(&id->ip_addr - , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ - break; - default: - bad_case(id->kind); - } + const struct id *id = resolve_myid(&end->id); + + zero(hd); + hd->isaiid_idtype = id->kind; + switch (id->kind) + { + case ID_ANY: + hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr; + tl->len = addrbytesptr(&end->host_addr + , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ + break; + case ID_FQDN: + case ID_USER_FQDN: + case ID_DER_ASN1_DN: + case ID_KEY_ID: + *tl = id->name; + break; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + tl->len = addrbytesptr(&id->ip_addr + , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ + break; + default: + bad_case(id->kind); + } } /* |