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