No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / racoon / isakmp_quick.c
blob91db6fbce5d3ddf03a54a01e0562e5a99e916e4e
1 /* $NetBSD: isakmp_quick.c,v 1.25 2009/03/12 10:57:26 tteras Exp $ */
3 /* Id: isakmp_quick.c,v 1.29 2006/08/22 18:17:17 manubsd Exp */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "config.h"
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
40 #include <netinet/in.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #if TIME_WITH_SYS_TIME
47 # include <sys/time.h>
48 # include <time.h>
49 #else
50 # if HAVE_SYS_TIME_H
51 # include <sys/time.h>
52 # else
53 # include <time.h>
54 # endif
55 #endif
57 #include PATH_IPSEC_H
59 #include "var.h"
60 #include "vmbuf.h"
61 #include "schedule.h"
62 #include "misc.h"
63 #include "plog.h"
64 #include "debug.h"
66 #include "localconf.h"
67 #include "remoteconf.h"
68 #include "handler.h"
69 #include "policy.h"
70 #include "proposal.h"
71 #include "isakmp_var.h"
72 #include "isakmp.h"
73 #include "isakmp_inf.h"
74 #include "isakmp_quick.h"
75 #include "oakley.h"
76 #include "ipsec_doi.h"
77 #include "crypto_openssl.h"
78 #include "pfkey.h"
79 #include "policy.h"
80 #include "algorithm.h"
81 #include "sockmisc.h"
82 #include "proposal.h"
83 #include "sainfo.h"
84 #include "admin.h"
85 #include "strnames.h"
87 #ifdef ENABLE_HYBRID
88 #include <resolv.h>
89 #include "isakmp_xauth.h"
90 #include "isakmp_cfg.h"
91 #endif
93 #ifdef ENABLE_NATT
94 #include "nattraversal.h"
95 #endif
97 /* quick mode */
98 static vchar_t *quick_ir1mx __P((struct ph2handle *, vchar_t *, vchar_t *));
99 static int get_sainfo_r __P((struct ph2handle *));
100 static int get_proposal_r __P((struct ph2handle *));
101 static int ph2_recv_n __P((struct ph2handle *, struct isakmp_gen *));
102 static void quick_timeover_stub __P((struct sched *));
103 static void quick_timeover __P((struct ph2handle *));
105 /* called from scheduler */
106 static void
107 quick_timeover_stub(p)
108 struct sched *p;
110 quick_timeover(container_of(p, struct ph2handle, sce));
113 static void
114 quick_timeover(iph2)
115 struct ph2handle *iph2;
117 plog(LLV_ERROR, LOCATION, NULL,
118 "%s give up to get IPsec-SA due to time up to wait.\n",
119 saddrwop2str(iph2->dst));
121 /* If initiator side, send error to kernel by SADB_ACQUIRE. */
122 if (iph2->side == INITIATOR)
123 pk_sendeacquire(iph2);
125 remph2(iph2);
126 delph2(iph2);
129 /* \f%%%
130 * Quick Mode
133 * begin Quick Mode as initiator. send pfkey getspi message to kernel.
136 quick_i1prep(iph2, msg)
137 struct ph2handle *iph2;
138 vchar_t *msg; /* must be null pointer */
140 int error = ISAKMP_INTERNAL_ERROR;
142 /* validity check */
143 if (iph2->status != PHASE2ST_STATUS2) {
144 plog(LLV_ERROR, LOCATION, NULL,
145 "status mismatched %d.\n", iph2->status);
146 goto end;
149 iph2->msgid = isakmp_newmsgid2(iph2->ph1);
150 iph2->ivm = oakley_newiv2(iph2->ph1, iph2->msgid);
151 if (iph2->ivm == NULL)
152 return 0;
154 iph2->status = PHASE2ST_GETSPISENT;
156 /* don't anything if local test mode. */
157 if (f_local) {
158 error = 0;
159 goto end;
162 /* send getspi message */
163 if (pk_sendgetspi(iph2) < 0)
164 goto end;
166 plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
168 sched_schedule(&iph2->sce, lcconf->wait_ph2complete,
169 quick_timeover_stub);
171 error = 0;
173 end:
174 return error;
178 * send to responder
179 * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
182 quick_i1send(iph2, msg)
183 struct ph2handle *iph2;
184 vchar_t *msg; /* must be null pointer */
186 vchar_t *body = NULL;
187 vchar_t *hash = NULL;
188 struct isakmp_gen *gen;
189 char *p;
190 int tlen;
191 int error = ISAKMP_INTERNAL_ERROR;
192 int natoa = ISAKMP_NPTYPE_NONE;
193 int pfsgroup, idci, idcr;
194 int np;
195 struct ipsecdoi_id_b *id, *id_p;
196 #ifdef ENABLE_NATT
197 vchar_t *nat_oai = NULL;
198 vchar_t *nat_oar = NULL;
199 #endif
201 /* validity check */
202 if (msg != NULL) {
203 plog(LLV_ERROR, LOCATION, NULL,
204 "msg has to be NULL in this function.\n");
205 goto end;
207 if (iph2->status != PHASE2ST_GETSPIDONE) {
208 plog(LLV_ERROR, LOCATION, NULL,
209 "status mismatched %d.\n", iph2->status);
210 goto end;
213 /* create SA payload for my proposal */
214 if (ipsecdoi_setph2proposal(iph2) < 0)
215 goto end;
217 /* generate NONCE value */
218 iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
219 if (iph2->nonce == NULL)
220 goto end;
223 * DH value calculation is kicked out into cfparse.y.
224 * because pfs group can not be negotiated, it's only to be checked
225 * acceptable.
227 /* generate KE value if need */
228 pfsgroup = iph2->proposal->pfs_group;
229 if (pfsgroup) {
230 /* DH group settting if PFS is required. */
231 if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
232 plog(LLV_ERROR, LOCATION, NULL,
233 "failed to set DH value.\n");
234 goto end;
236 if (oakley_dh_generate(iph2->pfsgrp,
237 &iph2->dhpub, &iph2->dhpriv) < 0) {
238 goto end;
242 /* generate ID value */
243 if (ipsecdoi_setid2(iph2) < 0) {
244 plog(LLV_ERROR, LOCATION, NULL,
245 "failed to get ID.\n");
246 goto end;
248 plog(LLV_DEBUG, LOCATION, NULL, "IDci:\n");
249 plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
250 plog(LLV_DEBUG, LOCATION, NULL, "IDcr:\n");
251 plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
254 * we do not attach IDci nor IDcr, under the following condition:
255 * - all proposals are transport mode
256 * - no MIP6 or proxy
257 * - id payload suggests to encrypt all the traffic (no specific
258 * protocol type)
259 * - SA endpoints and IKE addresses for the nego are the same
260 * (iph2->src/dst)
262 id = (struct ipsecdoi_id_b *)iph2->id->v;
263 id_p = (struct ipsecdoi_id_b *)iph2->id_p->v;
264 if (id->proto_id == 0 &&
265 id_p->proto_id == 0 &&
266 iph2->ph1->rmconf->support_proxy == 0 &&
267 iph2->sa_src == NULL && iph2->sa_dst == NULL &&
268 ipsecdoi_transportmode(iph2->proposal)) {
269 idci = idcr = 0;
270 } else
271 idci = idcr = 1;
273 #ifdef ENABLE_NATT
275 * RFC3947 5.2. if we propose UDP-Encapsulated-Transport
276 * we should send NAT-OA
278 if (ipsecdoi_transportmode(iph2->proposal)
279 && (iph2->ph1->natt_flags & NAT_DETECTED)) {
280 natoa = iph2->ph1->natt_options->payload_nat_oa;
282 nat_oai = ipsecdoi_sockaddr2id(iph2->src,
283 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
284 nat_oar = ipsecdoi_sockaddr2id(iph2->dst,
285 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
287 if (nat_oai == NULL || nat_oar == NULL) {
288 plog(LLV_ERROR, LOCATION, NULL,
289 "failed to generate NAT-OA payload.\n");
290 goto end;
293 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n");
294 plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l);
295 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n");
296 plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l);
297 } else {
298 natoa = ISAKMP_NPTYPE_NONE;
300 #endif
302 /* create SA;NONCE payload, and KE if need, and IDii, IDir. */
303 tlen = + sizeof(*gen) + iph2->sa->l
304 + sizeof(*gen) + iph2->nonce->l;
305 if (pfsgroup)
306 tlen += (sizeof(*gen) + iph2->dhpub->l);
307 if (idci)
308 tlen += sizeof(*gen) + iph2->id->l;
309 if (idcr)
310 tlen += sizeof(*gen) + iph2->id_p->l;
311 #ifdef ENABLE_NATT
312 if (natoa != ISAKMP_NPTYPE_NONE)
313 tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
314 #endif
316 body = vmalloc(tlen);
317 if (body == NULL) {
318 plog(LLV_ERROR, LOCATION, NULL,
319 "failed to get buffer to send.\n");
320 goto end;
323 p = body->v;
325 /* add SA payload */
326 p = set_isakmp_payload(p, iph2->sa, ISAKMP_NPTYPE_NONCE);
328 /* add NONCE payload */
329 if (pfsgroup)
330 np = ISAKMP_NPTYPE_KE;
331 else if (idci || idcr)
332 np = ISAKMP_NPTYPE_ID;
333 else
334 np = natoa;
335 p = set_isakmp_payload(p, iph2->nonce, np);
337 /* add KE payload if need. */
338 np = (idci || idcr) ? ISAKMP_NPTYPE_ID : natoa;
339 if (pfsgroup)
340 p = set_isakmp_payload(p, iph2->dhpub, np);
342 /* IDci */
343 np = (idcr) ? ISAKMP_NPTYPE_ID : natoa;
344 if (idci)
345 p = set_isakmp_payload(p, iph2->id, np);
347 /* IDcr */
348 if (idcr)
349 p = set_isakmp_payload(p, iph2->id_p, natoa);
351 #ifdef ENABLE_NATT
352 /* NAT-OA */
353 if (natoa != ISAKMP_NPTYPE_NONE) {
354 p = set_isakmp_payload(p, nat_oai, natoa);
355 p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
357 #endif
359 /* generate HASH(1) */
360 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
361 if (hash == NULL)
362 goto end;
364 /* send isakmp payload */
365 iph2->sendbuf = quick_ir1mx(iph2, body, hash);
366 if (iph2->sendbuf == NULL)
367 goto end;
369 /* send the packet, add to the schedule to resend */
370 if (isakmp_ph2send(iph2) == -1)
371 goto end;
373 /* change status of isakmp status entry */
374 iph2->status = PHASE2ST_MSG1SENT;
376 error = 0;
378 end:
379 if (body != NULL)
380 vfree(body);
381 if (hash != NULL)
382 vfree(hash);
383 #ifdef ENABLE_NATT
384 if (nat_oai != NULL)
385 vfree(nat_oai);
386 if (nat_oar != NULL)
387 vfree(nat_oar);
388 #endif
390 return error;
394 * receive from responder
395 * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
398 quick_i2recv(iph2, msg0)
399 struct ph2handle *iph2;
400 vchar_t *msg0;
402 vchar_t *msg = NULL;
403 vchar_t *hbuf = NULL; /* for hash computing. */
404 vchar_t *pbuf = NULL; /* for payload parsing */
405 vchar_t *idci = NULL;
406 vchar_t *idcr = NULL;
407 struct isakmp_parse_t *pa;
408 struct isakmp *isakmp = (struct isakmp *)msg0->v;
409 struct isakmp_pl_hash *hash = NULL;
410 char *p;
411 int tlen;
412 int error = ISAKMP_INTERNAL_ERROR;
414 /* validity check */
415 if (iph2->status != PHASE2ST_MSG1SENT) {
416 plog(LLV_ERROR, LOCATION, NULL,
417 "status mismatched %d.\n", iph2->status);
418 goto end;
421 /* decrypt packet */
422 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
423 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
424 "Packet wasn't encrypted.\n");
425 goto end;
427 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
428 if (msg == NULL)
429 goto end;
431 /* create buffer for validating HASH(2) */
433 * ordering rule:
434 * 1. the first one must be HASH
435 * 2. the second one must be SA (added in isakmp-oakley-05!)
436 * 3. two IDs must be considered as IDci, then IDcr
438 pbuf = isakmp_parse(msg);
439 if (pbuf == NULL)
440 goto end;
441 pa = (struct isakmp_parse_t *)pbuf->v;
443 /* HASH payload is fixed postion */
444 if (pa->type != ISAKMP_NPTYPE_HASH) {
445 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
446 "received invalid next payload type %d, "
447 "expecting %d.\n",
448 pa->type, ISAKMP_NPTYPE_HASH);
449 goto end;
451 hash = (struct isakmp_pl_hash *)pa->ptr;
452 pa++;
455 * this restriction was introduced in isakmp-oakley-05.
456 * we do not check this for backward compatibility.
457 * TODO: command line/config file option to enable/disable this code
459 /* HASH payload is fixed postion */
460 if (pa->type != ISAKMP_NPTYPE_SA) {
461 plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
462 "received invalid next payload type %d, "
463 "expecting %d.\n",
464 pa->type, ISAKMP_NPTYPE_HASH);
467 /* allocate buffer for computing HASH(2) */
468 tlen = iph2->nonce->l
469 + ntohl(isakmp->len) - sizeof(*isakmp);
470 hbuf = vmalloc(tlen);
471 if (hbuf == NULL) {
472 plog(LLV_ERROR, LOCATION, NULL,
473 "failed to get hash buffer.\n");
474 goto end;
476 p = hbuf->v + iph2->nonce->l; /* retain the space for Ni_b */
479 * parse the payloads.
480 * copy non-HASH payloads into hbuf, so that we can validate HASH.
482 iph2->sa_ret = NULL;
483 tlen = 0; /* count payload length except of HASH payload. */
484 for (; pa->type; pa++) {
486 /* copy to buffer for HASH */
487 /* Don't modify the payload */
488 memcpy(p, pa->ptr, pa->len);
490 switch (pa->type) {
491 case ISAKMP_NPTYPE_SA:
492 if (iph2->sa_ret != NULL) {
493 plog(LLV_ERROR, LOCATION, NULL,
494 "Ignored, multiple SA "
495 "isn't supported.\n");
496 break;
498 if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0)
499 goto end;
500 break;
502 case ISAKMP_NPTYPE_NONCE:
503 if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
504 goto end;
505 break;
507 case ISAKMP_NPTYPE_KE:
508 if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
509 goto end;
510 break;
512 case ISAKMP_NPTYPE_ID:
513 if (idci == NULL) {
514 if (isakmp_p2ph(&idci, pa->ptr) < 0)
515 goto end;
516 } else if (idcr == NULL) {
517 if (isakmp_p2ph(&idcr, pa->ptr) < 0)
518 goto end;
519 } else {
520 goto end;
522 break;
524 case ISAKMP_NPTYPE_N:
525 ph2_recv_n(iph2, pa->ptr);
526 break;
528 #ifdef ENABLE_NATT
529 case ISAKMP_NPTYPE_NATOA_DRAFT:
530 case ISAKMP_NPTYPE_NATOA_RFC:
532 struct sockaddr_storage addr;
533 struct sockaddr *daddr;
534 u_int8_t prefix;
535 u_int16_t ul_proto;
536 vchar_t *vp = NULL;
538 if (isakmp_p2ph(&vp, pa->ptr) < 0)
539 goto end;
541 error = ipsecdoi_id2sockaddr(vp,
542 (struct sockaddr *) &addr,
543 &prefix, &ul_proto);
545 vfree(vp);
547 if (error)
548 goto end;
550 daddr = dupsaddr((struct sockaddr *) &addr);
551 if (daddr == NULL)
552 goto end;
554 if (iph2->natoa_src == NULL)
555 iph2->natoa_src = daddr;
556 else if (iph2->natoa_dst == NULL)
557 iph2->natoa_dst = daddr;
558 else {
559 racoon_free(daddr);
560 goto end;
563 break;
564 #endif
566 default:
567 /* don't send information, see ident_r1recv() */
568 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
569 "ignore the packet, "
570 "received unexpecting payload type %d.\n",
571 pa->type);
572 goto end;
575 p += pa->len;
577 /* compute true length of payload. */
578 tlen += pa->len;
581 /* payload existency check */
582 if (hash == NULL || iph2->sa_ret == NULL || iph2->nonce_p == NULL) {
583 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
584 "few isakmp message received.\n");
585 goto end;
588 /* identity check */
589 if (idci != NULL) {
590 struct sockaddr_storage proposed_addr, got_addr;
591 u_int8_t proposed_prefix, got_prefix;
592 u_int16_t proposed_ulproto, got_ulproto;
594 error = ipsecdoi_id2sockaddr(iph2->id,
595 (struct sockaddr *) &proposed_addr,
596 &proposed_prefix, &proposed_ulproto);
597 if (error)
598 goto end;
600 error = ipsecdoi_id2sockaddr(idci,
601 (struct sockaddr *) &got_addr,
602 &got_prefix, &got_ulproto);
603 if (error)
604 goto end;
606 if (proposed_prefix != got_prefix
607 || proposed_ulproto != got_ulproto) {
608 plog(LLV_DEBUG, LOCATION, NULL,
609 "IDci prefix/ulproto does not match proposal.\n");
610 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
611 goto end;
613 #ifdef ENABLE_NATT
614 set_port(iph2->natoa_src,
615 extract_port((struct sockaddr *) &proposed_addr));
616 #endif
618 if (cmpsaddr((struct sockaddr *) &proposed_addr,
619 (struct sockaddr *) &got_addr) == 0) {
620 plog(LLV_DEBUG, LOCATION, NULL,
621 "IDci matches proposal.\n");
622 #ifdef ENABLE_NATT
623 } else if (iph2->natoa_src != NULL
624 && cmpsaddr(iph2->natoa_src,
625 (struct sockaddr *) &got_addr) == 0) {
626 plog(LLV_DEBUG, LOCATION, NULL,
627 "IDci matches NAT-OAi.\n");
628 #endif
629 } else {
630 plog(LLV_ERROR, LOCATION, NULL,
631 "mismatched IDci was returned.\n");
632 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
633 goto end;
636 if (idcr != NULL) {
637 struct sockaddr_storage proposed_addr, got_addr;
638 u_int8_t proposed_prefix, got_prefix;
639 u_int16_t proposed_ulproto, got_ulproto;
641 error = ipsecdoi_id2sockaddr(iph2->id_p,
642 (struct sockaddr *) &proposed_addr,
643 &proposed_prefix, &proposed_ulproto);
644 if (error)
645 goto end;
647 error = ipsecdoi_id2sockaddr(idcr,
648 (struct sockaddr *) &got_addr,
649 &got_prefix, &got_ulproto);
650 if (error)
651 goto end;
653 if (proposed_prefix != got_prefix
654 || proposed_ulproto != got_ulproto) {
655 plog(LLV_DEBUG, LOCATION, NULL,
656 "IDcr prefix/ulproto does not match proposal.\n");
657 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
658 goto end;
661 #ifdef ENABLE_NATT
662 set_port(iph2->natoa_dst,
663 extract_port((struct sockaddr *) &proposed_addr));
664 #endif
666 if (cmpsaddr((struct sockaddr *) &proposed_addr,
667 (struct sockaddr *) &got_addr) == 0) {
668 plog(LLV_DEBUG, LOCATION, NULL,
669 "IDcr matches proposal.\n");
670 #ifdef ENABLE_NATT
671 } else if (iph2->natoa_dst != NULL
672 && cmpsaddr(iph2->natoa_dst,
673 (struct sockaddr *) &got_addr) == 0) {
674 plog(LLV_DEBUG, LOCATION, NULL,
675 "IDcr matches NAT-OAr.\n");
676 #endif
677 } else {
678 plog(LLV_ERROR, LOCATION, NULL,
679 "mismatched IDcr was returned.\n");
680 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
681 goto end;
685 /* Fixed buffer for calculating HASH */
686 memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
687 plog(LLV_DEBUG, LOCATION, NULL,
688 "HASH allocated:hbuf->l=%zu actual:tlen=%zu\n",
689 hbuf->l, tlen + iph2->nonce->l);
690 /* adjust buffer length for HASH */
691 hbuf->l = iph2->nonce->l + tlen;
693 /* validate HASH(2) */
695 char *r_hash;
696 vchar_t *my_hash = NULL;
697 int result;
699 r_hash = (char *)hash + sizeof(*hash);
701 plog(LLV_DEBUG, LOCATION, NULL, "HASH(2) received:");
702 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
704 my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
705 if (my_hash == NULL)
706 goto end;
708 result = memcmp(my_hash->v, r_hash, my_hash->l);
709 vfree(my_hash);
711 if (result) {
712 plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
713 "HASH(2) mismatch.\n");
714 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
715 goto end;
719 /* validity check SA payload sent from responder */
720 if (ipsecdoi_checkph2proposal(iph2) < 0) {
721 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
722 goto end;
725 /* change status of isakmp status entry */
726 iph2->status = PHASE2ST_STATUS6;
728 error = 0;
730 end:
731 if (hbuf)
732 vfree(hbuf);
733 if (pbuf)
734 vfree(pbuf);
735 if (msg)
736 vfree(msg);
737 if (idci)
738 vfree(idci);
739 if (idcr)
740 vfree(idcr);
742 if (error) {
743 VPTRINIT(iph2->sa_ret);
744 VPTRINIT(iph2->nonce_p);
745 VPTRINIT(iph2->dhpub_p);
746 VPTRINIT(iph2->id);
747 VPTRINIT(iph2->id_p);
748 #ifdef ENABLE_NATT
749 if (iph2->natoa_src) {
750 racoon_free(iph2->natoa_src);
751 iph2->natoa_src = NULL;
753 if (iph2->natoa_dst) {
754 racoon_free(iph2->natoa_dst);
755 iph2->natoa_dst = NULL;
757 #endif
760 return error;
764 * send to responder
765 * HDR*, HASH(3)
768 quick_i2send(iph2, msg0)
769 struct ph2handle *iph2;
770 vchar_t *msg0;
772 vchar_t *msg = NULL;
773 vchar_t *buf = NULL;
774 vchar_t *hash = NULL;
775 char *p = NULL;
776 int tlen;
777 int error = ISAKMP_INTERNAL_ERROR;
779 /* validity check */
780 if (iph2->status != PHASE2ST_STATUS6) {
781 plog(LLV_ERROR, LOCATION, NULL,
782 "status mismatched %d.\n", iph2->status);
783 goto end;
786 /* generate HASH(3) */
788 vchar_t *tmp = NULL;
790 plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) generate\n");
792 tmp = vmalloc(iph2->nonce->l + iph2->nonce_p->l);
793 if (tmp == NULL) {
794 plog(LLV_ERROR, LOCATION, NULL,
795 "failed to get hash buffer.\n");
796 goto end;
798 memcpy(tmp->v, iph2->nonce->v, iph2->nonce->l);
799 memcpy(tmp->v + iph2->nonce->l, iph2->nonce_p->v, iph2->nonce_p->l);
801 hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
802 vfree(tmp);
804 if (hash == NULL)
805 goto end;
808 /* create buffer for isakmp payload */
809 tlen = sizeof(struct isakmp)
810 + sizeof(struct isakmp_gen) + hash->l;
811 buf = vmalloc(tlen);
812 if (buf == NULL) {
813 plog(LLV_ERROR, LOCATION, NULL,
814 "failed to get buffer to send.\n");
815 goto end;
818 /* create isakmp header */
819 p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
820 if (p == NULL)
821 goto end;
823 /* add HASH(3) payload */
824 p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_NONE);
826 #ifdef HAVE_PRINT_ISAKMP_C
827 isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
828 #endif
830 /* encoding */
831 iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
832 if (iph2->sendbuf == NULL)
833 goto end;
835 /* if there is commit bit, need resending */
836 if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
837 /* send the packet, add to the schedule to resend */
838 if (isakmp_ph2send(iph2) == -1)
839 goto end;
840 } else {
841 /* send the packet */
842 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
843 goto end;
846 /* the sending message is added to the received-list. */
847 if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local,
848 iph2->sendbuf, msg0) == -1) {
849 plog(LLV_ERROR , LOCATION, NULL,
850 "failed to add a response packet to the tree.\n");
851 goto end;
854 /* compute both of KEYMATs */
855 if (oakley_compute_keymat(iph2, INITIATOR) < 0)
856 goto end;
858 iph2->status = PHASE2ST_ADDSA;
860 /* don't anything if local test mode. */
861 if (f_local) {
862 error = 0;
863 goto end;
866 /* if there is commit bit don't set up SA now. */
867 if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
868 iph2->status = PHASE2ST_COMMIT;
869 error = 0;
870 goto end;
873 /* Do UPDATE for initiator */
874 plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
875 if (pk_sendupdate(iph2) < 0) {
876 plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
877 goto end;
879 plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
881 /* Do ADD for responder */
882 if (pk_sendadd(iph2) < 0) {
883 plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
884 goto end;
886 plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
888 error = 0;
890 end:
891 if (buf != NULL)
892 vfree(buf);
893 if (msg != NULL)
894 vfree(msg);
895 if (hash != NULL)
896 vfree(hash);
898 return error;
902 * receive from responder
903 * HDR#*, HASH(4), notify
906 quick_i3recv(iph2, msg0)
907 struct ph2handle *iph2;
908 vchar_t *msg0;
910 vchar_t *msg = NULL;
911 vchar_t *pbuf = NULL; /* for payload parsing */
912 struct isakmp_parse_t *pa;
913 struct isakmp_pl_hash *hash = NULL;
914 vchar_t *notify = NULL;
915 int error = ISAKMP_INTERNAL_ERROR;
917 /* validity check */
918 if (iph2->status != PHASE2ST_COMMIT) {
919 plog(LLV_ERROR, LOCATION, NULL,
920 "status mismatched %d.\n", iph2->status);
921 goto end;
924 /* decrypt packet */
925 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
926 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
927 "Packet wasn't encrypted.\n");
928 goto end;
930 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
931 if (msg == NULL)
932 goto end;
934 /* validate the type of next payload */
935 pbuf = isakmp_parse(msg);
936 if (pbuf == NULL)
937 goto end;
939 for (pa = (struct isakmp_parse_t *)pbuf->v;
940 pa->type != ISAKMP_NPTYPE_NONE;
941 pa++) {
943 switch (pa->type) {
944 case ISAKMP_NPTYPE_HASH:
945 hash = (struct isakmp_pl_hash *)pa->ptr;
946 break;
947 case ISAKMP_NPTYPE_N:
948 if (notify != NULL) {
949 plog(LLV_WARNING, LOCATION, NULL,
950 "Ignoring multiples notifications\n");
951 break;
953 ph2_recv_n(iph2, pa->ptr);
954 notify = vmalloc(pa->len);
955 if (notify == NULL) {
956 plog(LLV_ERROR, LOCATION, NULL,
957 "failed to get notify buffer.\n");
958 goto end;
960 memcpy(notify->v, pa->ptr, notify->l);
961 break;
962 default:
963 /* don't send information, see ident_r1recv() */
964 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
965 "ignore the packet, "
966 "received unexpecting payload type %d.\n",
967 pa->type);
968 goto end;
972 /* payload existency check */
973 if (hash == NULL) {
974 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
975 "few isakmp message received.\n");
976 goto end;
979 /* validate HASH(4) */
981 char *r_hash;
982 vchar_t *my_hash = NULL;
983 vchar_t *tmp = NULL;
984 int result;
986 r_hash = (char *)hash + sizeof(*hash);
988 plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) validate:");
989 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
991 my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
992 vfree(tmp);
993 if (my_hash == NULL)
994 goto end;
996 result = memcmp(my_hash->v, r_hash, my_hash->l);
997 vfree(my_hash);
999 if (result) {
1000 plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
1001 "HASH(4) mismatch.\n");
1002 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1003 goto end;
1007 iph2->status = PHASE2ST_ADDSA;
1008 iph2->flags ^= ISAKMP_FLAG_C; /* reset bit */
1010 /* don't anything if local test mode. */
1011 if (f_local) {
1012 error = 0;
1013 goto end;
1016 /* Do UPDATE for initiator */
1017 plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
1018 if (pk_sendupdate(iph2) < 0) {
1019 plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
1020 goto end;
1022 plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
1024 /* Do ADD for responder */
1025 if (pk_sendadd(iph2) < 0) {
1026 plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
1027 goto end;
1029 plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
1031 error = 0;
1033 end:
1034 if (msg != NULL)
1035 vfree(msg);
1036 if (pbuf != NULL)
1037 vfree(pbuf);
1038 if (notify != NULL)
1039 vfree(notify);
1041 return error;
1045 * receive from initiator
1046 * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
1049 quick_r1recv(iph2, msg0)
1050 struct ph2handle *iph2;
1051 vchar_t *msg0;
1053 vchar_t *msg = NULL;
1054 vchar_t *hbuf = NULL; /* for hash computing. */
1055 vchar_t *pbuf = NULL; /* for payload parsing */
1056 struct isakmp_parse_t *pa;
1057 struct isakmp *isakmp = (struct isakmp *)msg0->v;
1058 struct isakmp_pl_hash *hash = NULL;
1059 char *p;
1060 int tlen;
1061 int f_id_order; /* for ID payload detection */
1062 int error = ISAKMP_INTERNAL_ERROR;
1064 /* validity check */
1065 if (iph2->status != PHASE2ST_START) {
1066 plog(LLV_ERROR, LOCATION, NULL,
1067 "status mismatched %d.\n", iph2->status);
1068 goto end;
1071 /* decrypting */
1072 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1073 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1074 "Packet wasn't encrypted.\n");
1075 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1076 goto end;
1078 /* decrypt packet */
1079 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
1080 if (msg == NULL)
1081 goto end;
1083 /* create buffer for using to validate HASH(1) */
1085 * ordering rule:
1086 * 1. the first one must be HASH
1087 * 2. the second one must be SA (added in isakmp-oakley-05!)
1088 * 3. two IDs must be considered as IDci, then IDcr
1090 pbuf = isakmp_parse(msg);
1091 if (pbuf == NULL)
1092 goto end;
1093 pa = (struct isakmp_parse_t *)pbuf->v;
1095 /* HASH payload is fixed postion */
1096 if (pa->type != ISAKMP_NPTYPE_HASH) {
1097 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1098 "received invalid next payload type %d, "
1099 "expecting %d.\n",
1100 pa->type, ISAKMP_NPTYPE_HASH);
1101 error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
1102 goto end;
1104 hash = (struct isakmp_pl_hash *)pa->ptr;
1105 pa++;
1108 * this restriction was introduced in isakmp-oakley-05.
1109 * we do not check this for backward compatibility.
1110 * TODO: command line/config file option to enable/disable this code
1112 /* HASH payload is fixed postion */
1113 if (pa->type != ISAKMP_NPTYPE_SA) {
1114 plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
1115 "received invalid next payload type %d, "
1116 "expecting %d.\n",
1117 pa->type, ISAKMP_NPTYPE_SA);
1118 error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
1121 /* allocate buffer for computing HASH(1) */
1122 tlen = ntohl(isakmp->len) - sizeof(*isakmp);
1123 hbuf = vmalloc(tlen);
1124 if (hbuf == NULL) {
1125 plog(LLV_ERROR, LOCATION, NULL,
1126 "failed to get hash buffer.\n");
1127 goto end;
1129 p = hbuf->v;
1132 * parse the payloads.
1133 * copy non-HASH payloads into hbuf, so that we can validate HASH.
1135 iph2->sa = NULL; /* we don't support multi SAs. */
1136 iph2->nonce_p = NULL;
1137 iph2->dhpub_p = NULL;
1138 iph2->id_p = NULL;
1139 iph2->id = NULL;
1140 tlen = 0; /* count payload length except of HASH payload. */
1143 * IDi2 MUST be immediatelly followed by IDr2. We allowed the
1144 * illegal case, but logged. First ID payload is to be IDi2.
1145 * And next ID payload is to be IDr2.
1147 f_id_order = 0;
1149 for (; pa->type; pa++) {
1151 /* copy to buffer for HASH */
1152 /* Don't modify the payload */
1153 memcpy(p, pa->ptr, pa->len);
1155 if (pa->type != ISAKMP_NPTYPE_ID)
1156 f_id_order = 0;
1158 switch (pa->type) {
1159 case ISAKMP_NPTYPE_SA:
1160 if (iph2->sa != NULL) {
1161 plog(LLV_ERROR, LOCATION, NULL,
1162 "Multi SAs isn't supported.\n");
1163 goto end;
1165 if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0)
1166 goto end;
1167 break;
1169 case ISAKMP_NPTYPE_NONCE:
1170 if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
1171 goto end;
1172 break;
1174 case ISAKMP_NPTYPE_KE:
1175 if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
1176 goto end;
1177 break;
1179 case ISAKMP_NPTYPE_ID:
1180 if (iph2->id_p == NULL) {
1181 /* for IDci */
1182 f_id_order++;
1184 if (isakmp_p2ph(&iph2->id_p, pa->ptr) < 0)
1185 goto end;
1187 } else if (iph2->id == NULL) {
1188 /* for IDcr */
1189 if (f_id_order == 0) {
1190 plog(LLV_ERROR, LOCATION, NULL,
1191 "IDr2 payload is not "
1192 "immediatelly followed "
1193 "by IDi2. We allowed.\n");
1194 /* XXX we allowed in this case. */
1197 if (isakmp_p2ph(&iph2->id, pa->ptr) < 0)
1198 goto end;
1199 } else {
1200 plog(LLV_ERROR, LOCATION, NULL,
1201 "received too many ID payloads.\n");
1202 plogdump(LLV_ERROR, iph2->id->v, iph2->id->l);
1203 error = ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1204 goto end;
1206 break;
1208 case ISAKMP_NPTYPE_N:
1209 ph2_recv_n(iph2, pa->ptr);
1210 break;
1212 #ifdef ENABLE_NATT
1213 case ISAKMP_NPTYPE_NATOA_DRAFT:
1214 case ISAKMP_NPTYPE_NATOA_RFC:
1216 struct sockaddr_storage addr;
1217 struct sockaddr *daddr;
1218 u_int8_t prefix;
1219 u_int16_t ul_proto;
1220 vchar_t *vp = NULL;
1222 if (isakmp_p2ph(&vp, pa->ptr) < 0)
1223 goto end;
1225 error = ipsecdoi_id2sockaddr(vp,
1226 (struct sockaddr *) &addr,
1227 &prefix, &ul_proto);
1229 vfree(vp);
1231 if (error)
1232 goto end;
1234 daddr = dupsaddr((struct sockaddr *) &addr);
1235 if (daddr == NULL)
1236 goto end;
1238 if (iph2->natoa_dst == NULL)
1239 iph2->natoa_dst = daddr;
1240 else if (iph2->natoa_src == NULL)
1241 iph2->natoa_src = daddr;
1242 else {
1243 racoon_free(daddr);
1244 goto end;
1247 break;
1248 #endif
1250 default:
1251 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1252 "ignore the packet, "
1253 "received unexpecting payload type %d.\n",
1254 pa->type);
1255 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1256 goto end;
1259 p += pa->len;
1261 /* compute true length of payload. */
1262 tlen += pa->len;
1265 /* payload existency check */
1266 if (hash == NULL || iph2->sa == NULL || iph2->nonce_p == NULL) {
1267 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1268 "few isakmp message received.\n");
1269 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1270 goto end;
1273 if (iph2->id_p) {
1274 plog(LLV_DEBUG, LOCATION, NULL, "received IDci2:");
1275 plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
1277 if (iph2->id) {
1278 plog(LLV_DEBUG, LOCATION, NULL, "received IDcr2:");
1279 plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
1282 /* adjust buffer length for HASH */
1283 hbuf->l = tlen;
1285 /* validate HASH(1) */
1287 char *r_hash;
1288 vchar_t *my_hash = NULL;
1289 int result;
1291 r_hash = (caddr_t)hash + sizeof(*hash);
1293 plog(LLV_DEBUG, LOCATION, NULL, "HASH(1) validate:");
1294 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
1296 my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
1297 if (my_hash == NULL)
1298 goto end;
1300 result = memcmp(my_hash->v, r_hash, my_hash->l);
1301 vfree(my_hash);
1303 if (result) {
1304 plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
1305 "HASH(1) mismatch.\n");
1306 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1307 goto end;
1311 /* get sainfo */
1312 error = get_sainfo_r(iph2);
1313 if (error) {
1314 plog(LLV_ERROR, LOCATION, NULL,
1315 "failed to get sainfo.\n");
1316 goto end;
1320 /* check the existence of ID payload and create responder's proposal */
1321 error = get_proposal_r(iph2);
1322 switch (error) {
1323 case -2:
1324 /* generate a policy template from peer's proposal */
1325 if (set_proposal_from_proposal(iph2)) {
1326 plog(LLV_ERROR, LOCATION, NULL,
1327 "failed to generate a proposal template "
1328 "from client's proposal.\n");
1329 error = ISAKMP_INTERNAL_ERROR;
1330 goto end;
1332 /*FALLTHROUGH*/
1333 case 0:
1334 /* select single proposal or reject it. */
1335 if (ipsecdoi_selectph2proposal(iph2) < 0) {
1336 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1337 goto end;
1339 break;
1340 default:
1341 plog(LLV_ERROR, LOCATION, NULL,
1342 "failed to get proposal for responder.\n");
1343 goto end;
1346 /* check KE and attribute of PFS */
1347 if (iph2->dhpub_p != NULL && iph2->approval->pfs_group == 0) {
1348 plog(LLV_ERROR, LOCATION, NULL,
1349 "no PFS is specified, but peer sends KE.\n");
1350 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1351 goto end;
1353 if (iph2->dhpub_p == NULL && iph2->approval->pfs_group != 0) {
1354 plog(LLV_ERROR, LOCATION, NULL,
1355 "PFS is specified, but peer doesn't sends KE.\n");
1356 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1357 goto end;
1361 * save the packet from the initiator in order to resend the
1362 * responder's first packet against this packet.
1364 iph2->msg1 = vdup(msg0);
1366 /* change status of isakmp status entry */
1367 iph2->status = PHASE2ST_STATUS2;
1369 error = 0;
1371 end:
1372 if (hbuf)
1373 vfree(hbuf);
1374 if (msg)
1375 vfree(msg);
1376 if (pbuf)
1377 vfree(pbuf);
1379 if (error) {
1380 VPTRINIT(iph2->sa);
1381 VPTRINIT(iph2->nonce_p);
1382 VPTRINIT(iph2->dhpub_p);
1383 VPTRINIT(iph2->id);
1384 VPTRINIT(iph2->id_p);
1385 #ifdef ENABLE_NATT
1386 if (iph2->natoa_src) {
1387 racoon_free(iph2->natoa_src);
1388 iph2->natoa_src = NULL;
1390 if (iph2->natoa_dst) {
1391 racoon_free(iph2->natoa_dst);
1392 iph2->natoa_dst = NULL;
1394 #endif
1397 return error;
1401 * call pfkey_getspi.
1404 quick_r1prep(iph2, msg)
1405 struct ph2handle *iph2;
1406 vchar_t *msg;
1408 int error = ISAKMP_INTERNAL_ERROR;
1410 /* validity check */
1411 if (iph2->status != PHASE2ST_STATUS2) {
1412 plog(LLV_ERROR, LOCATION, NULL,
1413 "status mismatched %d.\n", iph2->status);
1414 goto end;
1417 iph2->status = PHASE2ST_GETSPISENT;
1419 /* send getspi message */
1420 if (pk_sendgetspi(iph2) < 0)
1421 goto end;
1423 plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
1425 sched_schedule(&iph2->sce, lcconf->wait_ph2complete,
1426 quick_timeover_stub);
1428 error = 0;
1430 end:
1431 return error;
1435 * send to initiator
1436 * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
1439 quick_r2send(iph2, msg)
1440 struct ph2handle *iph2;
1441 vchar_t *msg;
1443 vchar_t *body = NULL;
1444 vchar_t *hash = NULL;
1445 struct isakmp_gen *gen;
1446 char *p;
1447 int tlen;
1448 int error = ISAKMP_INTERNAL_ERROR;
1449 int natoa = ISAKMP_NPTYPE_NONE;
1450 int pfsgroup;
1451 u_int8_t *np_p = NULL;
1452 #ifdef ENABLE_NATT
1453 vchar_t *nat_oai = NULL;
1454 vchar_t *nat_oar = NULL;
1455 #endif
1457 /* validity check */
1458 if (msg != NULL) {
1459 plog(LLV_ERROR, LOCATION, NULL,
1460 "msg has to be NULL in this function.\n");
1461 goto end;
1463 if (iph2->status != PHASE2ST_GETSPIDONE) {
1464 plog(LLV_ERROR, LOCATION, NULL,
1465 "status mismatched %d.\n", iph2->status);
1466 goto end;
1469 /* update responders SPI */
1470 if (ipsecdoi_updatespi(iph2) < 0) {
1471 plog(LLV_ERROR, LOCATION, NULL, "failed to update spi.\n");
1472 goto end;
1475 /* generate NONCE value */
1476 iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
1477 if (iph2->nonce == NULL)
1478 goto end;
1480 /* generate KE value if need */
1481 pfsgroup = iph2->approval->pfs_group;
1482 if (iph2->dhpub_p != NULL && pfsgroup != 0) {
1483 /* DH group settting if PFS is required. */
1484 if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
1485 plog(LLV_ERROR, LOCATION, NULL,
1486 "failed to set DH value.\n");
1487 goto end;
1489 /* generate DH public value */
1490 if (oakley_dh_generate(iph2->pfsgrp,
1491 &iph2->dhpub, &iph2->dhpriv) < 0) {
1492 goto end;
1496 #ifdef ENABLE_NATT
1498 * RFC3947 5.2. if we chose UDP-Encapsulated-Transport
1499 * we should send NAT-OA
1501 if (ipsecdoi_transportmode(iph2->proposal)
1502 && (iph2->ph1->natt_flags & NAT_DETECTED)) {
1503 natoa = iph2->ph1->natt_options->payload_nat_oa;
1505 nat_oai = ipsecdoi_sockaddr2id(iph2->dst,
1506 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
1507 nat_oar = ipsecdoi_sockaddr2id(iph2->src,
1508 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
1510 if (nat_oai == NULL || nat_oar == NULL) {
1511 plog(LLV_ERROR, LOCATION, NULL,
1512 "failed to generate NAT-OA payload.\n");
1513 goto end;
1516 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n");
1517 plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l);
1518 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n");
1519 plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l);
1521 #endif
1523 /* create SA;NONCE payload, and KE and ID if need */
1524 tlen = sizeof(*gen) + iph2->sa_ret->l
1525 + sizeof(*gen) + iph2->nonce->l;
1526 if (iph2->dhpub_p != NULL && pfsgroup != 0)
1527 tlen += (sizeof(*gen) + iph2->dhpub->l);
1528 if (iph2->id_p != NULL)
1529 tlen += (sizeof(*gen) + iph2->id_p->l
1530 + sizeof(*gen) + iph2->id->l);
1531 #ifdef ENABLE_NATT
1532 if (natoa != ISAKMP_NPTYPE_NONE)
1533 tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
1534 #endif
1536 body = vmalloc(tlen);
1537 if (body == NULL) {
1538 plog(LLV_ERROR, LOCATION, NULL,
1539 "failed to get buffer to send.\n");
1540 goto end;
1542 p = body->v;
1544 /* make SA payload */
1545 p = set_isakmp_payload(body->v, iph2->sa_ret, ISAKMP_NPTYPE_NONCE);
1547 /* add NONCE payload */
1548 np_p = &((struct isakmp_gen *)p)->np; /* XXX */
1549 p = set_isakmp_payload(p, iph2->nonce,
1550 (iph2->dhpub_p != NULL && pfsgroup != 0)
1551 ? ISAKMP_NPTYPE_KE
1552 : (iph2->id_p != NULL
1553 ? ISAKMP_NPTYPE_ID
1554 : natoa));
1556 /* add KE payload if need. */
1557 if (iph2->dhpub_p != NULL && pfsgroup != 0) {
1558 np_p = &((struct isakmp_gen *)p)->np; /* XXX */
1559 p = set_isakmp_payload(p, iph2->dhpub,
1560 (iph2->id_p == NULL)
1561 ? natoa
1562 : ISAKMP_NPTYPE_ID);
1565 /* add ID payloads received. */
1566 if (iph2->id_p != NULL) {
1567 /* IDci */
1568 p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
1569 /* IDcr */
1570 np_p = &((struct isakmp_gen *)p)->np; /* XXX */
1571 p = set_isakmp_payload(p, iph2->id, natoa);
1574 #ifdef ENABLE_NATT
1575 /* NAT-OA */
1576 if (natoa != ISAKMP_NPTYPE_NONE) {
1577 p = set_isakmp_payload(p, nat_oai, natoa);
1578 p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
1580 #endif
1582 /* add a RESPONDER-LIFETIME notify payload if needed */
1584 vchar_t *data = NULL;
1585 struct saprop *pp = iph2->approval;
1586 struct saproto *pr;
1588 if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_SEC) {
1589 u_int32_t v = htonl((u_int32_t)pp->lifetime);
1590 data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
1591 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
1592 if (!data)
1593 goto end;
1594 data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
1595 (caddr_t)&v, sizeof(v));
1596 if (!data)
1597 goto end;
1599 if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_KB) {
1600 u_int32_t v = htonl((u_int32_t)pp->lifebyte);
1601 data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
1602 IPSECDOI_ATTR_SA_LD_TYPE_KB);
1603 if (!data)
1604 goto end;
1605 data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
1606 (caddr_t)&v, sizeof(v));
1607 if (!data)
1608 goto end;
1612 * XXX Is there only single RESPONDER-LIFETIME payload in a IKE message
1613 * in the case of SA bundle ?
1615 if (data) {
1616 for (pr = pp->head; pr; pr = pr->next) {
1617 body = isakmp_add_pl_n(body, &np_p,
1618 ISAKMP_NTYPE_RESPONDER_LIFETIME, pr, data);
1619 if (!body) {
1620 vfree(data);
1621 return error; /* XXX */
1624 vfree(data);
1628 /* generate HASH(2) */
1630 vchar_t *tmp;
1632 tmp = vmalloc(iph2->nonce_p->l + body->l);
1633 if (tmp == NULL) {
1634 plog(LLV_ERROR, LOCATION, NULL,
1635 "failed to get hash buffer.\n");
1636 goto end;
1638 memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
1639 memcpy(tmp->v + iph2->nonce_p->l, body->v, body->l);
1641 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, tmp);
1642 vfree(tmp);
1644 if (hash == NULL)
1645 goto end;
1648 /* send isakmp payload */
1649 iph2->sendbuf = quick_ir1mx(iph2, body, hash);
1650 if (iph2->sendbuf == NULL)
1651 goto end;
1653 /* send the packet, add to the schedule to resend */
1654 if (isakmp_ph2send(iph2) == -1)
1655 goto end;
1657 /* the sending message is added to the received-list. */
1658 if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, iph2->msg1) == -1) {
1659 plog(LLV_ERROR , LOCATION, NULL,
1660 "failed to add a response packet to the tree.\n");
1661 goto end;
1664 /* change status of isakmp status entry */
1665 iph2->status = PHASE2ST_MSG1SENT;
1667 error = 0;
1669 end:
1670 if (body != NULL)
1671 vfree(body);
1672 if (hash != NULL)
1673 vfree(hash);
1674 #ifdef ENABLE_NATT
1675 if (nat_oai != NULL)
1676 vfree(nat_oai);
1677 if (nat_oar != NULL)
1678 vfree(nat_oar);
1679 #endif
1681 return error;
1685 * receive from initiator
1686 * HDR*, HASH(3)
1690 quick_r3recv(iph2, msg0)
1691 struct ph2handle *iph2;
1692 vchar_t *msg0;
1694 vchar_t *msg = NULL;
1695 vchar_t *pbuf = NULL; /* for payload parsing */
1696 struct isakmp_parse_t *pa;
1697 struct isakmp_pl_hash *hash = NULL;
1698 int error = ISAKMP_INTERNAL_ERROR;
1700 /* validity check */
1701 if (iph2->status != PHASE2ST_MSG1SENT) {
1702 plog(LLV_ERROR, LOCATION, NULL,
1703 "status mismatched %d.\n", iph2->status);
1704 goto end;
1707 /* decrypt packet */
1708 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1709 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1710 "Packet wasn't encrypted.\n");
1711 goto end;
1713 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
1714 if (msg == NULL)
1715 goto end;
1717 /* validate the type of next payload */
1718 pbuf = isakmp_parse(msg);
1719 if (pbuf == NULL)
1720 goto end;
1722 for (pa = (struct isakmp_parse_t *)pbuf->v;
1723 pa->type != ISAKMP_NPTYPE_NONE;
1724 pa++) {
1726 switch (pa->type) {
1727 case ISAKMP_NPTYPE_HASH:
1728 hash = (struct isakmp_pl_hash *)pa->ptr;
1729 break;
1730 case ISAKMP_NPTYPE_N:
1731 ph2_recv_n(iph2, pa->ptr);
1732 break;
1733 default:
1734 /* don't send information, see ident_r1recv() */
1735 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1736 "ignore the packet, "
1737 "received unexpecting payload type %d.\n",
1738 pa->type);
1739 goto end;
1743 /* payload existency check */
1744 if (hash == NULL) {
1745 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1746 "few isakmp message received.\n");
1747 goto end;
1750 /* validate HASH(3) */
1751 /* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
1753 char *r_hash;
1754 vchar_t *my_hash = NULL;
1755 vchar_t *tmp = NULL;
1756 int result;
1758 r_hash = (char *)hash + sizeof(*hash);
1760 plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) validate:");
1761 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
1763 tmp = vmalloc(iph2->nonce_p->l + iph2->nonce->l);
1764 if (tmp == NULL) {
1765 plog(LLV_ERROR, LOCATION, NULL,
1766 "failed to get hash buffer.\n");
1767 goto end;
1769 memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
1770 memcpy(tmp->v + iph2->nonce_p->l, iph2->nonce->v, iph2->nonce->l);
1772 my_hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
1773 vfree(tmp);
1774 if (my_hash == NULL)
1775 goto end;
1777 result = memcmp(my_hash->v, r_hash, my_hash->l);
1778 vfree(my_hash);
1780 if (result) {
1781 plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1782 "HASH(3) mismatch.\n");
1783 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1784 goto end;
1788 /* if there is commit bit, don't set up SA now. */
1789 if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
1790 iph2->status = PHASE2ST_COMMIT;
1791 } else
1792 iph2->status = PHASE2ST_STATUS6;
1794 error = 0;
1796 end:
1797 if (pbuf != NULL)
1798 vfree(pbuf);
1799 if (msg != NULL)
1800 vfree(msg);
1802 return error;
1806 * send to initiator
1807 * HDR#*, HASH(4), notify
1810 quick_r3send(iph2, msg0)
1811 struct ph2handle *iph2;
1812 vchar_t *msg0;
1814 vchar_t *buf = NULL;
1815 vchar_t *myhash = NULL;
1816 struct isakmp_pl_n *n;
1817 vchar_t *notify = NULL;
1818 char *p;
1819 int tlen;
1820 int error = ISAKMP_INTERNAL_ERROR;
1822 /* validity check */
1823 if (iph2->status != PHASE2ST_COMMIT) {
1824 plog(LLV_ERROR, LOCATION, NULL,
1825 "status mismatched %d.\n", iph2->status);
1826 goto end;
1829 /* generate HASH(4) */
1830 /* XXX What can I do in the case of multiple different SA */
1831 plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) generate\n");
1833 /* XXX What should I do if there are multiple SAs ? */
1834 tlen = sizeof(struct isakmp_pl_n) + iph2->approval->head->spisize;
1835 notify = vmalloc(tlen);
1836 if (notify == NULL) {
1837 plog(LLV_ERROR, LOCATION, NULL,
1838 "failed to get notify buffer.\n");
1839 goto end;
1841 n = (struct isakmp_pl_n *)notify->v;
1842 n->h.np = ISAKMP_NPTYPE_NONE;
1843 n->h.len = htons(tlen);
1844 n->doi = htonl(IPSEC_DOI);
1845 n->proto_id = iph2->approval->head->proto_id;
1846 n->spi_size = sizeof(iph2->approval->head->spisize);
1847 n->type = htons(ISAKMP_NTYPE_CONNECTED);
1848 memcpy(n + 1, &iph2->approval->head->spi, iph2->approval->head->spisize);
1850 myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
1851 if (myhash == NULL)
1852 goto end;
1854 /* create buffer for isakmp payload */
1855 tlen = sizeof(struct isakmp)
1856 + sizeof(struct isakmp_gen) + myhash->l
1857 + notify->l;
1858 buf = vmalloc(tlen);
1859 if (buf == NULL) {
1860 plog(LLV_ERROR, LOCATION, NULL,
1861 "failed to get buffer to send.\n");
1862 goto end;
1865 /* create isakmp header */
1866 p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
1867 if (p == NULL)
1868 goto end;
1870 /* add HASH(4) payload */
1871 p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N);
1873 /* add notify payload */
1874 memcpy(p, notify->v, notify->l);
1876 #ifdef HAVE_PRINT_ISAKMP_C
1877 isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
1878 #endif
1880 /* encoding */
1881 iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
1882 if (iph2->sendbuf == NULL)
1883 goto end;
1885 /* send the packet */
1886 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
1887 goto end;
1889 /* the sending message is added to the received-list. */
1890 if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, msg0) == -1) {
1891 plog(LLV_ERROR , LOCATION, NULL,
1892 "failed to add a response packet to the tree.\n");
1893 goto end;
1896 iph2->status = PHASE2ST_COMMIT;
1898 error = 0;
1900 end:
1901 if (buf != NULL)
1902 vfree(buf);
1903 if (myhash != NULL)
1904 vfree(myhash);
1905 if (notify != NULL)
1906 vfree(notify);
1908 return error;
1912 tunnel_mode_prop(p)
1913 struct saprop *p;
1915 struct saproto *pr;
1917 for (pr = p->head; pr; pr = pr->next)
1918 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL)
1919 return 1;
1920 return 0;
1924 * set SA to kernel.
1927 quick_r3prep(iph2, msg0)
1928 struct ph2handle *iph2;
1929 vchar_t *msg0;
1931 int error = ISAKMP_INTERNAL_ERROR;
1933 /* validity check */
1934 if (iph2->status != PHASE2ST_STATUS6) {
1935 plog(LLV_ERROR, LOCATION, NULL,
1936 "status mismatched %d.\n", iph2->status);
1937 goto end;
1940 /* compute both of KEYMATs */
1941 if (oakley_compute_keymat(iph2, RESPONDER) < 0)
1942 goto end;
1944 iph2->status = PHASE2ST_ADDSA;
1945 iph2->flags ^= ISAKMP_FLAG_C; /* reset bit */
1947 /* don't anything if local test mode. */
1948 if (f_local) {
1949 error = 0;
1950 goto end;
1953 /* Do UPDATE as responder */
1954 plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
1955 if (pk_sendupdate(iph2) < 0) {
1956 plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
1957 goto end;
1959 plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
1961 /* Do ADD for responder */
1962 if (pk_sendadd(iph2) < 0) {
1963 plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
1964 goto end;
1966 plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
1969 * set policies into SPD if the policy is generated
1970 * from peer's policy.
1972 if (iph2->spidx_gen) {
1974 struct policyindex *spidx;
1975 struct sockaddr_storage addr;
1976 u_int8_t pref;
1977 struct sockaddr *src = iph2->src;
1978 struct sockaddr *dst = iph2->dst;
1980 /* make inbound policy */
1981 iph2->src = dst;
1982 iph2->dst = src;
1983 if (pk_sendspdupdate2(iph2) < 0) {
1984 plog(LLV_ERROR, LOCATION, NULL,
1985 "pfkey spdupdate2(inbound) failed.\n");
1986 goto end;
1988 plog(LLV_DEBUG, LOCATION, NULL,
1989 "pfkey spdupdate2(inbound) sent.\n");
1991 spidx = (struct policyindex *)iph2->spidx_gen;
1992 #ifdef HAVE_POLICY_FWD
1993 /* make forward policy if required */
1994 if (tunnel_mode_prop(iph2->approval)) {
1995 spidx->dir = IPSEC_DIR_FWD;
1996 if (pk_sendspdupdate2(iph2) < 0) {
1997 plog(LLV_ERROR, LOCATION, NULL,
1998 "pfkey spdupdate2(forward) failed.\n");
1999 goto end;
2001 plog(LLV_DEBUG, LOCATION, NULL,
2002 "pfkey spdupdate2(forward) sent.\n");
2004 #endif
2006 /* make outbound policy */
2007 iph2->src = src;
2008 iph2->dst = dst;
2009 spidx->dir = IPSEC_DIR_OUTBOUND;
2010 addr = spidx->src;
2011 spidx->src = spidx->dst;
2012 spidx->dst = addr;
2013 pref = spidx->prefs;
2014 spidx->prefs = spidx->prefd;
2015 spidx->prefd = pref;
2017 if (pk_sendspdupdate2(iph2) < 0) {
2018 plog(LLV_ERROR, LOCATION, NULL,
2019 "pfkey spdupdate2(outbound) failed.\n");
2020 goto end;
2022 plog(LLV_DEBUG, LOCATION, NULL,
2023 "pfkey spdupdate2(outbound) sent.\n");
2025 /* spidx_gen is unnecessary any more */
2026 delsp_bothdir((struct policyindex *)iph2->spidx_gen);
2027 racoon_free(iph2->spidx_gen);
2028 iph2->spidx_gen = NULL;
2029 iph2->generated_spidx=1;
2032 error = 0;
2034 end:
2035 return error;
2039 * create HASH, body (SA, NONCE) payload with isakmp header.
2041 static vchar_t *
2042 quick_ir1mx(iph2, body, hash)
2043 struct ph2handle *iph2;
2044 vchar_t *body, *hash;
2046 struct isakmp *isakmp;
2047 vchar_t *buf = NULL, *new = NULL;
2048 char *p;
2049 int tlen;
2050 struct isakmp_gen *gen;
2051 int error = ISAKMP_INTERNAL_ERROR;
2053 /* create buffer for isakmp payload */
2054 tlen = sizeof(*isakmp)
2055 + sizeof(*gen) + hash->l
2056 + body->l;
2057 buf = vmalloc(tlen);
2058 if (buf == NULL) {
2059 plog(LLV_ERROR, LOCATION, NULL,
2060 "failed to get buffer to send.\n");
2061 goto end;
2064 /* re-set encryption flag, for serurity. */
2065 iph2->flags |= ISAKMP_FLAG_E;
2067 /* set isakmp header */
2068 p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
2069 if (p == NULL)
2070 goto end;
2072 /* add HASH payload */
2073 /* XXX is next type always SA ? */
2074 p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_SA);
2076 /* add body payload */
2077 memcpy(p, body->v, body->l);
2079 #ifdef HAVE_PRINT_ISAKMP_C
2080 isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
2081 #endif
2083 /* encoding */
2084 new = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
2086 if (new == NULL)
2087 goto end;
2089 vfree(buf);
2091 buf = new;
2093 error = 0;
2095 end:
2096 if (error && buf != NULL) {
2097 vfree(buf);
2098 buf = NULL;
2101 return buf;
2105 * get remote's sainfo.
2106 * NOTE: this function is for responder.
2108 static int
2109 get_sainfo_r(iph2)
2110 struct ph2handle *iph2;
2112 vchar_t *idsrc = NULL, *iddst = NULL, *client = NULL;
2113 int error = ISAKMP_INTERNAL_ERROR;
2115 if (iph2->id == NULL) {
2116 idsrc = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
2117 IPSEC_ULPROTO_ANY);
2118 } else {
2119 idsrc = vdup(iph2->id);
2121 if (idsrc == NULL) {
2122 plog(LLV_ERROR, LOCATION, NULL,
2123 "failed to set ID for source.\n");
2124 goto end;
2127 if (iph2->id_p == NULL) {
2128 iddst = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
2129 IPSEC_ULPROTO_ANY);
2130 } else {
2131 iddst = vdup(iph2->id_p);
2133 if (iddst == NULL) {
2134 plog(LLV_ERROR, LOCATION, NULL,
2135 "failed to set ID for destination.\n");
2136 goto end;
2139 #ifdef ENABLE_HYBRID
2141 /* clientaddr check : obtain modecfg address */
2142 if (iph2->ph1->mode_cfg != NULL) {
2143 if ((iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
2144 (iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)){
2145 struct sockaddr saddr;
2146 saddr.sa_family = AF_INET;
2147 #ifndef __linux__
2148 saddr.sa_len = sizeof(struct sockaddr_in);
2149 #endif
2150 ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
2151 memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
2152 &iph2->ph1->mode_cfg->addr4, sizeof(struct in_addr));
2153 client = ipsecdoi_sockaddr2id(&saddr, 32, IPSEC_ULPROTO_ANY);
2157 /* clientaddr check, fallback to peer address */
2158 if (client == NULL)
2160 client = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
2161 IPSEC_ULPROTO_ANY);
2163 #endif
2165 /* obtain a matching sainfo section */
2166 iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, client, iph2->ph1->rmconf->ph1id);
2167 if (iph2->sainfo == NULL) {
2168 plog(LLV_ERROR, LOCATION, NULL,
2169 "failed to get sainfo.\n");
2170 goto end;
2173 #ifdef ENABLE_HYBRID
2174 /* xauth group inclusion check */
2175 if (iph2->sainfo->group != NULL)
2176 if(group_check(iph2->ph1,&iph2->sainfo->group->v,1))
2177 goto end;
2178 #endif
2180 plog(LLV_DEBUG, LOCATION, NULL,
2181 "selected sainfo: %s\n", sainfo2str(iph2->sainfo));
2183 error = 0;
2184 end:
2185 if (idsrc)
2186 vfree(idsrc);
2187 if (iddst)
2188 vfree(iddst);
2189 if (client)
2190 vfree(client);
2192 return error;
2196 * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types
2197 * are IP address and same address family.
2198 * Then get remote's policy from SPD copied from kernel.
2199 * If the type of ID payload is address or subnet type, then the index is
2200 * made from the payload. If there is no ID payload, or the type of ID
2201 * payload is NOT address type, then the index is made from the address
2202 * pair of phase 1.
2203 * NOTE: This function is only for responder.
2205 static int
2206 get_proposal_r(iph2)
2207 struct ph2handle *iph2;
2209 struct policyindex spidx;
2210 struct secpolicy *sp_in, *sp_out;
2211 int idi2type = 0; /* switch whether copy IDs into id[src,dst]. */
2212 int error = ISAKMP_INTERNAL_ERROR;
2214 /* check the existence of ID payload */
2215 if ((iph2->id_p != NULL && iph2->id == NULL)
2216 || (iph2->id_p == NULL && iph2->id != NULL)) {
2217 plog(LLV_ERROR, LOCATION, NULL,
2218 "Both IDs wasn't found in payload.\n");
2219 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2222 /* make sure if sa_[src, dst] are null. */
2223 if (iph2->sa_src || iph2->sa_dst) {
2224 plog(LLV_ERROR, LOCATION, NULL,
2225 "Why do ID[src,dst] exist already.\n");
2226 return ISAKMP_INTERNAL_ERROR;
2229 memset(&spidx, 0, sizeof(spidx));
2231 #define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
2233 /* make a spidx; a key to search SPD */
2234 spidx.dir = IPSEC_DIR_INBOUND;
2235 spidx.ul_proto = 0;
2238 * make destination address in spidx from either ID payload
2239 * or phase 1 address into a address in spidx.
2241 if (iph2->id != NULL
2242 && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
2243 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
2244 || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
2245 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
2246 /* get a destination address of a policy */
2247 error = ipsecdoi_id2sockaddr(iph2->id,
2248 (struct sockaddr *)&spidx.dst,
2249 &spidx.prefd, &spidx.ul_proto);
2250 if (error)
2251 return error;
2253 #ifdef INET6
2255 * get scopeid from the SA address.
2256 * note that the phase 1 source address is used as
2257 * a destination address to search for a inbound policy entry
2258 * because rcoon is responder.
2260 if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
2261 error = setscopeid((struct sockaddr *)&spidx.dst,
2262 iph2->src);
2263 if (error)
2264 return error;
2266 #endif
2268 if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
2269 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
2270 idi2type = _XIDT(iph2->id);
2272 } else {
2274 plog(LLV_DEBUG, LOCATION, NULL,
2275 "get a destination address of SP index "
2276 "from phase1 address "
2277 "due to no ID payloads found "
2278 "OR because ID type is not address.\n");
2281 * copy the SOURCE address of IKE into the DESTINATION address
2282 * of the key to search the SPD because the direction of policy
2283 * is inbound.
2285 memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
2286 switch (spidx.dst.ss_family) {
2287 case AF_INET:
2288 spidx.prefd = sizeof(struct in_addr) << 3;
2289 break;
2290 #ifdef INET6
2291 case AF_INET6:
2292 spidx.prefd = sizeof(struct in6_addr) << 3;
2293 break;
2294 #endif
2295 default:
2296 spidx.prefd = 0;
2297 break;
2301 /* make source address in spidx */
2302 if (iph2->id_p != NULL
2303 && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
2304 || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
2305 || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
2306 || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
2307 /* get a source address of inbound SA */
2308 error = ipsecdoi_id2sockaddr(iph2->id_p,
2309 (struct sockaddr *)&spidx.src,
2310 &spidx.prefs, &spidx.ul_proto);
2311 if (error)
2312 return error;
2314 #ifdef INET6
2316 * get scopeid from the SA address.
2317 * for more detail, see above of this function.
2319 if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
2320 error = setscopeid((struct sockaddr *)&spidx.src,
2321 iph2->dst);
2322 if (error)
2323 return error;
2325 #endif
2327 /* Before setting iph2->[sa_src, sa_dst] with the addresses
2328 * provided in ID payloads, we check:
2329 * - they are both addresses of same family
2330 * - sainfo has not been selected only based on ID payload
2331 * information but also based on specific Phase 1
2332 * credentials (iph2->sainfo->id_i is defined), i.e.
2333 * local configuration _explicitly_ expect that user
2334 * (e.g. from asn1dn "C=FR, ...") with those IDs) */
2335 if (_XIDT(iph2->id_p) == idi2type &&
2336 spidx.dst.ss_family == spidx.src.ss_family &&
2337 iph2->sainfo && iph2->sainfo->id_i) {
2339 iph2->sa_src = dupsaddr((struct sockaddr *)&spidx.dst);
2340 if (iph2->sa_src == NULL) {
2341 plog(LLV_ERROR, LOCATION, NULL,
2342 "buffer allocation failed.\n");
2343 return ISAKMP_INTERNAL_ERROR;
2346 iph2->sa_dst = dupsaddr((struct sockaddr *)&spidx.src);
2347 if (iph2->sa_dst == NULL) {
2348 plog(LLV_ERROR, LOCATION, NULL,
2349 "buffer allocation failed.\n");
2350 return ISAKMP_INTERNAL_ERROR;
2352 } else {
2353 plog(LLV_DEBUG, LOCATION, NULL,
2354 "Either family (%d - %d), types (%d - %d) of ID"
2355 "from initiator differ or matching sainfo has"
2356 "has no id_i defined for the peer. Not filling"
2357 "iph2->sa_src and iph2->sa_dst.\n",
2358 spidx.src.ss_family, spidx.dst.ss_family,
2359 _XIDT(iph2->id_p),idi2type);
2361 } else {
2362 plog(LLV_DEBUG, LOCATION, NULL,
2363 "get a source address of SP index from Phase 1"
2364 "addresses due to no ID payloads found"
2365 "OR because ID type is not address.\n");
2367 /* see above comment. */
2368 memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
2369 switch (spidx.src.ss_family) {
2370 case AF_INET:
2371 spidx.prefs = sizeof(struct in_addr) << 3;
2372 break;
2373 #ifdef INET6
2374 case AF_INET6:
2375 spidx.prefs = sizeof(struct in6_addr) << 3;
2376 break;
2377 #endif
2378 default:
2379 spidx.prefs = 0;
2380 break;
2384 #undef _XIDT
2386 plog(LLV_DEBUG, LOCATION, NULL,
2387 "get a src address from ID payload "
2388 "%s prefixlen=%u ul_proto=%u\n",
2389 saddr2str((struct sockaddr *)&spidx.src),
2390 spidx.prefs, spidx.ul_proto);
2391 plog(LLV_DEBUG, LOCATION, NULL,
2392 "get dst address from ID payload "
2393 "%s prefixlen=%u ul_proto=%u\n",
2394 saddr2str((struct sockaddr *)&spidx.dst),
2395 spidx.prefd, spidx.ul_proto);
2398 * convert the ul_proto if it is 0
2399 * because 0 in ID payload means a wild card.
2401 if (spidx.ul_proto == 0)
2402 spidx.ul_proto = IPSEC_ULPROTO_ANY;
2404 #ifdef HAVE_SECCTX
2406 * Need to use security context in spidx to ensure the correct
2407 * policy is selected. The only way to get the security context
2408 * is to look into the proposal sent by peer ahead of time.
2410 if (get_security_context(iph2->sa, &spidx)) {
2411 plog(LLV_ERROR, LOCATION, NULL,
2412 "error occurred trying to get security context.\n");
2413 return ISAKMP_INTERNAL_ERROR;
2415 #endif /* HAVE_SECCTX */
2417 /* get inbound policy */
2418 sp_in = getsp_r(&spidx);
2419 if (sp_in == NULL) {
2420 if (iph2->ph1->rmconf->gen_policy) {
2421 plog(LLV_INFO, LOCATION, NULL,
2422 "no policy found, "
2423 "try to generate the policy : %s\n",
2424 spidx2str(&spidx));
2425 iph2->spidx_gen = racoon_malloc(sizeof(spidx));
2426 if (!iph2->spidx_gen) {
2427 plog(LLV_ERROR, LOCATION, NULL,
2428 "buffer allocation failed.\n");
2429 return ISAKMP_INTERNAL_ERROR;
2431 memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
2432 return -2; /* special value */
2434 plog(LLV_ERROR, LOCATION, NULL,
2435 "no policy found: %s\n", spidx2str(&spidx));
2436 return ISAKMP_INTERNAL_ERROR;
2438 /* Refresh existing generated policies
2440 if (iph2->ph1->rmconf->gen_policy) {
2441 plog(LLV_INFO, LOCATION, NULL,
2442 "Update the generated policy : %s\n",
2443 spidx2str(&spidx));
2444 iph2->spidx_gen = racoon_malloc(sizeof(spidx));
2445 if (!iph2->spidx_gen) {
2446 plog(LLV_ERROR, LOCATION, NULL,
2447 "buffer allocation failed.\n");
2448 return ISAKMP_INTERNAL_ERROR;
2450 memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
2453 /* get outbound policy */
2455 struct sockaddr_storage addr;
2456 u_int8_t pref;
2458 spidx.dir = IPSEC_DIR_OUTBOUND;
2459 addr = spidx.src;
2460 spidx.src = spidx.dst;
2461 spidx.dst = addr;
2462 pref = spidx.prefs;
2463 spidx.prefs = spidx.prefd;
2464 spidx.prefd = pref;
2466 sp_out = getsp_r(&spidx);
2467 if (!sp_out) {
2468 plog(LLV_WARNING, LOCATION, NULL,
2469 "no outbound policy found: %s\n",
2470 spidx2str(&spidx));
2474 plog(LLV_DEBUG, LOCATION, NULL,
2475 "suitable SP found:%s\n", spidx2str(&spidx));
2478 * In the responder side, the inbound policy should be using IPsec.
2479 * outbound policy is not checked currently.
2481 if (sp_in->policy != IPSEC_POLICY_IPSEC) {
2482 plog(LLV_ERROR, LOCATION, NULL,
2483 "policy found, but no IPsec required: %s\n",
2484 spidx2str(&spidx));
2485 return ISAKMP_INTERNAL_ERROR;
2488 /* set new proposal derived from a policy into the iph2->proposal. */
2489 if (set_proposal_from_policy(iph2, sp_in, sp_out) < 0) {
2490 plog(LLV_ERROR, LOCATION, NULL,
2491 "failed to create saprop.\n");
2492 return ISAKMP_INTERNAL_ERROR;
2495 #ifdef HAVE_SECCTX
2496 if (spidx.sec_ctx.ctx_str) {
2497 set_secctx_in_proposal(iph2, spidx);
2499 #endif /* HAVE_SECCTX */
2501 iph2->spid = sp_in->id;
2503 return 0;
2507 * handle a notification payload inside phase2 exchange.
2508 * phase2 is always encrypted, so it does not need to be checked
2509 * for explicitely.
2511 static int
2512 ph2_recv_n(iph2, gen)
2513 struct ph2handle *iph2;
2514 struct isakmp_gen *gen;
2516 struct ph1handle *iph1 = iph2->ph1;
2517 struct isakmp_pl_n *notify = (struct isakmp_pl_n *) gen;
2518 u_int type;
2519 int check_level;
2521 type = ntohs(notify->type);
2522 switch (type) {
2523 case ISAKMP_NTYPE_CONNECTED:
2524 break;
2525 case ISAKMP_NTYPE_INITIAL_CONTACT:
2526 return isakmp_info_recv_initialcontact(iph1, iph2);
2527 case ISAKMP_NTYPE_RESPONDER_LIFETIME:
2528 ipsecdoi_parse_responder_lifetime(notify,
2529 &iph2->lifetime_secs, &iph2->lifetime_kb);
2531 if (iph1 != NULL && iph1->rmconf != NULL) {
2532 check_level = iph1->rmconf->pcheck_level;
2533 } else {
2534 if (iph1 != NULL)
2535 plog(LLV_DEBUG, LOCATION, NULL,
2536 "No phase1 rmconf found !\n");
2537 else
2538 plog(LLV_DEBUG, LOCATION, NULL,
2539 "No phase1 found !\n");
2540 check_level = PROP_CHECK_EXACT;
2543 switch (check_level) {
2544 case PROP_CHECK_OBEY:
2545 break;
2546 case PROP_CHECK_STRICT:
2547 case PROP_CHECK_CLAIM:
2548 if (iph2->sainfo == NULL
2549 || iph2->sainfo->lifetime <= iph2->lifetime_secs) {
2550 plog(LLV_WARNING, LOCATION, NULL,
2551 "RESPONDER-LIFETIME: lifetime mismatch\n");
2552 iph2->lifetime_secs = 0;
2554 break;
2555 case PROP_CHECK_EXACT:
2556 if (iph2->sainfo == NULL
2557 || iph2->sainfo->lifetime != iph2->lifetime_secs) {
2558 plog(LLV_WARNING, LOCATION, NULL,
2559 "RESPONDER-LIFETIME: lifetime mismatch\n");
2560 iph2->lifetime_secs = 0;
2562 break;
2564 break;
2565 default:
2566 isakmp_log_notify(iph2->ph1, notify, "phase2 exchange");
2567 isakmp_info_send_n2(iph2, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE,
2568 NULL);
2569 break;
2571 return 0;