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 
67 static 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  */
78 struct sainfo *
79 getsainfo(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 
163 struct sainfo *
newsainfo()164 newsainfo()
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 
178 void
delsainfo(si)179 delsainfo(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 
200 void
inssainfo(new)201 inssainfo(new)
202 	struct sainfo *new;
203 {
204 	LIST_INSERT_HEAD(&sitree, new, chain);
205 }
206 
207 void
remsainfo(si)208 remsainfo(si)
209 	struct sainfo *si;
210 {
211 	LIST_REMOVE(si, chain);
212 }
213 
214 void
flushsainfo()215 flushsainfo()
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 
226 void
initsainfo()227 initsainfo()
228 {
229 	LIST_INIT(&sitree);
230 }
231 
232 struct sainfoalg *
newsainfoalg()233 newsainfoalg()
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 
244 void
delsainfoalg(alg)245 delsainfoalg(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 
256 void
inssainfoalg(head,new)257 inssainfoalg(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 
271 const char *
sainfo2str(si)272 sainfo2str(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 
save_sainfotree(void)304 void save_sainfotree(void){
305 	sitree_save=sitree;
306 	initsainfo();
307 }
308 
save_sainfotree_flush(void)309 void save_sainfotree_flush(void){
310 	sitree_tmp=sitree;
311 	sitree=sitree_save;
312 	flushsainfo();
313 	sitree=sitree_tmp;
314 }
315 
save_sainfotree_restore(void)316 void save_sainfotree_restore(void){
317 	flushsainfo();
318 	sitree=sitree_save;
319 }
320