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