/* $NetBSD: sainfo.c,v 1.7.6.1 2007/08/01 11:52:22 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" static LIST_HEAD(_sitree, sainfo) sitree, sitree_save, sitree_tmp; /* %%% * 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, remoteid) const vchar_t *loc, *rmt, *peer; int remoteid; { struct sainfo *s = NULL; struct sainfo *anonymous = NULL; int pass = 1; if (peer == NULL) pass = 2; /* 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 == NULL) drmt = strdup("ANONYMOUS"); else drmt = ipsecdoi_id2str(rmt); if (peer == NULL) dpeer = strdup("NULL"); else dpeer = ipsecdoi_id2str(peer); plog(LLV_DEBUG, LOCATION, NULL, "getsainfo params: loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i\n", dloc, drmt, dpeer, remoteid ); racoon_free(dloc); racoon_free(drmt); racoon_free(dpeer); } again: plog(LLV_DEBUG, LOCATION, NULL, "getsainfo pass #%i\n", pass); LIST_FOREACH(s, &sitree, chain) { const char *sainfostr = sainfo2str(s); plog(LLV_DEBUG, LOCATION, NULL, "evaluating sainfo: %s\n", sainfostr); if(s->remoteid != remoteid) continue; if (s->id_i != NULL) { if (pass == 2) continue; if (ipsecdoi_chkcmpids(peer, s->id_i, 0)) continue; } else if (pass == 1) continue; if (s->idsrc == NULL && s->iddst == NULL) { anonymous = s; continue; } /* anonymous ? */ if (loc == NULL) { if (anonymous != NULL) break; continue; } /* compare the ids */ if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) && !ipsecdoi_chkcmpids(rmt, s->iddst, 0)) return s; } if ((anonymous == NULL) && (pass == 1)) { pass++; goto again; } return anonymous; } 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) vfree(si->iddst); #ifdef ENABLE_HYBRID if (si->group) vfree(si->group); #endif racoon_free(si); } void inssainfo(new) struct sainfo *new; { LIST_INSERT_HEAD(&sitree, new, chain); } 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 == NULL) idloc = strdup("ANONYMOUS"); else idloc = ipsecdoi_id2str(si->idsrc); if (si->iddst == NULL) idrmt = strdup("ANONYMOUS"); 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=%i", idloc, idrmt, id_i, si->remoteid); racoon_free(idloc); racoon_free(idrmt); racoon_free(id_i); return buf; } void save_sainfotree(void){ sitree_save=sitree; initsainfo(); } void save_sainfotree_flush(void){ sitree_tmp=sitree; sitree=sitree_save; flushsainfo(); sitree=sitree_tmp; } void save_sainfotree_restore(void){ flushsainfo(); sitree=sitree_save; }