1 /* $NetBSD: sainfo.c,v 1.16 2018/05/19 20:14:56 maxv 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 if (si == NULL)
210 return;
211
212 for (i = 0; i < MAXALGCLASS; i++)
213 delsainfoalg(si->algs[i]);
214
215 if (si->idsrc)
216 vfree(si->idsrc);
217 if (si->iddst != NULL &&
218 si->iddst != SAINFO_CLIENTADDR)
219 vfree(si->iddst);
220
221 #ifdef ENABLE_HYBRID
222 if (si->group)
223 vfree(si->group);
224 #endif
225
226 racoon_free(si);
227 }
228
229 static int
prisainfo(struct sainfo * s)230 prisainfo(struct sainfo *s)
231 {
232 /*
233 * determine the matching priority
234 * of an sainfo section
235 */
236
237 int pri = 0;
238
239 if(s->remoteid)
240 pri += 3;
241
242 if(s->id_i)
243 pri += 3;
244
245 if(s->idsrc)
246 pri++;
247
248 if(s->iddst)
249 pri++;
250
251 return pri;
252 }
253
254 void
inssainfo(new)255 inssainfo(new)
256 struct sainfo *new;
257 {
258 if(LIST_EMPTY(&sitree)) {
259
260 /* first in list */
261 LIST_INSERT_HEAD(&sitree, new, chain);
262 }
263 else {
264 int npri, spri;
265 struct sainfo *s, *n;
266
267 /*
268 * insert our new sainfo section
269 * into our list which is sorted
270 * based on the match priority
271 */
272
273 npri = prisainfo(new);
274
275 s = LIST_FIRST(&sitree);
276 while (1) {
277
278 spri = prisainfo(s);
279 n = LIST_NEXT(s, chain);
280
281 if(npri > spri)
282 {
283 /* higher priority */
284 LIST_INSERT_BEFORE(s, new, chain);
285 return;
286 }
287
288 if(n == NULL)
289 {
290 /* last in list */
291 LIST_INSERT_AFTER(s, new, chain);
292 return;
293 }
294
295 s = n;
296 }
297 }
298 }
299
300 void
remsainfo(si)301 remsainfo(si)
302 struct sainfo *si;
303 {
304 LIST_REMOVE(si, chain);
305 }
306
307 void
flushsainfo()308 flushsainfo()
309 {
310 struct sainfo *s, *next;
311
312 for (s = LIST_FIRST(&sitree); s; s = next) {
313 next = LIST_NEXT(s, chain);
314 remsainfo(s);
315 delsainfo(s);
316 }
317 }
318
319 void
initsainfo()320 initsainfo()
321 {
322 LIST_INIT(&sitree);
323 }
324
325 struct sainfoalg *
newsainfoalg()326 newsainfoalg()
327 {
328 struct sainfoalg *new;
329
330 new = racoon_calloc(1, sizeof(*new));
331 if (new == NULL)
332 return NULL;
333
334 return new;
335 }
336
337 void
delsainfoalg(alg)338 delsainfoalg(alg)
339 struct sainfoalg *alg;
340 {
341 struct sainfoalg *a, *next;
342
343 for (a = alg; a; a = next) {
344 next = a->next;
345 racoon_free(a);
346 }
347 }
348
349 void
inssainfoalg(head,new)350 inssainfoalg(head, new)
351 struct sainfoalg **head;
352 struct sainfoalg *new;
353 {
354 struct sainfoalg *a;
355
356 for (a = *head; a && a->next; a = a->next)
357 ;
358 if (a)
359 a->next = new;
360 else
361 *head = new;
362 }
363
364 const char *
sainfo2str(si)365 sainfo2str(si)
366 const struct sainfo *si;
367 {
368 static char buf[256];
369
370 char *idloc = NULL, *idrmt = NULL, *id_i;
371
372 if (si->idsrc == SAINFO_ANONYMOUS)
373 idloc = strdup("ANONYMOUS");
374 else
375 idloc = ipsecdoi_id2str(si->idsrc);
376
377 if (si->iddst == SAINFO_ANONYMOUS)
378 idrmt = strdup("ANONYMOUS");
379 else if (si->iddst == SAINFO_CLIENTADDR)
380 idrmt = strdup("CLIENTADDR");
381 else
382 idrmt = ipsecdoi_id2str(si->iddst);
383
384 if (si->id_i == NULL)
385 id_i = strdup("ANY");
386 else
387 id_i = ipsecdoi_id2str(si->id_i);
388
389 snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%u",
390 idloc, idrmt, id_i, si->remoteid);
391
392 racoon_free(idloc);
393 racoon_free(idrmt);
394 racoon_free(id_i);
395
396 return buf;
397 }
398
sainfo_start_reload(void)399 void sainfo_start_reload(void){
400 sitree_save=sitree;
401 initsainfo();
402 }
403
sainfo_finish_reload(void)404 void sainfo_finish_reload(void){
405 sainfo_tailq_head_t sitree_tmp;
406
407 sitree_tmp=sitree;
408 sitree=sitree_save;
409 flushsainfo();
410 sitree=sitree_tmp;
411 }
412
save_sainfotree_restore(void)413 void save_sainfotree_restore(void){
414 flushsainfo();
415 sitree=sitree_save;
416 }
417