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