c6f1b242cd2e43a3addc4051589488428367a0d5
[bcm963xx.git] / userapps / opensource / ipsec-tools / src / racoon / isakmp_base.c
1 /*      $KAME: isakmp_base.c,v 1.49 2003/11/13 02:30:20 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 /* Base Exchange (Base Mode) */
33
34 #include "config.h"
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <errno.h>
43 #if TIME_WITH_SYS_TIME
44 # include <sys/time.h>
45 # include <time.h>
46 #else
47 # if HAVE_SYS_TIME_H
48 #  include <sys/time.h>
49 # else
50 #  include <time.h>
51 # endif
52 #endif
53
54 #include "var.h"
55 #include "misc.h"
56 #include "vmbuf.h"
57 #include "plog.h"
58 #include "sockmisc.h"
59 #include "schedule.h"
60 #include "debug.h"
61
62 #include "localconf.h"
63 #include "remoteconf.h"
64 #include "isakmp_var.h"
65 #include "isakmp.h"
66 #include "evt.h"
67 #include "oakley.h"
68 #include "handler.h"
69 #include "ipsec_doi.h"
70 #include "crypto_openssl.h"
71 #include "pfkey.h"
72 #include "isakmp_base.h"
73 #include "isakmp_inf.h"
74 #include "vendorid.h"
75 #ifdef ENABLE_NATT
76 #include "nattraversal.h"
77 #endif
78 #ifdef ENABLE_FRAG
79 #include "isakmp_frag.h"
80 #endif
81
82 /* %%%
83  * begin Identity Protection Mode as initiator.
84  */
85 /*
86  * send to responder
87  *      psk: HDR, SA, Idii, Ni_b
88  *      sig: HDR, SA, Idii, Ni_b
89  *      rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r
90  *      rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i
91  */
92 int
93 base_i1send(iph1, msg)
94         struct ph1handle *iph1;
95         vchar_t *msg; /* must be null */
96 {
97         struct payload_list *plist = NULL;
98         int error = -1;
99 #ifdef ENABLE_NATT
100         vchar_t *vid_natt[MAX_NATT_VID_COUNT];
101         int i, vid_natt_i = 0;
102 #endif
103 #ifdef ENABLE_FRAG
104         vchar_t *vid_frag = NULL;
105 #endif
106
107         /* validity check */
108         if (msg != NULL) {
109                 plog(LLV_ERROR, LOCATION, NULL,
110                         "msg has to be NULL in this function.\n");
111                 goto end;
112         }
113         if (iph1->status != PHASE1ST_START) {
114                 plog(LLV_ERROR, LOCATION, NULL,
115                         "status mismatched %d.\n", iph1->status);
116                 goto end;
117         }
118
119         /* create isakmp index */
120         memset(&iph1->index, 0, sizeof(iph1->index));
121         isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
122
123         /* make ID payload into isakmp status */
124         if (ipsecdoi_setid1(iph1) < 0)
125                 goto end;
126
127         /* create SA payload for my proposal */
128         iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
129         if (iph1->sa == NULL)
130                 goto end;
131
132         /* generate NONCE value */
133         iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
134         if (iph1->nonce == NULL)
135                 goto end;
136
137 #ifdef ENABLE_FRAG
138         if (iph1->rmconf->ike_frag) {
139                 vid_frag = set_vendorid(VENDORID_FRAG);
140                 if (vid_frag != NULL)
141                         vid_frag = isakmp_frag_addcap(vid_frag, 
142                             VENDORID_FRAG_BASE);
143                 if (vid_frag == NULL)
144                         plog(LLV_ERROR, LOCATION, NULL, 
145                             "Frag vendorID construction failed\n");
146         }
147 #endif
148 #ifdef ENABLE_NATT
149         /* Is NAT-T support allowed in the config file? */
150         if (iph1->rmconf->nat_traversal) {
151                 /* Advertise NAT-T capability */
152                 memset (vid_natt, 0, sizeof (vid_natt));
153 #ifdef VENDORID_NATT_00
154                 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_00)) != NULL)
155                         vid_natt_i++;
156 #endif
157 #ifdef VENDORID_NATT_02
158                 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02)) != NULL)
159                         vid_natt_i++;
160 #endif
161 #ifdef VENDORID_NATT_02_N
162                 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02_N)) != NULL)
163                         vid_natt_i++;
164 #endif
165 #ifdef VENDORID_NATT_RFC
166                 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_RFC)) != NULL)
167                         vid_natt_i++;
168 #endif
169         }
170 #endif
171
172         /* set SA payload to propose */
173         plist = isakmp_plist_append(plist, iph1->sa, ISAKMP_NPTYPE_SA);
174
175         /* create isakmp ID payload */
176         plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
177
178         /* create isakmp NONCE payload */
179         plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
180
181 #ifdef ENABLE_FRAG
182         if (vid_frag)
183                 plist = isakmp_plist_append(plist, vid_frag, ISAKMP_NPTYPE_VID);
184 #endif
185 #ifdef ENABLE_NATT
186         /* set VID payload for NAT-T */
187         for (i = 0; i < vid_natt_i; i++)
188                 plist = isakmp_plist_append(plist, vid_natt[i], ISAKMP_NPTYPE_VID);
189
190         iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
191 #endif
192
193 #ifdef HAVE_PRINT_ISAKMP_C
194         isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
195 #endif
196
197         /* send the packet, add to the schedule to resend */
198         iph1->retry_counter = iph1->rmconf->retry_counter;
199         if (isakmp_ph1resend(iph1) == -1)
200                 goto end;
201
202         iph1->status = PHASE1ST_MSG1SENT;
203
204         error = 0;
205
206 end:
207 #ifdef ENABLE_FRAG
208         if (vid_frag)
209                 vfree(vid_frag);
210 #endif 
211 #ifdef ENABLE_NATT
212         for (i = 0; i < vid_natt_i; i++)
213                 vfree(vid_natt[i]);
214 #endif
215
216         return error;
217 }
218
219 /*
220  * receive from responder
221  *      psk: HDR, SA, Idir, Nr_b
222  *      sig: HDR, SA, Idir, Nr_b, [ CR ]
223  *      rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i
224  *      rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r
225  */
226 int
227 base_i2recv(iph1, msg)
228         struct ph1handle *iph1;
229         vchar_t *msg;
230 {
231         vchar_t *pbuf = NULL;
232         struct isakmp_parse_t *pa;
233         vchar_t *satmp = NULL;
234         int error = -1;
235         int vid_numeric;
236
237         /* validity check */
238         if (iph1->status != PHASE1ST_MSG1SENT) {
239                 plog(LLV_ERROR, LOCATION, NULL,
240                         "status mismatched %d.\n", iph1->status);
241                 goto end;
242         }
243
244         /* validate the type of next payload */
245         pbuf = isakmp_parse(msg);
246         if (pbuf == NULL)
247                 goto end;
248         pa = (struct isakmp_parse_t *)pbuf->v;
249
250         /* SA payload is fixed postion */
251         if (pa->type != ISAKMP_NPTYPE_SA) {
252                 plog(LLV_ERROR, LOCATION, iph1->remote,
253                         "received invalid next payload type %d, "
254                         "expecting %d.\n",
255                         pa->type, ISAKMP_NPTYPE_SA);
256                 goto end;
257         }
258         if (isakmp_p2ph(&satmp, pa->ptr) < 0)
259                 goto end;
260         pa++;
261
262         for (/*nothing*/;
263              pa->type != ISAKMP_NPTYPE_NONE;
264              pa++) {
265
266                 switch (pa->type) {
267                 case ISAKMP_NPTYPE_NONCE:
268                         if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
269                                 goto end;
270                         break;
271                 case ISAKMP_NPTYPE_ID:
272                         if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
273                                 goto end;
274                         break;
275                 case ISAKMP_NPTYPE_VID:
276                         vid_numeric = check_vendorid(pa->ptr);
277 #ifdef ENABLE_NATT
278                         if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
279                           natt_handle_vendorid(iph1, vid_numeric);
280 #endif
281                         break;
282                 default:
283                         /* don't send information, see ident_r1recv() */
284                         plog(LLV_ERROR, LOCATION, iph1->remote,
285                                 "ignore the packet, "
286                                 "received unexpecting payload type %d.\n",
287                                 pa->type);
288                         goto end;
289                 }
290         }
291
292         if (iph1->nonce_p == NULL || iph1->id_p == NULL) {
293                 plog(LLV_ERROR, LOCATION, iph1->remote,
294                         "few isakmp message received.\n");
295                 goto end;
296         }
297
298         /* verify identifier */
299         if (ipsecdoi_checkid1(iph1) != 0) {
300                 plog(LLV_ERROR, LOCATION, iph1->remote,
301                         "invalid ID payload.\n");
302                 goto end;
303         }
304
305 #ifdef ENABLE_NATT
306         if (NATT_AVAILABLE(iph1))
307                 plog(LLV_INFO, LOCATION, iph1->remote,
308                      "Selected NAT-T version: %s\n",
309                      vid_string_by_id(iph1->natt_options->version));
310 #endif
311
312         /* check SA payload and set approval SA for use */
313         if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
314                 plog(LLV_ERROR, LOCATION, iph1->remote,
315                         "failed to get valid proposal.\n");
316                 /* XXX send information */
317                 goto end;
318         }
319         VPTRINIT(iph1->sa_ret);
320
321         iph1->status = PHASE1ST_MSG2RECEIVED;
322
323         error = 0;
324
325 end:
326         if (pbuf)
327                 vfree(pbuf);
328         if (satmp)
329                 vfree(satmp);
330
331         if (error) {
332                 VPTRINIT(iph1->nonce_p);
333                 VPTRINIT(iph1->id_p);
334         }
335
336         return error;
337 }
338
339 /*
340  * send to responder
341  *      psk: HDR, KE, HASH_I
342  *      sig: HDR, KE, [ CR, ] [CERT,] SIG_I
343  *      rsa: HDR, KE, HASH_I
344  *      rev: HDR, <KE>Ke_i, HASH_I
345  */
346 int
347 base_i2send(iph1, msg)
348         struct ph1handle *iph1;
349         vchar_t *msg;
350 {
351         struct payload_list *plist = NULL;
352         vchar_t *vid = NULL;
353         int need_cert = 0;
354         int error = -1;
355
356         /* validity check */
357         if (iph1->status != PHASE1ST_MSG2RECEIVED) {
358                 plog(LLV_ERROR, LOCATION, NULL,
359                         "status mismatched %d.\n", iph1->status);
360                 goto end;
361         }
362
363         /* fix isakmp index */
364         memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
365                 sizeof(cookie_t));
366
367         /* generate DH public value */
368         if (oakley_dh_generate(iph1->approval->dhgrp,
369                                 &iph1->dhpub, &iph1->dhpriv) < 0)
370                 goto end;
371
372         /* generate SKEYID to compute hash if not signature mode */
373         if (iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_RSASIG
374          && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_DSSSIG) {
375                 if (oakley_skeyid(iph1) < 0)
376                         goto end;
377         }
378
379         /* generate HASH to send */
380         plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
381         iph1->hash = oakley_ph1hash_base_i(iph1, GENERATE);
382         if (iph1->hash == NULL)
383                 goto end;
384
385         switch (iph1->approval->authmethod) {
386         case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
387                 vid = set_vendorid(iph1->approval->vendorid);
388
389                 /* create isakmp KE payload */
390                 plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
391
392                 /* create isakmp HASH payload */
393                 plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH);
394
395                 /* append vendor id, if needed */
396                 if (vid)
397                         plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID);
398                 break;
399         case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
400         case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
401                 /* XXX if there is CR or not ? */
402
403                 if (oakley_getmycert(iph1) < 0)
404                         goto end;
405
406                 if (oakley_getsign(iph1) < 0)
407                         goto end;
408
409                 if (iph1->cert && iph1->rmconf->send_cert)
410                         need_cert = 1;
411
412                 /* create isakmp KE payload */
413                 plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
414
415                 /* add CERT payload if there */
416                 if (need_cert)
417                         plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT);
418
419                 /* add SIG payload */
420                 plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG);
421                 break;
422         case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
423                 /* ... */
424                 break;
425         case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
426         case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
427                 break;
428         }
429
430 #ifdef ENABLE_NATT
431         /* generate NAT-D payloads */
432         if (NATT_AVAILABLE(iph1))
433         {
434                 vchar_t *natd[2] = { NULL, NULL };
435
436                 plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n");
437                 if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
438                         plog(LLV_ERROR, LOCATION, NULL,
439                                 "NAT-D hashing failed for %s\n", saddr2str(iph1->remote));
440                         goto end;
441                 }
442
443                 if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
444                         plog(LLV_ERROR, LOCATION, NULL,
445                                 "NAT-D hashing failed for %s\n", saddr2str(iph1->local));
446                         goto end;
447                 }
448
449                 plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d);
450                 plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
451         }
452 #endif
453
454         iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
455
456 #ifdef HAVE_PRINT_ISAKMP_C
457         isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
458 #endif
459
460         /* send the packet, add to the schedule to resend */
461         iph1->retry_counter = iph1->rmconf->retry_counter;
462         if (isakmp_ph1resend(iph1) == -1)
463                 goto end;
464
465         /* the sending message is added to the received-list. */
466         if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
467                 plog(LLV_ERROR , LOCATION, NULL,
468                         "failed to add a response packet to the tree.\n");
469                 goto end;
470         }
471
472         iph1->status = PHASE1ST_MSG2SENT;
473
474         error = 0;
475
476 end:
477         if (vid)
478                 vfree(vid);
479         return error;
480 }
481
482 /*
483  * receive from responder
484  *      psk: HDR, KE, HASH_R
485  *      sig: HDR, KE, [CERT,] SIG_R
486  *      rsa: HDR, KE, HASH_R
487  *      rev: HDR, <KE>_Ke_r, HASH_R
488  */
489 int
490 base_i3recv(iph1, msg)
491         struct ph1handle *iph1;
492         vchar_t *msg;
493 {
494         vchar_t *pbuf = NULL;
495         struct isakmp_parse_t *pa;
496         int error = -1;
497         int ptype;
498 #ifdef ENABLE_NATT
499         vchar_t *natd_received;
500         int natd_seq = 0, natd_verified;
501 #endif
502
503         /* validity check */
504         if (iph1->status != PHASE1ST_MSG2SENT) {
505                 plog(LLV_ERROR, LOCATION, NULL,
506                         "status mismatched %d.\n", iph1->status);
507                 goto end;
508         }
509
510         /* validate the type of next payload */
511         pbuf = isakmp_parse(msg);
512         if (pbuf == NULL)
513                 goto end;
514
515         for (pa = (struct isakmp_parse_t *)pbuf->v;
516              pa->type != ISAKMP_NPTYPE_NONE;
517              pa++) {
518
519                 switch (pa->type) {
520                 case ISAKMP_NPTYPE_KE:
521                         if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
522                                 goto end;
523                         break;
524                 case ISAKMP_NPTYPE_HASH:
525                         iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
526                         break;
527                 case ISAKMP_NPTYPE_CERT:
528                         if (oakley_savecert(iph1, pa->ptr) < 0)
529                                 goto end;
530                         break;
531                 case ISAKMP_NPTYPE_SIG:
532                         if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
533                                 goto end;
534                         break;
535                 case ISAKMP_NPTYPE_VID:
536                         (void)check_vendorid(pa->ptr);
537                         break;
538
539 #ifdef ENABLE_NATT
540                 case ISAKMP_NPTYPE_NATD_DRAFT:
541                 case ISAKMP_NPTYPE_NATD_RFC:
542                         if (NATT_AVAILABLE(iph1) && iph1->natt_options &&
543                             pa->type == iph1->natt_options->payload_nat_d) {
544                                 natd_received = NULL;
545                                 if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
546                                         goto end;
547                         
548                                 /* set both bits first so that we can clear them
549                                    upon verifying hashes */
550                                 if (natd_seq == 0)
551                                         iph1->natt_flags |= NAT_DETECTED;
552                         
553                                 /* this function will clear appropriate bits bits 
554                                    from iph1->natt_flags */
555                                 natd_verified = natt_compare_addr_hash (iph1,
556                                         natd_received, natd_seq++);
557                         
558                                 plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
559                                         natd_seq - 1,
560                                         natd_verified ? "verified" : "doesn't match");
561                         
562                                 vfree (natd_received);
563                                 break;
564                         }
565                         /* passthrough to default... */
566 #endif
567
568                 default:
569                         /* don't send information, see ident_r1recv() */
570                         plog(LLV_ERROR, LOCATION, iph1->remote,
571                                 "ignore the packet, "
572                                 "received unexpecting payload type %d.\n",
573                                 pa->type);
574                         goto end;
575                 }
576         }
577
578 #ifdef ENABLE_NATT
579         if (NATT_AVAILABLE(iph1)) {
580                 plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
581                       iph1->natt_flags & NAT_DETECTED ? 
582                                 "detected:" : "not detected",
583                       iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
584                       iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
585                 if (iph1->natt_flags & NAT_DETECTED)
586                         natt_float_ports (iph1);
587         }
588 #endif
589
590         /* payload existency check */
591         /* validate authentication value */
592         ptype = oakley_validate_auth(iph1);
593         if (ptype != 0) {
594                 if (ptype == -1) {
595                         /* message printed inner oakley_validate_auth() */
596                         goto end;
597                 }
598                 EVT_PUSH(iph1->local, iph1->remote, 
599                     EVTT_PEERPH1AUTH_FAILED, NULL);
600                 isakmp_info_send_n1(iph1, ptype, NULL);
601                 goto end;
602         }
603
604         /* compute sharing secret of DH */
605         if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
606                                 iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
607                 goto end;
608
609         /* generate SKEYID to compute hash if signature mode */
610         if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_RSASIG
611          || iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_DSSSIG) {
612                 if (oakley_skeyid(iph1) < 0)
613                         goto end;
614         }
615
616         /* generate SKEYIDs & IV & final cipher key */
617         if (oakley_skeyid_dae(iph1) < 0)
618                 goto end;
619         if (oakley_compute_enckey(iph1) < 0)
620                 goto end;
621         if (oakley_newiv(iph1) < 0)
622                 goto end;
623
624         /* see handler.h about IV synchronization. */
625         memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
626
627         /* set encryption flag */
628         iph1->flags |= ISAKMP_FLAG_E;
629
630         iph1->status = PHASE1ST_MSG3RECEIVED;
631
632         error = 0;
633
634 end:
635         if (pbuf)
636                 vfree(pbuf);
637
638         if (error) {
639                 VPTRINIT(iph1->dhpub_p);
640                 oakley_delcert(iph1->cert_p);
641                 iph1->cert_p = NULL;
642                 oakley_delcert(iph1->crl_p);
643                 iph1->crl_p = NULL;
644                 VPTRINIT(iph1->sig_p);
645         }
646
647         return error;
648 }
649
650 /*
651  * status update and establish isakmp sa.
652  */
653 int
654 base_i3send(iph1, msg)
655         struct ph1handle *iph1;
656         vchar_t *msg;
657 {
658         int error = -1;
659
660         /* validity check */
661         if (iph1->status != PHASE1ST_MSG3RECEIVED) {
662                 plog(LLV_ERROR, LOCATION, NULL,
663                         "status mismatched %d.\n", iph1->status);
664                 goto end;
665         }
666
667         iph1->status = PHASE1ST_ESTABLISHED;
668
669         error = 0;
670
671 end:
672         return error;
673 }
674
675 /*
676  * receive from initiator
677  *      psk: HDR, SA, Idii, Ni_b
678  *      sig: HDR, SA, Idii, Ni_b
679  *      rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r
680  *      rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i
681  */
682 int
683 base_r1recv(iph1, msg)
684         struct ph1handle *iph1;
685         vchar_t *msg;
686 {
687         vchar_t *pbuf = NULL;
688         struct isakmp_parse_t *pa;
689         int error = -1;
690         int vid_numeric;
691
692         /* validity check */
693         if (iph1->status != PHASE1ST_START) {
694                 plog(LLV_ERROR, LOCATION, NULL,
695                         "status mismatched %d.\n", iph1->status);
696                 goto end;
697         }
698
699         /* validate the type of next payload */
700         /*
701          * NOTE: XXX even if multiple VID, we'll silently ignore those.
702          */
703         pbuf = isakmp_parse(msg);
704         if (pbuf == NULL)
705                 goto end;
706         pa = (struct isakmp_parse_t *)pbuf->v;
707
708         /* check the position of SA payload */
709         if (pa->type != ISAKMP_NPTYPE_SA) {
710                 plog(LLV_ERROR, LOCATION, iph1->remote,
711                         "received invalid next payload type %d, "
712                         "expecting %d.\n",
713                         pa->type, ISAKMP_NPTYPE_SA);
714                 goto end;
715         }
716         if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
717                 goto end;
718         pa++;
719
720         for (/*nothing*/;
721              pa->type != ISAKMP_NPTYPE_NONE;
722              pa++) {
723
724                 switch (pa->type) {
725                 case ISAKMP_NPTYPE_NONCE:
726                         if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
727                                 goto end;
728                         break;
729                 case ISAKMP_NPTYPE_ID:
730                         if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
731                                 goto end;
732                         break;
733                 case ISAKMP_NPTYPE_VID:
734                         vid_numeric = check_vendorid(pa->ptr);
735 #ifdef ENABLE_NATT
736                         if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
737                                 natt_handle_vendorid(iph1, vid_numeric);
738 #endif
739 #ifdef ENABLE_FRAG
740                         if ((vid_numeric == VENDORID_FRAG) &&
741                             (vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_BASE))
742                                 iph1->frag = 1;
743 #endif
744                         break;
745                 default:
746                         /* don't send information, see ident_r1recv() */
747                         plog(LLV_ERROR, LOCATION, iph1->remote,
748                                 "ignore the packet, "
749                                 "received unexpecting payload type %d.\n",
750                                 pa->type);
751                         goto end;
752                 }
753         }
754
755         if (iph1->nonce_p == NULL || iph1->id_p == NULL) {
756                 plog(LLV_ERROR, LOCATION, iph1->remote,
757                         "few isakmp message received.\n");
758                 goto end;
759         }
760
761         /* verify identifier */
762         if (ipsecdoi_checkid1(iph1) != 0) {
763                 plog(LLV_ERROR, LOCATION, iph1->remote,
764                         "invalid ID payload.\n");
765                 goto end;
766         }
767
768 #ifdef ENABLE_NATT
769         if (NATT_AVAILABLE(iph1))
770                 plog(LLV_INFO, LOCATION, iph1->remote,
771                      "Selected NAT-T version: %s\n",
772                      vid_string_by_id(iph1->natt_options->version));
773 #endif
774
775         /* check SA payload and set approval SA for use */
776         if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
777                 plog(LLV_ERROR, LOCATION, iph1->remote,
778                         "failed to get valid proposal.\n");
779                 /* XXX send information */
780                 goto end;
781         }
782
783         iph1->status = PHASE1ST_MSG1RECEIVED;
784
785         error = 0;
786
787 end:
788         if (pbuf)
789                 vfree(pbuf);
790
791         if (error) {
792                 VPTRINIT(iph1->sa);
793                 VPTRINIT(iph1->nonce_p);
794                 VPTRINIT(iph1->id_p);
795         }
796
797         return error;
798 }
799
800 /*
801  * send to initiator
802  *      psk: HDR, SA, Idir, Nr_b
803  *      sig: HDR, SA, Idir, Nr_b, [ CR ]
804  *      rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i
805  *      rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r
806  */
807 int
808 base_r1send(iph1, msg)
809         struct ph1handle *iph1;
810         vchar_t *msg;
811 {
812         struct payload_list *plist = NULL;
813         int error = -1;
814 #ifdef ENABLE_NATT
815         vchar_t *vid_natt = NULL;
816 #endif
817
818         /* validity check */
819         if (iph1->status != PHASE1ST_MSG1RECEIVED) {
820                 plog(LLV_ERROR, LOCATION, NULL,
821                         "status mismatched %d.\n", iph1->status);
822                 goto end;
823         }
824
825         /* set responder's cookie */
826         isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
827
828         /* make ID payload into isakmp status */
829         if (ipsecdoi_setid1(iph1) < 0)
830                 goto end;
831
832         /* generate NONCE value */
833         iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
834         if (iph1->nonce == NULL)
835                 goto end;
836
837         /* set SA payload to reply */
838         plist = isakmp_plist_append(plist, iph1->sa_ret, ISAKMP_NPTYPE_SA);
839
840         /* create isakmp ID payload */
841         plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
842
843         /* create isakmp NONCE payload */
844         plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
845
846 #ifdef ENABLE_NATT
847         /* has the peer announced nat-t? */
848         if (NATT_AVAILABLE(iph1))
849                 vid_natt = set_vendorid(iph1->natt_options->version);
850         if (vid_natt)
851                 plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID);
852 #endif
853
854         iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
855
856 #ifdef HAVE_PRINT_ISAKMP_C
857         isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
858 #endif
859
860         /* send the packet, add to the schedule to resend */
861         iph1->retry_counter = iph1->rmconf->retry_counter;
862         if (isakmp_ph1resend(iph1) == -1)
863                 goto end;
864
865         /* the sending message is added to the received-list. */
866         if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
867                 plog(LLV_ERROR , LOCATION, NULL,
868                         "failed to add a response packet to the tree.\n");
869                 goto end;
870         }
871
872         iph1->status = PHASE1ST_MSG1SENT;
873
874         error = 0;
875
876 end:
877 #ifdef ENABLE_NATT
878         if (vid_natt)
879                 vfree(vid_natt);
880 #endif
881
882         VPTRINIT(iph1->sa_ret);
883
884         return error;
885 }
886
887 /*
888  * receive from initiator
889  *      psk: HDR, KE, HASH_I
890  *      sig: HDR, KE, [ CR, ] [CERT,] SIG_I
891  *      rsa: HDR, KE, HASH_I
892  *      rev: HDR, <KE>Ke_i, HASH_I
893  */
894 int
895 base_r2recv(iph1, msg)
896         struct ph1handle *iph1;
897         vchar_t *msg;
898 {
899         vchar_t *pbuf = NULL;
900         struct isakmp_parse_t *pa;
901         int error = -1;
902         int ptype;
903 #ifdef ENABLE_NATT
904         int natd_seq = 0;
905 #endif
906
907         /* validity check */
908         if (iph1->status != PHASE1ST_MSG1SENT) {
909                 plog(LLV_ERROR, LOCATION, NULL,
910                         "status mismatched %d.\n", iph1->status);
911                 goto end;
912         }
913
914         /* validate the type of next payload */
915         pbuf = isakmp_parse(msg);
916         if (pbuf == NULL)
917                 goto end;
918
919         iph1->pl_hash = NULL;
920
921         for (pa = (struct isakmp_parse_t *)pbuf->v;
922              pa->type != ISAKMP_NPTYPE_NONE;
923              pa++) {
924
925                 switch (pa->type) {
926                 case ISAKMP_NPTYPE_KE:
927                         if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
928                                 goto end;
929                         break;
930                 case ISAKMP_NPTYPE_HASH:
931                         iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
932                         break;
933                 case ISAKMP_NPTYPE_CERT:
934                         if (oakley_savecert(iph1, pa->ptr) < 0)
935                                 goto end;
936                         break;
937                 case ISAKMP_NPTYPE_SIG:
938                         if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
939                                 goto end;
940                         break;
941                 case ISAKMP_NPTYPE_VID:
942                         (void)check_vendorid(pa->ptr);
943                         break;
944
945 #ifdef ENABLE_NATT
946                 case ISAKMP_NPTYPE_NATD_DRAFT:
947                 case ISAKMP_NPTYPE_NATD_RFC:
948                         if (pa->type == iph1->natt_options->payload_nat_d)
949                         {
950                                 vchar_t *natd_received = NULL;
951                                 int natd_verified;
952                                 
953                                 if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
954                                         goto end;
955                                 
956                                 if (natd_seq == 0)
957                                         iph1->natt_flags |= NAT_DETECTED;
958                                 
959                                 natd_verified = natt_compare_addr_hash (iph1,
960                                         natd_received, natd_seq++);
961                                 
962                                 plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
963                                         natd_seq - 1,
964                                         natd_verified ? "verified" : "doesn't match");
965                                 
966                                 vfree (natd_received);
967                                 break;
968                         }
969                         /* passthrough to default... */
970 #endif
971
972                 default:
973                         /* don't send information, see ident_r1recv() */
974                         plog(LLV_ERROR, LOCATION, iph1->remote,
975                                 "ignore the packet, "
976                                 "received unexpecting payload type %d.\n",
977                                 pa->type);
978                         goto end;
979                 }
980         }
981
982         /* generate DH public value */
983         if (oakley_dh_generate(iph1->approval->dhgrp,
984                                 &iph1->dhpub, &iph1->dhpriv) < 0)
985                 goto end;
986
987         /* compute sharing secret of DH */
988         if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
989                                 iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
990                 goto end;
991
992         /* generate SKEYID */
993         if (oakley_skeyid(iph1) < 0)
994                 goto end;
995
996 #ifdef ENABLE_NATT
997         if (NATT_AVAILABLE(iph1))
998                 plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
999                       iph1->natt_flags & NAT_DETECTED ? 
1000                                 "detected:" : "not detected",
1001                       iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
1002                       iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
1003 #endif
1004
1005         /* payload existency check */
1006         /* validate authentication value */
1007         ptype = oakley_validate_auth(iph1);
1008         if (ptype != 0) {
1009                 if (ptype == -1) {
1010                         /* message printed inner oakley_validate_auth() */
1011                         goto end;
1012                 }
1013                 EVT_PUSH(iph1->local, iph1->remote, 
1014                     EVTT_PEERPH1AUTH_FAILED, NULL);
1015                 isakmp_info_send_n1(iph1, ptype, NULL);
1016                 goto end;
1017         }
1018
1019         iph1->status = PHASE1ST_MSG2RECEIVED;
1020
1021         error = 0;
1022
1023 end:
1024         if (pbuf)
1025                 vfree(pbuf);
1026
1027         if (error) {
1028                 VPTRINIT(iph1->dhpub_p);
1029                 oakley_delcert(iph1->cert_p);
1030                 iph1->cert_p = NULL;
1031                 oakley_delcert(iph1->crl_p);
1032                 iph1->crl_p = NULL;
1033                 VPTRINIT(iph1->sig_p);
1034         }
1035
1036         return error;
1037 }
1038
1039 /*
1040  * send to initiator
1041  *      psk: HDR, KE, HASH_R
1042  *      sig: HDR, KE, [CERT,] SIG_R
1043  *      rsa: HDR, KE, HASH_R
1044  *      rev: HDR, <KE>_Ke_r, HASH_R
1045  */
1046 int
1047 base_r2send(iph1, msg)
1048         struct ph1handle *iph1;
1049         vchar_t *msg;
1050 {
1051         struct payload_list *plist = NULL;
1052         vchar_t *vid = NULL;
1053         int need_cert = 0;
1054         int error = -1;
1055
1056         /* validity check */
1057         if (iph1->status != PHASE1ST_MSG2RECEIVED) {
1058                 plog(LLV_ERROR, LOCATION, NULL,
1059                         "status mismatched %d.\n", iph1->status);
1060                 goto end;
1061         }
1062
1063         /* generate HASH to send */
1064         plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
1065         switch (iph1->approval->authmethod) {
1066         case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1067         case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1068         case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1069                 iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
1070                 break;
1071         case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1072         case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1073         case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1074                 iph1->hash = oakley_ph1hash_base_r(iph1, GENERATE);
1075                 break;
1076         default:
1077                 plog(LLV_ERROR, LOCATION, NULL,
1078                         "invalid authentication method %d\n",
1079                         iph1->approval->authmethod);
1080                 goto end; 
1081         }
1082         if (iph1->hash == NULL)
1083                 goto end;
1084
1085         switch (iph1->approval->authmethod) {
1086         case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1087                 vid = set_vendorid(iph1->approval->vendorid);
1088
1089                 /* create isakmp KE payload */
1090                 plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
1091
1092                 /* create isakmp HASH payload */
1093                 plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH);
1094
1095                 /* append vendor id, if needed */
1096                 if (vid)
1097                         plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID);
1098                 break;
1099         case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1100         case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1101                 /* XXX if there is CR or not ? */
1102
1103                 if (oakley_getmycert(iph1) < 0)
1104                         goto end;
1105
1106                 if (oakley_getsign(iph1) < 0)
1107                         goto end;
1108
1109                 if (iph1->cert && iph1->rmconf->send_cert)
1110                         need_cert = 1;
1111
1112                 /* create isakmp KE payload */
1113                 plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
1114
1115                 /* add CERT payload if there */
1116                 if (need_cert)
1117                         plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT);
1118                 /* add SIG payload */
1119                 plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG);
1120                 break;
1121         case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1122                 /* ... */
1123                 break;
1124         case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1125         case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1126                 break;
1127         }
1128
1129 #ifdef ENABLE_NATT
1130         /* generate NAT-D payloads */
1131         if (NATT_AVAILABLE(iph1))
1132         {
1133                 vchar_t *natd[2] = { NULL, NULL };
1134
1135                 plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n");
1136                 if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
1137                         plog(LLV_ERROR, LOCATION, NULL,
1138                                 "NAT-D hashing failed for %s\n", saddr2str(iph1->remote));
1139                         goto end;
1140                 }
1141
1142                 if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
1143                         plog(LLV_ERROR, LOCATION, NULL,
1144                                 "NAT-D hashing failed for %s\n", saddr2str(iph1->local));
1145                         goto end;
1146                 }
1147
1148                 plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d);
1149                 plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
1150         }
1151 #endif
1152
1153         iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
1154
1155 #ifdef HAVE_PRINT_ISAKMP_C
1156         isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
1157 #endif
1158
1159         /* send HDR;KE;NONCE to responder */
1160         if (isakmp_send(iph1, iph1->sendbuf) < 0)
1161                 goto end;
1162
1163         /* the sending message is added to the received-list. */
1164         if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1165                 plog(LLV_ERROR , LOCATION, NULL,
1166                         "failed to add a response packet to the tree.\n");
1167                 goto end;
1168         }
1169
1170         /* generate SKEYIDs & IV & final cipher key */
1171         if (oakley_skeyid_dae(iph1) < 0)
1172                 goto end;
1173         if (oakley_compute_enckey(iph1) < 0)
1174                 goto end;
1175         if (oakley_newiv(iph1) < 0)
1176                 goto end;
1177
1178         /* set encryption flag */
1179         iph1->flags |= ISAKMP_FLAG_E;
1180
1181         iph1->status = PHASE1ST_ESTABLISHED;
1182
1183         error = 0;
1184
1185 end:
1186         if (vid)
1187                 vfree(vid);
1188         return error;
1189 }