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