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