source: rtems-libbsd/ipsec-tools/src/racoon/isakmp_quick.c @ b376ae1

55-freebsd-126-freebsd-12
Last change on this file since b376ae1 was b376ae1, checked in by Christian Mauderer <christian.mauderer@…>, on 05/03/18 at 12:15:11

ipsec-tools: Port libipsec, setkey and racoon.

Note that this replaces the libipsec from FreeBSD with the one provided
by ipsec-tools.

  • Property mode set to 100644
File size: 62.6 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2#ifdef __rtems__
3#include <machine/rtems-bsd-program.h>
4#include "rtems-bsd-racoon-namespace.h"
5#endif /* __rtems__ */
6
7/*      $NetBSD: isakmp_quick.c,v 1.29 2011/03/14 17:18:13 tteras Exp $ */
8
9/* Id: isakmp_quick.c,v 1.29 2006/08/22 18:17:17 manubsd Exp */
10
11/*
12 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the project nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40#include "config.h"
41
42#include <sys/types.h>
43#include <sys/param.h>
44#include <sys/socket.h>
45
46#include <netinet/in.h>
47
48#include <stdlib.h>
49#include <stdio.h>
50#include <string.h>
51#include <errno.h>
52#if TIME_WITH_SYS_TIME
53# include <sys/time.h>
54# include <time.h>
55#else
56# if HAVE_SYS_TIME_H
57#  include <sys/time.h>
58# else
59#  include <time.h>
60# endif
61#endif
62
63#include PATH_IPSEC_H
64
65#include "var.h"
66#include "vmbuf.h"
67#include "schedule.h"
68#include "misc.h"
69#include "plog.h"
70#include "debug.h"
71
72#include "localconf.h"
73#include "remoteconf.h"
74#include "handler.h"
75#include "policy.h"
76#include "proposal.h"
77#include "isakmp_var.h"
78#include "isakmp.h"
79#include "isakmp_inf.h"
80#include "isakmp_quick.h"
81#include "oakley.h"
82#include "ipsec_doi.h"
83#include "crypto_openssl.h"
84#include "pfkey.h"
85#include "policy.h"
86#include "algorithm.h"
87#include "sockmisc.h"
88#include "proposal.h"
89#include "sainfo.h"
90#include "admin.h"
91#include "strnames.h"
92
93#ifdef ENABLE_HYBRID
94#include <resolv.h>
95#include "isakmp_xauth.h"
96#include "isakmp_cfg.h"
97#endif
98
99#ifdef ENABLE_NATT
100#include "nattraversal.h"
101#endif
102
103/* quick mode */
104static vchar_t *quick_ir1mx __P((struct ph2handle *, vchar_t *, vchar_t *));
105static int get_sainfo_r __P((struct ph2handle *));
106static int get_proposal_r __P((struct ph2handle *));
107static int ph2_recv_n __P((struct ph2handle *, struct isakmp_gen *));
108static void quick_timeover_stub __P((struct sched *));
109static void quick_timeover __P((struct ph2handle *));
110
111/* called from scheduler */
112static void
113quick_timeover_stub(p)
114        struct sched *p;
115{
116        quick_timeover(container_of(p, struct ph2handle, sce));
117}
118
119static void
120quick_timeover(iph2)
121        struct ph2handle *iph2;
122{
123        plog(LLV_ERROR, LOCATION, NULL,
124                "%s give up to get IPsec-SA due to time up to wait.\n",
125                saddrwop2str(iph2->dst));
126
127        /* If initiator side, send error to kernel by SADB_ACQUIRE. */
128        if (iph2->side == INITIATOR)
129                pk_sendeacquire(iph2);
130
131        remph2(iph2);
132        delph2(iph2);
133}
134
135/* %%%
136 * Quick Mode
137 */
138/*
139 * begin Quick Mode as initiator.  send pfkey getspi message to kernel.
140 */
141int
142quick_i1prep(iph2, msg)
143        struct ph2handle *iph2;
144        vchar_t *msg; /* must be null pointer */
145{
146        int error = ISAKMP_INTERNAL_ERROR;
147
148        /* validity check */
149        if (iph2->status != PHASE2ST_STATUS2) {
150                plog(LLV_ERROR, LOCATION, NULL,
151                        "status mismatched %d.\n", iph2->status);
152                goto end;
153        }
154
155        iph2->msgid = isakmp_newmsgid2(iph2->ph1);
156        iph2->ivm = oakley_newiv2(iph2->ph1, iph2->msgid);
157        if (iph2->ivm == NULL)
158                return 0;
159
160        iph2->status = PHASE2ST_GETSPISENT;
161
162        /* don't anything if local test mode. */
163        if (f_local) {
164                error = 0;
165                goto end;
166        }
167
168        /* send getspi message */
169        if (pk_sendgetspi(iph2) < 0)
170                goto end;
171
172        plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
173
174        sched_schedule(&iph2->sce, lcconf->wait_ph2complete,
175                       quick_timeover_stub);
176
177        error = 0;
178
179end:
180        return error;
181}
182
183/*
184 * send to responder
185 *      HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
186 */
187int
188quick_i1send(iph2, msg)
189        struct ph2handle *iph2;
190        vchar_t *msg; /* must be null pointer */
191{
192        vchar_t *body = NULL;
193        vchar_t *hash = NULL;
194        struct isakmp_gen *gen;
195        char *p;
196        int tlen;
197        int error = ISAKMP_INTERNAL_ERROR;
198        int natoa = ISAKMP_NPTYPE_NONE;
199        int pfsgroup, idci, idcr;
200        int np;
201        struct ipsecdoi_id_b *id, *id_p;
202#ifdef ENABLE_NATT
203        vchar_t *nat_oai = NULL;
204        vchar_t *nat_oar = NULL;
205#endif
206
207        /* validity check */
208        if (msg != NULL) {
209                plog(LLV_ERROR, LOCATION, NULL,
210                        "msg has to be NULL in this function.\n");
211                goto end;
212        }
213        if (iph2->status != PHASE2ST_GETSPIDONE) {
214                plog(LLV_ERROR, LOCATION, NULL,
215                        "status mismatched %d.\n", iph2->status);
216                goto end;
217        }
218
219        /* create SA payload for my proposal */
220        if (ipsecdoi_setph2proposal(iph2) < 0)
221                goto end;
222
223        /* generate NONCE value */
224        iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
225        if (iph2->nonce == NULL)
226                goto end;
227
228        /*
229         * DH value calculation is kicked out into cfparse.y.
230         * because pfs group can not be negotiated, it's only to be checked
231         * acceptable.
232         */
233        /* generate KE value if need */
234        pfsgroup = iph2->proposal->pfs_group;
235        if (pfsgroup) {
236                /* DH group settting if PFS is required. */
237                if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
238                        plog(LLV_ERROR, LOCATION, NULL,
239                                "failed to set DH value.\n");
240                        goto end;
241                }
242                if (oakley_dh_generate(iph2->pfsgrp,
243                                &iph2->dhpub, &iph2->dhpriv) < 0) {
244                        goto end;
245                }
246        }
247
248        /* generate ID value */
249        if (ipsecdoi_setid2(iph2) < 0) {
250                plog(LLV_ERROR, LOCATION, NULL,
251                        "failed to get ID.\n");
252                goto end;
253        }
254        plog(LLV_DEBUG, LOCATION, NULL, "IDci:\n");
255        plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
256        plog(LLV_DEBUG, LOCATION, NULL, "IDcr:\n");
257        plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
258
259        /*
260         * we do not attach IDci nor IDcr, under the following condition:
261         * - all proposals are transport mode
262         * - no MIP6 or proxy
263         * - id payload suggests to encrypt all the traffic (no specific
264         *   protocol type)
265         * - SA endpoints and IKE addresses for the nego are the same
266         *   (iph2->src/dst)
267         */
268        id = (struct ipsecdoi_id_b *)iph2->id->v;
269        id_p = (struct ipsecdoi_id_b *)iph2->id_p->v;
270        if (id->proto_id == 0 &&
271            id_p->proto_id == 0 &&
272            iph2->ph1->rmconf->support_proxy == 0 &&
273            iph2->sa_src == NULL && iph2->sa_dst == NULL &&
274            ipsecdoi_transportmode(iph2->proposal)) {
275                idci = idcr = 0;
276        } else
277                idci = idcr = 1;
278
279#ifdef ENABLE_NATT
280        /*
281         * RFC3947 5.2. if we propose UDP-Encapsulated-Transport
282         * we should send NAT-OA
283         */
284        if (ipsecdoi_transportmode(iph2->proposal)
285         && (iph2->ph1->natt_flags & NAT_DETECTED)) {
286                natoa = iph2->ph1->natt_options->payload_nat_oa;
287
288                nat_oai = ipsecdoi_sockaddr2id(iph2->src,
289                        IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
290                nat_oar = ipsecdoi_sockaddr2id(iph2->dst,
291                        IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
292
293                if (nat_oai == NULL || nat_oar == NULL) {
294                        plog(LLV_ERROR, LOCATION, NULL,
295                                "failed to generate NAT-OA payload.\n");
296                        goto end;
297                }
298
299                plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n");
300                plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l);
301                plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n");
302                plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l);
303        } else {
304                natoa = ISAKMP_NPTYPE_NONE;
305        }
306#endif
307
308        /* create SA;NONCE payload, and KE if need, and IDii, IDir. */
309        tlen = + sizeof(*gen) + iph2->sa->l
310                + sizeof(*gen) + iph2->nonce->l;
311        if (pfsgroup)
312                tlen += (sizeof(*gen) + iph2->dhpub->l);
313        if (idci)
314                tlen += sizeof(*gen) + iph2->id->l;
315        if (idcr)
316                tlen += sizeof(*gen) + iph2->id_p->l;
317#ifdef ENABLE_NATT
318        if (natoa != ISAKMP_NPTYPE_NONE)
319                tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
320#endif
321
322        body = vmalloc(tlen);
323        if (body == NULL) {
324                plog(LLV_ERROR, LOCATION, NULL,
325                        "failed to get buffer to send.\n");
326                goto end;
327        }
328
329        p = body->v;
330
331        /* add SA payload */
332        p = set_isakmp_payload(p, iph2->sa, ISAKMP_NPTYPE_NONCE);
333
334        /* add NONCE payload */
335        if (pfsgroup)
336                np = ISAKMP_NPTYPE_KE;
337        else if (idci || idcr)
338                np = ISAKMP_NPTYPE_ID;
339        else
340                np = natoa;
341        p = set_isakmp_payload(p, iph2->nonce, np);
342
343        /* add KE payload if need. */
344        np = (idci || idcr) ? ISAKMP_NPTYPE_ID : natoa;
345        if (pfsgroup)
346                p = set_isakmp_payload(p, iph2->dhpub, np);
347
348        /* IDci */
349        np = (idcr) ? ISAKMP_NPTYPE_ID : natoa;
350        if (idci)
351                p = set_isakmp_payload(p, iph2->id, np);
352
353        /* IDcr */
354        if (idcr)
355                p = set_isakmp_payload(p, iph2->id_p, natoa);
356
357#ifdef ENABLE_NATT
358        /* NAT-OA */
359        if (natoa != ISAKMP_NPTYPE_NONE) {
360                p = set_isakmp_payload(p, nat_oai, natoa);
361                p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
362        }
363#endif
364
365        /* generate HASH(1) */
366        hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
367        if (hash == NULL)
368                goto end;
369
370        /* send isakmp payload */
371        iph2->sendbuf = quick_ir1mx(iph2, body, hash);
372        if (iph2->sendbuf == NULL)
373                goto end;
374
375        /* send the packet, add to the schedule to resend */
376        if (isakmp_ph2send(iph2) == -1)
377                goto end;
378
379        /* change status of isakmp status entry */
380        iph2->status = PHASE2ST_MSG1SENT;
381
382        error = 0;
383
384end:
385        if (body != NULL)
386                vfree(body);
387        if (hash != NULL)
388                vfree(hash);
389#ifdef ENABLE_NATT
390        if (nat_oai != NULL)
391                vfree(nat_oai);
392        if (nat_oar != NULL)
393                vfree(nat_oar);
394#endif
395
396        return error;
397}
398
399/*
400 * receive from responder
401 *      HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
402 */
403int
404quick_i2recv(iph2, msg0)
405        struct ph2handle *iph2;
406        vchar_t *msg0;
407{
408        vchar_t *msg = NULL;
409        vchar_t *hbuf = NULL;   /* for hash computing. */
410        vchar_t *pbuf = NULL;   /* for payload parsing */
411        vchar_t *idci = NULL;
412        vchar_t *idcr = NULL;
413        struct isakmp_parse_t *pa;
414        struct isakmp *isakmp = (struct isakmp *)msg0->v;
415        struct isakmp_pl_hash *hash = NULL;
416        char *p;
417        int tlen;
418        int error = ISAKMP_INTERNAL_ERROR;
419
420        /* validity check */
421        if (iph2->status != PHASE2ST_MSG1SENT) {
422                plog(LLV_ERROR, LOCATION, NULL,
423                        "status mismatched %d.\n", iph2->status);
424                goto end;
425        }
426
427        /* decrypt packet */
428        if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
429                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
430                        "Packet wasn't encrypted.\n");
431                goto end;
432        }
433        msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
434        if (msg == NULL)
435                goto end;
436
437        /* create buffer for validating HASH(2) */
438        /*
439         * ordering rule:
440         *      1. the first one must be HASH
441         *      2. the second one must be SA (added in isakmp-oakley-05!)
442         *      3. two IDs must be considered as IDci, then IDcr
443         */
444        pbuf = isakmp_parse(msg);
445        if (pbuf == NULL)
446                goto end;
447        pa = (struct isakmp_parse_t *)pbuf->v;
448
449        /* HASH payload is fixed postion */
450        if (pa->type != ISAKMP_NPTYPE_HASH) {
451                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
452                        "received invalid next payload type %d, "
453                        "expecting %d.\n",
454                        pa->type, ISAKMP_NPTYPE_HASH);
455                goto end;
456        }
457        hash = (struct isakmp_pl_hash *)pa->ptr;
458        pa++;
459
460        /*
461         * this restriction was introduced in isakmp-oakley-05.
462         * we do not check this for backward compatibility.
463         * TODO: command line/config file option to enable/disable this code
464         */
465        /* HASH payload is fixed postion */
466        if (pa->type != ISAKMP_NPTYPE_SA) {
467                plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
468                        "received invalid next payload type %d, "
469                        "expecting %d.\n",
470                        pa->type, ISAKMP_NPTYPE_HASH);
471        }
472
473        /* allocate buffer for computing HASH(2) */
474        tlen = iph2->nonce->l
475                + ntohl(isakmp->len) - sizeof(*isakmp);
476        hbuf = vmalloc(tlen);
477        if (hbuf == NULL) {
478                plog(LLV_ERROR, LOCATION, NULL,
479                        "failed to get hash buffer.\n");
480                goto end;
481        }
482        p = hbuf->v + iph2->nonce->l;   /* retain the space for Ni_b */
483
484        /*
485         * parse the payloads.
486         * copy non-HASH payloads into hbuf, so that we can validate HASH.
487         */
488        iph2->sa_ret = NULL;
489        tlen = 0;       /* count payload length except of HASH payload. */
490        for (; pa->type; pa++) {
491
492                /* copy to buffer for HASH */
493                /* Don't modify the payload */
494                memcpy(p, pa->ptr, pa->len);
495
496                switch (pa->type) {
497                case ISAKMP_NPTYPE_SA:
498                        if (iph2->sa_ret != NULL) {
499                                plog(LLV_ERROR, LOCATION, NULL,
500                                        "Ignored, multiple SA "
501                                        "isn't supported.\n");
502                                break;
503                        }
504                        if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0) {
505                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
506                                        "duplicate ISAKMP_NPTYPE_SA.\n");
507                                goto end;
508                        }
509                        break;
510
511                case ISAKMP_NPTYPE_NONCE:
512                        if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) {
513                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
514                                        "duplicate ISAKMP_NPTYPE_NONCE.\n");
515                                goto end;
516                        }
517                        break;
518
519                case ISAKMP_NPTYPE_KE:
520                        if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) {
521                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
522                                        "duplicate ISAKMP_NPTYPE_KE.\n");
523                                goto end;
524                        }
525                        break;
526
527                case ISAKMP_NPTYPE_ID:
528                        if (idci == NULL) {
529                                if (isakmp_p2ph(&idci, pa->ptr) < 0)
530                                        goto end;
531                        } else if (idcr == NULL) {
532                                if (isakmp_p2ph(&idcr, pa->ptr) < 0)
533                                        goto end;
534                        } else {
535                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
536                                        "too many ISAKMP_NPTYPE_ID payloads.\n");
537                                goto end;
538                        }
539                        break;
540
541                case ISAKMP_NPTYPE_N:
542                        ph2_recv_n(iph2, pa->ptr);
543                        break;
544
545#ifdef ENABLE_NATT
546                case ISAKMP_NPTYPE_NATOA_DRAFT:
547                case ISAKMP_NPTYPE_NATOA_RFC:
548                    {
549                        struct sockaddr_storage addr;
550                        struct sockaddr *daddr;
551                        u_int8_t prefix;
552                        u_int16_t ul_proto;
553                        vchar_t *vp = NULL;
554
555                        if (isakmp_p2ph(&vp, pa->ptr) < 0)
556                                goto end;
557
558                        error = ipsecdoi_id2sockaddr(vp,
559                                        (struct sockaddr *) &addr,
560                                        &prefix, &ul_proto);
561
562                        vfree(vp);
563
564                        if (error)
565                                goto end;
566
567                        daddr = dupsaddr((struct sockaddr *) &addr);
568                        if (daddr == NULL)
569                                goto end;
570
571                        if (iph2->natoa_src == NULL)
572                                iph2->natoa_src = daddr;
573                        else if (iph2->natoa_dst == NULL)
574                                iph2->natoa_dst = daddr;
575                        else {
576                                racoon_free(daddr);
577                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
578                                        "too many ISAKMP_NPTYPE_NATOA payloads.\n");
579                                goto end;
580                        }
581                    }
582                        break;
583#endif
584
585                default:
586                        /* don't send information, see ident_r1recv() */
587                        plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
588                                "ignore the packet, "
589                                "received unexpecting payload type %d.\n",
590                                pa->type);
591                        goto end;
592                }
593
594                p += pa->len;
595
596                /* compute true length of payload. */
597                tlen += pa->len;
598        }
599
600        /* payload existency check */
601        if (hash == NULL || iph2->sa_ret == NULL || iph2->nonce_p == NULL) {
602                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
603                        "few isakmp message received.\n");
604                goto end;
605        }
606
607        /* identity check */
608        if (idci != NULL) {
609                struct sockaddr_storage proposed_addr, got_addr;
610                u_int8_t proposed_prefix, got_prefix;
611                u_int16_t proposed_ulproto, got_ulproto;
612
613                error = ipsecdoi_id2sockaddr(iph2->id,
614                                        (struct sockaddr *) &proposed_addr,
615                                        &proposed_prefix, &proposed_ulproto);
616                if (error)
617                        goto end;
618
619                error = ipsecdoi_id2sockaddr(idci,
620                                        (struct sockaddr *) &got_addr,
621                                        &got_prefix, &got_ulproto);
622                if (error)
623                        goto end;
624
625                if (proposed_prefix != got_prefix
626                 || proposed_ulproto != got_ulproto) {
627                        plog(LLV_DEBUG, LOCATION, NULL,
628                                "IDci prefix/ulproto does not match proposal.\n");
629                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
630                        goto end;
631                }
632#ifdef ENABLE_NATT
633                set_port(iph2->natoa_src,
634                         extract_port((struct sockaddr *) &proposed_addr));
635#endif
636
637                if (cmpsaddr((struct sockaddr *) &proposed_addr,
638                             (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) {
639                        plog(LLV_DEBUG, LOCATION, NULL,
640                                "IDci matches proposal.\n");
641#ifdef ENABLE_NATT
642                } else if (iph2->natoa_src != NULL
643                        && cmpsaddr(iph2->natoa_src,
644                                    (struct sockaddr *) &got_addr) == 0) {
645                        plog(LLV_DEBUG, LOCATION, NULL,
646                                "IDci matches NAT-OAi.\n");
647#endif
648                } else {
649                        plog(LLV_ERROR, LOCATION, NULL,
650                                "mismatched IDci was returned.\n");
651                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
652                        goto end;
653                }
654        }
655        if (idcr != NULL) {
656                struct sockaddr_storage proposed_addr, got_addr;
657                u_int8_t proposed_prefix, got_prefix;
658                u_int16_t proposed_ulproto, got_ulproto;
659
660                error = ipsecdoi_id2sockaddr(iph2->id_p,
661                                        (struct sockaddr *) &proposed_addr,
662                                        &proposed_prefix, &proposed_ulproto);
663                if (error)
664                        goto end;
665
666                error = ipsecdoi_id2sockaddr(idcr,
667                                        (struct sockaddr *) &got_addr,
668                                        &got_prefix, &got_ulproto);
669                if (error)
670                        goto end;
671
672                if (proposed_prefix != got_prefix
673                 || proposed_ulproto != got_ulproto) {
674                        plog(LLV_DEBUG, LOCATION, NULL,
675                                "IDcr prefix/ulproto does not match proposal.\n");
676                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
677                        goto end;
678                }
679
680#ifdef ENABLE_NATT
681                set_port(iph2->natoa_dst,
682                         extract_port((struct sockaddr *) &proposed_addr));
683#endif
684
685                if (cmpsaddr((struct sockaddr *) &proposed_addr,
686                             (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) {
687                        plog(LLV_DEBUG, LOCATION, NULL,
688                                "IDcr matches proposal.\n");
689#ifdef ENABLE_NATT
690                } else if (iph2->natoa_dst != NULL
691                        && cmpsaddr(iph2->natoa_dst,
692                                    (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) {
693                        plog(LLV_DEBUG, LOCATION, NULL,
694                                "IDcr matches NAT-OAr.\n");
695#endif
696                } else {
697                        plog(LLV_ERROR, LOCATION, NULL,
698                                "mismatched IDcr was returned.\n");
699                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
700                        goto end;
701                }
702        }
703
704        /* Fixed buffer for calculating HASH */
705        memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
706        plog(LLV_DEBUG, LOCATION, NULL,
707                "HASH allocated:hbuf->l=%zu actual:tlen=%zu\n",
708                hbuf->l, tlen + iph2->nonce->l);
709        /* adjust buffer length for HASH */
710        hbuf->l = iph2->nonce->l + tlen;
711
712        /* validate HASH(2) */
713    {
714        char *r_hash;
715        vchar_t *my_hash = NULL;
716        int result;
717
718        r_hash = (char *)hash + sizeof(*hash);
719
720        plog(LLV_DEBUG, LOCATION, NULL, "HASH(2) received:");
721        plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
722
723        my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
724        if (my_hash == NULL)
725                goto end;
726
727        result = memcmp(my_hash->v, r_hash, my_hash->l);
728        vfree(my_hash);
729
730        if (result) {
731                plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
732                        "HASH(2) mismatch.\n");
733                error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
734                goto end;
735        }
736    }
737
738        /* validity check SA payload sent from responder */
739        if (ipsecdoi_checkph2proposal(iph2) < 0) {
740                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
741                        "proposal check failed.\n");
742                error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
743                goto end;
744        }
745
746        /* change status of isakmp status entry */
747        iph2->status = PHASE2ST_STATUS6;
748
749        error = 0;
750
751end:
752        if (hbuf)
753                vfree(hbuf);
754        if (pbuf)
755                vfree(pbuf);
756        if (msg)
757                vfree(msg);
758        if (idci)
759                vfree(idci);
760        if (idcr)
761                vfree(idcr);
762
763        if (error) {
764                VPTRINIT(iph2->sa_ret);
765                VPTRINIT(iph2->nonce_p);
766                VPTRINIT(iph2->dhpub_p);
767                VPTRINIT(iph2->id);
768                VPTRINIT(iph2->id_p);
769#ifdef ENABLE_NATT
770                if (iph2->natoa_src) {
771                        racoon_free(iph2->natoa_src);
772                        iph2->natoa_src = NULL;
773                }
774                if (iph2->natoa_dst) {
775                        racoon_free(iph2->natoa_dst);
776                        iph2->natoa_dst = NULL;
777                }
778#endif
779        }
780
781        return error;
782}
783
784/*
785 * send to responder
786 *      HDR*, HASH(3)
787 */
788int
789quick_i2send(iph2, msg0)
790        struct ph2handle *iph2;
791        vchar_t *msg0;
792{
793        vchar_t *msg = NULL;
794        vchar_t *buf = NULL;
795        vchar_t *hash = NULL;
796        char *p = NULL;
797        int tlen;
798        int error = ISAKMP_INTERNAL_ERROR;
799
800        /* validity check */
801        if (iph2->status != PHASE2ST_STATUS6) {
802                plog(LLV_ERROR, LOCATION, NULL,
803                        "status mismatched %d.\n", iph2->status);
804                goto end;
805        }
806
807        /* generate HASH(3) */
808    {
809        vchar_t *tmp = NULL;
810
811        plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) generate\n");
812
813        tmp = vmalloc(iph2->nonce->l + iph2->nonce_p->l);
814        if (tmp == NULL) {
815                plog(LLV_ERROR, LOCATION, NULL,
816                        "failed to get hash buffer.\n");
817                goto end;
818        }
819        memcpy(tmp->v, iph2->nonce->v, iph2->nonce->l);
820        memcpy(tmp->v + iph2->nonce->l, iph2->nonce_p->v, iph2->nonce_p->l);
821
822        hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
823        vfree(tmp);
824
825        if (hash == NULL)
826                goto end;
827    }
828
829        /* create buffer for isakmp payload */
830        tlen = sizeof(struct isakmp)
831                + sizeof(struct isakmp_gen) + hash->l;
832        buf = vmalloc(tlen);
833        if (buf == NULL) {
834                plog(LLV_ERROR, LOCATION, NULL,
835                        "failed to get buffer to send.\n");
836                goto end;
837        }
838
839        /* create isakmp header */
840        p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
841        if (p == NULL)
842                goto end;
843
844        /* add HASH(3) payload */
845        p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_NONE);
846
847#ifdef HAVE_PRINT_ISAKMP_C
848        isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
849#endif
850
851        /* encoding */
852        iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
853        if (iph2->sendbuf == NULL)
854                goto end;
855
856        /* if there is commit bit, need resending */
857        if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
858                /* send the packet, add to the schedule to resend */
859                if (isakmp_ph2send(iph2) == -1)
860                        goto end;
861        } else {
862                /* send the packet */
863                if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
864                        goto end;
865        }
866
867        /* the sending message is added to the received-list. */
868        if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local,
869                        iph2->sendbuf, msg0) == -1) {
870                plog(LLV_ERROR , LOCATION, NULL,
871                        "failed to add a response packet to the tree.\n");
872                goto end;
873        }
874
875        /* compute both of KEYMATs */
876        if (oakley_compute_keymat(iph2, INITIATOR) < 0)
877                goto end;
878
879        iph2->status = PHASE2ST_ADDSA;
880
881        /* don't anything if local test mode. */
882        if (f_local) {
883                error = 0;
884                goto end;
885        }
886
887        /* if there is commit bit don't set up SA now. */
888        if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
889                iph2->status = PHASE2ST_COMMIT;
890                error = 0;
891                goto end;
892        }
893
894        /* Do UPDATE for initiator */
895        plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
896        if (pk_sendupdate(iph2) < 0) {
897                plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
898                goto end;
899        }
900        plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
901
902        /* Do ADD for responder */
903        if (pk_sendadd(iph2) < 0) {
904                plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
905                goto end;
906        }
907        plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
908
909        error = 0;
910
911end:
912        if (buf != NULL)
913                vfree(buf);
914        if (msg != NULL)
915                vfree(msg);
916        if (hash != NULL)
917                vfree(hash);
918
919        return error;
920}
921
922/*
923 * receive from responder
924 *      HDR#*, HASH(4), notify
925 */
926int
927quick_i3recv(iph2, msg0)
928        struct ph2handle *iph2;
929        vchar_t *msg0;
930{
931        vchar_t *msg = NULL;
932        vchar_t *pbuf = NULL;   /* for payload parsing */
933        struct isakmp_parse_t *pa;
934        struct isakmp_pl_hash *hash = NULL;
935        vchar_t *notify = NULL;
936        int error = ISAKMP_INTERNAL_ERROR;
937
938        /* validity check */
939        if (iph2->status != PHASE2ST_COMMIT) {
940                plog(LLV_ERROR, LOCATION, NULL,
941                        "status mismatched %d.\n", iph2->status);
942                goto end;
943        }
944
945        /* decrypt packet */
946        if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
947                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
948                        "Packet wasn't encrypted.\n");
949                goto end;
950        }
951        msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
952        if (msg == NULL)
953                goto end;
954
955        /* validate the type of next payload */
956        pbuf = isakmp_parse(msg);
957        if (pbuf == NULL)
958                goto end;
959
960        for (pa = (struct isakmp_parse_t *)pbuf->v;
961             pa->type != ISAKMP_NPTYPE_NONE;
962             pa++) {
963
964                switch (pa->type) {
965                case ISAKMP_NPTYPE_HASH:
966                        hash = (struct isakmp_pl_hash *)pa->ptr;
967                        break;
968                case ISAKMP_NPTYPE_N:
969                        if (notify != NULL) {
970                                plog(LLV_WARNING, LOCATION, NULL,
971                                    "Ignoring multiples notifications\n");
972                                break;
973                        }
974                        ph2_recv_n(iph2, pa->ptr);
975                        notify = vmalloc(pa->len);
976                        if (notify == NULL) {
977                                plog(LLV_ERROR, LOCATION, NULL,
978                                        "failed to get notify buffer.\n");
979                                goto end;
980                        }
981                        memcpy(notify->v, pa->ptr, notify->l);
982                        break;
983                default:
984                        /* don't send information, see ident_r1recv() */
985                        plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
986                                "ignore the packet, "
987                                "received unexpecting payload type %d.\n",
988                                pa->type);
989                        goto end;
990                }
991        }
992
993        /* payload existency check */
994        if (hash == NULL) {
995                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
996                        "few isakmp message received.\n");
997                goto end;
998        }
999
1000        /* validate HASH(4) */
1001    {
1002        char *r_hash;
1003        vchar_t *my_hash = NULL;
1004        vchar_t *tmp = NULL;
1005        int result;
1006
1007        r_hash = (char *)hash + sizeof(*hash);
1008
1009        plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) validate:");
1010        plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
1011
1012        my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
1013        vfree(tmp);
1014        if (my_hash == NULL)
1015                goto end;
1016
1017        result = memcmp(my_hash->v, r_hash, my_hash->l);
1018        vfree(my_hash);
1019
1020        if (result) {
1021                plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
1022                        "HASH(4) mismatch.\n");
1023                error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1024                goto end;
1025        }
1026    }
1027
1028        iph2->status = PHASE2ST_ADDSA;
1029        iph2->flags ^= ISAKMP_FLAG_C;   /* reset bit */
1030
1031        /* don't anything if local test mode. */
1032        if (f_local) {
1033                error = 0;
1034                goto end;
1035        }
1036
1037        /* Do UPDATE for initiator */
1038        plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
1039        if (pk_sendupdate(iph2) < 0) {
1040                plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
1041                goto end;
1042        }
1043        plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
1044
1045        /* Do ADD for responder */
1046        if (pk_sendadd(iph2) < 0) {
1047                plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
1048                goto end;
1049        }
1050        plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
1051
1052        error = 0;
1053
1054end:
1055        if (msg != NULL)
1056                vfree(msg);
1057        if (pbuf != NULL)
1058                vfree(pbuf);
1059        if (notify != NULL)
1060                vfree(notify);
1061
1062        return error;
1063}
1064
1065/*
1066 * receive from initiator
1067 *      HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
1068 */
1069int
1070quick_r1recv(iph2, msg0)
1071        struct ph2handle *iph2;
1072        vchar_t *msg0;
1073{
1074        vchar_t *msg = NULL;
1075        vchar_t *hbuf = NULL;   /* for hash computing. */
1076        vchar_t *pbuf = NULL;   /* for payload parsing */
1077        struct isakmp_parse_t *pa;
1078        struct isakmp *isakmp = (struct isakmp *)msg0->v;
1079        struct isakmp_pl_hash *hash = NULL;
1080        char *p;
1081        int tlen;
1082        int f_id_order; /* for ID payload detection */
1083        int error = ISAKMP_INTERNAL_ERROR;
1084
1085        /* validity check */
1086        if (iph2->status != PHASE2ST_START) {
1087                plog(LLV_ERROR, LOCATION, NULL,
1088                        "status mismatched %d.\n", iph2->status);
1089                goto end;
1090        }
1091
1092        /* decrypting */
1093        if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1094                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1095                        "Packet wasn't encrypted.\n");
1096                error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1097                goto end;
1098        }
1099        /* decrypt packet */
1100        msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
1101        if (msg == NULL) {
1102                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1103                        "Packet decryption failed.\n");
1104                goto end;
1105        }
1106
1107        /* create buffer for using to validate HASH(1) */
1108        /*
1109         * ordering rule:
1110         *      1. the first one must be HASH
1111         *      2. the second one must be SA (added in isakmp-oakley-05!)
1112         *      3. two IDs must be considered as IDci, then IDcr
1113         */
1114        pbuf = isakmp_parse(msg);
1115        if (pbuf == NULL)
1116                goto end;
1117        pa = (struct isakmp_parse_t *)pbuf->v;
1118
1119        /* HASH payload is fixed postion */
1120        if (pa->type != ISAKMP_NPTYPE_HASH) {
1121                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1122                        "received invalid next payload type %d, "
1123                        "expecting %d.\n",
1124                        pa->type, ISAKMP_NPTYPE_HASH);
1125                error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
1126                goto end;
1127        }
1128        hash = (struct isakmp_pl_hash *)pa->ptr;
1129        pa++;
1130
1131        /*
1132         * this restriction was introduced in isakmp-oakley-05.
1133         * we do not check this for backward compatibility.
1134         * TODO: command line/config file option to enable/disable this code
1135         */
1136        /* HASH payload is fixed postion */
1137        if (pa->type != ISAKMP_NPTYPE_SA) {
1138                plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
1139                        "received invalid next payload type %d, "
1140                        "expecting %d.\n",
1141                        pa->type, ISAKMP_NPTYPE_SA);
1142                error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
1143        }
1144
1145        /* allocate buffer for computing HASH(1) */
1146        tlen = ntohl(isakmp->len) - sizeof(*isakmp);
1147        hbuf = vmalloc(tlen);
1148        if (hbuf == NULL) {
1149                plog(LLV_ERROR, LOCATION, NULL,
1150                        "failed to get hash buffer.\n");
1151                goto end;
1152        }
1153        p = hbuf->v;
1154
1155        /*
1156         * parse the payloads.
1157         * copy non-HASH payloads into hbuf, so that we can validate HASH.
1158         */
1159        iph2->sa = NULL;        /* we don't support multi SAs. */
1160        iph2->nonce_p = NULL;
1161        iph2->dhpub_p = NULL;
1162        iph2->id_p = NULL;
1163        iph2->id = NULL;
1164        tlen = 0;       /* count payload length except of HASH payload. */
1165
1166        /*
1167         * IDi2 MUST be immediatelly followed by IDr2.  We allowed the
1168         * illegal case, but logged.  First ID payload is to be IDi2.
1169         * And next ID payload is to be IDr2.
1170         */
1171        f_id_order = 0;
1172
1173        for (; pa->type; pa++) {
1174
1175                /* copy to buffer for HASH */
1176                /* Don't modify the payload */
1177                memcpy(p, pa->ptr, pa->len);
1178
1179                if (pa->type != ISAKMP_NPTYPE_ID)
1180                        f_id_order = 0;
1181
1182                switch (pa->type) {
1183                case ISAKMP_NPTYPE_SA:
1184                        if (iph2->sa != NULL) {
1185                                plog(LLV_ERROR, LOCATION, NULL,
1186                                        "Multi SAs isn't supported.\n");
1187                                goto end;
1188                        }
1189                        if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0) {
1190                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1191                                        "duplicate ISAKMP_NPTYPE_SA.\n");
1192                                goto end;
1193                        }
1194                        break;
1195
1196                case ISAKMP_NPTYPE_NONCE:
1197                        if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) {
1198                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1199                                        "duplicate ISAKMP_NPTYPE_NONCE.\n");
1200                                goto end;
1201                        }
1202                        break;
1203
1204                case ISAKMP_NPTYPE_KE:
1205                        if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) {
1206                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1207                                        "duplicate ISAKMP_NPTYPE_KE.\n");
1208                                goto end;
1209                        }
1210                        break;
1211
1212                case ISAKMP_NPTYPE_ID:
1213                        if (iph2->id_p == NULL) {
1214                                /* for IDci */
1215                                f_id_order++;
1216
1217                                if (isakmp_p2ph(&iph2->id_p, pa->ptr) < 0)
1218                                        goto end;
1219
1220                        } else if (iph2->id == NULL) {
1221                                /* for IDcr */
1222                                if (f_id_order == 0) {
1223                                        plog(LLV_ERROR, LOCATION, NULL,
1224                                                "IDr2 payload is not "
1225                                                "immediatelly followed "
1226                                                "by IDi2. We allowed.\n");
1227                                        /* XXX we allowed in this case. */
1228                                }
1229
1230                                if (isakmp_p2ph(&iph2->id, pa->ptr) < 0)
1231                                        goto end;
1232                        } else {
1233                                plog(LLV_ERROR, LOCATION, NULL,
1234                                        "received too many ID payloads.\n");
1235                                plogdump(LLV_ERROR, iph2->id->v, iph2->id->l);
1236                                error = ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1237                                goto end;
1238                        }
1239                        break;
1240
1241                case ISAKMP_NPTYPE_N:
1242                        ph2_recv_n(iph2, pa->ptr);
1243                        break;
1244
1245#ifdef ENABLE_NATT
1246                case ISAKMP_NPTYPE_NATOA_DRAFT:
1247                case ISAKMP_NPTYPE_NATOA_RFC:
1248                    {
1249                        struct sockaddr_storage addr;
1250                        struct sockaddr *daddr;
1251                        u_int8_t prefix;
1252                        u_int16_t ul_proto;
1253                        vchar_t *vp = NULL;
1254
1255                        if (isakmp_p2ph(&vp, pa->ptr) < 0)
1256                                goto end;
1257
1258                        error = ipsecdoi_id2sockaddr(vp,
1259                                        (struct sockaddr *) &addr,
1260                                        &prefix, &ul_proto);
1261
1262                        vfree(vp);
1263
1264                        if (error)
1265                                goto end;
1266
1267                        daddr = dupsaddr((struct sockaddr *) &addr);
1268                        if (daddr == NULL)
1269                                goto end;
1270
1271                        if (iph2->natoa_dst == NULL)
1272                                iph2->natoa_dst = daddr;
1273                        else if (iph2->natoa_src == NULL)
1274                                iph2->natoa_src = daddr;
1275                        else {
1276                                racoon_free(daddr);
1277                                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1278                                        "received too many NAT-OA payloads.\n");
1279                                error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1280                                goto end;
1281                        }
1282                    }
1283                        break;
1284#endif
1285
1286                default:
1287                        plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1288                                "ignore the packet, "
1289                                "received unexpecting payload type %d.\n",
1290                                pa->type);
1291                        error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1292                        goto end;
1293                }
1294
1295                p += pa->len;
1296
1297                /* compute true length of payload. */
1298                tlen += pa->len;
1299        }
1300
1301        /* payload existency check */
1302        if (hash == NULL || iph2->sa == NULL || iph2->nonce_p == NULL) {
1303                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1304                        "few isakmp message received.\n");
1305                error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1306                goto end;
1307        }
1308
1309        if (iph2->id_p) {
1310                plog(LLV_DEBUG, LOCATION, NULL, "received IDci2:");
1311                plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
1312        }
1313        if (iph2->id) {
1314                plog(LLV_DEBUG, LOCATION, NULL, "received IDcr2:");
1315                plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
1316        }
1317
1318        /* adjust buffer length for HASH */
1319        hbuf->l = tlen;
1320
1321        /* validate HASH(1) */
1322    {
1323        char *r_hash;
1324        vchar_t *my_hash = NULL;
1325        int result;
1326
1327        r_hash = (caddr_t)hash + sizeof(*hash);
1328
1329        plog(LLV_DEBUG, LOCATION, NULL, "HASH(1) validate:");
1330        plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
1331
1332        my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
1333        if (my_hash == NULL)
1334                goto end;
1335
1336        result = memcmp(my_hash->v, r_hash, my_hash->l);
1337        vfree(my_hash);
1338
1339        if (result) {
1340                plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
1341                        "HASH(1) mismatch.\n");
1342                error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1343                goto end;
1344        }
1345    }
1346
1347        /* get sainfo */
1348        error = get_sainfo_r(iph2);
1349        if (error) {
1350                plog(LLV_ERROR, LOCATION, NULL,
1351                        "failed to get sainfo.\n");
1352                goto end;
1353        }
1354
1355
1356        /* check the existence of ID payload and create responder's proposal */
1357        error = get_proposal_r(iph2);
1358        switch (error) {
1359        case -2:
1360                /* generate a policy template from peer's proposal */
1361                if (set_proposal_from_proposal(iph2)) {
1362                        plog(LLV_ERROR, LOCATION, NULL,
1363                                "failed to generate a proposal template "
1364                                "from client's proposal.\n");
1365                        error = ISAKMP_INTERNAL_ERROR;
1366                        goto end;
1367                }
1368                /*FALLTHROUGH*/
1369        case 0:
1370                /* select single proposal or reject it. */
1371                if (ipsecdoi_selectph2proposal(iph2) < 0) {
1372                        plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1373                                "no proposal chosen.\n");
1374                        error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1375                        goto end;
1376                }
1377                break;
1378        default:
1379                plog(LLV_ERROR, LOCATION, NULL,
1380                        "failed to get proposal for responder.\n");
1381                goto end;
1382        }
1383
1384        /* check KE and attribute of PFS */
1385        if (iph2->dhpub_p != NULL && iph2->approval->pfs_group == 0) {
1386                plog(LLV_ERROR, LOCATION, NULL,
1387                        "no PFS is specified, but peer sends KE.\n");
1388                error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1389                goto end;
1390        }
1391        if (iph2->dhpub_p == NULL && iph2->approval->pfs_group != 0) {
1392                plog(LLV_ERROR, LOCATION, NULL,
1393                        "PFS is specified, but peer doesn't sends KE.\n");
1394                error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1395                goto end;
1396        }
1397
1398        /*
1399         * save the packet from the initiator in order to resend the
1400         * responder's first packet against this packet.
1401         */
1402        iph2->msg1 = vdup(msg0);
1403
1404        /* change status of isakmp status entry */
1405        iph2->status = PHASE2ST_STATUS2;
1406
1407        error = 0;
1408
1409end:
1410        if (hbuf)
1411                vfree(hbuf);
1412        if (msg)
1413                vfree(msg);
1414        if (pbuf)
1415                vfree(pbuf);
1416
1417        if (error) {
1418                VPTRINIT(iph2->sa);
1419                VPTRINIT(iph2->nonce_p);
1420                VPTRINIT(iph2->dhpub_p);
1421                VPTRINIT(iph2->id);
1422                VPTRINIT(iph2->id_p);
1423#ifdef ENABLE_NATT
1424                if (iph2->natoa_src) {
1425                        racoon_free(iph2->natoa_src);
1426                        iph2->natoa_src = NULL;
1427                }
1428                if (iph2->natoa_dst) {
1429                        racoon_free(iph2->natoa_dst);
1430                        iph2->natoa_dst = NULL;
1431                }
1432#endif
1433        }
1434
1435        return error;
1436}
1437
1438/*
1439 * call pfkey_getspi.
1440 */
1441int
1442quick_r1prep(iph2, msg)
1443        struct ph2handle *iph2;
1444        vchar_t *msg;
1445{
1446        int error = ISAKMP_INTERNAL_ERROR;
1447
1448        /* validity check */
1449        if (iph2->status != PHASE2ST_STATUS2) {
1450                plog(LLV_ERROR, LOCATION, NULL,
1451                        "status mismatched %d.\n", iph2->status);
1452                goto end;
1453        }
1454
1455        iph2->status = PHASE2ST_GETSPISENT;
1456
1457        /* send getspi message */
1458        if (pk_sendgetspi(iph2) < 0)
1459                goto end;
1460
1461        plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
1462
1463        sched_schedule(&iph2->sce, lcconf->wait_ph2complete,
1464                       quick_timeover_stub);
1465
1466        error = 0;
1467
1468end:
1469        return error;
1470}
1471
1472/*
1473 * send to initiator
1474 *      HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
1475 */
1476int
1477quick_r2send(iph2, msg)
1478        struct ph2handle *iph2;
1479        vchar_t *msg;
1480{
1481        vchar_t *body = NULL;
1482        vchar_t *hash = NULL;
1483        struct isakmp_gen *gen;
1484        char *p;
1485        int tlen;
1486        int error = ISAKMP_INTERNAL_ERROR;
1487        int natoa = ISAKMP_NPTYPE_NONE;
1488        int pfsgroup;
1489        u_int8_t *np_p = NULL;
1490#ifdef ENABLE_NATT
1491        vchar_t *nat_oai = NULL;
1492        vchar_t *nat_oar = NULL;
1493#endif
1494
1495        /* validity check */
1496        if (msg != NULL) {
1497                plog(LLV_ERROR, LOCATION, NULL,
1498                        "msg has to be NULL in this function.\n");
1499                goto end;
1500        }
1501        if (iph2->status != PHASE2ST_GETSPIDONE) {
1502                plog(LLV_ERROR, LOCATION, NULL,
1503                        "status mismatched %d.\n", iph2->status);
1504                goto end;
1505        }
1506
1507        /* update responders SPI */
1508        if (ipsecdoi_updatespi(iph2) < 0) {
1509                plog(LLV_ERROR, LOCATION, NULL, "failed to update spi.\n");
1510                goto end;
1511        }
1512
1513        /* generate NONCE value */
1514        iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
1515        if (iph2->nonce == NULL)
1516                goto end;
1517
1518        /* generate KE value if need */
1519        pfsgroup = iph2->approval->pfs_group;
1520        if (iph2->dhpub_p != NULL && pfsgroup != 0) {
1521                /* DH group settting if PFS is required. */
1522                if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
1523                        plog(LLV_ERROR, LOCATION, NULL,
1524                                "failed to set DH value.\n");
1525                        goto end;
1526                }
1527                /* generate DH public value */
1528                if (oakley_dh_generate(iph2->pfsgrp,
1529                                &iph2->dhpub, &iph2->dhpriv) < 0) {
1530                        goto end;
1531                }
1532        }
1533
1534#ifdef ENABLE_NATT
1535        /*
1536         * RFC3947 5.2. if we chose UDP-Encapsulated-Transport
1537         * we should send NAT-OA
1538         */
1539        if (ipsecdoi_transportmode(iph2->proposal)
1540         && (iph2->ph1->natt_flags & NAT_DETECTED)) {
1541                natoa = iph2->ph1->natt_options->payload_nat_oa;
1542
1543                nat_oai = ipsecdoi_sockaddr2id(iph2->dst,
1544                        IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
1545                nat_oar = ipsecdoi_sockaddr2id(iph2->src,
1546                        IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
1547
1548                if (nat_oai == NULL || nat_oar == NULL) {
1549                        plog(LLV_ERROR, LOCATION, NULL,
1550                                "failed to generate NAT-OA payload.\n");
1551                        goto end;
1552                }
1553
1554                plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n");
1555                plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l);
1556                plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n");
1557                plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l);
1558        }
1559#endif
1560
1561        /* create SA;NONCE payload, and KE and ID if need */
1562        tlen = sizeof(*gen) + iph2->sa_ret->l
1563                + sizeof(*gen) + iph2->nonce->l;
1564        if (iph2->dhpub_p != NULL && pfsgroup != 0)
1565                tlen += (sizeof(*gen) + iph2->dhpub->l);
1566        if (iph2->id_p != NULL)
1567                tlen += (sizeof(*gen) + iph2->id_p->l
1568                        + sizeof(*gen) + iph2->id->l);
1569#ifdef ENABLE_NATT
1570        if (natoa != ISAKMP_NPTYPE_NONE)
1571                tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
1572#endif
1573
1574        body = vmalloc(tlen);
1575        if (body == NULL) {
1576                plog(LLV_ERROR, LOCATION, NULL,
1577                        "failed to get buffer to send.\n");
1578                goto end;
1579        }
1580        p = body->v;
1581
1582        /* make SA payload */
1583        p = set_isakmp_payload(body->v, iph2->sa_ret, ISAKMP_NPTYPE_NONCE);
1584
1585        /* add NONCE payload */
1586        np_p = &((struct isakmp_gen *)p)->np;   /* XXX */
1587        p = set_isakmp_payload(p, iph2->nonce,
1588                (iph2->dhpub_p != NULL && pfsgroup != 0)
1589                                ? ISAKMP_NPTYPE_KE
1590                                : (iph2->id_p != NULL
1591                                        ? ISAKMP_NPTYPE_ID
1592                                        : natoa));
1593
1594        /* add KE payload if need. */
1595        if (iph2->dhpub_p != NULL && pfsgroup != 0) {
1596                np_p = &((struct isakmp_gen *)p)->np;   /* XXX */
1597                p = set_isakmp_payload(p, iph2->dhpub,
1598                        (iph2->id_p == NULL)
1599                                ? natoa
1600                                : ISAKMP_NPTYPE_ID);
1601        }
1602
1603        /* add ID payloads received. */
1604        if (iph2->id_p != NULL) {
1605                /* IDci */
1606                p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
1607                /* IDcr */
1608                np_p = &((struct isakmp_gen *)p)->np;   /* XXX */
1609                p = set_isakmp_payload(p, iph2->id, natoa);
1610        }
1611
1612#ifdef ENABLE_NATT
1613        /* NAT-OA */
1614        if (natoa != ISAKMP_NPTYPE_NONE) {
1615                p = set_isakmp_payload(p, nat_oai, natoa);
1616                p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
1617        }
1618#endif
1619
1620        /* add a RESPONDER-LIFETIME notify payload if needed */
1621    {
1622        vchar_t *data = NULL;
1623        struct saprop *pp = iph2->approval;
1624        struct saproto *pr;
1625
1626        if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_SEC) {
1627                u_int32_t v = htonl((u_int32_t)pp->lifetime);
1628                data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
1629                                        IPSECDOI_ATTR_SA_LD_TYPE_SEC);
1630                if (!data)
1631                        goto end;
1632                data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
1633                                        (caddr_t)&v, sizeof(v));
1634                if (!data)
1635                        goto end;
1636        }
1637        if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_KB) {
1638                u_int32_t v = htonl((u_int32_t)pp->lifebyte);
1639                data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
1640                                        IPSECDOI_ATTR_SA_LD_TYPE_KB);
1641                if (!data)
1642                        goto end;
1643                data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
1644                                        (caddr_t)&v, sizeof(v));
1645                if (!data)
1646                        goto end;
1647        }
1648
1649        /*
1650         * XXX Is there only single RESPONDER-LIFETIME payload in a IKE message
1651         * in the case of SA bundle ?
1652         */
1653        if (data) {
1654                for (pr = pp->head; pr; pr = pr->next) {
1655                        body = isakmp_add_pl_n(body, &np_p,
1656                                        ISAKMP_NTYPE_RESPONDER_LIFETIME, pr, data);
1657                        if (!body) {
1658                                vfree(data);
1659                                return error;   /* XXX */
1660                        }
1661                }
1662                vfree(data);
1663        }
1664    }
1665
1666        /* generate HASH(2) */
1667    {
1668        vchar_t *tmp;
1669
1670        tmp = vmalloc(iph2->nonce_p->l + body->l);
1671        if (tmp == NULL) {
1672                plog(LLV_ERROR, LOCATION, NULL,
1673                        "failed to get hash buffer.\n");
1674                goto end;
1675        }
1676        memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
1677        memcpy(tmp->v + iph2->nonce_p->l, body->v, body->l);
1678
1679        hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, tmp);
1680        vfree(tmp);
1681
1682        if (hash == NULL)
1683                goto end;
1684    }
1685
1686        /* send isakmp payload */
1687        iph2->sendbuf = quick_ir1mx(iph2, body, hash);
1688        if (iph2->sendbuf == NULL)
1689                goto end;
1690
1691        /* send the packet, add to the schedule to resend */
1692        if (isakmp_ph2send(iph2) == -1)
1693                goto end;
1694
1695        /* the sending message is added to the received-list. */
1696        if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, iph2->msg1) == -1) {
1697                plog(LLV_ERROR , LOCATION, NULL,
1698                        "failed to add a response packet to the tree.\n");
1699                goto end;
1700        }
1701
1702        /* change status of isakmp status entry */
1703        iph2->status = PHASE2ST_MSG1SENT;
1704
1705        error = 0;
1706
1707end:
1708        if (body != NULL)
1709                vfree(body);
1710        if (hash != NULL)
1711                vfree(hash);
1712#ifdef ENABLE_NATT
1713        if (nat_oai != NULL)
1714                vfree(nat_oai);
1715        if (nat_oar != NULL)
1716                vfree(nat_oar);
1717#endif
1718
1719        return error;
1720}
1721
1722/*
1723 * receive from initiator
1724 *      HDR*, HASH(3)
1725
1726 */
1727int
1728quick_r3recv(iph2, msg0)
1729        struct ph2handle *iph2;
1730        vchar_t *msg0;
1731{
1732        vchar_t *msg = NULL;
1733        vchar_t *pbuf = NULL;   /* for payload parsing */
1734        struct isakmp_parse_t *pa;
1735        struct isakmp_pl_hash *hash = NULL;
1736        int error = ISAKMP_INTERNAL_ERROR;
1737
1738        /* validity check */
1739        if (iph2->status != PHASE2ST_MSG1SENT) {
1740                plog(LLV_ERROR, LOCATION, NULL,
1741                        "status mismatched %d.\n", iph2->status);
1742                goto end;
1743        }
1744
1745        /* decrypt packet */
1746        if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1747                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1748                        "Packet wasn't encrypted.\n");
1749                goto end;
1750        }
1751        msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
1752        if (msg == NULL)
1753                goto end;
1754
1755        /* validate the type of next payload */
1756        pbuf = isakmp_parse(msg);
1757        if (pbuf == NULL)
1758                goto end;
1759
1760        for (pa = (struct isakmp_parse_t *)pbuf->v;
1761             pa->type != ISAKMP_NPTYPE_NONE;
1762             pa++) {
1763
1764                switch (pa->type) {
1765                case ISAKMP_NPTYPE_HASH:
1766                        hash = (struct isakmp_pl_hash *)pa->ptr;
1767                        break;
1768                case ISAKMP_NPTYPE_N:
1769                        ph2_recv_n(iph2, pa->ptr);
1770                        break;
1771                default:
1772                        /* don't send information, see ident_r1recv() */
1773                        plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1774                                "ignore the packet, "
1775                                "received unexpecting payload type %d.\n",
1776                                pa->type);
1777                        goto end;
1778                }
1779        }
1780
1781        /* payload existency check */
1782        if (hash == NULL) {
1783                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1784                        "few isakmp message received.\n");
1785                goto end;
1786        }
1787
1788        /* validate HASH(3) */
1789        /* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
1790    {
1791        char *r_hash;
1792        vchar_t *my_hash = NULL;
1793        vchar_t *tmp = NULL;
1794        int result;
1795
1796        r_hash = (char *)hash + sizeof(*hash);
1797
1798        plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) validate:");
1799        plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
1800
1801        tmp = vmalloc(iph2->nonce_p->l + iph2->nonce->l);
1802        if (tmp == NULL) {
1803                plog(LLV_ERROR, LOCATION, NULL,
1804                        "failed to get hash buffer.\n");
1805                goto end;
1806        }
1807        memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
1808        memcpy(tmp->v + iph2->nonce_p->l, iph2->nonce->v, iph2->nonce->l);
1809
1810        my_hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
1811        vfree(tmp);
1812        if (my_hash == NULL)
1813                goto end;
1814
1815        result = memcmp(my_hash->v, r_hash, my_hash->l);
1816        vfree(my_hash);
1817
1818        if (result) {
1819                plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
1820                        "HASH(3) mismatch.\n");
1821                error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1822                goto end;
1823        }
1824    }
1825
1826        /* if there is commit bit, don't set up SA now. */
1827        if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
1828                iph2->status = PHASE2ST_COMMIT;
1829        } else
1830                iph2->status = PHASE2ST_STATUS6;
1831
1832        error = 0;
1833
1834end:
1835        if (pbuf != NULL)
1836                vfree(pbuf);
1837        if (msg != NULL)
1838                vfree(msg);
1839
1840        return error;
1841}
1842
1843/*
1844 * send to initiator
1845 *      HDR#*, HASH(4), notify
1846 */
1847int
1848quick_r3send(iph2, msg0)
1849        struct ph2handle *iph2;
1850        vchar_t *msg0;
1851{
1852        vchar_t *buf = NULL;
1853        vchar_t *myhash = NULL;
1854        struct isakmp_pl_n *n;
1855        vchar_t *notify = NULL;
1856        char *p;
1857        int tlen;
1858        int error = ISAKMP_INTERNAL_ERROR;
1859
1860        /* validity check */
1861        if (iph2->status != PHASE2ST_COMMIT) {
1862                plog(LLV_ERROR, LOCATION, NULL,
1863                        "status mismatched %d.\n", iph2->status);
1864                goto end;
1865        }
1866
1867        /* generate HASH(4) */
1868        /* XXX What can I do in the case of multiple different SA */
1869        plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) generate\n");
1870
1871        /* XXX What should I do if there are multiple SAs ? */
1872        tlen = sizeof(struct isakmp_pl_n) + iph2->approval->head->spisize;
1873        notify = vmalloc(tlen);
1874        if (notify == NULL) {
1875                plog(LLV_ERROR, LOCATION, NULL,
1876                        "failed to get notify buffer.\n");
1877                goto end;
1878        }
1879        n = (struct isakmp_pl_n *)notify->v;
1880        n->h.np = ISAKMP_NPTYPE_NONE;
1881        n->h.len = htons(tlen);
1882        n->doi = htonl(IPSEC_DOI);
1883        n->proto_id = iph2->approval->head->proto_id;
1884        n->spi_size = sizeof(iph2->approval->head->spisize);
1885        n->type = htons(ISAKMP_NTYPE_CONNECTED);
1886        memcpy(n + 1, &iph2->approval->head->spi, iph2->approval->head->spisize);
1887
1888        myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
1889        if (myhash == NULL)
1890                goto end;
1891
1892        /* create buffer for isakmp payload */
1893        tlen = sizeof(struct isakmp)
1894                + sizeof(struct isakmp_gen) + myhash->l
1895                + notify->l;
1896        buf = vmalloc(tlen);
1897        if (buf == NULL) {
1898                plog(LLV_ERROR, LOCATION, NULL,
1899                        "failed to get buffer to send.\n");
1900                goto end;
1901        }
1902
1903        /* create isakmp header */
1904        p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
1905        if (p == NULL)
1906                goto end;
1907
1908        /* add HASH(4) payload */
1909        p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N);
1910
1911        /* add notify payload */
1912        memcpy(p, notify->v, notify->l);
1913
1914#ifdef HAVE_PRINT_ISAKMP_C
1915        isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
1916#endif
1917
1918        /* encoding */
1919        iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
1920        if (iph2->sendbuf == NULL)
1921                goto end;
1922
1923        /* send the packet */
1924        if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
1925                goto end;
1926
1927        /* the sending message is added to the received-list. */
1928        if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, msg0) == -1) {
1929                plog(LLV_ERROR , LOCATION, NULL,
1930                        "failed to add a response packet to the tree.\n");
1931                goto end;
1932        }
1933
1934        iph2->status = PHASE2ST_COMMIT;
1935
1936        error = 0;
1937
1938end:
1939        if (buf != NULL)
1940                vfree(buf);
1941        if (myhash != NULL)
1942                vfree(myhash);
1943        if (notify != NULL)
1944                vfree(notify);
1945
1946        return error;
1947}
1948
1949int
1950tunnel_mode_prop(p)
1951        struct saprop *p;
1952{
1953        struct saproto *pr;
1954
1955        for (pr = p->head; pr; pr = pr->next)
1956                if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL)
1957                        return 1;
1958        return 0;
1959}
1960
1961/*
1962 * set SA to kernel.
1963 */
1964int
1965quick_r3prep(iph2, msg0)
1966        struct ph2handle *iph2;
1967        vchar_t *msg0;
1968{
1969        int error = ISAKMP_INTERNAL_ERROR;
1970
1971        /* validity check */
1972        if (iph2->status != PHASE2ST_STATUS6) {
1973                plog(LLV_ERROR, LOCATION, NULL,
1974                        "status mismatched %d.\n", iph2->status);
1975                goto end;
1976        }
1977
1978        /* compute both of KEYMATs */
1979        if (oakley_compute_keymat(iph2, RESPONDER) < 0)
1980                goto end;
1981
1982        iph2->status = PHASE2ST_ADDSA;
1983        iph2->flags ^= ISAKMP_FLAG_C;   /* reset bit */
1984
1985        /* don't anything if local test mode. */
1986        if (f_local) {
1987                error = 0;
1988                goto end;
1989        }
1990
1991        /* Do UPDATE as responder */
1992        plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
1993        if (pk_sendupdate(iph2) < 0) {
1994                plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
1995                goto end;
1996        }
1997        plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
1998
1999        /* Do ADD for responder */
2000        if (pk_sendadd(iph2) < 0) {
2001                plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
2002                goto end;
2003        }
2004        plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
2005
2006        /*
2007         * set policies into SPD if the policy is generated
2008         * from peer's policy.
2009         */
2010        if (iph2->spidx_gen) {
2011
2012                struct policyindex *spidx;
2013                struct sockaddr_storage addr;
2014                u_int8_t pref;
2015                struct sockaddr *src = iph2->src;
2016                struct sockaddr *dst = iph2->dst;
2017
2018                /* make inbound policy */
2019                iph2->src = dst;
2020                iph2->dst = src;
2021                if (pk_sendspdupdate2(iph2) < 0) {
2022                        plog(LLV_ERROR, LOCATION, NULL,
2023                                "pfkey spdupdate2(inbound) failed.\n");
2024                        goto end;
2025                }
2026                plog(LLV_DEBUG, LOCATION, NULL,
2027                        "pfkey spdupdate2(inbound) sent.\n");
2028
2029                spidx = (struct policyindex *)iph2->spidx_gen;
2030#ifdef HAVE_POLICY_FWD
2031                /* make forward policy if required */
2032                if (tunnel_mode_prop(iph2->approval)) {
2033                        spidx->dir = IPSEC_DIR_FWD;
2034                        if (pk_sendspdupdate2(iph2) < 0) {
2035                                plog(LLV_ERROR, LOCATION, NULL,
2036                                        "pfkey spdupdate2(forward) failed.\n");
2037                                goto end;
2038                        }
2039                        plog(LLV_DEBUG, LOCATION, NULL,
2040                                "pfkey spdupdate2(forward) sent.\n");
2041                }
2042#endif
2043
2044                /* make outbound policy */
2045                iph2->src = src;
2046                iph2->dst = dst;
2047                spidx->dir = IPSEC_DIR_OUTBOUND;
2048                addr = spidx->src;
2049                spidx->src = spidx->dst;
2050                spidx->dst = addr;
2051                pref = spidx->prefs;
2052                spidx->prefs = spidx->prefd;
2053                spidx->prefd = pref;
2054
2055                if (pk_sendspdupdate2(iph2) < 0) {
2056                        plog(LLV_ERROR, LOCATION, NULL,
2057                                "pfkey spdupdate2(outbound) failed.\n");
2058                        goto end;
2059                }
2060                plog(LLV_DEBUG, LOCATION, NULL,
2061                        "pfkey spdupdate2(outbound) sent.\n");
2062
2063                /* spidx_gen is unnecessary any more */
2064                delsp_bothdir((struct policyindex *)iph2->spidx_gen);
2065                racoon_free(iph2->spidx_gen);
2066                iph2->spidx_gen = NULL;
2067                iph2->generated_spidx=1;
2068        }
2069
2070        error = 0;
2071
2072end:
2073        return error;
2074}
2075
2076/*
2077 * create HASH, body (SA, NONCE) payload with isakmp header.
2078 */
2079static vchar_t *
2080quick_ir1mx(iph2, body, hash)
2081        struct ph2handle *iph2;
2082        vchar_t *body, *hash;
2083{
2084        struct isakmp *isakmp;
2085        vchar_t *buf = NULL, *new = NULL;
2086        char *p;
2087        int tlen;
2088        struct isakmp_gen *gen;
2089        int error = ISAKMP_INTERNAL_ERROR;
2090
2091        /* create buffer for isakmp payload */
2092        tlen = sizeof(*isakmp)
2093                + sizeof(*gen) + hash->l
2094                + body->l;
2095        buf = vmalloc(tlen);
2096        if (buf == NULL) {
2097                plog(LLV_ERROR, LOCATION, NULL,
2098                        "failed to get buffer to send.\n");
2099                goto end;
2100        }
2101
2102        /* re-set encryption flag, for serurity. */
2103        iph2->flags |= ISAKMP_FLAG_E;
2104
2105        /* set isakmp header */
2106        p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
2107        if (p == NULL)
2108                goto end;
2109
2110        /* add HASH payload */
2111        /* XXX is next type always SA ? */
2112        p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_SA);
2113
2114        /* add body payload */
2115        memcpy(p, body->v, body->l);
2116
2117#ifdef HAVE_PRINT_ISAKMP_C
2118        isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
2119#endif
2120
2121        /* encoding */
2122        new = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
2123       
2124        if (new == NULL)
2125                goto end;
2126
2127        vfree(buf);
2128
2129        buf = new;
2130
2131        error = 0;
2132
2133end:
2134        if (error && buf != NULL) {
2135                vfree(buf);
2136                buf = NULL;
2137        }
2138
2139        return buf;
2140}
2141
2142/*
2143 * get remote's sainfo.
2144 * NOTE: this function is for responder.
2145 */
2146static int
2147get_sainfo_r(iph2)
2148        struct ph2handle *iph2;
2149{
2150        vchar_t *idsrc = NULL, *iddst = NULL, *client = NULL;
2151        int error = ISAKMP_INTERNAL_ERROR;
2152
2153        if (iph2->id == NULL) {
2154                idsrc = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
2155                                        IPSEC_ULPROTO_ANY);
2156        } else {
2157                idsrc = vdup(iph2->id);
2158        }
2159        if (idsrc == NULL) {
2160                plog(LLV_ERROR, LOCATION, NULL,
2161                        "failed to set ID for source.\n");
2162                goto end;
2163        }
2164
2165        if (iph2->id_p == NULL) {
2166                iddst = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
2167                                        IPSEC_ULPROTO_ANY);
2168        } else {
2169                iddst = vdup(iph2->id_p);
2170        }
2171        if (iddst == NULL) {
2172                plog(LLV_ERROR, LOCATION, NULL,
2173                        "failed to set ID for destination.\n");
2174                goto end;
2175        }
2176
2177#ifdef ENABLE_HYBRID
2178
2179        /* clientaddr check : obtain modecfg address */
2180        if (iph2->ph1->mode_cfg != NULL) {
2181                if ((iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
2182                    (iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)){
2183                        struct sockaddr saddr;
2184                        saddr.sa_family = AF_INET;
2185#ifndef __linux__
2186                        saddr.sa_len = sizeof(struct sockaddr_in);
2187#endif
2188                        ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
2189                        memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
2190                                &iph2->ph1->mode_cfg->addr4, sizeof(struct in_addr));
2191                        client = ipsecdoi_sockaddr2id(&saddr, 32, IPSEC_ULPROTO_ANY);
2192                }
2193        }
2194
2195        /* clientaddr check, fallback to peer address */
2196        if (client == NULL)
2197        {
2198                client = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
2199                                        IPSEC_ULPROTO_ANY);
2200        }
2201#endif
2202
2203        /* obtain a matching sainfo section */
2204        iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, client, iph2->ph1->rmconf->ph1id);
2205        if (iph2->sainfo == NULL) {
2206                plog(LLV_ERROR, LOCATION, NULL,
2207                        "failed to get sainfo.\n");
2208                goto end;
2209        }
2210
2211#ifdef ENABLE_HYBRID
2212        /* xauth group inclusion check */
2213        if (iph2->sainfo->group != NULL)
2214                if(group_check(iph2->ph1,&iph2->sainfo->group->v,1))
2215                        goto end;
2216#endif
2217
2218        plog(LLV_DEBUG, LOCATION, NULL,
2219                "selected sainfo: %s\n", sainfo2str(iph2->sainfo));
2220
2221        error = 0;
2222end:
2223        if (idsrc)
2224                vfree(idsrc);
2225        if (iddst)
2226                vfree(iddst);
2227        if (client)
2228                vfree(client);
2229
2230        return error;
2231}
2232
2233/*
2234 * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types
2235 * are IP address and same address family.
2236 * Then get remote's policy from SPD copied from kernel.
2237 * If the type of ID payload is address or subnet type, then the index is
2238 * made from the payload.  If there is no ID payload, or the type of ID
2239 * payload is NOT address type, then the index is made from the address
2240 * pair of phase 1.
2241 * NOTE: This function is only for responder.
2242 */
2243static int
2244get_proposal_r(iph2)
2245        struct ph2handle *iph2;
2246{
2247        struct policyindex spidx;
2248        struct secpolicy *sp_in, *sp_out;
2249        int idi2type = 0;       /* switch whether copy IDs into id[src,dst]. */
2250        int error = ISAKMP_INTERNAL_ERROR;
2251
2252        /* check the existence of ID payload */
2253        if ((iph2->id_p != NULL && iph2->id == NULL)
2254         || (iph2->id_p == NULL && iph2->id != NULL)) {
2255                plog(LLV_ERROR, LOCATION, NULL,
2256                        "Both IDs wasn't found in payload.\n");
2257                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2258        }
2259
2260        /* make sure if sa_[src, dst] are null. */
2261        if (iph2->sa_src || iph2->sa_dst) {
2262                plog(LLV_ERROR, LOCATION, NULL,
2263                        "Why do ID[src,dst] exist already.\n");
2264                return ISAKMP_INTERNAL_ERROR;
2265        }
2266
2267        memset(&spidx, 0, sizeof(spidx));
2268
2269#define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
2270
2271        /* make a spidx; a key to search SPD */
2272        spidx.dir = IPSEC_DIR_INBOUND;
2273        spidx.ul_proto = 0;
2274
2275        /*
2276         * make destination address in spidx from either ID payload
2277         * or phase 1 address into a address in spidx.
2278         */
2279        if (iph2->id != NULL
2280         && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
2281          || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
2282          || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
2283          || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
2284                /* get a destination address of a policy */
2285                error = ipsecdoi_id2sockaddr(iph2->id,
2286                                (struct sockaddr *)&spidx.dst,
2287                                &spidx.prefd, &spidx.ul_proto);
2288                if (error)
2289                        return error;
2290
2291#ifdef INET6
2292                /*
2293                 * get scopeid from the SA address.
2294                 * note that the phase 1 source address is used as
2295                 * a destination address to search for a inbound policy entry
2296                 * because rcoon is responder.
2297                 */
2298                if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
2299                        error = setscopeid((struct sockaddr *)&spidx.dst,
2300                                            iph2->src);
2301                        if (error)
2302                                return error;
2303                }
2304#endif
2305
2306                if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
2307                 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
2308                        idi2type = _XIDT(iph2->id);
2309
2310        } else {
2311
2312                plog(LLV_DEBUG, LOCATION, NULL,
2313                        "get a destination address of SP index "
2314                        "from phase1 address "
2315                        "due to no ID payloads found "
2316                        "OR because ID type is not address.\n");
2317
2318                /*
2319                 * copy the SOURCE address of IKE into the DESTINATION address
2320                 * of the key to search the SPD because the direction of policy
2321                 * is inbound.
2322                 */
2323                memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
2324                switch (spidx.dst.ss_family) {
2325                case AF_INET:
2326                        spidx.prefd = sizeof(struct in_addr) << 3;
2327                        break;
2328#ifdef INET6
2329                case AF_INET6:
2330                        spidx.prefd = sizeof(struct in6_addr) << 3;
2331                        break;
2332#endif
2333                default:
2334                        spidx.prefd = 0;
2335                        break;
2336                }
2337        }
2338
2339        /* make source address in spidx */
2340        if (iph2->id_p != NULL
2341         && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
2342          || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
2343          || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
2344          || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
2345                /* get a source address of inbound SA */
2346                error = ipsecdoi_id2sockaddr(iph2->id_p,
2347                                (struct sockaddr *)&spidx.src,
2348                                &spidx.prefs, &spidx.ul_proto);
2349                if (error)
2350                        return error;
2351
2352#ifdef INET6
2353                /*
2354                 * get scopeid from the SA address.
2355                 * for more detail, see above of this function.
2356                 */
2357                if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
2358                        error = setscopeid((struct sockaddr *)&spidx.src,
2359                                            iph2->dst);
2360                        if (error)
2361                                return error;
2362                }
2363#endif
2364
2365                /* Before setting iph2->[sa_src, sa_dst] with the addresses
2366                 * provided in ID payloads, we check:
2367                 * - they are both addresses of same family
2368                 * - sainfo has not been selected only based on ID payload
2369                 *   information but also based on specific Phase 1
2370                 *   credentials (iph2->sainfo->id_i is defined), i.e.
2371                 *   local configuration _explicitly_ expect that user
2372                 *   (e.g. from asn1dn "C=FR, ...") with those IDs) */
2373                if (_XIDT(iph2->id_p) == idi2type &&
2374                    spidx.dst.ss_family == spidx.src.ss_family &&
2375                    iph2->sainfo && iph2->sainfo->id_i) {
2376
2377                        iph2->sa_src = dupsaddr((struct sockaddr *)&spidx.dst);
2378                        if (iph2->sa_src  == NULL) {
2379                                plog(LLV_ERROR, LOCATION, NULL,
2380                                    "buffer allocation failed.\n");
2381                                return ISAKMP_INTERNAL_ERROR;
2382                        }
2383
2384                        iph2->sa_dst = dupsaddr((struct sockaddr *)&spidx.src);
2385                        if (iph2->sa_dst  == NULL) {
2386                                plog(LLV_ERROR, LOCATION, NULL,
2387                                    "buffer allocation failed.\n");
2388                                return ISAKMP_INTERNAL_ERROR;
2389                        }
2390                } else {
2391                        plog(LLV_DEBUG, LOCATION, NULL,
2392                             "Either family (%d - %d), types (%d - %d) of ID "
2393                             "from initiator differ or matching sainfo "
2394                             "has no id_i defined for the peer. Not filling "
2395                             "iph2->sa_src and iph2->sa_dst.\n",
2396                             spidx.src.ss_family, spidx.dst.ss_family,
2397                             _XIDT(iph2->id_p),idi2type);
2398                }
2399#ifdef ENABLE_NATT
2400                if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
2401                        u_int16_t port;
2402
2403                        port = extract_port(&spidx.src);
2404                        memcpy(&spidx.src, iph2->ph1->remote,
2405                            sysdep_sa_len(iph2->ph1->remote));
2406                        set_port(&spidx.src, port);
2407                        switch (spidx.src.ss_family) {
2408                        case AF_INET:
2409                                spidx.prefs = sizeof(struct in_addr) << 3;
2410                                break;
2411#ifdef INET6
2412                        case AF_INET6:
2413                                spidx.prefs = sizeof(struct in6_addr) << 3;
2414                                break;
2415#endif
2416                        default:
2417                                spidx.prefs = 0;
2418                                break;
2419                        }
2420                        plog(LLV_DEBUG, LOCATION,
2421                                NULL, "use NAT address %s as src\n",
2422                                saddr2str((struct sockaddr *)&spidx.src));
2423                }
2424#endif
2425        } else {
2426                plog(LLV_DEBUG, LOCATION, NULL,
2427                     "get a source address of SP index from Phase 1"
2428                     "addresses due to no ID payloads found"
2429                     "OR because ID type is not address.\n");
2430
2431                /* see above comment. */
2432                memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
2433                switch (spidx.src.ss_family) {
2434                case AF_INET:
2435                        spidx.prefs = sizeof(struct in_addr) << 3;
2436                        break;
2437#ifdef INET6
2438                case AF_INET6:
2439                        spidx.prefs = sizeof(struct in6_addr) << 3;
2440                        break;
2441#endif
2442                default:
2443                        spidx.prefs = 0;
2444                        break;
2445                }
2446        }
2447
2448#undef _XIDT
2449
2450        plog(LLV_DEBUG, LOCATION, NULL,
2451                "get src address from ID payload "
2452                "%s prefixlen=%u ul_proto=%u\n",
2453                saddr2str((struct sockaddr *)&spidx.src),
2454                spidx.prefs, spidx.ul_proto);
2455        plog(LLV_DEBUG, LOCATION, NULL,
2456                "get dst address from ID payload "
2457                "%s prefixlen=%u ul_proto=%u\n",
2458                saddr2str((struct sockaddr *)&spidx.dst),
2459                spidx.prefd, spidx.ul_proto);
2460
2461        /*
2462         * convert the ul_proto if it is 0
2463         * because 0 in ID payload means a wild card.
2464         */
2465        if (spidx.ul_proto == 0)
2466                spidx.ul_proto = IPSEC_ULPROTO_ANY;
2467
2468#ifdef HAVE_SECCTX
2469        /*
2470         * Need to use security context in spidx to ensure the correct
2471         * policy is selected. The only way to get the security context
2472         * is to look into the proposal sent by peer ahead of time.
2473         */
2474        if (get_security_context(iph2->sa, &spidx)) {
2475                plog(LLV_ERROR, LOCATION, NULL,
2476                     "error occurred trying to get security context.\n");
2477                return ISAKMP_INTERNAL_ERROR;
2478        }
2479#endif /* HAVE_SECCTX */
2480
2481        /* get inbound policy */
2482        sp_in = getsp_r(&spidx);
2483        if (sp_in == NULL) {
2484                if (iph2->ph1->rmconf->gen_policy) {
2485                        plog(LLV_INFO, LOCATION, NULL,
2486                                "no policy found, "
2487                                "try to generate the policy : %s\n",
2488                                spidx2str(&spidx));
2489                        iph2->spidx_gen = racoon_malloc(sizeof(spidx));
2490                        if (!iph2->spidx_gen) {
2491                                plog(LLV_ERROR, LOCATION, NULL,
2492                                        "buffer allocation failed.\n");
2493                                return ISAKMP_INTERNAL_ERROR;
2494                        }
2495                        memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
2496                        return -2;      /* special value */
2497                }
2498                plog(LLV_ERROR, LOCATION, NULL,
2499                        "no policy found: %s\n", spidx2str(&spidx));
2500                return ISAKMP_INTERNAL_ERROR;
2501        }
2502        /* Refresh existing generated policies
2503         */
2504        if (iph2->ph1->rmconf->gen_policy) {
2505                plog(LLV_INFO, LOCATION, NULL,
2506                         "Update the generated policy : %s\n",
2507                         spidx2str(&spidx));
2508                iph2->spidx_gen = racoon_malloc(sizeof(spidx));
2509                if (!iph2->spidx_gen) {
2510                        plog(LLV_ERROR, LOCATION, NULL,
2511                                 "buffer allocation failed.\n");
2512                        return ISAKMP_INTERNAL_ERROR;
2513                }
2514                memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
2515        }
2516
2517        /* get outbound policy */
2518    {
2519        struct sockaddr_storage addr;
2520        u_int8_t pref;
2521
2522        spidx.dir = IPSEC_DIR_OUTBOUND;
2523        addr = spidx.src;
2524        spidx.src = spidx.dst;
2525        spidx.dst = addr;
2526        pref = spidx.prefs;
2527        spidx.prefs = spidx.prefd;
2528        spidx.prefd = pref;
2529
2530        sp_out = getsp_r(&spidx);
2531        if (!sp_out) {
2532                plog(LLV_WARNING, LOCATION, NULL,
2533                        "no outbound policy found: %s\n",
2534                        spidx2str(&spidx));
2535        }
2536    }
2537
2538        plog(LLV_DEBUG, LOCATION, NULL,
2539                "suitable SP found:%s\n", spidx2str(&spidx));
2540
2541        /*
2542         * In the responder side, the inbound policy should be using IPsec.
2543         * outbound policy is not checked currently.
2544         */
2545        if (sp_in->policy != IPSEC_POLICY_IPSEC) {
2546                plog(LLV_ERROR, LOCATION, NULL,
2547                        "policy found, but no IPsec required: %s\n",
2548                        spidx2str(&spidx));
2549                return ISAKMP_INTERNAL_ERROR;
2550        }
2551
2552        /* set new proposal derived from a policy into the iph2->proposal. */
2553        if (set_proposal_from_policy(iph2, sp_in, sp_out) < 0) {
2554                plog(LLV_ERROR, LOCATION, NULL,
2555                        "failed to create saprop.\n");
2556                return ISAKMP_INTERNAL_ERROR;
2557        }
2558
2559#ifdef HAVE_SECCTX
2560        if (spidx.sec_ctx.ctx_str) {
2561                set_secctx_in_proposal(iph2, spidx);
2562        }
2563#endif /* HAVE_SECCTX */
2564
2565        iph2->spid = sp_in->id;
2566
2567        return 0;
2568}
2569
2570/*
2571 * handle a notification payload inside phase2 exchange.
2572 * phase2 is always encrypted, so it does not need to be checked
2573 * for explicitely.
2574 */
2575static int
2576ph2_recv_n(iph2, gen)
2577        struct ph2handle *iph2;
2578        struct isakmp_gen *gen;
2579{
2580        struct ph1handle *iph1 = iph2->ph1;
2581        struct isakmp_pl_n *notify = (struct isakmp_pl_n *) gen;
2582        u_int type;
2583        int check_level;
2584
2585        type = ntohs(notify->type);
2586        switch (type) {
2587        case ISAKMP_NTYPE_CONNECTED:
2588                break;
2589        case ISAKMP_NTYPE_INITIAL_CONTACT:
2590                return isakmp_info_recv_initialcontact(iph1, iph2);
2591        case ISAKMP_NTYPE_RESPONDER_LIFETIME:
2592                ipsecdoi_parse_responder_lifetime(notify,
2593                        &iph2->lifetime_secs, &iph2->lifetime_kb);
2594
2595                if (iph1 != NULL && iph1->rmconf != NULL) {
2596                        check_level = iph1->rmconf->pcheck_level;
2597                } else {
2598                        if (iph1 != NULL)
2599                                plog(LLV_DEBUG, LOCATION, NULL,
2600                                        "No phase1 rmconf found !\n");
2601                        else
2602                                plog(LLV_DEBUG, LOCATION, NULL,
2603                                        "No phase1 found !\n");
2604                        check_level = PROP_CHECK_EXACT;
2605                }
2606
2607                switch (check_level) {
2608                case PROP_CHECK_OBEY:
2609                        break;
2610                case PROP_CHECK_STRICT:
2611                case PROP_CHECK_CLAIM:
2612                        if (iph2->sainfo == NULL
2613                         || iph2->sainfo->lifetime <= iph2->lifetime_secs) {
2614                                plog(LLV_WARNING, LOCATION, NULL,
2615                                        "RESPONDER-LIFETIME: lifetime mismatch\n");
2616                                iph2->lifetime_secs = 0;
2617                        }
2618                        break;
2619                case PROP_CHECK_EXACT:
2620                        if (iph2->sainfo == NULL
2621                         || iph2->sainfo->lifetime != iph2->lifetime_secs) {
2622                                plog(LLV_WARNING, LOCATION, NULL,
2623                                        "RESPONDER-LIFETIME: lifetime mismatch\n");
2624                                iph2->lifetime_secs = 0;
2625                        }
2626                        break;
2627                }
2628                break;
2629        default:
2630                isakmp_log_notify(iph2->ph1, notify, "phase2 exchange");
2631                isakmp_info_send_n2(iph2, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE,
2632                        NULL);
2633                break;
2634        }
2635        return 0;
2636}
2637
2638#ifdef __rtems__
2639#include "rtems-bsd-racoon-isakmp_quick-data.h"
2640#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.