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