1/*	$NetBSD: isakmp_ident.c,v 1.6 2006/10/02 21:41:59 manu Exp $	*/
2
3/* Id: isakmp_ident.c,v 1.21 2006/04/06 16:46:08 manubsd 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/* Identity Protecion Exchange (Main Mode) */
35
36#include "config.h"
37
38#include <sys/types.h>
39#include <sys/param.h>
40
41#include <stdlib.h>
42#include <stdio.h>
43#include <string.h>
44#include <errno.h>
45#if TIME_WITH_SYS_TIME
46# include <sys/time.h>
47# include <time.h>
48#else
49# if HAVE_SYS_TIME_H
50#  include <sys/time.h>
51# else
52#  include <time.h>
53# endif
54#endif
55
56#include "var.h"
57#include "misc.h"
58#include "vmbuf.h"
59#include "plog.h"
60#include "sockmisc.h"
61#include "schedule.h"
62#include "debug.h"
63
64#include "localconf.h"
65#include "remoteconf.h"
66#include "isakmp_var.h"
67#include "isakmp.h"
68#include "evt.h"
69#include "oakley.h"
70#include "handler.h"
71#include "ipsec_doi.h"
72#include "crypto_openssl.h"
73#include "pfkey.h"
74#include "isakmp_ident.h"
75#include "isakmp_inf.h"
76#include "vendorid.h"
77
78#ifdef ENABLE_NATT
79#include "nattraversal.h"
80#endif
81#ifdef HAVE_GSSAPI
82#include "gssapi.h"
83#endif
84#ifdef ENABLE_HYBRID
85#include <resolv.h>
86#include "isakmp_xauth.h"
87#include "isakmp_cfg.h"
88#endif
89#ifdef ENABLE_FRAG
90#include "isakmp_frag.h"
91#endif
92
93static vchar_t *ident_ir2mx __P((struct ph1handle *));
94static vchar_t *ident_ir3mx __P((struct ph1handle *));
95
96/* %%%
97 * begin Identity Protection Mode as initiator.
98 */
99/*
100 * send to responder
101 * 	psk: HDR, SA
102 * 	sig: HDR, SA
103 * 	rsa: HDR, SA
104 * 	rev: HDR, SA
105 */
106int
107ident_i1send(iph1, msg)
108	struct ph1handle *iph1;
109	vchar_t *msg; /* must be null */
110{
111	struct payload_list *plist = NULL;
112	int error = -1;
113#ifdef ENABLE_NATT
114	vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL };
115	int i;
116#endif
117#ifdef ENABLE_HYBRID
118	vchar_t *vid_xauth = NULL;
119	vchar_t *vid_unity = NULL;
120#endif
121#ifdef ENABLE_FRAG
122	vchar_t *vid_frag = NULL;
123#endif
124#ifdef ENABLE_DPD
125	vchar_t *vid_dpd = NULL;
126#endif
127	/* validity check */
128	if (msg != NULL) {
129		plog(LLV_ERROR, LOCATION, NULL,
130			"msg has to be NULL in this function.\n");
131		goto end;
132	}
133	if (iph1->status != PHASE1ST_START) {
134		plog(LLV_ERROR, LOCATION, NULL,
135			"status mismatched %d.\n", iph1->status);
136		goto end;
137	}
138
139	/* create isakmp index */
140	memset(&iph1->index, 0, sizeof(iph1->index));
141	isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
142
143	/* create SA payload for my proposal */
144	iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
145	if (iph1->sa == NULL)
146		goto end;
147
148	/* set SA payload to propose */
149	plist = isakmp_plist_append(plist, iph1->sa, ISAKMP_NPTYPE_SA);
150
151#ifdef ENABLE_NATT
152	/* set VID payload for NAT-T if NAT-T support allowed in the config file */
153	if (iph1->rmconf->nat_traversal)
154		plist = isakmp_plist_append_natt_vids(plist, vid_natt);
155#endif
156#ifdef ENABLE_HYBRID
157	/* Do we need Xauth VID? */
158	switch (RMAUTHMETHOD(iph1)) {
159	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
160	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
161	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
162	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
163	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
164	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
165	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
166		if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL)
167			plog(LLV_ERROR, LOCATION, NULL,
168			     "Xauth vendor ID generation failed\n");
169		else
170			plist = isakmp_plist_append(plist,
171			    vid_xauth, ISAKMP_NPTYPE_VID);
172
173		if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL)
174			plog(LLV_ERROR, LOCATION, NULL,
175			     "Unity vendor ID generation failed\n");
176		else
177                	plist = isakmp_plist_append(plist,
178			    vid_unity, ISAKMP_NPTYPE_VID);
179		break;
180	default:
181		break;
182	}
183#endif
184#ifdef ENABLE_FRAG
185	if (iph1->rmconf->ike_frag) {
186		if ((vid_frag = set_vendorid(VENDORID_FRAG)) == NULL) {
187			plog(LLV_ERROR, LOCATION, NULL,
188			    "Frag vendorID construction failed\n");
189		} else {
190			vid_frag = isakmp_frag_addcap(vid_frag,
191			    VENDORID_FRAG_IDENT);
192			plist = isakmp_plist_append(plist,
193			    vid_frag, ISAKMP_NPTYPE_VID);
194		}
195	}
196#endif
197#ifdef ENABLE_DPD
198	if(iph1->rmconf->dpd){
199		vid_dpd = set_vendorid(VENDORID_DPD);
200		if (vid_dpd != NULL)
201			plist = isakmp_plist_append(plist, vid_dpd,
202			    ISAKMP_NPTYPE_VID);
203	}
204#endif
205
206	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
207
208#ifdef HAVE_PRINT_ISAKMP_C
209	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
210#endif
211
212	/* send the packet, add to the schedule to resend */
213	iph1->retry_counter = iph1->rmconf->retry_counter;
214	if (isakmp_ph1resend(iph1) == -1)
215		goto end;
216
217	iph1->status = PHASE1ST_MSG1SENT;
218
219	error = 0;
220
221end:
222#ifdef ENABLE_FRAG
223	if (vid_frag)
224		vfree(vid_frag);
225#endif
226#ifdef ENABLE_NATT
227	for (i = 0; i < MAX_NATT_VID_COUNT && vid_natt[i] != NULL; i++)
228		vfree(vid_natt[i]);
229#endif
230#ifdef ENABLE_HYBRID
231	if (vid_xauth != NULL)
232		vfree(vid_xauth);
233	if (vid_unity != NULL)
234		vfree(vid_unity);
235#endif
236#ifdef ENABLE_DPD
237	if (vid_dpd != NULL)
238		vfree(vid_dpd);
239#endif
240
241	return error;
242}
243
244/*
245 * receive from responder
246 * 	psk: HDR, SA
247 * 	sig: HDR, SA
248 * 	rsa: HDR, SA
249 * 	rev: HDR, SA
250 */
251int
252ident_i2recv(iph1, msg)
253	struct ph1handle *iph1;
254	vchar_t *msg;
255{
256	vchar_t *pbuf = NULL;
257	struct isakmp_parse_t *pa;
258	vchar_t *satmp = NULL;
259	int error = -1;
260	int vid_numeric;
261
262	/* validity check */
263	if (iph1->status != PHASE1ST_MSG1SENT) {
264		plog(LLV_ERROR, LOCATION, NULL,
265			"status mismatched %d.\n", iph1->status);
266		goto end;
267	}
268
269	/* validate the type of next payload */
270	/*
271	 * NOTE: RedCreek(as responder) attaches N[responder-lifetime] here,
272	 *	if proposal-lifetime > lifetime-redcreek-wants.
273	 *	(see doi-08 4.5.4)
274	 *	=> According to the seciton 4.6.3 in RFC 2407, This is illegal.
275	 * NOTE: we do not really care about ordering of VID and N.
276	 *	does it matters?
277	 * NOTE: even if there's multiple VID/N, we'll ignore them.
278	 */
279	pbuf = isakmp_parse(msg);
280	if (pbuf == NULL)
281		goto end;
282	pa = (struct isakmp_parse_t *)pbuf->v;
283
284	/* SA payload is fixed postion */
285	if (pa->type != ISAKMP_NPTYPE_SA) {
286		plog(LLV_ERROR, LOCATION, iph1->remote,
287			"received invalid next payload type %d, "
288			"expecting %d.\n",
289			pa->type, ISAKMP_NPTYPE_SA);
290		goto end;
291	}
292	if (isakmp_p2ph(&satmp, pa->ptr) < 0)
293		goto end;
294	pa++;
295
296	for (/*nothing*/;
297	     pa->type != ISAKMP_NPTYPE_NONE;
298	     pa++) {
299
300		switch (pa->type) {
301		case ISAKMP_NPTYPE_VID:
302			handle_vendorid(iph1, pa->ptr);
303			break;
304		default:
305			/* don't send information, see ident_r1recv() */
306			plog(LLV_ERROR, LOCATION, iph1->remote,
307				"ignore the packet, "
308				"received unexpecting payload type %d.\n",
309				pa->type);
310			goto end;
311		}
312	}
313
314#ifdef ENABLE_NATT
315	if (NATT_AVAILABLE(iph1))
316		plog(LLV_INFO, LOCATION, iph1->remote,
317		     "Selected NAT-T version: %s\n",
318		     vid_string_by_id(iph1->natt_options->version));
319#endif
320
321	/* check SA payload and set approval SA for use */
322	if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
323		plog(LLV_ERROR, LOCATION, iph1->remote,
324			"failed to get valid proposal.\n");
325		/* XXX send information */
326		goto end;
327	}
328	VPTRINIT(iph1->sa_ret);
329
330	iph1->status = PHASE1ST_MSG2RECEIVED;
331
332	error = 0;
333
334end:
335	if (pbuf)
336		vfree(pbuf);
337	if (satmp)
338		vfree(satmp);
339	return error;
340}
341
342/*
343 * send to responder
344 * 	psk: HDR, KE, Ni
345 * 	sig: HDR, KE, Ni
346 *   gssapi: HDR, KE, Ni, GSSi
347 * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
348 * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
349 * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
350 */
351int
352ident_i2send(iph1, msg)
353	struct ph1handle *iph1;
354	vchar_t *msg;
355{
356	int error = -1;
357
358	/* validity check */
359	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
360		plog(LLV_ERROR, LOCATION, NULL,
361			"status mismatched %d.\n", iph1->status);
362		goto end;
363	}
364
365	/* fix isakmp index */
366	memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
367		sizeof(cookie_t));
368
369	/* generate DH public value */
370	if (oakley_dh_generate(iph1->approval->dhgrp,
371				&iph1->dhpub, &iph1->dhpriv) < 0)
372		goto end;
373
374	/* generate NONCE value */
375	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
376	if (iph1->nonce == NULL)
377		goto end;
378
379#ifdef HAVE_GSSAPI
380	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
381	    gssapi_get_itoken(iph1, NULL) < 0)
382		goto end;
383#endif
384
385	/* create buffer to send isakmp payload */
386	iph1->sendbuf = ident_ir2mx(iph1);
387	if (iph1->sendbuf == NULL)
388		goto end;
389
390#ifdef HAVE_PRINT_ISAKMP_C
391	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
392#endif
393
394	/* send the packet, add to the schedule to resend */
395	iph1->retry_counter = iph1->rmconf->retry_counter;
396	if (isakmp_ph1resend(iph1) == -1)
397		goto end;
398
399	/* the sending message is added to the received-list. */
400	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
401		plog(LLV_ERROR , LOCATION, NULL,
402			"failed to add a response packet to the tree.\n");
403		goto end;
404	}
405
406	iph1->status = PHASE1ST_MSG2SENT;
407
408	error = 0;
409
410end:
411	return error;
412}
413
414/*
415 * receive from responder
416 * 	psk: HDR, KE, Nr
417 * 	sig: HDR, KE, Nr [, CR ]
418 *   gssapi: HDR, KE, Nr, GSSr
419 * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
420 * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
421 */
422int
423ident_i3recv(iph1, msg)
424	struct ph1handle *iph1;
425	vchar_t *msg;
426{
427	vchar_t *pbuf = NULL;
428	struct isakmp_parse_t *pa;
429	int error = -1;
430#ifdef HAVE_GSSAPI
431	vchar_t *gsstoken = NULL;
432#endif
433#ifdef ENABLE_NATT
434	vchar_t	*natd_received;
435	int natd_seq = 0, natd_verified;
436#endif
437
438	/* validity check */
439	if (iph1->status != PHASE1ST_MSG2SENT) {
440		plog(LLV_ERROR, LOCATION, NULL,
441			"status mismatched %d.\n", iph1->status);
442		goto end;
443	}
444
445	/* validate the type of next payload */
446	pbuf = isakmp_parse(msg);
447	if (pbuf == NULL)
448		goto end;
449
450	for (pa = (struct isakmp_parse_t *)pbuf->v;
451	     pa->type != ISAKMP_NPTYPE_NONE;
452	     pa++) {
453
454		switch (pa->type) {
455		case ISAKMP_NPTYPE_KE:
456			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
457				goto end;
458			break;
459		case ISAKMP_NPTYPE_NONCE:
460			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
461				goto end;
462			break;
463		case ISAKMP_NPTYPE_VID:
464			handle_vendorid(iph1, pa->ptr);
465			break;
466		case ISAKMP_NPTYPE_CR:
467			if (oakley_savecr(iph1, pa->ptr) < 0)
468				goto end;
469			break;
470#ifdef HAVE_GSSAPI
471		case ISAKMP_NPTYPE_GSS:
472			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
473				goto end;
474			gssapi_save_received_token(iph1, gsstoken);
475			break;
476#endif
477
478#ifdef ENABLE_NATT
479		case ISAKMP_NPTYPE_NATD_DRAFT:
480		case ISAKMP_NPTYPE_NATD_RFC:
481			if (NATT_AVAILABLE(iph1) && iph1->natt_options != NULL &&
482			    pa->type == iph1->natt_options->payload_nat_d) {
483				natd_received = NULL;
484				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
485					goto end;
486
487				/* set both bits first so that we can clear them
488				   upon verifying hashes */
489				if (natd_seq == 0)
490					iph1->natt_flags |= NAT_DETECTED;
491
492				/* this function will clear appropriate bits bits
493				   from iph1->natt_flags */
494				natd_verified = natt_compare_addr_hash (iph1,
495					natd_received, natd_seq++);
496
497				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
498					natd_seq - 1,
499					natd_verified ? "verified" : "doesn't match");
500
501				vfree (natd_received);
502				break;
503			}
504			/* passthrough to default... */
505#endif
506
507		default:
508			/* don't send information, see ident_r1recv() */
509			plog(LLV_ERROR, LOCATION, iph1->remote,
510				"ignore the packet, "
511				"received unexpecting payload type %d.\n",
512				pa->type);
513			goto end;
514		}
515	}
516
517#ifdef ENABLE_NATT
518	if (NATT_AVAILABLE(iph1)) {
519		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
520		      iph1->natt_flags & NAT_DETECTED ?
521		      		"detected:" : "not detected",
522		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
523		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
524		if (iph1->natt_flags & NAT_DETECTED)
525			natt_float_ports (iph1);
526	}
527#endif
528
529	/* payload existency check */
530	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
531		plog(LLV_ERROR, LOCATION, iph1->remote,
532			"few isakmp message received.\n");
533		goto end;
534	}
535
536	if (oakley_checkcr(iph1) < 0) {
537		/* Ignore this error in order to be interoperability. */
538		;
539	}
540
541	iph1->status = PHASE1ST_MSG3RECEIVED;
542
543	error = 0;
544
545end:
546#ifdef HAVE_GSSAPI
547	if (gsstoken)
548		vfree(gsstoken);
549#endif
550	if (pbuf)
551		vfree(pbuf);
552	if (error) {
553		VPTRINIT(iph1->dhpub_p);
554		VPTRINIT(iph1->nonce_p);
555		VPTRINIT(iph1->id_p);
556		oakley_delcert(iph1->cr_p);
557		iph1->cr_p = NULL;
558	}
559
560	return error;
561}
562
563/*
564 * send to responder
565 * 	psk: HDR*, IDi1, HASH_I
566 * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
567 *   gssapi: HDR*, IDi1, < Gssi(n) | HASH_I >
568 * 	rsa: HDR*, HASH_I
569 * 	rev: HDR*, HASH_I
570 */
571int
572ident_i3send(iph1, msg0)
573	struct ph1handle *iph1;
574	vchar_t *msg0;
575{
576	int error = -1;
577	int dohash = 1;
578#ifdef HAVE_GSSAPI
579	int len;
580#endif
581
582	/* validity check */
583	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
584		plog(LLV_ERROR, LOCATION, NULL,
585			"status mismatched %d.\n", iph1->status);
586		goto end;
587	}
588
589	/* compute sharing secret of DH */
590	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
591				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
592		goto end;
593
594	/* generate SKEYIDs & IV & final cipher key */
595	if (oakley_skeyid(iph1) < 0)
596		goto end;
597	if (oakley_skeyid_dae(iph1) < 0)
598		goto end;
599	if (oakley_compute_enckey(iph1) < 0)
600		goto end;
601	if (oakley_newiv(iph1) < 0)
602		goto end;
603
604	/* make ID payload into isakmp status */
605	if (ipsecdoi_setid1(iph1) < 0)
606		goto end;
607
608#ifdef HAVE_GSSAPI
609	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
610	    gssapi_more_tokens(iph1)) {
611		plog(LLV_DEBUG, LOCATION, NULL, "calling get_itoken\n");
612		if (gssapi_get_itoken(iph1, &len) < 0)
613			goto end;
614		if (len != 0)
615			dohash = 0;
616	}
617#endif
618
619	/* generate HASH to send */
620	if (dohash) {
621		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
622		if (iph1->hash == NULL)
623			goto end;
624	} else
625		iph1->hash = NULL;
626
627	/* set encryption flag */
628	iph1->flags |= ISAKMP_FLAG_E;
629
630	/* create HDR;ID;HASH payload */
631	iph1->sendbuf = ident_ir3mx(iph1);
632	if (iph1->sendbuf == NULL)
633		goto end;
634
635	/* send the packet, add to the schedule to resend */
636	iph1->retry_counter = iph1->rmconf->retry_counter;
637	if (isakmp_ph1resend(iph1) == -1)
638		goto end;
639
640	/* the sending message is added to the received-list. */
641	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg0) == -1) {
642		plog(LLV_ERROR , LOCATION, NULL,
643			"failed to add a response packet to the tree.\n");
644		goto end;
645	}
646
647	/* see handler.h about IV synchronization. */
648	memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l);
649
650	iph1->status = PHASE1ST_MSG3SENT;
651
652	error = 0;
653
654end:
655	return error;
656}
657
658/*
659 * receive from responder
660 * 	psk: HDR*, IDr1, HASH_R
661 * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
662 *   gssapi: HDR*, IDr1, < GSSr(n) | HASH_R >
663 * 	rsa: HDR*, HASH_R
664 * 	rev: HDR*, HASH_R
665 */
666int
667ident_i4recv(iph1, msg0)
668	struct ph1handle *iph1;
669	vchar_t *msg0;
670{
671	vchar_t *pbuf = NULL;
672	struct isakmp_parse_t *pa;
673	vchar_t *msg = NULL;
674	int error = -1;
675	int type;
676#ifdef HAVE_GSSAPI
677	vchar_t *gsstoken = NULL;
678#endif
679
680	/* validity check */
681	if (iph1->status != PHASE1ST_MSG3SENT) {
682		plog(LLV_ERROR, LOCATION, NULL,
683			"status mismatched %d.\n", iph1->status);
684		goto end;
685	}
686
687	/* decrypting */
688	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
689		plog(LLV_ERROR, LOCATION, iph1->remote,
690			"ignore the packet, "
691			"expecting the packet encrypted.\n");
692		goto end;
693	}
694	msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive);
695	if (msg == NULL)
696		goto end;
697
698	/* validate the type of next payload */
699	pbuf = isakmp_parse(msg);
700	if (pbuf == NULL)
701		goto end;
702
703	iph1->pl_hash = NULL;
704
705	for (pa = (struct isakmp_parse_t *)pbuf->v;
706	     pa->type != ISAKMP_NPTYPE_NONE;
707	     pa++) {
708
709		switch (pa->type) {
710		case ISAKMP_NPTYPE_ID:
711			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
712				goto end;
713			break;
714		case ISAKMP_NPTYPE_HASH:
715			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
716			break;
717		case ISAKMP_NPTYPE_CERT:
718			if (oakley_savecert(iph1, pa->ptr) < 0)
719				goto end;
720			break;
721		case ISAKMP_NPTYPE_SIG:
722			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
723				goto end;
724			break;
725#ifdef HAVE_GSSAPI
726		case ISAKMP_NPTYPE_GSS:
727			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
728				goto end;
729			gssapi_save_received_token(iph1, gsstoken);
730			break;
731#endif
732		case ISAKMP_NPTYPE_VID:
733			handle_vendorid(iph1, pa->ptr);
734			break;
735		case ISAKMP_NPTYPE_N:
736			isakmp_check_notify(pa->ptr, iph1);
737			break;
738		default:
739			/* don't send information, see ident_r1recv() */
740			plog(LLV_ERROR, LOCATION, iph1->remote,
741				"ignore the packet, "
742				"received unexpecting payload type %d.\n",
743				pa->type);
744			goto end;
745		}
746	}
747
748	/* payload existency check */
749
750	/* verify identifier */
751	if (ipsecdoi_checkid1(iph1) != 0) {
752		plog(LLV_ERROR, LOCATION, iph1->remote,
753			"invalid ID payload.\n");
754		goto end;
755	}
756
757	/* validate authentication value */
758#ifdef HAVE_GSSAPI
759	if (gsstoken == NULL) {
760#endif
761		type = oakley_validate_auth(iph1);
762		if (type != 0) {
763			if (type == -1) {
764				/* msg printed inner oakley_validate_auth() */
765				goto end;
766			}
767			EVT_PUSH(iph1->local, iph1->remote,
768			    EVTT_PEERPH1AUTH_FAILED, NULL);
769			isakmp_info_send_n1(iph1, type, NULL);
770			goto end;
771		}
772#ifdef HAVE_GSSAPI
773	}
774#endif
775
776	/*
777	 * XXX: Should we do compare two addresses, ph1handle's and ID
778	 * payload's.
779	 */
780
781	plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID:");
782	plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l);
783
784	/* see handler.h about IV synchronization. */
785	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l);
786
787	/*
788	 * If we got a GSS token, we need to this roundtrip again.
789	 */
790#ifdef HAVE_GSSAPI
791	iph1->status = gsstoken != 0 ? PHASE1ST_MSG3RECEIVED :
792	    PHASE1ST_MSG4RECEIVED;
793#else
794	iph1->status = PHASE1ST_MSG4RECEIVED;
795#endif
796
797	error = 0;
798
799end:
800	if (pbuf)
801		vfree(pbuf);
802	if (msg)
803		vfree(msg);
804#ifdef HAVE_GSSAPI
805	if (gsstoken)
806		vfree(gsstoken);
807#endif
808
809	if (error) {
810		VPTRINIT(iph1->id_p);
811		oakley_delcert(iph1->cert_p);
812		iph1->cert_p = NULL;
813		oakley_delcert(iph1->crl_p);
814		iph1->crl_p = NULL;
815		VPTRINIT(iph1->sig_p);
816	}
817
818	return error;
819}
820
821/*
822 * status update and establish isakmp sa.
823 */
824int
825ident_i4send(iph1, msg)
826	struct ph1handle *iph1;
827	vchar_t *msg;
828{
829	int error = -1;
830
831	/* validity check */
832	if (iph1->status != PHASE1ST_MSG4RECEIVED) {
833		plog(LLV_ERROR, LOCATION, NULL,
834			"status mismatched %d.\n", iph1->status);
835		goto end;
836	}
837
838	/* see handler.h about IV synchronization. */
839	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
840
841	iph1->status = PHASE1ST_ESTABLISHED;
842
843	error = 0;
844
845end:
846	return error;
847}
848
849/*
850 * receive from initiator
851 * 	psk: HDR, SA
852 * 	sig: HDR, SA
853 * 	rsa: HDR, SA
854 * 	rev: HDR, SA
855 */
856int
857ident_r1recv(iph1, msg)
858	struct ph1handle *iph1;
859	vchar_t *msg;
860{
861	vchar_t *pbuf = NULL;
862	struct isakmp_parse_t *pa;
863	int error = -1;
864	int vid_numeric;
865
866	/* validity check */
867	if (iph1->status != PHASE1ST_START) {
868		plog(LLV_ERROR, LOCATION, NULL,
869			"status mismatched %d.\n", iph1->status);
870		goto end;
871	}
872
873	/* validate the type of next payload */
874	/*
875	 * NOTE: XXX even if multiple VID, we'll silently ignore those.
876	 */
877	pbuf = isakmp_parse(msg);
878	if (pbuf == NULL)
879		goto end;
880	pa = (struct isakmp_parse_t *)pbuf->v;
881
882	/* check the position of SA payload */
883	if (pa->type != ISAKMP_NPTYPE_SA) {
884		plog(LLV_ERROR, LOCATION, iph1->remote,
885			"received invalid next payload type %d, "
886			"expecting %d.\n",
887			pa->type, ISAKMP_NPTYPE_SA);
888		goto end;
889	}
890	if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
891		goto end;
892	pa++;
893
894	for (/*nothing*/;
895	     pa->type != ISAKMP_NPTYPE_NONE;
896	     pa++) {
897
898		switch (pa->type) {
899		case ISAKMP_NPTYPE_VID:
900			vid_numeric = handle_vendorid(iph1, pa->ptr);
901#ifdef ENABLE_FRAG
902			if ((vid_numeric == VENDORID_FRAG) &&
903			    (vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_IDENT))
904				iph1->frag = 1;
905#endif
906			break;
907		default:
908			/*
909			 * We don't send information to the peer even
910			 * if we received malformed packet.  Because we
911			 * can't distinguish the malformed packet and
912			 * the re-sent packet.  And we do same behavior
913			 * when we expect encrypted packet.
914			 */
915			plog(LLV_ERROR, LOCATION, iph1->remote,
916				"ignore the packet, "
917				"received unexpecting payload type %d.\n",
918				pa->type);
919			goto end;
920		}
921	}
922
923#ifdef ENABLE_NATT
924	if (NATT_AVAILABLE(iph1))
925		plog(LLV_INFO, LOCATION, iph1->remote,
926		     "Selected NAT-T version: %s\n",
927		     vid_string_by_id(iph1->natt_options->version));
928#endif
929
930	/* check SA payload and set approval SA for use */
931	if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
932		plog(LLV_ERROR, LOCATION, iph1->remote,
933			"failed to get valid proposal.\n");
934		/* XXX send information */
935		goto end;
936	}
937
938	iph1->status = PHASE1ST_MSG1RECEIVED;
939
940	error = 0;
941
942end:
943	if (pbuf)
944		vfree(pbuf);
945	if (error) {
946		VPTRINIT(iph1->sa);
947	}
948
949	return error;
950}
951
952/*
953 * send to initiator
954 * 	psk: HDR, SA
955 * 	sig: HDR, SA
956 * 	rsa: HDR, SA
957 * 	rev: HDR, SA
958 */
959int
960ident_r1send(iph1, msg)
961	struct ph1handle *iph1;
962	vchar_t *msg;
963{
964	struct payload_list *plist = NULL;
965	int error = -1;
966	vchar_t *gss_sa = NULL;
967#ifdef HAVE_GSSAPI
968	int free_gss_sa = 0;
969#endif
970#ifdef ENABLE_NATT
971	vchar_t *vid_natt = NULL;
972#endif
973#ifdef ENABLE_HYBRID
974        vchar_t *vid_xauth = NULL;
975        vchar_t *vid_unity = NULL;
976#endif
977#ifdef ENABLE_DPD
978	vchar_t *vid_dpd = NULL;
979#endif
980#ifdef ENABLE_FRAG
981	vchar_t *vid_frag = NULL;
982#endif
983
984	/* validity check */
985	if (iph1->status != PHASE1ST_MSG1RECEIVED) {
986		plog(LLV_ERROR, LOCATION, NULL,
987			"status mismatched %d.\n", iph1->status);
988		goto end;
989	}
990
991	/* set responder's cookie */
992	isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
993
994#ifdef HAVE_GSSAPI
995	if (iph1->approval->gssid != NULL) {
996		gss_sa = ipsecdoi_setph1proposal(iph1->approval);
997		if (gss_sa != iph1->sa_ret)
998			free_gss_sa = 1;
999	} else
1000#endif
1001		gss_sa = iph1->sa_ret;
1002
1003	/* set SA payload to reply */
1004	plist = isakmp_plist_append(plist, gss_sa, ISAKMP_NPTYPE_SA);
1005
1006#ifdef ENABLE_HYBRID
1007	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
1008		plog (LLV_INFO, LOCATION, NULL, "Adding xauth VID payload.\n");
1009		if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL) {
1010			plog(LLV_ERROR, LOCATION, NULL,
1011			    "Cannot create Xauth vendor ID\n");
1012			goto end;
1013		}
1014		plist = isakmp_plist_append(plist,
1015		    vid_xauth, ISAKMP_NPTYPE_VID);
1016	}
1017
1018	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_UNITY) {
1019		if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL) {
1020			plog(LLV_ERROR, LOCATION, NULL,
1021			    "Cannot create Unity vendor ID\n");
1022			goto end;
1023		}
1024		plist = isakmp_plist_append(plist,
1025		    vid_unity, ISAKMP_NPTYPE_VID);
1026	}
1027#endif
1028#ifdef ENABLE_NATT
1029	/* Has the peer announced NAT-T? */
1030	if (NATT_AVAILABLE(iph1))
1031		vid_natt = set_vendorid(iph1->natt_options->version);
1032
1033	if (vid_natt)
1034		plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID);
1035#endif
1036#ifdef ENABLE_DPD
1037	/* XXX only send DPD VID if remote sent it ? */
1038	if(iph1->rmconf->dpd){
1039		vid_dpd = set_vendorid(VENDORID_DPD);
1040		if (vid_dpd != NULL)
1041			plist = isakmp_plist_append(plist, vid_dpd, ISAKMP_NPTYPE_VID);
1042	}
1043#endif
1044#ifdef ENABLE_FRAG
1045	if (iph1->frag) {
1046		vid_frag = set_vendorid(VENDORID_FRAG);
1047		if (vid_frag != NULL)
1048			vid_frag = isakmp_frag_addcap(vid_frag,
1049			    VENDORID_FRAG_IDENT);
1050		if (vid_frag == NULL)
1051			plog(LLV_ERROR, LOCATION, NULL,
1052			    "Frag vendorID construction failed\n");
1053		else
1054			plist = isakmp_plist_append(plist,
1055			     vid_frag, ISAKMP_NPTYPE_VID);
1056	}
1057#endif
1058
1059	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
1060
1061#ifdef HAVE_PRINT_ISAKMP_C
1062	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
1063#endif
1064
1065	/* send the packet, add to the schedule to resend */
1066	iph1->retry_counter = iph1->rmconf->retry_counter;
1067	if (isakmp_ph1resend(iph1) == -1) {
1068		goto end;
1069	}
1070
1071	/* the sending message is added to the received-list. */
1072	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1073		plog(LLV_ERROR , LOCATION, NULL,
1074			"failed to add a response packet to the tree.\n");
1075		goto end;
1076	}
1077
1078	iph1->status = PHASE1ST_MSG1SENT;
1079
1080	error = 0;
1081
1082end:
1083#ifdef HAVE_GSSAPI
1084	if (free_gss_sa)
1085		vfree(gss_sa);
1086#endif
1087#ifdef ENABLE_NATT
1088	if (vid_natt)
1089		vfree(vid_natt);
1090#endif
1091#ifdef ENABLE_HYBRID
1092	if (vid_xauth != NULL)
1093		vfree(vid_xauth);
1094	if (vid_unity != NULL)
1095		vfree(vid_unity);
1096#endif
1097#ifdef ENABLE_DPD
1098	if (vid_dpd != NULL)
1099		vfree(vid_dpd);
1100#endif
1101#ifdef ENABLE_FRAG
1102	if (vid_frag != NULL)
1103		vfree(vid_frag);
1104#endif
1105
1106	return error;
1107}
1108
1109/*
1110 * receive from initiator
1111 * 	psk: HDR, KE, Ni
1112 * 	sig: HDR, KE, Ni
1113 *   gssapi: HDR, KE, Ni, GSSi
1114 * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
1115 * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
1116 * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
1117 */
1118int
1119ident_r2recv(iph1, msg)
1120	struct ph1handle *iph1;
1121	vchar_t *msg;
1122{
1123	vchar_t *pbuf = NULL;
1124	struct isakmp_parse_t *pa;
1125	int error = -1;
1126#ifdef HAVE_GSSAPI
1127	vchar_t *gsstoken = NULL;
1128#endif
1129#ifdef ENABLE_NATT
1130	int natd_seq = 0;
1131#endif
1132
1133	/* validity check */
1134	if (iph1->status != PHASE1ST_MSG1SENT) {
1135		plog(LLV_ERROR, LOCATION, NULL,
1136			"status mismatched %d.\n", iph1->status);
1137		goto end;
1138	}
1139
1140	/* validate the type of next payload */
1141	pbuf = isakmp_parse(msg);
1142	if (pbuf == NULL)
1143		goto end;
1144
1145	for (pa = (struct isakmp_parse_t *)pbuf->v;
1146	     pa->type != ISAKMP_NPTYPE_NONE;
1147	     pa++) {
1148		switch (pa->type) {
1149		case ISAKMP_NPTYPE_KE:
1150			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
1151				goto end;
1152			break;
1153		case ISAKMP_NPTYPE_NONCE:
1154			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
1155				goto end;
1156			break;
1157		case ISAKMP_NPTYPE_VID:
1158			handle_vendorid(iph1, pa->ptr);
1159			break;
1160		case ISAKMP_NPTYPE_CR:
1161			plog(LLV_WARNING, LOCATION, iph1->remote,
1162				"CR received, ignore it. "
1163				"It should be in other exchange.\n");
1164			break;
1165#ifdef HAVE_GSSAPI
1166		case ISAKMP_NPTYPE_GSS:
1167			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
1168				goto end;
1169			gssapi_save_received_token(iph1, gsstoken);
1170			break;
1171#endif
1172
1173#ifdef ENABLE_NATT
1174		case ISAKMP_NPTYPE_NATD_DRAFT:
1175		case ISAKMP_NPTYPE_NATD_RFC:
1176			if (NATT_AVAILABLE(iph1) && iph1->natt_options != NULL &&
1177				pa->type == iph1->natt_options->payload_nat_d)
1178			{
1179				vchar_t *natd_received = NULL;
1180				int natd_verified;
1181
1182				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
1183					goto end;
1184
1185				if (natd_seq == 0)
1186					iph1->natt_flags |= NAT_DETECTED;
1187
1188				natd_verified = natt_compare_addr_hash (iph1,
1189					natd_received, natd_seq++);
1190
1191				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
1192					natd_seq - 1,
1193					natd_verified ? "verified" : "doesn't match");
1194
1195				vfree (natd_received);
1196				break;
1197			}
1198			/* passthrough to default... */
1199#endif
1200
1201		default:
1202			/* don't send information, see ident_r1recv() */
1203			plog(LLV_ERROR, LOCATION, iph1->remote,
1204				"ignore the packet, "
1205				"received unexpecting payload type %d.\n",
1206				pa->type);
1207			goto end;
1208		}
1209	}
1210
1211#ifdef ENABLE_NATT
1212	if (NATT_AVAILABLE(iph1))
1213		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
1214		      iph1->natt_flags & NAT_DETECTED ?
1215		      		"detected:" : "not detected",
1216		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
1217		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
1218#endif
1219
1220	/* payload existency check */
1221	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
1222		plog(LLV_ERROR, LOCATION, iph1->remote,
1223			"few isakmp message received.\n");
1224		goto end;
1225	}
1226
1227	iph1->status = PHASE1ST_MSG2RECEIVED;
1228
1229	error = 0;
1230
1231end:
1232	if (pbuf)
1233		vfree(pbuf);
1234#ifdef HAVE_GSSAPI
1235	if (gsstoken)
1236		vfree(gsstoken);
1237#endif
1238
1239	if (error) {
1240		VPTRINIT(iph1->dhpub_p);
1241		VPTRINIT(iph1->nonce_p);
1242		VPTRINIT(iph1->id_p);
1243	}
1244
1245	return error;
1246}
1247
1248/*
1249 * send to initiator
1250 * 	psk: HDR, KE, Nr
1251 * 	sig: HDR, KE, Nr [, CR ]
1252 *   gssapi: HDR, KE, Nr, GSSr
1253 * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
1254 * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
1255 */
1256int
1257ident_r2send(iph1, msg)
1258	struct ph1handle *iph1;
1259	vchar_t *msg;
1260{
1261	int error = -1;
1262
1263	/* validity check */
1264	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
1265		plog(LLV_ERROR, LOCATION, NULL,
1266			"status mismatched %d.\n", iph1->status);
1267		goto end;
1268	}
1269
1270	/* generate DH public value */
1271	if (oakley_dh_generate(iph1->approval->dhgrp,
1272				&iph1->dhpub, &iph1->dhpriv) < 0)
1273		goto end;
1274
1275	/* generate NONCE value */
1276	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
1277	if (iph1->nonce == NULL)
1278		goto end;
1279
1280#ifdef HAVE_GSSAPI
1281	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
1282		gssapi_get_rtoken(iph1, NULL);
1283#endif
1284
1285	/* create HDR;KE;NONCE payload */
1286	iph1->sendbuf = ident_ir2mx(iph1);
1287	if (iph1->sendbuf == NULL)
1288		goto end;
1289
1290#ifdef HAVE_PRINT_ISAKMP_C
1291	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
1292#endif
1293
1294	/* send the packet, add to the schedule to resend */
1295	iph1->retry_counter = iph1->rmconf->retry_counter;
1296	if (isakmp_ph1resend(iph1) == -1)
1297		goto end;
1298
1299	/* the sending message is added to the received-list. */
1300	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1301		plog(LLV_ERROR , LOCATION, NULL,
1302			"failed to add a response packet to the tree.\n");
1303		goto end;
1304	}
1305
1306	/* compute sharing secret of DH */
1307	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
1308				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
1309		goto end;
1310
1311	/* generate SKEYIDs & IV & final cipher key */
1312	if (oakley_skeyid(iph1) < 0)
1313		goto end;
1314	if (oakley_skeyid_dae(iph1) < 0)
1315		goto end;
1316	if (oakley_compute_enckey(iph1) < 0)
1317		goto end;
1318	if (oakley_newiv(iph1) < 0)
1319		goto end;
1320
1321	iph1->status = PHASE1ST_MSG2SENT;
1322
1323	error = 0;
1324
1325end:
1326	return error;
1327}
1328
1329/*
1330 * receive from initiator
1331 * 	psk: HDR*, IDi1, HASH_I
1332 * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
1333 *   gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I >
1334 * 	rsa: HDR*, HASH_I
1335 * 	rev: HDR*, HASH_I
1336 */
1337int
1338ident_r3recv(iph1, msg0)
1339	struct ph1handle *iph1;
1340	vchar_t *msg0;
1341{
1342	vchar_t *msg = NULL;
1343	vchar_t *pbuf = NULL;
1344	struct isakmp_parse_t *pa;
1345	int error = -1;
1346	int type;
1347#ifdef HAVE_GSSAPI
1348	vchar_t *gsstoken = NULL;
1349#endif
1350
1351	/* validity check */
1352	if (iph1->status != PHASE1ST_MSG2SENT) {
1353		plog(LLV_ERROR, LOCATION, NULL,
1354			"status mismatched %d.\n", iph1->status);
1355		goto end;
1356	}
1357
1358	/* decrypting */
1359	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1360		plog(LLV_ERROR, LOCATION, iph1->remote,
1361			"reject the packet, "
1362			"expecting the packet encrypted.\n");
1363		goto end;
1364	}
1365	msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive);
1366	if (msg == NULL)
1367		goto end;
1368
1369	/* validate the type of next payload */
1370	pbuf = isakmp_parse(msg);
1371	if (pbuf == NULL)
1372		goto end;
1373
1374	iph1->pl_hash = NULL;
1375
1376	for (pa = (struct isakmp_parse_t *)pbuf->v;
1377	     pa->type != ISAKMP_NPTYPE_NONE;
1378	     pa++) {
1379
1380		switch (pa->type) {
1381		case ISAKMP_NPTYPE_ID:
1382			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
1383				goto end;
1384			break;
1385		case ISAKMP_NPTYPE_HASH:
1386			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
1387			break;
1388		case ISAKMP_NPTYPE_CR:
1389			if (oakley_savecr(iph1, pa->ptr) < 0)
1390				goto end;
1391			break;
1392		case ISAKMP_NPTYPE_CERT:
1393			if (oakley_savecert(iph1, pa->ptr) < 0)
1394				goto end;
1395			break;
1396		case ISAKMP_NPTYPE_SIG:
1397			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
1398				goto end;
1399			break;
1400#ifdef HAVE_GSSAPI
1401		case ISAKMP_NPTYPE_GSS:
1402			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
1403				goto end;
1404			gssapi_save_received_token(iph1, gsstoken);
1405			break;
1406#endif
1407		case ISAKMP_NPTYPE_VID:
1408			handle_vendorid(iph1, pa->ptr);
1409			break;
1410		case ISAKMP_NPTYPE_N:
1411			isakmp_check_notify(pa->ptr, iph1);
1412			break;
1413		default:
1414			/* don't send information, see ident_r1recv() */
1415			plog(LLV_ERROR, LOCATION, iph1->remote,
1416				"ignore the packet, "
1417				"received unexpecting payload type %d.\n",
1418				pa->type);
1419			goto end;
1420		}
1421	}
1422
1423	/* payload existency check */
1424	/* XXX same as ident_i4recv(), should be merged. */
1425    {
1426	int ng = 0;
1427
1428	switch (AUTHMETHOD(iph1)) {
1429	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1430#ifdef ENABLE_HYBRID
1431	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1432	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1433	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1434#endif
1435		if (iph1->id_p == NULL || iph1->pl_hash == NULL)
1436			ng++;
1437		break;
1438	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1439	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1440#ifdef ENABLE_HYBRID
1441	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1442	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1443#endif
1444		if (iph1->id_p == NULL || iph1->sig_p == NULL)
1445			ng++;
1446		break;
1447	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1448	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1449#ifdef ENABLE_HYBRID
1450	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1451	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1452#endif
1453		if (iph1->pl_hash == NULL)
1454			ng++;
1455		break;
1456#ifdef HAVE_GSSAPI
1457	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1458		if (gsstoken == NULL && iph1->pl_hash == NULL)
1459			ng++;
1460		break;
1461#endif
1462	default:
1463		plog(LLV_ERROR, LOCATION, iph1->remote,
1464			"invalid authmethod %d why ?\n",
1465			iph1->approval->authmethod);
1466		goto end;
1467	}
1468	if (ng) {
1469		plog(LLV_ERROR, LOCATION, iph1->remote,
1470			"few isakmp message received.\n");
1471		goto end;
1472	}
1473    }
1474
1475	/* verify identifier */
1476	if (ipsecdoi_checkid1(iph1) != 0) {
1477		plog(LLV_ERROR, LOCATION, iph1->remote,
1478			"invalid ID payload.\n");
1479		goto end;
1480	}
1481
1482	/* validate authentication value */
1483#ifdef HAVE_GSSAPI
1484	if (gsstoken == NULL) {
1485#endif
1486		type = oakley_validate_auth(iph1);
1487		if (type != 0) {
1488			if (type == -1) {
1489				/* msg printed inner oakley_validate_auth() */
1490				goto end;
1491			}
1492			EVT_PUSH(iph1->local, iph1->remote,
1493			    EVTT_PEERPH1AUTH_FAILED, NULL);
1494			isakmp_info_send_n1(iph1, type, NULL);
1495			goto end;
1496		}
1497#ifdef HAVE_GSSAPI
1498	}
1499#endif
1500
1501	if (oakley_checkcr(iph1) < 0) {
1502		/* Ignore this error in order to be interoperability. */
1503		;
1504	}
1505
1506	/*
1507	 * XXX: Should we do compare two addresses, ph1handle's and ID
1508	 * payload's.
1509	 */
1510
1511	plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID\n");
1512	plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l);
1513
1514	/* see handler.h about IV synchronization. */
1515	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l);
1516
1517#ifdef HAVE_GSSAPI
1518	iph1->status = gsstoken != NULL ? PHASE1ST_MSG2RECEIVED :
1519	    PHASE1ST_MSG3RECEIVED;
1520#else
1521	iph1->status = PHASE1ST_MSG3RECEIVED;
1522#endif
1523
1524	error = 0;
1525
1526end:
1527	if (pbuf)
1528		vfree(pbuf);
1529	if (msg)
1530		vfree(msg);
1531#ifdef HAVE_GSSAPI
1532	if (gsstoken)
1533		vfree(gsstoken);
1534#endif
1535
1536	if (error) {
1537		VPTRINIT(iph1->id_p);
1538		oakley_delcert(iph1->cert_p);
1539		iph1->cert_p = NULL;
1540		oakley_delcert(iph1->crl_p);
1541		iph1->crl_p = NULL;
1542		VPTRINIT(iph1->sig_p);
1543		oakley_delcert(iph1->cr_p);
1544		iph1->cr_p = NULL;
1545	}
1546
1547	return error;
1548}
1549
1550/*
1551 * send to initiator
1552 * 	psk: HDR*, IDr1, HASH_R
1553 * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
1554 *   gssapi: HDR*, IDr1, < GSSr(n) | HASH_R >
1555 * 	rsa: HDR*, HASH_R
1556 * 	rev: HDR*, HASH_R
1557 */
1558int
1559ident_r3send(iph1, msg)
1560	struct ph1handle *iph1;
1561	vchar_t *msg;
1562{
1563	int error = -1;
1564	int dohash = 1;
1565#ifdef HAVE_GSSAPI
1566	int len;
1567#endif
1568
1569	/* validity check */
1570	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
1571		plog(LLV_ERROR, LOCATION, NULL,
1572			"status mismatched %d.\n", iph1->status);
1573		goto end;
1574	}
1575
1576	/* make ID payload into isakmp status */
1577	if (ipsecdoi_setid1(iph1) < 0)
1578		goto end;
1579
1580#ifdef HAVE_GSSAPI
1581	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
1582	    gssapi_more_tokens(iph1)) {
1583		gssapi_get_rtoken(iph1, &len);
1584		if (len != 0)
1585			dohash = 0;
1586	}
1587#endif
1588
1589	if (dohash) {
1590		/* generate HASH to send */
1591		plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_R\n");
1592		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
1593		if (iph1->hash == NULL)
1594			goto end;
1595	} else
1596		iph1->hash = NULL;
1597
1598	/* set encryption flag */
1599	iph1->flags |= ISAKMP_FLAG_E;
1600
1601	/* create HDR;ID;HASH payload */
1602	iph1->sendbuf = ident_ir3mx(iph1);
1603	if (iph1->sendbuf == NULL)
1604		goto end;
1605
1606	/* send HDR;ID;HASH to responder */
1607	if (isakmp_send(iph1, iph1->sendbuf) < 0)
1608		goto end;
1609
1610	/* the sending message is added to the received-list. */
1611	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1612		plog(LLV_ERROR , LOCATION, NULL,
1613			"failed to add a response packet to the tree.\n");
1614		goto end;
1615	}
1616
1617	/* see handler.h about IV synchronization. */
1618	memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l);
1619
1620	iph1->status = PHASE1ST_ESTABLISHED;
1621
1622	error = 0;
1623
1624end:
1625
1626	return error;
1627}
1628
1629/*
1630 * This is used in main mode for:
1631 * initiator's 3rd exchange send to responder
1632 * 	psk: HDR, KE, Ni
1633 * 	sig: HDR, KE, Ni
1634 * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
1635 * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
1636 * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
1637 * responders 2nd exchnage send to initiator
1638 * 	psk: HDR, KE, Nr
1639 * 	sig: HDR, KE, Nr [, CR ]
1640 * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
1641 * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
1642 */
1643static vchar_t *
1644ident_ir2mx(iph1)
1645	struct ph1handle *iph1;
1646{
1647	vchar_t *buf = 0;
1648	struct payload_list *plist = NULL;
1649	int need_cr = 0;
1650	vchar_t *cr = NULL;
1651	vchar_t *vid = NULL;
1652	int error = -1;
1653#ifdef HAVE_GSSAPI
1654	vchar_t *gsstoken = NULL;
1655#endif
1656#ifdef ENABLE_NATT
1657	vchar_t *natd[2] = { NULL, NULL };
1658#endif
1659
1660	/* create CR if need */
1661	if (iph1->side == RESPONDER
1662	 && iph1->rmconf->send_cr
1663	 && oakley_needcr(iph1->approval->authmethod)
1664	 && iph1->rmconf->peerscertfile == NULL) {
1665		need_cr = 1;
1666		cr = oakley_getcr(iph1);
1667		if (cr == NULL) {
1668			plog(LLV_ERROR, LOCATION, NULL,
1669				"failed to get cr buffer.\n");
1670			goto end;
1671		}
1672	}
1673
1674#ifdef HAVE_GSSAPI
1675	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
1676		gssapi_get_token_to_send(iph1, &gsstoken);
1677#endif
1678
1679	/* create isakmp KE payload */
1680	plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
1681
1682	/* create isakmp NONCE payload */
1683	plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
1684
1685#ifdef HAVE_GSSAPI
1686	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
1687		plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
1688#endif
1689
1690	/* append vendor id, if needed */
1691	if (vid)
1692		plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID);
1693
1694	/* create isakmp CR payload if needed */
1695	if (need_cr)
1696		plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
1697
1698#ifdef ENABLE_NATT
1699	/* generate and append NAT-D payloads */
1700	if (NATT_AVAILABLE(iph1) && iph1->status == PHASE1ST_MSG2RECEIVED)
1701	{
1702		if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
1703			plog(LLV_ERROR, LOCATION, NULL,
1704				"NAT-D hashing failed for %s\n", saddr2str(iph1->remote));
1705			goto end;
1706		}
1707
1708		if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
1709			plog(LLV_ERROR, LOCATION, NULL,
1710				"NAT-D hashing failed for %s\n", saddr2str(iph1->local));
1711			goto end;
1712		}
1713
1714		plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n");
1715		plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d);
1716		plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
1717	}
1718#endif
1719
1720	buf = isakmp_plist_set_all (&plist, iph1);
1721
1722	error = 0;
1723
1724end:
1725	if (error && buf != NULL) {
1726		vfree(buf);
1727		buf = NULL;
1728	}
1729	if (cr)
1730		vfree(cr);
1731#ifdef HAVE_GSSAPI
1732	if (gsstoken)
1733		vfree(gsstoken);
1734#endif
1735	if (vid)
1736		vfree(vid);
1737
1738#ifdef ENABLE_NATT
1739	if (natd[0])
1740		vfree(natd[0]);
1741	if (natd[1])
1742		vfree(natd[1]);
1743#endif
1744
1745	return buf;
1746}
1747
1748/*
1749 * This is used in main mode for:
1750 * initiator's 4th exchange send to responder
1751 * 	psk: HDR*, IDi1, HASH_I
1752 * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
1753 *   gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I >
1754 * 	rsa: HDR*, HASH_I
1755 * 	rev: HDR*, HASH_I
1756 * responders 3rd exchnage send to initiator
1757 * 	psk: HDR*, IDr1, HASH_R
1758 * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
1759 *   gssapi: HDR*, [ IDr1, ] < GSSr(n) | HASH_R >
1760 * 	rsa: HDR*, HASH_R
1761 * 	rev: HDR*, HASH_R
1762 */
1763static vchar_t *
1764ident_ir3mx(iph1)
1765	struct ph1handle *iph1;
1766{
1767	struct payload_list *plist = NULL;
1768	vchar_t *buf = NULL, *new = NULL;
1769	int need_cr = 0;
1770	int need_cert = 0;
1771	vchar_t *cr = NULL;
1772	int error = -1;
1773#ifdef HAVE_GSSAPI
1774	int nptype;
1775	vchar_t *gsstoken = NULL;
1776	vchar_t *gsshash = NULL;
1777#endif
1778
1779	switch (AUTHMETHOD(iph1)) {
1780	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1781#ifdef ENABLE_HYBRID
1782	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
1783	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1784	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1785	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
1786#endif
1787		/* create isakmp ID payload */
1788		plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
1789
1790		/* create isakmp HASH payload */
1791		plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH);
1792		break;
1793	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1794	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1795#ifdef ENABLE_HYBRID
1796	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1797	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1798	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1799	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1800	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1801	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1802#endif
1803		if (oakley_getmycert(iph1) < 0)
1804			goto end;
1805
1806		if (oakley_getsign(iph1) < 0)
1807			goto end;
1808
1809		/* create CR if need */
1810		if (iph1->side == INITIATOR
1811		 && iph1->rmconf->send_cr
1812	 	 && oakley_needcr(iph1->approval->authmethod)
1813		 && iph1->rmconf->peerscertfile == NULL) {
1814			need_cr = 1;
1815			cr = oakley_getcr(iph1);
1816			if (cr == NULL) {
1817				plog(LLV_ERROR, LOCATION, NULL,
1818					"failed to get cr buffer.\n");
1819				goto end;
1820			}
1821		}
1822
1823		if (iph1->cert != NULL && iph1->rmconf->send_cert)
1824			need_cert = 1;
1825
1826		/* add ID payload */
1827		plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
1828
1829		/* add CERT payload if there */
1830		if (need_cert)
1831			plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT);
1832		/* add SIG payload */
1833		plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG);
1834
1835		/* create isakmp CR payload */
1836		if (need_cr)
1837			plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
1838		break;
1839#ifdef HAVE_GSSAPI
1840	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1841		if (iph1->hash != NULL) {
1842			gsshash = gssapi_wraphash(iph1);
1843			if (gsshash == NULL)
1844				goto end;
1845		} else {
1846			gssapi_get_token_to_send(iph1, &gsstoken);
1847		}
1848
1849		if (!gssapi_id_sent(iph1)) {
1850			/* create isakmp ID payload */
1851			plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
1852			gssapi_set_id_sent(iph1);
1853		}
1854
1855		if (iph1->hash != NULL)
1856			/* create isakmp HASH payload */
1857			plist = isakmp_plist_append(plist, gsshash, ISAKMP_NPTYPE_HASH);
1858		else
1859			plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
1860		break;
1861#endif
1862	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1863	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1864#ifdef ENABLE_HYBRID
1865	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
1866	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1867	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
1868	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1869#endif
1870		plog(LLV_ERROR, LOCATION, NULL,
1871			"not supported authentication type %d\n",
1872			iph1->approval->authmethod);
1873		goto end;
1874	default:
1875		plog(LLV_ERROR, LOCATION, NULL,
1876			"invalid authentication type %d\n",
1877			iph1->approval->authmethod);
1878		goto end;
1879	}
1880
1881	buf = isakmp_plist_set_all (&plist, iph1);
1882
1883#ifdef HAVE_PRINT_ISAKMP_C
1884	isakmp_printpacket(buf, iph1->local, iph1->remote, 1);
1885#endif
1886
1887	/* encoding */
1888	new = oakley_do_encrypt(iph1, buf, iph1->ivm->ive, iph1->ivm->iv);
1889	if (new == NULL)
1890		goto end;
1891
1892	vfree(buf);
1893
1894	buf = new;
1895
1896	error = 0;
1897
1898end:
1899#ifdef HAVE_GSSAPI
1900	if (gsstoken)
1901		vfree(gsstoken);
1902#endif
1903	if (cr)
1904		vfree(cr);
1905	if (error && buf != NULL) {
1906		vfree(buf);
1907		buf = NULL;
1908	}
1909
1910	return buf;
1911}
1912