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