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
87static 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
100int verbose_proposal_check = 1;
101
102static vchar_t *get_ph1approval __P((struct ph1handle *, struct prop_pair **));
103static struct isakmpsa *get_ph1approvalx __P((struct prop_pair *,
104	struct isakmpsa *, struct isakmpsa *, int));
105static void print_ph1mismatched __P((struct prop_pair *, struct isakmpsa *));
106static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *));
107static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
108static struct prop_pair *get_ph2approval __P((struct ph2handle *,
109	struct prop_pair **));
110static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
111	struct prop_pair *));
112static void free_proppair0 __P((struct prop_pair *));
113
114static int get_transform
115	__P((struct isakmp_pl_p *, struct prop_pair **, int *));
116static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
117
118static int check_doi __P((u_int32_t));
119static int check_situation __P((u_int32_t));
120
121static int check_prot_main __P((int));
122static int check_prot_quick __P((int));
123static int (*check_protocol[]) __P((int)) = {
124	check_prot_main,	/* IPSECDOI_TYPE_PH1 */
125	check_prot_quick,	/* IPSECDOI_TYPE_PH2 */
126};
127
128static int check_spi_size __P((int, int));
129
130static int check_trns_isakmp __P((int));
131static int check_trns_ah __P((int));
132static int check_trns_esp __P((int));
133static int check_trns_ipcomp __P((int));
134static 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
142static int check_attr_isakmp __P((struct isakmp_pl_t *));
143static int check_attr_ah __P((struct isakmp_pl_t *));
144static int check_attr_esp __P((struct isakmp_pl_t *));
145static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
146static int check_attr_ipcomp __P((struct isakmp_pl_t *));
147static 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
155static int setph1prop __P((struct isakmpsa *, caddr_t));
156static int setph1trns __P((struct isakmpsa *, caddr_t));
157static int setph1attr __P((struct isakmpsa *, caddr_t));
158static vchar_t *setph2proposal0 __P((const struct ph2handle *,
159	const struct saprop *, const struct saproto *));
160
161static vchar_t *getidval __P((int, vchar_t *));
162
163#ifdef HAVE_GSSAPI
164static 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 */
178int
179ipsecdoi_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 */
208static vchar_t *
209get_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
263found:
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
284saok:
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 */
333static struct isakmpsa *
334get_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
441found:
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 */
478static void
479print_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 */
548static int
549t2isakmpsa(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;
833out:
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;
875err:
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 */
888int
889ipsecdoi_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 */
923int
924ipsecdoi_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
1007end:
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 */
1029static int
1030cmp_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 */
1113static struct prop_pair *
1114get_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 */
1150static struct prop_pair *
1151get_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 */
1181err:
1182	flushsaprop(pr0);
1183	return NULL;
1184
1185found:
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
1249void
1250free_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
1262static void
1263free_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 */
1285struct prop_pair **
1286get_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;
1447bad:
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 */
1459static int
1460get_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 */
1566vchar_t *
1567get_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 */
1631int
1632ipsecdoi_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;
1682end:
1683	free_proppair(pair);
1684	return error;
1685}
1686
1687/*
1688 * make a new SA payload from prop_pair.
1689 */
1690vchar_t *
1691get_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;
1785out:
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 */
1805static u_int32_t
1806ipsecdoi_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 */
1835static int
1836check_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 */
1853static int
1854check_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 */
1878static int
1879check_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 */
1897static int
1898check_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
1917static int
1918check_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 */
1959static int
1960check_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 */
1978static int
1979check_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 */
2004static int
2005check_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 */
2038static int
2039check_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 */
2058static int
2059check_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 */
2258static int
2259check_attr_ah(trns)
2260	struct isakmp_pl_t *trns;
2261{
2262	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2263}
2264
2265static int
2266check_attr_esp(trns)
2267	struct isakmp_pl_t *trns;
2268{
2269	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2270}
2271
2272static int
2273check_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) {
2340ahmismatch:
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
2494static int
2495check_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 */
2644vchar_t *
2645ipsecdoi_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
2673static int
2674setph1prop(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
2724static int
2725setph1trns(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
2754static int
2755setph1attr(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
2940static vchar_t *
2941setph2proposal0(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 */
3161int
3162ipsecdoi_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 */
3236int
3237ipsecdoi_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
3252int
3253ipsecdoi_get_defaultlifetime()
3254{
3255	return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3256}
3257
3258int
3259ipsecdoi_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
3306int
3307ipproto2doi(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
3321int
3322doi2ipproto(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
3345int
3346ipsecdoi_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
3368int
3369ipsecdoi_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
3402int
3403ipsecdoi_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
3549cmpid_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
3578cmpid_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 */
3599int
3600ipsecdoi_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;
3740matched: /* 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 */
3753int
3754ipsecdoi_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
3865err:
3866	if (ident)
3867		vfree(ident);
3868	plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3869	return -1;
3870}
3871
3872static vchar_t *
3873getidval(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. */
3888int
3889set_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
3896int
3897set_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 */
4055int
4056ipsecdoi_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 */
4101vchar_t *
4102ipsecdoi_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
4193vchar_t *
4194ipsecdoi_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 */
4263int
4264ipsecdoi_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 */
4390char *
4391ipsecdoi_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 */
4612int
4613ipsecdoi_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;
4822end:
4823	return error;
4824}
4825
4826int
4827ipsecdoi_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
4853struct isakmpsa *
4854fixup_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
4864static 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 */
4879int
4880idtype2doi(idtype)
4881	int idtype;
4882{
4883	if (ARRAYLEN(rm_idtype2doi) > idtype)
4884		return rm_idtype2doi[idtype];
4885	return 255;
4886}
4887
4888int
4889doi2idtype(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
4916static int
4917switch_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