diff options
Diffstat (limited to 'ipsec-tools/src/racoon/sainfo.c')
-rw-r--r-- | ipsec-tools/src/racoon/sainfo.c | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/ipsec-tools/src/racoon/sainfo.c b/ipsec-tools/src/racoon/sainfo.c new file mode 100644 index 00000000..b6577c2e --- /dev/null +++ b/ipsec-tools/src/racoon/sainfo.c @@ -0,0 +1,413 @@ +/* $NetBSD: sainfo.c,v 1.14 2011/02/02 15:21:34 vanhu Exp $ */ + +/* $KAME: sainfo.c,v 1.16 2003/06/27 07:32:39 sakane Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> + +#include <netinet/in.h> +#include <netinet/in.h> +#include PATH_IPSEC_H + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "var.h" +#include "misc.h" +#include "vmbuf.h" +#include "plog.h" +#include "sockmisc.h" +#include "debug.h" + +#include "localconf.h" +#include "isakmp_var.h" +#include "isakmp.h" +#include "ipsec_doi.h" +#include "oakley.h" +#include "handler.h" +#include "algorithm.h" +#include "sainfo.h" +#include "gcmalloc.h" + +typedef LIST_HEAD(_sitree, sainfo) sainfo_tailq_head_t; +static sainfo_tailq_head_t sitree, sitree_save; + +/* %%% + * modules for ipsec sa info + */ +/* + * return matching entry. + * no matching entry found and if there is anonymous entry, return it. + * else return NULL. + * First pass is for sainfo from a specified peer, second for others. + */ +struct sainfo * +getsainfo(loc, rmt, peer, client, remoteid) + const vchar_t *loc, *rmt, *peer, *client; + uint32_t remoteid; +{ + struct sainfo *s = NULL; + + /* debug level output */ + if(loglevel >= LLV_DEBUG) { + char *dloc, *drmt, *dpeer, *dclient; + + if (loc == NULL) + dloc = strdup("ANONYMOUS"); + else + dloc = ipsecdoi_id2str(loc); + + if (rmt == SAINFO_ANONYMOUS) + drmt = strdup("ANONYMOUS"); + else if (rmt == SAINFO_CLIENTADDR) + drmt = strdup("CLIENTADDR"); + else + drmt = ipsecdoi_id2str(rmt); + + if (peer == NULL) + dpeer = strdup("NULL"); + else + dpeer = ipsecdoi_id2str(peer); + + if (client == NULL) + dclient = strdup("NULL"); + else + dclient = ipsecdoi_id2str(client); + + plog(LLV_DEBUG, LOCATION, NULL, + "getsainfo params: loc=\'%s\' rmt=\'%s\' peer=\'%s\' client=\'%s\' id=%u\n", + dloc, drmt, dpeer, dclient, remoteid ); + + racoon_free(dloc); + racoon_free(drmt); + racoon_free(dpeer); + racoon_free(dclient); + } + + LIST_FOREACH(s, &sitree, chain) { + const char *sainfostr = sainfo2str(s); + plog(LLV_DEBUG, LOCATION, NULL, + "evaluating sainfo: %s\n", sainfostr); + + if(s->remoteid != remoteid) { + plog(LLV_DEBUG, LOCATION, NULL, + "remoteid mismatch: %u != %u\n", + s->remoteid, remoteid); + continue; + } + + /* compare 'from' id value */ + if (s->id_i != NULL) + if (ipsecdoi_chkcmpids(peer, s->id_i, 0)) + continue; + + /* compare ids - client */ + if( s->iddst == SAINFO_CLIENTADDR ) { + /* + * This sainfo section enforces client address + * checking. Prevent match if the client value + * ( modecfg or tunnel address ) is NULL. + */ + + if (client == NULL) + continue; + + if( rmt == SAINFO_CLIENTADDR ) { + /* + * In the case where a supplied rmt value is + * also SAINFO_CLIENTADDR, we are comparing + * with another sainfo to check for duplicate. + * Only compare the local values to determine + * a match. + */ + + if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0)) + return s; + } + else { + /* + * In the case where a supplied rmt value is + * not SAINFO_CLIENTADDR, do a standard match + * for local values and enforce that the rmt + * id matches the client address value. + */ + + if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) && + !ipsecdoi_chkcmpids(rmt, client, 0)) + return s; + } + + continue; + } + + + /* compare ids - standard */ + if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) && + !ipsecdoi_chkcmpids(rmt, s->iddst, 0)) + return s; + } + + return NULL; +} + +struct sainfo * +newsainfo() +{ + struct sainfo *new; + + new = racoon_calloc(1, sizeof(*new)); + if (new == NULL) + return NULL; + + new->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT; + new->lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX; + + return new; +} + +void +delsainfo(si) + struct sainfo *si; +{ + int i; + + for (i = 0; i < MAXALGCLASS; i++) + delsainfoalg(si->algs[i]); + + if (si->idsrc) + vfree(si->idsrc); + if (si->iddst != NULL && + si->iddst != SAINFO_CLIENTADDR) + vfree(si->iddst); + +#ifdef ENABLE_HYBRID + if (si->group) + vfree(si->group); +#endif + + racoon_free(si); +} + +int prisainfo(s) + struct sainfo *s; +{ + /* + * determine the matching priority + * of an sainfo section + */ + + int pri = 0; + + if(s->remoteid) + pri += 3; + + if(s->id_i) + pri += 3; + + if(s->idsrc) + pri++; + + if(s->iddst) + pri++; + + return pri; +} + +void +inssainfo(new) + struct sainfo *new; +{ + if(LIST_EMPTY(&sitree)) { + + /* first in list */ + LIST_INSERT_HEAD(&sitree, new, chain); + } + else { + int npri, spri; + struct sainfo *s, *n; + + /* + * insert our new sainfo section + * into our list which is sorted + * based on the match priority + */ + + npri = prisainfo(new); + + s = LIST_FIRST(&sitree); + while (1) { + + spri = prisainfo(s); + n = LIST_NEXT(s, chain); + + if(npri > spri) + { + /* higher priority */ + LIST_INSERT_BEFORE(s, new, chain); + return; + } + + if(n == NULL) + { + /* last in list */ + LIST_INSERT_AFTER(s, new, chain); + return; + } + + s = n; + } + } +} + +void +remsainfo(si) + struct sainfo *si; +{ + LIST_REMOVE(si, chain); +} + +void +flushsainfo() +{ + struct sainfo *s, *next; + + for (s = LIST_FIRST(&sitree); s; s = next) { + next = LIST_NEXT(s, chain); + remsainfo(s); + delsainfo(s); + } +} + +void +initsainfo() +{ + LIST_INIT(&sitree); +} + +struct sainfoalg * +newsainfoalg() +{ + struct sainfoalg *new; + + new = racoon_calloc(1, sizeof(*new)); + if (new == NULL) + return NULL; + + return new; +} + +void +delsainfoalg(alg) + struct sainfoalg *alg; +{ + struct sainfoalg *a, *next; + + for (a = alg; a; a = next) { + next = a->next; + racoon_free(a); + } +} + +void +inssainfoalg(head, new) + struct sainfoalg **head; + struct sainfoalg *new; +{ + struct sainfoalg *a; + + for (a = *head; a && a->next; a = a->next) + ; + if (a) + a->next = new; + else + *head = new; +} + +const char * +sainfo2str(si) + const struct sainfo *si; +{ + static char buf[256]; + + char *idloc = NULL, *idrmt = NULL, *id_i; + + if (si->idsrc == SAINFO_ANONYMOUS) + idloc = strdup("ANONYMOUS"); + else + idloc = ipsecdoi_id2str(si->idsrc); + + if (si->iddst == SAINFO_ANONYMOUS) + idrmt = strdup("ANONYMOUS"); + else if (si->iddst == SAINFO_CLIENTADDR) + idrmt = strdup("CLIENTADDR"); + else + idrmt = ipsecdoi_id2str(si->iddst); + + if (si->id_i == NULL) + id_i = strdup("ANY"); + else + id_i = ipsecdoi_id2str(si->id_i); + + snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%u", + idloc, idrmt, id_i, si->remoteid); + + racoon_free(idloc); + racoon_free(idrmt); + racoon_free(id_i); + + return buf; +} + +void sainfo_start_reload(void){ + sitree_save=sitree; + initsainfo(); +} + +void sainfo_finish_reload(void){ + sainfo_tailq_head_t sitree_tmp; + + sitree_tmp=sitree; + sitree=sitree_save; + flushsainfo(); + sitree=sitree_tmp; +} + +void save_sainfotree_restore(void){ + flushsainfo(); + sitree=sitree_save; +} |