• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
getsainfo(loc,rmt,peer,client,remoteid)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 *
newsainfo()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
delsainfo(si)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 
prisainfo(s)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
inssainfo(new)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
remsainfo(si)298 remsainfo(si)
299 	struct sainfo *si;
300 {
301 	LIST_REMOVE(si, chain);
302 }
303 
304 void
flushsainfo()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
initsainfo()317 initsainfo()
318 {
319 	LIST_INIT(&sitree);
320 }
321 
322 struct sainfoalg *
newsainfoalg()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
delsainfoalg(alg)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
inssainfoalg(head,new)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 *
sainfo2str(si)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 
sainfo_start_reload(void)396 void sainfo_start_reload(void){
397 	sitree_save=sitree;
398 	initsainfo();
399 }
400 
sainfo_finish_reload(void)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 
save_sainfotree_restore(void)410 void save_sainfotree_restore(void){
411 	flushsainfo();
412 	sitree=sitree_save;
413 }
414