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