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