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	memset(pair, 0, sizeof(pair));
1322
1323	bp = (caddr_t)(sab + 1);
1324	tlen = sa->l - sizeof(*sab);
1325
1326    {
1327	struct isakmp_pl_p *prop;
1328	int proplen;
1329	vchar_t *pbuf = NULL;
1330	struct isakmp_parse_t *pa;
1331
1332	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1333	if (pbuf == NULL)
1334		goto bad;
1335
1336	for (pa = (struct isakmp_parse_t *)pbuf->v;
1337	     pa->type != ISAKMP_NPTYPE_NONE;
1338	     pa++) {
1339		/* check the value of next payload */
1340		if (pa->type != ISAKMP_NPTYPE_P) {
1341			plog(LLV_ERROR, LOCATION, NULL,
1342				"Invalid payload type=%u\n", pa->type);
1343			vfree(pbuf);
1344			goto bad;
1345		}
1346
1347		prop = (struct isakmp_pl_p *)pa->ptr;
1348		proplen = pa->len;
1349
1350		plog(LLV_DEBUG, LOCATION, NULL,
1351			"proposal #%u len=%d\n", prop->p_no, proplen);
1352
1353		if (proplen == 0) {
1354			plog(LLV_ERROR, LOCATION, NULL,
1355				"invalid proposal with length %d\n", proplen);
1356			vfree(pbuf);
1357			goto bad;
1358		}
1359
1360		/* check Protocol ID */
1361		if (!check_protocol[mode]) {
1362			plog(LLV_ERROR, LOCATION, NULL,
1363				"unsupported mode %d\n", mode);
1364			continue;
1365		}
1366
1367		if (check_protocol[mode](prop->proto_id) < 0)
1368			continue;
1369
1370		/* check SPI length when IKE. */
1371		if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1372			continue;
1373
1374		/* get transform */
1375		if (get_transform(prop, pair, &num_p) < 0) {
1376			vfree(pbuf);
1377			goto bad;
1378		}
1379	}
1380	vfree(pbuf);
1381	pbuf = NULL;
1382    }
1383
1384    {
1385	int notrans, nprop;
1386	struct prop_pair *p, *q;
1387
1388	/* check for proposals with no transforms */
1389	for (i = 0; i < MAXPROPPAIRLEN; i++) {
1390		if (!pair[i])
1391			continue;
1392
1393		plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
1394		print_proppair(LLV_DEBUG, pair[i]);
1395
1396		notrans = nprop = 0;
1397		for (p = pair[i]; p; p = p->next) {
1398			if (p->trns == NULL) {
1399				notrans++;
1400				break;
1401			}
1402			for (q = p; q; q = q->tnext)
1403				nprop++;
1404		}
1405
1406#if 0
1407		/*
1408		 * XXX at this moment, we cannot accept proposal group
1409		 * with multiple proposals.  this should be fixed.
1410		 */
1411		if (pair[i]->next) {
1412			plog(LLV_WARNING, LOCATION, NULL,
1413				"proposal #%u ignored "
1414				"(multiple proposal not supported)\n",
1415				pair[i]->prop->p_no);
1416			notrans++;
1417		}
1418#endif
1419
1420		if (notrans) {
1421			for (p = pair[i]; p; p = q) {
1422				q = p->next;
1423				racoon_free(p);
1424			}
1425			pair[i] = NULL;
1426			num_p--;
1427		} else {
1428			plog(LLV_DEBUG, LOCATION, NULL,
1429				"proposal #%u: %d transform\n",
1430				pair[i]->prop->p_no, nprop);
1431		}
1432	}
1433    }
1434
1435	/* bark if no proposal is found. */
1436	if (num_p <= 0) {
1437		plog(LLV_ERROR, LOCATION, NULL,
1438			"no Proposal found.\n");
1439		goto bad;
1440	}
1441
1442	return pair;
1443bad:
1444	if (pair != NULL)
1445		racoon_free(pair);
1446	return NULL;
1447}
1448
1449/*
1450 * check transform payload.
1451 * OUT:
1452 *	positive: return the pointer to the payload of valid transform.
1453 *	0	: No valid transform found.
1454 */
1455static int
1456get_transform(prop, pair, num_p)
1457	struct isakmp_pl_p *prop;
1458	struct prop_pair **pair;
1459	int *num_p;
1460{
1461	int tlen; /* total length of all transform in a proposal */
1462	caddr_t bp;
1463	struct isakmp_pl_t *trns;
1464	int trnslen;
1465	vchar_t *pbuf = NULL;
1466	struct isakmp_parse_t *pa;
1467	struct prop_pair *p = NULL, *q;
1468	int num_t;
1469
1470	bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1471	tlen = ntohs(prop->h.len)
1472		- (sizeof(struct isakmp_pl_p) + prop->spi_size);
1473	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1474	if (pbuf == NULL)
1475		return -1;
1476
1477	/* check and get transform for use */
1478	num_t = 0;
1479	for (pa = (struct isakmp_parse_t *)pbuf->v;
1480	     pa->type != ISAKMP_NPTYPE_NONE;
1481	     pa++) {
1482
1483		num_t++;
1484
1485		/* check the value of next payload */
1486		if (pa->type != ISAKMP_NPTYPE_T) {
1487			plog(LLV_ERROR, LOCATION, NULL,
1488				"Invalid payload type=%u\n", pa->type);
1489			break;
1490		}
1491
1492		trns = (struct isakmp_pl_t *)pa->ptr;
1493		trnslen = pa->len;
1494
1495		plog(LLV_DEBUG, LOCATION, NULL,
1496			"transform #%u len=%u\n", trns->t_no, trnslen);
1497
1498		/* check transform ID */
1499		if (prop->proto_id >= ARRAYLEN(check_transform)) {
1500			plog(LLV_WARNING, LOCATION, NULL,
1501				"unsupported proto_id %u\n",
1502				prop->proto_id);
1503			continue;
1504		}
1505		if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1506			plog(LLV_WARNING, LOCATION, NULL,
1507				"unsupported proto_id %u\n",
1508				prop->proto_id);
1509			continue;
1510		}
1511
1512		if (!check_transform[prop->proto_id]
1513		 || !check_attributes[prop->proto_id]) {
1514			plog(LLV_WARNING, LOCATION, NULL,
1515				"unsupported proto_id %u\n",
1516				prop->proto_id);
1517			continue;
1518		}
1519		if (check_transform[prop->proto_id](trns->t_id) < 0)
1520			continue;
1521
1522		/* check data attributes */
1523		if (check_attributes[prop->proto_id](trns) != 0)
1524			continue;
1525
1526		p = racoon_calloc(1, sizeof(*p));
1527		if (p == NULL) {
1528			plog(LLV_ERROR, LOCATION, NULL,
1529				"failed to get buffer.\n");
1530			vfree(pbuf);
1531			return -1;
1532		}
1533		p->prop = prop;
1534		p->trns = trns;
1535
1536		/* need to preserve the order */
1537		for (q = pair[prop->p_no]; q && q->next; q = q->next)
1538			;
1539		if (q && q->prop == p->prop) {
1540			for (/*nothing*/; q && q->tnext; q = q->tnext)
1541				;
1542			q->tnext = p;
1543		} else {
1544			if (q)
1545				q->next = p;
1546			else {
1547				pair[prop->p_no] = p;
1548				(*num_p)++;
1549			}
1550		}
1551	}
1552
1553	vfree(pbuf);
1554
1555	return 0;
1556}
1557
1558/*
1559 * make a new SA payload from prop_pair.
1560 * NOTE: this function make spi value clear.
1561 */
1562vchar_t *
1563get_sabyproppair(pair, iph1)
1564	struct prop_pair *pair;
1565	struct ph1handle *iph1;
1566{
1567	vchar_t *newsa;
1568	int newtlen;
1569	u_int8_t *np_p = NULL;
1570	struct prop_pair *p;
1571	int prophlen, trnslen;
1572	caddr_t bp;
1573
1574	newtlen = sizeof(struct ipsecdoi_sa_b);
1575	for (p = pair; p; p = p->next) {
1576		newtlen += sizeof(struct isakmp_pl_p);
1577		newtlen += p->prop->spi_size;
1578		newtlen += ntohs(p->trns->h.len);
1579	}
1580
1581	newsa = vmalloc(newtlen);
1582	if (newsa == NULL) {
1583		plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1584		return NULL;
1585	}
1586	bp = newsa->v;
1587
1588	((struct isakmp_gen *)bp)->len = htons(newtlen);
1589
1590	/* update some of values in SA header */
1591	((struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
1592	((struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
1593	bp += sizeof(struct ipsecdoi_sa_b);
1594
1595	/* create proposal payloads */
1596	for (p = pair; p; p = p->next) {
1597		prophlen = sizeof(struct isakmp_pl_p)
1598				+ p->prop->spi_size;
1599		trnslen = ntohs(p->trns->h.len);
1600
1601		if (np_p)
1602			*np_p = ISAKMP_NPTYPE_P;
1603
1604		/* create proposal */
1605
1606		memcpy(bp, p->prop, prophlen);
1607		((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1608		((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1609		((struct isakmp_pl_p *)bp)->num_t = 1;
1610		np_p = &((struct isakmp_pl_p *)bp)->h.np;
1611		memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1612		bp += prophlen;
1613
1614		/* create transform */
1615		memcpy(bp, p->trns, trnslen);
1616		((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1617		((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1618		bp += trnslen;
1619	}
1620
1621	return newsa;
1622}
1623
1624/*
1625 * update responder's spi
1626 */
1627int
1628ipsecdoi_updatespi(iph2)
1629	struct ph2handle *iph2;
1630{
1631	struct prop_pair **pair, *p;
1632	struct saprop *pp;
1633	struct saproto *pr;
1634	int i;
1635	int error = -1;
1636	u_int8_t *spi;
1637
1638	pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1639	if (pair == NULL)
1640		return -1;
1641	for (i = 0; i < MAXPROPPAIRLEN; i++) {
1642		if (pair[i])
1643			break;
1644	}
1645	if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1646		/* multiple transform must be filtered by selectph2proposal.*/
1647		goto end;
1648	}
1649
1650	pp = iph2->approval;
1651
1652	/* create proposal payloads */
1653	for (p = pair[i]; p; p = p->next) {
1654		/*
1655		 * find a proposal/transform with matching proto_id/t_id.
1656		 * we have analyzed validity already, in cmpsaprop_alloc().
1657		 */
1658		for (pr = pp->head; pr; pr = pr->next) {
1659			if (p->prop->proto_id == pr->proto_id &&
1660			    p->trns->t_id == pr->head->trns_id) {
1661				break;
1662			}
1663		}
1664		if (!pr)
1665			goto end;
1666
1667		/*
1668		 * XXX SPI bits are left-filled, for use with IPComp.
1669		 * we should be switching to variable-length spi field...
1670		 */
1671		spi = (u_int8_t *)&pr->spi;
1672		spi += sizeof(pr->spi);
1673		spi -= pr->spisize;
1674		memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1675	}
1676
1677	error = 0;
1678end:
1679	free_proppair(pair);
1680	return error;
1681}
1682
1683/*
1684 * make a new SA payload from prop_pair.
1685 */
1686vchar_t *
1687get_sabysaprop(pp0, sa0)
1688	struct saprop *pp0;
1689	vchar_t *sa0;
1690{
1691	struct prop_pair **pair = NULL;
1692	vchar_t *newsa = NULL;
1693	int newtlen;
1694	u_int8_t *np_p = NULL;
1695	struct prop_pair *p = NULL;
1696	struct saprop *pp;
1697	struct saproto *pr;
1698	struct satrns *tr;
1699	int prophlen, trnslen;
1700	caddr_t bp;
1701	int error = -1;
1702
1703	/* get proposal pair */
1704	pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1705	if (pair == NULL)
1706		goto out;
1707
1708	newtlen = sizeof(struct ipsecdoi_sa_b);
1709	for (pp = pp0; pp; pp = pp->next) {
1710
1711		if (pair[pp->prop_no] == NULL)
1712			goto out;
1713
1714		for (pr = pp->head; pr; pr = pr->next) {
1715			newtlen += (sizeof(struct isakmp_pl_p)
1716				+ pr->spisize);
1717
1718			for (tr = pr->head; tr; tr = tr->next) {
1719				for (p = pair[pp->prop_no]; p; p = p->tnext) {
1720					if (tr->trns_no == p->trns->t_no)
1721						break;
1722				}
1723				if (p == NULL)
1724					goto out;
1725
1726				newtlen += ntohs(p->trns->h.len);
1727			}
1728		}
1729	}
1730
1731	newsa = vmalloc(newtlen);
1732	if (newsa == NULL) {
1733		plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1734		goto out;
1735	}
1736	bp = newsa->v;
1737
1738	/* some of values of SA must be updated in the out of this function */
1739	((struct isakmp_gen *)bp)->len = htons(newtlen);
1740	bp += sizeof(struct ipsecdoi_sa_b);
1741
1742	/* create proposal payloads */
1743	for (pp = pp0; pp; pp = pp->next) {
1744
1745		for (pr = pp->head; pr; pr = pr->next) {
1746			prophlen = sizeof(struct isakmp_pl_p)
1747					+ p->prop->spi_size;
1748
1749			for (tr = pr->head; tr; tr = tr->next) {
1750				for (p = pair[pp->prop_no]; p; p = p->tnext) {
1751					if (tr->trns_no == p->trns->t_no)
1752						break;
1753				}
1754				if (p == NULL)
1755					goto out;
1756
1757				trnslen = ntohs(p->trns->h.len);
1758
1759				if (np_p)
1760					*np_p = ISAKMP_NPTYPE_P;
1761
1762				/* create proposal */
1763
1764				memcpy(bp, p->prop, prophlen);
1765				((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1766				((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1767				((struct isakmp_pl_p *)bp)->num_t = 1;
1768				np_p = &((struct isakmp_pl_p *)bp)->h.np;
1769				bp += prophlen;
1770
1771				/* create transform */
1772				memcpy(bp, p->trns, trnslen);
1773				((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1774				((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1775				bp += trnslen;
1776			}
1777		}
1778	}
1779
1780	error = 0;
1781out:
1782	if (pair != NULL)
1783		racoon_free(pair);
1784
1785	if (error != 0) {
1786		if (newsa != NULL) {
1787			vfree(newsa);
1788			newsa = NULL;
1789		}
1790	}
1791
1792	return newsa;
1793}
1794
1795/*
1796 * If some error happens then return 0.  Although 0 means that lifetime is zero,
1797 * such a value should not be accepted.
1798 * Also 0 of lifebyte should not be included in a packet although 0 means not
1799 * to care of it.
1800 */
1801static u_int32_t
1802ipsecdoi_set_ld(buf)
1803	vchar_t *buf;
1804{
1805	u_int32_t ld;
1806
1807	if (buf == 0)
1808		return 0;
1809
1810	switch (buf->l) {
1811	case 2:
1812		ld = ntohs(*(u_int16_t *)buf->v);
1813		break;
1814	case 4:
1815		ld = ntohl(*(u_int32_t *)buf->v);
1816		break;
1817	default:
1818		plog(LLV_ERROR, LOCATION, NULL,
1819			"length %zu of life duration "
1820			"isn't supported.\n", buf->l);
1821		return 0;
1822	}
1823
1824	return ld;
1825}
1826
1827/*%%%*/
1828/*
1829 * check DOI
1830 */
1831static int
1832check_doi(doi)
1833	u_int32_t doi;
1834{
1835	switch (doi) {
1836	case IPSEC_DOI:
1837		return 0;
1838	default:
1839		plog(LLV_ERROR, LOCATION, NULL,
1840			"invalid value of DOI 0x%08x.\n", doi);
1841		return -1;
1842	}
1843	/* NOT REACHED */
1844}
1845
1846/*
1847 * check situation
1848 */
1849static int
1850check_situation(sit)
1851	u_int32_t sit;
1852{
1853	switch (sit) {
1854	case IPSECDOI_SIT_IDENTITY_ONLY:
1855		return 0;
1856
1857	case IPSECDOI_SIT_SECRECY:
1858	case IPSECDOI_SIT_INTEGRITY:
1859		plog(LLV_ERROR, LOCATION, NULL,
1860			"situation 0x%08x unsupported yet.\n", sit);
1861		return -1;
1862
1863	default:
1864		plog(LLV_ERROR, LOCATION, NULL,
1865			"invalid situation 0x%08x.\n", sit);
1866		return -1;
1867	}
1868	/* NOT REACHED */
1869}
1870
1871/*
1872 * check protocol id in main mode
1873 */
1874static int
1875check_prot_main(proto_id)
1876	int proto_id;
1877{
1878	switch (proto_id) {
1879	case IPSECDOI_PROTO_ISAKMP:
1880		return 0;
1881
1882	default:
1883		plog(LLV_ERROR, LOCATION, NULL,
1884			"Illegal protocol id=%u.\n", proto_id);
1885		return -1;
1886	}
1887	/* NOT REACHED */
1888}
1889
1890/*
1891 * check protocol id in quick mode
1892 */
1893static int
1894check_prot_quick(proto_id)
1895	int proto_id;
1896{
1897	switch (proto_id) {
1898	case IPSECDOI_PROTO_IPSEC_AH:
1899	case IPSECDOI_PROTO_IPSEC_ESP:
1900		return 0;
1901
1902	case IPSECDOI_PROTO_IPCOMP:
1903		return 0;
1904
1905	default:
1906		plog(LLV_ERROR, LOCATION, NULL,
1907			"invalid protocol id %d.\n", proto_id);
1908		return -1;
1909	}
1910	/* NOT REACHED */
1911}
1912
1913static int
1914check_spi_size(proto_id, size)
1915	int proto_id, size;
1916{
1917	switch (proto_id) {
1918	case IPSECDOI_PROTO_ISAKMP:
1919		if (size != 0) {
1920			/* WARNING */
1921			plog(LLV_WARNING, LOCATION, NULL,
1922				"SPI size isn't zero, but IKE proposal.\n");
1923		}
1924		return 0;
1925
1926	case IPSECDOI_PROTO_IPSEC_AH:
1927	case IPSECDOI_PROTO_IPSEC_ESP:
1928		if (size != 4) {
1929			plog(LLV_ERROR, LOCATION, NULL,
1930				"invalid SPI size=%d for IPSEC proposal.\n",
1931				size);
1932			return -1;
1933		}
1934		return 0;
1935
1936	case IPSECDOI_PROTO_IPCOMP:
1937		if (size != 2 && size != 4) {
1938			plog(LLV_ERROR, LOCATION, NULL,
1939				"invalid SPI size=%d for IPCOMP proposal.\n",
1940				size);
1941			return -1;
1942		}
1943		return 0;
1944
1945	default:
1946		/* ??? */
1947		return -1;
1948	}
1949	/* NOT REACHED */
1950}
1951
1952/*
1953 * check transform ID in ISAKMP.
1954 */
1955static int
1956check_trns_isakmp(t_id)
1957	int t_id;
1958{
1959	switch (t_id) {
1960	case IPSECDOI_KEY_IKE:
1961		return 0;
1962	default:
1963		plog(LLV_ERROR, LOCATION, NULL,
1964			"invalid transform-id=%u in proto_id=%u.\n",
1965			t_id, IPSECDOI_KEY_IKE);
1966		return -1;
1967	}
1968	/* NOT REACHED */
1969}
1970
1971/*
1972 * check transform ID in AH.
1973 */
1974static int
1975check_trns_ah(t_id)
1976	int t_id;
1977{
1978	switch (t_id) {
1979	case IPSECDOI_AH_MD5:
1980	case IPSECDOI_AH_SHA:
1981	case IPSECDOI_AH_SHA256:
1982	case IPSECDOI_AH_SHA384:
1983	case IPSECDOI_AH_SHA512:
1984		return 0;
1985	case IPSECDOI_AH_DES:
1986		plog(LLV_ERROR, LOCATION, NULL,
1987			"not support transform-id=%u in AH.\n", t_id);
1988		return -1;
1989	default:
1990		plog(LLV_ERROR, LOCATION, NULL,
1991			"invalid transform-id=%u in AH.\n", t_id);
1992		return -1;
1993	}
1994	/* NOT REACHED */
1995}
1996
1997/*
1998 * check transform ID in ESP.
1999 */
2000static int
2001check_trns_esp(t_id)
2002	int t_id;
2003{
2004	switch (t_id) {
2005	case IPSECDOI_ESP_DES:
2006	case IPSECDOI_ESP_3DES:
2007	case IPSECDOI_ESP_NULL:
2008	case IPSECDOI_ESP_RC5:
2009	case IPSECDOI_ESP_CAST:
2010	case IPSECDOI_ESP_BLOWFISH:
2011	case IPSECDOI_ESP_AES:
2012	case IPSECDOI_ESP_TWOFISH:
2013	case IPSECDOI_ESP_CAMELLIA:
2014		return 0;
2015	case IPSECDOI_ESP_DES_IV32:
2016	case IPSECDOI_ESP_DES_IV64:
2017	case IPSECDOI_ESP_IDEA:
2018	case IPSECDOI_ESP_3IDEA:
2019	case IPSECDOI_ESP_RC4:
2020		plog(LLV_ERROR, LOCATION, NULL,
2021			"not support transform-id=%u in ESP.\n", t_id);
2022		return -1;
2023	default:
2024		plog(LLV_ERROR, LOCATION, NULL,
2025			"invalid transform-id=%u in ESP.\n", t_id);
2026		return -1;
2027	}
2028	/* NOT REACHED */
2029}
2030
2031/*
2032 * check transform ID in IPCOMP.
2033 */
2034static int
2035check_trns_ipcomp(t_id)
2036	int t_id;
2037{
2038	switch (t_id) {
2039	case IPSECDOI_IPCOMP_OUI:
2040	case IPSECDOI_IPCOMP_DEFLATE:
2041	case IPSECDOI_IPCOMP_LZS:
2042		return 0;
2043	default:
2044		plog(LLV_ERROR, LOCATION, NULL,
2045			"invalid transform-id=%u in IPCOMP.\n", t_id);
2046		return -1;
2047	}
2048	/* NOT REACHED */
2049}
2050
2051/*
2052 * check data attributes in IKE.
2053 */
2054static int
2055check_attr_isakmp(trns)
2056	struct isakmp_pl_t *trns;
2057{
2058	struct isakmp_data *d;
2059	int tlen;
2060	int flag, type;
2061	u_int16_t lorv;
2062
2063	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2064	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2065
2066	while (tlen > 0) {
2067		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2068		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2069		lorv = ntohs(d->lorv);
2070
2071		plog(LLV_DEBUG, LOCATION, NULL,
2072			"type=%s, flag=0x%04x, lorv=%s\n",
2073			s_oakley_attr(type), flag,
2074			s_oakley_attr_v(type, lorv));
2075
2076		/*
2077		 * some of the attributes must be encoded in TV.
2078		 * see RFC2409 Appendix A "Attribute Classes".
2079		 */
2080		switch (type) {
2081		case OAKLEY_ATTR_ENC_ALG:
2082		case OAKLEY_ATTR_HASH_ALG:
2083		case OAKLEY_ATTR_AUTH_METHOD:
2084		case OAKLEY_ATTR_GRP_DESC:
2085		case OAKLEY_ATTR_GRP_TYPE:
2086		case OAKLEY_ATTR_SA_LD_TYPE:
2087		case OAKLEY_ATTR_PRF:
2088		case OAKLEY_ATTR_KEY_LEN:
2089		case OAKLEY_ATTR_FIELD_SIZE:
2090			if (!flag) {	/* TLV*/
2091				plog(LLV_ERROR, LOCATION, NULL,
2092					"oakley attribute %d must be TV.\n",
2093					type);
2094				return -1;
2095			}
2096			break;
2097		}
2098
2099		/* sanity check for TLV.  length must be specified. */
2100		if (!flag && lorv == 0) {	/*TLV*/
2101			plog(LLV_ERROR, LOCATION, NULL,
2102				"invalid length %d for TLV attribute %d.\n",
2103				lorv, type);
2104			return -1;
2105		}
2106
2107		switch (type) {
2108		case OAKLEY_ATTR_ENC_ALG:
2109			if (!alg_oakley_encdef_ok(lorv)) {
2110				plog(LLV_ERROR, LOCATION, NULL,
2111					"invalied encryption algorithm=%d.\n",
2112					lorv);
2113				return -1;
2114			}
2115			break;
2116
2117		case OAKLEY_ATTR_HASH_ALG:
2118			if (!alg_oakley_hashdef_ok(lorv)) {
2119				plog(LLV_ERROR, LOCATION, NULL,
2120					"invalied hash algorithm=%d.\n",
2121					lorv);
2122				return -1;
2123			}
2124			break;
2125
2126		case OAKLEY_ATTR_AUTH_METHOD:
2127			switch (lorv) {
2128			case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2129			case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2130#ifdef ENABLE_HYBRID
2131			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2132			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2133#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2134			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2135#endif
2136#endif
2137			case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2138				break;
2139			case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2140#ifdef ENABLE_HYBRID
2141			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2142			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2143			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2144			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2145			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
2146			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2147			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2148			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2149			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2150			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2151			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
2152#endif
2153			case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2154			case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2155				plog(LLV_ERROR, LOCATION, NULL,
2156					"auth method %s isn't supported.\n",
2157					s_oakley_attr_method(lorv));
2158				return -1;
2159			default:
2160				plog(LLV_ERROR, LOCATION, NULL,
2161					"invalid auth method %d.\n",
2162					lorv);
2163				return -1;
2164			}
2165			break;
2166
2167		case OAKLEY_ATTR_GRP_DESC:
2168			if (!alg_oakley_dhdef_ok(lorv)) {
2169				plog(LLV_ERROR, LOCATION, NULL,
2170					"invalid DH group %d.\n",
2171					lorv);
2172				return -1;
2173			}
2174			break;
2175
2176		case OAKLEY_ATTR_GRP_TYPE:
2177			switch (lorv) {
2178			case OAKLEY_ATTR_GRP_TYPE_MODP:
2179				break;
2180			default:
2181				plog(LLV_ERROR, LOCATION, NULL,
2182					"unsupported DH group type %d.\n",
2183					lorv);
2184				return -1;
2185			}
2186			break;
2187
2188		case OAKLEY_ATTR_GRP_PI:
2189		case OAKLEY_ATTR_GRP_GEN_ONE:
2190			/* sanity checks? */
2191			break;
2192
2193		case OAKLEY_ATTR_GRP_GEN_TWO:
2194		case OAKLEY_ATTR_GRP_CURVE_A:
2195		case OAKLEY_ATTR_GRP_CURVE_B:
2196			plog(LLV_ERROR, LOCATION, NULL,
2197				"attr type=%u isn't supported.\n", type);
2198			return -1;
2199
2200		case OAKLEY_ATTR_SA_LD_TYPE:
2201			switch (lorv) {
2202			case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2203			case OAKLEY_ATTR_SA_LD_TYPE_KB:
2204				break;
2205			default:
2206				plog(LLV_ERROR, LOCATION, NULL,
2207					"invalid life type %d.\n", lorv);
2208				return -1;
2209			}
2210			break;
2211
2212		case OAKLEY_ATTR_SA_LD:
2213			/* should check the value */
2214			break;
2215
2216		case OAKLEY_ATTR_PRF:
2217		case OAKLEY_ATTR_KEY_LEN:
2218			break;
2219
2220		case OAKLEY_ATTR_FIELD_SIZE:
2221			plog(LLV_ERROR, LOCATION, NULL,
2222				"attr type=%u isn't supported.\n", type);
2223			return -1;
2224
2225		case OAKLEY_ATTR_GRP_ORDER:
2226			break;
2227
2228		case OAKLEY_ATTR_GSS_ID:
2229			break;
2230
2231		default:
2232			plog(LLV_ERROR, LOCATION, NULL,
2233				"invalid attribute type %d.\n", type);
2234			return -1;
2235		}
2236
2237		if (flag) {
2238			tlen -= sizeof(*d);
2239			d = (struct isakmp_data *)((char *)d
2240				+ sizeof(*d));
2241		} else {
2242			tlen -= (sizeof(*d) + lorv);
2243			d = (struct isakmp_data *)((char *)d
2244				+ sizeof(*d) + lorv);
2245		}
2246	}
2247
2248	return 0;
2249}
2250
2251/*
2252 * check data attributes in IPSEC AH/ESP.
2253 */
2254static int
2255check_attr_ah(trns)
2256	struct isakmp_pl_t *trns;
2257{
2258	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2259}
2260
2261static int
2262check_attr_esp(trns)
2263	struct isakmp_pl_t *trns;
2264{
2265	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2266}
2267
2268static int
2269check_attr_ipsec(proto_id, trns)
2270	int proto_id;
2271	struct isakmp_pl_t *trns;
2272{
2273	struct isakmp_data *d;
2274	int tlen;
2275	int flag, type = 0;
2276	u_int16_t lorv;
2277	int attrseen[16];	/* XXX magic number */
2278
2279	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2280	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2281	memset(attrseen, 0, sizeof(attrseen));
2282
2283	while (tlen > 0) {
2284		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2285		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2286		lorv = ntohs(d->lorv);
2287
2288		plog(LLV_DEBUG, LOCATION, NULL,
2289			"type=%s, flag=0x%04x, lorv=%s\n",
2290			s_ipsecdoi_attr(type), flag,
2291			s_ipsecdoi_attr_v(type, lorv));
2292
2293		if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2294			attrseen[type]++;
2295
2296		switch (type) {
2297		case IPSECDOI_ATTR_ENC_MODE:
2298			if (! flag) {
2299				plog(LLV_ERROR, LOCATION, NULL,
2300					"must be TV when ENC_MODE.\n");
2301				return -1;
2302			}
2303
2304			switch (lorv) {
2305			case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2306			case IPSECDOI_ATTR_ENC_MODE_TRNS:
2307				break;
2308#ifdef ENABLE_NATT
2309			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2310			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2311			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2312			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2313				plog(LLV_DEBUG, LOCATION, NULL,
2314				     "UDP encapsulation requested\n");
2315				break;
2316#endif
2317			default:
2318				plog(LLV_ERROR, LOCATION, NULL,
2319					"invalid encryption mode=%u.\n",
2320					lorv);
2321				return -1;
2322			}
2323			break;
2324
2325		case IPSECDOI_ATTR_AUTH:
2326			if (! flag) {
2327				plog(LLV_ERROR, LOCATION, NULL,
2328					"must be TV when AUTH.\n");
2329				return -1;
2330			}
2331
2332			switch (lorv) {
2333			case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2334				if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2335				    trns->t_id != IPSECDOI_AH_MD5) {
2336ahmismatch:
2337					plog(LLV_ERROR, LOCATION, NULL,
2338						"auth algorithm %u conflicts "
2339						"with transform %u.\n",
2340						lorv, trns->t_id);
2341					return -1;
2342				}
2343				break;
2344			case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2345				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2346					if (trns->t_id != IPSECDOI_AH_SHA)
2347						goto ahmismatch;
2348				}
2349				break;
2350 			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2351 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2352 					if (trns->t_id != IPSECDOI_AH_SHA256)
2353 						goto ahmismatch;
2354 				}
2355 				break;
2356 			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2357 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2358 					if (trns->t_id != IPSECDOI_AH_SHA384)
2359 						goto ahmismatch;
2360 				}
2361 				break;
2362 			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2363 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2364 					if (trns->t_id != IPSECDOI_AH_SHA512)
2365 					goto ahmismatch;
2366 				}
2367 				break;
2368			case IPSECDOI_ATTR_AUTH_DES_MAC:
2369			case IPSECDOI_ATTR_AUTH_KPDK:
2370				plog(LLV_ERROR, LOCATION, NULL,
2371					"auth algorithm %u isn't supported.\n",
2372					lorv);
2373				return -1;
2374			default:
2375				plog(LLV_ERROR, LOCATION, NULL,
2376					"invalid auth algorithm=%u.\n",
2377					lorv);
2378				return -1;
2379			}
2380			break;
2381
2382		case IPSECDOI_ATTR_SA_LD_TYPE:
2383			if (! flag) {
2384				plog(LLV_ERROR, LOCATION, NULL,
2385					"must be TV when LD_TYPE.\n");
2386				return -1;
2387			}
2388
2389			switch (lorv) {
2390			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2391			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2392				break;
2393			default:
2394				plog(LLV_ERROR, LOCATION, NULL,
2395					"invalid life type %d.\n", lorv);
2396				return -1;
2397			}
2398			break;
2399
2400		case IPSECDOI_ATTR_SA_LD:
2401			if (flag) {
2402				/* i.e. ISAKMP_GEN_TV */
2403				plog(LLV_DEBUG, LOCATION, NULL,
2404					"life duration was in TLV.\n");
2405			} else {
2406				/* i.e. ISAKMP_GEN_TLV */
2407				if (lorv == 0) {
2408					plog(LLV_ERROR, LOCATION, NULL,
2409						"invalid length of LD\n");
2410					return -1;
2411				}
2412			}
2413			break;
2414
2415		case IPSECDOI_ATTR_GRP_DESC:
2416			if (! flag) {
2417				plog(LLV_ERROR, LOCATION, NULL,
2418					"must be TV when GRP_DESC.\n");
2419				return -1;
2420			}
2421
2422			if (!alg_oakley_dhdef_ok(lorv)) {
2423				plog(LLV_ERROR, LOCATION, NULL,
2424					"invalid group description=%u.\n",
2425					lorv);
2426				return -1;
2427			}
2428			break;
2429
2430		case IPSECDOI_ATTR_KEY_LENGTH:
2431			if (! flag) {
2432				plog(LLV_ERROR, LOCATION, NULL,
2433					"must be TV when KEY_LENGTH.\n");
2434				return -1;
2435			}
2436			break;
2437
2438#ifdef HAVE_SECCTX
2439		case IPSECDOI_ATTR_SECCTX:
2440			if (flag) {
2441				plog(LLV_ERROR, LOCATION, NULL,
2442					"SECCTX must be in TLV.\n");
2443				return -1;
2444			}
2445		break;
2446#endif
2447
2448		case IPSECDOI_ATTR_KEY_ROUNDS:
2449		case IPSECDOI_ATTR_COMP_DICT_SIZE:
2450		case IPSECDOI_ATTR_COMP_PRIVALG:
2451			plog(LLV_ERROR, LOCATION, NULL,
2452				"attr type=%u isn't supported.\n", type);
2453			return -1;
2454
2455		default:
2456			plog(LLV_ERROR, LOCATION, NULL,
2457				"invalid attribute type %d.\n", type);
2458			return -1;
2459		}
2460
2461		if (flag) {
2462			tlen -= sizeof(*d);
2463			d = (struct isakmp_data *)((char *)d
2464				+ sizeof(*d));
2465		} else {
2466			tlen -= (sizeof(*d) + lorv);
2467			d = (struct isakmp_data *)((caddr_t)d
2468				+ sizeof(*d) + lorv);
2469		}
2470	}
2471
2472	if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2473	    !attrseen[IPSECDOI_ATTR_AUTH]) {
2474		plog(LLV_ERROR, LOCATION, NULL,
2475			"attr AUTH must be present for AH.\n");
2476		return -1;
2477	}
2478
2479	if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2480	    trns->t_id == IPSECDOI_ESP_NULL &&
2481	    !attrseen[IPSECDOI_ATTR_AUTH]) {
2482		plog(LLV_ERROR, LOCATION, NULL,
2483		    "attr AUTH must be present for ESP NULL encryption.\n");
2484		return -1;
2485	}
2486
2487	return 0;
2488}
2489
2490static int
2491check_attr_ipcomp(trns)
2492	struct isakmp_pl_t *trns;
2493{
2494	struct isakmp_data *d;
2495	int tlen;
2496	int flag, type = 0;
2497	u_int16_t lorv;
2498	int attrseen[16];	/* XXX magic number */
2499
2500	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2501	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2502	memset(attrseen, 0, sizeof(attrseen));
2503
2504	while (tlen > 0) {
2505		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2506		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2507		lorv = ntohs(d->lorv);
2508
2509		plog(LLV_DEBUG, LOCATION, NULL,
2510			"type=%d, flag=0x%04x, lorv=0x%04x\n",
2511			type, flag, lorv);
2512
2513		if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2514			attrseen[type]++;
2515
2516		switch (type) {
2517		case IPSECDOI_ATTR_ENC_MODE:
2518			if (! flag) {
2519				plog(LLV_ERROR, LOCATION, NULL,
2520					"must be TV when ENC_MODE.\n");
2521				return -1;
2522			}
2523
2524			switch (lorv) {
2525			case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2526			case IPSECDOI_ATTR_ENC_MODE_TRNS:
2527				break;
2528#ifdef ENABLE_NATT
2529			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2530			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2531			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2532			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2533				plog(LLV_DEBUG, LOCATION, NULL,
2534				     "UDP encapsulation requested\n");
2535				break;
2536#endif
2537			default:
2538				plog(LLV_ERROR, LOCATION, NULL,
2539					"invalid encryption mode=%u.\n",
2540					lorv);
2541				return -1;
2542			}
2543			break;
2544
2545		case IPSECDOI_ATTR_SA_LD_TYPE:
2546			if (! flag) {
2547				plog(LLV_ERROR, LOCATION, NULL,
2548					"must be TV when LD_TYPE.\n");
2549				return -1;
2550			}
2551
2552			switch (lorv) {
2553			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2554			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2555				break;
2556			default:
2557				plog(LLV_ERROR, LOCATION, NULL,
2558					"invalid life type %d.\n", lorv);
2559				return -1;
2560			}
2561			break;
2562
2563		case IPSECDOI_ATTR_SA_LD:
2564			if (flag) {
2565				/* i.e. ISAKMP_GEN_TV */
2566				plog(LLV_DEBUG, LOCATION, NULL,
2567					"life duration was in TLV.\n");
2568			} else {
2569				/* i.e. ISAKMP_GEN_TLV */
2570				if (lorv == 0) {
2571					plog(LLV_ERROR, LOCATION, NULL,
2572						"invalid length of LD\n");
2573					return -1;
2574				}
2575			}
2576			break;
2577
2578		case IPSECDOI_ATTR_GRP_DESC:
2579			if (! flag) {
2580				plog(LLV_ERROR, LOCATION, NULL,
2581					"must be TV when GRP_DESC.\n");
2582				return -1;
2583			}
2584
2585			if (!alg_oakley_dhdef_ok(lorv)) {
2586				plog(LLV_ERROR, LOCATION, NULL,
2587					"invalid group description=%u.\n",
2588					lorv);
2589				return -1;
2590			}
2591			break;
2592
2593		case IPSECDOI_ATTR_AUTH:
2594			plog(LLV_ERROR, LOCATION, NULL,
2595				"invalid attr type=%u.\n", type);
2596			return -1;
2597
2598		case IPSECDOI_ATTR_KEY_LENGTH:
2599		case IPSECDOI_ATTR_KEY_ROUNDS:
2600		case IPSECDOI_ATTR_COMP_DICT_SIZE:
2601		case IPSECDOI_ATTR_COMP_PRIVALG:
2602			plog(LLV_ERROR, LOCATION, NULL,
2603				"attr type=%u isn't supported.\n", type);
2604			return -1;
2605
2606		default:
2607			plog(LLV_ERROR, LOCATION, NULL,
2608				"invalid attribute type %d.\n", type);
2609			return -1;
2610		}
2611
2612		if (flag) {
2613			tlen -= sizeof(*d);
2614			d = (struct isakmp_data *)((char *)d
2615				+ sizeof(*d));
2616		} else {
2617			tlen -= (sizeof(*d) + lorv);
2618			d = (struct isakmp_data *)((caddr_t)d
2619				+ sizeof(*d) + lorv);
2620		}
2621	}
2622
2623#if 0
2624	if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2625	    !attrseen[IPSECDOI_ATTR_AUTH]) {
2626		plog(LLV_ERROR, LOCATION, NULL,
2627			"attr AUTH must be present for AH.\n", type);
2628		return -1;
2629	}
2630#endif
2631
2632	return 0;
2633}
2634
2635/* %%% */
2636/*
2637 * create phase1 proposal from remote configuration.
2638 * NOT INCLUDING isakmp general header of SA payload
2639 */
2640vchar_t *
2641ipsecdoi_setph1proposal(props)
2642	struct isakmpsa *props;
2643{
2644	vchar_t *mysa;
2645	int sablen;
2646
2647	/* count total size of SA minus isakmp general header */
2648	/* not including isakmp general header of SA payload */
2649	sablen = sizeof(struct ipsecdoi_sa_b);
2650	sablen += setph1prop(props, NULL);
2651
2652	mysa = vmalloc(sablen);
2653	if (mysa == NULL) {
2654		plog(LLV_ERROR, LOCATION, NULL,
2655			"failed to allocate my sa buffer\n");
2656		return NULL;
2657	}
2658
2659	/* create SA payload */
2660	/* not including isakmp general header */
2661	((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
2662	((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
2663
2664	(void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2665
2666	return mysa;
2667}
2668
2669static int
2670setph1prop(props, buf)
2671	struct isakmpsa *props;
2672	caddr_t buf;
2673{
2674	struct isakmp_pl_p *prop = NULL;
2675	struct isakmpsa *s = NULL;
2676	int proplen, trnslen;
2677	u_int8_t *np_t; /* pointer next trns type in previous header */
2678	int trns_num;
2679	caddr_t p = buf;
2680
2681	proplen = sizeof(*prop);
2682	if (buf) {
2683		/* create proposal */
2684		prop = (struct isakmp_pl_p *)p;
2685		prop->h.np = ISAKMP_NPTYPE_NONE;
2686		prop->p_no = props->prop_no;
2687		prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2688		prop->spi_size = 0;
2689		p += sizeof(*prop);
2690	}
2691
2692	np_t = NULL;
2693	trns_num = 0;
2694
2695	for (s = props; s != NULL; s = s->next) {
2696		if (np_t)
2697			*np_t = ISAKMP_NPTYPE_T;
2698
2699		trnslen = setph1trns(s, p);
2700		proplen += trnslen;
2701		if (buf) {
2702			/* save buffer to pre-next payload */
2703			np_t = &((struct isakmp_pl_t *)p)->h.np;
2704			p += trnslen;
2705
2706			/* count up transform length */
2707			trns_num++;
2708		}
2709	}
2710
2711	/* update proposal length */
2712	if (buf) {
2713		prop->h.len = htons(proplen);
2714		prop->num_t = trns_num;
2715	}
2716
2717	return proplen;
2718}
2719
2720static int
2721setph1trns(sa, buf)
2722	struct isakmpsa *sa;
2723	caddr_t buf;
2724{
2725	struct isakmp_pl_t *trns = NULL;
2726	int trnslen, attrlen;
2727	caddr_t p = buf;
2728
2729	trnslen = sizeof(*trns);
2730	if (buf) {
2731		/* create transform */
2732		trns = (struct isakmp_pl_t *)p;
2733		trns->h.np  = ISAKMP_NPTYPE_NONE;
2734		trns->t_no  = sa->trns_no;
2735		trns->t_id  = IPSECDOI_KEY_IKE;
2736		p += sizeof(*trns);
2737	}
2738
2739	attrlen = setph1attr(sa, p);
2740	trnslen += attrlen;
2741	if (buf)
2742		p += attrlen;
2743
2744	if (buf)
2745		trns->h.len = htons(trnslen);
2746
2747	return trnslen;
2748}
2749
2750static int
2751setph1attr(sa, buf)
2752	struct isakmpsa *sa;
2753	caddr_t buf;
2754{
2755	caddr_t p = buf;
2756	int attrlen = 0;
2757
2758	if (sa->lifetime) {
2759		u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
2760
2761		attrlen += sizeof(struct isakmp_data)
2762			+ sizeof(struct isakmp_data);
2763		if (sa->lifetime > 0xffff)
2764			attrlen += sizeof(lifetime);
2765		if (buf) {
2766			p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2767						OAKLEY_ATTR_SA_LD_TYPE_SEC);
2768			if (sa->lifetime > 0xffff) {
2769				p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2770						(caddr_t)&lifetime,
2771						sizeof(lifetime));
2772			} else {
2773				p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2774							sa->lifetime);
2775			}
2776		}
2777	}
2778
2779	if (sa->lifebyte) {
2780		u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
2781
2782		attrlen += sizeof(struct isakmp_data)
2783			+ sizeof(struct isakmp_data);
2784		if (sa->lifebyte > 0xffff)
2785			attrlen += sizeof(lifebyte);
2786		if (buf) {
2787			p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2788						OAKLEY_ATTR_SA_LD_TYPE_KB);
2789			if (sa->lifebyte > 0xffff) {
2790				p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2791							(caddr_t)&lifebyte,
2792							sizeof(lifebyte));
2793			} else {
2794				p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2795							sa->lifebyte);
2796			}
2797		}
2798	}
2799
2800	if (sa->enctype) {
2801		attrlen += sizeof(struct isakmp_data);
2802		if (buf)
2803			p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2804	}
2805	if (sa->encklen) {
2806		attrlen += sizeof(struct isakmp_data);
2807		if (buf)
2808			p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2809	}
2810	if (sa->authmethod) {
2811		int authmethod;
2812
2813#ifdef ENABLE_HYBRID
2814		authmethod = switch_authmethod(sa->authmethod);
2815#else
2816		authmethod = sa->authmethod;
2817#endif
2818		attrlen += sizeof(struct isakmp_data);
2819		if (buf)
2820			p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
2821	}
2822	if (sa->hashtype) {
2823		attrlen += sizeof(struct isakmp_data);
2824		if (buf)
2825			p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2826	}
2827	switch (sa->dh_group) {
2828	case OAKLEY_ATTR_GRP_DESC_MODP768:
2829	case OAKLEY_ATTR_GRP_DESC_MODP1024:
2830	case OAKLEY_ATTR_GRP_DESC_MODP1536:
2831	case OAKLEY_ATTR_GRP_DESC_MODP2048:
2832	case OAKLEY_ATTR_GRP_DESC_MODP3072:
2833	case OAKLEY_ATTR_GRP_DESC_MODP4096:
2834	case OAKLEY_ATTR_GRP_DESC_MODP6144:
2835	case OAKLEY_ATTR_GRP_DESC_MODP8192:
2836		/* don't attach group type for known groups */
2837		attrlen += sizeof(struct isakmp_data);
2838		if (buf) {
2839			p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2840				sa->dh_group);
2841		}
2842		break;
2843	case OAKLEY_ATTR_GRP_DESC_EC2N155:
2844	case OAKLEY_ATTR_GRP_DESC_EC2N185:
2845		/* don't attach group type for known groups */
2846		attrlen += sizeof(struct isakmp_data);
2847		if (buf) {
2848			p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2849				OAKLEY_ATTR_GRP_TYPE_EC2N);
2850		}
2851		break;
2852	case 0:
2853	default:
2854		break;
2855	}
2856
2857#ifdef HAVE_GSSAPI
2858	if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2859	    sa->gssid != NULL) {
2860		attrlen += sizeof(struct isakmp_data);
2861		/*
2862		 * Older versions of racoon just placed the ISO-Latin-1
2863		 * string on the wire directly.  Check to see if we are
2864		 * configured to be compatible with this behavior.  Otherwise,
2865		 * we encode the GSS ID as UTF-16LE for Windows 2000
2866		 * compatibility, which requires twice the number of octets.
2867		 */
2868		if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
2869			attrlen += sa->gssid->l;
2870		else
2871			attrlen += sa->gssid->l * 2;
2872		if (buf) {
2873			plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
2874			    "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
2875			    sa->gssid->v);
2876			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
2877				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2878					(caddr_t)sa->gssid->v,
2879					sa->gssid->l);
2880			} else {
2881				size_t dstleft = sa->gssid->l * 2;
2882				size_t srcleft = sa->gssid->l;
2883				const char *src = (const char *)sa->gssid->v;
2884				char *odst, *dst = racoon_malloc(dstleft);
2885				iconv_t cd;
2886				size_t rv;
2887
2888				cd = iconv_open("utf-16le", "latin1");
2889				if (cd == (iconv_t) -1) {
2890					plog(LLV_ERROR, LOCATION, NULL,
2891					    "unable to initialize "
2892					    "latin1 -> utf-16le "
2893					    "converstion descriptor: %s\n",
2894					    strerror(errno));
2895					attrlen -= sa->gssid->l * 2;
2896					goto gssid_done;
2897				}
2898				odst = dst;
2899				rv = iconv(cd, (__iconv_const char **)&src,
2900				    &srcleft, &dst, &dstleft);
2901				if (rv != 0) {
2902					if (rv == -1) {
2903						plog(LLV_ERROR, LOCATION, NULL,
2904						    "unable to convert GSS ID "
2905						    "from latin1 -> utf-16le: "
2906						    "%s\n", strerror(errno));
2907					} else {
2908						/* should never happen */
2909						plog(LLV_ERROR, LOCATION, NULL,
2910						    "%zd character%s in GSS ID "
2911						    "cannot be represented "
2912						    "in utf-16le\n",
2913						    rv, rv == 1 ? "" : "s");
2914					}
2915					(void) iconv_close(cd);
2916					attrlen -= sa->gssid->l * 2;
2917					goto gssid_done;
2918				}
2919				(void) iconv_close(cd);
2920
2921				/* XXX Check srcleft and dstleft? */
2922
2923				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2924					odst, sa->gssid->l * 2);
2925
2926				racoon_free(odst);
2927			}
2928		}
2929	}
2930 gssid_done:
2931#endif /* HAVE_GSSAPI */
2932
2933	return attrlen;
2934}
2935
2936static vchar_t *
2937setph2proposal0(iph2, pp, pr)
2938	const struct ph2handle *iph2;
2939	const struct saprop *pp;
2940	const struct saproto *pr;
2941{
2942	vchar_t *p;
2943	struct isakmp_pl_p *prop;
2944	struct isakmp_pl_t *trns;
2945	struct satrns *tr;
2946	int attrlen;
2947	size_t trnsoff;
2948	caddr_t x0, x;
2949	u_int8_t *np_t; /* pointer next trns type in previous header */
2950	const u_int8_t *spi;
2951#ifdef HAVE_SECCTX
2952	int truectxlen = 0;
2953#endif
2954
2955	p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2956	if (p == NULL)
2957		return NULL;
2958
2959	/* create proposal */
2960	prop = (struct isakmp_pl_p *)p->v;
2961	prop->h.np = ISAKMP_NPTYPE_NONE;
2962	prop->p_no = pp->prop_no;
2963	prop->proto_id = pr->proto_id;
2964	prop->num_t = 1;
2965
2966	spi = (const u_int8_t *)&pr->spi;
2967	switch (pr->proto_id) {
2968	case IPSECDOI_PROTO_IPCOMP:
2969		/*
2970		 * draft-shacham-ippcp-rfc2393bis-05.txt:
2971		 * construct 16bit SPI (CPI).
2972		 * XXX we may need to provide a configuration option to
2973		 * generate 32bit SPI.  otherwise we cannot interoeprate
2974		 * with nodes that uses 32bit SPI, in case we are initiator.
2975		 */
2976		prop->spi_size = sizeof(u_int16_t);
2977		spi += sizeof(pr->spi) - sizeof(u_int16_t);
2978		p->l -= sizeof(pr->spi);
2979		p->l += sizeof(u_int16_t);
2980		break;
2981	default:
2982		prop->spi_size = sizeof(pr->spi);
2983		break;
2984	}
2985	memcpy(prop + 1, spi, prop->spi_size);
2986
2987	/* create transform */
2988	trnsoff = sizeof(*prop) + prop->spi_size;
2989	np_t = NULL;
2990
2991	for (tr = pr->head; tr; tr = tr->next) {
2992
2993		switch (pr->proto_id) {
2994		case IPSECDOI_PROTO_IPSEC_ESP:
2995			/*
2996			 * don't build a null encryption
2997			 * with no authentication transform.
2998			 */
2999			if (tr->trns_id == IPSECDOI_ESP_NULL &&
3000			    tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
3001				continue;
3002			break;
3003		}
3004
3005		if (np_t) {
3006			*np_t = ISAKMP_NPTYPE_T;
3007			prop->num_t++;
3008		}
3009
3010		/* get attribute length */
3011		attrlen = 0;
3012		if (pp->lifetime) {
3013			attrlen += sizeof(struct isakmp_data)
3014				+ sizeof(struct isakmp_data);
3015			if (pp->lifetime > 0xffff)
3016				attrlen += sizeof(u_int32_t);
3017		}
3018		if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3019			attrlen += sizeof(struct isakmp_data)
3020				+ sizeof(struct isakmp_data);
3021			if (pp->lifebyte > 0xffff)
3022				attrlen += sizeof(u_int32_t);
3023		}
3024		attrlen += sizeof(struct isakmp_data);	/* enc mode */
3025		if (tr->encklen)
3026			attrlen += sizeof(struct isakmp_data);
3027
3028		switch (pr->proto_id) {
3029		case IPSECDOI_PROTO_IPSEC_ESP:
3030			/* non authentication mode ? */
3031			if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3032				attrlen += sizeof(struct isakmp_data);
3033			break;
3034		case IPSECDOI_PROTO_IPSEC_AH:
3035			if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
3036				plog(LLV_ERROR, LOCATION, NULL,
3037					"no authentication algorithm found "
3038					"but protocol is AH.\n");
3039				vfree(p);
3040				return NULL;
3041			}
3042			attrlen += sizeof(struct isakmp_data);
3043			break;
3044		case IPSECDOI_PROTO_IPCOMP:
3045			break;
3046		default:
3047			plog(LLV_ERROR, LOCATION, NULL,
3048				"invalid protocol: %d\n", pr->proto_id);
3049			vfree(p);
3050			return NULL;
3051		}
3052
3053		if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3054			attrlen += sizeof(struct isakmp_data);
3055
3056#ifdef HAVE_SECCTX
3057		/* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
3058		 * The string may be smaller than MAX_CTXSTR_SIZ.
3059		 */
3060		if (*pp->sctx.ctx_str) {
3061			truectxlen = sizeof(struct security_ctx) -
3062				     (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
3063			attrlen += sizeof(struct isakmp_data) + truectxlen;
3064		}
3065#endif /* HAVE_SECCTX */
3066
3067		p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
3068		if (p == NULL)
3069			return NULL;
3070		prop = (struct isakmp_pl_p *)p->v;
3071
3072		/* set transform's values */
3073		trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3074		trns->h.np  = ISAKMP_NPTYPE_NONE;
3075		trns->t_no  = tr->trns_no;
3076		trns->t_id  = tr->trns_id;
3077
3078		/* set attributes */
3079		x = x0 = p->v + trnsoff + sizeof(*trns);
3080
3081		if (pp->lifetime) {
3082			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3083						IPSECDOI_ATTR_SA_LD_TYPE_SEC);
3084			if (pp->lifetime > 0xffff) {
3085				u_int32_t v = htonl((u_int32_t)pp->lifetime);
3086				x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3087							(caddr_t)&v, sizeof(v));
3088			} else {
3089				x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3090							pp->lifetime);
3091			}
3092		}
3093
3094		if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3095			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3096						IPSECDOI_ATTR_SA_LD_TYPE_KB);
3097			if (pp->lifebyte > 0xffff) {
3098				u_int32_t v = htonl((u_int32_t)pp->lifebyte);
3099				x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3100							(caddr_t)&v, sizeof(v));
3101			} else {
3102				x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3103							pp->lifebyte);
3104			}
3105		}
3106
3107		x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
3108
3109		if (tr->encklen)
3110			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
3111
3112		/* mandatory check has done above. */
3113		if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3114		 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
3115			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
3116
3117		if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3118			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
3119				iph2->sainfo->pfs_group);
3120
3121#ifdef HAVE_SECCTX
3122		if (*pp->sctx.ctx_str) {
3123			struct security_ctx secctx;
3124			secctx = pp->sctx;
3125			secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
3126			x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
3127					     (caddr_t)&secctx, truectxlen);
3128		}
3129#endif
3130		/* update length of this transform. */
3131		trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3132		trns->h.len = htons(sizeof(*trns) + attrlen);
3133
3134		/* save buffer to pre-next payload */
3135		np_t = &trns->h.np;
3136
3137		trnsoff += (sizeof(*trns) + attrlen);
3138	}
3139
3140	if (np_t == NULL) {
3141		plog(LLV_ERROR, LOCATION, NULL,
3142			"no suitable proposal was created.\n");
3143		return NULL;
3144	}
3145
3146	/* update length of this protocol. */
3147	prop->h.len = htons(p->l);
3148
3149	return p;
3150}
3151
3152/*
3153 * create phase2 proposal from policy configuration.
3154 * NOT INCLUDING isakmp general header of SA payload.
3155 * This function is called by initiator only.
3156 */
3157int
3158ipsecdoi_setph2proposal(iph2)
3159	struct ph2handle *iph2;
3160{
3161	struct saprop *proposal, *a;
3162	struct saproto *b = NULL;
3163	vchar_t *q;
3164	struct ipsecdoi_sa_b *sab;
3165	struct isakmp_pl_p *prop;
3166	size_t propoff;	/* for previous field of type of next payload. */
3167
3168	proposal = iph2->proposal;
3169
3170	iph2->sa = vmalloc(sizeof(*sab));
3171	if (iph2->sa == NULL) {
3172		plog(LLV_ERROR, LOCATION, NULL,
3173			"failed to allocate my sa buffer\n");
3174		return -1;
3175	}
3176
3177	/* create SA payload */
3178	sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
3179	sab->doi = htonl(IPSEC_DOI);
3180	sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY);	/* XXX configurable ? */
3181
3182	prop = NULL;
3183	propoff = 0;
3184	for (a = proposal; a; a = a->next) {
3185		for (b = a->head; b; b = b->next) {
3186#ifdef ENABLE_NATT
3187			if (iph2->ph1->natt_flags & NAT_DETECTED) {
3188			  int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
3189			  plog (LLV_INFO, LOCATION, NULL,
3190				"NAT detected -> UDP encapsulation "
3191				"(ENC_MODE %d->%d).\n",
3192				b->encmode,
3193				b->encmode+udp_diff);
3194			  /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3195			  b->encmode += udp_diff;
3196			  b->udp_encap = 1;
3197			}
3198#endif
3199
3200			q = setph2proposal0(iph2, a, b);
3201			if (q == NULL) {
3202				VPTRINIT(iph2->sa);
3203				return -1;
3204			}
3205
3206			iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
3207			if (iph2->sa == NULL) {
3208				plog(LLV_ERROR, LOCATION, NULL,
3209					"failed to allocate my sa buffer\n");
3210				if (q)
3211					vfree(q);
3212				return -1;
3213			}
3214			memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3215			if (propoff != 0) {
3216				prop = (struct isakmp_pl_p *)(iph2->sa->v +
3217					propoff);
3218				prop->h.np = ISAKMP_NPTYPE_P;
3219			}
3220			propoff = iph2->sa->l - q->l;
3221
3222			vfree(q);
3223		}
3224	}
3225
3226	return 0;
3227}
3228
3229/*
3230 * return 1 if all of the given protocols are transport mode.
3231 */
3232int
3233ipsecdoi_transportmode(pp)
3234	struct saprop *pp;
3235{
3236	struct saproto *pr = NULL;
3237
3238	for (; pp; pp = pp->next) {
3239		for (pr = pp->head; pr; pr = pr->next) {
3240			if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3241				return 0;
3242		}
3243	}
3244
3245	return 1;
3246}
3247
3248int
3249ipsecdoi_get_defaultlifetime()
3250{
3251	return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3252}
3253
3254int
3255ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3256	int proto_id, enc, auth, comp;
3257{
3258#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3259	switch (proto_id) {
3260	case IPSECDOI_PROTO_IPSEC_ESP:
3261		if (enc == 0 || comp != 0) {
3262			plog(LLV_ERROR, LOCATION, NULL,
3263				"illegal algorithm defined "
3264				"ESP enc=%s auth=%s comp=%s.\n",
3265				TMPALGTYPE2STR(enc),
3266				TMPALGTYPE2STR(auth),
3267				TMPALGTYPE2STR(comp));
3268			return -1;
3269		}
3270		break;
3271	case IPSECDOI_PROTO_IPSEC_AH:
3272		if (enc != 0 || auth == 0 || comp != 0) {
3273			plog(LLV_ERROR, LOCATION, NULL,
3274				"illegal algorithm defined "
3275				"AH enc=%s auth=%s comp=%s.\n",
3276				TMPALGTYPE2STR(enc),
3277				TMPALGTYPE2STR(auth),
3278				TMPALGTYPE2STR(comp));
3279			return -1;
3280		}
3281		break;
3282	case IPSECDOI_PROTO_IPCOMP:
3283		if (enc != 0 || auth != 0 || comp == 0) {
3284			plog(LLV_ERROR, LOCATION, NULL,
3285				"illegal algorithm defined "
3286				"IPcomp enc=%s auth=%s comp=%s.\n",
3287				TMPALGTYPE2STR(enc),
3288				TMPALGTYPE2STR(auth),
3289				TMPALGTYPE2STR(comp));
3290			return -1;
3291		}
3292		break;
3293	default:
3294		plog(LLV_ERROR, LOCATION, NULL,
3295			"invalid ipsec protocol %d\n", proto_id);
3296		return -1;
3297	}
3298#undef TMPALGTYPE2STR
3299	return 0;
3300}
3301
3302int
3303ipproto2doi(proto)
3304	int proto;
3305{
3306	switch (proto) {
3307	case IPPROTO_AH:
3308		return IPSECDOI_PROTO_IPSEC_AH;
3309	case IPPROTO_ESP:
3310		return IPSECDOI_PROTO_IPSEC_ESP;
3311	case IPPROTO_IPCOMP:
3312		return IPSECDOI_PROTO_IPCOMP;
3313	}
3314	return -1;	/* XXX */
3315}
3316
3317int
3318doi2ipproto(proto)
3319	int proto;
3320{
3321	switch (proto) {
3322	case IPSECDOI_PROTO_IPSEC_AH:
3323		return IPPROTO_AH;
3324	case IPSECDOI_PROTO_IPSEC_ESP:
3325		return IPPROTO_ESP;
3326	case IPSECDOI_PROTO_IPCOMP:
3327		return IPPROTO_IPCOMP;
3328	}
3329	return -1;	/* XXX */
3330}
3331
3332/*
3333 * Check if a subnet id is valid for comparison
3334 * with an address id ( address length mask )
3335 * and compare them
3336 * Return value
3337 * =  0 for match
3338 * =  1 for mismatch
3339 */
3340
3341int
3342ipsecdoi_subnetisaddr_v4( subnet, address )
3343	const vchar_t *subnet;
3344	const vchar_t *address;
3345{
3346	struct in_addr *mask;
3347
3348	if (address->l != sizeof(struct in_addr))
3349		return 1;
3350
3351	if (subnet->l != (sizeof(struct in_addr)*2))
3352		return 1;
3353
3354	mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
3355
3356	if (mask->s_addr!=0xffffffff)
3357		return 1;
3358
3359	return memcmp(subnet->v,address->v,address->l);
3360}
3361
3362#ifdef INET6
3363
3364int
3365ipsecdoi_subnetisaddr_v6( subnet, address )
3366	const vchar_t *subnet;
3367	const vchar_t *address;
3368{
3369	struct in6_addr *mask;
3370	int i;
3371
3372	if (address->l != sizeof(struct in6_addr))
3373		return 1;
3374
3375	if (subnet->l != (sizeof(struct in6_addr)*2))
3376		return 1;
3377
3378	mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
3379
3380	for (i=0; i<16; i++)
3381		if(mask->s6_addr[i]!=0xff)
3382			return 1;
3383
3384	return memcmp(subnet->v,address->v,address->l);
3385}
3386
3387#endif
3388
3389/*
3390 * Check and Compare two IDs
3391 * - specify 0 for exact if wildcards are allowed
3392 * Return value
3393 * =  0 for match
3394 * =  1 for misatch
3395 * = -1 for integrity error
3396 */
3397
3398int
3399ipsecdoi_chkcmpids( idt, ids, exact )
3400	const vchar_t *idt; /* id cmp target */
3401	const vchar_t *ids; /* id cmp source */
3402	int exact;
3403{
3404	struct ipsecdoi_id_b *id_bt;
3405	struct ipsecdoi_id_b *id_bs;
3406	vchar_t ident_t;
3407	vchar_t ident_s;
3408	int result;
3409
3410	/* handle wildcard IDs */
3411
3412	if (idt == NULL || ids == NULL)
3413	{
3414		if( !exact )
3415		{
3416			plog(LLV_DEBUG, LOCATION, NULL,
3417				"check and compare ids : values matched (ANONYMOUS)\n" );
3418			return 0;
3419		}
3420		else
3421		{
3422			plog(LLV_DEBUG, LOCATION, NULL,
3423				"check and compare ids : value mismatch (ANONYMOUS)\n" );
3424			return -1;
3425		}
3426	}
3427
3428	/* make sure the ids are of the same type */
3429
3430	id_bt = (struct ipsecdoi_id_b *) idt->v;
3431	id_bs = (struct ipsecdoi_id_b *) ids->v;
3432
3433	ident_t.v = idt->v + sizeof(*id_bt);
3434	ident_t.l = idt->l - sizeof(*id_bt);
3435	ident_s.v = ids->v + sizeof(*id_bs);
3436	ident_s.l = ids->l - sizeof(*id_bs);
3437
3438	if (id_bs->type != id_bt->type)
3439	{
3440		/*
3441		 * special exception for comparing
3442                 * address to subnet id types when
3443                 * the netmask is address length
3444                 */
3445
3446		if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3447		    (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3448			result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3449			goto cmpid_result;
3450		}
3451
3452		if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3453		    (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3454			result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3455			goto cmpid_result;
3456		}
3457
3458#ifdef INET6
3459		if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3460		    (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3461			result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3462			goto cmpid_result;
3463		}
3464
3465		if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3466		    (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3467			result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3468			goto cmpid_result;
3469		}
3470#endif
3471		plog(LLV_DEBUG, LOCATION, NULL,
3472			"check and compare ids : id type mismatch %s != %s\n",
3473			s_ipsecdoi_ident(id_bs->type),
3474			s_ipsecdoi_ident(id_bt->type));
3475
3476		return 1;
3477	}
3478
3479	if(id_bs->proto_id != id_bt->proto_id){
3480		plog(LLV_DEBUG, LOCATION, NULL,
3481			"check and compare ids : proto_id mismatch %d != %d\n",
3482			id_bs->proto_id, id_bt->proto_id);
3483
3484		return 1;
3485	}
3486
3487	/* compare the ID data. */
3488
3489	switch (id_bt->type) {
3490	        case IPSECDOI_ID_DER_ASN1_DN:
3491        	case IPSECDOI_ID_DER_ASN1_GN:
3492			/* compare asn1 ids */
3493			result = eay_cmp_asn1dn(&ident_t, &ident_s);
3494			goto cmpid_result;
3495
3496		case IPSECDOI_ID_IPV4_ADDR:
3497			/* validate lengths */
3498			if ((ident_t.l != sizeof(struct in_addr))||
3499			    (ident_s.l != sizeof(struct in_addr)))
3500				goto cmpid_invalid;
3501			break;
3502
3503		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3504		case IPSECDOI_ID_IPV4_ADDR_RANGE:
3505			/* validate lengths */
3506			if ((ident_t.l != (sizeof(struct in_addr)*2))||
3507			    (ident_s.l != (sizeof(struct in_addr)*2)))
3508				goto cmpid_invalid;
3509			break;
3510
3511#ifdef INET6
3512		case IPSECDOI_ID_IPV6_ADDR:
3513			/* validate lengths */
3514			if ((ident_t.l != sizeof(struct in6_addr))||
3515			    (ident_s.l != sizeof(struct in6_addr)))
3516				goto cmpid_invalid;
3517			break;
3518
3519		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3520		case IPSECDOI_ID_IPV6_ADDR_RANGE:
3521			/* validate lengths */
3522			if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3523			    (ident_s.l != (sizeof(struct in6_addr)*2)))
3524				goto cmpid_invalid;
3525			break;
3526#endif
3527		case IPSECDOI_ID_FQDN:
3528		case IPSECDOI_ID_USER_FQDN:
3529		case IPSECDOI_ID_KEY_ID:
3530			break;
3531
3532		default:
3533			plog(LLV_ERROR, LOCATION, NULL,
3534				"Unhandled id type %i specified for comparison\n",
3535				id_bt->type);
3536			return -1;
3537	}
3538
3539	/* validate matching data and length */
3540	if (ident_t.l == ident_s.l)
3541		result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3542	else
3543		result = 1;
3544
3545cmpid_result:
3546
3547	/* debug level output */
3548	if(loglevel >= LLV_DEBUG) {
3549		char *idstrt = ipsecdoi_id2str(idt);
3550		char *idstrs = ipsecdoi_id2str(ids);
3551
3552		if (!result)
3553	 		plog(LLV_DEBUG, LOCATION, NULL,
3554				"check and compare ids : values matched (%s)\n",
3555				 s_ipsecdoi_ident(id_bs->type) );
3556		else
3557 			plog(LLV_DEBUG, LOCATION, NULL,
3558				"check and compare ids : value mismatch (%s)\n",
3559				 s_ipsecdoi_ident(id_bs->type));
3560
3561		plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
3562		plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
3563
3564		racoon_free(idstrs);
3565		racoon_free(idstrt);
3566	}
3567
3568	/* return result */
3569	if( !result )
3570		return 0;
3571	else
3572		return 1;
3573
3574cmpid_invalid:
3575
3576	/* id integrity error */
3577	plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
3578		s_ipsecdoi_ident(id_bs->type));
3579	plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
3580	plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
3581
3582	return -1;
3583}
3584
3585/*
3586 * check the following:
3587 * - In main mode with pre-shared key, only address type can be used.
3588 * - if proper type for phase 1 ?
3589 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3590 *   (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3591 * - if ID payload sent from peer is equal to the ID expected by me.
3592 *
3593 * both of "id" and "id_p" should be ID payload without general header,
3594 */
3595int
3596ipsecdoi_checkid1(iph1)
3597	struct ph1handle *iph1;
3598{
3599	struct ipsecdoi_id_b *id_b;
3600	struct sockaddr *sa;
3601	caddr_t sa1, sa2;
3602
3603	if (iph1->id_p == NULL) {
3604		plog(LLV_ERROR, LOCATION, NULL,
3605			"invalid iph1 passed id_p == NULL\n");
3606		return ISAKMP_INTERNAL_ERROR;
3607	}
3608	if (iph1->id_p->l < sizeof(*id_b)) {
3609		plog(LLV_ERROR, LOCATION, NULL,
3610			"invalid value passed as \"ident\" (len=%lu)\n",
3611			(u_long)iph1->id_p->l);
3612		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3613	}
3614
3615	id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3616
3617#ifndef ANDROID_PATCHED
3618	/* In main mode with pre-shared key, only address type can be used. */
3619	if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3620	    iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3621		 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3622		  && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3623			plog(LLV_ERROR, LOCATION, NULL,
3624				"Expecting IP address type in main mode, "
3625				"but %s.\n", s_ipsecdoi_ident(id_b->type));
3626			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3627		}
3628	}
3629#endif
3630
3631	/* if proper type for phase 1 ? */
3632	switch (id_b->type) {
3633	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3634	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3635	case IPSECDOI_ID_IPV4_ADDR_RANGE:
3636	case IPSECDOI_ID_IPV6_ADDR_RANGE:
3637		plog(LLV_WARNING, LOCATION, NULL,
3638			"such ID type %s is not proper.\n",
3639			s_ipsecdoi_ident(id_b->type));
3640		/*FALLTHROUGH*/
3641	}
3642
3643	/* if phase 1 ID payload conformed RFC2407 4.6.2. */
3644	if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3645	    id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3646
3647		if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3648			plog(LLV_WARNING, LOCATION, NULL,
3649				"protocol ID and Port mismatched. "
3650				"proto_id:%d port:%d\n",
3651				id_b->proto_id, ntohs(id_b->port));
3652			/*FALLTHROUGH*/
3653
3654		} else if (id_b->proto_id == IPPROTO_UDP) {
3655			/*
3656			 * copmaring with expecting port.
3657			 * always permit if port is equal to PORT_ISAKMP
3658			 */
3659			if (ntohs(id_b->port) != PORT_ISAKMP) {
3660				u_int16_t port;
3661
3662				port = extract_port(iph1->remote);
3663				if (ntohs(id_b->port) != port) {
3664					plog(LLV_WARNING, LOCATION, NULL,
3665						"port %d expected, but %d\n",
3666						port, ntohs(id_b->port));
3667					/*FALLTHROUGH*/
3668				}
3669			}
3670		}
3671	}
3672
3673	/* compare with the ID if specified. */
3674	if (genlist_next(iph1->rmconf->idvl_p, 0)) {
3675		vchar_t *ident0 = NULL;
3676		vchar_t ident;
3677		struct idspec *id;
3678		struct genlist_entry *gpb;
3679
3680		for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
3681			/* check the type of both IDs */
3682			if (id->idtype != doi2idtype(id_b->type))
3683				continue;  /* ID type mismatch */
3684			if (id->id == 0)
3685				goto matched;
3686
3687			/* compare defined ID with the ID sent by peer. */
3688			if (ident0 != NULL)
3689				vfree(ident0);
3690			ident0 = getidval(id->idtype, id->id);
3691
3692			switch (id->idtype) {
3693			case IDTYPE_ASN1DN:
3694				ident.v = iph1->id_p->v + sizeof(*id_b);
3695				ident.l = iph1->id_p->l - sizeof(*id_b);
3696				if (eay_cmp_asn1dn(ident0, &ident) == 0)
3697					goto matched;
3698				break;
3699			case IDTYPE_ADDRESS:
3700				sa = (struct sockaddr *)ident0->v;
3701				sa2 = (caddr_t)(id_b + 1);
3702				switch (sa->sa_family) {
3703				case AF_INET:
3704					if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
3705						continue;  /* ID value mismatch */
3706					sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
3707					if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
3708						goto matched;
3709					break;
3710#ifdef INET6
3711				case AF_INET6:
3712					if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
3713						continue;  /* ID value mismatch */
3714					sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
3715					if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
3716						goto matched;
3717					break;
3718#endif
3719				default:
3720					break;
3721				}
3722				break;
3723			default:
3724				if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
3725					goto matched;
3726				break;
3727			}
3728		}
3729		if (ident0 != NULL) {
3730			vfree(ident0);
3731			ident0 = NULL;
3732		}
3733		plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
3734		if (iph1->rmconf->verify_identifier)
3735			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3736matched: /* ID value match */
3737		if (ident0 != NULL)
3738			vfree(ident0);
3739	}
3740
3741	return 0;
3742}
3743
3744/*
3745 * create ID payload for phase 1 and set into iph1->id.
3746 * NOT INCLUDING isakmp general header.
3747 * see, RFC2407 4.6.2.1
3748 */
3749int
3750ipsecdoi_setid1(iph1)
3751	struct ph1handle *iph1;
3752{
3753	vchar_t *ret = NULL;
3754	struct ipsecdoi_id_b id_b;
3755	vchar_t *ident = NULL;
3756	struct sockaddr *ipid = NULL;
3757
3758	/* init */
3759	id_b.proto_id = 0;
3760	id_b.port = 0;
3761	ident = NULL;
3762
3763	switch (iph1->rmconf->idvtype) {
3764	case IDTYPE_FQDN:
3765		id_b.type = IPSECDOI_ID_FQDN;
3766		ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3767		break;
3768	case IDTYPE_USERFQDN:
3769		id_b.type = IPSECDOI_ID_USER_FQDN;
3770		ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3771		break;
3772	case IDTYPE_KEYID:
3773		id_b.type = IPSECDOI_ID_KEY_ID;
3774		ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3775		break;
3776	case IDTYPE_ASN1DN:
3777		id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3778		if (iph1->rmconf->idv) {
3779			/* XXX it must be encoded to asn1dn. */
3780			ident = vdup(iph1->rmconf->idv);
3781		} else {
3782			if (oakley_getmycert(iph1) < 0) {
3783				plog(LLV_ERROR, LOCATION, NULL,
3784					"failed to get own CERT.\n");
3785				goto err;
3786			}
3787			ident = eay_get_x509asn1subjectname(&iph1->cert->cert);
3788		}
3789		break;
3790	case IDTYPE_ADDRESS:
3791		/*
3792		 * if the value of the id type was set by the configuration
3793		 * file, then use it.  otherwise the value is get from local
3794		 * ip address by using ike negotiation.
3795		 */
3796		if (iph1->rmconf->idv)
3797			ipid = (struct sockaddr *)iph1->rmconf->idv->v;
3798		/*FALLTHROUGH*/
3799	default:
3800	    {
3801		int l;
3802		caddr_t p;
3803
3804		if (ipid == NULL)
3805			ipid = iph1->local;
3806
3807		/* use IP address */
3808		switch (ipid->sa_family) {
3809		case AF_INET:
3810			id_b.type = IPSECDOI_ID_IPV4_ADDR;
3811			l = sizeof(struct in_addr);
3812			p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3813			break;
3814#ifdef INET6
3815		case AF_INET6:
3816			id_b.type = IPSECDOI_ID_IPV6_ADDR;
3817			l = sizeof(struct in6_addr);
3818			p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3819			break;
3820#endif
3821		default:
3822			plog(LLV_ERROR, LOCATION, NULL,
3823				"invalid address family.\n");
3824			goto err;
3825		}
3826		id_b.proto_id = IPPROTO_UDP;
3827		id_b.port = htons(PORT_ISAKMP);
3828		ident = vmalloc(l);
3829		if (!ident) {
3830			plog(LLV_ERROR, LOCATION, NULL,
3831				"failed to get ID buffer.\n");
3832			return 0;
3833		}
3834		memcpy(ident->v, p, ident->l);
3835	    }
3836	}
3837	if (!ident) {
3838		plog(LLV_ERROR, LOCATION, NULL,
3839			"failed to get ID buffer.\n");
3840		return 0;
3841	}
3842
3843	ret = vmalloc(sizeof(id_b) + ident->l);
3844	if (ret == NULL) {
3845		plog(LLV_ERROR, LOCATION, NULL,
3846			"failed to get ID buffer.\n");
3847		goto err;
3848	}
3849
3850	memcpy(ret->v, &id_b, sizeof(id_b));
3851	memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3852
3853	iph1->id = ret;
3854
3855	plog(LLV_DEBUG, LOCATION, NULL,
3856		"use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3857	if (ident)
3858		vfree(ident);
3859	return 0;
3860
3861err:
3862	if (ident)
3863		vfree(ident);
3864	plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3865	return -1;
3866}
3867
3868static vchar_t *
3869getidval(type, val)
3870	int type;
3871	vchar_t *val;
3872{
3873	vchar_t *new = NULL;
3874
3875	if (val)
3876		new = vdup(val);
3877	else if (lcconf->ident[type])
3878		new = vdup(lcconf->ident[type]);
3879
3880	return new;
3881}
3882
3883/* it's only called by cfparse.y. */
3884int
3885set_identifier(vpp, type, value)
3886	vchar_t **vpp, *value;
3887	int type;
3888{
3889	return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
3890}
3891
3892int
3893set_identifier_qual(vpp, type, value, qual)
3894	vchar_t **vpp, *value;
3895	int type;
3896	int qual;
3897{
3898	vchar_t *new = NULL;
3899
3900	/* simply return if value is null. */
3901	if (!value){
3902		if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
3903			plog(LLV_ERROR, LOCATION, NULL,
3904				 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3905			return -1;
3906		}
3907		return 0;
3908	}
3909
3910	switch (type) {
3911	case IDTYPE_FQDN:
3912	case IDTYPE_USERFQDN:
3913		if(value->l <= 1){
3914			plog(LLV_ERROR, LOCATION, NULL,
3915				 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3916			return -1;
3917		}
3918		/* length is adjusted since QUOTEDSTRING teminates NULL. */
3919		new = vmalloc(value->l - 1);
3920		if (new == NULL)
3921			return -1;
3922		memcpy(new->v, value->v, new->l);
3923		break;
3924	case IDTYPE_KEYID:
3925		/*
3926		 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3927		 * to use a file for backward compatibility sake.
3928		 */
3929		switch(qual) {
3930		case IDQUAL_FILE:
3931		case IDQUAL_UNSPEC: {
3932			FILE *fp;
3933			char b[512];
3934			int tlen, len;
3935
3936			fp = fopen(value->v, "r");
3937			if (fp == NULL) {
3938				plog(LLV_ERROR, LOCATION, NULL,
3939					"can not open %s\n", value->v);
3940				return -1;
3941			}
3942			tlen = 0;
3943			while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3944				new = vrealloc(new, tlen + len);
3945				if (!new) {
3946					fclose(fp);
3947					return -1;
3948				}
3949				memcpy(new->v + tlen, b, len);
3950				tlen += len;
3951			}
3952			break;
3953		}
3954
3955		case IDQUAL_TAG:
3956			new = vmalloc(value->l - 1);
3957			if (new == NULL) {
3958				plog(LLV_ERROR, LOCATION, NULL,
3959					"can not allocate memory");
3960				return -1;
3961			}
3962			memcpy(new->v, value->v, new->l);
3963			break;
3964
3965		default:
3966			plog(LLV_ERROR, LOCATION, NULL,
3967				"unknown qualifier");
3968			return -1;
3969		}
3970		break;
3971
3972	case IDTYPE_ADDRESS: {
3973		struct sockaddr *sa;
3974
3975		/* length is adjusted since QUOTEDSTRING teminates NULL. */
3976		if (value->l == 0)
3977			break;
3978
3979		sa = str2saddr(value->v, NULL);
3980		if (sa == NULL) {
3981			plog(LLV_ERROR, LOCATION, NULL,
3982				"invalid ip address %s\n", value->v);
3983			return -1;
3984		}
3985
3986		new = vmalloc(sysdep_sa_len(sa));
3987		if (new == NULL) {
3988			racoon_free(sa);
3989			return -1;
3990		}
3991		memcpy(new->v, sa, new->l);
3992		racoon_free(sa);
3993		break;
3994	}
3995	case IDTYPE_ASN1DN:
3996		if (value->v[0] == '~')
3997			/* Hex-encoded ASN1 strings */
3998			new = eay_hex2asn1dn(value->v + 1, - 1);
3999		else
4000			/* DN encoded strings */
4001			new = eay_str2asn1dn(value->v, value->l - 1);
4002
4003		if (new == NULL)
4004			return -1;
4005
4006		if (loglevel >= LLV_DEBUG) {
4007			X509_NAME *xn;
4008			BIO *bio;
4009			unsigned char *ptr = (unsigned char *) new->v, *buf;
4010			size_t len;
4011			char save;
4012
4013			xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
4014			bio = BIO_new(BIO_s_mem());
4015
4016			X509_NAME_print_ex(bio, xn, 0, 0);
4017			len = BIO_get_mem_data(bio, &ptr);
4018			save = ptr[len];
4019			ptr[len] = 0;
4020			plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
4021			ptr[len] = save;
4022			X509_NAME_free(xn);
4023			BIO_free(bio);
4024		}
4025
4026		break;
4027	}
4028
4029	*vpp = new;
4030
4031	return 0;
4032}
4033
4034/*
4035 * create ID payload for phase 2, and set into iph2->id and id_p.  There are
4036 * NOT INCLUDING isakmp general header.
4037 * this function is for initiator.  responder will get to copy from payload.
4038 * responder ID type is always address type.
4039 * see, RFC2407 4.6.2.1
4040 */
4041int
4042ipsecdoi_setid2(iph2)
4043	struct ph2handle *iph2;
4044{
4045	struct secpolicy *sp;
4046
4047	/* check there is phase 2 handler ? */
4048	sp = getspbyspid(iph2->spid);
4049	if (sp == NULL) {
4050		plog(LLV_ERROR, LOCATION, NULL,
4051			"no policy found for spid:%u.\n", iph2->spid);
4052		return -1;
4053	}
4054
4055	iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
4056					sp->spidx.prefs, sp->spidx.ul_proto);
4057	if (iph2->id == NULL) {
4058		plog(LLV_ERROR, LOCATION, NULL,
4059			"failed to get ID for %s\n",
4060			spidx2str(&sp->spidx));
4061		return -1;
4062	}
4063	plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
4064		s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
4065
4066	/* remote side */
4067	iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
4068				sp->spidx.prefd, sp->spidx.ul_proto);
4069	if (iph2->id_p == NULL) {
4070		plog(LLV_ERROR, LOCATION, NULL,
4071			"failed to get ID for %s\n",
4072			spidx2str(&sp->spidx));
4073		VPTRINIT(iph2->id);
4074		return -1;
4075	}
4076	plog(LLV_DEBUG, LOCATION, NULL,
4077		"use remote ID type %s\n",
4078		s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
4079
4080	return 0;
4081}
4082
4083/*
4084 * set address type of ID.
4085 * NOT INCLUDING general header.
4086 */
4087vchar_t *
4088ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
4089	struct sockaddr *saddr;
4090	u_int prefixlen;
4091	u_int ul_proto;
4092{
4093	vchar_t *new;
4094	int type, len1, len2;
4095	caddr_t sa;
4096	u_short port;
4097
4098	/*
4099	 * Q. When type is SUBNET, is it allowed to be ::1/128.
4100	 * A. Yes. (consensus at bake-off)
4101	 */
4102	switch (saddr->sa_family) {
4103	case AF_INET:
4104		len1 = sizeof(struct in_addr);
4105		if (prefixlen == (sizeof(struct in_addr) << 3)) {
4106			type = IPSECDOI_ID_IPV4_ADDR;
4107			len2 = 0;
4108		} else {
4109			type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
4110			len2 = sizeof(struct in_addr);
4111		}
4112		sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
4113		port = ((struct sockaddr_in *)(saddr))->sin_port;
4114		break;
4115#ifdef INET6
4116	case AF_INET6:
4117		len1 = sizeof(struct in6_addr);
4118		if (prefixlen == (sizeof(struct in6_addr) << 3)) {
4119			type = IPSECDOI_ID_IPV6_ADDR;
4120			len2 = 0;
4121		} else {
4122			type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
4123			len2 = sizeof(struct in6_addr);
4124		}
4125		sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
4126		port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
4127		break;
4128#endif
4129	default:
4130		plog(LLV_ERROR, LOCATION, NULL,
4131			"invalid family: %d.\n", saddr->sa_family);
4132		return NULL;
4133	}
4134
4135	/* get ID buffer */
4136	new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4137	if (new == NULL) {
4138		plog(LLV_ERROR, LOCATION, NULL,
4139			"failed to get ID buffer.\n");
4140		return NULL;
4141	}
4142
4143	memset(new->v, 0, new->l);
4144
4145	/* set the part of header. */
4146	((struct ipsecdoi_id_b *)new->v)->type = type;
4147
4148	/* set ul_proto and port */
4149	/*
4150	 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4151	 * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
4152	 */
4153	((struct ipsecdoi_id_b *)new->v)->proto_id =
4154		ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4155	((struct ipsecdoi_id_b *)new->v)->port =
4156		port == IPSEC_PORT_ANY ? 0 : port;
4157	memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
4158
4159	/* set address */
4160
4161	/* set prefix */
4162	if (len2) {
4163		u_char *p = (unsigned char *) new->v +
4164			sizeof(struct ipsecdoi_id_b) + len1;
4165		u_int bits = prefixlen;
4166
4167		while (bits >= 8) {
4168			*p++ = 0xff;
4169			bits -= 8;
4170		}
4171
4172		if (bits > 0)
4173			*p = ~((1 << (8 - bits)) - 1);
4174	}
4175
4176	return new;
4177}
4178
4179vchar_t *
4180ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
4181	struct sockaddr *laddr, *haddr;
4182	u_int ul_proto;
4183{
4184	vchar_t *new;
4185	int type, len1, len2;
4186	u_short port;
4187
4188	if (laddr->sa_family != haddr->sa_family) {
4189	    plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
4190	    return NULL;
4191	}
4192
4193	switch (laddr->sa_family) {
4194	case AF_INET:
4195	    type = IPSECDOI_ID_IPV4_ADDR_RANGE;
4196	    len1 = sizeof(struct in_addr);
4197	    len2 = sizeof(struct in_addr);
4198	    break;
4199#ifdef INET6
4200	case AF_INET6:
4201		type = IPSECDOI_ID_IPV6_ADDR_RANGE;
4202		len1 = sizeof(struct in6_addr);
4203		len2 = sizeof(struct in6_addr);
4204		break;
4205#endif
4206	default:
4207		plog(LLV_ERROR, LOCATION, NULL,
4208			"invalid family: %d.\n", laddr->sa_family);
4209		return NULL;
4210	}
4211
4212	/* get ID buffer */
4213	new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4214	if (new == NULL) {
4215		plog(LLV_ERROR, LOCATION, NULL,
4216			"failed to get ID buffer.\n");
4217		return NULL;
4218	}
4219
4220	memset(new->v, 0, new->l);
4221	/* set the part of header. */
4222	((struct ipsecdoi_id_b *)new->v)->type = type;
4223
4224	/* set ul_proto and port */
4225	/*
4226	 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4227	 * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
4228	 */
4229	((struct ipsecdoi_id_b *)new->v)->proto_id =
4230		ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4231	port = ((struct sockaddr_in *)(laddr))->sin_port;
4232	((struct ipsecdoi_id_b *)new->v)->port =
4233		port == IPSEC_PORT_ANY ? 0 : port;
4234	memcpy(new->v + sizeof(struct ipsecdoi_id_b),
4235	       (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
4236	       len1);
4237	memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
4238	       (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
4239	       len2);
4240	return new;
4241}
4242
4243
4244/*
4245 * create sockaddr structure from ID payload (buf).
4246 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4247 * see, RFC2407 4.6.2.1
4248 */
4249int
4250ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
4251	vchar_t *buf;
4252	struct sockaddr *saddr;
4253	u_int8_t *prefixlen;
4254	u_int16_t *ul_proto;
4255{
4256	struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
4257	u_int plen = 0;
4258
4259	/*
4260	 * When a ID payload of subnet type with a IP address of full bit
4261	 * masked, it has to be processed as host address.
4262	 * e.g. below 2 type are same.
4263	 *      type = ipv6 subnet, data = 2001::1/128
4264	 *      type = ipv6 address, data = 2001::1
4265	 */
4266	switch (id_b->type) {
4267	case IPSECDOI_ID_IPV4_ADDR:
4268	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4269#ifndef __linux__
4270		saddr->sa_len = sizeof(struct sockaddr_in);
4271#endif
4272		saddr->sa_family = AF_INET;
4273		((struct sockaddr_in *)saddr)->sin_port =
4274			(id_b->port == 0
4275				? IPSEC_PORT_ANY
4276				: id_b->port);		/* see sockaddr2id() */
4277		memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
4278			buf->v + sizeof(*id_b), sizeof(struct in_addr));
4279		break;
4280#ifdef INET6
4281	case IPSECDOI_ID_IPV6_ADDR:
4282	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4283#ifndef __linux__
4284		saddr->sa_len = sizeof(struct sockaddr_in6);
4285#endif
4286		saddr->sa_family = AF_INET6;
4287		((struct sockaddr_in6 *)saddr)->sin6_port =
4288			(id_b->port == 0
4289				? IPSEC_PORT_ANY
4290				: id_b->port);		/* see sockaddr2id() */
4291		memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
4292			buf->v + sizeof(*id_b), sizeof(struct in6_addr));
4293		break;
4294#endif
4295	default:
4296		plog(LLV_ERROR, LOCATION, NULL,
4297			"unsupported ID type %d\n", id_b->type);
4298		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
4299	}
4300
4301	/* get prefix length */
4302	switch (id_b->type) {
4303	case IPSECDOI_ID_IPV4_ADDR:
4304		plen = sizeof(struct in_addr) << 3;
4305		break;
4306#ifdef INET6
4307	case IPSECDOI_ID_IPV6_ADDR:
4308		plen = sizeof(struct in6_addr) << 3;
4309		break;
4310#endif
4311	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4312#ifdef INET6
4313	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4314#endif
4315	    {
4316		u_char *p;
4317		u_int max;
4318		int alen = sizeof(struct in_addr);
4319
4320		switch (id_b->type) {
4321		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4322			alen = sizeof(struct in_addr);
4323			break;
4324#ifdef INET6
4325		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4326			alen = sizeof(struct in6_addr);
4327			break;
4328#endif
4329		}
4330
4331		/* sanity check */
4332		if (buf->l < alen)
4333			return ISAKMP_INTERNAL_ERROR;
4334
4335		/* get subnet mask length */
4336		plen = 0;
4337		max = alen <<3;
4338
4339		p = (unsigned char *) buf->v
4340			+ sizeof(struct ipsecdoi_id_b)
4341			+ alen;
4342
4343		for (; *p == 0xff; p++) {
4344			plen += 8;
4345			if (plen >= max)
4346				break;
4347		}
4348
4349		if (plen < max) {
4350			u_int l = 0;
4351			u_char b = ~(*p);
4352
4353			while (b) {
4354				b >>= 1;
4355				l++;
4356			}
4357
4358			l = 8 - l;
4359			plen += l;
4360		}
4361	    }
4362		break;
4363	}
4364
4365	*prefixlen = plen;
4366	*ul_proto = id_b->proto_id == 0
4367				? IPSEC_ULPROTO_ANY
4368				: id_b->proto_id;	/* see sockaddr2id() */
4369
4370	return 0;
4371}
4372
4373/*
4374 * make printable string from ID payload except of general header.
4375 */
4376char *
4377ipsecdoi_id2str(id)
4378	const vchar_t *id;
4379{
4380#define BUFLEN 512
4381	char * ret = NULL;
4382	int len = 0;
4383	char *dat;
4384	static char buf[BUFLEN];
4385	struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
4386	struct sockaddr_storage saddr_storage;
4387	struct sockaddr        *saddr;
4388	struct sockaddr_in     *saddr_in;
4389	struct sockaddr_in6    *saddr_in6;
4390	u_int plen = 0;
4391
4392	saddr     = (struct sockaddr *)&saddr_storage;
4393	saddr_in  = (struct sockaddr_in *)&saddr_storage;
4394	saddr_in6 = (struct sockaddr_in6 *)&saddr_storage;
4395
4396
4397	switch (id_b->type) {
4398	case IPSECDOI_ID_IPV4_ADDR:
4399	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4400	case IPSECDOI_ID_IPV4_ADDR_RANGE:
4401
4402#ifndef __linux__
4403		saddr->sa_len = sizeof(struct sockaddr_in);
4404#endif
4405		saddr->sa_family = AF_INET;
4406
4407		saddr_in->sin_port = IPSEC_PORT_ANY;
4408		memcpy(&saddr_in->sin_addr,
4409			id->v + sizeof(*id_b), sizeof(struct in_addr));
4410		break;
4411#ifdef INET6
4412	case IPSECDOI_ID_IPV6_ADDR:
4413	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4414	case IPSECDOI_ID_IPV6_ADDR_RANGE:
4415
4416#ifndef __linux__
4417		saddr->sa_len = sizeof(struct sockaddr_in6);
4418#endif
4419		saddr->sa_family = AF_INET6;
4420
4421		saddr_in6->sin6_port = IPSEC_PORT_ANY;
4422		memcpy(&saddr_in6->sin6_addr,
4423			id->v + sizeof(*id_b), sizeof(struct in6_addr));
4424		saddr_in6->sin6_scope_id =
4425			(IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
4426				? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4427				: 0);
4428		break;
4429#endif
4430	}
4431
4432	switch (id_b->type) {
4433	case IPSECDOI_ID_IPV4_ADDR:
4434#ifdef INET6
4435	case IPSECDOI_ID_IPV6_ADDR:
4436#endif
4437		len = snprintf( buf, BUFLEN, "%s", saddrwop2str(saddr));
4438		break;
4439
4440	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4441#ifdef INET6
4442	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4443#endif
4444	    {
4445		u_char *p;
4446		u_int max;
4447		int alen = sizeof(struct in_addr);
4448
4449		switch (id_b->type) {
4450		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4451			alen = sizeof(struct in_addr);
4452			break;
4453#ifdef INET6
4454		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4455			alen = sizeof(struct in6_addr);
4456			break;
4457#endif
4458		}
4459
4460		/* sanity check */
4461		if (id->l < alen) {
4462			len = 0;
4463			break;
4464		}
4465
4466		/* get subnet mask length */
4467		plen = 0;
4468		max = alen <<3;
4469
4470		p = (unsigned char *) id->v
4471			+ sizeof(struct ipsecdoi_id_b)
4472			+ alen;
4473
4474		for (; *p == 0xff; p++) {
4475			plen += 8;
4476			if (plen >= max)
4477				break;
4478		}
4479
4480		if (plen < max) {
4481			u_int l = 0;
4482			u_char b = ~(*p);
4483
4484			while (b) {
4485				b >>= 1;
4486				l++;
4487			}
4488
4489			l = 8 - l;
4490			plen += l;
4491		}
4492
4493		len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(saddr), plen);
4494	    }
4495		break;
4496
4497	case IPSECDOI_ID_IPV4_ADDR_RANGE:
4498
4499		len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
4500
4501#ifndef __linux__
4502		saddr->sa_len = sizeof(struct sockaddr_in);
4503#endif
4504		saddr->sa_family = AF_INET;
4505		saddr_in->sin_port = IPSEC_PORT_ANY;
4506		memcpy(&saddr_in->sin_addr,
4507			id->v + sizeof(*id_b) + sizeof(struct in_addr),
4508			sizeof(struct in_addr));
4509
4510		len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
4511
4512		break;
4513
4514#ifdef INET6
4515	case IPSECDOI_ID_IPV6_ADDR_RANGE:
4516
4517		len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
4518
4519#ifndef __linux__
4520		saddr->sa_len = sizeof(struct sockaddr_in6);
4521#endif
4522		saddr->sa_family = AF_INET6;
4523		saddr_in6->sin6_port = IPSEC_PORT_ANY;
4524		memcpy(&saddr_in6->sin6_addr,
4525			id->v + sizeof(*id_b) + sizeof(struct in6_addr),
4526			sizeof(struct in6_addr));
4527		saddr_in6->sin6_scope_id =
4528			(IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
4529				? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4530				: 0);
4531
4532		len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
4533
4534		break;
4535#endif
4536
4537	case IPSECDOI_ID_FQDN:
4538	case IPSECDOI_ID_USER_FQDN:
4539		len = id->l - sizeof(*id_b);
4540		if (len > BUFLEN)
4541			len = BUFLEN;
4542		memcpy(buf, id->v + sizeof(*id_b), len);
4543		break;
4544
4545	case IPSECDOI_ID_DER_ASN1_DN:
4546	case IPSECDOI_ID_DER_ASN1_GN:
4547	{
4548		X509_NAME *xn = NULL;
4549
4550		dat = id->v + sizeof(*id_b);
4551		len = id->l - sizeof(*id_b);
4552
4553		if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
4554			BIO *bio = BIO_new(BIO_s_mem());
4555			X509_NAME_print_ex(bio, xn, 0, 0);
4556			len = BIO_get_mem_data(bio, &dat);
4557			if (len > BUFLEN)
4558				len = BUFLEN;
4559			memcpy(buf,dat,len);
4560			BIO_free(bio);
4561			X509_NAME_free(xn);
4562		} else {
4563			plog(LLV_ERROR, LOCATION, NULL,
4564				"unable to extract asn1dn from id\n");
4565
4566			len = sprintf(buf, "<ASN1-DN>");
4567		}
4568
4569		break;
4570	}
4571
4572	/* currently unhandled id types */
4573	case IPSECDOI_ID_KEY_ID:
4574		len = sprintf( buf, "<KEY-ID>");
4575		break;
4576
4577	default:
4578		plog(LLV_ERROR, LOCATION, NULL,
4579			"unknown ID type %d\n", id_b->type);
4580	}
4581
4582	if (!len)
4583		len = sprintf( buf, "<?>");
4584
4585	ret = racoon_malloc(len+1);
4586	if (ret != NULL) {
4587		memcpy(ret,buf,len);
4588		ret[len]=0;
4589	}
4590
4591	return ret;
4592}
4593
4594/*
4595 * set IPsec data attributes into a proposal.
4596 * NOTE: MUST called per a transform.
4597 */
4598int
4599ipsecdoi_t2satrns(t, pp, pr, tr)
4600	struct isakmp_pl_t *t;
4601	struct saprop *pp;
4602	struct saproto *pr;
4603	struct satrns *tr;
4604{
4605	struct isakmp_data *d, *prev;
4606	int flag, type;
4607	int error = -1;
4608	int life_t;
4609	int tlen;
4610
4611	tr->trns_no = t->t_no;
4612	tr->trns_id = t->t_id;
4613
4614	tlen = ntohs(t->h.len) - sizeof(*t);
4615	prev = (struct isakmp_data *)NULL;
4616	d = (struct isakmp_data *)(t + 1);
4617
4618	/* default */
4619	life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4620	pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
4621	pp->lifebyte = 0;
4622	tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
4623
4624	while (tlen > 0) {
4625
4626		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
4627		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
4628
4629		plog(LLV_DEBUG, LOCATION, NULL,
4630			"type=%s, flag=0x%04x, lorv=%s\n",
4631			s_ipsecdoi_attr(type), flag,
4632			s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
4633
4634		switch (type) {
4635		case IPSECDOI_ATTR_SA_LD_TYPE:
4636		{
4637			int type = ntohs(d->lorv);
4638			switch (type) {
4639			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4640			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4641				life_t = type;
4642				break;
4643			default:
4644				plog(LLV_WARNING, LOCATION, NULL,
4645					"invalid life duration type. "
4646					"use default\n");
4647				life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4648				break;
4649			}
4650			break;
4651		}
4652		case IPSECDOI_ATTR_SA_LD:
4653			if (prev == NULL
4654			 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
4655					IPSECDOI_ATTR_SA_LD_TYPE) {
4656				plog(LLV_ERROR, LOCATION, NULL,
4657				    "life duration must follow ltype\n");
4658				break;
4659			}
4660
4661		    {
4662			u_int32_t t;
4663			vchar_t *ld_buf = NULL;
4664
4665			if (flag) {
4666				/* i.e. ISAKMP_GEN_TV */
4667				ld_buf = vmalloc(sizeof(d->lorv));
4668				if (ld_buf == NULL) {
4669					plog(LLV_ERROR, LOCATION, NULL,
4670					    "failed to get LD buffer.\n");
4671					goto end;
4672				}
4673				memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
4674			} else {
4675				int len = ntohs(d->lorv);
4676				/* i.e. ISAKMP_GEN_TLV */
4677				ld_buf = vmalloc(len);
4678				if (ld_buf == NULL) {
4679					plog(LLV_ERROR, LOCATION, NULL,
4680					    "failed to get LD buffer.\n");
4681					goto end;
4682				}
4683				memcpy(ld_buf->v, d + 1, len);
4684			}
4685			switch (life_t) {
4686			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4687				t = ipsecdoi_set_ld(ld_buf);
4688				vfree(ld_buf);
4689				if (t == 0) {
4690					plog(LLV_ERROR, LOCATION, NULL,
4691						"invalid life duration.\n");
4692					goto end;
4693				}
4694				/* lifetime must be equal in a proposal. */
4695				if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
4696					pp->lifetime = t;
4697				else if (pp->lifetime != t) {
4698					plog(LLV_ERROR, LOCATION, NULL,
4699						"lifetime mismatched "
4700						"in a proposal, "
4701						"prev:%ld curr:%u.\n",
4702						(long)pp->lifetime, t);
4703					goto end;
4704				}
4705				break;
4706			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4707				t = ipsecdoi_set_ld(ld_buf);
4708				vfree(ld_buf);
4709				if (t == 0) {
4710					plog(LLV_ERROR, LOCATION, NULL,
4711						"invalid life duration.\n");
4712					goto end;
4713				}
4714				/* lifebyte must be equal in a proposal. */
4715				if (pp->lifebyte == 0)
4716					pp->lifebyte = t;
4717				else if (pp->lifebyte != t) {
4718					plog(LLV_ERROR, LOCATION, NULL,
4719						"lifebyte mismatched "
4720						"in a proposal, "
4721						"prev:%d curr:%u.\n",
4722						pp->lifebyte, t);
4723					goto end;
4724				}
4725				break;
4726			default:
4727				vfree(ld_buf);
4728				plog(LLV_ERROR, LOCATION, NULL,
4729					"invalid life type: %d\n", life_t);
4730				goto end;
4731			}
4732		    }
4733			break;
4734
4735		case IPSECDOI_ATTR_GRP_DESC:
4736			/*
4737			 * RFC2407: 4.5 IPSEC Security Association Attributes
4738			 *   Specifies the Oakley Group to be used in a PFS QM
4739			 *   negotiation.  For a list of supported values, see
4740			 *   Appendix A of [IKE].
4741			 */
4742			if (pp->pfs_group == 0)
4743				pp->pfs_group = (u_int16_t)ntohs(d->lorv);
4744			else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
4745				plog(LLV_ERROR, LOCATION, NULL,
4746					"pfs_group mismatched "
4747					"in a proposal.\n");
4748				goto end;
4749			}
4750			break;
4751
4752		case IPSECDOI_ATTR_ENC_MODE:
4753			if (pr->encmode &&
4754			    pr->encmode != (u_int16_t)ntohs(d->lorv)) {
4755				plog(LLV_ERROR, LOCATION, NULL,
4756					"multiple encmode exist "
4757					"in a transform.\n");
4758				goto end;
4759			}
4760			pr->encmode = (u_int16_t)ntohs(d->lorv);
4761			break;
4762
4763		case IPSECDOI_ATTR_AUTH:
4764			if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
4765				plog(LLV_ERROR, LOCATION, NULL,
4766					"multiple authtype exist "
4767					"in a transform.\n");
4768				goto end;
4769			}
4770			tr->authtype = (u_int16_t)ntohs(d->lorv);
4771			break;
4772
4773		case IPSECDOI_ATTR_KEY_LENGTH:
4774			if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
4775				plog(LLV_ERROR, LOCATION, NULL,
4776					"key length defined but not ESP");
4777				goto end;
4778			}
4779			tr->encklen = ntohs(d->lorv);
4780			break;
4781#ifdef HAVE_SECCTX
4782		case IPSECDOI_ATTR_SECCTX:
4783		{
4784			int len = ntohs(d->lorv);
4785			memcpy(&pp->sctx, d + 1, len);
4786			pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
4787			break;
4788		}
4789#endif /* HAVE_SECCTX */
4790		case IPSECDOI_ATTR_KEY_ROUNDS:
4791		case IPSECDOI_ATTR_COMP_DICT_SIZE:
4792		case IPSECDOI_ATTR_COMP_PRIVALG:
4793		default:
4794			break;
4795		}
4796
4797		prev = d;
4798		if (flag) {
4799			tlen -= sizeof(*d);
4800			d = (struct isakmp_data *)((char *)d + sizeof(*d));
4801		} else {
4802			tlen -= (sizeof(*d) + ntohs(d->lorv));
4803			d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
4804		}
4805	}
4806
4807	error = 0;
4808end:
4809	return error;
4810}
4811
4812int
4813ipsecdoi_authalg2trnsid(alg)
4814	int alg;
4815{
4816	switch (alg) {
4817        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
4818		return IPSECDOI_AH_MD5;
4819        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
4820		return IPSECDOI_AH_SHA;
4821	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
4822		return IPSECDOI_AH_SHA256;
4823	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
4824		return IPSECDOI_AH_SHA384;
4825	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
4826		return IPSECDOI_AH_SHA512;
4827        case IPSECDOI_ATTR_AUTH_DES_MAC:
4828		return IPSECDOI_AH_DES;
4829	case IPSECDOI_ATTR_AUTH_KPDK:
4830		return IPSECDOI_AH_MD5;	/* XXX */
4831	default:
4832		plog(LLV_ERROR, LOCATION, NULL,
4833			"invalid authentication algorithm:%d\n", alg);
4834	}
4835	return -1;
4836}
4837
4838#ifdef HAVE_GSSAPI
4839struct isakmpsa *
4840fixup_initiator_sa(match, received)
4841	struct isakmpsa *match, *received;
4842{
4843	if (received->gssid != NULL)
4844		match->gssid = vdup(received->gssid);
4845
4846	return match;
4847}
4848#endif
4849
4850static int rm_idtype2doi[] = {
4851	255,				/* IDTYPE_UNDEFINED, 0 */
4852	IPSECDOI_ID_FQDN,		/* IDTYPE_FQDN, 1 */
4853	IPSECDOI_ID_USER_FQDN,		/* IDTYPE_USERFQDN, 2 */
4854	IPSECDOI_ID_KEY_ID,		/* IDTYPE_KEYID, 3 */
4855	255,    /*			   IDTYPE_ADDRESS, 4
4856		 * it expands into 4 types by another function. */
4857	IPSECDOI_ID_DER_ASN1_DN,	/* IDTYPE_ASN1DN, 5 */
4858};
4859
4860/*
4861 * convert idtype to DOI value.
4862 * OUT	255  : NG
4863 *	other: converted.
4864 */
4865int
4866idtype2doi(idtype)
4867	int idtype;
4868{
4869	if (ARRAYLEN(rm_idtype2doi) > idtype)
4870		return rm_idtype2doi[idtype];
4871	return 255;
4872}
4873
4874int
4875doi2idtype(doi)
4876	int doi;
4877{
4878	switch(doi) {
4879	case IPSECDOI_ID_FQDN:
4880		return(IDTYPE_FQDN);
4881	case IPSECDOI_ID_USER_FQDN:
4882		return(IDTYPE_USERFQDN);
4883	case IPSECDOI_ID_KEY_ID:
4884		return(IDTYPE_KEYID);
4885	case IPSECDOI_ID_DER_ASN1_DN:
4886		return(IDTYPE_ASN1DN);
4887	case IPSECDOI_ID_IPV4_ADDR:
4888	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4889	case IPSECDOI_ID_IPV6_ADDR:
4890	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4891		return(IDTYPE_ADDRESS);
4892	default:
4893		plog(LLV_WARNING, LOCATION, NULL,
4894			"Inproper idtype:%s in this function.\n",
4895			s_ipsecdoi_ident(doi));
4896		return(IDTYPE_ADDRESS);	/* XXX */
4897	}
4898	/*NOTREACHED*/
4899}
4900
4901#ifdef ENABLE_HYBRID
4902static int
4903switch_authmethod(authmethod)
4904	int authmethod;
4905{
4906	switch(authmethod) {
4907	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
4908		authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
4909		break;
4910	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
4911		authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
4912		break;
4913	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
4914		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
4915		break;
4916	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
4917		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
4918		break;
4919	/* Those are not implemented */
4920	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
4921		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
4922		break;
4923	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
4924		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
4925		break;
4926	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
4927		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
4928		break;
4929	default:
4930		break;
4931	}
4932
4933	return authmethod;
4934}
4935#endif
4936