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