| /* $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; |
| } |