1: /* $NetBSD: sainfo.c,v 1.14 2011/02/02 15:21:34 vanhu Exp $ */
2:
3: /* $KAME: sainfo.c,v 1.16 2003/06/27 07:32:39 sakane Exp $ */
4:
5: /*
6: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. Neither the name of the project nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
34: #include "config.h"
35:
36: #include <sys/param.h>
37: #include <sys/types.h>
38: #include <sys/socket.h>
39: #include <sys/queue.h>
40:
41: #include <netinet/in.h>
42: #include <netinet/in.h>
43: #include PATH_IPSEC_H
44:
45: #include <stdlib.h>
46: #include <stdio.h>
47: #include <string.h>
48: #include <errno.h>
49:
50: #include "var.h"
51: #include "misc.h"
52: #include "vmbuf.h"
53: #include "plog.h"
54: #include "sockmisc.h"
55: #include "debug.h"
56:
57: #include "localconf.h"
58: #include "isakmp_var.h"
59: #include "isakmp.h"
60: #include "ipsec_doi.h"
61: #include "oakley.h"
62: #include "handler.h"
63: #include "algorithm.h"
64: #include "sainfo.h"
65: #include "gcmalloc.h"
66:
67: typedef LIST_HEAD(_sitree, sainfo) sainfo_tailq_head_t;
68: static sainfo_tailq_head_t sitree, sitree_save;
69:
70: /* %%%
71: * modules for ipsec sa info
72: */
73: /*
74: * return matching entry.
75: * no matching entry found and if there is anonymous entry, return it.
76: * else return NULL.
77: * First pass is for sainfo from a specified peer, second for others.
78: */
79: struct sainfo *
80: getsainfo(loc, rmt, peer, client, remoteid)
81: const vchar_t *loc, *rmt, *peer, *client;
82: uint32_t remoteid;
83: {
84: struct sainfo *s = NULL;
85:
86: /* debug level output */
87: if(loglevel >= LLV_DEBUG) {
88: char *dloc, *drmt, *dpeer, *dclient;
89:
90: if (loc == NULL)
91: dloc = strdup("ANONYMOUS");
92: else
93: dloc = ipsecdoi_id2str(loc);
94:
95: if (rmt == SAINFO_ANONYMOUS)
96: drmt = strdup("ANONYMOUS");
97: else if (rmt == SAINFO_CLIENTADDR)
98: drmt = strdup("CLIENTADDR");
99: else
100: drmt = ipsecdoi_id2str(rmt);
101:
102: if (peer == NULL)
103: dpeer = strdup("NULL");
104: else
105: dpeer = ipsecdoi_id2str(peer);
106:
107: if (client == NULL)
108: dclient = strdup("NULL");
109: else
110: dclient = ipsecdoi_id2str(client);
111:
112: plog(LLV_DEBUG, LOCATION, NULL,
113: "getsainfo params: loc=\'%s\' rmt=\'%s\' peer=\'%s\' client=\'%s\' id=%u\n",
114: dloc, drmt, dpeer, dclient, remoteid );
115:
116: racoon_free(dloc);
117: racoon_free(drmt);
118: racoon_free(dpeer);
119: racoon_free(dclient);
120: }
121:
122: LIST_FOREACH(s, &sitree, chain) {
123: const char *sainfostr = sainfo2str(s);
124: plog(LLV_DEBUG, LOCATION, NULL,
125: "evaluating sainfo: %s\n", sainfostr);
126:
127: if(s->remoteid != remoteid) {
128: plog(LLV_DEBUG, LOCATION, NULL,
129: "remoteid mismatch: %u != %u\n",
130: s->remoteid, remoteid);
131: continue;
132: }
133:
134: /* compare 'from' id value */
135: if (s->id_i != NULL)
136: if (ipsecdoi_chkcmpids(peer, s->id_i, 0))
137: continue;
138:
139: /* compare ids - client */
140: if( s->iddst == SAINFO_CLIENTADDR ) {
141: /*
142: * This sainfo section enforces client address
143: * checking. Prevent match if the client value
144: * ( modecfg or tunnel address ) is NULL.
145: */
146:
147: if (client == NULL)
148: continue;
149:
150: if( rmt == SAINFO_CLIENTADDR ) {
151: /*
152: * In the case where a supplied rmt value is
153: * also SAINFO_CLIENTADDR, we are comparing
154: * with another sainfo to check for duplicate.
155: * Only compare the local values to determine
156: * a match.
157: */
158:
159: if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0))
160: return s;
161: }
162: else {
163: /*
164: * In the case where a supplied rmt value is
165: * not SAINFO_CLIENTADDR, do a standard match
166: * for local values and enforce that the rmt
167: * id matches the client address value.
168: */
169:
170: if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) &&
171: !ipsecdoi_chkcmpids(rmt, client, 0))
172: return s;
173: }
174:
175: continue;
176: }
177:
178:
179: /* compare ids - standard */
180: if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) &&
181: !ipsecdoi_chkcmpids(rmt, s->iddst, 0))
182: return s;
183: }
184:
185: return NULL;
186: }
187:
188: struct sainfo *
189: newsainfo()
190: {
191: struct sainfo *new;
192:
193: new = racoon_calloc(1, sizeof(*new));
194: if (new == NULL)
195: return NULL;
196:
197: new->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
198: new->lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
199:
200: return new;
201: }
202:
203: void
204: delsainfo(si)
205: struct sainfo *si;
206: {
207: int i;
208:
209: for (i = 0; i < MAXALGCLASS; i++)
210: delsainfoalg(si->algs[i]);
211:
212: if (si->idsrc)
213: vfree(si->idsrc);
214: if (si->iddst != NULL &&
215: si->iddst != SAINFO_CLIENTADDR)
216: vfree(si->iddst);
217:
218: #ifdef ENABLE_HYBRID
219: if (si->group)
220: vfree(si->group);
221: #endif
222:
223: racoon_free(si);
224: }
225:
226: int prisainfo(s)
227: struct sainfo *s;
228: {
229: /*
230: * determine the matching priority
231: * of an sainfo section
232: */
233:
234: int pri = 0;
235:
236: if(s->remoteid)
237: pri += 3;
238:
239: if(s->id_i)
240: pri += 3;
241:
242: if(s->idsrc)
243: pri++;
244:
245: if(s->iddst)
246: pri++;
247:
248: return pri;
249: }
250:
251: void
252: inssainfo(new)
253: struct sainfo *new;
254: {
255: if(LIST_EMPTY(&sitree)) {
256:
257: /* first in list */
258: LIST_INSERT_HEAD(&sitree, new, chain);
259: }
260: else {
261: int npri, spri;
262: struct sainfo *s, *n;
263:
264: /*
265: * insert our new sainfo section
266: * into our list which is sorted
267: * based on the match priority
268: */
269:
270: npri = prisainfo(new);
271:
272: s = LIST_FIRST(&sitree);
273: while (1) {
274:
275: spri = prisainfo(s);
276: n = LIST_NEXT(s, chain);
277:
278: if(npri > spri)
279: {
280: /* higher priority */
281: LIST_INSERT_BEFORE(s, new, chain);
282: return;
283: }
284:
285: if(n == NULL)
286: {
287: /* last in list */
288: LIST_INSERT_AFTER(s, new, chain);
289: return;
290: }
291:
292: s = n;
293: }
294: }
295: }
296:
297: void
298: remsainfo(si)
299: struct sainfo *si;
300: {
301: LIST_REMOVE(si, chain);
302: }
303:
304: void
305: flushsainfo()
306: {
307: struct sainfo *s, *next;
308:
309: for (s = LIST_FIRST(&sitree); s; s = next) {
310: next = LIST_NEXT(s, chain);
311: remsainfo(s);
312: delsainfo(s);
313: }
314: }
315:
316: void
317: initsainfo()
318: {
319: LIST_INIT(&sitree);
320: }
321:
322: struct sainfoalg *
323: newsainfoalg()
324: {
325: struct sainfoalg *new;
326:
327: new = racoon_calloc(1, sizeof(*new));
328: if (new == NULL)
329: return NULL;
330:
331: return new;
332: }
333:
334: void
335: delsainfoalg(alg)
336: struct sainfoalg *alg;
337: {
338: struct sainfoalg *a, *next;
339:
340: for (a = alg; a; a = next) {
341: next = a->next;
342: racoon_free(a);
343: }
344: }
345:
346: void
347: inssainfoalg(head, new)
348: struct sainfoalg **head;
349: struct sainfoalg *new;
350: {
351: struct sainfoalg *a;
352:
353: for (a = *head; a && a->next; a = a->next)
354: ;
355: if (a)
356: a->next = new;
357: else
358: *head = new;
359: }
360:
361: const char *
362: sainfo2str(si)
363: const struct sainfo *si;
364: {
365: static char buf[256];
366:
367: char *idloc = NULL, *idrmt = NULL, *id_i;
368:
369: if (si->idsrc == SAINFO_ANONYMOUS)
370: idloc = strdup("ANONYMOUS");
371: else
372: idloc = ipsecdoi_id2str(si->idsrc);
373:
374: if (si->iddst == SAINFO_ANONYMOUS)
375: idrmt = strdup("ANONYMOUS");
376: else if (si->iddst == SAINFO_CLIENTADDR)
377: idrmt = strdup("CLIENTADDR");
378: else
379: idrmt = ipsecdoi_id2str(si->iddst);
380:
381: if (si->id_i == NULL)
382: id_i = strdup("ANY");
383: else
384: id_i = ipsecdoi_id2str(si->id_i);
385:
386: snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%u",
387: idloc, idrmt, id_i, si->remoteid);
388:
389: racoon_free(idloc);
390: racoon_free(idrmt);
391: racoon_free(id_i);
392:
393: return buf;
394: }
395:
396: void sainfo_start_reload(void){
397: sitree_save=sitree;
398: initsainfo();
399: }
400:
401: void sainfo_finish_reload(void){
402: sainfo_tailq_head_t sitree_tmp;
403:
404: sitree_tmp=sitree;
405: sitree=sitree_save;
406: flushsainfo();
407: sitree=sitree_tmp;
408: }
409:
410: void save_sainfotree_restore(void){
411: flushsainfo();
412: sitree=sitree_save;
413: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>