/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1) * Copyright (C) 1999 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * 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,v 1.6 2000/06/18 21:20:33 dhr Exp $ */ #include #include #include #include #include #include #include "constants.h" #include "defs.h" #include "id.h" #include "connections.h" /* needs id.h */ #include "packet.h" const struct id empty_id; /* all zeros and NULLs */ /* convert textual form of id into a (temporary) struct id */ complaint_t atoid(char *src, struct id *id) { complaint_t ugh = NULL; memset(id, 0, sizeof(*id)); id->name.ptr = NULL; id->next = NULL; if (strchr(src, '@') == NULL) { id->kind = ID_IPV4_ADDR; ugh = atoaddr(src, 0, &id->ip_addr); } else { if (*src == '@') { id->kind = ID_FQDN; id->name.ptr = src+1; /* discard @ */ } 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(id->name.ptr); } return ugh; } int idtoa(struct id *id, char *dst, size_t dstlen) { switch (id->kind) { case ID_NONE: return snprintf(dst, dstlen, "(none)"); case ID_IPV4_ADDR: return snprintf(dst, dstlen, "%s", inet_ntoa(id->ip_addr)); case ID_FQDN: return snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr); case ID_USER_FQDN: return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); default: return snprintf(dst, dstlen, "unknown id kind %d", id->kind); } } /* deep-copy a struct id into a new heap object * This is needed if the result of atoid is to be kept. */ struct id * clone_id(const struct id *src) { struct id *dst = clone_thing(*src, "keep id"); clone_id_content(dst); dst->next = NULL; return dst; } void clone_id_content(struct id *id) { switch (id->kind) { case ID_FQDN: case ID_USER_FQDN: id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name"); break; case ID_NONE: case ID_IPV4_ADDR: break; default: passert(FALSE); } } /* free a heap struct id */ void free_id(struct id *id) { free_id_content(id); pfree(id); } void free_id_content(struct id *id) { switch (id->kind) { case ID_FQDN: case ID_USER_FQDN: pfree(id->name.ptr); break; case ID_NONE: case ID_IPV4_ADDR: break; default: passert(FALSE); } } /* compare two struct id values */ bool id_same(const struct id *a, const struct id *b) { if (a->kind != b->kind) return FALSE; switch (a->kind) { case ID_NONE: return TRUE; /* kind of vacuous */ case ID_IPV4_ADDR: return same_ip(a->ip_addr, b->ip_addr); case ID_FQDN: case ID_USER_FQDN: /* assumption: case should be ignored */ return a->name.len == b->name.len && strncasecmp(a->name.ptr, b->name.ptr, a->name.len) == 0; default: passert(FALSE); } } void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end) { memset(hd, '\0', sizeof(*hd)); hd->isaiid_idtype = end->id.kind; switch (end->id.kind) { case ID_NONE: hd->isaiid_idtype = ID_IPV4_ADDR; tl->ptr = (void *)&end->host_addr; tl->len = sizeof(end->host_addr); break; case ID_FQDN: case ID_USER_FQDN: *tl = end->id.name; break; case ID_IPV4_ADDR: tl->ptr = (void *)&end->id.ip_addr; tl->len = sizeof(end->id.ip_addr); break; default: passert(FALSE); } }