1 /* $NetBSD: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $ */
2
3 /* $Id: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu 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 PATH_IPSEC_H
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <errno.h>
48
49 #include "var.h"
50 #include "misc.h"
51 #include "vmbuf.h"
52 #include "plog.h"
53 #include "sockmisc.h"
54 #include "debug.h"
55
56 #include "policy.h"
57 #include "pfkey.h"
58 #include "isakmp_var.h"
59 #include "isakmp.h"
60 #include "ipsec_doi.h"
61 #include "algorithm.h"
62 #include "proposal.h"
63 #include "sainfo.h"
64 #include "localconf.h"
65 #include "remoteconf.h"
66 #include "oakley.h"
67 #include "handler.h"
68 #include "strnames.h"
69 #include "gcmalloc.h"
70 #ifdef ENABLE_NATT
71 #include "nattraversal.h"
72 #endif
73
74 static uint g_nextreqid = 1;
75
76 /* %%%
77 * modules for ipsec sa spec
78 */
79 struct saprop *
newsaprop()80 newsaprop()
81 {
82 struct saprop *new;
83
84 new = racoon_calloc(1, sizeof(*new));
85 if (new == NULL)
86 return NULL;
87
88 return new;
89 }
90
91 struct saproto *
newsaproto()92 newsaproto()
93 {
94 struct saproto *new;
95
96 new = racoon_calloc(1, sizeof(*new));
97 if (new == NULL)
98 return NULL;
99
100 return new;
101 }
102
103 /* set saprop to last part of the prop tree */
104 void
inssaprop(head,new)105 inssaprop(head, new)
106 struct saprop **head;
107 struct saprop *new;
108 {
109 struct saprop *p;
110
111 if (*head == NULL) {
112 *head = new;
113 return;
114 }
115
116 for (p = *head; p->next; p = p->next)
117 ;
118 p->next = new;
119
120 return;
121 }
122
123 /* set saproto to the end of the proto tree in saprop */
124 void
inssaproto(pp,new)125 inssaproto(pp, new)
126 struct saprop *pp;
127 struct saproto *new;
128 {
129 struct saproto *p;
130
131 for (p = pp->head; p && p->next; p = p->next)
132 ;
133 if (p == NULL)
134 pp->head = new;
135 else
136 p->next = new;
137
138 return;
139 }
140
141 /* set saproto to the top of the proto tree in saprop */
142 void
inssaprotorev(pp,new)143 inssaprotorev(pp, new)
144 struct saprop *pp;
145 struct saproto *new;
146 {
147 new->next = pp->head;
148 pp->head = new;
149
150 return;
151 }
152
153 struct satrns *
newsatrns()154 newsatrns()
155 {
156 struct satrns *new;
157
158 new = racoon_calloc(1, sizeof(*new));
159 if (new == NULL)
160 return NULL;
161
162 return new;
163 }
164
165 /* set saproto to last part of the proto tree in saprop */
166 void
inssatrns(pr,new)167 inssatrns(pr, new)
168 struct saproto *pr;
169 struct satrns *new;
170 {
171 struct satrns *tr;
172
173 for (tr = pr->head; tr && tr->next; tr = tr->next)
174 ;
175 if (tr == NULL)
176 pr->head = new;
177 else
178 tr->next = new;
179
180 return;
181 }
182
183 /*
184 * take a single match between saprop. allocate a new proposal and return it
185 * for future use (like picking single proposal from a bundle).
186 * pp1: peer's proposal.
187 * pp2: my proposal.
188 * NOTE: In the case of initiator, must be ensured that there is no
189 * modification of the proposal by calling cmp_aproppair_i() before
190 * this function.
191 * XXX cannot understand the comment!
192 */
193 struct saprop *
cmpsaprop_alloc(ph1,pp1,pp2,side)194 cmpsaprop_alloc(ph1, pp1, pp2, side)
195 struct ph1handle *ph1;
196 const struct saprop *pp1, *pp2;
197 int side;
198 {
199 struct saprop *newpp = NULL;
200 struct saproto *pr1, *pr2, *newpr = NULL;
201 struct satrns *tr1, *tr2, *newtr;
202 const int ordermatters = 0;
203 int npr1, npr2;
204 int spisizematch;
205
206 newpp = newsaprop();
207 if (newpp == NULL) {
208 plog(LLV_ERROR, LOCATION, NULL,
209 "failed to allocate saprop.\n");
210 return NULL;
211 }
212 newpp->prop_no = pp1->prop_no;
213
214 /* see proposal.h about lifetime/key length and PFS selection. */
215
216 /* check time/bytes lifetime and PFS */
217 switch (ph1->rmconf->pcheck_level) {
218 case PROP_CHECK_OBEY:
219 newpp->lifetime = pp1->lifetime;
220 newpp->lifebyte = pp1->lifebyte;
221 newpp->pfs_group = pp1->pfs_group;
222 break;
223
224 case PROP_CHECK_STRICT:
225 if (pp1->lifetime > pp2->lifetime) {
226 plog(LLV_ERROR, LOCATION, NULL,
227 "long lifetime proposed: "
228 "my:%d peer:%d\n",
229 (int)pp2->lifetime, (int)pp1->lifetime);
230 goto err;
231 }
232 if (pp1->lifebyte > pp2->lifebyte) {
233 plog(LLV_ERROR, LOCATION, NULL,
234 "long lifebyte proposed: "
235 "my:%d peer:%d\n",
236 pp2->lifebyte, pp1->lifebyte);
237 goto err;
238 }
239 newpp->lifetime = pp1->lifetime;
240 newpp->lifebyte = pp1->lifebyte;
241
242 prop_pfs_check:
243 if (pp2->pfs_group != 0 && pp1->pfs_group != pp2->pfs_group) {
244 plog(LLV_ERROR, LOCATION, NULL,
245 "pfs group mismatched: "
246 "my:%d peer:%d\n",
247 pp2->pfs_group, pp1->pfs_group);
248 goto err;
249 }
250 newpp->pfs_group = pp1->pfs_group;
251 break;
252
253 case PROP_CHECK_CLAIM:
254 /* lifetime */
255 if (pp1->lifetime <= pp2->lifetime) {
256 newpp->lifetime = pp1->lifetime;
257 } else {
258 newpp->lifetime = pp2->lifetime;
259 newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
260 plog(LLV_NOTIFY, LOCATION, NULL,
261 "use own lifetime: "
262 "my:%d peer:%d\n",
263 (int)pp2->lifetime, (int)pp1->lifetime);
264 }
265
266 /* lifebyte */
267 if (pp1->lifebyte > pp2->lifebyte) {
268 newpp->lifebyte = pp2->lifebyte;
269 newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
270 plog(LLV_NOTIFY, LOCATION, NULL,
271 "use own lifebyte: "
272 "my:%d peer:%d\n",
273 pp2->lifebyte, pp1->lifebyte);
274 }
275 newpp->lifebyte = pp1->lifebyte;
276
277 goto prop_pfs_check;
278 break;
279
280 case PROP_CHECK_EXACT:
281 if (pp1->lifetime != pp2->lifetime) {
282 plog(LLV_ERROR, LOCATION, NULL,
283 "lifetime mismatched: "
284 "my:%d peer:%d\n",
285 (int)pp2->lifetime, (int)pp1->lifetime);
286 goto err;
287 }
288
289 if (pp1->lifebyte != pp2->lifebyte) {
290 plog(LLV_ERROR, LOCATION, NULL,
291 "lifebyte mismatched: "
292 "my:%d peer:%d\n",
293 pp2->lifebyte, pp1->lifebyte);
294 goto err;
295 }
296 if (pp1->pfs_group != pp2->pfs_group) {
297 plog(LLV_ERROR, LOCATION, NULL,
298 "pfs group mismatched: "
299 "my:%d peer:%d\n",
300 pp2->pfs_group, pp1->pfs_group);
301 goto err;
302 }
303 newpp->lifetime = pp1->lifetime;
304 newpp->lifebyte = pp1->lifebyte;
305 newpp->pfs_group = pp1->pfs_group;
306 break;
307
308 default:
309 plog(LLV_ERROR, LOCATION, NULL,
310 "invalid pcheck_level why?.\n");
311 goto err;
312 }
313
314 #ifdef HAVE_SECCTX
315 /* check the security_context properties.
316 * It is possible for one side to have a security context
317 * and the other side doesn't. If so, this is an error.
318 */
319
320 if (*pp1->sctx.ctx_str && !(*pp2->sctx.ctx_str)) {
321 plog(LLV_ERROR, LOCATION, NULL,
322 "My proposal missing security context\n");
323 goto err;
324 }
325 if (!(*pp1->sctx.ctx_str) && *pp2->sctx.ctx_str) {
326 plog(LLV_ERROR, LOCATION, NULL,
327 "Peer is missing security context\n");
328 goto err;
329 }
330
331 if (*pp1->sctx.ctx_str && *pp2->sctx.ctx_str) {
332 if (pp1->sctx.ctx_doi == pp2->sctx.ctx_doi)
333 newpp->sctx.ctx_doi = pp1->sctx.ctx_doi;
334 else {
335 plog(LLV_ERROR, LOCATION, NULL,
336 "sec doi mismatched: my:%d peer:%d\n",
337 pp2->sctx.ctx_doi, pp1->sctx.ctx_doi);
338 goto err;
339 }
340
341 if (pp1->sctx.ctx_alg == pp2->sctx.ctx_alg)
342 newpp->sctx.ctx_alg = pp1->sctx.ctx_alg;
343 else {
344 plog(LLV_ERROR, LOCATION, NULL,
345 "sec alg mismatched: my:%d peer:%d\n",
346 pp2->sctx.ctx_alg, pp1->sctx.ctx_alg);
347 goto err;
348 }
349
350 if ((pp1->sctx.ctx_strlen != pp2->sctx.ctx_strlen) ||
351 memcmp(pp1->sctx.ctx_str, pp2->sctx.ctx_str,
352 pp1->sctx.ctx_strlen) != 0) {
353 plog(LLV_ERROR, LOCATION, NULL,
354 "sec ctx string mismatched: my:%s peer:%s\n",
355 pp2->sctx.ctx_str, pp1->sctx.ctx_str);
356 goto err;
357 } else {
358 newpp->sctx.ctx_strlen = pp1->sctx.ctx_strlen;
359 memcpy(newpp->sctx.ctx_str, pp1->sctx.ctx_str,
360 pp1->sctx.ctx_strlen);
361 }
362 }
363 #endif /* HAVE_SECCTX */
364
365 npr1 = npr2 = 0;
366 for (pr1 = pp1->head; pr1; pr1 = pr1->next)
367 npr1++;
368 for (pr2 = pp2->head; pr2; pr2 = pr2->next)
369 npr2++;
370 if (npr1 != npr2)
371 goto err;
372
373 /* check protocol order */
374 pr1 = pp1->head;
375 pr2 = pp2->head;
376
377 while (1) {
378 if (!ordermatters) {
379 /*
380 * XXX does not work if we have multiple proposals
381 * with the same proto_id
382 */
383 switch (side) {
384 case RESPONDER:
385 if (!pr2)
386 break;
387 for (pr1 = pp1->head; pr1; pr1 = pr1->next) {
388 if (pr1->proto_id == pr2->proto_id)
389 break;
390 }
391 break;
392 case INITIATOR:
393 if (!pr1)
394 break;
395 for (pr2 = pp2->head; pr2; pr2 = pr2->next) {
396 if (pr2->proto_id == pr1->proto_id)
397 break;
398 }
399 break;
400 }
401 }
402 if (!pr1 || !pr2)
403 break;
404
405 if (pr1->proto_id != pr2->proto_id) {
406 plog(LLV_ERROR, LOCATION, NULL,
407 "proto_id mismatched: "
408 "my:%s peer:%s\n",
409 s_ipsecdoi_proto(pr2->proto_id),
410 s_ipsecdoi_proto(pr1->proto_id));
411 goto err;
412 }
413 spisizematch = 0;
414 if (pr1->spisize == pr2->spisize)
415 spisizematch = 1;
416 else if (pr1->proto_id == IPSECDOI_PROTO_IPCOMP) {
417 /*
418 * draft-shacham-ippcp-rfc2393bis-05.txt:
419 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
420 */
421 if (pr1->spisize == sizeof(u_int16_t) &&
422 pr2->spisize == sizeof(u_int32_t)) {
423 spisizematch = 1;
424 } else if (pr2->spisize == sizeof(u_int16_t) &&
425 pr1->spisize == sizeof(u_int32_t)) {
426 spisizematch = 1;
427 }
428 if (spisizematch) {
429 plog(LLV_ERROR, LOCATION, NULL,
430 "IPComp SPI size promoted "
431 "from 16bit to 32bit\n");
432 }
433 }
434 if (!spisizematch) {
435 plog(LLV_ERROR, LOCATION, NULL,
436 "spisize mismatched: "
437 "my:%d peer:%d\n",
438 (int)pr2->spisize, (int)pr1->spisize);
439 goto err;
440 }
441
442 #ifdef ENABLE_NATT
443 if ((ph1->natt_flags & NAT_DETECTED) &&
444 natt_udp_encap (pr2->encmode))
445 {
446 plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s->%s\n",
447 s_ipsecdoi_encmode(pr2->encmode),
448 s_ipsecdoi_encmode(pr2->encmode - ph1->natt_options->mode_udp_diff));
449 pr2->encmode -= ph1->natt_options->mode_udp_diff;
450 pr2->udp_encap = 1;
451 }
452
453 if ((ph1->natt_flags & NAT_DETECTED) &&
454 natt_udp_encap (pr1->encmode))
455 {
456 plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
457 s_ipsecdoi_encmode(pr1->encmode),
458 pr1->encmode,
459 s_ipsecdoi_encmode(pr1->encmode - ph1->natt_options->mode_udp_diff),
460 pr1->encmode - ph1->natt_options->mode_udp_diff);
461 pr1->encmode -= ph1->natt_options->mode_udp_diff;
462 pr1->udp_encap = 1;
463 }
464 #endif
465
466 if (pr1->encmode != pr2->encmode) {
467 plog(LLV_ERROR, LOCATION, NULL,
468 "encmode mismatched: "
469 "my:%s peer:%s\n",
470 s_ipsecdoi_encmode(pr2->encmode),
471 s_ipsecdoi_encmode(pr1->encmode));
472 goto err;
473 }
474
475 for (tr1 = pr1->head; tr1; tr1 = tr1->next) {
476 for (tr2 = pr2->head; tr2; tr2 = tr2->next) {
477 if (cmpsatrns(pr1->proto_id, tr1, tr2, ph1->rmconf->pcheck_level) == 0)
478 goto found;
479 }
480 }
481
482 goto err;
483
484 found:
485 newpr = newsaproto();
486 if (newpr == NULL) {
487 plog(LLV_ERROR, LOCATION, NULL,
488 "failed to allocate saproto.\n");
489 goto err;
490 }
491 newpr->proto_id = pr1->proto_id;
492 newpr->spisize = pr1->spisize;
493 newpr->encmode = pr1->encmode;
494 newpr->spi = pr2->spi; /* copy my SPI */
495 newpr->spi_p = pr1->spi; /* copy peer's SPI */
496 newpr->reqid_in = pr2->reqid_in;
497 newpr->reqid_out = pr2->reqid_out;
498 #ifdef ENABLE_NATT
499 newpr->udp_encap = pr1->udp_encap | pr2->udp_encap;
500 #endif
501
502 newtr = newsatrns();
503 if (newtr == NULL) {
504 plog(LLV_ERROR, LOCATION, NULL,
505 "failed to allocate satrns.\n");
506 racoon_free(newpr);
507 goto err;
508 }
509 newtr->trns_no = tr1->trns_no;
510 newtr->trns_id = tr1->trns_id;
511 newtr->encklen = tr1->encklen;
512 newtr->authtype = tr1->authtype;
513
514 inssatrns(newpr, newtr);
515 inssaproto(newpp, newpr);
516
517 pr1 = pr1->next;
518 pr2 = pr2->next;
519 }
520
521 /* XXX should check if we have visited all items or not */
522 if (!ordermatters) {
523 switch (side) {
524 case RESPONDER:
525 if (!pr2)
526 pr1 = NULL;
527 break;
528 case INITIATOR:
529 if (!pr1)
530 pr2 = NULL;
531 break;
532 }
533 }
534
535 /* should be matched all protocols in a proposal */
536 if (pr1 != NULL || pr2 != NULL)
537 goto err;
538
539 return newpp;
540
541 err:
542 flushsaprop(newpp);
543 return NULL;
544 }
545
546 /* take a single match between saprop. returns 0 if pp1 equals to pp2. */
547 int
cmpsaprop(pp1,pp2)548 cmpsaprop(pp1, pp2)
549 const struct saprop *pp1, *pp2;
550 {
551 if (pp1->pfs_group != pp2->pfs_group) {
552 plog(LLV_WARNING, LOCATION, NULL,
553 "pfs_group mismatch. mine:%d peer:%d\n",
554 pp1->pfs_group, pp2->pfs_group);
555 /* FALLTHRU */
556 }
557
558 if (pp1->lifetime > pp2->lifetime) {
559 plog(LLV_WARNING, LOCATION, NULL,
560 "less lifetime proposed. mine:%d peer:%d\n",
561 (int)pp1->lifetime, (int)pp2->lifetime);
562 /* FALLTHRU */
563 }
564 if (pp1->lifebyte > pp2->lifebyte) {
565 plog(LLV_WARNING, LOCATION, NULL,
566 "less lifebyte proposed. mine:%d peer:%d\n",
567 pp1->lifebyte, pp2->lifebyte);
568 /* FALLTHRU */
569 }
570
571 return 0;
572 }
573
574 /*
575 * take a single match between satrns. returns 0 if tr1 equals to tr2.
576 * tr1: peer's satrns
577 * tr2: my satrns
578 */
579 int
cmpsatrns(proto_id,tr1,tr2,check_level)580 cmpsatrns(proto_id, tr1, tr2, check_level)
581 int proto_id;
582 const struct satrns *tr1, *tr2;
583 int check_level;
584 {
585 if (tr1->trns_id != tr2->trns_id) {
586 plog(LLV_WARNING, LOCATION, NULL,
587 "trns_id mismatched: "
588 "my:%s peer:%s\n",
589 s_ipsecdoi_trns(proto_id, tr2->trns_id),
590 s_ipsecdoi_trns(proto_id, tr1->trns_id));
591 return 1;
592 }
593
594 if (tr1->authtype != tr2->authtype) {
595 plog(LLV_WARNING, LOCATION, NULL,
596 "authtype mismatched: "
597 "my:%s peer:%s\n",
598 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr2->authtype),
599 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr1->authtype));
600 return 1;
601 }
602
603 /* Check key length regarding checkmode
604 * XXX Shall we send some kind of notify message when key length rejected ?
605 */
606 switch(check_level){
607 case PROP_CHECK_OBEY:
608 return 0;
609 break;
610
611 case PROP_CHECK_STRICT:
612 /* FALLTHROUGH */
613 case PROP_CHECK_CLAIM:
614 if (tr1->encklen < tr2->encklen) {
615 plog(LLV_WARNING, LOCATION, NULL,
616 "low key length proposed, "
617 "mine:%d peer:%d.\n",
618 tr2->encklen, tr1->encklen);
619 return 1;
620 }
621 break;
622 case PROP_CHECK_EXACT:
623 if (tr1->encklen != tr2->encklen) {
624 plog(LLV_WARNING, LOCATION, NULL,
625 "key length mismatched, "
626 "mine:%d peer:%d.\n",
627 tr2->encklen, tr1->encklen);
628 return 1;
629 }
630 break;
631 }
632
633 return 0;
634 }
635
636 int
set_satrnsbysainfo(pr,sainfo)637 set_satrnsbysainfo(pr, sainfo)
638 struct saproto *pr;
639 struct sainfo *sainfo;
640 {
641 struct sainfoalg *a, *b;
642 struct satrns *newtr;
643 int t;
644
645 switch (pr->proto_id) {
646 case IPSECDOI_PROTO_IPSEC_AH:
647 if (sainfo->algs[algclass_ipsec_auth] == NULL) {
648 plog(LLV_ERROR, LOCATION, NULL,
649 "no auth algorithm found\n");
650 goto err;
651 }
652 t = 1;
653 for (a = sainfo->algs[algclass_ipsec_auth]; a; a = a->next) {
654
655 if (a->alg == IPSECDOI_ATTR_AUTH_NONE)
656 continue;
657
658 /* allocate satrns */
659 newtr = newsatrns();
660 if (newtr == NULL) {
661 plog(LLV_ERROR, LOCATION, NULL,
662 "failed to allocate satrns.\n");
663 goto err;
664 }
665
666 newtr->trns_no = t++;
667 newtr->trns_id = ipsecdoi_authalg2trnsid(a->alg);
668 newtr->authtype = a->alg;
669
670 inssatrns(pr, newtr);
671 }
672 break;
673 case IPSECDOI_PROTO_IPSEC_ESP:
674 if (sainfo->algs[algclass_ipsec_enc] == NULL) {
675 plog(LLV_ERROR, LOCATION, NULL,
676 "no encryption algorithm found\n");
677 goto err;
678 }
679 t = 1;
680 for (a = sainfo->algs[algclass_ipsec_enc]; a; a = a->next) {
681 for (b = sainfo->algs[algclass_ipsec_auth]; b; b = b->next) {
682 /* allocate satrns */
683 newtr = newsatrns();
684 if (newtr == NULL) {
685 plog(LLV_ERROR, LOCATION, NULL,
686 "failed to allocate satrns.\n");
687 goto err;
688 }
689
690 newtr->trns_no = t++;
691 newtr->trns_id = a->alg;
692 newtr->encklen = a->encklen;
693 newtr->authtype = b->alg;
694
695 inssatrns(pr, newtr);
696 }
697 }
698 break;
699 case IPSECDOI_PROTO_IPCOMP:
700 if (sainfo->algs[algclass_ipsec_comp] == NULL) {
701 plog(LLV_ERROR, LOCATION, NULL,
702 "no ipcomp algorithm found\n");
703 goto err;
704 }
705 t = 1;
706 for (a = sainfo->algs[algclass_ipsec_comp]; a; a = a->next) {
707
708 /* allocate satrns */
709 newtr = newsatrns();
710 if (newtr == NULL) {
711 plog(LLV_ERROR, LOCATION, NULL,
712 "failed to allocate satrns.\n");
713 goto err;
714 }
715
716 newtr->trns_no = t++;
717 newtr->trns_id = a->alg;
718 newtr->authtype = IPSECDOI_ATTR_AUTH_NONE; /*no auth*/
719
720 inssatrns(pr, newtr);
721 }
722 break;
723 default:
724 plog(LLV_ERROR, LOCATION, NULL,
725 "unknown proto_id (%d).\n", pr->proto_id);
726 goto err;
727 }
728
729 /* no proposal found */
730 if (pr->head == NULL) {
731 plog(LLV_ERROR, LOCATION, NULL, "no algorithms found.\n");
732 return -1;
733 }
734
735 return 0;
736
737 err:
738 flushsatrns(pr->head);
739 return -1;
740 }
741
742 struct saprop *
aproppair2saprop(p0)743 aproppair2saprop(p0)
744 struct prop_pair *p0;
745 {
746 struct prop_pair *p, *t;
747 struct saprop *newpp;
748 struct saproto *newpr;
749 struct satrns *newtr;
750 u_int8_t *spi;
751
752 if (p0 == NULL)
753 return NULL;
754
755 /* allocate ipsec a sa proposal */
756 newpp = newsaprop();
757 if (newpp == NULL) {
758 plog(LLV_ERROR, LOCATION, NULL,
759 "failed to allocate saprop.\n");
760 return NULL;
761 }
762 newpp->prop_no = p0->prop->p_no;
763 /* lifetime & lifebyte must be updated later */
764
765 for (p = p0; p; p = p->next) {
766
767 /* allocate ipsec sa protocol */
768 newpr = newsaproto();
769 if (newpr == NULL) {
770 plog(LLV_ERROR, LOCATION, NULL,
771 "failed to allocate saproto.\n");
772 goto err;
773 }
774
775 /* check spi size */
776 /* XXX should be handled isakmp cookie */
777 if (sizeof(newpr->spi) < p->prop->spi_size) {
778 plog(LLV_ERROR, LOCATION, NULL,
779 "invalid spi size %d.\n", p->prop->spi_size);
780 racoon_free(newpr);
781 goto err;
782 }
783
784 /*
785 * XXX SPI bits are left-filled, for use with IPComp.
786 * we should be switching to variable-length spi field...
787 */
788 newpr->proto_id = p->prop->proto_id;
789 newpr->spisize = p->prop->spi_size;
790 memset(&newpr->spi, 0, sizeof(newpr->spi));
791 spi = (u_int8_t *)&newpr->spi;
792 spi += sizeof(newpr->spi);
793 spi -= p->prop->spi_size;
794 memcpy(spi, p->prop + 1, p->prop->spi_size);
795 newpr->reqid_in = 0;
796 newpr->reqid_out = 0;
797
798 for (t = p; t; t = t->tnext) {
799
800 plog(LLV_DEBUG, LOCATION, NULL,
801 "prop#=%d prot-id=%s spi-size=%d "
802 "#trns=%d trns#=%d trns-id=%s\n",
803 t->prop->p_no,
804 s_ipsecdoi_proto(t->prop->proto_id),
805 t->prop->spi_size, t->prop->num_t,
806 t->trns->t_no,
807 s_ipsecdoi_trns(t->prop->proto_id,
808 t->trns->t_id));
809
810 /* allocate ipsec sa transform */
811 newtr = newsatrns();
812 if (newtr == NULL) {
813 plog(LLV_ERROR, LOCATION, NULL,
814 "failed to allocate satrns.\n");
815 racoon_free(newpr);
816 goto err;
817 }
818
819 if (ipsecdoi_t2satrns(t->trns,
820 newpp, newpr, newtr) < 0) {
821 flushsaprop(newpp);
822 racoon_free(newtr);
823 racoon_free(newpr);
824 return NULL;
825 }
826
827 inssatrns(newpr, newtr);
828 }
829
830 /*
831 * If the peer does not specify encryption mode, use
832 * transport mode by default. This is to conform to
833 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
834 * that unspecified == transport), as well as RFC2407
835 * (unspecified == implementation dependent default).
836 */
837 if (newpr->encmode == 0)
838 newpr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS;
839
840 inssaproto(newpp, newpr);
841 }
842
843 return newpp;
844
845 err:
846 flushsaprop(newpp);
847 return NULL;
848 }
849
850 void
flushsaprop(head)851 flushsaprop(head)
852 struct saprop *head;
853 {
854 struct saprop *p, *save;
855
856 for (p = head; p != NULL; p = save) {
857 save = p->next;
858 flushsaproto(p->head);
859 racoon_free(p);
860 }
861
862 return;
863 }
864
865 void
flushsaproto(head)866 flushsaproto(head)
867 struct saproto *head;
868 {
869 struct saproto *p, *save;
870
871 for (p = head; p != NULL; p = save) {
872 save = p->next;
873 flushsatrns(p->head);
874 vfree(p->keymat);
875 vfree(p->keymat_p);
876 racoon_free(p);
877 }
878
879 return;
880 }
881
882 void
flushsatrns(head)883 flushsatrns(head)
884 struct satrns *head;
885 {
886 struct satrns *p, *save;
887
888 for (p = head; p != NULL; p = save) {
889 save = p->next;
890 racoon_free(p);
891 }
892
893 return;
894 }
895
896 /*
897 * print multiple proposals
898 */
899 void
printsaprop(pri,pp)900 printsaprop(pri, pp)
901 const int pri;
902 const struct saprop *pp;
903 {
904 const struct saprop *p;
905
906 if (pp == NULL) {
907 plog(pri, LOCATION, NULL, "(null)");
908 return;
909 }
910
911 for (p = pp; p; p = p->next) {
912 printsaprop0(pri, p);
913 }
914
915 return;
916 }
917
918 /*
919 * print one proposal.
920 */
921 void
printsaprop0(pri,pp)922 printsaprop0(pri, pp)
923 int pri;
924 const struct saprop *pp;
925 {
926 const struct saproto *p;
927
928 if (pp == NULL)
929 return;
930
931 for (p = pp->head; p; p = p->next) {
932 printsaproto(pri, p);
933 }
934
935 return;
936 }
937
938 void
printsaproto(pri,pr)939 printsaproto(pri, pr)
940 const int pri;
941 const struct saproto *pr;
942 {
943 struct satrns *tr;
944
945 if (pr == NULL)
946 return;
947
948 plog(pri, LOCATION, NULL,
949 " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
950 "encmode=%s reqid=%d:%d)\n",
951 s_ipsecdoi_proto(pr->proto_id),
952 (int)pr->spisize,
953 (unsigned long)ntohl(pr->spi),
954 (unsigned long)ntohl(pr->spi_p),
955 s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE, pr->encmode),
956 (int)pr->reqid_in, (int)pr->reqid_out);
957
958 for (tr = pr->head; tr; tr = tr->next) {
959 printsatrns(pri, pr->proto_id, tr);
960 }
961
962 return;
963 }
964
965 void
printsatrns(pri,proto_id,tr)966 printsatrns(pri, proto_id, tr)
967 const int pri;
968 const int proto_id;
969 const struct satrns *tr;
970 {
971 if (tr == NULL)
972 return;
973
974 switch (proto_id) {
975 case IPSECDOI_PROTO_IPSEC_AH:
976 plog(pri, LOCATION, NULL,
977 " (trns_id=%s authtype=%s)\n",
978 s_ipsecdoi_trns(proto_id, tr->trns_id),
979 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
980 break;
981 case IPSECDOI_PROTO_IPSEC_ESP:
982 plog(pri, LOCATION, NULL,
983 " (trns_id=%s encklen=%d authtype=%s)\n",
984 s_ipsecdoi_trns(proto_id, tr->trns_id),
985 tr->encklen,
986 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
987 break;
988 case IPSECDOI_PROTO_IPCOMP:
989 plog(pri, LOCATION, NULL,
990 " (trns_id=%s)\n",
991 s_ipsecdoi_trns(proto_id, tr->trns_id));
992 break;
993 default:
994 plog(pri, LOCATION, NULL,
995 "(unknown proto_id %d)\n", proto_id);
996 }
997
998 return;
999 }
1000
1001 void
print_proppair0(pri,p,level)1002 print_proppair0(pri, p, level)
1003 int pri;
1004 struct prop_pair *p;
1005 int level;
1006 {
1007 char spc[21];
1008
1009 memset(spc, ' ', sizeof(spc));
1010 spc[sizeof(spc) - 1] = '\0';
1011 if (level < 20) {
1012 spc[level] = '\0';
1013 }
1014
1015 plog(pri, LOCATION, NULL,
1016 "%s%p: next=%p tnext=%p\n", spc, p, p->next, p->tnext);
1017 if (p->next)
1018 print_proppair0(pri, p->next, level + 1);
1019 if (p->tnext)
1020 print_proppair0(pri, p->tnext, level + 1);
1021 }
1022
1023 void
print_proppair(pri,p)1024 print_proppair(pri, p)
1025 int pri;
1026 struct prop_pair *p;
1027 {
1028 print_proppair0(pri, p, 1);
1029 }
1030
1031 int
set_proposal_from_policy(iph2,sp_main,sp_sub)1032 set_proposal_from_policy(iph2, sp_main, sp_sub)
1033 struct ph2handle *iph2;
1034 struct secpolicy *sp_main, *sp_sub;
1035 {
1036 struct saprop *newpp;
1037 struct ipsecrequest *req;
1038 int encmodesv = IPSECDOI_ATTR_ENC_MODE_TRNS; /* use only when complex_bundle */
1039
1040 newpp = newsaprop();
1041 if (newpp == NULL) {
1042 plog(LLV_ERROR, LOCATION, NULL,
1043 "failed to allocate saprop.\n");
1044 goto err;
1045 }
1046 newpp->prop_no = 1;
1047 newpp->lifetime = iph2->sainfo->lifetime;
1048 newpp->lifebyte = iph2->sainfo->lifebyte;
1049 newpp->pfs_group = iph2->sainfo->pfs_group;
1050
1051 if (lcconf->complex_bundle)
1052 goto skip1;
1053
1054 /*
1055 * decide the encryption mode of this SA bundle.
1056 * the mode becomes tunnel mode when there is even one policy
1057 * of tunnel mode in the SPD. otherwise the mode becomes
1058 * transport mode.
1059 */
1060 for (req = sp_main->req; req; req = req->next) {
1061 if (req->saidx.mode == IPSEC_MODE_TUNNEL) {
1062 encmodesv = pfkey2ipsecdoi_mode(req->saidx.mode);
1063 #ifdef ENABLE_NATT
1064 if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
1065 encmodesv += iph2->ph1->natt_options->mode_udp_diff;
1066 #endif
1067 break;
1068 }
1069 }
1070
1071 skip1:
1072 for (req = sp_main->req; req; req = req->next) {
1073 struct saproto *newpr;
1074 caddr_t paddr = NULL;
1075
1076 /*
1077 * check if SA bundle ?
1078 * nested SAs negotiation is NOT supported.
1079 * me +--- SA1 ---+ peer1
1080 * me +--- SA2 --------------+ peer2
1081 */
1082 #ifdef __linux__
1083 if (req->saidx.src.ss_family && req->saidx.dst.ss_family) {
1084 #else
1085 if (req->saidx.src.ss_len && req->saidx.dst.ss_len) {
1086 #endif
1087 /* check the end of ip addresses of SA */
1088 if (iph2->side == INITIATOR)
1089 paddr = (caddr_t)&req->saidx.dst;
1090 else
1091 paddr = (caddr_t)&req->saidx.src;
1092 }
1093
1094 /* allocate ipsec sa protocol */
1095 newpr = newsaproto();
1096 if (newpr == NULL) {
1097 plog(LLV_ERROR, LOCATION, NULL,
1098 "failed to allocate saproto.\n");
1099 goto err;
1100 }
1101
1102 newpr->proto_id = ipproto2doi(req->saidx.proto);
1103 if (newpr->proto_id == IPSECDOI_PROTO_IPCOMP)
1104 newpr->spisize = 2;
1105 else
1106 newpr->spisize = 4;
1107 if (lcconf->complex_bundle) {
1108 newpr->encmode = pfkey2ipsecdoi_mode(req->saidx.mode);
1109 #ifdef ENABLE_NATT
1110 if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
1111 newpr->encmode +=
1112 iph2->ph1->natt_options->mode_udp_diff;
1113 #endif
1114 }
1115 else
1116 newpr->encmode = encmodesv;
1117
1118 if (iph2->side == INITIATOR)
1119 newpr->reqid_out = req->saidx.reqid;
1120 else
1121 newpr->reqid_in = req->saidx.reqid;
1122
1123 if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0) {
1124 plog(LLV_ERROR, LOCATION, NULL,
1125 "failed to get algorithms.\n");
1126 racoon_free(newpr);
1127 goto err;
1128 }
1129
1130 /* set new saproto */
1131 inssaprotorev(newpp, newpr);
1132 }
1133
1134 /* get reqid_in from inbound policy */
1135 if (sp_sub) {
1136 struct saproto *pr;
1137
1138 req = sp_sub->req;
1139 pr = newpp->head;
1140 while (req && pr) {
1141 if (iph2->side == INITIATOR)
1142 pr->reqid_in = req->saidx.reqid;
1143 else
1144 pr->reqid_out = req->saidx.reqid;
1145 pr = pr->next;
1146 req = req->next;
1147 }
1148 if (pr || req) {
1149 plog(LLV_NOTIFY, LOCATION, NULL,
1150 "There is a difference "
1151 "between the in/out bound policies in SPD.\n");
1152 }
1153 }
1154
1155 iph2->proposal = newpp;
1156
1157 printsaprop0(LLV_DEBUG, newpp);
1158
1159 return 0;
1160 err:
1161 flushsaprop(newpp);
1162 return -1;
1163 }
1164
1165 /*
1166 * generate a policy from peer's proposal.
1167 * this function unconditionally choices first proposal in SA payload
1168 * passed by peer.
1169 */
1170 int
set_proposal_from_proposal(iph2)1171 set_proposal_from_proposal(iph2)
1172 struct ph2handle *iph2;
1173 {
1174 struct saprop *newpp = NULL, *pp0, *pp_peer = NULL;
1175 struct saproto *newpr = NULL, *pr;
1176 struct prop_pair **pair;
1177 int error = -1;
1178 int i;
1179
1180 /* get proposal pair */
1181 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
1182 if (pair == NULL)
1183 goto end;
1184
1185 /*
1186 * make my proposal according as the client proposal.
1187 * XXX assumed there is only one proposal even if it's the SA bundle.
1188 */
1189 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1190 if (pair[i] == NULL)
1191 continue;
1192
1193 if (pp_peer != NULL)
1194 flushsaprop(pp_peer);
1195
1196 pp_peer = aproppair2saprop(pair[i]);
1197 if (pp_peer == NULL)
1198 goto end;
1199
1200 pp0 = newsaprop();
1201 if (pp0 == NULL) {
1202 plog(LLV_ERROR, LOCATION, NULL,
1203 "failed to allocate saprop.\n");
1204 goto end;
1205 }
1206 pp0->prop_no = 1;
1207 pp0->lifetime = iph2->sainfo->lifetime;
1208 pp0->lifebyte = iph2->sainfo->lifebyte;
1209 pp0->pfs_group = iph2->sainfo->pfs_group;
1210
1211 #ifdef HAVE_SECCTX
1212 if (*pp_peer->sctx.ctx_str) {
1213 pp0->sctx.ctx_doi = pp_peer->sctx.ctx_doi;
1214 pp0->sctx.ctx_alg = pp_peer->sctx.ctx_alg;
1215 pp0->sctx.ctx_strlen = pp_peer->sctx.ctx_strlen;
1216 memcpy(pp0->sctx.ctx_str, pp_peer->sctx.ctx_str,
1217 pp_peer->sctx.ctx_strlen);
1218 }
1219 #endif /* HAVE_SECCTX */
1220
1221 if (pp_peer->next != NULL) {
1222 plog(LLV_ERROR, LOCATION, NULL,
1223 "pp_peer is inconsistency, ignore it.\n");
1224 /*FALLTHROUGH*/
1225 }
1226
1227 for (pr = pp_peer->head; pr; pr = pr->next)
1228 {
1229 struct remoteconf *conf;
1230
1231 newpr = newsaproto();
1232 if (newpr == NULL)
1233 {
1234 plog(LLV_ERROR, LOCATION, NULL,
1235 "failed to allocate saproto.\n");
1236 racoon_free(pp0);
1237 goto end;
1238 }
1239 newpr->proto_id = pr->proto_id;
1240 newpr->spisize = pr->spisize;
1241 newpr->encmode = pr->encmode;
1242 newpr->spi = 0;
1243 newpr->spi_p = pr->spi; /* copy peer's SPI */
1244 newpr->reqid_in = 0;
1245 newpr->reqid_out = 0;
1246
1247 conf = getrmconf(iph2->dst);
1248 if (conf != NULL &&
1249 conf->gen_policy == GENERATE_POLICY_UNIQUE){
1250 newpr->reqid_in = g_nextreqid ;
1251 newpr->reqid_out = g_nextreqid ++;
1252 /*
1253 * XXX there is a (very limited)
1254 * risk of reusing the same reqid
1255 * as another SP entry for the same peer
1256 */
1257 if(g_nextreqid >= IPSEC_MANUAL_REQID_MAX)
1258 g_nextreqid = 1;
1259 }else{
1260 newpr->reqid_in = 0;
1261 newpr->reqid_out = 0;
1262 }
1263
1264 if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0)
1265 {
1266 plog(LLV_ERROR, LOCATION, NULL,
1267 "failed to get algorithms.\n");
1268 racoon_free(newpr);
1269 racoon_free(pp0);
1270 goto end;
1271 }
1272 inssaproto(pp0, newpr);
1273 }
1274
1275 inssaprop(&newpp, pp0);
1276 }
1277
1278 plog(LLV_DEBUG, LOCATION, NULL, "make a proposal from peer's:\n");
1279 printsaprop0(LLV_DEBUG, newpp);
1280
1281 iph2->proposal = newpp;
1282
1283 error = 0;
1284
1285 end:
1286 if (error && newpp)
1287 flushsaprop(newpp);
1288
1289 if (pp_peer)
1290 flushsaprop(pp_peer);
1291 if (pair)
1292 free_proppair(pair);
1293 return error;
1294 }
1295