1 /* $KAME: ipsec_doi.c,v 1.168 2004/03/03 02:28:46 sakane Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <config.h>
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37
38 #include <netinet/in.h>
39
40 #ifdef HAVE_NETINET6_IPSEC_H
41 # include <netinet6/ipsec.h>
42 #else
43 # ifdef HAVE_NETIPSEC_IPSEC_H
44 # include <netipsec/ipsec.h>
45 # else
46 # include <linux/ipsec.h>
47 # endif
48 #endif
49
50 #include <assert.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <errno.h>
55 #include <netdb.h>
56 #if TIME_WITH_SYS_TIME
57 # include <sys/time.h>
58 # include <time.h>
59 #else
60 # if HAVE_SYS_TIME_H
61 # include <sys/time.h>
62 # else
63 # include <time.h>
64 # endif
65 #endif
66
67 #include "racoon.h"
68
69 #include "var.h"
70 /* #include "vmbuf.h" */
71 /* #include "misc.h" */
72 #include "plog.h"
73 #include "debug.h"
74
75 /* #include "cfparse_proto.h" */
76 #include "isakmp.h"
77 #include "isakmp_impl.h"
78 #include "isakmp_var.h"
79 #include "ikev1_impl.h"
80 #include "ipsec_doi.h"
81 #include "dhgroup.h"
82 #include "oakley.h"
83 #include "remoteconf.h"
84 /* #include "localconf.h" */
85 #include "sockmisc.h"
86 #include "handler.h"
87 /* #include "policy.h" */
88 #include "algorithm.h"
89 /* #include "sainfo.h" */
90 #include "proposal.h"
91 #include "crypto_impl.h"
92 #include "strnames.h"
93 #include "gcmalloc.h"
94
95 #ifdef ENABLE_NATT
96 #include "ikev1_natt.h"
97 #endif
98 #ifdef HAVE_GSSAPI
99 #include "gssapi.h"
100 #endif
101
102 #include "ike_conf.h"
103
104 int verbose_proposal_check = 1;
105
106 static rc_vchar_t *get_ph1approval (struct ph1handle *,
107 struct prop_pair **);
108 static struct isakmpsa *get_ph1approvalx (struct prop_pair *,
109 struct isakmpsa *, struct isakmpsa *, rc_type);
110 static void print_ph1mismatched (struct prop_pair *, struct isakmpsa *);
111 static int t2isakmpsa (struct isakmp_pl_t *, struct isakmpsa *);
112 static int cmp_aproppair_i (struct prop_pair *, struct prop_pair *);
113 static struct prop_pair *get_ph2approval (struct ph2handle *,
114 struct prop_pair **);
115 static struct prop_pair *get_ph2approvalx (struct ph2handle *,
116 struct prop_pair *);
117 static void free_proppair0 (struct prop_pair *);
118
119 static int get_transform
120 (struct isakmp_pl_p *, struct prop_pair **, int *);
121 static uint32_t ipsecdoi_set_ld (rc_vchar_t *);
122
123 static int check_doi (uint32_t);
124 static int check_situation (uint32_t);
125
126 static int check_prot_main (int);
127 static int check_prot_quick (int);
128 static int (*check_protocol[]) (int) = {
129 check_prot_main, /* IPSECDOI_TYPE_PH1 */
130 check_prot_quick, /* IPSECDOI_TYPE_PH2 */
131 };
132
133 static int check_spi_size (int, int);
134
135 static int check_trns_isakmp (int);
136 static int check_trns_ah (int);
137 static int check_trns_esp (int);
138 static int check_trns_ipcomp (int);
139 static int (*check_transform[]) (int) = {
140 0,
141 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
142 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
143 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
144 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
145 };
146
147 static int check_attr_isakmp (struct isakmp_pl_t *);
148 static int check_attr_ah (struct isakmp_pl_t *);
149 static int check_attr_esp (struct isakmp_pl_t *);
150 static int check_attr_ipsec (int, struct isakmp_pl_t *);
151 static int check_attr_ipcomp (struct isakmp_pl_t *);
152 static int (*check_attributes[]) (struct isakmp_pl_t *) = {
153 0,
154 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
155 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
156 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
157 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
158 };
159
160 static int setph1prop (struct isakmpsa *, caddr_t);
161 static int setph1trns (struct isakmpsa *, caddr_t);
162 static int setph1attr (struct isakmpsa *, caddr_t);
163 static rc_vchar_t *setph2proposal0 (const struct ph2handle *,
164 const struct saprop *, const struct saproto *);
165
166 #if 0
167 static rc_vchar_t *getidval (int, rc_vchar_t *);
168 #endif
169
170 #ifdef HAVE_GSSAPI
171 static struct isakmpsa *fixup_initiator_sa (struct isakmpsa *,
172 struct isakmpsa *);
173 #endif
174
175 /*%%%*/
176 /*
177 * check phase 1 SA payload.
178 * make new SA payload to be replyed not including general header.
179 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
180 * OUT:
181 * positive: the pointer to new buffer of SA payload.
182 * network byte order.
183 * NULL : error occurd.
184 */
185 int
186 ipsecdoi_checkph1proposal(sa, iph1)
187 rc_vchar_t *sa;
188 struct ph1handle *iph1;
189 {
190 rc_vchar_t *newsa; /* new SA payload approved. */
191 struct prop_pair **pair;
192
193 /* get proposal pair */
194 pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
195 if (pair == NULL)
196 return -1;
197
198 /* check and get one SA for use */
199 newsa = get_ph1approval(iph1, pair);
200
201 free_proppair(pair);
202
203 if (newsa == NULL)
204 return -1;
205
206 iph1->sa_ret = newsa;
207
208 return 0;
209 }
210
211 /*
212 * acceptable check for remote configuration.
213 * return a new SA payload to be reply to peer.
214 */
215 static rc_vchar_t *
216 get_ph1approval(iph1, pair)
217 struct ph1handle *iph1;
218 struct prop_pair **pair;
219 {
220 rc_vchar_t *newsa;
221 struct isakmpsa *sa, tsa;
222 struct prop_pair *s, *p;
223 int prophlen;
224 int i;
225
226 if (iph1->approval) {
227 delisakmpsa(iph1->approval);
228 iph1->approval = NULL;
229 }
230
231 for (i = 0; i < MAXPROPPAIRLEN; i++) {
232 if (pair[i] == NULL)
233 continue;
234 for (s = pair[i]; s; s = s->next) {
235 prophlen = sizeof(struct isakmp_pl_p)
236 + s->prop->spi_size;
237 /* compare proposal and select one */
238 for (p = s; p; p = p->tnext) {
239 sa = get_ph1approvalx(p, iph1->proposal,
240 &tsa,
241 ikev1_proposal_check(iph1->rmconf));
242 if (sa != NULL)
243 goto found;
244 }
245 }
246 }
247
248 /*
249 * if there is no suitable proposal, racoon complains about all of
250 * mismatched items in those proposal.
251 */
252 if (verbose_proposal_check) {
253 for (i = 0; i < MAXPROPPAIRLEN; i++) {
254 if (pair[i] == NULL)
255 continue;
256 for (s = pair[i]; s; s = s->next) {
257 prophlen = sizeof(struct isakmp_pl_p)
258 + s->prop->spi_size;
259 for (p = s; p; p = p->tnext) {
260 print_ph1mismatched(p,
261 iph1->proposal);
262 }
263 }
264 }
265 }
266 plog(PLOG_PROTOERR, PLOGLOC, NULL, "no suitable proposal found.\n");
267
268 return NULL;
269
270 found:
271 plog(PLOG_DEBUG, PLOGLOC, NULL, "an acceptable proposal found.\n");
272
273 /* check DH group settings */
274 if (sa->dhgrp) {
275 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
276 /* it's ok */
277 goto saok;
278 }
279 plog(PLOG_PROTOWARN, PLOGLOC, 0,
280 "invalid DH parameter found, use default.\n");
281 oakley_dhgrp_free(sa->dhgrp);
282 sa->dhgrp = NULL;
283 }
284
285 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
286 racoon_free(sa);
287 return NULL;
288 }
289
290 saok:
291 #ifdef HAVE_GSSAPI
292 if (sa->gssid != NULL)
293 plog(PLOG_DEBUG, PLOGLOC, NULL, "gss id in new sa '%s'\n",
294 sa->gssid->v);
295 if (iph1-> side == INITIATOR) {
296 if (iph1->proposal->gssid != NULL)
297 iph1->gi_i = rc_vdup(iph1->proposal->gssid);
298 if (tsa.gssid != NULL)
299 iph1->gi_r = rc_vdup(tsa.gssid);
300 iph1->approval = fixup_initiator_sa(sa, &tsa);
301 } else {
302 if (tsa.gssid != NULL) {
303 iph1->gi_r = rc_vdup(tsa.gssid);
304 if (iph1->proposal->gssid != NULL)
305 iph1->gi_i =
306 rc_vdup(iph1->proposal->gssid);
307 else
308 iph1->gi_i = gssapi_get_default_id(iph1);
309 if (sa->gssid == NULL && iph1->gi_i != NULL)
310 sa->gssid = rc_vdup(iph1->gi_i);
311 }
312 iph1->approval = sa;
313 }
314 if (iph1->gi_i != NULL)
315 plog(PLOG_DEBUG, PLOGLOC, NULL, "GIi is %*s\n",
316 iph1->gi_i->l, iph1->gi_i->v);
317 if (iph1->gi_r != NULL)
318 plog(PLOG_DEBUG, PLOGLOC, NULL, "GIr is %*s\n",
319 iph1->gi_r->l, iph1->gi_r->v);
320 #else
321 iph1->approval = sa;
322 #endif
323
324 newsa = get_sabyproppair(p, iph1);
325 if (newsa == NULL && iph1->approval != NULL) {
326 delisakmpsa(iph1->approval);
327 iph1->approval = NULL;
328 }
329
330 return newsa;
331 }
332
333 /*
334 * compare peer's single proposal and all of my proposal.
335 * and select one if suiatable.
336 * p : one of peer's proposal.
337 * proposal: my proposals.
338 */
339 static struct isakmpsa *
340 get_ph1approvalx(p, proposal, sap, check_level)
341 struct prop_pair *p;
342 struct isakmpsa *proposal, *sap;
343 rc_type check_level;
344 {
345 struct isakmp_pl_p *prop = p->prop;
346 struct isakmp_pl_t *trns = p->trns;
347 struct isakmpsa sa, *s, *tsap;
348
349 plog(PLOG_DEBUG, PLOGLOC, NULL,
350 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
351 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
352 prop->spi_size, prop->num_t);
353
354 plog(PLOG_DEBUG, PLOGLOC, NULL,
355 "trns#=%d, trns-id=%s\n",
356 trns->t_no,
357 s_ipsecdoi_trns(prop->proto_id, trns->t_id));
358
359 tsap = sap != NULL ? sap : &sa;
360
361 memset(tsap, 0, sizeof(*tsap));
362 if (t2isakmpsa(trns, tsap) < 0)
363 return NULL;
364 for (s = proposal; s != NULL; s = s->next) {
365 int authmethod;
366
367 #ifdef ENABLE_HYBRID
368 authmethod = switch_authmethod(s->authmethod);
369 #else
370 authmethod = s->authmethod;
371 #endif
372 plog(PLOG_DEBUG, PLOGLOC, NULL, "Compared: DB:Peer\n");
373 plog(PLOG_DEBUG, PLOGLOC, NULL, "(lifetime = %ld:%ld)\n",
374 (long)s->lifetime, (long)tsap->lifetime);
375 plog(PLOG_DEBUG, PLOGLOC, NULL, "(lifebyte = %zu:%zu)\n",
376 s->lifebyte, tsap->lifebyte);
377 plog(PLOG_DEBUG, PLOGLOC, NULL, "enctype = %s:%s\n",
378 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
379 s->enctype),
380 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
381 tsap->enctype));
382 plog(PLOG_DEBUG, PLOGLOC, NULL, "(encklen = %d:%d)\n",
383 s->encklen, tsap->encklen);
384 plog(PLOG_DEBUG, PLOGLOC, NULL, "hashtype = %s:%s\n",
385 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
386 s->hashtype),
387 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
388 tsap->hashtype));
389 plog(PLOG_DEBUG, PLOGLOC, NULL, "authmethod = %s:%s\n",
390 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
391 authmethod),
392 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
393 tsap->authmethod));
394 plog(PLOG_DEBUG, PLOGLOC, NULL, "dh_group = %s:%s\n",
395 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
396 s->dh_group),
397 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
398 tsap->dh_group));
399 #if 0
400 /* XXX to be considered ? */
401 if (tsap->lifebyte > s->lifebyte) ;
402 #endif
403 /*
404 * if responder side and peer's key length in proposal
405 * is bigger than mine, it might be accepted.
406 */
407 if(tsap->enctype == s->enctype &&
408 tsap->authmethod == authmethod &&
409 tsap->hashtype == s->hashtype &&
410 tsap->dh_group == s->dh_group &&
411 tsap->encklen == s->encklen) {
412 switch(check_level) {
413 case RCT_PCT_OBEY:
414 goto found;
415 break;
416
417 case RCT_PCT_STRICT:
418 if ((s->lifetime != 0 &&
419 tsap->lifetime > s->lifetime) ||
420 (s->lifebyte != 0 &&
421 tsap->lifebyte > s->lifebyte))
422 continue;
423 goto found;
424 break;
425
426 case RCT_PCT_CLAIM:
427 if (s->lifetime == 0 ||
428 tsap->lifetime < s->lifetime)
429 s->lifetime = tsap->lifetime;
430 if (s->lifebyte == 0 ||
431 tsap->lifebyte < s->lifebyte)
432 s->lifebyte = tsap->lifebyte;
433 goto found;
434 break;
435
436 case RCT_PCT_EXACT:
437 if ((tsap->lifetime != s->lifetime) ||
438 (tsap->lifebyte != s->lifebyte))
439 continue;
440 goto found;
441 break;
442
443 default:
444 plog(PLOG_PROTOERR, PLOGLOC, NULL,
445 "Unexpected proposal_check value\n");
446 continue;
447 break;
448 }
449 }
450 }
451
452 found:
453 if (tsap->dhgrp != NULL) {
454 oakley_dhgrp_free(tsap->dhgrp);
455 tsap->dhgrp = NULL;
456 }
457
458 if ((s = dupisakmpsa(s)) != NULL) {
459 switch(check_level) {
460 case RCT_PCT_OBEY:
461 s->lifetime = tsap->lifetime;
462 s->lifebyte = tsap->lifebyte;
463 break;
464
465 case RCT_PCT_STRICT:
466 s->lifetime = tsap->lifetime;
467 s->lifebyte = tsap->lifebyte;
468 break;
469
470 case RCT_PCT_CLAIM:
471 if (tsap->lifetime < s->lifetime)
472 s->lifetime = tsap->lifetime;
473 if (tsap->lifebyte < s->lifebyte)
474 s->lifebyte = tsap->lifebyte;
475 break;
476
477 default:
478 break;
479 }
480 }
481
482 return s;
483 }
484
485 /*
486 * print all of items in peer's proposal which are mismatched to my proposal.
487 * p : one of peer's proposal.
488 * proposal: my proposals.
489 */
490 static void
491 print_ph1mismatched(p, proposal)
492 struct prop_pair *p;
493 struct isakmpsa *proposal;
494 {
495 struct isakmpsa sa, *s;
496
497 memset(&sa, 0, sizeof(sa));
498 if (t2isakmpsa(p->trns, &sa) < 0)
499 return;
500 for (s = proposal; s ; s = s->next) {
501 if (sa.enctype != s->enctype) {
502 plog(PLOG_PROTOERR, PLOGLOC, NULL,
503 "rejected enctype: "
504 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
505 "%s:%s\n",
506 s->prop_no, s->trns_no,
507 p->prop->p_no, p->trns->t_no,
508 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
509 s->enctype),
510 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
511 sa.enctype));
512 }
513 if (sa.authmethod != s->authmethod) {
514 plog(PLOG_PROTOERR, PLOGLOC, NULL,
515 "rejected authmethod: "
516 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
517 "%s:%s\n",
518 s->prop_no, s->trns_no,
519 p->prop->p_no, p->trns->t_no,
520 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
521 s->authmethod),
522 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
523 sa.authmethod));
524 }
525 if (sa.hashtype != s->hashtype) {
526 plog(PLOG_PROTOERR, PLOGLOC, NULL,
527 "rejected hashtype: "
528 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
529 "%s:%s\n",
530 s->prop_no, s->trns_no,
531 p->prop->p_no, p->trns->t_no,
532 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
533 s->hashtype),
534 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
535 sa.hashtype));
536 }
537 if (sa.dh_group != s->dh_group) {
538 plog(PLOG_PROTOERR, PLOGLOC, NULL,
539 "rejected dh_group: "
540 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
541 "%s:%s\n",
542 s->prop_no, s->trns_no,
543 p->prop->p_no, p->trns->t_no,
544 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
545 s->dh_group),
546 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
547 sa.dh_group));
548 }
549 }
550
551 if (sa.dhgrp != NULL)
552 oakley_dhgrp_free(sa.dhgrp);
553 }
554
555 /*
556 * get ISAKMP data attributes
557 */
558 static int
559 t2isakmpsa(trns, sa)
560 struct isakmp_pl_t *trns;
561 struct isakmpsa *sa;
562 {
563 struct isakmp_data *d, *prev;
564 int flag, type;
565 int error = -1;
566 int life_t;
567 int keylen = 0;
568 rc_vchar_t *val = NULL;
569 int len, tlen;
570 unsigned char *p;
571
572 tlen = get_uint16(&trns->h.len) - sizeof(*trns);
573 prev = (struct isakmp_data *)NULL;
574 d = (struct isakmp_data *)(trns + 1);
575
576 /* default */
577 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
578 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
579 sa->lifebyte = 0;
580 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
581 if (!sa->dhgrp)
582 goto err;
583
584 while (tlen > 0) {
585
586 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
587 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
588
589 plog(PLOG_DEBUG, PLOGLOC, NULL,
590 "type=%s, flag=0x%04x, lorv=%s\n",
591 s_oakley_attr(type), flag,
592 s_oakley_attr_v(type, get_uint16(&d->lorv)));
593
594 /* get variable-sized item */
595 switch (type) {
596 case OAKLEY_ATTR_GRP_PI:
597 case OAKLEY_ATTR_GRP_GEN_ONE:
598 case OAKLEY_ATTR_GRP_GEN_TWO:
599 case OAKLEY_ATTR_GRP_CURVE_A:
600 case OAKLEY_ATTR_GRP_CURVE_B:
601 case OAKLEY_ATTR_SA_LD:
602 case OAKLEY_ATTR_GRP_ORDER:
603 if (flag) { /*TV*/
604 len = 2;
605 p = (unsigned char *)&d->lorv;
606 } else { /*TLV*/
607 len = get_uint16(&d->lorv);
608 p = (unsigned char *)(d + 1);
609 }
610 val = rc_vmalloc(len);
611 if (!val)
612 return -1;
613 memcpy(val->v, p, len);
614 break;
615
616 default:
617 break;
618 }
619
620 switch (type) {
621 case OAKLEY_ATTR_ENC_ALG:
622 sa->enctype = get_uint16(&d->lorv);
623 break;
624
625 case OAKLEY_ATTR_HASH_ALG:
626 sa->hashtype = get_uint16(&d->lorv);
627 break;
628
629 case OAKLEY_ATTR_AUTH_METHOD:
630 sa->authmethod = get_uint16(&d->lorv);
631 break;
632
633 case OAKLEY_ATTR_GRP_DESC:
634 sa->dh_group = get_uint16(&d->lorv);
635 break;
636
637 case OAKLEY_ATTR_GRP_TYPE:
638 {
639 int type = get_uint16(&d->lorv);
640 if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
641 sa->dhgrp->type = type;
642 else
643 return -1;
644 break;
645 }
646 case OAKLEY_ATTR_GRP_PI:
647 sa->dhgrp->prime = val;
648 break;
649
650 case OAKLEY_ATTR_GRP_GEN_ONE:
651 rc_vfree(val);
652 if (!flag)
653 sa->dhgrp->gen1 = get_uint16(&d->lorv);
654 else {
655 int len = get_uint16(&d->lorv);
656 sa->dhgrp->gen1 = 0;
657 if (len > 4)
658 return -1;
659 memcpy(&sa->dhgrp->gen1, d + 1, len);
660 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
661 }
662 break;
663
664 case OAKLEY_ATTR_GRP_GEN_TWO:
665 rc_vfree(val);
666 if (!flag)
667 sa->dhgrp->gen2 = get_uint16(&d->lorv);
668 else {
669 int len = get_uint16(&d->lorv);
670 sa->dhgrp->gen2 = 0;
671 if (len > 4)
672 return -1;
673 memcpy(&sa->dhgrp->gen2, d + 1, len);
674 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
675 }
676 break;
677
678 case OAKLEY_ATTR_GRP_CURVE_A:
679 sa->dhgrp->curve_a = val;
680 break;
681
682 case OAKLEY_ATTR_GRP_CURVE_B:
683 sa->dhgrp->curve_b = val;
684 break;
685
686 case OAKLEY_ATTR_SA_LD_TYPE:
687 {
688 int type = get_uint16(&d->lorv);
689 switch (type) {
690 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
691 case OAKLEY_ATTR_SA_LD_TYPE_KB:
692 life_t = type;
693 break;
694 default:
695 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
696 break;
697 }
698 break;
699 }
700 case OAKLEY_ATTR_SA_LD:
701 if (!prev
702 || (get_uint16(&prev->type) & ~ISAKMP_GEN_MASK) !=
703 OAKLEY_ATTR_SA_LD_TYPE) {
704 plog(PLOG_PROTOERR, PLOGLOC, NULL,
705 "life duration must follow ltype\n");
706 break;
707 }
708
709 switch (life_t) {
710 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
711 sa->lifetime = ipsecdoi_set_ld(val);
712 rc_vfree(val);
713 if (sa->lifetime == 0) {
714 plog(PLOG_PROTOERR, PLOGLOC, NULL,
715 "invalid life duration.\n");
716 goto err;
717 }
718 break;
719 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
720 sa->lifebyte = ipsecdoi_set_ld(val);
721 rc_vfree(val);
722 if (sa->lifetime == 0) {
723 plog(PLOG_PROTOERR, PLOGLOC, NULL,
724 "invalid life duration.\n");
725 goto err;
726 }
727 break;
728 default:
729 rc_vfree(val);
730 plog(PLOG_PROTOERR, PLOGLOC, NULL,
731 "invalid life type: %d\n", life_t);
732 goto err;
733 }
734 break;
735
736 case OAKLEY_ATTR_KEY_LEN:
737 {
738 int len = get_uint16(&d->lorv);
739 if (len % 8 != 0) {
740 plog(PLOG_PROTOERR, PLOGLOC, NULL,
741 "keylen %d: not multiple of 8\n",
742 len);
743 goto err;
744 }
745 sa->encklen = (uint16_t)len;
746 keylen++;
747 break;
748 }
749 case OAKLEY_ATTR_PRF:
750 case OAKLEY_ATTR_FIELD_SIZE:
751 /* unsupported */
752 break;
753
754 case OAKLEY_ATTR_GRP_ORDER:
755 sa->dhgrp->order = val;
756 break;
757 #ifdef HAVE_GSSAPI
758 case OAKLEY_ATTR_GSS_ID:
759 {
760 int len = get_uint16(&d->lorv);
761
762 sa->gssid = rc_vmalloc(len);
763 memcpy(sa->gssid->v, d + 1, len);
764 plog(PLOG_DEBUG, PLOGLOC, NULL,
765 "received gss id '%s' (len %d)\n", sa->gssid->v,
766 sa->gssid->l);
767 break;
768 }
769 #endif
770
771 default:
772 break;
773 }
774
775 prev = d;
776 if (flag) {
777 tlen -= sizeof(*d);
778 d = (struct isakmp_data *)((char *)d + sizeof(*d));
779 } else {
780 tlen -= (sizeof(*d) + get_uint16(&d->lorv));
781 d = (struct isakmp_data *)((char *)d + sizeof(*d) + get_uint16(&d->lorv));
782 }
783 }
784
785 /* key length must not be specified on some algorithms */
786 if (keylen) {
787 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
788 #ifdef HAVE_OPENSSL_IDEA_H
789 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
790 #endif
791 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
792 plog(PLOG_PROTOERR, PLOGLOC, NULL,
793 "keylen must not be specified "
794 "for encryption algorithm %d\n",
795 sa->enctype);
796 return -1;
797 }
798 }
799
800 return 0;
801 err:
802 return error;
803 }
804
805 /*%%%*/
806 /*
807 * check phase 2 SA payload and select single proposal.
808 * make new SA payload to be replyed not including general header.
809 * This function is called by responder only.
810 * OUT:
811 * 0: succeed.
812 * -1: error occured.
813 */
814 int
815 ipsecdoi_selectph2proposal(iph2)
816 struct ph2handle *iph2;
817 {
818 struct prop_pair **pair;
819 struct prop_pair *ret;
820
821 /* get proposal pair */
822 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
823 if (pair == NULL)
824 return -1;
825
826 /* check and select a proposal. */
827 ret = get_ph2approval(iph2, pair);
828 free_proppair(pair);
829 if (ret == NULL)
830 return -1;
831
832 /* make a SA to be replayed. */
833 /* SPI must be updated later. */
834 iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
835 free_proppair0(ret);
836 if (iph2->sa_ret == NULL)
837 return -1;
838
839 return 0;
840 }
841
842 /*
843 * check phase 2 SA payload returned from responder.
844 * This function is called by initiator only.
845 * OUT:
846 * 0: valid.
847 * -1: invalid.
848 */
849 int
850 ipsecdoi_checkph2proposal(iph2)
851 struct ph2handle *iph2;
852 {
853 struct prop_pair **rpair = NULL, **spair = NULL;
854 struct prop_pair *p;
855 rc_vchar_t *old_sa;
856 int i, n, num;
857 int error = -1;
858
859 /* get proposal pair of SA sent. */
860 spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
861 if (spair == NULL) {
862 plog(PLOG_PROTOERR, PLOGLOC, NULL,
863 "failed to get prop pair.\n");
864 goto end;
865 }
866
867 /* XXX should check the number of transform */
868
869 /* get proposal pair of SA replyed */
870 rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
871 if (rpair == NULL) {
872 plog(PLOG_PROTOERR, PLOGLOC, NULL,
873 "failed to get prop pair.\n");
874 goto end;
875 }
876
877 /* check proposal is only one ? */
878 n = 0;
879 num = 0;
880 for (i = 0; i < MAXPROPPAIRLEN; i++) {
881 if (rpair[i]) {
882 n = i;
883 num++;
884 }
885 }
886 if (num == 0) {
887 plog(PLOG_PROTOERR, PLOGLOC, NULL,
888 "no proposal received.\n");
889 goto end;
890 }
891 if (num != 1) {
892 plog(PLOG_PROTOERR, PLOGLOC, NULL,
893 "some proposals received.\n");
894 goto end;
895 }
896
897 if (spair[n] == NULL) {
898 plog(PLOG_PROTOWARN, PLOGLOC, 0,
899 "invalid proposal number:%d received.\n", i);
900 }
901
902
903 if (rpair[n]->tnext != NULL) {
904 plog(PLOG_PROTOERR, PLOGLOC, NULL,
905 "multi transforms replyed.\n");
906 goto end;
907 }
908
909 if (cmp_aproppair_i(rpair[n], spair[n])) {
910 plog(PLOG_PROTOERR, PLOGLOC, NULL,
911 "proposal mismathed.\n");
912 goto end;
913 }
914
915 /*
916 * check and select a proposal.
917 * ensure that there is no modification of the proposal by
918 * cmp_aproppair_i()
919 */
920 p = get_ph2approval(iph2, rpair);
921 if (p == NULL)
922 goto end;
923
924 /* make a SA to be replayed. */
925 old_sa = iph2->sa_ret; /* since p->prop points inside iph2->sa_ret */
926 iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
927 rc_vfree(old_sa);
928 free_proppair0(p);
929 if (iph2->sa_ret == NULL)
930 goto end;
931
932 error = 0;
933
934 end:
935 if (rpair)
936 free_proppair(rpair);
937 if (spair)
938 free_proppair(spair);
939
940 return error;
941 }
942
943 /*
944 * compare two prop_pair which is assumed to have same proposal number.
945 * the case of bundle or single SA, NOT multi transforms.
946 * a: a proposal that is multi protocols and single transform, usually replyed.
947 * b: a proposal that is multi protocols and multi transform, usually sent.
948 * NOTE: this function is for initiator.
949 * OUT
950 * 0: equal
951 * 1: not equal
952 * XXX cannot understand the comment!
953 */
954 static int
955 cmp_aproppair_i(a, b)
956 struct prop_pair *a, *b;
957 {
958 struct prop_pair *p, *q, *r;
959 int len;
960
961 for (p = a, q = b; p && q; p = p->next, q = q->next) {
962 for (r = q; r; r = r->tnext) {
963 /* compare trns */
964 if (p->trns->t_no == r->trns->t_no)
965 break;
966 }
967 if (!r) {
968 /* no suitable transform found */
969 plog(PLOG_PROTOERR, PLOGLOC, NULL,
970 "no suitable transform found.\n");
971 return -1;
972 }
973
974 /* compare prop */
975 if (p->prop->p_no != r->prop->p_no) {
976 plog(PLOG_PROTOWARN, PLOGLOC, 0,
977 "proposal #%d mismatched, "
978 "expected #%d.\n",
979 r->prop->p_no, p->prop->p_no);
980 /*FALLTHROUGH*/
981 }
982
983 if (p->prop->proto_id != r->prop->proto_id) {
984 plog(PLOG_PROTOERR, PLOGLOC, NULL,
985 "proto_id mismathed: my:%d peer:%d\n",
986 r->prop->proto_id, p->prop->proto_id);
987 return -1;
988 }
989
990 if (p->prop->spi_size != r->prop->spi_size) {
991 plog(PLOG_PROTOERR, PLOGLOC, NULL,
992 "invalid spi size: %d.\n",
993 p->prop->spi_size);
994 return -1;
995 }
996
997 /* check #of transforms */
998 if (p->prop->num_t != 1) {
999 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1000 "#of transform is %d, "
1001 "but expected 1.\n", p->prop->num_t);
1002 /*FALLTHROUGH*/
1003 }
1004
1005 if (p->trns->t_id != r->trns->t_id) {
1006 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1007 "transform number has been modified.\n");
1008 /*FALLTHROUGH*/
1009 }
1010 if (p->trns->reserved != r->trns->reserved) {
1011 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1012 "reserved field should be zero.\n");
1013 /*FALLTHROUGH*/
1014 }
1015
1016 /* compare attribute */
1017 len = get_uint16(&r->trns->h.len) - sizeof(*p->trns);
1018 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
1019 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1020 "attribute has been modified.\n");
1021 /*FALLTHROUGH*/
1022 }
1023 }
1024 if ((p && !q) || (!p && q)) {
1025 /* # of protocols mismatched */
1026 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1027 "#of protocols mismatched.\n");
1028 return -1;
1029 }
1030
1031 return 0;
1032 }
1033
1034 /*
1035 * acceptable check for policy configuration.
1036 * return a new SA payload to be reply to peer.
1037 */
1038 static struct prop_pair *
1039 get_ph2approval(iph2, pair)
1040 struct ph2handle *iph2;
1041 struct prop_pair **pair;
1042 {
1043 struct prop_pair *ret;
1044 int i;
1045
1046 iph2->approval = NULL;
1047
1048 plog(PLOG_DEBUG, PLOGLOC, NULL,
1049 "begin compare proposals.\n");
1050
1051 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1052 if (pair[i] == NULL)
1053 continue;
1054 plog(PLOG_DEBUG, PLOGLOC, NULL,
1055 "pair[%d]: %p\n", i, pair[i]);
1056 print_proppair(PLOG_DEBUG, pair[i]);;
1057
1058 /* compare proposal and select one */
1059 ret = get_ph2approvalx(iph2, pair[i]);
1060 if (ret != NULL) {
1061 /* found */
1062 return ret;
1063 }
1064 }
1065
1066 plog(PLOG_PROTOERR, PLOGLOC, NULL, "no suitable policy found.\n");
1067
1068 return NULL;
1069 }
1070
1071 /*
1072 * compare my proposal and peers just one proposal.
1073 * set a approval.
1074 */
1075 static struct prop_pair *
1076 get_ph2approvalx(iph2, pp)
1077 struct ph2handle *iph2;
1078 struct prop_pair *pp;
1079 {
1080 struct prop_pair *ret = NULL;
1081 struct saprop *pr0, *pr = NULL;
1082 struct saprop *q1, *q2;
1083
1084 pr0 = aproppair2saprop(pp);
1085 if (pr0 == NULL)
1086 return NULL;
1087
1088 for (q1 = pr0; q1; q1 = q1->next) {
1089 for (q2 = iph2->proposal; q2; q2 = q2->next) {
1090 plog(PLOG_DEBUG, PLOGLOC, NULL,
1091 "peer's single bundle:\n");
1092 printsaprop0(PLOG_DEBUG, q1);
1093 plog(PLOG_DEBUG, PLOGLOC, NULL,
1094 "my single bundle:\n");
1095 printsaprop0(PLOG_DEBUG, q2);
1096
1097 pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1098 if (pr != NULL)
1099 goto found;
1100
1101 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1102 "not matched\n");
1103 }
1104 }
1105 /* no proposal matching */
1106 err:
1107 flushsaprop(pr0);
1108 return NULL;
1109
1110 found:
1111 flushsaprop(pr0);
1112 plog(PLOG_DEBUG, PLOGLOC, NULL, "matched\n");
1113 iph2->approval = pr;
1114
1115 {
1116 struct saproto *sp;
1117 struct prop_pair *p, *n, *x;
1118
1119 ret = NULL;
1120
1121 for (p = pp; p; p = p->next) {
1122 /*
1123 * find a proposal with matching proto_id.
1124 * we have analyzed validity already, in cmpsaprop_alloc().
1125 */
1126 for (sp = pr->head; sp; sp = sp->next) {
1127 if (sp->proto_id == p->prop->proto_id)
1128 break;
1129 }
1130 if (!sp)
1131 goto err;
1132 if (sp->head->next)
1133 goto err; /* XXX */
1134
1135 for (x = p; x; x = x->tnext)
1136 if (sp->head->trns_no == x->trns->t_no)
1137 break;
1138 if (!x)
1139 goto err; /* XXX */
1140
1141 n = racoon_calloc(1, sizeof(struct prop_pair));
1142 if (!n) {
1143 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1144 "failed to get buffer.\n");
1145 goto err;
1146 }
1147
1148 n->prop = x->prop;
1149 n->trns = x->trns;
1150
1151 /* need to preserve the order */
1152 for (x = ret; x && x->next; x = x->next)
1153 ;
1154 if (x && x->prop == n->prop) {
1155 for (/*nothing*/; x && x->tnext; x = x->tnext)
1156 ;
1157 x->tnext = n;
1158 } else {
1159 if (x)
1160 x->next = n;
1161 else {
1162 ret = n;
1163 }
1164 }
1165
1166 /* #of transforms should be updated ? */
1167 }
1168 }
1169
1170 return ret;
1171 }
1172
1173 void
1174 free_proppair(pair)
1175 struct prop_pair **pair;
1176 {
1177 int i;
1178
1179 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1180 free_proppair0(pair[i]);
1181 pair[i] = NULL;
1182 }
1183 racoon_free(pair);
1184 }
1185
1186 static void
1187 free_proppair0(pair)
1188 struct prop_pair *pair;
1189 {
1190 struct prop_pair *p, *q, *r, *s;
1191
1192 for (p = pair; p; p = q) {
1193 q = p->next;
1194 for (r = p; r; r = s) {
1195 s = r->tnext;
1196 racoon_free(r);
1197 }
1198 }
1199 }
1200
1201 /*
1202 * get proposal pairs from SA payload.
1203 * tiny check for proposal payload.
1204 */
1205 struct prop_pair **
1206 get_proppair(sa, mode)
1207 rc_vchar_t *sa;
1208 int mode;
1209 {
1210 struct prop_pair **pair = NULL;
1211 int num_p = 0; /* number of proposal for use */
1212 int tlen;
1213 caddr_t bp;
1214 int i;
1215 struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
1216
1217 plog(PLOG_DEBUG, PLOGLOC, NULL, "total SA len=%d\n", sa->l);
1218 plogdump(PLOG_DEBUG, PLOGLOC, 0, sa->v, sa->l);
1219
1220 /* check SA payload size */
1221 if (sa->l < sizeof(*sab)) {
1222 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1223 "Invalid SA length = %d.\n", sa->l);
1224 return NULL;
1225 }
1226
1227 /* check DOI */
1228 if (check_doi(get_uint32(&sab->doi)) < 0)
1229 return NULL;
1230
1231 /* check SITUATION */
1232 if (check_situation(get_uint32(&sab->sit)) < 0)
1233 return NULL;
1234
1235 pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1236 if (pair == NULL) {
1237 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1238 "failed to get buffer.\n");
1239 return NULL;
1240 }
1241 memset(pair, 0, sizeof(pair));
1242
1243 bp = (caddr_t)(sab + 1);
1244 tlen = sa->l - sizeof(*sab);
1245
1246 {
1247 struct isakmp_pl_p *prop;
1248 int proplen;
1249 rc_vchar_t *pbuf = NULL;
1250 struct isakmp_parse_t *pa;
1251
1252 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1253 if (pbuf == NULL)
1254 goto bad;
1255
1256 for (pa = (struct isakmp_parse_t *)pbuf->v;
1257 pa->type != ISAKMP_NPTYPE_NONE;
1258 pa++) {
1259 /* check the value of next payload */
1260 if (pa->type != ISAKMP_NPTYPE_P) {
1261 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1262 "Invalid payload type=%u\n", pa->type);
1263 rc_vfree(pbuf);
1264 goto bad;
1265 }
1266
1267 prop = (struct isakmp_pl_p *)pa->ptr;
1268 proplen = pa->len;
1269
1270 plog(PLOG_DEBUG, PLOGLOC, NULL,
1271 "proposal #%u len=%d\n", prop->p_no, proplen);
1272
1273 if (proplen == 0) {
1274 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1275 "invalid proposal with length %d\n", proplen);
1276 rc_vfree(pbuf);
1277 goto bad;
1278 }
1279
1280 /* check Protocol ID */
1281 if (!check_protocol[mode]) {
1282 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1283 "unsupported mode %d\n", mode);
1284 continue;
1285 }
1286
1287 if (check_protocol[mode](prop->proto_id) < 0)
1288 continue;
1289
1290 /* check SPI length when IKE. */
1291 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1292 continue;
1293
1294 /* get transform */
1295 if (get_transform(prop, pair, &num_p) < 0) {
1296 rc_vfree(pbuf);
1297 goto bad;
1298 }
1299 }
1300 rc_vfree(pbuf);
1301 pbuf = NULL;
1302 }
1303
1304 {
1305 int notrans, nprop;
1306 struct prop_pair *p, *q;
1307
1308 /* check for proposals with no transforms */
1309 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1310 if (!pair[i])
1311 continue;
1312
1313 plog(PLOG_DEBUG, PLOGLOC, NULL, "pair %d:\n", i);
1314 print_proppair(PLOG_DEBUG, pair[i]);
1315
1316 notrans = nprop = 0;
1317 for (p = pair[i]; p; p = p->next) {
1318 if (p->trns == NULL) {
1319 notrans++;
1320 break;
1321 }
1322 for (q = p; q; q = q->tnext)
1323 nprop++;
1324 }
1325
1326 #if 0
1327 /*
1328 * XXX at this moment, we cannot accept proposal group
1329 * with multiple proposals. this should be fixed.
1330 */
1331 if (pair[i]->next) {
1332 plog(LLV_WARNING, PLOGLOC, NULL,
1333 "proposal #%u ignored "
1334 "(multiple proposal not supported)\n",
1335 pair[i]->prop->p_no);
1336 notrans++;
1337 }
1338 #endif
1339
1340 if (notrans) {
1341 for (p = pair[i]; p; p = q) {
1342 q = p->next;
1343 racoon_free(p);
1344 }
1345 pair[i] = NULL;
1346 num_p--;
1347 } else {
1348 plog(PLOG_DEBUG, PLOGLOC, NULL,
1349 "proposal #%u: %d transform\n",
1350 pair[i]->prop->p_no, nprop);
1351 }
1352 }
1353 }
1354
1355 /* bark if no proposal is found. */
1356 if (num_p <= 0) {
1357 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1358 "no Proposal found.\n");
1359 goto bad;
1360 }
1361
1362 return pair;
1363
1364 bad:
1365 if (pair)
1366 racoon_free(pair);
1367 return NULL;
1368 }
1369
1370 /*
1371 * check transform payload.
1372 * OUT:
1373 * positive: return the pointer to the payload of valid transform.
1374 * 0 : No valid transform found.
1375 */
1376 static int
1377 get_transform(prop, pair, num_p)
1378 struct isakmp_pl_p *prop;
1379 struct prop_pair **pair;
1380 int *num_p;
1381 {
1382 int tlen; /* total length of all transform in a proposal */
1383 caddr_t bp;
1384 struct isakmp_pl_t *trns;
1385 int trnslen;
1386 rc_vchar_t *pbuf = NULL;
1387 struct isakmp_parse_t *pa;
1388 struct prop_pair *p = NULL, *q;
1389 int num_t;
1390
1391 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1392 tlen = get_uint16(&prop->h.len)
1393 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1394 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1395 if (pbuf == NULL)
1396 return -1;
1397
1398 /* check and get transform for use */
1399 num_t = 0;
1400 for (pa = (struct isakmp_parse_t *)pbuf->v;
1401 pa->type != ISAKMP_NPTYPE_NONE;
1402 pa++) {
1403
1404 num_t++;
1405
1406 /* check the value of next payload */
1407 if (pa->type != ISAKMP_NPTYPE_T) {
1408 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1409 "Invalid payload type=%u\n", pa->type);
1410 break;
1411 }
1412
1413 trns = (struct isakmp_pl_t *)pa->ptr;
1414 trnslen = pa->len;
1415
1416 plog(PLOG_DEBUG, PLOGLOC, NULL,
1417 "transform #%u len=%u\n", trns->t_no, trnslen);
1418
1419 /* check transform ID */
1420 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1421 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1422 "unsupported proto_id %u\n",
1423 prop->proto_id);
1424 continue;
1425 }
1426 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1427 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1428 "unsupported proto_id %u\n",
1429 prop->proto_id);
1430 continue;
1431 }
1432
1433 if (!check_transform[prop->proto_id]
1434 || !check_attributes[prop->proto_id]) {
1435 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1436 "unsupported proto_id %u\n",
1437 prop->proto_id);
1438 continue;
1439 }
1440 if (check_transform[prop->proto_id](trns->t_id) < 0)
1441 continue;
1442
1443 /* check data attributes */
1444 if (check_attributes[prop->proto_id](trns) != 0)
1445 continue;
1446
1447 p = racoon_calloc(1, sizeof(*p));
1448 if (p == NULL) {
1449 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1450 "failed to get buffer.\n");
1451 rc_vfree(pbuf);
1452 return -1;
1453 }
1454 p->prop = prop;
1455 p->trns = trns;
1456
1457 /* need to preserve the order */
1458 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1459 ;
1460 if (q && q->prop == p->prop) {
1461 for (/*nothing*/; q && q->tnext; q = q->tnext)
1462 ;
1463 q->tnext = p;
1464 } else {
1465 if (q)
1466 q->next = p;
1467 else {
1468 pair[prop->p_no] = p;
1469 (*num_p)++;
1470 }
1471 }
1472 }
1473
1474 rc_vfree(pbuf);
1475
1476 return 0;
1477 }
1478
1479 /*
1480 * make a new SA payload from prop_pair.
1481 * NOTE: this function make spi value clear.
1482 */
1483 rc_vchar_t *
1484 get_sabyproppair(pair, iph1)
1485 struct prop_pair *pair;
1486 struct ph1handle *iph1;
1487 {
1488 rc_vchar_t *newsa;
1489 int newtlen;
1490 uint8_t *np_p = NULL;
1491 struct prop_pair *p;
1492 int prophlen, trnslen;
1493 caddr_t bp;
1494
1495 newtlen = sizeof(struct ipsecdoi_sa_b);
1496 for (p = pair; p; p = p->next) {
1497 newtlen += (sizeof(struct isakmp_pl_p)
1498 + p->prop->spi_size
1499 + get_uint16(&p->trns->h.len));
1500 }
1501
1502 newsa = rc_vmalloc(newtlen);
1503 if (newsa == NULL) {
1504 plog(PLOG_PROTOERR, PLOGLOC, NULL, "failed to get newsa.\n");
1505 return NULL;
1506 }
1507 bp = newsa->v;
1508
1509 put_uint16(&((struct isakmp_gen *)bp)->len, newtlen);
1510
1511 /* update some of values in SA header */
1512 put_uint32(&((struct ipsecdoi_sa_b *)bp)->doi, ikev1_doitype(iph1->rmconf));
1513 put_uint32(&((struct ipsecdoi_sa_b *)bp)->sit, ikev1_sittype(iph1->rmconf));
1514 bp += sizeof(struct ipsecdoi_sa_b);
1515
1516 /* create proposal payloads */
1517 for (p = pair; p; p = p->next) {
1518 prophlen = sizeof(struct isakmp_pl_p)
1519 + p->prop->spi_size;
1520 trnslen = get_uint16(&p->trns->h.len);
1521
1522 if (np_p)
1523 *np_p = ISAKMP_NPTYPE_P;
1524
1525 /* create proposal */
1526
1527 memcpy(bp, p->prop, prophlen);
1528 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1529 put_uint16(&((struct isakmp_pl_p *)bp)->h.len, prophlen + trnslen);
1530 ((struct isakmp_pl_p *)bp)->num_t = 1;
1531 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1532 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1533 bp += prophlen;
1534
1535 /* create transform */
1536 memcpy(bp, p->trns, trnslen);
1537 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1538 put_uint16(&((struct isakmp_pl_t *)bp)->h.len, trnslen);
1539 bp += trnslen;
1540 }
1541
1542 return newsa;
1543 }
1544
1545 /*
1546 * update responder's spi
1547 */
1548 int
1549 ipsecdoi_updatespi(iph2)
1550 struct ph2handle *iph2;
1551 {
1552 struct prop_pair **pair, *p;
1553 struct saprop *pp;
1554 struct saproto *pr;
1555 int i;
1556 int error = -1;
1557 uint8_t *spi;
1558
1559 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1560 if (pair == NULL)
1561 return -1;
1562 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1563 if (pair[i])
1564 break;
1565 }
1566 if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1567 /* multiple transform must be filtered by selectph2proposal.*/
1568 goto end;
1569 }
1570
1571 pp = iph2->approval;
1572
1573 /* create proposal payloads */
1574 for (p = pair[i]; p; p = p->next) {
1575 /*
1576 * find a proposal/transform with matching proto_id/t_id.
1577 * we have analyzed validity already, in cmpsaprop_alloc().
1578 */
1579 for (pr = pp->head; pr; pr = pr->next) {
1580 if (p->prop->proto_id == pr->proto_id &&
1581 p->trns->t_id == pr->head->trns_id) {
1582 break;
1583 }
1584 }
1585 if (!pr)
1586 goto end;
1587
1588 /*
1589 * XXX SPI bits are left-filled, for use with IPComp.
1590 * we should be switching to variable-length spi field...
1591 */
1592 spi = (uint8_t *)&pr->spi;
1593 spi += sizeof(pr->spi);
1594 spi -= pr->spisize;
1595 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1596 }
1597
1598 error = 0;
1599 end:
1600 free_proppair(pair);
1601 return error;
1602 }
1603
1604 /*
1605 * make a new SA payload from prop_pair.
1606 */
1607 rc_vchar_t *
1608 get_sabysaprop(pp0, sa0)
1609 struct saprop *pp0;
1610 rc_vchar_t *sa0;
1611 {
1612 struct prop_pair **pair;
1613 rc_vchar_t *newsa = NULL;
1614 int newtlen;
1615 uint8_t *np_p = NULL;
1616 struct prop_pair *p = NULL;
1617 struct saprop *pp;
1618 struct saproto *pr;
1619 struct satrns *tr;
1620 int prophlen, trnslen;
1621 caddr_t bp;
1622 int error = -1;
1623
1624 /* get proposal pair */
1625 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1626 if (pair == NULL)
1627 return NULL;
1628
1629 newtlen = sizeof(struct ipsecdoi_sa_b);
1630 for (pp = pp0; pp; pp = pp->next) {
1631
1632 if (pair[pp->prop_no] == NULL)
1633 goto out;
1634
1635 for (pr = pp->head; pr; pr = pr->next) {
1636 newtlen += (sizeof(struct isakmp_pl_p)
1637 + pr->spisize);
1638
1639 for (tr = pr->head; tr; tr = tr->next) {
1640 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1641 if (tr->trns_no == p->trns->t_no)
1642 break;
1643 }
1644 if (p == NULL)
1645 goto out;
1646
1647 newtlen += get_uint16(&p->trns->h.len);
1648 }
1649 }
1650 }
1651
1652 newsa = rc_vmalloc(newtlen);
1653 if (newsa == NULL) {
1654 plog(PLOG_PROTOERR, PLOGLOC, NULL, "failed to get newsa.\n");
1655 goto out;
1656 }
1657 bp = newsa->v;
1658
1659 /* some of values of SA must be updated in the out of this function */
1660 put_uint16(&((struct isakmp_gen *)bp)->len, newtlen);
1661 bp += sizeof(struct ipsecdoi_sa_b);
1662
1663 /* create proposal payloads */
1664 for (pp = pp0; pp; pp = pp->next) {
1665
1666 for (pr = pp->head; pr; pr = pr->next) {
1667 prophlen = sizeof(struct isakmp_pl_p)
1668 + p->prop->spi_size;
1669
1670 for (tr = pr->head; tr; tr = tr->next) {
1671 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1672 if (tr->trns_no == p->trns->t_no)
1673 break;
1674 }
1675 if (p == NULL)
1676 goto out;
1677
1678 trnslen = get_uint16(&p->trns->h.len);
1679
1680 if (np_p)
1681 *np_p = ISAKMP_NPTYPE_P;
1682
1683 /* create proposal */
1684
1685 memcpy(bp, p->prop, prophlen);
1686 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1687 put_uint16(&((struct isakmp_pl_p *)bp)->h.len, prophlen + trnslen);
1688 ((struct isakmp_pl_p *)bp)->num_t = 1;
1689 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1690 bp += prophlen;
1691
1692 /* create transform */
1693 memcpy(bp, p->trns, trnslen);
1694 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1695 put_uint16(&((struct isakmp_pl_t *)bp)->h.len, trnslen);
1696 bp += trnslen;
1697 }
1698 }
1699 }
1700
1701 error = 0;
1702 out:
1703 if (pair != NULL)
1704 racoon_free(pair);
1705
1706 if (error != 0) {
1707 if (newsa)
1708 rc_vfree(newsa);
1709 newsa = NULL;
1710 }
1711
1712 return newsa;
1713 }
1714
1715 /*
1716 * If some error happens then return 0. Although 0 means that lifetime is zero,
1717 * such a value should not be accepted.
1718 * Also 0 of lifebyte should not be included in a packet although 0 means not
1719 * to care of it.
1720 */
1721 static uint32_t
1722 ipsecdoi_set_ld(buf)
1723 rc_vchar_t *buf;
1724 {
1725 uint32_t ld;
1726
1727 if (buf == 0)
1728 return 0;
1729
1730 switch (buf->l) {
1731 case 2:
1732 ld = get_uint16((uint16_t *)buf->v);
1733 break;
1734 case 4:
1735 ld = get_uint32((uint32_t *)buf->v);
1736 break;
1737 default:
1738 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1739 "length %d of life duration "
1740 "isn't supported.\n", buf->l);
1741 return 0;
1742 }
1743
1744 return ld;
1745 }
1746
1747 /*%%%*/
1748 /*
1749 * check DOI
1750 */
1751 static int
1752 check_doi(doi)
1753 uint32_t doi;
1754 {
1755 switch (doi) {
1756 case IPSEC_DOI:
1757 return 0;
1758 default:
1759 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1760 "invalid value of DOI 0x%08x.\n", doi);
1761 return -1;
1762 }
1763 /* NOT REACHED */
1764 }
1765
1766 /*
1767 * check situation
1768 */
1769 static int
1770 check_situation(sit)
1771 uint32_t sit;
1772 {
1773 switch (sit) {
1774 case IPSECDOI_SIT_IDENTITY_ONLY:
1775 return 0;
1776
1777 case IPSECDOI_SIT_SECRECY:
1778 case IPSECDOI_SIT_INTEGRITY:
1779 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1780 "situation 0x%08x unsupported yet.\n", sit);
1781 return -1;
1782
1783 default:
1784 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1785 "invalid situation 0x%08x.\n", sit);
1786 return -1;
1787 }
1788 /* NOT REACHED */
1789 }
1790
1791 /*
1792 * check protocol id in main mode
1793 */
1794 static int
1795 check_prot_main(proto_id)
1796 int proto_id;
1797 {
1798 switch (proto_id) {
1799 case IPSECDOI_PROTO_ISAKMP:
1800 return 0;
1801
1802 default:
1803 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1804 "Illegal protocol id=%u.\n", proto_id);
1805 return -1;
1806 }
1807 /* NOT REACHED */
1808 }
1809
1810 /*
1811 * check protocol id in quick mode
1812 */
1813 static int
1814 check_prot_quick(proto_id)
1815 int proto_id;
1816 {
1817 switch (proto_id) {
1818 case IPSECDOI_PROTO_IPSEC_AH:
1819 case IPSECDOI_PROTO_IPSEC_ESP:
1820 return 0;
1821
1822 case IPSECDOI_PROTO_IPCOMP:
1823 return 0;
1824
1825 default:
1826 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1827 "invalid protocol id %d.\n", proto_id);
1828 return -1;
1829 }
1830 /* NOT REACHED */
1831 }
1832
1833 static int
1834 check_spi_size(proto_id, size)
1835 int proto_id, size;
1836 {
1837 switch (proto_id) {
1838 case IPSECDOI_PROTO_ISAKMP:
1839 if (size != 0) {
1840 /* WARNING */
1841 plog(PLOG_DEBUG, PLOGLOC, NULL,
1842 "SPI size isn't zero, but IKE proposal.\n");
1843 }
1844 return 0;
1845
1846 case IPSECDOI_PROTO_IPSEC_AH:
1847 case IPSECDOI_PROTO_IPSEC_ESP:
1848 if (size != 4) {
1849 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1850 "invalid SPI size=%d for IPSEC proposal.\n",
1851 size);
1852 return -1;
1853 }
1854 return 0;
1855
1856 case IPSECDOI_PROTO_IPCOMP:
1857 if (size != 2 && size != 4) {
1858 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1859 "invalid SPI size=%d for IPCOMP proposal.\n",
1860 size);
1861 return -1;
1862 }
1863 return 0;
1864
1865 default:
1866 /* ??? */
1867 return -1;
1868 }
1869 /* NOT REACHED */
1870 }
1871
1872 /*
1873 * check transform ID in ISAKMP.
1874 */
1875 static int
1876 check_trns_isakmp(t_id)
1877 int t_id;
1878 {
1879 switch (t_id) {
1880 case IPSECDOI_KEY_IKE:
1881 return 0;
1882 default:
1883 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1884 "invalid transform-id=%u in proto_id=%u.\n",
1885 t_id, IPSECDOI_KEY_IKE);
1886 return -1;
1887 }
1888 /* NOT REACHED */
1889 }
1890
1891 /*
1892 * check transform ID in AH.
1893 */
1894 static int
1895 check_trns_ah(t_id)
1896 int t_id;
1897 {
1898 switch (t_id) {
1899 case IPSECDOI_AH_MD5:
1900 case IPSECDOI_AH_SHA:
1901 case IPSECDOI_AH_SHA256:
1902 case IPSECDOI_AH_SHA384:
1903 case IPSECDOI_AH_SHA512:
1904 return 0;
1905 case IPSECDOI_AH_DES:
1906 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1907 "not support transform-id=%u in AH.\n", t_id);
1908 return -1;
1909 default:
1910 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1911 "invalid transform-id=%u in AH.\n", t_id);
1912 return -1;
1913 }
1914 /* NOT REACHED */
1915 }
1916
1917 /*
1918 * check transform ID in ESP.
1919 */
1920 static int
1921 check_trns_esp(t_id)
1922 int t_id;
1923 {
1924 switch (t_id) {
1925 case IPSECDOI_ESP_DES:
1926 case IPSECDOI_ESP_3DES:
1927 case IPSECDOI_ESP_NULL:
1928 case IPSECDOI_ESP_RC5:
1929 case IPSECDOI_ESP_CAST:
1930 case IPSECDOI_ESP_BLOWFISH:
1931 case IPSECDOI_ESP_AES:
1932 case IPSECDOI_ESP_TWOFISH:
1933 return 0;
1934 case IPSECDOI_ESP_DES_IV32:
1935 case IPSECDOI_ESP_DES_IV64:
1936 case IPSECDOI_ESP_IDEA:
1937 case IPSECDOI_ESP_3IDEA:
1938 case IPSECDOI_ESP_RC4:
1939 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1940 "not support transform-id=%u in ESP.\n", t_id);
1941 return -1;
1942 default:
1943 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1944 "invalid transform-id=%u in ESP.\n", t_id);
1945 return -1;
1946 }
1947 /* NOT REACHED */
1948 }
1949
1950 /*
1951 * check transform ID in IPCOMP.
1952 */
1953 static int
1954 check_trns_ipcomp(t_id)
1955 int t_id;
1956 {
1957 switch (t_id) {
1958 case IPSECDOI_IPCOMP_OUI:
1959 case IPSECDOI_IPCOMP_DEFLATE:
1960 case IPSECDOI_IPCOMP_LZS:
1961 return 0;
1962 default:
1963 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1964 "invalid transform-id=%u in IPCOMP.\n", t_id);
1965 return -1;
1966 }
1967 /* NOT REACHED */
1968 }
1969
1970 /*
1971 * check data attributes in IKE.
1972 */
1973 static int
1974 check_attr_isakmp(trns)
1975 struct isakmp_pl_t *trns;
1976 {
1977 struct isakmp_data *d;
1978 int tlen;
1979 int flag, type;
1980 uint16_t lorv;
1981
1982 tlen = get_uint16(&trns->h.len) - sizeof(struct isakmp_pl_t);
1983 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
1984
1985 while (tlen > 0) {
1986 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
1987 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
1988 lorv = get_uint16(&d->lorv);
1989
1990 plog(PLOG_DEBUG, PLOGLOC, NULL,
1991 "type=%s, flag=0x%04x, lorv=%s\n",
1992 s_oakley_attr(type), flag,
1993 s_oakley_attr_v(type, lorv));
1994
1995 /*
1996 * some of the attributes must be encoded in TV.
1997 * see RFC2409 Appendix A "Attribute Classes".
1998 */
1999 switch (type) {
2000 case OAKLEY_ATTR_ENC_ALG:
2001 case OAKLEY_ATTR_HASH_ALG:
2002 case OAKLEY_ATTR_AUTH_METHOD:
2003 case OAKLEY_ATTR_GRP_DESC:
2004 case OAKLEY_ATTR_GRP_TYPE:
2005 case OAKLEY_ATTR_SA_LD_TYPE:
2006 case OAKLEY_ATTR_PRF:
2007 case OAKLEY_ATTR_KEY_LEN:
2008 case OAKLEY_ATTR_FIELD_SIZE:
2009 if (!flag) { /* TLV*/
2010 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2011 "oakley attribute %d must be TV.\n",
2012 type);
2013 return -1;
2014 }
2015 break;
2016 }
2017
2018 /* sanity check for TLV. length must be specified. */
2019 if (!flag && lorv == 0) { /*TLV*/
2020 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2021 "invalid length %d for TLV attribute %d.\n",
2022 lorv, type);
2023 return -1;
2024 }
2025
2026 switch (type) {
2027 case OAKLEY_ATTR_ENC_ALG:
2028 if (!alg_oakley_encdef_ok(lorv)) {
2029 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2030 "invalied encryption algorithm=%d.\n",
2031 lorv);
2032 return -1;
2033 }
2034 break;
2035
2036 case OAKLEY_ATTR_HASH_ALG:
2037 if (!alg_oakley_hashdef_ok(lorv)) {
2038 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2039 "invalied hash algorithm=%d.\n",
2040 lorv);
2041 return -1;
2042 }
2043 break;
2044
2045 case OAKLEY_ATTR_AUTH_METHOD:
2046 switch (lorv) {
2047 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2048 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2049 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2050 break;
2051 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2052 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2053 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2054 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2055 "auth method %d isn't supported.\n",
2056 lorv);
2057 return -1;
2058 default:
2059 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2060 "invalid auth method %d.\n",
2061 lorv);
2062 return -1;
2063 }
2064 break;
2065
2066 case OAKLEY_ATTR_GRP_DESC:
2067 if (!alg_oakley_dhdef_ok(lorv)) {
2068 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2069 "invalid DH group %d.\n",
2070 lorv);
2071 return -1;
2072 }
2073 break;
2074
2075 case OAKLEY_ATTR_GRP_TYPE:
2076 switch (lorv) {
2077 case OAKLEY_ATTR_GRP_TYPE_MODP:
2078 break;
2079 default:
2080 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2081 "unsupported DH group type %d.\n",
2082 lorv);
2083 return -1;
2084 }
2085 break;
2086
2087 case OAKLEY_ATTR_GRP_PI:
2088 case OAKLEY_ATTR_GRP_GEN_ONE:
2089 /* sanity checks? */
2090 break;
2091
2092 case OAKLEY_ATTR_GRP_GEN_TWO:
2093 case OAKLEY_ATTR_GRP_CURVE_A:
2094 case OAKLEY_ATTR_GRP_CURVE_B:
2095 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2096 "attr type=%u isn't supported.\n", type);
2097 return -1;
2098
2099 case OAKLEY_ATTR_SA_LD_TYPE:
2100 switch (lorv) {
2101 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2102 case OAKLEY_ATTR_SA_LD_TYPE_KB:
2103 break;
2104 default:
2105 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2106 "invalid life type %d.\n", lorv);
2107 return -1;
2108 }
2109 break;
2110
2111 case OAKLEY_ATTR_SA_LD:
2112 /* should check the value */
2113 break;
2114
2115 case OAKLEY_ATTR_PRF:
2116 case OAKLEY_ATTR_KEY_LEN:
2117 break;
2118
2119 case OAKLEY_ATTR_FIELD_SIZE:
2120 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2121 "attr type=%u isn't supported.\n", type);
2122 return -1;
2123
2124 case OAKLEY_ATTR_GRP_ORDER:
2125 break;
2126
2127 case OAKLEY_ATTR_GSS_ID:
2128 break;
2129
2130 default:
2131 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2132 "invalid attribute type %d.\n", type);
2133 return -1;
2134 }
2135
2136 if (flag) {
2137 tlen -= sizeof(*d);
2138 d = (struct isakmp_data *)((char *)d
2139 + sizeof(*d));
2140 } else {
2141 tlen -= (sizeof(*d) + lorv);
2142 d = (struct isakmp_data *)((char *)d
2143 + sizeof(*d) + lorv);
2144 }
2145 }
2146
2147 return 0;
2148 }
2149
2150 /*
2151 * check data attributes in IPSEC AH/ESP.
2152 */
2153 static int
2154 check_attr_ah(trns)
2155 struct isakmp_pl_t *trns;
2156 {
2157 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2158 }
2159
2160 static int
2161 check_attr_esp(trns)
2162 struct isakmp_pl_t *trns;
2163 {
2164 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2165 }
2166
2167 static int
2168 check_attr_ipsec(proto_id, trns)
2169 int proto_id;
2170 struct isakmp_pl_t *trns;
2171 {
2172 struct isakmp_data *d;
2173 int tlen;
2174 int flag, type = 0;
2175 uint16_t lorv;
2176 int attrseen[16]; /* XXX magic number */
2177
2178 tlen = get_uint16(&trns->h.len) - sizeof(struct isakmp_pl_t);
2179 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2180 memset(attrseen, 0, sizeof(attrseen));
2181
2182 while (tlen > 0) {
2183 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
2184 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
2185 lorv = get_uint16(&d->lorv);
2186
2187 plog(PLOG_DEBUG, PLOGLOC, NULL,
2188 "type=%s, flag=0x%04x, lorv=%s\n",
2189 s_ipsecdoi_attr(type), flag,
2190 s_ipsecdoi_attr_v(type, lorv));
2191
2192 if (type < ARRAYLEN(attrseen))
2193 attrseen[type]++;
2194
2195 switch (type) {
2196 case IPSECDOI_ATTR_ENC_MODE:
2197 if (! flag) {
2198 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2199 "must be TV when ENC_MODE.\n");
2200 return -1;
2201 }
2202
2203 switch (lorv) {
2204 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2205 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2206 break;
2207 #ifdef ENABLE_NATT
2208 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2209 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2210 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2211 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2212 plog(PLOG_DEBUG, PLOGLOC, NULL,
2213 "UDP encapsulation requested\n");
2214 break;
2215 #endif
2216 default:
2217 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2218 "invalid encryption mode=%u.\n",
2219 lorv);
2220 return -1;
2221 }
2222 break;
2223
2224 case IPSECDOI_ATTR_AUTH:
2225 if (! flag) {
2226 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2227 "must be TV when AUTH.\n");
2228 return -1;
2229 }
2230
2231 switch (lorv) {
2232 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2233 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2234 trns->t_id != IPSECDOI_AH_MD5) {
2235 ahmismatch:
2236 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2237 "auth algorithm %u conflicts "
2238 "with transform %u.\n",
2239 lorv, trns->t_id);
2240 return -1;
2241 }
2242 break;
2243 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2244 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2245 if (trns->t_id != IPSECDOI_AH_SHA)
2246 goto ahmismatch;
2247 }
2248 break;
2249 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2250 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2251 if (trns->t_id != IPSECDOI_AH_SHA256)
2252 goto ahmismatch;
2253 }
2254 break;
2255 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2256 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2257 if (trns->t_id != IPSECDOI_AH_SHA384)
2258 goto ahmismatch;
2259 }
2260 break;
2261 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2262 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2263 if (trns->t_id != IPSECDOI_AH_SHA512)
2264 goto ahmismatch;
2265 }
2266 break;
2267 case IPSECDOI_ATTR_AUTH_DES_MAC:
2268 case IPSECDOI_ATTR_AUTH_KPDK:
2269 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2270 "auth algorithm %u isn't supported.\n",
2271 lorv);
2272 return -1;
2273 default:
2274 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2275 "invalid auth algorithm=%u.\n",
2276 lorv);
2277 return -1;
2278 }
2279 break;
2280
2281 case IPSECDOI_ATTR_SA_LD_TYPE:
2282 if (! flag) {
2283 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2284 "must be TV when LD_TYPE.\n");
2285 return -1;
2286 }
2287
2288 switch (lorv) {
2289 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2290 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2291 break;
2292 default:
2293 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2294 "invalid life type %d.\n", lorv);
2295 return -1;
2296 }
2297 break;
2298
2299 case IPSECDOI_ATTR_SA_LD:
2300 if (flag) {
2301 /* i.e. ISAKMP_GEN_TV */
2302 plog(PLOG_DEBUG, PLOGLOC, NULL,
2303 "life duration was in TLV.\n");
2304 } else {
2305 /* i.e. ISAKMP_GEN_TLV */
2306 if (lorv == 0) {
2307 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2308 "invalid length of LD\n");
2309 return -1;
2310 }
2311 }
2312 break;
2313
2314 case IPSECDOI_ATTR_GRP_DESC:
2315 if (! flag) {
2316 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2317 "must be TV when GRP_DESC.\n");
2318 return -1;
2319 }
2320
2321 if (!alg_oakley_dhdef_ok(lorv)) {
2322 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2323 "invalid group description=%u.\n",
2324 lorv);
2325 return -1;
2326 }
2327 break;
2328
2329 case IPSECDOI_ATTR_KEY_LENGTH:
2330 if (! flag) {
2331 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2332 "must be TV when KEY_LENGTH.\n");
2333 return -1;
2334 }
2335 break;
2336
2337 case IPSECDOI_ATTR_KEY_ROUNDS:
2338 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2339 case IPSECDOI_ATTR_COMP_PRIVALG:
2340 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2341 "attr type=%u isn't supported.\n", type);
2342 return -1;
2343
2344 default:
2345 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2346 "invalid attribute type %d.\n", type);
2347 return -1;
2348 }
2349
2350 if (flag) {
2351 tlen -= sizeof(*d);
2352 d = (struct isakmp_data *)((char *)d
2353 + sizeof(*d));
2354 } else {
2355 tlen -= (sizeof(*d) + lorv);
2356 d = (struct isakmp_data *)((caddr_t)d
2357 + sizeof(*d) + lorv);
2358 }
2359 }
2360
2361 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2362 !attrseen[IPSECDOI_ATTR_AUTH]) {
2363 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2364 "attr AUTH must be present for AH.\n");
2365 return -1;
2366 }
2367
2368 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2369 trns->t_id == IPSECDOI_ESP_NULL &&
2370 !attrseen[IPSECDOI_ATTR_AUTH]) {
2371 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2372 "attr AUTH must be present for ESP NULL encryption.\n");
2373 return -1;
2374 }
2375
2376 return 0;
2377 }
2378
2379 static int
2380 check_attr_ipcomp(trns)
2381 struct isakmp_pl_t *trns;
2382 {
2383 struct isakmp_data *d;
2384 int tlen;
2385 int flag, type = 0;
2386 uint16_t lorv;
2387 int attrseen[16]; /* XXX magic number */
2388
2389 tlen = get_uint16(&trns->h.len) - sizeof(struct isakmp_pl_t);
2390 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2391 memset(attrseen, 0, sizeof(attrseen));
2392
2393 while (tlen > 0) {
2394 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
2395 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
2396 lorv = get_uint16(&d->lorv);
2397
2398 plog(PLOG_DEBUG, PLOGLOC, NULL,
2399 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2400 type, flag, lorv);
2401
2402 if (type < ARRAYLEN(attrseen))
2403 attrseen[type]++;
2404
2405 switch (type) {
2406 case IPSECDOI_ATTR_ENC_MODE:
2407 if (! flag) {
2408 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2409 "must be TV when ENC_MODE.\n");
2410 return -1;
2411 }
2412
2413 switch (lorv) {
2414 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2415 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2416 break;
2417 #ifdef ENABLE_NATT
2418 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2419 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2420 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2421 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2422 plog(PLOG_DEBUG, PLOGLOC, NULL,
2423 "UDP encapsulation requested\n");
2424 break;
2425 #endif
2426 default:
2427 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2428 "invalid encryption mode=%u.\n",
2429 lorv);
2430 return -1;
2431 }
2432 break;
2433
2434 case IPSECDOI_ATTR_SA_LD_TYPE:
2435 if (! flag) {
2436 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2437 "must be TV when LD_TYPE.\n");
2438 return -1;
2439 }
2440
2441 switch (lorv) {
2442 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2443 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2444 break;
2445 default:
2446 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2447 "invalid life type %d.\n", lorv);
2448 return -1;
2449 }
2450 break;
2451
2452 case IPSECDOI_ATTR_SA_LD:
2453 if (flag) {
2454 /* i.e. ISAKMP_GEN_TV */
2455 plog(PLOG_DEBUG, PLOGLOC, NULL,
2456 "life duration was in TLV.\n");
2457 } else {
2458 /* i.e. ISAKMP_GEN_TLV */
2459 if (lorv == 0) {
2460 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2461 "invalid length of LD\n");
2462 return -1;
2463 }
2464 }
2465 break;
2466
2467 case IPSECDOI_ATTR_GRP_DESC:
2468 if (! flag) {
2469 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2470 "must be TV when GRP_DESC.\n");
2471 return -1;
2472 }
2473
2474 if (!alg_oakley_dhdef_ok(lorv)) {
2475 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2476 "invalid group description=%u.\n",
2477 lorv);
2478 return -1;
2479 }
2480 break;
2481
2482 case IPSECDOI_ATTR_AUTH:
2483 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2484 "invalid attr type=%u.\n", type);
2485 return -1;
2486
2487 case IPSECDOI_ATTR_KEY_LENGTH:
2488 case IPSECDOI_ATTR_KEY_ROUNDS:
2489 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2490 case IPSECDOI_ATTR_COMP_PRIVALG:
2491 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2492 "attr type=%u isn't supported.\n", type);
2493 return -1;
2494
2495 default:
2496 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2497 "invalid attribute type %d.\n", type);
2498 return -1;
2499 }
2500
2501 if (flag) {
2502 tlen -= sizeof(*d);
2503 d = (struct isakmp_data *)((char *)d
2504 + sizeof(*d));
2505 } else {
2506 tlen -= (sizeof(*d) + lorv);
2507 d = (struct isakmp_data *)((caddr_t)d
2508 + sizeof(*d) + lorv);
2509 }
2510 }
2511
2512 #if 0
2513 if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2514 !attrseen[IPSECDOI_ATTR_AUTH]) {
2515 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2516 "attr AUTH must be present for AH.\n", type);
2517 return -1;
2518 }
2519 #endif
2520
2521 return 0;
2522 }
2523
2524 /* %%% */
2525 /*
2526 * create phase1 proposal from remote configuration.
2527 * NOT INCLUDING isakmp general header of SA payload
2528 */
2529 rc_vchar_t *
2530 ipsecdoi_setph1proposal(props)
2531 struct isakmpsa *props;
2532 {
2533 rc_vchar_t *mysa;
2534 int sablen;
2535
2536 /* count total size of SA minus isakmp general header */
2537 /* not including isakmp general header of SA payload */
2538 sablen = sizeof(struct ipsecdoi_sa_b);
2539 sablen += setph1prop(props, NULL);
2540
2541 mysa = rc_vmalloc(sablen);
2542 if (mysa == NULL) {
2543 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2544 "failed to allocate my sa buffer\n");
2545 return NULL;
2546 }
2547
2548 /* create SA payload */
2549 /* not including isakmp general header */
2550 put_uint32(&((struct ipsecdoi_sa_b *)mysa->v)->doi, ikev1_doitype(props->rmconf));
2551 put_uint32(&((struct ipsecdoi_sa_b *)mysa->v)->sit, ikev1_sittype(props->rmconf));
2552
2553 (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2554
2555 return mysa;
2556 }
2557
2558 static int
2559 setph1prop(props, buf)
2560 struct isakmpsa *props;
2561 caddr_t buf;
2562 {
2563 struct isakmp_pl_p *prop = NULL;
2564 struct isakmpsa *s = NULL;
2565 int proplen, trnslen;
2566 uint8_t *np_t; /* pointer next trns type in previous header */
2567 int trns_num;
2568 caddr_t p = buf;
2569
2570 proplen = sizeof(*prop);
2571 if (buf) {
2572 /* create proposal */
2573 prop = (struct isakmp_pl_p *)p;
2574 prop->h.np = ISAKMP_NPTYPE_NONE;
2575 prop->p_no = props->prop_no;
2576 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2577 prop->spi_size = 0;
2578 p += sizeof(*prop);
2579 }
2580
2581 np_t = NULL;
2582 trns_num = 0;
2583
2584 for (s = props; s != NULL; s = s->next) {
2585 if (np_t)
2586 *np_t = ISAKMP_NPTYPE_T;
2587
2588 trnslen = setph1trns(s, p);
2589 proplen += trnslen;
2590 if (buf) {
2591 /* save buffer to pre-next payload */
2592 np_t = &((struct isakmp_pl_t *)p)->h.np;
2593 p += trnslen;
2594
2595 /* count up transform length */
2596 trns_num++;
2597 }
2598 }
2599
2600 /* update proposal length */
2601 if (buf) {
2602 put_uint16(&prop->h.len, proplen);
2603 prop->num_t = trns_num;
2604 }
2605
2606 return proplen;
2607 }
2608
2609 static int
2610 setph1trns(sa, buf)
2611 struct isakmpsa *sa;
2612 caddr_t buf;
2613 {
2614 struct isakmp_pl_t *trns = NULL;
2615 int trnslen, attrlen;
2616 caddr_t p = buf;
2617
2618 trnslen = sizeof(*trns);
2619 if (buf) {
2620 /* create transform */
2621 trns = (struct isakmp_pl_t *)p;
2622 trns->h.np = ISAKMP_NPTYPE_NONE;
2623 trns->t_no = sa->trns_no;
2624 trns->t_id = IPSECDOI_KEY_IKE;
2625 p += sizeof(*trns);
2626 }
2627
2628 attrlen = setph1attr(sa, p);
2629 trnslen += attrlen;
2630 if (buf)
2631 p += attrlen;
2632
2633 if (buf)
2634 put_uint16(&trns->h.len, trnslen);
2635
2636 return trnslen;
2637 }
2638
2639 static int
2640 setph1attr(sa, buf)
2641 struct isakmpsa *sa;
2642 caddr_t buf;
2643 {
2644 caddr_t p = buf;
2645 int attrlen = 0;
2646
2647 if (sa->lifetime) {
2648 uint32_t lifetime = htonl((uint32_t)sa->lifetime);
2649
2650 attrlen += sizeof(struct isakmp_data)
2651 + sizeof(struct isakmp_data);
2652 if (sa->lifetime > 0xffff)
2653 attrlen += sizeof(lifetime);
2654 if (buf) {
2655 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2656 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2657 if (sa->lifetime > 0xffff) {
2658 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2659 (caddr_t)&lifetime,
2660 sizeof(lifetime));
2661 } else {
2662 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2663 sa->lifetime);
2664 }
2665 }
2666 }
2667
2668 if (sa->lifebyte) {
2669 uint32_t lifebyte = htonl((uint32_t)sa->lifebyte);
2670
2671 attrlen += sizeof(struct isakmp_data)
2672 + sizeof(struct isakmp_data);
2673 if (sa->lifebyte > 0xffff)
2674 attrlen += sizeof(lifebyte);
2675 if (buf) {
2676 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2677 OAKLEY_ATTR_SA_LD_TYPE_KB);
2678 if (sa->lifebyte > 0xffff) {
2679 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2680 (caddr_t)&lifebyte,
2681 sizeof(lifebyte));
2682 } else {
2683 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2684 sa->lifebyte);
2685 }
2686 }
2687 }
2688
2689 if (sa->enctype) {
2690 attrlen += sizeof(struct isakmp_data);
2691 if (buf)
2692 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2693 }
2694 if (sa->encklen) {
2695 attrlen += sizeof(struct isakmp_data);
2696 if (buf)
2697 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2698 }
2699 if (sa->authmethod) {
2700 attrlen += sizeof(struct isakmp_data);
2701 if (buf)
2702 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, sa->authmethod);
2703 }
2704 if (sa->hashtype) {
2705 attrlen += sizeof(struct isakmp_data);
2706 if (buf)
2707 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2708 }
2709 switch (sa->dh_group) {
2710 case OAKLEY_ATTR_GRP_DESC_MODP768:
2711 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2712 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2713 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2714 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2715 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2716 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2717 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2718 /* don't attach group type for known groups */
2719 attrlen += sizeof(struct isakmp_data);
2720 if (buf) {
2721 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2722 sa->dh_group);
2723 }
2724 break;
2725 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2726 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2727 /* don't attach group type for known groups */
2728 attrlen += sizeof(struct isakmp_data);
2729 if (buf) {
2730 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2731 OAKLEY_ATTR_GRP_TYPE_EC2N);
2732 }
2733 break;
2734 case 0:
2735 default:
2736 break;
2737 }
2738
2739 #ifdef HAVE_GSSAPI
2740 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2741 sa->gssid != NULL) {
2742 attrlen += sizeof(struct isakmp_data);
2743 attrlen += sa->gssid->l;
2744 if (buf) {
2745 plog(PLOG_DEBUG, PLOGLOC, NULL, "gss id attr: len %d, "
2746 "val '%s'\n", sa->gssid->l, sa->gssid->v);
2747 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2748 (caddr_t)sa->gssid->v,
2749 sa->gssid->l);
2750 }
2751 }
2752 #endif
2753
2754 return attrlen;
2755 }
2756
2757 static rc_vchar_t *
2758 setph2proposal0(iph2, pp, pr)
2759 const struct ph2handle *iph2;
2760 const struct saprop *pp;
2761 const struct saproto *pr;
2762 {
2763 rc_vchar_t *p;
2764 struct isakmp_pl_p *prop;
2765 struct isakmp_pl_t *trns;
2766 struct satrns *tr;
2767 int attrlen;
2768 size_t trnsoff;
2769 caddr_t x0, x;
2770 uint8_t *np_t; /* pointer next trns type in previous header */
2771 const uint8_t *spi;
2772
2773 p = rc_vmalloc(sizeof(*prop) + sizeof(pr->spi));
2774 if (p == NULL)
2775 return NULL;
2776
2777 /* create proposal */
2778 prop = (struct isakmp_pl_p *)p->v;
2779 prop->h.np = ISAKMP_NPTYPE_NONE;
2780 prop->p_no = pp->prop_no;
2781 prop->proto_id = pr->proto_id;
2782 prop->num_t = 1;
2783
2784 spi = (const uint8_t *)&pr->spi;
2785 switch (pr->proto_id) {
2786 case IPSECDOI_PROTO_IPCOMP:
2787 /*
2788 * draft-shacham-ippcp-rfc2393bis-05.txt:
2789 * construct 16bit SPI (CPI).
2790 * XXX we may need to provide a configuration option to
2791 * generate 32bit SPI. otherwise we cannot interoeprate
2792 * with nodes that uses 32bit SPI, in case we are initiator.
2793 */
2794 prop->spi_size = sizeof(uint16_t);
2795 spi += sizeof(pr->spi) - sizeof(uint16_t);
2796 p->l -= sizeof(pr->spi);
2797 p->l += sizeof(uint16_t);
2798 break;
2799 default:
2800 prop->spi_size = sizeof(pr->spi);
2801 break;
2802 }
2803 memcpy(prop + 1, spi, prop->spi_size);
2804
2805 /* create transform */
2806 trnsoff = sizeof(*prop) + prop->spi_size;
2807 np_t = NULL;
2808
2809 for (tr = pr->head; tr; tr = tr->next) {
2810
2811 switch (pr->proto_id) {
2812 case IPSECDOI_PROTO_IPSEC_ESP:
2813 /*
2814 * don't build a null encryption
2815 * with no authentication transform.
2816 */
2817 if (tr->trns_id == IPSECDOI_ESP_NULL &&
2818 tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
2819 continue;
2820 break;
2821 }
2822
2823 if (np_t) {
2824 *np_t = ISAKMP_NPTYPE_T;
2825 prop->num_t++;
2826 }
2827
2828 /* get attribute length */
2829 attrlen = 0;
2830 if (pp->lifetime) {
2831 attrlen += sizeof(struct isakmp_data)
2832 + sizeof(struct isakmp_data);
2833 if (pp->lifetime > 0xffff)
2834 attrlen += sizeof(uint32_t);
2835 }
2836 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2837 attrlen += sizeof(struct isakmp_data)
2838 + sizeof(struct isakmp_data);
2839 if (pp->lifebyte > 0xffff)
2840 attrlen += sizeof(uint32_t);
2841 }
2842 attrlen += sizeof(struct isakmp_data); /* enc mode */
2843 if (tr->encklen)
2844 attrlen += sizeof(struct isakmp_data);
2845
2846 switch (pr->proto_id) {
2847 case IPSECDOI_PROTO_IPSEC_ESP:
2848 /* non authentication mode ? */
2849 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2850 attrlen += sizeof(struct isakmp_data);
2851 break;
2852 case IPSECDOI_PROTO_IPSEC_AH:
2853 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
2854 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2855 "no authentication algorithm found "
2856 "but protocol is AH.\n");
2857 rc_vfree(p);
2858 return NULL;
2859 }
2860 attrlen += sizeof(struct isakmp_data);
2861 break;
2862 case IPSECDOI_PROTO_IPCOMP:
2863 break;
2864 default:
2865 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2866 "invalid protocol: %d\n", pr->proto_id);
2867 rc_vfree(p);
2868 return NULL;
2869 }
2870
2871 if (alg_oakley_dhdef_ok(pp->pfs_group))
2872 attrlen += sizeof(struct isakmp_data);
2873
2874 p = rc_vrealloc(p, p->l + sizeof(*trns) + attrlen);
2875 if (p == NULL)
2876 return NULL;
2877 prop = (struct isakmp_pl_p *)p->v;
2878
2879 /* set transform's values */
2880 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2881 trns->h.np = ISAKMP_NPTYPE_NONE;
2882 trns->t_no = tr->trns_no;
2883 trns->t_id = tr->trns_id;
2884
2885 /* set attributes */
2886 x = x0 = p->v + trnsoff + sizeof(*trns);
2887
2888 if (pp->lifetime) {
2889 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2890 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
2891 if (pp->lifetime > 0xffff) {
2892 uint32_t v = htonl((uint32_t)pp->lifetime);
2893 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2894 (caddr_t)&v, sizeof(v));
2895 } else {
2896 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2897 pp->lifetime);
2898 }
2899 }
2900
2901 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2902 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2903 IPSECDOI_ATTR_SA_LD_TYPE_KB);
2904 if (pp->lifebyte > 0xffff) {
2905 uint32_t v = htonl((uint32_t)pp->lifebyte);
2906 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2907 (caddr_t)&v, sizeof(v));
2908 } else {
2909 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2910 pp->lifebyte);
2911 }
2912 }
2913
2914 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
2915
2916 if (tr->encklen)
2917 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
2918
2919 /* mandatory check has done above. */
2920 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2921 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
2922 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
2923
2924 if (alg_oakley_dhdef_ok(pp->pfs_group))
2925 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
2926 pp->pfs_group);
2927
2928 /* update length of this transform. */
2929 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2930 put_uint16(&trns->h.len, sizeof(*trns) + attrlen);
2931
2932 /* save buffer to pre-next payload */
2933 np_t = &trns->h.np;
2934
2935 trnsoff += (sizeof(*trns) + attrlen);
2936 }
2937
2938 if (np_t == NULL) {
2939 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2940 "no suitable proposal was created.\n");
2941 return NULL;
2942 }
2943
2944 /* update length of this protocol. */
2945 put_uint16(&prop->h.len, p->l);
2946
2947 return p;
2948 }
2949
2950 /*
2951 * create phase2 proposal from policy configuration.
2952 * NOT INCLUDING isakmp general header of SA payload.
2953 * This function is called by initiator only.
2954 */
2955 int
2956 ipsecdoi_setph2proposal(iph2)
2957 struct ph2handle *iph2;
2958 {
2959 struct saprop *proposal, *a;
2960 struct saproto *b = NULL;
2961 rc_vchar_t *q;
2962 struct ipsecdoi_sa_b *sab;
2963 struct isakmp_pl_p *prop;
2964 size_t propoff; /* for previous field of type of next payload. */
2965
2966 proposal = iph2->proposal;
2967
2968 iph2->sa = rc_vmalloc(sizeof(*sab));
2969 if (iph2->sa == NULL) {
2970 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2971 "failed to allocate my sa buffer\n");
2972 return -1;
2973 }
2974
2975 /* create SA payload */
2976 sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
2977 put_uint32(&sab->doi, IPSEC_DOI);
2978 put_uint32(&sab->sit, IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
2979
2980 prop = NULL;
2981 propoff = 0;
2982 for (a = proposal; a; a = a->next) {
2983 for (b = a->head; b; b = b->next) {
2984 #ifdef ENABLE_NATT
2985 if (iph2->ph1->natt_flags & NAT_DETECTED) {
2986 int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
2987 plog (PLOG_INFO, PLOGLOC, NULL,
2988 "NAT detected -> UDP encapsulation "
2989 "(ENC_MODE %d->%d).\n",
2990 b->encmode,
2991 b->encmode+udp_diff);
2992 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
2993 b->encmode += udp_diff;
2994 b->udp_encap = 1;
2995 }
2996 #endif
2997
2998 q = setph2proposal0(iph2, a, b);
2999 if (q == NULL) {
3000 VPTRINIT(iph2->sa);
3001 return -1;
3002 }
3003
3004 iph2->sa = rc_vrealloc(iph2->sa, iph2->sa->l + q->l);
3005 if (iph2->sa == NULL) {
3006 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3007 "failed to allocate my sa buffer\n");
3008 if (q)
3009 rc_vfree(q);
3010 return -1;
3011 }
3012 memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3013 if (propoff != 0) {
3014 prop = (struct isakmp_pl_p *)(iph2->sa->v +
3015 propoff);
3016 prop->h.np = ISAKMP_NPTYPE_P;
3017 }
3018 propoff = iph2->sa->l - q->l;
3019
3020 rc_vfree(q);
3021 }
3022 }
3023
3024 return 0;
3025 }
3026
3027 /*
3028 * return 1 if all of the given protocols are transport mode.
3029 */
3030 int
3031 ipsecdoi_transportmode(pp)
3032 struct saprop *pp;
3033 {
3034 struct saproto *pr = NULL;
3035
3036 for (; pp; pp = pp->next) {
3037 for (pr = pp->head; pr; pr = pr->next) {
3038 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3039 return 0;
3040 }
3041 }
3042
3043 return 1;
3044 }
3045
3046 #if 0
3047 int
3048 ipsecdoi_get_defaultlifetime()
3049 {
3050 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3051 }
3052 #endif
3053
3054 int
3055 ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3056 int proto_id, enc, auth, comp;
3057 {
3058 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3059 switch (proto_id) {
3060 case IPSECDOI_PROTO_IPSEC_ESP:
3061 if (enc == 0 || comp != 0) {
3062 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3063 "illegal algorithm defined "
3064 "ESP enc=%s auth=%s comp=%s.\n",
3065 TMPALGTYPE2STR(enc),
3066 TMPALGTYPE2STR(auth),
3067 TMPALGTYPE2STR(comp));
3068 return -1;
3069 }
3070 break;
3071 case IPSECDOI_PROTO_IPSEC_AH:
3072 if (enc != 0 || auth == 0 || comp != 0) {
3073 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3074 "illegal algorithm defined "
3075 "AH enc=%s auth=%s comp=%s.\n",
3076 TMPALGTYPE2STR(enc),
3077 TMPALGTYPE2STR(auth),
3078 TMPALGTYPE2STR(comp));
3079 return -1;
3080 }
3081 break;
3082 case IPSECDOI_PROTO_IPCOMP:
3083 if (enc != 0 || auth != 0 || comp == 0) {
3084 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3085 "illegal algorithm defined "
3086 "IPcomp enc=%s auth=%s comp=%s.\n",
3087 TMPALGTYPE2STR(enc),
3088 TMPALGTYPE2STR(auth),
3089 TMPALGTYPE2STR(comp));
3090 return -1;
3091 }
3092 break;
3093 default:
3094 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3095 "invalid ipsec protocol %d\n", proto_id);
3096 return -1;
3097 }
3098 #undef TMPALGTYPE2STR
3099 return 0;
3100 }
3101
3102 int
3103 ipproto2doi(proto)
3104 int proto;
3105 {
3106 switch (proto) {
3107 case IPPROTO_AH:
3108 return IPSECDOI_PROTO_IPSEC_AH;
3109 case IPPROTO_ESP:
3110 return IPSECDOI_PROTO_IPSEC_ESP;
3111 case IPPROTO_IPCOMP:
3112 return IPSECDOI_PROTO_IPCOMP;
3113 }
3114 return -1; /* XXX */
3115 }
3116
3117 int
3118 doi2ipproto(proto)
3119 int proto;
3120 {
3121 switch (proto) {
3122 case IPSECDOI_PROTO_IPSEC_AH:
3123 return IPPROTO_AH;
3124 case IPSECDOI_PROTO_IPSEC_ESP:
3125 return IPPROTO_ESP;
3126 case IPSECDOI_PROTO_IPCOMP:
3127 return IPPROTO_IPCOMP;
3128 }
3129 return -1; /* XXX */
3130 }
3131
3132 /*
3133 * check the following:
3134 * - In main mode with pre-shared key, only address type can be used.
3135 * - if proper type for phase 1 ?
3136 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3137 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3138 * - if ID payload sent from peer is equal to the ID expected by me.
3139 *
3140 * both of "id" and "id_p" should be ID payload without general header,
3141 */
3142 int
3143 ipsecdoi_checkid1(iph1)
3144 struct ph1handle *iph1;
3145 {
3146 struct ipsecdoi_id_b *id_b;
3147 #if 0
3148 struct sockaddr *sa;
3149 caddr_t sa1, sa2;
3150 #endif
3151
3152 if (iph1->id_p == NULL) {
3153 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3154 "invalid iph1 passed id_p == NULL\n");
3155 return ISAKMP_INTERNAL_ERROR;
3156 }
3157 if (iph1->id_p->l < sizeof(*id_b)) {
3158 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3159 "invalid value passed as \"ident\" (len=%lu)\n",
3160 (u_long)iph1->id_p->l);
3161 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3162 }
3163
3164 id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3165
3166 /* In main mode with pre-shared key, only address type can be used. */
3167 if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3168 iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3169 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3170 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3171 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3172 "Expecting IP address type in main mode, "
3173 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3174 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3175 }
3176 }
3177
3178 /* if proper type for phase 1 ? */
3179 switch (id_b->type) {
3180 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3181 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3182 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3183 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3184 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3185 "peer ID type %s is not acceptable\n",
3186 s_ipsecdoi_ident(id_b->type));
3187 /*FALLTHROUGH*/
3188 }
3189
3190 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3191 if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3192 id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3193
3194 if (id_b->proto_id == 0 && get_uint16(&id_b->port) != 0) {
3195 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3196 "protocol ID and Port mismatched. "
3197 "proto_id:%d port:%d\n",
3198 id_b->proto_id, get_uint16(&id_b->port));
3199 /*FALLTHROUGH*/
3200
3201 } else if (id_b->proto_id == IPPROTO_UDP) {
3202 /*
3203 * copmaring with expecting port.
3204 * always permit if port is equal to PORT_ISAKMP
3205 */
3206 if (get_uint16(&id_b->port) != PORT_ISAKMP) {
3207
3208 uint16_t port;
3209
3210 switch (iph1->remote->sa_family) {
3211 case AF_INET:
3212 port = ((struct sockaddr_in *)iph1->remote)->sin_port;
3213 break;
3214 #ifdef INET6
3215 case AF_INET6:
3216 port = ((struct sockaddr_in6 *)iph1->remote)->sin6_port;
3217 break;
3218 #endif
3219 default:
3220 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3221 "invalid family: %d\n",
3222 iph1->remote->sa_family);
3223 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3224 }
3225 if (get_uint16(&id_b->port) != port) {
3226 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3227 "port %d expected, but %d\n",
3228 port, get_uint16(&id_b->port));
3229 /*FALLTHROUGH*/
3230 }
3231 }
3232 }
3233 }
3234
3235 #if 0
3236 /* compare with the ID if specified. */
3237 if (ikev1_peers_id(iph1->rmconf)) {
3238 rc_type rc_id_type;
3239 rc_vchar_t *id_data;
3240
3241 /* check the type of both IDs */
3242 if (ikev1_compare_id(iph1->id_p, ikev1_peers_id(iph1->rmconf)) != 0) {
3243 if (ikev1_verify_id(iph1->rmconf) == RCT_BOOL_ON) {
3244 plog(PLOG_PROTOERR, PLOGLOC, 0,
3245 "peer identifier does not match\n");
3246 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3247 }
3248 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3249 "peer identifier does not match\n");
3250 }
3251 }
3252 #endif
3253
3254 return 0;
3255 }
3256
3257 /*
3258 * create ID payload for phase 1 and set into iph1->id.
3259 * NOT INCLUDING isakmp general header.
3260 * see, RFC2407 4.6.2.1
3261 */
3262 int
3263 ipsecdoi_setid1(iph1)
3264 struct ph1handle *iph1;
3265 {
3266 struct rc_idlist *id;
3267 rc_vchar_t *id_data = 0;
3268 int id_type;
3269 struct ipsecdoi_id_b id_b;
3270 rc_vchar_t *ret;
3271
3272 id = ikev1_my_id(iph1->rmconf);
3273 id_data = ike_identifier_data(id, &id_type);
3274 if (!id_data)
3275 goto err;
3276
3277 /* init */
3278 id_b.type = id_type;
3279 id_b.proto_id = 0;
3280 id_b.port = 0;
3281
3282 ret = rc_vmalloc(sizeof(id_b) + id_data->l);
3283 if (ret == NULL)
3284 goto err;
3285
3286 memcpy(ret->v, &id_b, sizeof(id_b));
3287 memcpy(ret->v + sizeof(id_b), id_data->v, id_data->l);
3288
3289 iph1->id = ret;
3290
3291 plog(PLOG_DEBUG, PLOGLOC, NULL,
3292 "using ID type %s\n", s_ipsecdoi_ident(id_b.type));
3293 if (id_data)
3294 rc_vfree(id_data);
3295 return 0;
3296
3297 err:
3298 if (id_data)
3299 rc_vfree(id_data);
3300 plog(PLOG_INTERR, PLOGLOC, NULL, "failed constructing my ID\n");
3301 return -1;
3302 }
3303
3304 #if 0
3305 static rc_vchar_t *
3306 getidval(type, val)
3307 int type;
3308 rc_vchar_t *val;
3309 {
3310 rc_vchar_t *new = NULL;
3311
3312 if (val)
3313 new = rc_vdup(val);
3314 else if (lcconf->ident[type])
3315 new = rc_vdup(lcconf->ident[type]);
3316
3317 return new;
3318 }
3319 #endif
3320
3321 #if 0
3322 /* it's only called by cfparse.y. */
3323 int
3324 set_identifier(vpp, type, value)
3325 rc_vchar_t **vpp, *value;
3326 int type;
3327 {
3328 rc_vchar_t *new = NULL;
3329
3330 /* simply return if value is null. */
3331 if (!value)
3332 return 0;
3333
3334 switch (type) {
3335 case IDTYPE_FQDN:
3336 case IDTYPE_USERFQDN:
3337 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3338 new = rc_vmalloc(value->l - 1);
3339 if (new == NULL)
3340 return -1;
3341 memcpy(new->v, value->v, new->l);
3342 break;
3343 case IDTYPE_KEYID:
3344 {
3345 FILE *fp;
3346 char b[512];
3347 int tlen, len;
3348
3349 fp = fopen(value->v, "r");
3350 if (fp == NULL) {
3351 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3352 "can not open %s\n", value->v);
3353 return -1;
3354 }
3355 tlen = 0;
3356 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3357 new = rc_vrealloc(new, tlen + len);
3358 if (!new) {
3359 fclose(fp);
3360 return -1;
3361 }
3362 memcpy(new->v + tlen, b, len);
3363 tlen += len;
3364 }
3365 break;
3366 }
3367 case IDTYPE_ADDRESS:
3368 {
3369 struct sockaddr *sa;
3370
3371 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3372 if (value->l == 0)
3373 break;
3374
3375 sa = str2saddr(value->v, NULL);
3376 if (sa == NULL) {
3377 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3378 "invalid ip address %s\n", value->v);
3379 return -1;
3380 }
3381
3382 new = rc_vmalloc(sa->sa_len);
3383 if (new == NULL)
3384 return -1;
3385 memcpy(new->v, sa, new->l);
3386 break;
3387 }
3388 case IDTYPE_ASN1DN:
3389 new = eay_str2asn1dn(value->v, value->l - 1);
3390 if (new == NULL)
3391 return -1;
3392 break;
3393 }
3394
3395 *vpp = new;
3396
3397 return 0;
3398 }
3399 #endif
3400
3401 /*
3402 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3403 * NOT INCLUDING isakmp general header.
3404 * this function is for initiator. responder will get to copy from payload.
3405 * responder ID type is always address type.
3406 * see, RFC2407 4.6.2.1
3407 */
3408 int
3409 ipsecdoi_setid2(iph2)
3410 struct ph2handle *iph2;
3411 {
3412 struct rcf_selector *sel;
3413 int proto;
3414
3415 /* check there is phase 2 handler ? */
3416 sel = iph2->selector;
3417 assert(sel->src->type == RCT_ADDR_INET);
3418 assert(sel->dst->type == RCT_ADDR_INET);
3419 proto = sel->upper_layer_protocol;
3420 if (proto == RC_PROTO_ANY)
3421 proto = 0;
3422
3423 iph2->id = ipsecdoi_sockaddr2id(sel->src->a.ipaddr, sel->src->prefixlen, proto);
3424 if (iph2->id == NULL) {
3425 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3426 "failed to create ID payload for %s\n",
3427 rc_vmem2str(sel->sl_index));
3428 return -1;
3429 }
3430 plog(PLOG_DEBUG, PLOGLOC, NULL, "use local ID type %s\n",
3431 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
3432
3433 /* remote side */
3434 iph2->id_p = ipsecdoi_sockaddr2id(sel->dst->a.ipaddr, sel->dst->prefixlen, proto);
3435 if (iph2->id_p == NULL) {
3436 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3437 "failed to create ID payload for %s\n",
3438 rc_vmem2str(sel->sl_index));
3439 VPTRINIT(iph2->id);
3440 return -1;
3441 }
3442 plog(PLOG_DEBUG, PLOGLOC, NULL,
3443 "use remote ID type %s\n",
3444 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
3445
3446 return 0;
3447 }
3448
3449 /*
3450 * set address type of ID.
3451 * NOT INCLUDING general header.
3452 */
3453 rc_vchar_t *
3454 ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
3455 struct sockaddr *saddr;
3456 unsigned int prefixlen;
3457 unsigned int ul_proto;
3458 {
3459 rc_vchar_t *new;
3460 int type, len1, len2;
3461 caddr_t sa;
3462 uint16_t port;
3463
3464 /*
3465 * Q. When type is SUBNET, is it allowed to be ::1/128.
3466 * A. Yes. (consensus at bake-off)
3467 */
3468 switch (saddr->sa_family) {
3469 case AF_INET:
3470 len1 = sizeof(struct in_addr);
3471 if (prefixlen == (sizeof(struct in_addr) << 3)) {
3472 type = IPSECDOI_ID_IPV4_ADDR;
3473 len2 = 0;
3474 } else {
3475 type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
3476 len2 = sizeof(struct in_addr);
3477 }
3478 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
3479 port = ((struct sockaddr_in *)(saddr))->sin_port;
3480 break;
3481 #ifdef INET6
3482 case AF_INET6:
3483 len1 = sizeof(struct in6_addr);
3484 if (prefixlen == (sizeof(struct in6_addr) << 3)) {
3485 type = IPSECDOI_ID_IPV6_ADDR;
3486 len2 = 0;
3487 } else {
3488 type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
3489 len2 = sizeof(struct in6_addr);
3490 }
3491 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
3492 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
3493 break;
3494 #endif
3495 default:
3496 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3497 "invalid family: %d.\n", saddr->sa_family);
3498 return NULL;
3499 }
3500
3501 /* get ID buffer */
3502 new = rc_vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
3503 if (new == NULL) {
3504 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3505 "failed to get ID buffer.\n");
3506 return NULL;
3507 }
3508
3509 memset(new->v, 0, new->l);
3510
3511 /* set the part of header. */
3512 ((struct ipsecdoi_id_b *)new->v)->type = type;
3513
3514 /* set ul_proto and port */
3515 /*
3516 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3517 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3518 */
3519 ((struct ipsecdoi_id_b *)new->v)->proto_id =
3520 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
3521 ((struct ipsecdoi_id_b *)new->v)->port =
3522 port == IPSEC_PORT_ANY ? 0 : port;
3523 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
3524
3525 /* set address */
3526
3527 /* set prefix */
3528 if (len2) {
3529 unsigned char *p = (unsigned char *)new->v + sizeof(struct ipsecdoi_id_b) + len1;
3530 unsigned int bits = prefixlen;
3531
3532 while (bits >= 8) {
3533 *p++ = 0xff;
3534 bits -= 8;
3535 }
3536
3537 if (bits > 0)
3538 *p = ~((1 << (8 - bits)) - 1);
3539 }
3540
3541 return new;
3542 }
3543
3544 /*
3545 * create sockaddr structure from ID payload (buf).
3546 * buffers (saddr, prefixlen, ul_proto) must be allocated.
3547 * see, RFC2407 4.6.2.1
3548 */
3549 int
3550 ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
3551 rc_vchar_t *buf;
3552 struct sockaddr *saddr;
3553 uint8_t *prefixlen;
3554 uint16_t *ul_proto;
3555 {
3556 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
3557 unsigned int plen = 0;
3558
3559 /*
3560 * When a ID payload of subnet type with a IP address of full bit
3561 * masked, it has to be processed as host address.
3562 * e.g. below 2 type are same.
3563 * type = ipv6 subnet, data = 2001::1/128
3564 * type = ipv6 address, data = 2001::1
3565 */
3566 switch (id_b->type) {
3567 case IPSECDOI_ID_IPV4_ADDR:
3568 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3569 SET_SOCKADDR_LEN(saddr, sizeof(struct sockaddr_in));
3570 saddr->sa_family = AF_INET;
3571 ((struct sockaddr_in *)saddr)->sin_port =
3572 (id_b->port == 0
3573 ? IPSEC_PORT_ANY
3574 : id_b->port); /* see sockaddr2id() */
3575 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
3576 buf->v + sizeof(*id_b), sizeof(struct in_addr));
3577 break;
3578 #ifdef INET6
3579 case IPSECDOI_ID_IPV6_ADDR:
3580 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3581 SET_SOCKADDR_LEN(saddr, sizeof(struct sockaddr_in6));
3582 saddr->sa_family = AF_INET6;
3583 ((struct sockaddr_in6 *)saddr)->sin6_port =
3584 (id_b->port == 0
3585 ? IPSEC_PORT_ANY
3586 : id_b->port); /* see sockaddr2id() */
3587 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
3588 buf->v + sizeof(*id_b), sizeof(struct in6_addr));
3589 ((struct sockaddr_in6 *)saddr)->sin6_scope_id = 0;
3590 break;
3591 #endif
3592 default:
3593 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3594 "unsupported ID type %d\n", id_b->type);
3595 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3596 }
3597
3598 /* get prefix length */
3599 switch (id_b->type) {
3600 case IPSECDOI_ID_IPV4_ADDR:
3601 plen = sizeof(struct in_addr) << 3;
3602 break;
3603 #ifdef INET6
3604 case IPSECDOI_ID_IPV6_ADDR:
3605 plen = sizeof(struct in6_addr) << 3;
3606 break;
3607 #endif
3608 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3609 #ifdef INET6
3610 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3611 #endif
3612 {
3613 unsigned char *p;
3614 unsigned int max;
3615 int alen = sizeof(struct in_addr);
3616
3617 switch (id_b->type) {
3618 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3619 alen = sizeof(struct in_addr);
3620 break;
3621 #ifdef INET6
3622 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3623 alen = sizeof(struct in6_addr);
3624 break;
3625 #endif
3626 }
3627
3628 /* sanity check */
3629 if (buf->l < alen)
3630 return ISAKMP_INTERNAL_ERROR;
3631
3632 /* get subnet mask length */
3633 plen = 0;
3634 max = alen <<3;
3635
3636 p = (unsigned char *) buf->v
3637 + sizeof(struct ipsecdoi_id_b)
3638 + alen;
3639
3640 for (; *p == 0xff; p++) {
3641 plen += 8;
3642 if (plen >= max)
3643 break;
3644 }
3645
3646 if (plen < max) {
3647 unsigned int l = 0;
3648 unsigned char b = ~(*p);
3649
3650 while (b) {
3651 b >>= 1;
3652 l++;
3653 }
3654
3655 l = 8 - l;
3656 plen += l;
3657 }
3658 }
3659 break;
3660 }
3661
3662 *prefixlen = plen;
3663 *ul_proto = id_b->proto_id == 0
3664 ? IPSEC_ULPROTO_ANY
3665 : id_b->proto_id; /* see sockaddr2id() */
3666
3667 return 0;
3668 }
3669
3670 /*
3671 * make printable string from ID payload except of general header.
3672 */
3673 const char *
3674 ipsecdoi_id2str(id)
3675 const rc_vchar_t *id;
3676 {
3677 static char buf[256];
3678
3679 /* XXX */
3680 buf[0] = '\0';
3681
3682 return buf;
3683 }
3684
3685 /*
3686 * set IPsec data attributes into a proposal.
3687 * NOTE: MUST called per a transform.
3688 */
3689 int
3690 ipsecdoi_t2satrns(t, pp, pr, tr)
3691 struct isakmp_pl_t *t;
3692 struct saprop *pp;
3693 struct saproto *pr;
3694 struct satrns *tr;
3695 {
3696 struct isakmp_data *d, *prev;
3697 int flag, type;
3698 int error = -1;
3699 int life_t;
3700 int tlen;
3701
3702 tr->trns_no = t->t_no;
3703 tr->trns_id = t->t_id;
3704
3705 tlen = get_uint16(&t->h.len) - sizeof(*t);
3706 prev = (struct isakmp_data *)NULL;
3707 d = (struct isakmp_data *)(t + 1);
3708
3709 /* default */
3710 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
3711 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3712 pp->lifebyte = 0;
3713 tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
3714
3715 while (tlen > 0) {
3716
3717 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
3718 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
3719
3720 plog(PLOG_DEBUG, PLOGLOC, NULL,
3721 "type=%s, flag=0x%04x, lorv=%s\n",
3722 s_ipsecdoi_attr(type), flag,
3723 s_ipsecdoi_attr_v(type, get_uint16(&d->lorv)));
3724
3725 switch (type) {
3726 case IPSECDOI_ATTR_SA_LD_TYPE:
3727 {
3728 int type = get_uint16(&d->lorv);
3729 switch (type) {
3730 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
3731 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
3732 life_t = type;
3733 break;
3734 default:
3735 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3736 "invalid life duration type. "
3737 "using default value.\n");
3738 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
3739 break;
3740 }
3741 break;
3742 }
3743 case IPSECDOI_ATTR_SA_LD:
3744 if (prev == NULL
3745 || (get_uint16(&prev->type) & ~ISAKMP_GEN_MASK) !=
3746 IPSECDOI_ATTR_SA_LD_TYPE) {
3747 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3748 "life duration must follow ltype\n");
3749 break;
3750 }
3751
3752 {
3753 uint32_t t;
3754 rc_vchar_t *ld_buf = NULL;
3755
3756 if (flag) {
3757 /* i.e. ISAKMP_GEN_TV */
3758 ld_buf = rc_vmalloc(sizeof(d->lorv));
3759 if (ld_buf == NULL) {
3760 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3761 "failed to get LD buffer.\n");
3762 goto end;
3763 }
3764 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
3765 } else {
3766 int len = get_uint16(&d->lorv);
3767 /* i.e. ISAKMP_GEN_TLV */
3768 ld_buf = rc_vmalloc(len);
3769 if (ld_buf == NULL) {
3770 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3771 "failed to get LD buffer.\n");
3772 goto end;
3773 }
3774 memcpy(ld_buf->v, d + 1, len);
3775 }
3776 switch (life_t) {
3777 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
3778 t = ipsecdoi_set_ld(ld_buf);
3779 rc_vfree(ld_buf);
3780 if (t == 0) {
3781 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3782 "invalid life duration.\n");
3783 goto end;
3784 }
3785 /* lifetime must be equal in a proposal. */
3786 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
3787 pp->lifetime = t;
3788 else if (pp->lifetime != t) {
3789 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3790 "lifetime mismatched "
3791 "in a proposal, "
3792 "prev:%ld curr:%lu.\n",
3793 (long)pp->lifetime, (unsigned long)t);
3794 goto end;
3795 }
3796 break;
3797 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
3798 t = ipsecdoi_set_ld(ld_buf);
3799 rc_vfree(ld_buf);
3800 if (t == 0) {
3801 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3802 "invalid life duration.\n");
3803 goto end;
3804 }
3805 /* lifebyte must be equal in a proposal. */
3806 if (pp->lifebyte == 0)
3807 pp->lifebyte = t;
3808 else if (pp->lifebyte != t) {
3809 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3810 "lifebyte mismatched "
3811 "in a proposal, "
3812 "prev:%ld curr:%lu.\n",
3813 (long)pp->lifebyte, (unsigned long)t);
3814 goto end;
3815 }
3816 break;
3817 default:
3818 rc_vfree(ld_buf);
3819 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3820 "invalid life type: %d\n", life_t);
3821 goto end;
3822 }
3823 }
3824 break;
3825
3826 case IPSECDOI_ATTR_GRP_DESC:
3827 /*
3828 * RFC2407: 4.5 IPSEC Security Association Attributes
3829 * Specifies the Oakley Group to be used in a PFS QM
3830 * negotiation. For a list of supported values, see
3831 * Appendix A of [IKE].
3832 */
3833 if (pp->pfs_group == 0)
3834 pp->pfs_group = get_uint16(&d->lorv);
3835 else if (pp->pfs_group != get_uint16(&d->lorv)) {
3836 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3837 "pfs_group mismatched "
3838 "in a proposal.\n");
3839 goto end;
3840 }
3841 break;
3842
3843 case IPSECDOI_ATTR_ENC_MODE:
3844 if (pr->encmode &&
3845 pr->encmode != get_uint16(&d->lorv)) {
3846 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3847 "multiple encmode exist "
3848 "in a transform.\n");
3849 goto end;
3850 }
3851 pr->encmode = get_uint16(&d->lorv);
3852 break;
3853
3854 case IPSECDOI_ATTR_AUTH:
3855 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
3856 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3857 "multiple authtype exist "
3858 "in a transform.\n");
3859 goto end;
3860 }
3861 tr->authtype = get_uint16(&d->lorv);
3862 break;
3863
3864 case IPSECDOI_ATTR_KEY_LENGTH:
3865 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
3866 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3867 "key length defined but not ESP");
3868 goto end;
3869 }
3870 tr->encklen = get_uint16(&d->lorv);
3871 break;
3872
3873 case IPSECDOI_ATTR_KEY_ROUNDS:
3874 case IPSECDOI_ATTR_COMP_DICT_SIZE:
3875 case IPSECDOI_ATTR_COMP_PRIVALG:
3876 default:
3877 break;
3878 }
3879
3880 prev = d;
3881 if (flag) {
3882 tlen -= sizeof(*d);
3883 d = (struct isakmp_data *)((char *)d + sizeof(*d));
3884 } else {
3885 tlen -= (sizeof(*d) + get_uint16(&d->lorv));
3886 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + get_uint16(&d->lorv));
3887 }
3888 }
3889
3890 error = 0;
3891 end:
3892 return error;
3893 }
3894
3895 int
3896 ipsecdoi_authalg_rct2trnsid(rc_type alg)
3897 {
3898 switch (alg) {
3899 case RCT_ALG_HMAC_MD5:
3900 return IPSECDOI_AH_MD5;
3901 case RCT_ALG_HMAC_SHA1:
3902 return IPSECDOI_AH_SHA;
3903 #if 0
3904 case RCT_ALG_DES_MAC:
3905 return IPSECDOI_AH_DES;
3906 #endif
3907 case RCT_ALG_KPDK_MD5:
3908 return IPSECDOI_AH_MD5;
3909 case RCT_ALG_KPDK_SHA1:
3910 return IPSECDOI_AH_SHA;
3911 default:
3912 plog(PLOG_INTERR, PLOGLOC, 0,
3913 "unsupported authentication algorithm for AH: %s\n",
3914 rct2str(alg));
3915 return -1;
3916 }
3917 }
3918
3919 #if 0
3920 int
3921 ipsecdoi_authalg2trnsid(alg)
3922 int alg;
3923 {
3924 switch (alg) {
3925 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
3926 return IPSECDOI_AH_MD5;
3927 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
3928 return IPSECDOI_AH_SHA;
3929 case IPSECDOI_ATTR_AUTH_DES_MAC:
3930 return IPSECDOI_AH_DES;
3931 case IPSECDOI_ATTR_AUTH_KPDK:
3932 return IPSECDOI_AH_MD5; /* XXX */
3933 default:
3934 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3935 "invalid authentication algorithm:%d\n", alg);
3936 }
3937 return -1;
3938 }
3939 #endif
3940
3941 #ifdef HAVE_GSSAPI
3942 struct isakmpsa *
3943 fixup_initiator_sa(match, received)
3944 struct isakmpsa *match, *received;
3945 {
3946 struct isakmpsa *newsa;
3947
3948 if (received->gssid == NULL)
3949 return match;
3950
3951 newsa = newisakmpsa();
3952 memcpy(newsa, match, sizeof *newsa);
3953
3954 if (match->dhgrp != NULL) {
3955 newsa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
3956 memcpy(newsa->dhgrp, match->dhgrp, sizeof (struct dhgroup));
3957 }
3958 newsa->next = NULL;
3959 newsa->rmconf = NULL;
3960
3961 newsa->gssid = rc_vdup(received->gssid);
3962
3963 return newsa;
3964 }
3965 #endif
3966
3967 #if 0
3968 static int rm_idtype2doi[] = {
3969 IPSECDOI_ID_FQDN,
3970 IPSECDOI_ID_USER_FQDN,
3971 IPSECDOI_ID_KEY_ID,
3972 255, /* it's type of "address"
3973 * it expands into 4 types by another function. */
3974 IPSECDOI_ID_DER_ASN1_DN,
3975 };
3976
3977 /*
3978 * convert idtype to DOI value.
3979 * OUT 255 : NG
3980 * other: converted.
3981 */
3982 int
3983 idtype2doi(idtype)
3984 int idtype;
3985 {
3986 if (ARRAYLEN(rm_idtype2doi) > idtype)
3987 return rm_idtype2doi[idtype];
3988 return 255;
3989 }
3990
3991 int
3992 doi2idtype(doi)
3993 int doi;
3994 {
3995 switch(doi) {
3996 case IPSECDOI_ID_FQDN:
3997 return(IDTYPE_FQDN);
3998 case IPSECDOI_ID_USER_FQDN:
3999 return(IDTYPE_USERFQDN);
4000 case IPSECDOI_ID_KEY_ID:
4001 return(IDTYPE_KEYID);
4002 case IPSECDOI_ID_DER_ASN1_DN:
4003 return(IDTYPE_ASN1DN);
4004 case IPSECDOI_ID_IPV4_ADDR:
4005 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4006 case IPSECDOI_ID_IPV6_ADDR:
4007 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4008 return(IDTYPE_ADDRESS);
4009 default:
4010 plog(PLOG_PROTOWARN, PLOGLOC, 0,
4011 "Improper idtype:%s\n",
4012 s_ipsecdoi_ident(doi));
4013 return(IDTYPE_ADDRESS); /* XXX */
4014 }
4015 /*NOTREACHED*/
4016 }
4017 #endif
4018