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