1/*	$NetBSD: sainfo.c,v 1.7.6.1 2007/08/01 11:52:22 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
67static LIST_HEAD(_sitree, sainfo) sitree, sitree_save, sitree_tmp;
68
69/* %%%
70 * modules for ipsec sa info
71 */
72/*
73 * return matching entry.
74 * no matching entry found and if there is anonymous entry, return it.
75 * else return NULL.
76 * First pass is for sainfo from a specified peer, second for others.
77 */
78struct sainfo *
79getsainfo(loc, rmt, peer, remoteid)
80	const vchar_t *loc, *rmt, *peer;
81	int remoteid;
82{
83	struct sainfo *s = NULL;
84	struct sainfo *anonymous = NULL;
85	int pass = 1;
86
87	if (peer == NULL)
88		pass = 2;
89
90	/* debug level output */
91	if(loglevel >= LLV_DEBUG) {
92		char *dloc, *drmt, *dpeer, *dclient;
93
94		if (loc == NULL)
95			dloc = strdup("ANONYMOUS");
96		else
97			dloc = ipsecdoi_id2str(loc);
98
99		if (rmt == NULL)
100			drmt = strdup("ANONYMOUS");
101		else
102			drmt = ipsecdoi_id2str(rmt);
103
104		if (peer == NULL)
105			dpeer = strdup("NULL");
106		else
107			dpeer = ipsecdoi_id2str(peer);
108
109		plog(LLV_DEBUG, LOCATION, NULL,
110			"getsainfo params: loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i\n",
111			dloc, drmt, dpeer, remoteid );
112
113                racoon_free(dloc);
114                racoon_free(drmt);
115                racoon_free(dpeer);
116	}
117
118    again:
119	plog(LLV_DEBUG, LOCATION, NULL,
120		"getsainfo pass #%i\n", pass);
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			continue;
129
130		if (s->id_i != NULL) {
131			if (pass == 2)
132				continue;
133			if (ipsecdoi_chkcmpids(peer, s->id_i, 0))
134				continue;
135		} else if (pass == 1)
136			continue;
137		if (s->idsrc == NULL && s->iddst == NULL) {
138			anonymous = s;
139			continue;
140		}
141
142		/* anonymous ? */
143		if (loc == NULL) {
144			if (anonymous != NULL)
145				break;
146			continue;
147		}
148
149		/* compare the ids */
150		if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) &&
151		    !ipsecdoi_chkcmpids(rmt, s->iddst, 0))
152			return s;
153	}
154
155	if ((anonymous == NULL) && (pass == 1)) {
156		pass++;
157		goto again;
158	}
159
160	return anonymous;
161}
162
163struct sainfo *
164newsainfo()
165{
166	struct sainfo *new;
167
168	new = racoon_calloc(1, sizeof(*new));
169	if (new == NULL)
170		return NULL;
171
172	new->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
173	new->lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
174
175	return new;
176}
177
178void
179delsainfo(si)
180	struct sainfo *si;
181{
182	int i;
183
184	for (i = 0; i < MAXALGCLASS; i++)
185		delsainfoalg(si->algs[i]);
186
187	if (si->idsrc)
188		vfree(si->idsrc);
189	if (si->iddst)
190		vfree(si->iddst);
191
192#ifdef ENABLE_HYBRID
193	if (si->group)
194		vfree(si->group);
195#endif
196
197	racoon_free(si);
198}
199
200void
201inssainfo(new)
202	struct sainfo *new;
203{
204	LIST_INSERT_HEAD(&sitree, new, chain);
205}
206
207void
208remsainfo(si)
209	struct sainfo *si;
210{
211	LIST_REMOVE(si, chain);
212}
213
214void
215flushsainfo()
216{
217	struct sainfo *s, *next;
218
219	for (s = LIST_FIRST(&sitree); s; s = next) {
220		next = LIST_NEXT(s, chain);
221		remsainfo(s);
222		delsainfo(s);
223	}
224}
225
226void
227initsainfo()
228{
229	LIST_INIT(&sitree);
230}
231
232struct sainfoalg *
233newsainfoalg()
234{
235	struct sainfoalg *new;
236
237	new = racoon_calloc(1, sizeof(*new));
238	if (new == NULL)
239		return NULL;
240
241	return new;
242}
243
244void
245delsainfoalg(alg)
246	struct sainfoalg *alg;
247{
248	struct sainfoalg *a, *next;
249
250	for (a = alg; a; a = next) {
251		next = a->next;
252		racoon_free(a);
253	}
254}
255
256void
257inssainfoalg(head, new)
258	struct sainfoalg **head;
259	struct sainfoalg *new;
260{
261	struct sainfoalg *a;
262
263	for (a = *head; a && a->next; a = a->next)
264		;
265	if (a)
266		a->next = new;
267	else
268		*head = new;
269}
270
271const char *
272sainfo2str(si)
273	const struct sainfo *si;
274{
275        static char buf[256];
276
277        char *idloc = NULL, *idrmt = NULL, *id_i;
278
279        if (si->idsrc == NULL)
280                idloc = strdup("ANONYMOUS");
281        else
282                idloc = ipsecdoi_id2str(si->idsrc);
283
284        if (si->iddst == NULL)
285                idrmt = strdup("ANONYMOUS");
286        else
287                idrmt = ipsecdoi_id2str(si->iddst);
288
289        if (si->id_i == NULL)
290                id_i = strdup("ANY");
291        else
292                id_i = ipsecdoi_id2str(si->id_i);
293
294        snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i",
295		idloc, idrmt, id_i, si->remoteid);
296
297        racoon_free(idloc);
298        racoon_free(idrmt);
299        racoon_free(id_i);
300
301        return buf;
302}
303
304void save_sainfotree(void){
305	sitree_save=sitree;
306	initsainfo();
307}
308
309void save_sainfotree_flush(void){
310	sitree_tmp=sitree;
311	sitree=sitree_save;
312	flushsainfo();
313	sitree=sitree_tmp;
314}
315
316void save_sainfotree_restore(void){
317	flushsainfo();
318	sitree=sitree_save;
319}
320