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