]> git.saurik.com Git - apple/network_cmds.git/blame - racoon.tproj/ipsec_doi.c
network_cmds-245.19.tar.gz
[apple/network_cmds.git] / racoon.tproj / ipsec_doi.c
CommitLineData
ac2f15b3 1/* $KAME: ipsec_doi.c,v 1.158 2002/09/27 05:55:52 itojun Exp $ */
7ba0088d
A
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"
ac2f15b3 83#include "isakmp_natd.h"
7ba0088d
A
84
85#ifdef HAVE_GSSAPI
86#include "gssapi.h"
87#endif
88
89int verbose_proposal_check = 1;
90
91static vchar_t *get_ph1approval __P((struct ph1handle *, struct prop_pair **));
92static struct isakmpsa *get_ph1approvalx __P((struct prop_pair *,
93 struct isakmpsa *, struct isakmpsa *));
94static void print_ph1mismatched __P((struct prop_pair *, struct isakmpsa *));
95static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *));
96static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
97static struct prop_pair *get_ph2approval __P((struct ph2handle *,
98 struct prop_pair **));
99static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
100 struct prop_pair *));
101static void free_proppair0 __P((struct prop_pair *));
102
103static int get_transform
104 __P((struct isakmp_pl_p *, struct prop_pair **, int *));
105static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
106
107static int check_doi __P((u_int32_t));
108static int check_situation __P((u_int32_t));
109
110static int check_prot_main __P((int));
111static int check_prot_quick __P((int));
112static int (*check_protocol[]) __P((int)) = {
113 check_prot_main, /* IPSECDOI_TYPE_PH1 */
114 check_prot_quick, /* IPSECDOI_TYPE_PH2 */
115};
116
117static int check_spi_size __P((int, int));
118
119static int check_trns_isakmp __P((int));
120static int check_trns_ah __P((int));
121static int check_trns_esp __P((int));
122static int check_trns_ipcomp __P((int));
123static int (*check_transform[]) __P((int)) = {
124 0,
125 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
126 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
127 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
128 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
129};
130
131static int check_attr_isakmp __P((struct isakmp_pl_t *));
132static int check_attr_ah __P((struct isakmp_pl_t *));
133static int check_attr_esp __P((struct isakmp_pl_t *));
134static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
135static int check_attr_ipcomp __P((struct isakmp_pl_t *));
136static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
137 0,
138 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
139 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
140 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
141 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
142};
143
144static int setph1prop __P((struct isakmpsa *, caddr_t));
145static int setph1trns __P((struct isakmpsa *, caddr_t));
146static int setph1attr __P((struct isakmpsa *, caddr_t));
147static vchar_t *setph2proposal0 __P((const struct ph2handle *,
148 const struct saprop *, const struct saproto *));
149
150static vchar_t *getidval __P((int, vchar_t *));
151
152#ifdef HAVE_GSSAPI
153static struct isakmpsa *fixup_initiator_sa __P((struct isakmpsa *,
154 struct isakmpsa *));
155#endif
156
157/*%%%*/
158/*
159 * check phase 1 SA payload.
160 * make new SA payload to be replyed not including general header.
161 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
162 * OUT:
163 * positive: the pointer to new buffer of SA payload.
164 * network byte order.
165 * NULL : error occurd.
166 */
167int
168ipsecdoi_checkph1proposal(sa, iph1)
169 vchar_t *sa;
170 struct ph1handle *iph1;
171{
172 vchar_t *newsa; /* new SA payload approved. */
173 struct prop_pair **pair;
174
175 /* get proposal pair */
176 pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
177 if (pair == NULL)
178 return -1;
179
180 /* check and get one SA for use */
181 newsa = get_ph1approval(iph1, pair);
182
183 free_proppair(pair);
184
185 if (newsa == NULL)
186 return -1;
187
188 iph1->sa_ret = newsa;
189
190 return 0;
191}
192
193/*
194 * acceptable check for remote configuration.
195 * return a new SA payload to be reply to peer.
196 */
197static vchar_t *
198get_ph1approval(iph1, pair)
199 struct ph1handle *iph1;
200 struct prop_pair **pair;
201{
202 vchar_t *newsa;
203 struct isakmpsa *sa, tsa;
204 struct prop_pair *s, *p;
205 int prophlen;
206 int i;
207
208 iph1->approval = NULL;
209
210 for (i = 0; i < MAXPROPPAIRLEN; i++) {
211 if (pair[i] == NULL)
212 continue;
213 for (s = pair[i]; s; s = s->next) {
214 prophlen = sizeof(struct isakmp_pl_p)
215 + s->prop->spi_size;
216 /* compare proposal and select one */
217 for (p = s; p; p = p->tnext) {
218 sa = get_ph1approvalx(p, iph1->rmconf->proposal,
219 &tsa);
220 if (sa != NULL)
221 goto found;
222 }
223 }
224 }
225
226 /*
227 * if there is no suitable proposal, racoon complains about all of
228 * mismatched items in those proposal.
229 */
230 if (verbose_proposal_check) {
231 for (i = 0; i < MAXPROPPAIRLEN; i++) {
232 if (pair[i] == NULL)
233 continue;
234 for (s = pair[i]; s; s = s->next) {
235 prophlen = sizeof(struct isakmp_pl_p)
236 + s->prop->spi_size;
237 for (p = s; p; p = p->tnext) {
238 print_ph1mismatched(p,
239 iph1->rmconf->proposal);
240 }
241 }
242 }
243 }
244 plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
245
246 return NULL;
247
248found:
249 plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
250
251 /* check DH group settings */
252 if (sa->dhgrp) {
253 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
254 /* it's ok */
255 goto saok;
256 }
257 plog(LLV_WARNING, LOCATION, NULL,
258 "invalid DH parameter found, use default.\n");
259 oakley_dhgrp_free(sa->dhgrp);
260 }
261
262 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
263 sa->dhgrp = NULL;
264 return NULL;
265 }
266
267saok:
268#ifdef HAVE_GSSAPI
269 if (sa->gssid != NULL)
270 plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%s'\n",
271 sa->gssid->v);
272 if (iph1-> side == INITIATOR) {
273 if (iph1->rmconf->proposal->gssid != NULL)
274 iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
275 if (tsa.gssid != NULL)
276 iph1->gi_r = vdup(tsa.gssid);
277 iph1->approval = fixup_initiator_sa(sa, &tsa);
278 } else {
279 if (tsa.gssid != NULL) {
280 iph1->gi_r = vdup(tsa.gssid);
281 if (iph1->rmconf->proposal->gssid != NULL)
282 iph1->gi_i =
283 vdup(iph1->rmconf->proposal->gssid);
284 else
285 iph1->gi_i = gssapi_get_default_id(iph1);
286 if (sa->gssid == NULL && iph1->gi_i != NULL)
287 sa->gssid = vdup(iph1->gi_i);
288 }
289 iph1->approval = sa;
290 }
291 if (iph1->gi_i != NULL)
292 plog(LLV_DEBUG, LOCATION, NULL, "GIi is %*s\n",
293 iph1->gi_i->l, iph1->gi_i->v);
294 if (iph1->gi_r != NULL)
295 plog(LLV_DEBUG, LOCATION, NULL, "GIr is %*s\n",
296 iph1->gi_r->l, iph1->gi_r->v);
297#else
298 iph1->approval = sa;
299#endif
300
301 newsa = get_sabyproppair(p, iph1);
302 if (newsa == NULL)
303 iph1->approval = NULL;
304
305 return newsa;
306}
307
308/*
309 * compare peer's single proposal and all of my proposal.
310 * and select one if suiatable.
311 * p : one of peer's proposal.
312 * proposal: my proposals.
313 */
314static struct isakmpsa *
315get_ph1approvalx(p, proposal, sap)
316 struct prop_pair *p;
317 struct isakmpsa *proposal, *sap;
318{
7ba0088d 319 struct isakmp_pl_p *prop = p->prop;
7ba0088d
A
320 struct isakmp_pl_t *trns = p->trns;
321 struct isakmpsa sa, *s, *tsap;
322
323 plog(LLV_DEBUG, LOCATION, NULL,
324 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
325 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
326 prop->spi_size, prop->num_t);
327
328 plog(LLV_DEBUG, LOCATION, NULL,
329 "trns#=%d, trns-id=%s\n",
330 trns->t_no,
331 s_ipsecdoi_trns(prop->proto_id, trns->t_id));
332
333 tsap = sap != NULL ? sap : &sa;
334
335 memset(tsap, 0, sizeof(*tsap));
336 if (t2isakmpsa(trns, tsap) < 0)
337 return NULL;
338 for (s = proposal; s != NULL; s = s->next) {
339 plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
340 plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
341 s->lifetime, tsap->lifetime);
342 plog(LLV_DEBUG, LOCATION, NULL, "(lifebyte = %ld:%ld)\n",
343 s->lifebyte, tsap->lifebyte);
344 plog(LLV_DEBUG, LOCATION, NULL, "enctype = %s:%s\n",
345 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
346 s->enctype),
347 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
348 tsap->enctype));
349 plog(LLV_DEBUG, LOCATION, NULL, "(encklen = %d:%d)\n",
350 s->encklen, tsap->encklen);
351 plog(LLV_DEBUG, LOCATION, NULL, "hashtype = %s:%s\n",
352 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
353 s->hashtype),
354 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
355 tsap->hashtype));
356 plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
357 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
358 s->authmethod),
359 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
360 tsap->authmethod));
361 plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
362 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
363 s->dh_group),
364 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
365 tsap->dh_group));
366#if 0
367 /* XXX to be considered */
368 if (tsap->lifetime > s->lifetime) ;
369 if (tsap->lifebyte > s->lifebyte) ;
370#endif
371 /*
372 * if responder side and peer's key length in proposal
373 * is bigger than mine, it might be accepted.
374 */
375 if(tsap->enctype == s->enctype
376 && tsap->authmethod == s->authmethod
377 && tsap->hashtype == s->hashtype
378 && tsap->dh_group == s->dh_group
379 && tsap->encklen == s->encklen)
380 break;
381 }
382
383 if (tsap->dhgrp != NULL)
384 oakley_dhgrp_free(tsap->dhgrp);
385 return s;
386}
387
388/*
389 * print all of items in peer's proposal which are mismatched to my proposal.
390 * p : one of peer's proposal.
391 * proposal: my proposals.
392 */
393static void
394print_ph1mismatched(p, proposal)
395 struct prop_pair *p;
396 struct isakmpsa *proposal;
397{
398 struct isakmpsa sa, *s;
399
400 memset(&sa, 0, sizeof(sa));
401 if (t2isakmpsa(p->trns, &sa) < 0)
402 return;
403 for (s = proposal; s ; s = s->next) {
404 if (sa.enctype != s->enctype) {
405 plog(LLV_ERROR, LOCATION, NULL,
406 "rejected enctype: "
407 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
408 "%s:%s\n",
409 s->prop_no, s->trns_no,
410 p->prop->p_no, p->trns->t_no,
411 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
412 s->enctype),
413 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
414 sa.enctype));
415 }
416 if (sa.authmethod != s->authmethod) {
417 plog(LLV_ERROR, LOCATION, NULL,
418 "rejected authmethod: "
419 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
420 "%s:%s\n",
421 s->prop_no, s->trns_no,
422 p->prop->p_no, p->trns->t_no,
423 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
424 s->authmethod),
425 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
426 sa.authmethod));
427 }
428 if (sa.hashtype != s->hashtype) {
429 plog(LLV_ERROR, LOCATION, NULL,
430 "rejected hashtype: "
431 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
432 "%s:%s\n",
433 s->prop_no, s->trns_no,
434 p->prop->p_no, p->trns->t_no,
435 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
436 s->hashtype),
437 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
438 sa.hashtype));
439 }
440 if (sa.dh_group != s->dh_group) {
441 plog(LLV_ERROR, LOCATION, NULL,
442 "rejected dh_group: "
443 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
444 "%s:%s\n",
445 s->prop_no, s->trns_no,
446 p->prop->p_no, p->trns->t_no,
447 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
448 s->dh_group),
449 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
450 sa.dh_group));
451 }
452 }
453
454 if (sa.dhgrp != NULL)
455 oakley_dhgrp_free(sa.dhgrp);
456}
457
458/*
459 * get ISAKMP data attributes
460 */
461static int
462t2isakmpsa(trns, sa)
463 struct isakmp_pl_t *trns;
464 struct isakmpsa *sa;
465{
466 struct isakmp_data *d, *prev;
467 int flag, type;
468 int error = -1;
469 int life_t;
470 int keylen = 0;
471 vchar_t *val = NULL;
472 int len, tlen;
473 u_char *p;
474
475 tlen = ntohs(trns->h.len) - sizeof(*trns);
476 prev = (struct isakmp_data *)NULL;
477 d = (struct isakmp_data *)(trns + 1);
478
479 /* default */
480 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
481 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
482 sa->lifebyte = 0;
483 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
484 if (!sa->dhgrp)
485 goto err;
486
487 while (tlen > 0) {
488
489 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
490 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
491
492 plog(LLV_DEBUG, LOCATION, NULL,
493 "type=%s, flag=0x%04x, lorv=%s\n",
494 s_oakley_attr(type), flag,
495 s_oakley_attr_v(type, ntohs(d->lorv)));
496
497 /* get variable-sized item */
498 switch (type) {
499 case OAKLEY_ATTR_GRP_PI:
500 case OAKLEY_ATTR_GRP_GEN_ONE:
501 case OAKLEY_ATTR_GRP_GEN_TWO:
502 case OAKLEY_ATTR_GRP_CURVE_A:
503 case OAKLEY_ATTR_GRP_CURVE_B:
504 case OAKLEY_ATTR_SA_LD:
505 case OAKLEY_ATTR_GRP_ORDER:
506 if (flag) { /*TV*/
507 len = 2;
508 p = (u_char *)&d->lorv;
509 } else { /*TLV*/
510 len = ntohs(d->lorv);
511 p = (u_char *)(d + 1);
512 }
513 val = vmalloc(len);
514 if (!val)
515 return -1;
516 memcpy(val->v, p, len);
517 break;
518
519 default:
520 break;
521 }
522
523 switch (type) {
524 case OAKLEY_ATTR_ENC_ALG:
525 sa->enctype = (u_int16_t)ntohs(d->lorv);
526 break;
527
528 case OAKLEY_ATTR_HASH_ALG:
529 sa->hashtype = (u_int16_t)ntohs(d->lorv);
530 break;
531
532 case OAKLEY_ATTR_AUTH_METHOD:
533 sa->authmethod = ntohs(d->lorv);
534 break;
535
536 case OAKLEY_ATTR_GRP_DESC:
537 sa->dh_group = (u_int16_t)ntohs(d->lorv);
538 break;
539
540 case OAKLEY_ATTR_GRP_TYPE:
541 {
542 int type = (int)ntohs(d->lorv);
543 if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
544 sa->dhgrp->type = type;
545 else
546 return -1;
547 break;
548 }
549 case OAKLEY_ATTR_GRP_PI:
550 sa->dhgrp->prime = val;
551 break;
552
553 case OAKLEY_ATTR_GRP_GEN_ONE:
554 vfree(val);
555 if (!flag)
556 sa->dhgrp->gen1 = ntohs(d->lorv);
557 else {
558 int len = ntohs(d->lorv);
559 sa->dhgrp->gen1 = 0;
560 if (len > 4)
561 return -1;
562 memcpy(&sa->dhgrp->gen1, d + 1, len);
563 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
564 }
565 break;
566
567 case OAKLEY_ATTR_GRP_GEN_TWO:
568 vfree(val);
569 if (!flag)
570 sa->dhgrp->gen2 = ntohs(d->lorv);
571 else {
572 int len = ntohs(d->lorv);
573 sa->dhgrp->gen2 = 0;
574 if (len > 4)
575 return -1;
576 memcpy(&sa->dhgrp->gen2, d + 1, len);
577 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
578 }
579 break;
580
581 case OAKLEY_ATTR_GRP_CURVE_A:
582 sa->dhgrp->curve_a = val;
583 break;
584
585 case OAKLEY_ATTR_GRP_CURVE_B:
586 sa->dhgrp->curve_b = val;
587 break;
588
589 case OAKLEY_ATTR_SA_LD_TYPE:
590 {
591 int type = (int)ntohs(d->lorv);
592 switch (type) {
593 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
594 case OAKLEY_ATTR_SA_LD_TYPE_KB:
595 life_t = type;
596 break;
597 default:
598 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
599 break;
600 }
601 break;
602 }
603 case OAKLEY_ATTR_SA_LD:
604 if (!prev
605 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
606 OAKLEY_ATTR_SA_LD_TYPE) {
607 plog(LLV_ERROR, LOCATION, NULL,
608 "life duration must follow ltype\n");
609 break;
610 }
611
612 switch (life_t) {
613 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
614 sa->lifetime = ipsecdoi_set_ld(val);
615 vfree(val);
616 if (sa->lifetime == 0) {
617 plog(LLV_ERROR, LOCATION, NULL,
618 "invalid life duration.\n");
619 goto err;
620 }
621 break;
622 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
623 sa->lifebyte = ipsecdoi_set_ld(val);
624 vfree(val);
625 if (sa->lifetime == 0) {
626 plog(LLV_ERROR, LOCATION, NULL,
627 "invalid life duration.\n");
628 goto err;
629 }
630 break;
631 default:
632 vfree(val);
633 plog(LLV_ERROR, LOCATION, NULL,
634 "invalid life type: %d\n", life_t);
635 goto err;
636 }
637 break;
638
639 case OAKLEY_ATTR_KEY_LEN:
640 {
641 int len = ntohs(d->lorv);
642 if (len % 8 != 0) {
643 plog(LLV_ERROR, LOCATION, NULL,
644 "keylen %d: not multiple of 8\n",
645 len);
646 goto err;
647 }
648 sa->encklen = (u_int16_t)len;
649 keylen++;
650 break;
651 }
652 case OAKLEY_ATTR_PRF:
653 case OAKLEY_ATTR_FIELD_SIZE:
654 /* unsupported */
655 break;
656
657 case OAKLEY_ATTR_GRP_ORDER:
658 sa->dhgrp->order = val;
659 break;
660#ifdef HAVE_GSSAPI
661 case OAKLEY_ATTR_GSS_ID:
662 {
663 int len = ntohs(d->lorv);
664
665 sa->gssid = vmalloc(len);
666 memcpy(sa->gssid->v, d + 1, len);
667 plog(LLV_DEBUG, LOCATION, NULL,
668 "received gss id '%s' (len %d)\n", sa->gssid->v,
669 sa->gssid->l);
670 break;
671 }
672#endif
673
674 default:
675 break;
676 }
677
678 prev = d;
679 if (flag) {
680 tlen -= sizeof(*d);
681 d = (struct isakmp_data *)((char *)d + sizeof(*d));
682 } else {
683 tlen -= (sizeof(*d) + ntohs(d->lorv));
684 d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
685 }
686 }
687
688 /* key length must not be specified on some algorithms */
689 if (keylen) {
690 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
691#ifdef HAVE_OPENSSL_IDEA_H
692 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
693#endif
694 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
695 plog(LLV_ERROR, LOCATION, NULL,
696 "keylen must not be specified "
697 "for encryption algorithm %d\n",
698 sa->enctype);
699 return -1;
700 }
701 }
702
703 return 0;
704err:
705 return error;
706}
707
708/*%%%*/
709/*
710 * check phase 2 SA payload and select single proposal.
711 * make new SA payload to be replyed not including general header.
712 * This function is called by responder only.
713 * OUT:
714 * 0: succeed.
715 * -1: error occured.
716 */
717int
718ipsecdoi_selectph2proposal(iph2)
719 struct ph2handle *iph2;
720{
721 struct prop_pair **pair;
722 struct prop_pair *ret;
723
724 /* get proposal pair */
725 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
726 if (pair == NULL)
727 return -1;
728
729 /* check and select a proposal. */
730 ret = get_ph2approval(iph2, pair);
731 free_proppair(pair);
732 if (ret == NULL)
733 return -1;
734
735 /* make a SA to be replayed. */
736 /* SPI must be updated later. */
737 iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
ffda1f4a 738
7ba0088d
A
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 */
753int
754ipsecdoi_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
836end:
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 */
856static int
857cmp_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 */
940static struct prop_pair *
941get_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 */
977static struct prop_pair *
978get_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 */
1008err:
1009 flushsaprop(pr0);
1010 return NULL;
1011
1012found:
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
1075void
1076free_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
1088static void
1089free_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 */
1107struct prop_pair **
1108get_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 */
1273static int
1274get_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 */
1380vchar_t *
1381get_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 */
1445int
1446ipsecdoi_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;
1496end:
1497 free_proppair(pair);
1498 return error;
1499}
1500
1501/*
1502 * make a new SA payload from prop_pair.
1503 */
1504vchar_t *
1505get_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 */
1606static u_int32_t
1607ipsecdoi_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 */
1636static int
1637check_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 */
1654static int
1655check_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 */
1679static int
1680check_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 */
1698static int
1699check_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
1718static int
1719check_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 */
1760static int
1761check_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 */
1779static int
1780check_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 */
1802static int
1803check_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 */
1835static int
1836check_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 */
1855static int
1856check_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 */
2035static int
2036check_attr_ah(trns)
2037 struct isakmp_pl_t *trns;
2038{
2039 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2040}
2041
2042static int
2043check_attr_esp(trns)
2044 struct isakmp_pl_t *trns;
2045{
2046 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2047}
2048
2049static int
2050check_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:
ffda1f4a
A
2088 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2089 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2090 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2091 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
7ba0088d
A
2092 break;
2093 default:
2094 plog(LLV_ERROR, LOCATION, NULL,
2095 "invalid encryption mode=%u.\n",
2096 lorv);
2097 return -1;
2098 }
2099 break;
2100
2101 case IPSECDOI_ATTR_AUTH:
2102 if (! flag) {
2103 plog(LLV_ERROR, LOCATION, NULL,
2104 "must be TV when AUTH.\n");
2105 return -1;
2106 }
2107
2108 switch (lorv) {
2109 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2110 if (proto_id == IPSECDOI_PROTO_IPSEC_AH
2111 && trns->t_id != IPSECDOI_AH_MD5) {
2112ahmismatch:
2113 plog(LLV_ERROR, LOCATION, NULL,
2114 "auth algorithm %u conflicts "
2115 "with transform %u.\n",
2116 lorv, trns->t_id);
2117 return -1;
2118 }
2119 break;
2120 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2121 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2122 if (trns->t_id != IPSECDOI_AH_SHA)
2123 goto ahmismatch;
2124 }
2125 break;
2126 case IPSECDOI_ATTR_AUTH_DES_MAC:
2127 case IPSECDOI_ATTR_AUTH_KPDK:
2128 plog(LLV_ERROR, LOCATION, NULL,
2129 "auth algorithm %u isn't supported.\n",
2130 lorv);
2131 return -1;
2132 default:
2133 plog(LLV_ERROR, LOCATION, NULL,
2134 "invalid auth algorithm=%u.\n",
2135 lorv);
2136 return -1;
2137 }
2138 break;
2139
2140 case IPSECDOI_ATTR_SA_LD_TYPE:
2141 if (! flag) {
2142 plog(LLV_ERROR, LOCATION, NULL,
2143 "must be TV when LD_TYPE.\n");
2144 return -1;
2145 }
2146
2147 switch (lorv) {
2148 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2149 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2150 break;
2151 default:
2152 plog(LLV_ERROR, LOCATION, NULL,
2153 "invalid life type %d.\n", lorv);
2154 return -1;
2155 }
2156 break;
2157
2158 case IPSECDOI_ATTR_SA_LD:
2159 if (flag) {
2160 /* i.e. ISAKMP_GEN_TV */
2161 plog(LLV_DEBUG, LOCATION, NULL,
2162 "life duration was in TLV.\n");
2163 } else {
2164 /* i.e. ISAKMP_GEN_TLV */
2165 if (lorv == 0) {
2166 plog(LLV_ERROR, LOCATION, NULL,
2167 "invalid length of LD\n");
2168 return -1;
2169 }
2170 }
2171 break;
2172
2173 case IPSECDOI_ATTR_GRP_DESC:
2174 if (! flag) {
2175 plog(LLV_ERROR, LOCATION, NULL,
2176 "must be TV when GRP_DESC.\n");
2177 return -1;
2178 }
2179
2180 if (!alg_oakley_dhdef_ok(lorv)) {
2181 plog(LLV_ERROR, LOCATION, NULL,
2182 "invalid group description=%u.\n",
2183 lorv);
2184 return -1;
2185 }
2186 break;
2187
2188 case IPSECDOI_ATTR_KEY_LENGTH:
2189 if (! flag) {
2190 plog(LLV_ERROR, LOCATION, NULL,
2191 "must be TV when KEY_LENGTH.\n");
2192 return -1;
2193 }
2194 break;
2195
2196 case IPSECDOI_ATTR_KEY_ROUNDS:
2197 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2198 case IPSECDOI_ATTR_COMP_PRIVALG:
2199 plog(LLV_ERROR, LOCATION, NULL,
2200 "attr type=%u isn't supported.\n", type);
2201 return -1;
2202
2203 default:
2204 plog(LLV_ERROR, LOCATION, NULL,
2205 "invalid attribute type %d.\n", type);
2206 return -1;
2207 }
2208
2209 if (flag) {
2210 tlen -= sizeof(*d);
2211 d = (struct isakmp_data *)((char *)d
2212 + sizeof(*d));
2213 } else {
2214 tlen -= (sizeof(*d) + lorv);
2215 d = (struct isakmp_data *)((caddr_t)d
2216 + sizeof(*d) + lorv);
2217 }
2218 }
2219
2220 if (proto_id == IPSECDOI_PROTO_IPSEC_AH
2221 && !attrseen[IPSECDOI_ATTR_AUTH]) {
2222 plog(LLV_ERROR, LOCATION, NULL,
2223 "attr AUTH must be present for AH.\n", type);
2224 return -1;
2225 }
2226
2227 return 0;
2228}
2229
2230static int
2231check_attr_ipcomp(trns)
2232 struct isakmp_pl_t *trns;
2233{
2234 struct isakmp_data *d;
2235 int tlen;
2236 int flag, type = 0;
2237 u_int16_t lorv;
2238 int attrseen[16]; /* XXX magic number */
2239
2240 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2241 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2242 memset(attrseen, 0, sizeof(attrseen));
2243
2244 while (tlen > 0) {
2245 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2246 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2247 lorv = ntohs(d->lorv);
2248
2249 plog(LLV_DEBUG, LOCATION, NULL,
2250 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2251 type, flag, lorv);
2252
2253 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2254 attrseen[type]++;
2255
2256 switch (type) {
2257 case IPSECDOI_ATTR_ENC_MODE:
2258 if (! flag) {
2259 plog(LLV_ERROR, LOCATION, NULL,
2260 "must be TV when ENC_MODE.\n");
2261 return -1;
2262 }
2263
2264 switch (lorv) {
2265 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2266 case IPSECDOI_ATTR_ENC_MODE_TRNS:
ffda1f4a
A
2267 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2268 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2269 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2270 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
7ba0088d
A
2271 break;
2272 default:
2273 plog(LLV_ERROR, LOCATION, NULL,
2274 "invalid encryption mode=%u.\n",
2275 lorv);
2276 return -1;
2277 }
2278 break;
2279
2280 case IPSECDOI_ATTR_SA_LD_TYPE:
2281 if (! flag) {
2282 plog(LLV_ERROR, LOCATION, NULL,
2283 "must be TV when LD_TYPE.\n");
2284 return -1;
2285 }
2286
2287 switch (lorv) {
2288 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2289 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2290 break;
2291 default:
2292 plog(LLV_ERROR, LOCATION, NULL,
2293 "invalid life type %d.\n", lorv);
2294 return -1;
2295 }
2296 break;
2297
2298 case IPSECDOI_ATTR_SA_LD:
2299 if (flag) {
2300 /* i.e. ISAKMP_GEN_TV */
2301 plog(LLV_DEBUG, LOCATION, NULL,
2302 "life duration was in TLV.\n");
2303 } else {
2304 /* i.e. ISAKMP_GEN_TLV */
2305 if (lorv == 0) {
2306 plog(LLV_ERROR, LOCATION, NULL,
2307 "invalid length of LD\n");
2308 return -1;
2309 }
2310 }
2311 break;
2312
2313 case IPSECDOI_ATTR_GRP_DESC:
2314 if (! flag) {
2315 plog(LLV_ERROR, LOCATION, NULL,
2316 "must be TV when GRP_DESC.\n");
2317 return -1;
2318 }
2319
2320 if (!alg_oakley_dhdef_ok(lorv)) {
2321 plog(LLV_ERROR, LOCATION, NULL,
2322 "invalid group description=%u.\n",
2323 lorv);
2324 return -1;
2325 }
2326 break;
2327
2328 case IPSECDOI_ATTR_AUTH:
2329 plog(LLV_ERROR, LOCATION, NULL,
2330 "invalid attr type=%u.\n", type);
2331 return -1;
2332
2333 case IPSECDOI_ATTR_KEY_LENGTH:
2334 case IPSECDOI_ATTR_KEY_ROUNDS:
2335 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2336 case IPSECDOI_ATTR_COMP_PRIVALG:
2337 plog(LLV_ERROR, LOCATION, NULL,
2338 "attr type=%u isn't supported.\n", type);
2339 return -1;
2340
2341 default:
2342 plog(LLV_ERROR, LOCATION, NULL,
2343 "invalid attribute type %d.\n", type);
2344 return -1;
2345 }
2346
2347 if (flag) {
2348 tlen -= sizeof(*d);
2349 d = (struct isakmp_data *)((char *)d
2350 + sizeof(*d));
2351 } else {
2352 tlen -= (sizeof(*d) + lorv);
2353 d = (struct isakmp_data *)((caddr_t)d
2354 + sizeof(*d) + lorv);
2355 }
2356 }
2357
2358#if 0
2359 if (proto_id == IPSECDOI_PROTO_IPCOMP
2360 && !attrseen[IPSECDOI_ATTR_AUTH]) {
2361 plog(LLV_ERROR, LOCATION, NULL,
2362 "attr AUTH must be present for AH.\n", type);
2363 return -1;
2364 }
2365#endif
2366
2367 return 0;
2368}
2369
2370/* %%% */
2371/*
2372 * create phase1 proposal from remote configuration.
2373 * NOT INCLUDING isakmp general header of SA payload
2374 */
2375vchar_t *
2376ipsecdoi_setph1proposal(props)
2377 struct isakmpsa *props;
2378{
2379 vchar_t *mysa;
2380 int sablen;
2381
2382 /* count total size of SA minus isakmp general header */
2383 /* not including isakmp general header of SA payload */
2384 sablen = sizeof(struct ipsecdoi_sa_b);
2385 sablen += setph1prop(props, NULL);
2386
2387 mysa = vmalloc(sablen);
2388 if (mysa == NULL) {
2389 plog(LLV_ERROR, LOCATION, NULL,
2390 "failed to allocate my sa buffer\n");
2391 return NULL;
2392 }
2393
2394 /* create SA payload */
2395 /* not including isakmp general header */
2396 ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
2397 ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
2398
2399 (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2400
2401 return mysa;
2402}
2403
2404static int
2405setph1prop(props, buf)
2406 struct isakmpsa *props;
2407 caddr_t buf;
2408{
2409 struct isakmp_pl_p *prop = NULL;
2410 struct isakmpsa *s = NULL;
2411 int proplen, trnslen;
2412 u_int8_t *np_t; /* pointer next trns type in previous header */
2413 int trns_num;
2414 caddr_t p = buf;
2415
2416 proplen = sizeof(*prop);
2417 if (buf) {
2418 /* create proposal */
2419 prop = (struct isakmp_pl_p *)p;
2420 prop->h.np = ISAKMP_NPTYPE_NONE;
2421 prop->p_no = props->prop_no;
2422 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2423 prop->spi_size = 0;
2424 p += sizeof(*prop);
2425 }
2426
2427 np_t = NULL;
2428 trns_num = 0;
2429
2430 for (s = props; s != NULL; s = s->next) {
2431 if (np_t)
2432 *np_t = ISAKMP_NPTYPE_T;
2433
2434 trnslen = setph1trns(s, p);
2435 proplen += trnslen;
2436 if (buf) {
2437 /* save buffer to pre-next payload */
2438 np_t = &((struct isakmp_pl_t *)p)->h.np;
2439 p += trnslen;
2440
2441 /* count up transform length */
2442 trns_num++;
2443 }
2444 }
2445
2446 /* update proposal length */
2447 if (buf) {
2448 prop->h.len = htons(proplen);
2449 prop->num_t = trns_num;
2450 }
2451
2452 return proplen;
2453}
2454
2455static int
2456setph1trns(sa, buf)
2457 struct isakmpsa *sa;
2458 caddr_t buf;
2459{
2460 struct isakmp_pl_t *trns = NULL;
2461 int trnslen, attrlen;
2462 caddr_t p = buf;
2463
2464 trnslen = sizeof(*trns);
2465 if (buf) {
2466 /* create transform */
2467 trns = (struct isakmp_pl_t *)p;
2468 trns->h.np = ISAKMP_NPTYPE_NONE;
2469 trns->t_no = sa->trns_no;
2470 trns->t_id = IPSECDOI_KEY_IKE;
2471 p += sizeof(*trns);
2472 }
2473
2474 attrlen = setph1attr(sa, p);
2475 trnslen += attrlen;
2476 if (buf)
2477 p += attrlen;
2478
2479 if (buf)
2480 trns->h.len = htons(trnslen);
2481
2482 return trnslen;
2483}
2484
2485static int
2486setph1attr(sa, buf)
2487 struct isakmpsa *sa;
2488 caddr_t buf;
2489{
2490 caddr_t p = buf;
2491 int attrlen = 0;
2492
2493 if (sa->lifetime) {
2494 attrlen += sizeof(struct isakmp_data)
2495 + sizeof(struct isakmp_data);
2496 if (sa->lifetime > 0xffff)
2497 attrlen += sizeof(sa->lifetime);
2498 if (buf) {
2499 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2500 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2501 if (sa->lifetime > 0xffff) {
2502 u_int32_t v = htonl((u_int32_t)sa->lifetime);
2503 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2504 (caddr_t)&v, sizeof(v));
2505 } else {
2506 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2507 sa->lifetime);
2508 }
2509 }
2510 }
2511
2512 if (sa->lifebyte) {
2513 attrlen += sizeof(struct isakmp_data)
2514 + sizeof(struct isakmp_data);
2515 if (sa->lifebyte > 0xffff)
2516 attrlen += sizeof(sa->lifebyte);
2517 if (buf) {
2518 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2519 OAKLEY_ATTR_SA_LD_TYPE_KB);
2520 if (sa->lifebyte > 0xffff) {
2521 u_int32_t v = htonl((u_int32_t)sa->lifebyte);
2522 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2523 (caddr_t)&v, sizeof(v));
2524 } else {
2525 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2526 sa->lifebyte);
2527 }
2528 }
2529 }
2530
2531 if (sa->enctype) {
2532 attrlen += sizeof(struct isakmp_data);
2533 if (buf)
2534 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2535 }
2536 if (sa->encklen) {
2537 attrlen += sizeof(struct isakmp_data);
2538 if (buf)
2539 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2540 }
2541 if (sa->authmethod) {
2542 attrlen += sizeof(struct isakmp_data);
2543 if (buf)
2544 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, sa->authmethod);
2545 }
2546 if (sa->hashtype) {
2547 attrlen += sizeof(struct isakmp_data);
2548 if (buf)
2549 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2550 }
2551 switch (sa->dh_group) {
2552 case OAKLEY_ATTR_GRP_DESC_MODP768:
2553 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2554 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2555 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2556 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2557 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2558 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2559 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2560 /* don't attach group type for known groups */
2561 attrlen += sizeof(struct isakmp_data);
2562 if (buf) {
2563 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2564 sa->dh_group);
2565 }
2566 break;
2567 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2568 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2569 /* don't attach group type for known groups */
2570 attrlen += sizeof(struct isakmp_data);
2571 if (buf) {
2572 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2573 OAKLEY_ATTR_GRP_TYPE_EC2N);
2574 }
2575 break;
2576 case 0:
2577 default:
2578 break;
2579 }
2580
2581#ifdef HAVE_GSSAPI
2582 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2583 sa->gssid != NULL) {
2584 attrlen += sizeof(struct isakmp_data);
2585 attrlen += sa->gssid->l;
2586 if (buf) {
2587 plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %d, "
2588 "val '%s'\n", sa->gssid->l, sa->gssid->v);
2589 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2590 (caddr_t)sa->gssid->v,
2591 sa->gssid->l);
2592 }
2593 }
2594#endif
2595
2596 return attrlen;
2597}
2598
2599static vchar_t *
2600setph2proposal0(iph2, pp, pr)
2601 const struct ph2handle *iph2;
2602 const struct saprop *pp;
2603 const struct saproto *pr;
2604{
2605 vchar_t *p;
2606 struct isakmp_pl_p *prop;
2607 struct isakmp_pl_t *trns;
2608 struct satrns *tr;
2609 int attrlen;
2610 size_t trnsoff;
2611 caddr_t x0, x;
2612 u_int8_t *np_t; /* pointer next trns type in previous header */
2613 const u_int8_t *spi;
2614
2615 p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2616 if (p == NULL)
2617 return NULL;
2618
2619 /* create proposal */
2620 prop = (struct isakmp_pl_p *)p->v;
2621 prop->h.np = ISAKMP_NPTYPE_NONE;
2622 prop->p_no = pp->prop_no;
2623 prop->proto_id = pr->proto_id;
2624 prop->num_t = 1;
2625
2626 spi = (const u_int8_t *)&pr->spi;
2627 switch (pr->proto_id) {
2628 case IPSECDOI_PROTO_IPCOMP:
2629 /*
2630 * draft-shacham-ippcp-rfc2393bis-05.txt:
2631 * construct 16bit SPI (CPI).
2632 * XXX we may need to provide a configuration option to
2633 * generate 32bit SPI. otherwise we cannot interoeprate
2634 * with nodes that uses 32bit SPI, in case we are initiator.
2635 */
2636 prop->spi_size = sizeof(u_int16_t);
2637 spi += sizeof(pr->spi) - sizeof(u_int16_t);
2638 p->l -= sizeof(pr->spi);
2639 p->l += sizeof(u_int16_t);
2640 break;
2641 default:
2642 prop->spi_size = sizeof(pr->spi);
2643 break;
2644 }
2645 memcpy(prop + 1, spi, prop->spi_size);
2646
2647 /* create transform */
2648 trnsoff = sizeof(*prop) + prop->spi_size;
2649 np_t = NULL;
2650
2651 for (tr = pr->head; tr; tr = tr->next) {
2652
2653 if (np_t) {
2654 *np_t = ISAKMP_NPTYPE_T;
2655 prop->num_t++;
2656 }
2657
2658 /* get attribute length */
2659 attrlen = 0;
2660 if (pp->lifetime) {
2661 attrlen += sizeof(struct isakmp_data)
2662 + sizeof(struct isakmp_data);
2663 if (pp->lifetime > 0xffff)
2664 attrlen += sizeof(u_int32_t);
2665 }
2666 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2667 attrlen += sizeof(struct isakmp_data)
2668 + sizeof(struct isakmp_data);
2669 if (pp->lifebyte > 0xffff)
2670 attrlen += sizeof(u_int32_t);
2671 }
2672 attrlen += sizeof(struct isakmp_data); /* enc mode */
2673 if (tr->encklen)
2674 attrlen += sizeof(struct isakmp_data);
2675
2676 switch (pr->proto_id) {
2677 case IPSECDOI_PROTO_IPSEC_ESP:
2678 /* non authentication mode ? */
2679 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2680 attrlen += sizeof(struct isakmp_data);
2681 break;
2682 case IPSECDOI_PROTO_IPSEC_AH:
2683 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
2684 plog(LLV_ERROR, LOCATION, NULL,
2685 "no authentication algorithm found "
2686 "but protocol is AH.\n");
2687 vfree(p);
2688 return NULL;
2689 }
2690 attrlen += sizeof(struct isakmp_data);
2691 break;
2692 case IPSECDOI_PROTO_IPCOMP:
2693 break;
2694 default:
2695 plog(LLV_ERROR, LOCATION, NULL,
2696 "invalid protocol: %d\n", pr->proto_id);
2697 vfree(p);
2698 return NULL;
2699 }
2700
2701 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
2702 attrlen += sizeof(struct isakmp_data);
2703
2704 p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
2705 if (p == NULL)
2706 return NULL;
2707 prop = (struct isakmp_pl_p *)p->v;
2708
2709 /* set transform's values */
2710 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2711 trns->h.np = ISAKMP_NPTYPE_NONE;
2712 trns->t_no = tr->trns_no;
2713 trns->t_id = tr->trns_id;
2714
2715 /* set attributes */
2716 x = x0 = p->v + trnsoff + sizeof(*trns);
2717
2718 if (pp->lifetime) {
2719 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2720 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
2721 if (pp->lifetime > 0xffff) {
2722 u_int32_t v = htonl((u_int32_t)pp->lifetime);
2723 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2724 (caddr_t)&v, sizeof(v));
2725 } else {
2726 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2727 pp->lifetime);
2728 }
2729 }
2730
2731 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2732 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2733 IPSECDOI_ATTR_SA_LD_TYPE_KB);
2734 if (pp->lifebyte > 0xffff) {
2735 u_int32_t v = htonl((u_int32_t)pp->lifebyte);
2736 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2737 (caddr_t)&v, sizeof(v));
2738 } else {
2739 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2740 pp->lifebyte);
2741 }
2742 }
2743
2744 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
2745
2746 if (tr->encklen)
2747 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
2748
2749 /* mandatory check has done above. */
2750 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2751 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
2752 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
2753
2754 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
2755 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
2756 iph2->sainfo->pfs_group);
2757
2758 /* update length of this transform. */
2759 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2760 trns->h.len = htons(sizeof(*trns) + attrlen);
2761
2762 /* save buffer to pre-next payload */
2763 np_t = &trns->h.np;
2764
2765 trnsoff += (sizeof(*trns) + attrlen);
2766 }
2767
2768 /* update length of this protocol. */
2769 prop->h.len = htons(p->l);
2770
2771 return p;
2772}
2773
2774/*
2775 * create phase2 proposal from policy configuration.
2776 * NOT INCLUDING isakmp general header of SA payload.
2777 * This function is called by initiator only.
2778 */
2779int
2780ipsecdoi_setph2proposal(iph2)
2781 struct ph2handle *iph2;
2782{
2783 struct saprop *proposal, *a;
2784 struct saproto *b = NULL;
2785 vchar_t *q;
2786 struct ipsecdoi_sa_b *sab;
2787 struct isakmp_pl_p *prop;
2788 size_t propoff; /* for previous field of type of next payload. */
2789
2790 proposal = iph2->proposal;
2791
2792 iph2->sa = vmalloc(sizeof(*sab));
2793 if (iph2->sa == NULL) {
2794 plog(LLV_ERROR, LOCATION, NULL,
2795 "failed to allocate my sa buffer\n");
2796 return -1;
2797 }
2798
2799 /* create SA payload */
2800 sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
2801 sab->doi = htonl(IPSEC_DOI);
2802 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
2803
2804 prop = NULL;
2805 propoff = 0;
2806 for (a = proposal; a; a = a->next) {
2807 for (b = a->head; b; b = b->next) {
ac2f15b3
A
2808#ifdef IKE_NAT_T
2809 /*
2810 * Hack to fix encmode, we may have detected a nat since
2811 * we last set pr->encmode. We need to fix this if
2812 * we now have a NAT. NAT-T doesn't work with AH.
2813 */
ffda1f4a
A
2814 int nattype;
2815 if (iph2->ph1 && (nattype = natd_hasnat(iph2->ph1)) &&
ac2f15b3
A
2816 b->proto_id != IPSECDOI_PROTO_IPSEC_AH)
2817 {
2818 switch (b->encmode)
2819 {
ffda1f4a 2820
ac2f15b3 2821 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
ffda1f4a
A
2822 if (nattype == natt_type_rfc ||
2823 nattype == natt_type_apple)
2824 b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC;
2825 else
2826 b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
ac2f15b3
A
2827 break;
2828 case IPSECDOI_ATTR_ENC_MODE_TRNS:
ffda1f4a
A
2829 if (nattype == natt_type_rfc ||
2830 nattype == natt_type_apple)
2831 b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
2832 else
2833 b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
ac2f15b3
A
2834 break;
2835 }
2836 }
2837#endif
2838
7ba0088d
A
2839 q = setph2proposal0(iph2, a, b);
2840 if (q == NULL) {
2841 vfree(iph2->sa);
2842 return -1;
2843 }
2844
2845 iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
2846 if (iph2->sa == NULL) {
2847 plog(LLV_ERROR, LOCATION, NULL,
2848 "failed to allocate my sa buffer\n");
2849 if (q)
2850 vfree(q);
2851 return -1;
2852 }
2853 memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
2854 if (propoff != 0) {
2855 prop = (struct isakmp_pl_p *)(iph2->sa->v +
2856 propoff);
2857 prop->h.np = ISAKMP_NPTYPE_P;
2858 }
2859 propoff = iph2->sa->l - q->l;
2860
2861 vfree(q);
2862 }
2863 }
2864
2865 return 0;
2866}
2867
ffda1f4a
A
2868/*
2869 * return 1 if all of the proposed protocols are tunnel mode.
2870 */
2871int
2872ipsecdoi_tunnelmode(iph2)
2873 struct ph2handle *iph2;
2874{
2875 struct saprop *pp;
2876 struct saproto *pr = NULL;
2877
2878 for (pp = iph2->proposal; pp; pp = pp->next) {
2879 for (pr = pp->head; pr; pr = pr->next) {
2880 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TUNNEL &&
2881 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC &&
2882 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT)
2883 return 0;
2884 }
2885 }
2886
2887 return 1;
2888}
2889
7ba0088d
A
2890/*
2891 * return 1 if all of the proposed protocols are transport mode.
2892 */
2893int
2894ipsecdoi_transportmode(iph2)
2895 struct ph2handle *iph2;
2896{
2897 struct saprop *pp;
2898 struct saproto *pr = NULL;
2899
2900 for (pp = iph2->proposal; pp; pp = pp->next) {
2901 for (pr = pp->head; pr; pr = pr->next) {
ac2f15b3 2902 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
ffda1f4a
A
2903 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
2904 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
7ba0088d
A
2905 return 0;
2906 }
2907 }
2908
2909 return 1;
2910}
2911
ffda1f4a 2912
7ba0088d
A
2913int
2914ipsecdoi_get_defaultlifetime()
2915{
2916 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
2917}
2918
2919int
2920ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
2921 int proto_id, enc, auth, comp;
2922{
2923#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
2924 switch (proto_id) {
2925 case IPSECDOI_PROTO_IPSEC_ESP:
2926 if (enc == 0 || comp != 0) {
2927 plog(LLV_ERROR, LOCATION, NULL,
2928 "illegal algorithm defined "
2929 "ESP enc=%s auth=%s comp=%s.\n",
2930 TMPALGTYPE2STR(enc),
2931 TMPALGTYPE2STR(auth),
2932 TMPALGTYPE2STR(comp));
2933 return -1;
2934 }
2935 break;
2936 case IPSECDOI_PROTO_IPSEC_AH:
2937 if (enc != 0 || auth == 0 || comp != 0) {
2938 plog(LLV_ERROR, LOCATION, NULL,
2939 "illegal algorithm defined "
2940 "AH enc=%s auth=%s comp=%s.\n",
2941 TMPALGTYPE2STR(enc),
2942 TMPALGTYPE2STR(auth),
2943 TMPALGTYPE2STR(comp));
2944 return -1;
2945 }
2946 break;
2947 case IPSECDOI_PROTO_IPCOMP:
2948 if (enc != 0 || auth != 0 || comp == 0) {
2949 plog(LLV_ERROR, LOCATION, NULL,
2950 "illegal algorithm defined "
2951 "IPcomp enc=%s auth=%s comp=%s.\n",
2952 TMPALGTYPE2STR(enc),
2953 TMPALGTYPE2STR(auth),
2954 TMPALGTYPE2STR(comp));
2955 return -1;
2956 }
2957 break;
2958 default:
2959 plog(LLV_ERROR, LOCATION, NULL,
2960 "invalid ipsec protocol %d\n", proto_id);
2961 return -1;
2962 }
2963#undef TMPALGTYPE2STR
2964 return 0;
2965}
2966
2967int
2968ipproto2doi(proto)
2969 int proto;
2970{
2971 switch (proto) {
2972 case IPPROTO_AH:
2973 return IPSECDOI_PROTO_IPSEC_AH;
2974 case IPPROTO_ESP:
2975 return IPSECDOI_PROTO_IPSEC_ESP;
2976 case IPPROTO_IPCOMP:
2977 return IPSECDOI_PROTO_IPCOMP;
2978 }
2979 return -1; /* XXX */
2980}
2981
2982int
2983doi2ipproto(proto)
2984 int proto;
2985{
2986 switch (proto) {
2987 case IPSECDOI_PROTO_IPSEC_AH:
2988 return IPPROTO_AH;
2989 case IPSECDOI_PROTO_IPSEC_ESP:
2990 return IPPROTO_ESP;
2991 case IPSECDOI_PROTO_IPCOMP:
2992 return IPPROTO_IPCOMP;
2993 }
2994 return -1; /* XXX */
2995}
2996
2997/*
2998 * check the following:
2999 * - In main mode with pre-shared key, only address type can be used.
3000 * - if proper type for phase 1 ?
3001 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3002 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3003 * - if ID payload sent from peer is equal to the ID expected by me.
3004 *
3005 * both of "id" and "id_p" should be ID payload without general header,
3006 */
3007int
3008ipsecdoi_checkid1(iph1)
3009 struct ph1handle *iph1;
3010{
3011 struct ipsecdoi_id_b *id_b;
2b484d24
A
3012 struct sockaddr *sa;
3013 caddr_t sa1, sa2;
7ba0088d
A
3014
3015 if (iph1->id_p == NULL) {
3016 plog(LLV_ERROR, LOCATION, NULL,
3017 "invalid iph1 passed id_p == NULL\n");
3018 return ISAKMP_INTERNAL_ERROR;
3019 }
3020 if (iph1->id_p->l < sizeof(*id_b)) {
3021 plog(LLV_ERROR, LOCATION, NULL,
3022 "invalid value passed as \"ident\" (len=%lu)\n",
3023 (u_long)iph1->id_p->l);
3024 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3025 }
3026
3027 id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3028
ffda1f4a
A
3029 /* In main mode with pre-shared key, only address type can be used.
3030 If NAT Traversal draft 02 being used - allow this. */
7ba0088d 3031 if (iph1->etype == ISAKMP_ETYPE_IDENT
ffda1f4a
A
3032 && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY
3033 && !natd_hasnat(iph1)) {
7ba0088d
A
3034 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3035 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3036 plog(LLV_ERROR, LOCATION, NULL,
3037 "Expecting IP address type in main mode, "
3038 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3039 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3040 }
3041 }
3042
3043 /* if proper type for phase 1 ? */
3044 switch (id_b->type) {
3045 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3046 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3047 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3048 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3049 plog(LLV_WARNING, LOCATION, NULL,
3050 "such ID type %s is not proper.\n",
3051 s_ipsecdoi_ident(id_b->type));
3052 /*FALLTHROUGH*/
3053 }
3054
3055 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3056 if (id_b->type == IPSECDOI_ID_IPV4_ADDR
3057 && id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3058
3059 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3060 plog(LLV_WARNING, LOCATION, NULL,
3061 "protocol ID and Port mismatched. "
3062 "proto_id:%d port:%d\n",
3063 id_b->proto_id, ntohs(id_b->port));
3064 /*FALLTHROUGH*/
3065
3066 } else if (id_b->proto_id == IPPROTO_UDP) {
3067 /*
3068 * copmaring with expecting port.
3069 * always permit if port is equal to PORT_ISAKMP
3070 */
3071 if (ntohs(id_b->port) != PORT_ISAKMP) {
3072
3073 u_int16_t port;
3074
3075 switch (iph1->remote->sa_family) {
3076 case AF_INET:
3077 port = ((struct sockaddr_in *)iph1->remote)->sin_port;
3078 break;
3079#ifdef INET6
3080 case AF_INET6:
3081 port = ((struct sockaddr_in6 *)iph1->remote)->sin6_port;
3082 break;
3083#endif
3084 default:
3085 plog(LLV_ERROR, LOCATION, NULL,
3086 "invalid family: %d\n",
3087 iph1->remote->sa_family);
3088 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3089 }
3090 if (ntohs(id_b->port) != port) {
3091 plog(LLV_WARNING, LOCATION, NULL,
3092 "port %d expected, but %d\n",
3093 port, ntohs(id_b->port));
3094 /*FALLTHROUGH*/
3095 }
3096 }
3097 }
3098 }
3099
3100 /* compare with the ID if specified. */
3101 if (iph1->rmconf->idv_p) {
3102 vchar_t *ident0 = NULL;
3103 vchar_t ident;
3104
3105 /* check the type of both IDs */
3106 if (iph1->rmconf->idvtype_p != doi2idtype(id_b->type)) {
3107 plog(LLV_WARNING, LOCATION, NULL,
3108 "ID type mismatched.\n");
3109 if (iph1->rmconf->verify_identifier)
3110 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3111 }
3112
3113 /* compare defined ID with the ID sent by peer. */
3114 ident0 = getidval(iph1->rmconf->idvtype_p, iph1->rmconf->idv_p);
3115
3116 switch (iph1->rmconf->idvtype_p) {
3117 case IDTYPE_ASN1DN:
3118 ident.v = (caddr_t)(id_b + 1);
3119 ident.l = ident0->l;
2b484d24
A
3120 if (eay_cmp_asn1dn(ident0, &ident))
3121 goto err;
3122 break;
3123 case IDTYPE_ADDRESS:
3124 sa = (struct sockaddr *)ident0->v;
3125 sa2 = (caddr_t)(id_b + 1);
3126 switch (sa->sa_family) {
3127 case AF_INET:
3128 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
3129 goto err;
3130
3131 sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
3132 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
3133 goto err;
3134 break;
3135#ifdef INET6
3136 case AF_INET6:
3137 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
3138 goto err;
3139 sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
3140 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
3141 goto err;
3142 break;
3143#endif
3144 default:
3145 goto err;
7ba0088d
A
3146 }
3147 break;
3148 default:
3149 if (memcmp(ident0->v, id_b + 1, ident0->l)) {
2b484d24 3150err:
7ba0088d
A
3151 plog(LLV_WARNING, LOCATION, NULL,
3152 "ID value mismatched.\n");
2b484d24
A
3153 if (iph1->rmconf->verify_identifier) {
3154 vfree(ident0);
7ba0088d 3155 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2b484d24 3156 }
7ba0088d
A
3157 }
3158 break;
3159 }
3160 vfree(ident0);
3161 }
3162
3163 return 0;
3164}
3165
3166/*
3167 * create ID payload for phase 1 and set into iph1->id.
3168 * NOT INCLUDING isakmp general header.
3169 * see, RFC2407 4.6.2.1
3170 */
3171int
3172ipsecdoi_setid1(iph1)
3173 struct ph1handle *iph1;
3174{
3175 vchar_t *ret = NULL;
3176 struct ipsecdoi_id_b id_b;
3177 vchar_t *ident = NULL;
3178 struct sockaddr *ipid = NULL;
3179
3180 /* init */
3181 id_b.proto_id = 0;
3182 id_b.port = 0;
3183 ident = NULL;
3184
3185 switch (iph1->rmconf->idvtype) {
3186 case IDTYPE_FQDN:
3187 id_b.type = IPSECDOI_ID_FQDN;
3188 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3189 break;
3190 case IDTYPE_USERFQDN:
3191 id_b.type = IPSECDOI_ID_USER_FQDN;
3192 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3193 break;
3194 case IDTYPE_KEYID:
c6887256 3195 case IDTYPE_KEYIDUSE:
7ba0088d
A
3196 id_b.type = IPSECDOI_ID_KEY_ID;
3197 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3198 break;
3199#ifdef HAVE_SIGNING_C
3200 case IDTYPE_ASN1DN:
3201 id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3202 if (iph1->rmconf->idv) {
3203 /* XXX it must be encoded to asn1dn. */
3204 ident = vdup(iph1->rmconf->idv);
3205 } else {
3206 if (oakley_getmycert(iph1) < 0) {
3207 plog(LLV_ERROR, LOCATION, NULL,
3208 "failed to get own CERT.\n");
3209 goto err;
3210 }
3211 ident = eay_get_x509asn1subjectname(&iph1->cert->cert);
3212 }
3213 break;
3214#endif
3215 case IDTYPE_ADDRESS:
3216 /*
3217 * if the value of the id type was set by the configuration
3218 * file, then use it. otherwise the value is get from local
3219 * ip address by using ike negotiation.
3220 */
3221 if (iph1->rmconf->idv)
3222 ipid = (struct sockaddr *)iph1->rmconf->idv->v;
3223 /*FALLTHROUGH*/
3224 default:
3225 {
3226 int l;
3227 caddr_t p;
3228
3229 if (ipid == NULL)
3230 ipid = iph1->local;
3231
3232 /* use IP address */
3233 switch (ipid->sa_family) {
3234 case AF_INET:
3235 id_b.type = IPSECDOI_ID_IPV4_ADDR;
3236 l = sizeof(struct in_addr);
3237 p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3238 break;
3239#ifdef INET6
3240 case AF_INET6:
3241 id_b.type = IPSECDOI_ID_IPV6_ADDR;
3242 l = sizeof(struct in6_addr);
3243 p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3244 break;
3245#endif
3246 default:
3247 plog(LLV_ERROR, LOCATION, NULL,
3248 "invalid address family.\n");
3249 goto err;
3250 }
3251 id_b.proto_id = IPPROTO_UDP;
3252 id_b.port = htons(PORT_ISAKMP);
3253 ident = vmalloc(l);
3254 if (!ident) {
3255 plog(LLV_ERROR, LOCATION, NULL,
3256 "failed to get ID buffer.\n");
3257 return 0;
3258 }
3259 memcpy(ident->v, p, ident->l);
3260 }
3261 }
3262 if (!ident) {
3263 plog(LLV_ERROR, LOCATION, NULL,
3264 "failed to get ID buffer.\n");
3265 return 0;
3266 }
3267
3268 ret = vmalloc(sizeof(id_b) + ident->l);
3269 if (ret == NULL) {
3270 plog(LLV_ERROR, LOCATION, NULL,
3271 "failed to get ID buffer.\n");
3272 goto err;
3273 }
3274
3275 memcpy(ret->v, &id_b, sizeof(id_b));
3276 memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3277
3278 iph1->id = ret;
3279
3280 plog(LLV_DEBUG, LOCATION, NULL,
3281 "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3282 if (ident)
3283 vfree(ident);
3284 return 0;
3285
3286err:
3287 if (ident)
3288 vfree(ident);
3289 plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3290 return -1;
3291}
3292
3293static vchar_t *
3294getidval(type, val)
3295 int type;
3296 vchar_t *val;
3297{
3298 vchar_t *new = NULL;
3299
3300 if (val)
3301 new = vdup(val);
3302 else if (lcconf->ident[type])
3303 new = vdup(lcconf->ident[type]);
3304
3305 return new;
3306}
3307
3308/* it's only called by cfparse.y. */
3309int
3310set_identifier(vpp, type, value)
3311 vchar_t **vpp, *value;
3312 int type;
3313{
3314 vchar_t *new = NULL;
3315
3316 /* simply return if value is null. */
3317 if (!value)
3318 return 0;
3319
3320 switch (type) {
3321 case IDTYPE_FQDN:
3322 case IDTYPE_USERFQDN:
c6887256 3323 case IDTYPE_KEYIDUSE:
7ba0088d
A
3324 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3325 new = vmalloc(value->l - 1);
3326 if (new == NULL)
3327 return -1;
3328 memcpy(new->v, value->v, new->l);
3329 break;
3330 case IDTYPE_KEYID:
3331 {
3332 FILE *fp;
3333 char b[512];
3334 int tlen, len;
3335
3336 fp = fopen(value->v, "r");
3337 if (fp == NULL) {
3338 plog(LLV_ERROR, LOCATION, NULL,
3339 "can not open %s\n", value->v);
3340 return -1;
3341 }
3342 tlen = 0;
3343 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3344 new = vrealloc(new, tlen + len);
3345 if (!new) {
3346 fclose(fp);
3347 return -1;
3348 }
3349 memcpy(new->v + tlen, b, len);
3350 tlen += len;
3351 }
3352 break;
3353 }
3354 case IDTYPE_ADDRESS:
3355 {
3356 struct sockaddr *sa;
3357
3358 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3359 if (value->l == 0)
3360 break;
3361
3362 sa = str2saddr(value->v, NULL);
3363 if (sa == NULL) {
3364 plog(LLV_ERROR, LOCATION, NULL,
3365 "invalid ip address %s\n", value->v);
3366 return -1;
3367 }
3368
3369 new = vmalloc(sa->sa_len);
3370 if (new == NULL)
3371 return -1;
3372 memcpy(new->v, sa, new->l);
3373 break;
3374 }
3375 case IDTYPE_ASN1DN:
3376 new = eay_str2asn1dn(value->v, value->l - 1);
3377 if (new == NULL)
3378 return -1;
3379 break;
3380 }
3381
3382 *vpp = new;
3383
3384 return 0;
3385}
3386
3387/*
3388 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3389 * NOT INCLUDING isakmp general header.
3390 * this function is for initiator. responder will get to copy from payload.
3391 * responder ID type is always address type.
3392 * see, RFC2407 4.6.2.1
3393 */
3394int
3395ipsecdoi_setid2(iph2)
3396 struct ph2handle *iph2;
3397{
3398 struct secpolicy *sp;
3399
3400 /* check there is phase 2 handler ? */
3401 sp = getspbyspid(iph2->spid);
3402 if (sp == NULL) {
3403 plog(LLV_ERROR, LOCATION, NULL,
3404 "no policy found for spid:%lu.\n", iph2->spid);
3405 return -1;
3406 }
3407
3408 if (!iph2->sainfo->idv) {
3409 iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
3410 sp->spidx.prefs, sp->spidx.ul_proto);
3411 if (iph2->id == NULL) {
3412 plog(LLV_ERROR, LOCATION, NULL,
3413 "failed to get ID for %s\n",
3414 spidx2str(&sp->spidx));
3415 return -1;
3416 }
3417 plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
3418 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
3419 } else {
3420 struct ipsecdoi_id_b id_b;
3421 vchar_t *ident;
3422
3423 id_b.type = idtype2doi(iph2->sainfo->idvtype);
ac2f15b3
A
3424 if (id_b.type == 255) {
3425 plog(LLV_ERROR, LOCATION, NULL,
3426 "failed to convert ID type to DOI.\n");
3427 return -1;
3428 }
7ba0088d
A
3429 id_b.proto_id = 0;
3430 id_b.port = 0;
3431
3432 ident = getidval(iph2->sainfo->idvtype, iph2->sainfo->idv);
3433 if (!ident) {
3434 plog(LLV_ERROR, LOCATION, NULL,
3435 "failed to get ID value.\n");
3436 return -1;
3437 }
3438 iph2->id = vmalloc(sizeof(id_b) + ident->l);
3439 if (iph2->id == NULL) {
3440 plog(LLV_ERROR, LOCATION, NULL,
3441 "failed to get ID buffer.\n");
3442 vfree(ident);
3443 return -1;
3444 }
3445
3446 memcpy(iph2->id->v, &id_b, sizeof(id_b));
3447 memcpy(iph2->id->v + sizeof(id_b), ident->v, ident->l);
3448 vfree(ident);
3449 }
3450
3451 /* remote side */
3452 iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
3453 sp->spidx.prefd, sp->spidx.ul_proto);
3454 if (iph2->id_p == NULL) {
3455 plog(LLV_ERROR, LOCATION, NULL,
3456 "failed to get ID for %s\n",
3457 spidx2str(&sp->spidx));
3458 vfree(iph2->id);
3459 iph2->id = NULL;
3460 return -1;
3461 }
3462 plog(LLV_DEBUG, LOCATION, NULL,
3463 "use remote ID type %s\n",
3464 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
3465
3466 return 0;
3467}
3468
3469/*
3470 * set address type of ID.
3471 * NOT INCLUDING general header.
3472 */
3473vchar_t *
3474ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
3475 struct sockaddr *saddr;
3476 u_int prefixlen;
3477 u_int ul_proto;
3478{
3479 vchar_t *new;
3480 int type, len1, len2;
3481 caddr_t sa;
3482 u_short port;
3483
3484 /*
3485 * Q. When type is SUBNET, is it allowed to be ::1/128.
3486 * A. Yes. (consensus at bake-off)
3487 */
3488 switch (saddr->sa_family) {
3489 case AF_INET:
3490 len1 = sizeof(struct in_addr);
3491 if (prefixlen == (sizeof(struct in_addr) << 3)) {
3492 type = IPSECDOI_ID_IPV4_ADDR;
3493 len2 = 0;
3494 } else {
3495 type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
3496 len2 = sizeof(struct in_addr);
3497 }
3498 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
3499 port = ((struct sockaddr_in *)(saddr))->sin_port;
3500 break;
3501#ifdef INET6
3502 case AF_INET6:
3503 len1 = sizeof(struct in6_addr);
3504 if (prefixlen == (sizeof(struct in6_addr) << 3)) {
3505 type = IPSECDOI_ID_IPV6_ADDR;
3506 len2 = 0;
3507 } else {
3508 type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
3509 len2 = sizeof(struct in6_addr);
3510 }
3511 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
3512 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
3513 break;
3514#endif
3515 default:
3516 plog(LLV_ERROR, LOCATION, NULL,
3517 "invalid family: %d.\n", saddr->sa_family);
3518 return NULL;
3519 }
3520
3521 /* get ID buffer */
3522 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
3523 if (new == NULL) {
3524 plog(LLV_ERROR, LOCATION, NULL,
3525 "failed to get ID buffer.\n");
3526 return NULL;
3527 }
3528
3529 memset(new->v, 0, new->l);
3530
3531 /* set the part of header. */
3532 ((struct ipsecdoi_id_b *)new->v)->type = type;
3533
3534 /* set ul_proto and port */
3535 /*
3536 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3537 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3538 */
3539 ((struct ipsecdoi_id_b *)new->v)->proto_id =
3540 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
3541 ((struct ipsecdoi_id_b *)new->v)->port =
3542 port == IPSEC_PORT_ANY ? 0 : port;
3543 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
3544
3545 /* set address */
3546
3547 /* set prefix */
3548 if (len2) {
3549 u_char *p = new->v + sizeof(struct ipsecdoi_id_b) + len1;
3550 u_int bits = prefixlen;
3551
3552 while (bits >= 8) {
3553 *p++ = 0xff;
3554 bits -= 8;
3555 }
3556
3557 if (bits > 0)
3558 *p = ~((1 << (8 - bits)) - 1);
3559 }
3560
3561 return new;
3562}
3563
3564/*
3565 * create sockaddr structure from ID payload (buf).
3566 * buffers (saddr, prefixlen, ul_proto) must be allocated.
3567 * see, RFC2407 4.6.2.1
3568 */
3569int
3570ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
3571 vchar_t *buf;
3572 struct sockaddr *saddr;
3573 u_int8_t *prefixlen;
3574 u_int16_t *ul_proto;
3575{
3576 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
3577 u_int plen = 0;
3578
3579 /*
3580 * When a ID payload of subnet type with a IP address of full bit
3581 * masked, it has to be processed as host address.
3582 * e.g. below 2 type are same.
3583 * type = ipv6 subnet, data = 2001::1/128
3584 * type = ipv6 address, data = 2001::1
3585 */
3586 switch (id_b->type) {
3587 case IPSECDOI_ID_IPV4_ADDR:
3588 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3589 saddr->sa_len = sizeof(struct sockaddr_in);
3590 saddr->sa_family = AF_INET;
3591 ((struct sockaddr_in *)saddr)->sin_port =
3592 (id_b->port == 0
3593 ? IPSEC_PORT_ANY
3594 : id_b->port); /* see sockaddr2id() */
3595 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
3596 buf->v + sizeof(*id_b), sizeof(struct in_addr));
3597 break;
3598#ifdef INET6
3599 case IPSECDOI_ID_IPV6_ADDR:
3600 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3601 saddr->sa_len = sizeof(struct sockaddr_in6);
3602 saddr->sa_family = AF_INET6;
3603 ((struct sockaddr_in6 *)saddr)->sin6_port =
3604 (id_b->port == 0
3605 ? IPSEC_PORT_ANY
3606 : id_b->port); /* see sockaddr2id() */
3607 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
3608 buf->v + sizeof(*id_b), sizeof(struct in6_addr));
3609 break;
3610#endif
3611 default:
3612 plog(LLV_ERROR, LOCATION, NULL,
3613 "unsupported ID type %d\n", id_b->type);
3614 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3615 }
3616
3617 /* get prefix length */
3618 switch (id_b->type) {
3619 case IPSECDOI_ID_IPV4_ADDR:
3620 plen = sizeof(struct in_addr) << 3;
3621 break;
3622#ifdef INET6
3623 case IPSECDOI_ID_IPV6_ADDR:
3624 plen = sizeof(struct in6_addr) << 3;
3625 break;
3626#endif
3627 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3628#ifdef INET6
3629 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3630#endif
3631 {
3632 u_char *p;
3633 u_int max;
3634 int alen = sizeof(struct in_addr);
3635
3636 switch (id_b->type) {
3637 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3638 alen = sizeof(struct in_addr);
3639 break;
3640#ifdef INET6
3641 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3642 alen = sizeof(struct in6_addr);
3643 break;
3644#endif
3645 }
3646
3647 /* sanity check */
3648 if (buf->l < alen)
3649 return ISAKMP_INTERNAL_ERROR;
3650
3651 /* get subnet mask length */
3652 plen = 0;
3653 max = alen <<3;
3654
3655 p = buf->v
3656 + sizeof(struct ipsecdoi_id_b)
3657 + alen;
3658
3659 for (; *p == 0xff; p++) {
3660 if (plen >= max)
3661 break;
3662 plen += 8;
3663 }
3664
3665 if (plen < max) {
3666 u_int l = 0;
3667 u_char b = ~(*p);
3668
3669 while (b) {
3670 b >>= 1;
3671 l++;
3672 }
3673
3674 l = 8 - l;
3675 plen += l;
3676 }
3677 }
3678 break;
3679 }
3680
3681 *prefixlen = plen;
3682 *ul_proto = id_b->proto_id == 0
3683 ? IPSEC_ULPROTO_ANY
3684 : id_b->proto_id; /* see sockaddr2id() */
3685
3686 return 0;
3687}
3688
3689/*
3690 * make printable string from ID payload except of general header.
3691 */
3692const char *
3693ipsecdoi_id2str(id)
3694 const vchar_t *id;
3695{
3696 static char buf[256];
3697
3698 /* XXX */
3699 buf[0] = '\0';
3700
3701 return buf;
3702}
3703
3704/*
3705 * set IPsec data attributes into a proposal.
3706 * NOTE: MUST called per a transform.
3707 */
3708int
3709ipsecdoi_t2satrns(t, pp, pr, tr)
3710 struct isakmp_pl_t *t;
3711 struct saprop *pp;
3712 struct saproto *pr;
3713 struct satrns *tr;
3714{
3715 struct isakmp_data *d, *prev;
3716 int flag, type;
3717 int error = -1;
3718 int life_t;
3719 int tlen;
3720
3721 tr->trns_no = t->t_no;
3722 tr->trns_id = t->t_id;
3723
3724 tlen = ntohs(t->h.len) - sizeof(*t);
3725 prev = (struct isakmp_data *)NULL;
3726 d = (struct isakmp_data *)(t + 1);
3727
3728 /* default */
3729 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
3730 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3731 pp->lifebyte = 0;
3732 tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
3733
3734 while (tlen > 0) {
3735
3736 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
3737 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
3738
3739 plog(LLV_DEBUG, LOCATION, NULL,
3740 "type=%s, flag=0x%04x, lorv=%s\n",
3741 s_ipsecdoi_attr(type), flag,
3742 s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
3743
3744 switch (type) {
3745 case IPSECDOI_ATTR_SA_LD_TYPE:
3746 {
3747 int type = ntohs(d->lorv);
3748 switch (type) {
3749 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
3750 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
3751 life_t = type;
3752 break;
3753 default:
3754 plog(LLV_WARNING, LOCATION, NULL,
3755 "invalid life duration type. "
3756 "use default\n");
3757 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
3758 break;
3759 }
3760 break;
3761 }
3762 case IPSECDOI_ATTR_SA_LD:
3763 if (prev == NULL
3764 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
3765 IPSECDOI_ATTR_SA_LD_TYPE) {
3766 plog(LLV_ERROR, LOCATION, NULL,
3767 "life duration must follow ltype\n");
3768 break;
3769 }
3770
3771 {
3772 u_int32_t t;
3773 vchar_t *ld_buf = NULL;
3774
3775 if (flag) {
3776 /* i.e. ISAKMP_GEN_TV */
3777 ld_buf = vmalloc(sizeof(d->lorv));
3778 if (ld_buf == NULL) {
3779 plog(LLV_ERROR, LOCATION, NULL,
3780 "failed to get LD buffer.\n");
3781 goto end;
3782 }
3783 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
3784 } else {
3785 int len = ntohs(d->lorv);
3786 /* i.e. ISAKMP_GEN_TLV */
3787 ld_buf = vmalloc(len);
3788 if (ld_buf == NULL) {
3789 plog(LLV_ERROR, LOCATION, NULL,
3790 "failed to get LD buffer.\n");
3791 goto end;
3792 }
3793 memcpy(ld_buf->v, d + 1, len);
3794 }
3795 switch (life_t) {
3796 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
3797 t = ipsecdoi_set_ld(ld_buf);
3798 vfree(ld_buf);
3799 if (t == 0) {
3800 plog(LLV_ERROR, LOCATION, NULL,
3801 "invalid life duration.\n");
3802 goto end;
3803 }
3804 /* lifetime must be equal in a proposal. */
3805 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
3806 pp->lifetime = t;
3807 else if (pp->lifetime != t) {
3808 plog(LLV_ERROR, LOCATION, NULL,
3809 "lifetime mismatched "
3810 "in a proposal, "
3811 "prev:%ld curr:%ld.\n",
3812 pp->lifetime, t);
3813 goto end;
3814 }
3815 break;
3816 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
3817 t = ipsecdoi_set_ld(ld_buf);
3818 vfree(ld_buf);
3819 if (t == 0) {
3820 plog(LLV_ERROR, LOCATION, NULL,
3821 "invalid life duration.\n");
3822 goto end;
3823 }
3824 /* lifebyte must be equal in a proposal. */
3825 if (pp->lifebyte == 0)
3826 pp->lifebyte = t;
3827 else if (pp->lifebyte != t) {
3828 plog(LLV_ERROR, LOCATION, NULL,
3829 "lifebyte mismatched "
3830 "in a proposal, "
3831 "prev:%ld curr:%ld.\n",
3832 pp->lifebyte, t);
3833 goto end;
3834 }
3835 break;
3836 default:
3837 vfree(ld_buf);
3838 plog(LLV_ERROR, LOCATION, NULL,
3839 "invalid life type: %d\n", life_t);
3840 goto end;
3841 }
3842 }
3843 break;
3844
3845 case IPSECDOI_ATTR_GRP_DESC:
3846 /*
3847 * RFC2407: 4.5 IPSEC Security Association Attributes
3848 * Specifies the Oakley Group to be used in a PFS QM
3849 * negotiation. For a list of supported values, see
3850 * Appendix A of [IKE].
3851 */
3852 if (pp->pfs_group == 0)
3853 pp->pfs_group = (u_int16_t)ntohs(d->lorv);
3854 else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
3855 plog(LLV_ERROR, LOCATION, NULL,
3856 "pfs_group mismatched "
3857 "in a proposal.\n");
3858 goto end;
3859 }
3860 break;
3861
3862 case IPSECDOI_ATTR_ENC_MODE:
3863 if (pr->encmode
3864 && pr->encmode != (u_int16_t)ntohs(d->lorv)) {
3865 plog(LLV_ERROR, LOCATION, NULL,
3866 "multiple encmode exist "
3867 "in a transform.\n");
3868 goto end;
3869 }
3870 pr->encmode = (u_int16_t)ntohs(d->lorv);
3871 break;
3872
3873 case IPSECDOI_ATTR_AUTH:
3874 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
3875 plog(LLV_ERROR, LOCATION, NULL,
3876 "multiple authtype exist "
3877 "in a transform.\n");
3878 goto end;
3879 }
3880 tr->authtype = (u_int16_t)ntohs(d->lorv);
3881 break;
3882
3883 case IPSECDOI_ATTR_KEY_LENGTH:
3884 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
3885 plog(LLV_ERROR, LOCATION, NULL,
3886 "key length defined but not ESP");
3887 goto end;
3888 }
3889 tr->encklen = ntohs(d->lorv);
3890 break;
3891
3892 case IPSECDOI_ATTR_KEY_ROUNDS:
3893 case IPSECDOI_ATTR_COMP_DICT_SIZE:
3894 case IPSECDOI_ATTR_COMP_PRIVALG:
3895 default:
3896 break;
3897 }
3898
3899 prev = d;
3900 if (flag) {
3901 tlen -= sizeof(*d);
3902 d = (struct isakmp_data *)((char *)d + sizeof(*d));
3903 } else {
3904 tlen -= (sizeof(*d) + ntohs(d->lorv));
3905 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
3906 }
3907 }
3908
3909 error = 0;
3910end:
3911 return error;
3912}
3913
3914int
3915ipsecdoi_authalg2trnsid(alg)
3916 int alg;
3917{
3918 switch (alg) {
3919 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
3920 return IPSECDOI_AH_MD5;
3921 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
3922 return IPSECDOI_AH_SHA;
3923 case IPSECDOI_ATTR_AUTH_DES_MAC:
3924 return IPSECDOI_AH_DES;
3925 case IPSECDOI_ATTR_AUTH_KPDK:
3926 return IPSECDOI_AH_MD5; /* XXX */
3927 default:
3928 plog(LLV_ERROR, LOCATION, NULL,
3929 "invalid authentication algorithm:%d\n", alg);
3930 }
3931 return -1;
3932}
3933
3934#ifdef HAVE_GSSAPI
3935struct isakmpsa *
3936fixup_initiator_sa(match, received)
3937 struct isakmpsa *match, *received;
3938{
3939 struct isakmpsa *newsa;
3940
3941 if (received->gssid == NULL)
3942 return match;
3943
3944 newsa = newisakmpsa();
3945 memcpy(newsa, match, sizeof *newsa);
3946
3947 if (match->dhgrp != NULL) {
3948 newsa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
3949 memcpy(newsa->dhgrp, match->dhgrp, sizeof (struct dhgroup));
3950 }
3951 newsa->next = NULL;
3952 newsa->rmconf = NULL;
3953
3954 newsa->gssid = vdup(received->gssid);
3955
3956 return newsa;
3957}
3958#endif
3959
3960static int rm_idtype2doi[] = {
3961 IPSECDOI_ID_FQDN,
3962 IPSECDOI_ID_USER_FQDN,
3963 IPSECDOI_ID_KEY_ID,
ac2f15b3 3964 255, /* it's type of "address"
7ba0088d
A
3965 * it expands into 4 types by another function. */
3966 IPSECDOI_ID_DER_ASN1_DN,
3967};
3968
3969/*
3970 * convert idtype to DOI value.
ac2f15b3 3971 * OUT 255 : NG
7ba0088d
A
3972 * other: converted.
3973 */
3974int
3975idtype2doi(idtype)
3976 int idtype;
3977{
3978 if (ARRAYLEN(rm_idtype2doi) > idtype)
3979 return rm_idtype2doi[idtype];
ac2f15b3 3980 return 255;
7ba0088d
A
3981}
3982
3983int
3984doi2idtype(doi)
3985 int doi;
3986{
3987 switch(doi) {
3988 case IPSECDOI_ID_FQDN:
3989 return(IDTYPE_FQDN);
3990 case IPSECDOI_ID_USER_FQDN:
3991 return(IDTYPE_USERFQDN);
3992 case IPSECDOI_ID_KEY_ID:
3993 return(IDTYPE_KEYID);
3994 case IPSECDOI_ID_DER_ASN1_DN:
3995 return(IDTYPE_ASN1DN);
3996 case IPSECDOI_ID_IPV4_ADDR:
3997 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3998 case IPSECDOI_ID_IPV6_ADDR:
3999 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4000 return(IDTYPE_ADDRESS);
4001 default:
4002 plog(LLV_WARNING, LOCATION, NULL,
4003 "Inproper idtype:%d in this function.\n",
4004 s_ipsecdoi_ident(doi));
4005 return(IDTYPE_ADDRESS); /* XXX */
4006 }
4007 /*NOTREACHED*/
4008}
4009