1/*	$KAME: isakmp_ident.c,v 1.63 2001/12/12 17:57:26 sakane Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/* Identity Protecion Exchange (Main Mode) */
33
34#include <sys/types.h>
35#include <sys/param.h>
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40#include <errno.h>
41#if TIME_WITH_SYS_TIME
42# include <sys/time.h>
43# include <time.h>
44#else
45# if HAVE_SYS_TIME_H
46#  include <sys/time.h>
47# else
48#  include <time.h>
49# endif
50#endif
51
52#include "var.h"
53#include "misc.h"
54#include "vmbuf.h"
55#include "plog.h"
56#include "sockmisc.h"
57#include "schedule.h"
58#include "debug.h"
59
60#include "localconf.h"
61#include "remoteconf.h"
62#include "isakmp_var.h"
63#include "isakmp.h"
64#include "oakley.h"
65#include "handler.h"
66#include "ipsec_doi.h"
67#include "crypto_openssl.h"
68#include "pfkey.h"
69#include "isakmp_ident.h"
70#include "isakmp_inf.h"
71#include "vendorid.h"
72
73#ifdef HAVE_GSSAPI
74#include "gssapi.h"
75#endif
76
77static vchar_t *ident_ir2mx __P((struct ph1handle *));
78static vchar_t *ident_ir3mx __P((struct ph1handle *));
79
80/* %%%
81 * begin Identity Protection Mode as initiator.
82 */
83/*
84 * send to responder
85 * 	psk: HDR, SA
86 * 	sig: HDR, SA
87 * 	rsa: HDR, SA
88 * 	rev: HDR, SA
89 */
90int
91ident_i1send(iph1, msg)
92	struct ph1handle *iph1;
93	vchar_t *msg; /* must be null */
94{
95	struct isakmp_gen *gen;
96	caddr_t p;
97	int tlen;
98	int error = -1;
99
100	/* validity check */
101	if (msg != NULL) {
102		plog(LLV_ERROR, LOCATION, NULL,
103			"msg has to be NULL in this function.\n");
104		goto end;
105	}
106	if (iph1->status != PHASE1ST_START) {
107		plog(LLV_ERROR, LOCATION, NULL,
108			"status mismatched %d.\n", iph1->status);
109		goto end;
110	}
111
112	/* create isakmp index */
113	memset(&iph1->index, 0, sizeof(iph1->index));
114	isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
115
116	/* create SA payload for my proposal */
117	iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
118	if (iph1->sa == NULL)
119		goto end;
120
121	/* create buffer to send isakmp payload */
122	tlen = sizeof(struct isakmp)
123		+ sizeof(*gen) + iph1->sa->l;
124
125	iph1->sendbuf = vmalloc(tlen);
126	if (iph1->sendbuf == NULL) {
127		plog(LLV_ERROR, LOCATION, NULL,
128			"failed to get buffer to send.\n");
129		goto end;
130	}
131
132	/* set isakmp header */
133	p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
134	if (p == NULL)
135		goto end;
136
137	/* set SA payload to propose */
138	p = set_isakmp_payload(p, iph1->sa, ISAKMP_NPTYPE_NONE);
139
140#ifdef HAVE_PRINT_ISAKMP_C
141	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
142#endif
143
144	/* send the packet, add to the schedule to resend */
145	iph1->retry_counter = iph1->rmconf->retry_counter;
146	if (isakmp_ph1resend(iph1) == -1)
147		goto end;
148
149	iph1->status = PHASE1ST_MSG1SENT;
150
151	error = 0;
152
153end:
154
155	return error;
156}
157
158/*
159 * receive from responder
160 * 	psk: HDR, SA
161 * 	sig: HDR, SA
162 * 	rsa: HDR, SA
163 * 	rev: HDR, SA
164 */
165int
166ident_i2recv(iph1, msg)
167	struct ph1handle *iph1;
168	vchar_t *msg;
169{
170	vchar_t *pbuf = NULL;
171	struct isakmp_parse_t *pa;
172	vchar_t *satmp = NULL;
173	int error = -1;
174
175	/* validity check */
176	if (iph1->status != PHASE1ST_MSG1SENT) {
177		plog(LLV_ERROR, LOCATION, NULL,
178			"status mismatched %d.\n", iph1->status);
179		goto end;
180	}
181
182	/* validate the type of next payload */
183	/*
184	 * NOTE: RedCreek(as responder) attaches N[responder-lifetime] here,
185	 *	if proposal-lifetime > lifetime-redcreek-wants.
186	 *	(see doi-08 4.5.4)
187	 *	=> According to the seciton 4.6.3 in RFC 2407, This is illegal.
188	 * NOTE: we do not really care about ordering of VID and N.
189	 *	does it matters?
190	 * NOTE: even if there's multiple VID/N, we'll ignore them.
191	 */
192	pbuf = isakmp_parse(msg);
193	if (pbuf == NULL)
194		goto end;
195	pa = (struct isakmp_parse_t *)pbuf->v;
196
197	/* SA payload is fixed postion */
198	if (pa->type != ISAKMP_NPTYPE_SA) {
199		plog(LLV_ERROR, LOCATION, iph1->remote,
200			"received invalid next payload type %d, "
201			"expecting %d.\n",
202			pa->type, ISAKMP_NPTYPE_SA);
203		goto end;
204	}
205	if (isakmp_p2ph(&satmp, pa->ptr) < 0)
206		goto end;
207	pa++;
208
209	for (/*nothing*/;
210	     pa->type != ISAKMP_NPTYPE_NONE;
211	     pa++) {
212
213		switch (pa->type) {
214		case ISAKMP_NPTYPE_VID:
215			(void)check_vendorid(pa->ptr);
216			break;
217		default:
218			/* don't send information, see ident_r1recv() */
219			plog(LLV_ERROR, LOCATION, iph1->remote,
220				"ignore the packet, "
221				"received unexpecting payload type %d.\n",
222				pa->type);
223			goto end;
224		}
225	}
226
227	/* check SA payload and set approval SA for use */
228	if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
229		plog(LLV_ERROR, LOCATION, iph1->remote,
230			"failed to get valid proposal.\n");
231		goto end;
232	}
233	if (iph1->sa_ret) {
234		vfree(iph1->sa_ret);
235		iph1->sa_ret = NULL;
236	}
237
238	iph1->status = PHASE1ST_MSG2RECEIVED;
239
240	error = 0;
241
242end:
243	if (pbuf)
244		vfree(pbuf);
245	if (satmp)
246		vfree(satmp);
247	return error;
248}
249
250/*
251 * send to responder
252 * 	psk: HDR, KE, Ni
253 * 	sig: HDR, KE, Ni
254 *   gssapi: HDR, KE, Ni, GSSi
255 * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
256 * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
257 * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
258 */
259int
260ident_i2send(iph1, msg)
261	struct ph1handle *iph1;
262	vchar_t *msg;
263{
264	int error = -1;
265
266	/* validity check */
267	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
268		plog(LLV_ERROR, LOCATION, NULL,
269			"status mismatched %d.\n", iph1->status);
270		goto end;
271	}
272
273	/* fix isakmp index */
274	memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
275		sizeof(cookie_t));
276
277	/* generate DH public value */
278	if (oakley_dh_generate(iph1->approval->dhgrp,
279				&iph1->dhpub, &iph1->dhpriv) < 0)
280		goto end;
281
282	/* generate NONCE value */
283	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
284	if (iph1->nonce == NULL)
285		goto end;
286
287#ifdef HAVE_GSSAPI
288	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
289	    gssapi_get_itoken(iph1, NULL) < 0)
290		goto end;
291#endif
292
293	/* create buffer to send isakmp payload */
294	iph1->sendbuf = ident_ir2mx(iph1);
295	if (iph1->sendbuf == NULL)
296		goto end;
297
298#ifdef HAVE_PRINT_ISAKMP_C
299	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
300#endif
301
302	/* send the packet, add to the schedule to resend */
303	iph1->retry_counter = iph1->rmconf->retry_counter;
304	if (isakmp_ph1resend(iph1) == -1)
305		goto end;
306
307	/* the sending message is added to the received-list. */
308	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
309		plog(LLV_ERROR , LOCATION, NULL,
310			"failed to add a response packet to the tree.\n");
311		goto end;
312	}
313
314	iph1->status = PHASE1ST_MSG2SENT;
315
316	error = 0;
317
318end:
319	return error;
320}
321
322/*
323 * receive from responder
324 * 	psk: HDR, KE, Nr
325 * 	sig: HDR, KE, Nr [, CR ]
326 *   gssapi: HDR, KE, Nr, GSSr
327 * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
328 * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
329 */
330int
331ident_i3recv(iph1, msg)
332	struct ph1handle *iph1;
333	vchar_t *msg;
334{
335	vchar_t *pbuf = NULL;
336	struct isakmp_parse_t *pa;
337	int error = -1;
338#ifdef HAVE_GSSAPI
339	vchar_t *gsstoken = NULL;
340#endif
341
342	/* validity check */
343	if (iph1->status != PHASE1ST_MSG2SENT) {
344		plog(LLV_ERROR, LOCATION, NULL,
345			"status mismatched %d.\n", iph1->status);
346		goto end;
347	}
348
349	/* validate the type of next payload */
350	pbuf = isakmp_parse(msg);
351	if (pbuf == NULL)
352		goto end;
353
354	for (pa = (struct isakmp_parse_t *)pbuf->v;
355	     pa->type != ISAKMP_NPTYPE_NONE;
356	     pa++) {
357
358		switch (pa->type) {
359		case ISAKMP_NPTYPE_KE:
360			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
361				goto end;
362			break;
363		case ISAKMP_NPTYPE_NONCE:
364			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
365				goto end;
366			break;
367		case ISAKMP_NPTYPE_VID:
368			(void)check_vendorid(pa->ptr);
369			break;
370#ifdef HAVE_SIGNING_C
371		case ISAKMP_NPTYPE_CR:
372			if (oakley_savecr(iph1, pa->ptr) < 0)
373				goto end;
374			break;
375#endif
376#ifdef HAVE_GSSAPI
377		case ISAKMP_NPTYPE_GSS:
378			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
379				goto end;
380			gssapi_save_received_token(iph1, gsstoken);
381			break;
382#endif
383		default:
384			/* don't send information, see ident_r1recv() */
385			plog(LLV_ERROR, LOCATION, iph1->remote,
386				"ignore the packet, "
387				"received unexpecting payload type %d.\n",
388				pa->type);
389			goto end;
390		}
391	}
392
393	/* payload existency check */
394	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
395		plog(LLV_ERROR, LOCATION, iph1->remote,
396			"few isakmp message received.\n");
397		goto end;
398	}
399
400#ifdef HAVE_SIGNING_C
401	if (oakley_checkcr(iph1) < 0) {
402		/* Ignore this error in order to be interoperability. */
403		;
404	}
405#endif
406
407	iph1->status = PHASE1ST_MSG3RECEIVED;
408
409	error = 0;
410
411end:
412	if (pbuf)
413		vfree(pbuf);
414	if (error) {
415		VPTRINIT(iph1->dhpub_p);
416		VPTRINIT(iph1->nonce_p);
417		VPTRINIT(iph1->id_p);
418		oakley_delcert(iph1->cr_p);
419		iph1->cr_p = NULL;
420	}
421
422	return error;
423}
424
425/*
426 * send to responder
427 * 	psk: HDR*, IDi1, HASH_I
428 * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
429 *   gssapi: HDR*, IDi1, < Gssi(n) | HASH_I >
430 * 	rsa: HDR*, HASH_I
431 * 	rev: HDR*, HASH_I
432 */
433int
434ident_i3send(iph1, msg0)
435	struct ph1handle *iph1;
436	vchar_t *msg0;
437{
438	int error = -1;
439	int dohash = 1;
440#ifdef HAVE_GSSAPI
441	int len;
442#endif
443
444	/* validity check */
445	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
446		plog(LLV_ERROR, LOCATION, NULL,
447			"status mismatched %d.\n", iph1->status);
448		goto end;
449	}
450
451	/* compute sharing secret of DH */
452	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
453				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
454		goto end;
455
456	/* generate SKEYIDs & IV & final cipher key */
457	if (oakley_skeyid(iph1) < 0)
458		goto end;
459	if (oakley_skeyid_dae(iph1) < 0)
460		goto end;
461	if (oakley_compute_enckey(iph1) < 0)
462		goto end;
463	if (oakley_newiv(iph1) < 0)
464		goto end;
465
466	/* make ID payload into isakmp status */
467	if (ipsecdoi_setid1(iph1) < 0)
468		goto end;
469
470#ifdef HAVE_GSSAPI
471	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
472	    gssapi_more_tokens(iph1)) {
473		plog(LLV_DEBUG, LOCATION, NULL, "calling get_itoken\n");
474		if (gssapi_get_itoken(iph1, &len) < 0)
475			goto end;
476		if (len != 0)
477			dohash = 0;
478	}
479#endif
480
481	/* generate HASH to send */
482	if (dohash) {
483		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
484		if (iph1->hash == NULL)
485			goto end;
486	} else
487		iph1->hash = NULL;
488
489	/* set encryption flag */
490	iph1->flags |= ISAKMP_FLAG_E;
491
492	/* create HDR;ID;HASH payload */
493	iph1->sendbuf = ident_ir3mx(iph1);
494	if (iph1->sendbuf == NULL)
495		goto end;
496
497	/* send the packet, add to the schedule to resend */
498	iph1->retry_counter = iph1->rmconf->retry_counter;
499	if (isakmp_ph1resend(iph1) == -1)
500		goto end;
501
502	/* the sending message is added to the received-list. */
503	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg0) == -1) {
504		plog(LLV_ERROR , LOCATION, NULL,
505			"failed to add a response packet to the tree.\n");
506		goto end;
507	}
508
509	/* see handler.h about IV synchronization. */
510	memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l);
511
512	iph1->status = PHASE1ST_MSG3SENT;
513
514	error = 0;
515
516end:
517	return error;
518}
519
520/*
521 * receive from responder
522 * 	psk: HDR*, IDr1, HASH_R
523 * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
524 *   gssapi: HDR*, IDr1, < GSSr(n) | HASH_R >
525 * 	rsa: HDR*, HASH_R
526 * 	rev: HDR*, HASH_R
527 */
528int
529ident_i4recv(iph1, msg0)
530	struct ph1handle *iph1;
531	vchar_t *msg0;
532{
533	vchar_t *pbuf = NULL;
534	struct isakmp_parse_t *pa;
535	vchar_t *msg = NULL;
536	int error = -1;
537	int type;
538#ifdef HAVE_GSSAPI
539	vchar_t *gsstoken = NULL;
540#endif
541
542	/* validity check */
543	if (iph1->status != PHASE1ST_MSG3SENT) {
544		plog(LLV_ERROR, LOCATION, NULL,
545			"status mismatched %d.\n", iph1->status);
546		goto end;
547	}
548
549	/* decrypting */
550	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
551		plog(LLV_ERROR, LOCATION, iph1->remote,
552			"ignore the packet, "
553			"expecting the packet encrypted.\n");
554		goto end;
555	}
556	msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive);
557	if (msg == NULL)
558		goto end;
559
560	/* validate the type of next payload */
561	pbuf = isakmp_parse(msg);
562	if (pbuf == NULL)
563		goto end;
564
565	iph1->pl_hash = NULL;
566
567	for (pa = (struct isakmp_parse_t *)pbuf->v;
568	     pa->type != ISAKMP_NPTYPE_NONE;
569	     pa++) {
570
571		switch (pa->type) {
572		case ISAKMP_NPTYPE_ID:
573			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
574				goto end;
575			break;
576		case ISAKMP_NPTYPE_HASH:
577			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
578			break;
579#ifdef HAVE_SIGNING_C
580		case ISAKMP_NPTYPE_CERT:
581			if (oakley_savecert(iph1, pa->ptr) < 0)
582				goto end;
583			break;
584		case ISAKMP_NPTYPE_SIG:
585			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
586				goto end;
587			break;
588#endif
589#ifdef HAVE_GSSAPI
590		case ISAKMP_NPTYPE_GSS:
591			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
592				goto end;
593			gssapi_save_received_token(iph1, gsstoken);
594			break;
595#endif
596		case ISAKMP_NPTYPE_VID:
597			(void)check_vendorid(pa->ptr);
598			break;
599		case ISAKMP_NPTYPE_N:
600			isakmp_check_notify(pa->ptr, iph1);
601			break;
602		default:
603			/* don't send information, see ident_r1recv() */
604			plog(LLV_ERROR, LOCATION, iph1->remote,
605				"ignore the packet, "
606				"received unexpecting payload type %d.\n",
607				pa->type);
608			goto end;
609		}
610	}
611
612	/* payload existency check */
613
614	/* see handler.h about IV synchronization. */
615	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l);
616
617	/* verify identifier */
618	if (ipsecdoi_checkid1(iph1) != 0) {
619		plog(LLV_ERROR, LOCATION, iph1->remote,
620			"invalid ID payload.\n");
621		goto end;
622	}
623
624	/* validate authentication value */
625#ifdef HAVE_GSSAPI
626	if (gsstoken == NULL) {
627#endif
628		type = oakley_validate_auth(iph1);
629		if (type != 0) {
630			if (type == -1) {
631				/* msg printed inner oakley_validate_auth() */
632				goto end;
633			}
634			isakmp_info_send_n1(iph1, type, NULL);
635			goto end;
636		}
637#ifdef HAVE_GSSAPI
638	}
639#endif
640
641
642	plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID:");
643	plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l);
644
645	/*
646	 * If we got a GSS token, we need to this roundtrip again.
647	 */
648#ifdef HAVE_GSSAPI
649	iph1->status = gsstoken != 0 ? PHASE1ST_MSG3RECEIVED :
650	    PHASE1ST_MSG4RECEIVED;
651#else
652	iph1->status = PHASE1ST_MSG4RECEIVED;
653#endif
654
655	error = 0;
656
657end:
658	if (pbuf)
659		vfree(pbuf);
660	if (msg)
661		vfree(msg);
662#ifdef HAVE_GSSAPI
663	if (gsstoken)
664		vfree(gsstoken);
665#endif
666
667	if (error) {
668		VPTRINIT(iph1->id_p);
669		oakley_delcert(iph1->cert_p);
670		iph1->cert_p = NULL;
671		oakley_delcert(iph1->crl_p);
672		iph1->crl_p = NULL;
673		VPTRINIT(iph1->sig_p);
674	}
675
676	return error;
677}
678
679/*
680 * status update and establish isakmp sa.
681 */
682int
683ident_i4send(iph1, msg)
684	struct ph1handle *iph1;
685	vchar_t *msg;
686{
687	int error = -1;
688
689	/* validity check */
690	if (iph1->status != PHASE1ST_MSG4RECEIVED) {
691		plog(LLV_ERROR, LOCATION, NULL,
692			"status mismatched %d.\n", iph1->status);
693		goto end;
694	}
695
696	/* see handler.h about IV synchronization. */
697	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
698
699	iph1->status = PHASE1ST_ESTABLISHED;
700
701	error = 0;
702
703end:
704	return error;
705}
706
707/*
708 * receive from initiator
709 * 	psk: HDR, SA
710 * 	sig: HDR, SA
711 * 	rsa: HDR, SA
712 * 	rev: HDR, SA
713 */
714int
715ident_r1recv(iph1, msg)
716	struct ph1handle *iph1;
717	vchar_t *msg;
718{
719	vchar_t *pbuf = NULL;
720	struct isakmp_parse_t *pa;
721	int error = -1;
722
723	/* validity check */
724	if (iph1->status != PHASE1ST_START) {
725		plog(LLV_ERROR, LOCATION, NULL,
726			"status mismatched %d.\n", iph1->status);
727		goto end;
728	}
729
730	/* validate the type of next payload */
731	pbuf = isakmp_parse(msg);
732	if (pbuf == NULL)
733		goto end;
734	pa = (struct isakmp_parse_t *)pbuf->v;
735
736	/* check the position of SA payload */
737	if (pa->type != ISAKMP_NPTYPE_SA) {
738		plog(LLV_ERROR, LOCATION, iph1->remote,
739			"received invalid next payload type %d, "
740			"expecting %d.\n",
741			pa->type, ISAKMP_NPTYPE_SA);
742		goto end;
743	}
744	if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
745		goto end;
746	pa++;
747
748	for (/*nothing*/;
749	     pa->type != ISAKMP_NPTYPE_NONE;
750	     pa++) {
751
752		switch (pa->type) {
753		case ISAKMP_NPTYPE_VID:
754			(void)check_vendorid(pa->ptr);
755			break;
756		default:
757			/*
758			 * We don't send information to the peer even
759			 * if we received malformed packet.  Because we
760			 * can't distinguish the malformed packet and
761			 * the re-sent packet.  And we do same behavior
762			 * when we expect encrypted packet.
763			 */
764			plog(LLV_ERROR, LOCATION, iph1->remote,
765				"ignore the packet, "
766				"received unexpecting payload type %d.\n",
767				pa->type);
768			goto end;
769		}
770	}
771
772	/* check SA payload and set approval SA for use */
773	if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
774		plog(LLV_ERROR, LOCATION, iph1->remote,
775			"failed to get valid proposal.\n");
776		goto end;
777	}
778
779	iph1->status = PHASE1ST_MSG1RECEIVED;
780
781	error = 0;
782
783end:
784	if (pbuf)
785		vfree(pbuf);
786	if (error) {
787		VPTRINIT(iph1->sa);
788	}
789
790	return error;
791}
792
793/*
794 * send to initiator
795 * 	psk: HDR, SA
796 * 	sig: HDR, SA
797 * 	rsa: HDR, SA
798 * 	rev: HDR, SA
799 */
800int
801ident_r1send(iph1, msg)
802	struct ph1handle *iph1;
803	vchar_t *msg;
804{
805	struct isakmp_gen *gen;
806	caddr_t p;
807	int tlen;
808	int error = -1;
809	vchar_t *gss_sa = NULL;
810	vchar_t *vid = NULL;
811
812	/* validity check */
813	if (iph1->status != PHASE1ST_MSG1RECEIVED) {
814		plog(LLV_ERROR, LOCATION, NULL,
815			"status mismatched %d.\n", iph1->status);
816		goto end;
817	}
818
819	/* set responder's cookie */
820	isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
821
822#ifdef HAVE_GSSAPI
823	if (iph1->approval->gssid != NULL)
824		gss_sa = ipsecdoi_setph1proposal(iph1->approval);
825	else
826#endif
827		gss_sa = iph1->sa_ret;
828
829	/* create buffer to send isakmp payload */
830	tlen = sizeof(struct isakmp)
831		+ sizeof(*gen) + gss_sa->l;
832
833	if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
834		tlen += sizeof(*gen) + vid->l;
835
836	iph1->sendbuf = vmalloc(tlen);
837	if (iph1->sendbuf == NULL) {
838		plog(LLV_ERROR, LOCATION, NULL,
839			"failed to get buffer to send.\n");
840		goto end;
841	}
842
843	/* set isakmp header */
844	p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
845	if (p == NULL)
846		goto end;
847
848	/* set SA payload to reply */
849	p = set_isakmp_payload(p, gss_sa,
850	    vid ? ISAKMP_NPTYPE_VID
851		: ISAKMP_NPTYPE_NONE);
852
853	/* Set Vendor ID, if necessary. */
854	if (vid)
855		p = set_isakmp_payload(p, vid, ISAKMP_NPTYPE_NONE);
856
857#ifdef HAVE_PRINT_ISAKMP_C
858	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
859#endif
860
861	/* send the packet, add to the schedule to resend */
862	iph1->retry_counter = iph1->rmconf->retry_counter;
863	if (isakmp_ph1resend(iph1) == -1)
864		goto end;
865
866	/* the sending message is added to the received-list. */
867	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
868		plog(LLV_ERROR , LOCATION, NULL,
869			"failed to add a response packet to the tree.\n");
870		goto end;
871	}
872
873	iph1->status = PHASE1ST_MSG1SENT;
874
875	error = 0;
876
877end:
878#ifdef HAVE_GSSAPI
879	if (gss_sa != iph1->sa_ret)
880		vfree(gss_sa);
881#endif
882	if (vid)
883		vfree(vid);
884	return error;
885}
886
887/*
888 * receive from initiator
889 * 	psk: HDR, KE, Ni
890 * 	sig: HDR, KE, Ni
891 *   gssapi: HDR, KE, Ni, GSSi
892 * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
893 * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
894 * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
895 */
896int
897ident_r2recv(iph1, msg)
898	struct ph1handle *iph1;
899	vchar_t *msg;
900{
901	vchar_t *pbuf = NULL;
902	struct isakmp_parse_t *pa;
903	int error = -1;
904#ifdef HAVE_GSSAPI
905	vchar_t *gsstoken = NULL;
906#endif
907
908	/* validity check */
909	if (iph1->status != PHASE1ST_MSG1SENT) {
910		plog(LLV_ERROR, LOCATION, NULL,
911			"status mismatched %d.\n", iph1->status);
912		goto end;
913	}
914
915	/* validate the type of next payload */
916	pbuf = isakmp_parse(msg);
917	if (pbuf == NULL)
918		goto end;
919
920	for (pa = (struct isakmp_parse_t *)pbuf->v;
921	     pa->type != ISAKMP_NPTYPE_NONE;
922	     pa++) {
923
924		switch (pa->type) {
925		case ISAKMP_NPTYPE_KE:
926			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
927				goto end;
928			break;
929		case ISAKMP_NPTYPE_NONCE:
930			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
931				goto end;
932			break;
933		case ISAKMP_NPTYPE_VID:
934			(void)check_vendorid(pa->ptr);
935			break;
936		case ISAKMP_NPTYPE_CR:
937			plog(LLV_WARNING, LOCATION, iph1->remote,
938				"CR received, ignore it. "
939				"It should be in other exchange.\n");
940			break;
941#ifdef HAVE_GSSAPI
942		case ISAKMP_NPTYPE_GSS:
943			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
944				goto end;
945			gssapi_save_received_token(iph1, gsstoken);
946			break;
947#endif
948		default:
949			/* don't send information, see ident_r1recv() */
950			plog(LLV_ERROR, LOCATION, iph1->remote,
951				"ignore the packet, "
952				"received unexpecting payload type %d.\n",
953				pa->type);
954			goto end;
955		}
956	}
957
958	/* payload existency check */
959	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
960		plog(LLV_ERROR, LOCATION, iph1->remote,
961			"few isakmp message received.\n");
962		goto end;
963	}
964
965	iph1->status = PHASE1ST_MSG2RECEIVED;
966
967	error = 0;
968
969end:
970	if (pbuf)
971		vfree(pbuf);
972#ifdef HAVE_GSSAPI
973	if (gsstoken)
974		vfree(gsstoken);
975#endif
976
977	if (error) {
978		VPTRINIT(iph1->dhpub_p);
979		VPTRINIT(iph1->nonce_p);
980		VPTRINIT(iph1->id_p);
981	}
982
983	return error;
984}
985
986/*
987 * send to initiator
988 * 	psk: HDR, KE, Nr
989 * 	sig: HDR, KE, Nr [, CR ]
990 *   gssapi: HDR, KE, Nr, GSSr
991 * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
992 * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
993 */
994int
995ident_r2send(iph1, msg)
996	struct ph1handle *iph1;
997	vchar_t *msg;
998{
999	int error = -1;
1000
1001	/* validity check */
1002	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
1003		plog(LLV_ERROR, LOCATION, NULL,
1004			"status mismatched %d.\n", iph1->status);
1005		goto end;
1006	}
1007
1008	/* generate DH public value */
1009	if (oakley_dh_generate(iph1->approval->dhgrp,
1010				&iph1->dhpub, &iph1->dhpriv) < 0)
1011		goto end;
1012
1013	/* generate NONCE value */
1014	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
1015	if (iph1->nonce == NULL)
1016		goto end;
1017
1018#ifdef HAVE_GSSAPI
1019	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
1020		gssapi_get_rtoken(iph1, NULL);
1021#endif
1022
1023	/* create HDR;KE;NONCE payload */
1024	iph1->sendbuf = ident_ir2mx(iph1);
1025	if (iph1->sendbuf == NULL)
1026		goto end;
1027
1028#ifdef HAVE_PRINT_ISAKMP_C
1029	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
1030#endif
1031
1032	/* send the packet, add to the schedule to resend */
1033	iph1->retry_counter = iph1->rmconf->retry_counter;
1034	if (isakmp_ph1resend(iph1) == -1)
1035		goto end;
1036
1037	/* the sending message is added to the received-list. */
1038	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1039		plog(LLV_ERROR , LOCATION, NULL,
1040			"failed to add a response packet to the tree.\n");
1041		goto end;
1042	}
1043
1044	/* compute sharing secret of DH */
1045	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
1046				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
1047		goto end;
1048
1049	/* generate SKEYIDs & IV & final cipher key */
1050	if (oakley_skeyid(iph1) < 0)
1051		goto end;
1052	if (oakley_skeyid_dae(iph1) < 0)
1053		goto end;
1054	if (oakley_compute_enckey(iph1) < 0)
1055		goto end;
1056	if (oakley_newiv(iph1) < 0)
1057		goto end;
1058
1059	iph1->status = PHASE1ST_MSG2SENT;
1060
1061	error = 0;
1062
1063end:
1064	return error;
1065}
1066
1067/*
1068 * receive from initiator
1069 * 	psk: HDR*, IDi1, HASH_I
1070 * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
1071 *   gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I >
1072 * 	rsa: HDR*, HASH_I
1073 * 	rev: HDR*, HASH_I
1074 */
1075int
1076ident_r3recv(iph1, msg0)
1077	struct ph1handle *iph1;
1078	vchar_t *msg0;
1079{
1080	vchar_t *msg = NULL;
1081	vchar_t *pbuf = NULL;
1082	struct isakmp_parse_t *pa;
1083	int error = -1;
1084	int type;
1085#ifdef HAVE_GSSAPI
1086	vchar_t *gsstoken = NULL;
1087#endif
1088
1089	/* validity check */
1090	if (iph1->status != PHASE1ST_MSG2SENT) {
1091		plog(LLV_ERROR, LOCATION, NULL,
1092			"status mismatched %d.\n", iph1->status);
1093		goto end;
1094	}
1095
1096	/* decrypting */
1097	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1098		plog(LLV_ERROR, LOCATION, iph1->remote,
1099			"reject the packet, "
1100			"expecting the packet encrypted.\n");
1101		goto end;
1102	}
1103	msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive);
1104	if (msg == NULL)
1105		goto end;
1106
1107	/* validate the type of next payload */
1108	pbuf = isakmp_parse(msg);
1109	if (pbuf == NULL)
1110		goto end;
1111
1112	iph1->pl_hash = NULL;
1113
1114	for (pa = (struct isakmp_parse_t *)pbuf->v;
1115	     pa->type != ISAKMP_NPTYPE_NONE;
1116	     pa++) {
1117
1118		switch (pa->type) {
1119		case ISAKMP_NPTYPE_ID:
1120			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
1121				goto end;
1122			break;
1123		case ISAKMP_NPTYPE_HASH:
1124			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
1125			break;
1126#ifdef HAVE_SIGNING_C
1127		case ISAKMP_NPTYPE_CR:
1128			if (oakley_savecr(iph1, pa->ptr) < 0)
1129				goto end;
1130			break;
1131		case ISAKMP_NPTYPE_CERT:
1132			if (oakley_savecert(iph1, pa->ptr) < 0)
1133				goto end;
1134			break;
1135		case ISAKMP_NPTYPE_SIG:
1136			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
1137				goto end;
1138			break;
1139#endif
1140#ifdef HAVE_GSSAPI
1141		case ISAKMP_NPTYPE_GSS:
1142			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
1143				goto end;
1144			gssapi_save_received_token(iph1, gsstoken);
1145			break;
1146#endif
1147		case ISAKMP_NPTYPE_VID:
1148			(void)check_vendorid(pa->ptr);
1149			break;
1150		case ISAKMP_NPTYPE_N:
1151			isakmp_check_notify(pa->ptr, iph1);
1152			break;
1153		default:
1154			/* don't send information, see ident_r1recv() */
1155			plog(LLV_ERROR, LOCATION, iph1->remote,
1156				"ignore the packet, "
1157				"received unexpecting payload type %d.\n",
1158				pa->type);
1159			goto end;
1160		}
1161	}
1162
1163	/* payload existency check */
1164    {
1165	int ng = 0;
1166
1167	switch (iph1->approval->authmethod) {
1168	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1169		if (iph1->id_p == NULL || iph1->pl_hash == NULL)
1170			ng++;
1171		break;
1172	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1173	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1174		if (iph1->id_p == NULL || iph1->sig_p == NULL)
1175			ng++;
1176		break;
1177	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1178	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1179		if (iph1->pl_hash == NULL)
1180			ng++;
1181		break;
1182#ifdef HAVE_GSSAPI
1183	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1184		if (gsstoken == NULL && iph1->pl_hash == NULL)
1185			ng++;
1186		break;
1187#endif
1188	default:
1189		plog(LLV_ERROR, LOCATION, iph1->remote,
1190			"invalid authmethod %d why ?\n",
1191			iph1->approval->authmethod);
1192		goto end;
1193	}
1194	if (ng) {
1195		plog(LLV_ERROR, LOCATION, iph1->remote,
1196			"few isakmp message received.\n");
1197		goto end;
1198	}
1199    }
1200
1201	/* see handler.h about IV synchronization. */
1202	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l);
1203
1204	/* verify identifier */
1205	if (ipsecdoi_checkid1(iph1) != 0) {
1206		plog(LLV_ERROR, LOCATION, iph1->remote,
1207			"invalid ID payload.\n");
1208		goto end;
1209	}
1210
1211	/* validate authentication value */
1212#ifdef HAVE_GSSAPI
1213	if (gsstoken == NULL) {
1214#endif
1215		type = oakley_validate_auth(iph1);
1216		if (type != 0) {
1217			if (type == -1) {
1218				/* msg printed inner oakley_validate_auth() */
1219				goto end;
1220			}
1221			isakmp_info_send_n1(iph1, type, NULL);
1222			goto end;
1223		}
1224#ifdef HAVE_GSSAPI
1225	}
1226#endif
1227
1228#ifdef HAVE_SIGNING_C
1229	if (oakley_checkcr(iph1) < 0) {
1230		/* Ignore this error in order to be interoperability. */
1231		;
1232	}
1233#endif
1234
1235
1236	plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID\n");
1237	plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l);
1238
1239#ifdef HAVE_GSSAPI
1240	iph1->status = gsstoken != NULL ? PHASE1ST_MSG2RECEIVED :
1241	    PHASE1ST_MSG3RECEIVED;
1242#else
1243	iph1->status = PHASE1ST_MSG3RECEIVED;
1244#endif
1245
1246	error = 0;
1247
1248end:
1249	if (pbuf)
1250		vfree(pbuf);
1251	if (msg)
1252		vfree(msg);
1253#ifdef HAVE_GSSAPI
1254	if (gsstoken)
1255		vfree(gsstoken);
1256#endif
1257
1258	if (error) {
1259		VPTRINIT(iph1->id_p);
1260		oakley_delcert(iph1->cert_p);
1261		iph1->cert_p = NULL;
1262		oakley_delcert(iph1->crl_p);
1263		iph1->crl_p = NULL;
1264		VPTRINIT(iph1->sig_p);
1265		oakley_delcert(iph1->cr_p);
1266		iph1->cr_p = NULL;
1267	}
1268
1269	return error;
1270}
1271
1272/*
1273 * send to initiator
1274 * 	psk: HDR*, IDr1, HASH_R
1275 * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
1276 *   gssapi: HDR*, IDr1, < GSSr(n) | HASH_R >
1277 * 	rsa: HDR*, HASH_R
1278 * 	rev: HDR*, HASH_R
1279 */
1280int
1281ident_r3send(iph1, msg)
1282	struct ph1handle *iph1;
1283	vchar_t *msg;
1284{
1285	int error = -1;
1286	int dohash = 1;
1287#ifdef HAVE_GSSAPI
1288	int len;
1289#endif
1290
1291	/* validity check */
1292	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
1293		plog(LLV_ERROR, LOCATION, NULL,
1294			"status mismatched %d.\n", iph1->status);
1295		goto end;
1296	}
1297
1298	/* make ID payload into isakmp status */
1299	if (ipsecdoi_setid1(iph1) < 0)
1300		goto end;
1301
1302#ifdef HAVE_GSSAPI
1303	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
1304	    gssapi_more_tokens(iph1)) {
1305		gssapi_get_rtoken(iph1, &len);
1306		if (len != 0)
1307			dohash = 0;
1308	}
1309#endif
1310
1311	if (dohash) {
1312		/* generate HASH to send */
1313		plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_R\n");
1314		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
1315		if (iph1->hash == NULL)
1316			goto end;
1317	} else
1318		iph1->hash = NULL;
1319
1320	/* set encryption flag */
1321	iph1->flags |= ISAKMP_FLAG_E;
1322
1323	/* create HDR;ID;HASH payload */
1324	iph1->sendbuf = ident_ir3mx(iph1);
1325	if (iph1->sendbuf == NULL)
1326		goto end;
1327
1328	/* send HDR;ID;HASH to responder */
1329	if (isakmp_send(iph1, iph1->sendbuf) < 0)
1330		goto end;
1331
1332	/* the sending message is added to the received-list. */
1333	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1334		plog(LLV_ERROR , LOCATION, NULL,
1335			"failed to add a response packet to the tree.\n");
1336		goto end;
1337	}
1338
1339	/* see handler.h about IV synchronization. */
1340	memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l);
1341
1342	iph1->status = PHASE1ST_ESTABLISHED;
1343
1344	error = 0;
1345
1346end:
1347
1348	return error;
1349}
1350
1351/*
1352 * This is used in main mode for:
1353 * initiator's 3rd exchange send to responder
1354 * 	psk: HDR, KE, Ni
1355 * 	sig: HDR, KE, Ni
1356 * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
1357 * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
1358 * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
1359 * responders 2nd exchnage send to initiator
1360 * 	psk: HDR, KE, Nr
1361 * 	sig: HDR, KE, Nr [, CR ]
1362 * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
1363 * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
1364 */
1365static vchar_t *
1366ident_ir2mx(iph1)
1367	struct ph1handle *iph1;
1368{
1369	vchar_t *buf = 0;
1370	struct isakmp_gen *gen;
1371	char *p;
1372	int tlen;
1373	int need_cr = 0;
1374	vchar_t *cr = NULL;
1375	vchar_t *vid = NULL;
1376	int error = -1;
1377	int nptype;
1378#ifdef HAVE_GSSAPI
1379	vchar_t *gsstoken = NULL;
1380#endif
1381
1382#ifdef HAVE_SIGNING_C
1383	/* create CR if need */
1384	if (iph1->side == RESPONDER
1385	 && iph1->rmconf->send_cr
1386	 && oakley_needcr(iph1->approval->authmethod)
1387	 && iph1->rmconf->peerscertfile == NULL) {
1388		need_cr = 1;
1389		cr = oakley_getcr(iph1);
1390		if (cr == NULL) {
1391			plog(LLV_ERROR, LOCATION, NULL,
1392				"failed to get cr buffer.\n");
1393			goto end;
1394		}
1395	}
1396#endif
1397
1398#ifdef HAVE_GSSAPI
1399	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
1400		gssapi_get_token_to_send(iph1, &gsstoken);
1401#endif
1402
1403	/* create buffer */
1404	tlen = sizeof(struct isakmp)
1405	     + sizeof(*gen) + iph1->dhpub->l
1406	     + sizeof(*gen) + iph1->nonce->l;
1407	if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
1408		tlen += sizeof(*gen) + vid->l;
1409	if (need_cr)
1410		tlen += sizeof(*gen) + cr->l;
1411#ifdef HAVE_GSSAPI
1412	if (gsstoken)
1413		tlen += sizeof(*gen) + gsstoken->l;
1414#endif
1415
1416	buf = vmalloc(tlen);
1417	if (buf == NULL) {
1418		plog(LLV_ERROR, LOCATION, NULL,
1419			"failed to get buffer to send.\n");
1420		goto end;
1421	}
1422
1423	/* set isakmp header */
1424	p = set_isakmp_header(buf, iph1, ISAKMP_NPTYPE_KE);
1425	if (p == NULL)
1426		goto end;
1427
1428	/* create isakmp KE payload */
1429	p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_NONCE);
1430
1431	/* create isakmp NONCE payload */
1432#ifdef HAVE_GSSAPI
1433	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
1434		nptype = ISAKMP_NPTYPE_GSS;
1435	else
1436#endif
1437		nptype = vid ? ISAKMP_NPTYPE_VID :
1438		    (need_cr ? ISAKMP_NPTYPE_CR : ISAKMP_NPTYPE_NONE);
1439	p = set_isakmp_payload(p, iph1->nonce, nptype);
1440
1441#ifdef HAVE_GSSAPI
1442	if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
1443		p = set_isakmp_payload(p, gsstoken,
1444			vid ? ISAKMP_NPTYPE_VID
1445			    : (need_cr ? ISAKMP_NPTYPE_CR
1446				       : ISAKMP_NPTYPE_NONE));
1447	}
1448#endif
1449
1450	/* append vendor id, if needed */
1451	if (vid)
1452		p = set_isakmp_payload(p, vid,
1453				need_cr ? ISAKMP_NPTYPE_CR
1454					: ISAKMP_NPTYPE_NONE);
1455
1456	/* create isakmp CR payload if needed */
1457	if (need_cr)
1458		p = set_isakmp_payload(p, cr, ISAKMP_NPTYPE_NONE);
1459
1460	error = 0;
1461
1462end:
1463	if (error && buf != NULL) {
1464		vfree(buf);
1465		buf = NULL;
1466	}
1467	if (cr)
1468		vfree(cr);
1469#ifdef HAVE_GSSAPI
1470	if (gsstoken)
1471		vfree(gsstoken);
1472#endif
1473	if (vid)
1474		vfree(vid);
1475
1476	return buf;
1477}
1478
1479/*
1480 * This is used in main mode for:
1481 * initiator's 4th exchange send to responder
1482 * 	psk: HDR*, IDi1, HASH_I
1483 * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
1484 *   gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I >
1485 * 	rsa: HDR*, HASH_I
1486 * 	rev: HDR*, HASH_I
1487 * responders 3rd exchnage send to initiator
1488 * 	psk: HDR*, IDr1, HASH_R
1489 * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
1490 *   gssapi: HDR*, [ IDr1, ] < GSSr(n) | HASH_R >
1491 * 	rsa: HDR*, HASH_R
1492 * 	rev: HDR*, HASH_R
1493 */
1494static vchar_t *
1495ident_ir3mx(iph1)
1496	struct ph1handle *iph1;
1497{
1498	vchar_t *buf = NULL, *new = NULL;
1499	char *p;
1500	int tlen;
1501	struct isakmp_gen *gen;
1502	int need_cr = 0;
1503	int need_cert = 0;
1504	vchar_t *cr = NULL;
1505	int error = -1;
1506#ifdef HAVE_GSSAPI
1507	int nptype;
1508	vchar_t *gsstoken = NULL;
1509	vchar_t *gsshash = NULL;
1510#endif
1511
1512	tlen = sizeof(struct isakmp);
1513
1514	switch (iph1->approval->authmethod) {
1515	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1516		tlen += sizeof(*gen) + iph1->id->l
1517			+ sizeof(*gen) + iph1->hash->l;
1518
1519		buf = vmalloc(tlen);
1520		if (buf == NULL) {
1521			plog(LLV_ERROR, LOCATION, NULL,
1522				"failed to get buffer to send.\n");
1523			goto end;
1524		}
1525
1526		/* set isakmp header */
1527		p = set_isakmp_header(buf, iph1, ISAKMP_NPTYPE_ID);
1528		if (p == NULL)
1529			goto end;
1530
1531		/* create isakmp ID payload */
1532		p = set_isakmp_payload(p, iph1->id, ISAKMP_NPTYPE_HASH);
1533
1534		/* create isakmp HASH payload */
1535		p = set_isakmp_payload(p, iph1->hash, ISAKMP_NPTYPE_NONE);
1536		break;
1537#ifdef HAVE_SIGNING_C
1538	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1539	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1540		if (oakley_getmycert(iph1) < 0)
1541			goto end;
1542
1543		if (oakley_getsign(iph1) < 0)
1544			goto end;
1545
1546		/* create CR if need */
1547		if (iph1->side == INITIATOR
1548		 && iph1->rmconf->send_cr
1549	 	 && oakley_needcr(iph1->approval->authmethod)
1550		 && iph1->rmconf->peerscertfile == NULL) {
1551			need_cr = 1;
1552			cr = oakley_getcr(iph1);
1553			if (cr == NULL) {
1554				plog(LLV_ERROR, LOCATION, NULL,
1555					"failed to get cr buffer.\n");
1556				goto end;
1557			}
1558		}
1559
1560		if (iph1->cert != NULL && iph1->rmconf->send_cert)
1561			need_cert = 1;
1562
1563		tlen += sizeof(*gen) + iph1->id->l
1564			+ sizeof(*gen) + iph1->sig->l;
1565		if (need_cert)
1566			tlen += sizeof(*gen) + iph1->cert->pl->l;
1567		if (need_cr)
1568			tlen += sizeof(*gen) + cr->l;
1569
1570		buf = vmalloc(tlen);
1571		if (buf == NULL) {
1572			plog(LLV_ERROR, LOCATION, NULL,
1573				"failed to get buffer to send.\n");
1574			goto end;
1575		}
1576
1577		/* set isakmp header */
1578		p = set_isakmp_header(buf, iph1, ISAKMP_NPTYPE_ID);
1579		if (p == NULL)
1580			goto end;
1581
1582		/* add ID payload */
1583		p = set_isakmp_payload(p, iph1->id, need_cert
1584							? ISAKMP_NPTYPE_CERT
1585							: ISAKMP_NPTYPE_SIG);
1586
1587		/* add CERT payload if there */
1588		if (need_cert)
1589			p = set_isakmp_payload(p, iph1->cert->pl, ISAKMP_NPTYPE_SIG);
1590		/* add SIG payload */
1591		p = set_isakmp_payload(p, iph1->sig,
1592			need_cr ? ISAKMP_NPTYPE_CR : ISAKMP_NPTYPE_NONE);
1593
1594		/* create isakmp CR payload */
1595		if (need_cr)
1596			p = set_isakmp_payload(p, cr, ISAKMP_NPTYPE_NONE);
1597		break;
1598#endif
1599#ifdef HAVE_GSSAPI
1600	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1601		if (!gssapi_id_sent(iph1))
1602			tlen += sizeof (*gen) + iph1->id->l;
1603		if (iph1->hash != NULL) {
1604			gsshash = gssapi_wraphash(iph1);
1605			if (gsshash == NULL)
1606				goto end;
1607			tlen += sizeof (*gen) + gsshash->l;
1608		} else {
1609			gssapi_get_token_to_send(iph1, &gsstoken);
1610			tlen += sizeof (*gen) + gsstoken->l;
1611		}
1612
1613		buf = vmalloc(tlen);
1614		if (buf == NULL) {
1615			plog(LLV_ERROR, LOCATION, NULL,
1616				"failed to get buffer to send.\n");
1617			goto end;
1618		}
1619
1620		/* set isakmp header */
1621		if (!gssapi_id_sent(iph1))
1622			nptype = ISAKMP_NPTYPE_ID;
1623		else
1624			nptype = iph1->hash != NULL ? ISAKMP_NPTYPE_HASH :
1625			    ISAKMP_NPTYPE_GSS;
1626		p = set_isakmp_header(buf, iph1, nptype);
1627		if (p == NULL)
1628			goto end;
1629
1630		if (!gssapi_id_sent(iph1)) {
1631			/* create isakmp ID payload */
1632			nptype = iph1->hash != NULL ? ISAKMP_NPTYPE_HASH :
1633			    ISAKMP_NPTYPE_GSS;
1634			p = set_isakmp_payload(p, iph1->id, nptype);
1635			if (p == NULL)
1636				goto end;
1637			gssapi_set_id_sent(iph1);
1638		}
1639
1640		if (iph1->hash != NULL)
1641			/* create isakmp HASH payload */
1642			p = set_isakmp_payload(p, gsshash,
1643			    ISAKMP_NPTYPE_NONE);
1644		else
1645			p = set_isakmp_payload(p, gsstoken, ISAKMP_NPTYPE_NONE);
1646		break;
1647#endif
1648	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1649	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1650		plog(LLV_ERROR, LOCATION, NULL,
1651			"not supported authentication type %d\n",
1652			iph1->approval->authmethod);
1653		goto end;
1654	default:
1655		plog(LLV_ERROR, LOCATION, NULL,
1656			"invalid authentication type %d\n",
1657			iph1->approval->authmethod);
1658		goto end;
1659	}
1660
1661#ifdef HAVE_PRINT_ISAKMP_C
1662	isakmp_printpacket(buf, iph1->local, iph1->remote, 1);
1663#endif
1664
1665	/* encoding */
1666	new = oakley_do_encrypt(iph1, buf, iph1->ivm->ive, iph1->ivm->iv);
1667	if (new == NULL)
1668		goto end;
1669
1670	vfree(buf);
1671
1672	buf = new;
1673
1674	error = 0;
1675
1676end:
1677	if (cr)
1678		vfree(cr);
1679	if (error && buf != NULL) {
1680		vfree(buf);
1681		buf = NULL;
1682	}
1683
1684	return buf;
1685}
1686