1/*	$KAME: isakmp_agg.c,v 1.55 2001/12/12 15:29:13 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/* Aggressive Exchange (Aggressive 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_agg.h"
70#include "isakmp_inf.h"
71#include "vendorid.h"
72#include "strnames.h"
73
74#ifdef HAVE_GSSAPI
75#include "gssapi.h"
76#endif
77
78/*
79 * begin Aggressive Mode as initiator.
80 */
81/*
82 * send to responder
83 * 	psk: HDR, SA, KE, Ni, IDi1
84 * 	sig: HDR, SA, KE, Ni, IDi1 [, CR ]
85 *   gssapi: HDR, SA, KE, Ni, IDi1, GSSi
86 * 	rsa: HDR, SA, [ HASH(1),] KE, <IDi1_b>Pubkey_r, <Ni_b>Pubkey_r
87 * 	rev: HDR, SA, [ HASH(1),] <Ni_b>Pubkey_r, <KE_b>Ke_i,
88 * 	     <IDii_b>Ke_i [, <Cert-I_b>Ke_i ]
89 */
90int
91agg_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 need_cr = 0;
99	vchar_t *cr = NULL, *gsstoken = NULL;
100	int error = -1;
101	int nptype;
102#ifdef HAVE_GSSAPI
103	int len;
104#endif
105
106	/* validity check */
107	if (msg != NULL) {
108		plog(LLV_ERROR, LOCATION, NULL,
109			"msg has to be NULL in this function.\n");
110		goto end;
111	}
112	if (iph1->status != PHASE1ST_START) {
113		plog(LLV_ERROR, LOCATION, NULL,
114			"status mismatched %d.\n", iph1->status);
115		goto end;
116	}
117
118	/* create isakmp index */
119	memset(&iph1->index, 0, sizeof(iph1->index));
120	isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
121
122	/* make ID payload into isakmp status */
123	if (ipsecdoi_setid1(iph1) < 0)
124		goto end;
125
126	/* create SA payload for my proposal */
127	iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
128	if (iph1->sa == NULL)
129		goto end;
130
131	/* consistency check of proposals */
132	if (iph1->rmconf->dhgrp == NULL) {
133		plog(LLV_ERROR, LOCATION, NULL,
134			"configuration failure about DH group.\n");
135		goto end;
136	}
137
138	/* generate DH public value */
139	if (oakley_dh_generate(iph1->rmconf->dhgrp,
140				&iph1->dhpub, &iph1->dhpriv) < 0)
141		goto end;
142
143	/* generate NONCE value */
144	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
145	if (iph1->nonce == NULL)
146		goto end;
147
148#ifdef HAVE_SIGNING_C
149	/* create CR if need */
150	if (iph1->rmconf->send_cr
151	 && oakley_needcr(iph1->rmconf->proposal->authmethod)
152	 && iph1->rmconf->peerscertfile == NULL) {
153		need_cr = 1;
154		cr = oakley_getcr(iph1);
155		if (cr == NULL) {
156			plog(LLV_ERROR, LOCATION, NULL,
157				"failed to get cr buffer.\n");
158			goto end;
159		}
160	}
161#endif
162	plog(LLV_DEBUG, LOCATION, NULL, "authmethod is %s\n",
163		s_oakley_attr_method(iph1->rmconf->proposal->authmethod));
164	/* create buffer to send isakmp payload */
165	tlen = sizeof(struct isakmp)
166		+ sizeof(*gen) + iph1->sa->l
167		+ sizeof(*gen) + iph1->dhpub->l
168		+ sizeof(*gen) + iph1->nonce->l
169		+ sizeof(*gen) + iph1->id->l;
170	if (need_cr)
171		tlen += sizeof(*gen) + cr->l;
172#ifdef HAVE_GSSAPI
173	if (iph1->rmconf->proposal->authmethod ==
174	    OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
175		gssapi_get_itoken(iph1, &len);
176		tlen += sizeof (*gen) + len;
177	}
178#endif
179
180	iph1->sendbuf = vmalloc(tlen);
181	if (iph1->sendbuf == NULL) {
182		plog(LLV_ERROR, LOCATION, NULL,
183			"failed to get buffer to send.\n");
184		goto end;
185	}
186
187	/* set isakmp header */
188	p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
189	if (p == NULL)
190		goto end;
191
192	/* set SA payload to propose */
193	p = set_isakmp_payload(p, iph1->sa, ISAKMP_NPTYPE_KE);
194
195	/* create isakmp KE payload */
196	p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_NONCE);
197
198	/* create isakmp NONCE payload */
199	p = set_isakmp_payload(p, iph1->nonce, ISAKMP_NPTYPE_ID);
200
201	/* create isakmp ID payload */
202#ifdef HAVE_GSSAPI
203	if (iph1->rmconf->proposal->authmethod ==
204	    OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
205		nptype = ISAKMP_NPTYPE_GSS;
206	else
207#endif
208	if (need_cr)
209		nptype = ISAKMP_NPTYPE_CR;
210	else
211		nptype = ISAKMP_NPTYPE_NONE;
212
213	p = set_isakmp_payload(p, iph1->id, nptype);
214
215#ifdef HAVE_GSSAPI
216	if (iph1->rmconf->proposal->authmethod ==
217	    OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
218		gssapi_get_token_to_send(iph1, &gsstoken);
219		p = set_isakmp_payload(p, gsstoken, ISAKMP_NPTYPE_NONE);
220	} else
221#endif
222	if (need_cr)
223		/* create isakmp CR payload */
224		p = set_isakmp_payload(p, cr, ISAKMP_NPTYPE_NONE);
225
226#ifdef HAVE_PRINT_ISAKMP_C
227	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
228#endif
229
230	/* send the packet, add to the schedule to resend */
231	iph1->retry_counter = iph1->rmconf->retry_counter;
232	if (isakmp_ph1resend(iph1) == -1)
233		goto end;
234
235	iph1->status = PHASE1ST_MSG1SENT;
236
237	error = 0;
238
239end:
240	if (cr)
241		vfree(cr);
242	if (gsstoken)
243		vfree(gsstoken);
244
245	return error;
246}
247
248/*
249 * receive from responder
250 * 	psk: HDR, SA, KE, Nr, IDr1, HASH_R
251 * 	sig: HDR, SA, KE, Nr, IDr1, [ CR, ] [ CERT, ] SIG_R
252 *   gssapi: HDR, SA, KE, Nr, IDr1, GSSr, HASH_R
253 * 	rsa: HDR, SA, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i, HASH_R
254 * 	rev: HDR, SA, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDir_b>Ke_r, HASH_R
255 */
256int
257agg_i2recv(iph1, msg)
258	struct ph1handle *iph1;
259	vchar_t *msg;
260{
261	vchar_t *pbuf = NULL;
262	struct isakmp_parse_t *pa;
263	vchar_t *satmp = NULL;
264	int error = -1;
265#ifdef HAVE_GSSAPI
266	vchar_t *gsstoken = NULL;
267#endif
268
269	/* validity check */
270	if (iph1->status != PHASE1ST_MSG1SENT) {
271		plog(LLV_ERROR, LOCATION, NULL,
272			"status mismatched %d.\n", iph1->status);
273		goto end;
274	}
275
276	/* validate the type of next payload */
277	pbuf = isakmp_parse(msg);
278	if (pbuf == NULL)
279		goto end;
280	pa = (struct isakmp_parse_t *)pbuf->v;
281
282	iph1->pl_hash = NULL;
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_KE:
302			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
303				goto end;
304			break;
305		case ISAKMP_NPTYPE_NONCE:
306			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
307				goto end;
308			break;
309		case ISAKMP_NPTYPE_ID:
310			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
311				goto end;
312			break;
313		case ISAKMP_NPTYPE_HASH:
314			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
315			break;
316#ifdef HAVE_SIGNING_C
317		case ISAKMP_NPTYPE_CR:
318			if (oakley_savecr(iph1, pa->ptr) < 0)
319				goto end;
320			break;
321		case ISAKMP_NPTYPE_CERT:
322			if (oakley_savecert(iph1, pa->ptr) < 0)
323				goto end;
324			break;
325		case ISAKMP_NPTYPE_SIG:
326			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
327				goto end;
328			break;
329#endif
330		case ISAKMP_NPTYPE_VID:
331			(void)check_vendorid(pa->ptr);
332			break;
333		case ISAKMP_NPTYPE_N:
334			isakmp_check_notify(pa->ptr, iph1);
335			break;
336#ifdef HAVE_GSSAPI
337		case ISAKMP_NPTYPE_GSS:
338			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
339				goto end;
340			gssapi_save_received_token(iph1, gsstoken);
341			break;
342#endif
343		default:
344			/* don't send information, see isakmp_ident_r1() */
345			plog(LLV_ERROR, LOCATION, iph1->remote,
346				"ignore the packet, "
347				"received unexpecting payload type %d.\n",
348				pa->type);
349			goto end;
350		}
351	}
352
353	/* payload existency check */
354
355	/* verify identifier */
356	if (ipsecdoi_checkid1(iph1) != 0) {
357		plog(LLV_ERROR, LOCATION, iph1->remote,
358			"invalid ID payload.\n");
359		goto end;
360	}
361
362	/* check SA payload and set approval SA for use */
363	if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
364		plog(LLV_ERROR, LOCATION, iph1->remote,
365			"failed to get valid proposal.\n");
366		goto end;
367	}
368	if (iph1->sa_ret) {
369		vfree(iph1->sa_ret);
370		iph1->sa_ret = NULL;
371	}
372
373	/* fix isakmp index */
374	memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
375		sizeof(cookie_t));
376
377	/* compute sharing secret of DH */
378	if (oakley_dh_compute(iph1->rmconf->dhgrp, iph1->dhpub,
379				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
380		goto end;
381
382	/* generate SKEYIDs & IV & final cipher key */
383	if (oakley_skeyid(iph1) < 0)
384		goto end;
385	if (oakley_skeyid_dae(iph1) < 0)
386		goto end;
387	if (oakley_compute_enckey(iph1) < 0)
388		goto end;
389	if (oakley_newiv(iph1) < 0)
390		goto end;
391
392	/* validate authentication value */
393    {
394	int type;
395	type = oakley_validate_auth(iph1);
396	if (type != 0) {
397		if (type == -1) {
398			/* message printed inner oakley_validate_auth() */
399			goto end;
400		}
401		isakmp_info_send_n1(iph1, type, NULL);
402		goto end;
403	}
404    }
405
406#ifdef HAVE_SIGNING_C
407	if (oakley_checkcr(iph1) < 0) {
408		/* Ignore this error in order to be interoperability. */
409		;
410	}
411#endif
412
413	/* change status of isakmp status entry */
414	iph1->status = PHASE1ST_MSG2RECEIVED;
415
416	error = 0;
417
418end:
419	if (pbuf)
420		vfree(pbuf);
421	if (satmp)
422		vfree(satmp);
423	if (error) {
424		VPTRINIT(iph1->dhpub_p);
425		VPTRINIT(iph1->nonce_p);
426		VPTRINIT(iph1->id_p);
427		oakley_delcert(iph1->cert_p);
428		iph1->cert_p = NULL;
429		oakley_delcert(iph1->crl_p);
430		iph1->crl_p = NULL;
431		VPTRINIT(iph1->sig_p);
432		oakley_delcert(iph1->cr_p);
433		iph1->cr_p = NULL;
434	}
435
436	return error;
437}
438
439/*
440 * send to responder
441 * 	psk: HDR, HASH_I
442 *   gssapi: HDR, HASH_I
443 * 	sig: HDR, [ CERT, ] SIG_I
444 * 	rsa: HDR, HASH_I
445 * 	rev: HDR, HASH_I
446 */
447int
448agg_i2send(iph1, msg)
449	struct ph1handle *iph1;
450	vchar_t *msg;
451{
452	struct isakmp_gen *gen;
453	char *p;
454	int tlen;
455	int need_cert = 0;
456	int error = -1;
457	vchar_t *gsshash = NULL;
458
459	/* validity check */
460	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
461		plog(LLV_ERROR, LOCATION, NULL,
462			"status mismatched %d.\n", iph1->status);
463		goto end;
464	}
465
466	/* generate HASH to send */
467	plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
468	iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
469	if (iph1->hash == NULL) {
470#ifdef HAVE_GSSAPI
471		if (gssapi_more_tokens(iph1))
472			isakmp_info_send_n1(iph1,
473			    ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
474#endif
475		goto end;
476	}
477
478	tlen = sizeof(struct isakmp);
479
480	switch (iph1->approval->authmethod) {
481	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
482		tlen += sizeof(*gen) + iph1->hash->l;
483
484		iph1->sendbuf = vmalloc(tlen);
485		if (iph1->sendbuf == NULL) {
486			plog(LLV_ERROR, LOCATION, NULL,
487				"failed to get buffer to send.\n");
488			goto end;
489		}
490
491		/* set isakmp header */
492		p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_HASH);
493		if (p == NULL)
494			goto end;
495
496		/* set HASH payload */
497		p = set_isakmp_payload(p, iph1->hash, ISAKMP_NPTYPE_NONE);
498		break;
499#ifdef HAVE_SIGNING_C
500	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
501	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
502
503		if (oakley_getmycert(iph1) < 0)
504			goto end;
505
506		if (oakley_getsign(iph1) < 0)
507			goto end;
508
509		if (iph1->cert != NULL && iph1->rmconf->send_cert)
510			need_cert = 1;
511
512		tlen += sizeof(*gen) + iph1->sig->l;
513		if (need_cert)
514			tlen += sizeof(*gen) + iph1->cert->pl->l;
515
516		iph1->sendbuf = vmalloc(tlen);
517		if (iph1->sendbuf == NULL) {
518			plog(LLV_ERROR, LOCATION, NULL,
519				"failed to get buffer to send.\n");
520			goto end;
521		}
522
523		/* set isakmp header */
524		p = set_isakmp_header(iph1->sendbuf, iph1, need_cert
525							? ISAKMP_NPTYPE_CERT
526							: ISAKMP_NPTYPE_SIG);
527		if (p == NULL)
528			goto end;
529
530		/* add CERT payload if there */
531		if (need_cert)
532			p = set_isakmp_payload(p, iph1->cert->pl, ISAKMP_NPTYPE_SIG);
533		/* add SIG payload */
534		p = set_isakmp_payload(p, iph1->sig, ISAKMP_NPTYPE_NONE);
535		break;
536#endif
537	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
538	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
539		tlen += sizeof(*gen) + iph1->hash->l;
540		break;
541#ifdef HAVE_GSSAPI
542	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
543		gsshash = gssapi_wraphash(iph1);
544		if (gsshash == NULL) {
545			plog(LLV_ERROR, LOCATION, NULL,
546				"failed to wrap hash\n");
547			isakmp_info_send_n1(iph1,
548				ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
549			goto end;
550		}
551		tlen += sizeof(*gen) + gsshash->l;
552
553		iph1->sendbuf = vmalloc(tlen);
554		if (iph1->sendbuf == NULL) {
555			plog(LLV_ERROR, LOCATION, NULL,
556				"failed to get buffer to send.\n");
557			goto end;
558		}
559		/* set isakmp header */
560		p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_HASH);
561		if (p == NULL)
562			goto end;
563		p = set_isakmp_payload(p, gsshash, ISAKMP_NPTYPE_NONE);
564		break;
565#endif
566	}
567
568#ifdef HAVE_PRINT_ISAKMP_C
569	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
570#endif
571
572	/* send to responder */
573	if (isakmp_send(iph1, iph1->sendbuf) < 0)
574		goto end;
575
576	/* the sending message is added to the received-list. */
577	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
578		plog(LLV_ERROR , LOCATION, NULL,
579			"failed to add a response packet to the tree.\n");
580		goto end;
581	}
582
583	/* set encryption flag */
584	iph1->flags |= ISAKMP_FLAG_E;
585
586	iph1->status = PHASE1ST_ESTABLISHED;
587
588	error = 0;
589
590end:
591	if (gsshash)
592		vfree(gsshash);
593	return error;
594}
595
596/*
597 * receive from initiator
598 * 	psk: HDR, SA, KE, Ni, IDi1
599 * 	sig: HDR, SA, KE, Ni, IDi1 [, CR ]
600 *   gssapi: HDR, SA, KE, Ni, IDi1 , GSSi
601 * 	rsa: HDR, SA, [ HASH(1),] KE, <IDi1_b>Pubkey_r, <Ni_b>Pubkey_r
602 * 	rev: HDR, SA, [ HASH(1),] <Ni_b>Pubkey_r, <KE_b>Ke_i,
603 * 	     <IDii_b>Ke_i [, <Cert-I_b>Ke_i ]
604 */
605int
606agg_r1recv(iph1, msg)
607	struct ph1handle *iph1;
608	vchar_t *msg;
609{
610	int error = -1;
611	vchar_t *pbuf = NULL;
612	struct isakmp_parse_t *pa;
613#ifdef HAVE_GSSAPI
614	vchar_t *gsstoken = NULL;
615#endif
616
617	/* validity check */
618	if (iph1->status != PHASE1ST_START) {
619		plog(LLV_ERROR, LOCATION, NULL,
620			"status mismatched %d.\n", iph1->status);
621		goto end;
622	}
623
624	/* validate the type of next payload */
625	pbuf = isakmp_parse(msg);
626	if (pbuf == NULL)
627		goto end;
628	pa = (struct isakmp_parse_t *)pbuf->v;
629
630	/* SA payload is fixed postion */
631	if (pa->type != ISAKMP_NPTYPE_SA) {
632		plog(LLV_ERROR, LOCATION, iph1->remote,
633			"received invalid next payload type %d, "
634			"expecting %d.\n",
635			pa->type, ISAKMP_NPTYPE_SA);
636		goto end;
637	}
638	if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
639		goto end;
640	pa++;
641
642	for (/*nothing*/;
643	     pa->type != ISAKMP_NPTYPE_NONE;
644	     pa++) {
645
646		plog(LLV_DEBUG, LOCATION, NULL,
647			"received payload of type %s\n",
648			s_isakmp_nptype(pa->type));
649
650		switch (pa->type) {
651		case ISAKMP_NPTYPE_KE:
652			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
653				goto end;
654			break;
655		case ISAKMP_NPTYPE_NONCE:
656			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
657				goto end;
658			break;
659		case ISAKMP_NPTYPE_ID:
660			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
661				goto end;
662			break;
663		case ISAKMP_NPTYPE_VID:
664			(void)check_vendorid(pa->ptr);
665			break;
666#ifdef HAVE_SIGNING_C
667		case ISAKMP_NPTYPE_CR:
668			if (oakley_savecr(iph1, pa->ptr) < 0)
669				goto end;
670			break;
671#endif
672#ifdef HAVE_GSSAPI
673		case ISAKMP_NPTYPE_GSS:
674			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
675				goto end;
676			gssapi_save_received_token(iph1, gsstoken);
677			break;
678#endif
679		default:
680			/* don't send information, see isakmp_ident_r1() */
681			plog(LLV_ERROR, LOCATION, iph1->remote,
682				"ignore the packet, "
683				"received unexpecting payload type %d.\n",
684				pa->type);
685			goto end;
686		}
687	}
688
689	/* payload existency check */
690
691	/* verify identifier */
692	if (ipsecdoi_checkid1(iph1) != 0) {
693		plog(LLV_ERROR, LOCATION, iph1->remote,
694			"invalid ID payload.\n");
695		goto end;
696	}
697
698	/* check SA payload and set approval SA for use */
699	if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
700		plog(LLV_ERROR, LOCATION, iph1->remote,
701			"failed to get valid proposal.\n");
702		goto end;
703	}
704
705#ifdef HAVE_SIGNING_C
706	if (oakley_checkcr(iph1) < 0) {
707		/* Ignore this error in order to be interoperability. */
708		;
709	}
710#endif
711
712	iph1->status = PHASE1ST_MSG1RECEIVED;
713
714	error = 0;
715
716end:
717	if (pbuf)
718		vfree(pbuf);
719	if (error) {
720		VPTRINIT(iph1->sa);
721		VPTRINIT(iph1->dhpub_p);
722		VPTRINIT(iph1->nonce_p);
723		VPTRINIT(iph1->id_p);
724		oakley_delcert(iph1->cr_p);
725		iph1->cr_p = NULL;
726	}
727
728	return error;
729}
730
731/*
732 * send to initiator
733 * 	psk: HDR, SA, KE, Nr, IDr1, HASH_R
734 * 	sig: HDR, SA, KE, Nr, IDr1, [ CR, ] [ CERT, ] SIG_R
735 *   gssapi: HDR, SA, KE, Nr, IDr1, GSSr, HASH_R
736 * 	rsa: HDR, SA, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i, HASH_R
737 * 	rev: HDR, SA, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDir_b>Ke_r, HASH_R
738 */
739int
740agg_r1send(iph1, msg)
741	struct ph1handle *iph1;
742	vchar_t *msg;
743{
744	struct isakmp_gen *gen;
745	char *p;
746	int tlen;
747	int need_cr = 0;
748	int need_cert = 0;
749	vchar_t *cr = NULL;
750	vchar_t *vid = NULL;
751	int error = -1;
752#ifdef HAVE_GSSAPI
753	int gsslen;
754	vchar_t *gsstoken = NULL, *gsshash = NULL;
755	vchar_t *gss_sa = NULL;
756#endif
757
758	/* validity check */
759	if (iph1->status != PHASE1ST_MSG1RECEIVED) {
760		plog(LLV_ERROR, LOCATION, NULL,
761			"status mismatched %d.\n", iph1->status);
762		goto end;
763	}
764
765	/* set responder's cookie */
766	isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
767
768	/* make ID payload into isakmp status */
769	if (ipsecdoi_setid1(iph1) < 0)
770		goto end;
771
772	/* generate DH public value */
773	if (oakley_dh_generate(iph1->rmconf->dhgrp,
774				&iph1->dhpub, &iph1->dhpriv) < 0)
775		goto end;
776
777	/* generate NONCE value */
778	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
779	if (iph1->nonce == NULL)
780		goto end;
781
782	/* compute sharing secret of DH */
783	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
784				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
785		goto end;
786
787	/* generate SKEYIDs & IV & final cipher key */
788	if (oakley_skeyid(iph1) < 0)
789		goto end;
790	if (oakley_skeyid_dae(iph1) < 0)
791		goto end;
792	if (oakley_compute_enckey(iph1) < 0)
793		goto end;
794	if (oakley_newiv(iph1) < 0)
795		goto end;
796
797#ifdef HAVE_GSSAPI
798	if (iph1->rmconf->proposal->authmethod ==
799	    OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
800		gssapi_get_rtoken(iph1, &gsslen);
801#endif
802
803	/* generate HASH to send */
804	plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_R\n");
805	iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
806	if (iph1->hash == NULL) {
807#ifdef HAVE_GSSAPI
808		if (gssapi_more_tokens(iph1))
809			isakmp_info_send_n1(iph1,
810			    ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
811#endif
812		goto end;
813	}
814
815#ifdef HAVE_SIGNING_C
816	/* create CR if need */
817	if (iph1->rmconf->send_cr
818	 && oakley_needcr(iph1->approval->authmethod)
819	 && iph1->rmconf->peerscertfile == NULL) {
820		need_cr = 1;
821		cr = oakley_getcr(iph1);
822		if (cr == NULL) {
823			plog(LLV_ERROR, LOCATION, NULL,
824				"failed to get cr buffer.\n");
825			goto end;
826		}
827	}
828#endif
829
830	tlen = sizeof(struct isakmp);
831
832	switch (iph1->approval->authmethod) {
833	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
834		/* create buffer to send isakmp payload */
835		tlen += sizeof(*gen) + iph1->sa_ret->l
836			+ sizeof(*gen) + iph1->dhpub->l
837			+ sizeof(*gen) + iph1->nonce->l
838			+ sizeof(*gen) + iph1->id->l
839			+ sizeof(*gen) + iph1->hash->l;
840		if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
841			tlen += sizeof(*gen) + vid->l;
842		if (need_cr)
843			tlen += sizeof(*gen) + cr->l;
844
845		iph1->sendbuf = vmalloc(tlen);
846		if (iph1->sendbuf == NULL) {
847			plog(LLV_ERROR, LOCATION, NULL,
848				"failed to get buffer to send\n");
849			goto end;
850		}
851
852		/* set isakmp header */
853		p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
854		if (p == NULL)
855			goto end;
856
857		/* set SA payload to reply */
858		p = set_isakmp_payload(p, iph1->sa_ret, ISAKMP_NPTYPE_KE);
859
860		/* create isakmp KE payload */
861		p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_NONCE);
862
863		/* create isakmp NONCE payload */
864		p = set_isakmp_payload(p, iph1->nonce, ISAKMP_NPTYPE_ID);
865
866		/* create isakmp ID payload */
867		p = set_isakmp_payload(p, iph1->id, ISAKMP_NPTYPE_HASH);
868
869		/* create isakmp HASH payload */
870		p = set_isakmp_payload(p, iph1->hash,
871			vid ? ISAKMP_NPTYPE_VID
872			    : (need_cr ? ISAKMP_NPTYPE_CR
873				       : ISAKMP_NPTYPE_NONE));
874
875		/* append vendor id, if needed */
876		if (vid)
877			p = set_isakmp_payload(p, vid,
878				need_cr ? ISAKMP_NPTYPE_CR
879					: ISAKMP_NPTYPE_NONE);
880
881		/* create isakmp CR payload if needed */
882		if (need_cr)
883			p = set_isakmp_payload(p, cr, ISAKMP_NPTYPE_NONE);
884		break;
885#ifdef HAVE_SIGNING_C
886	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
887	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
888
889		if (oakley_getmycert(iph1) < 0)
890			goto end;
891
892		if (oakley_getsign(iph1) < 0)
893			goto end;
894
895		if (iph1->cert != NULL && iph1->rmconf->send_cert)
896			need_cert = 1;
897
898		tlen += sizeof(*gen) + iph1->sa_ret->l
899			+ sizeof(*gen) + iph1->dhpub->l
900			+ sizeof(*gen) + iph1->nonce->l
901			+ sizeof(*gen) + iph1->id->l
902			+ sizeof(*gen) + iph1->sig->l;
903		if (need_cert)
904			tlen += sizeof(*gen) + iph1->cert->pl->l;
905		if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
906			tlen += sizeof(*gen) + vid->l;
907		if (need_cr)
908			tlen += sizeof(*gen) + cr->l;
909
910		iph1->sendbuf = vmalloc(tlen);
911		if (iph1->sendbuf == NULL) {
912			plog(LLV_ERROR, LOCATION, NULL,
913				"failed to get buffer to send.\n");
914			goto end;
915		}
916
917		/* set isakmp header */
918		p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
919		if (p == NULL)
920			goto end;
921
922		/* set SA payload to reply */
923		p = set_isakmp_payload(p, iph1->sa_ret, ISAKMP_NPTYPE_KE);
924
925		/* create isakmp KE payload */
926		p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_NONCE);
927
928		/* create isakmp NONCE payload */
929		p = set_isakmp_payload(p, iph1->nonce, ISAKMP_NPTYPE_ID);
930
931		/* add ID payload */
932		p = set_isakmp_payload(p, iph1->id, need_cert
933							? ISAKMP_NPTYPE_CERT
934							: ISAKMP_NPTYPE_SIG);
935
936		/* add CERT payload if there */
937		if (need_cert)
938			p = set_isakmp_payload(p, iph1->cert->pl, ISAKMP_NPTYPE_SIG);
939		/* add SIG payload */
940		p = set_isakmp_payload(p, iph1->sig,
941			vid ? ISAKMP_NPTYPE_VID
942			    : (need_cr ? ISAKMP_NPTYPE_CR
943				       : ISAKMP_NPTYPE_NONE));
944
945		/* append vendor id, if needed */
946		if (vid)
947			p = set_isakmp_payload(p, vid,
948				need_cr ? ISAKMP_NPTYPE_CR
949					: ISAKMP_NPTYPE_NONE);
950
951		/* create isakmp CR payload if needed */
952		if (need_cr)
953			p = set_isakmp_payload(p, cr, ISAKMP_NPTYPE_NONE);
954		break;
955#endif
956	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
957	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
958		tlen += sizeof(*gen) + iph1->hash->l;
959		break;
960#ifdef HAVE_GSSAPI
961	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
962		/* create buffer to send isakmp payload */
963		gsshash = gssapi_wraphash(iph1);
964		if (gsshash == NULL) {
965			plog(LLV_ERROR, LOCATION, NULL,
966				"failed to wrap hash\n");
967			/*
968			 * This is probably due to the GSS roundtrips not
969			 * being finished yet. Return this error in
970			 * the hope that a fallback to main mode will
971			 * be done.
972			 */
973			isakmp_info_send_n1(iph1,
974			    ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
975			goto end;
976		}
977		if (iph1->approval->gssid != NULL)
978			gss_sa = ipsecdoi_setph1proposal(iph1->approval);
979		else
980			gss_sa = iph1->sa_ret;
981
982		tlen += sizeof(*gen) + gss_sa->l
983			+ sizeof(*gen) + iph1->dhpub->l
984			+ sizeof(*gen) + iph1->nonce->l
985			+ sizeof(*gen) + iph1->id->l
986			+ sizeof(*gen) + gsslen
987			+ sizeof(*gen) + gsshash->l;
988		if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
989			tlen += sizeof(*gen) + vid->l;
990		iph1->sendbuf = vmalloc(tlen);
991		if (iph1->sendbuf == NULL) {
992			plog(LLV_ERROR, LOCATION, NULL,
993				"failed to get buffer to send\n");
994			goto end;
995		}
996
997		/* set isakmp header */
998		p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
999		if (p == NULL)
1000			goto end;
1001
1002		/* set SA payload to reply */
1003		p = set_isakmp_payload(p, gss_sa, ISAKMP_NPTYPE_KE);
1004
1005		/* create isakmp KE payload */
1006		p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_NONCE);
1007
1008		/* create isakmp NONCE payload */
1009		p = set_isakmp_payload(p, iph1->nonce, ISAKMP_NPTYPE_ID);
1010
1011		/* create isakmp ID payload */
1012		p = set_isakmp_payload(p, iph1->id, ISAKMP_NPTYPE_GSS);
1013
1014		/* create GSS payload */
1015		gssapi_get_token_to_send(iph1, &gsstoken);
1016		p = set_isakmp_payload(p, gsstoken, ISAKMP_NPTYPE_HASH);
1017
1018		/* create isakmp HASH payload */
1019		p = set_isakmp_payload(p, gsshash,
1020		    vid != NULL ? ISAKMP_NPTYPE_VID
1021				: ISAKMP_NPTYPE_NONE);
1022
1023		/* append vendor id, if needed */
1024		if (vid)
1025			p = set_isakmp_payload(p, vid, ISAKMP_NPTYPE_NONE);
1026		break;
1027#endif
1028	}
1029
1030
1031#ifdef HAVE_PRINT_ISAKMP_C
1032	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 1);
1033#endif
1034
1035	/* send the packet, add to the schedule to resend */
1036	iph1->retry_counter = iph1->rmconf->retry_counter;
1037	if (isakmp_ph1resend(iph1) == -1)
1038		goto end;
1039
1040	/* the sending message is added to the received-list. */
1041	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1042		plog(LLV_ERROR , LOCATION, NULL,
1043			"failed to add a response packet to the tree.\n");
1044		goto end;
1045	}
1046
1047	iph1->status = PHASE1ST_MSG1SENT;
1048
1049	error = 0;
1050
1051end:
1052	if (cr)
1053		vfree(cr);
1054	if (vid)
1055		vfree(vid);
1056#ifdef HAVE_GSSAPI
1057	if (gsstoken)
1058		vfree(gsstoken);
1059	if (gsshash)
1060		vfree(gsshash);
1061	if (gss_sa != iph1->sa_ret)
1062		vfree(gss_sa);
1063#endif
1064
1065	return error;
1066}
1067
1068/*
1069 * receive from initiator
1070 * 	psk: HDR, HASH_I
1071 *   gssapi: HDR, HASH_I
1072 * 	sig: HDR, [ CERT, ] SIG_I
1073 * 	rsa: HDR, HASH_I
1074 * 	rev: HDR, HASH_I
1075 */
1076int
1077agg_r2recv(iph1, msg0)
1078	struct ph1handle *iph1;
1079	vchar_t *msg0;
1080{
1081	vchar_t *msg = NULL;
1082	vchar_t *pbuf = NULL;
1083	struct isakmp_parse_t *pa;
1084	int error = -1;
1085
1086	/* validity check */
1087	if (iph1->status != PHASE1ST_MSG1SENT) {
1088		plog(LLV_ERROR, LOCATION, NULL,
1089			"status mismatched %d.\n", iph1->status);
1090		goto end;
1091	}
1092
1093	/* decrypting if need. */
1094	if (ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1095		msg = oakley_do_decrypt(iph1, msg0,
1096					iph1->ivm->iv, iph1->ivm->ive);
1097		if (msg == NULL)
1098			goto end;
1099	} else
1100		msg = vdup(msg0);
1101
1102	/* validate the type of next payload */
1103	pbuf = isakmp_parse(msg);
1104	if (pbuf == NULL)
1105		goto end;
1106
1107	iph1->pl_hash = NULL;
1108
1109	for (pa = (struct isakmp_parse_t *)pbuf->v;
1110	     pa->type != ISAKMP_NPTYPE_NONE;
1111	     pa++) {
1112
1113		switch (pa->type) {
1114		case ISAKMP_NPTYPE_HASH:
1115			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
1116			break;
1117		case ISAKMP_NPTYPE_VID:
1118			(void)check_vendorid(pa->ptr);
1119			break;
1120#ifdef HAVE_SIGNING_C
1121		case ISAKMP_NPTYPE_CERT:
1122			if (oakley_savecert(iph1, pa->ptr) < 0)
1123				goto end;
1124			break;
1125		case ISAKMP_NPTYPE_SIG:
1126			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
1127				goto end;
1128			break;
1129#endif
1130		case ISAKMP_NPTYPE_N:
1131			isakmp_check_notify(pa->ptr, iph1);
1132			break;
1133		default:
1134			/* don't send information, see isakmp_ident_r1() */
1135			plog(LLV_ERROR, LOCATION, iph1->remote,
1136				"ignore the packet, "
1137				"received unexpecting payload type %d.\n",
1138				pa->type);
1139			goto end;
1140		}
1141	}
1142
1143	/* validate authentication value */
1144    {
1145	int type;
1146	type = oakley_validate_auth(iph1);
1147	if (type != 0) {
1148		if (type == -1) {
1149			/* message printed inner oakley_validate_auth() */
1150			goto end;
1151		}
1152		isakmp_info_send_n1(iph1, type, NULL);
1153		goto end;
1154	}
1155    }
1156
1157	iph1->status = PHASE1ST_MSG2RECEIVED;
1158
1159	error = 0;
1160
1161end:
1162	if (pbuf)
1163		vfree(pbuf);
1164	if (msg)
1165		vfree(msg);
1166	if (error) {
1167		oakley_delcert(iph1->cert_p);
1168		iph1->cert_p = NULL;
1169		oakley_delcert(iph1->crl_p);
1170		iph1->crl_p = NULL;
1171		VPTRINIT(iph1->sig_p);
1172	}
1173
1174	return error;
1175}
1176
1177/*
1178 * status update and establish isakmp sa.
1179 */
1180int
1181agg_r2send(iph1, msg)
1182	struct ph1handle *iph1;
1183	vchar_t *msg;
1184{
1185	int error = -1;
1186
1187	/* validity check */
1188	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
1189		plog(LLV_ERROR, LOCATION, NULL,
1190			"status mismatched %d.\n", iph1->status);
1191		goto end;
1192	}
1193
1194	/* IV synchronized when packet encrypted. */
1195	/* see handler.h about IV synchronization. */
1196	if (ISSET(((struct isakmp *)msg->v)->flags, ISAKMP_FLAG_E))
1197		memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
1198
1199	/* set encryption flag */
1200	iph1->flags |= ISAKMP_FLAG_E;
1201
1202	iph1->status = PHASE1ST_ESTABLISHED;
1203
1204	error = 0;
1205
1206end:
1207	return error;
1208}
1209