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