1 /*        $NetBSD: handler.c,v 1.44 2025/03/08 16:39:08 christos Exp $          */
2 
3 /* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */
4 
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "config.h"
35 
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <time.h>
44 #include <errno.h>
45 
46 #include "var.h"
47 #include "misc.h"
48 #include "vmbuf.h"
49 #include "plog.h"
50 #include "sockmisc.h"
51 #include "debug.h"
52 
53 #ifdef ENABLE_HYBRID
54 #include <resolv.h>
55 #endif
56 
57 #include "schedule.h"
58 #include "grabmyaddr.h"
59 #include "algorithm.h"
60 #include "crypto_openssl.h"
61 #include "policy.h"
62 #include "proposal.h"
63 #include "isakmp_var.h"
64 #include "evt.h"
65 #include "isakmp.h"
66 #ifdef ENABLE_HYBRID
67 #include "isakmp_xauth.h"
68 #include "isakmp_cfg.h"
69 #endif
70 #include "isakmp_inf.h"
71 #include "oakley.h"
72 #include "str2val.h"
73 #include "remoteconf.h"
74 #include "localconf.h"
75 #include "handler.h"
76 #include "gcmalloc.h"
77 #include "nattraversal.h"
78 
79 #include "sainfo.h"
80 
81 #ifdef HAVE_GSSAPI
82 #include "gssapi.h"
83 #endif
84 
85 static LIST_HEAD(_ph1tree_, ph1handle) ph1tree;
86 static LIST_HEAD(_ph2tree_, ph2handle) ph2tree;
87 static LIST_HEAD(_ctdtree_, contacted) ctdtree;
88 static LIST_HEAD(_rcptree_, recvdpkt) rcptree;
89 static struct sched sc_sweep = SCHED_INITIALIZER();
90 
91 static void del_recvdpkt(struct recvdpkt *);
92 static void rem_recvdpkt(struct recvdpkt *);
93 
94 /*
95  * functions about management of the isakmp status table
96  */
97 /* %%% management phase 1 handler */
98 /*
99  * search for isakmpsa handler with isakmp index.
100  */
101 
102 /*
103  * Enumerate the Phase 1 tree.
104  * If enum_func() internally return a non-zero value,  this specific
105  * error value is returned. 0 is returned if everything went right.
106  *
107  * Note that it is ok for enum_func() to call insph1(). Those inserted
108  * Phase 1 will not interfere with current enumeration process.
109  */
110 int
enumph1(struct ph1selector * sel,int (* enum_func)(struct ph1handle * iph1,void * arg),void * enum_arg)111 enumph1(struct ph1selector *sel,
112     int (* enum_func)(struct ph1handle *iph1, void *arg), void *enum_arg)
113 {
114           struct ph1handle *p;
115           int ret;
116 
117           LIST_FOREACH(p, &ph1tree, chain) {
118                     if (sel != NULL) {
119                               if (sel->local != NULL &&
120                                   cmpsaddr(sel->local, p->local) > CMPSADDR_WILDPORT_MATCH)
121                                         continue;
122 
123                               if (sel->remote != NULL &&
124                                   cmpsaddr(sel->remote, p->remote) > CMPSADDR_WILDPORT_MATCH)
125                                         continue;
126                     }
127 
128                     if ((ret = enum_func(p, enum_arg)) != 0)
129                               return ret;
130           }
131 
132           return 0;
133 }
134 
135 struct ph1handle *
getph1byindex(isakmp_index * index)136 getph1byindex(isakmp_index *index)
137 {
138           struct ph1handle *p;
139 
140           LIST_FOREACH(p, &ph1tree, chain) {
141                     if (p->status >= PHASE1ST_EXPIRED)
142                               continue;
143                     if (memcmp(&p->index, index, sizeof(*index)) == 0)
144                               return p;
145           }
146 
147           return NULL;
148 }
149 
150 
151 /*
152  * search for isakmp handler by i_ck in index.
153  */
154 struct ph1handle *
getph1byindex0(isakmp_index * index)155 getph1byindex0(isakmp_index *index)
156 {
157           struct ph1handle *p;
158 
159           LIST_FOREACH(p, &ph1tree, chain) {
160                     if (p->status >= PHASE1ST_EXPIRED)
161                               continue;
162                     if (memcmp(&p->index, index, sizeof(cookie_t)) == 0)
163                               return p;
164           }
165 
166           return NULL;
167 }
168 
169 /*
170  * search for isakmpsa handler by source and remote address.
171  * don't use port number to search because this function search
172  * with phase 2's destinaion.
173  */
174 struct ph1handle *
getph1(struct ph1handle * ph1hint,struct sockaddr * local,struct sockaddr * remote,int flags)175 getph1(struct ph1handle *ph1hint, struct sockaddr *local,
176     struct sockaddr *remote, int flags)
177 {
178           struct ph1handle *p;
179 
180           plog(LLV_DEBUG2, LOCATION, NULL, "getph1: start\n");
181           plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local));
182           plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote));
183 
184           LIST_FOREACH(p, &ph1tree, chain) {
185                     if (p->status >= PHASE1ST_DYING)
186                               continue;
187 
188                     plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local));
189                     plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote));
190 
191                     if ((flags & GETPH1_F_ESTABLISHED) &&
192                         (p->status != PHASE1ST_ESTABLISHED)) {
193                               plog(LLV_DEBUG2, LOCATION, NULL,
194                                    "status %d, skipping\n", p->status);
195                               continue;
196                     }
197 
198                     if (local != NULL && cmpsaddr(local, p->local) == CMPSADDR_MISMATCH)
199                               continue;
200 
201                     if (remote != NULL && cmpsaddr(remote, p->remote) == CMPSADDR_MISMATCH)
202                               continue;
203 
204                     if (ph1hint != NULL) {
205                               if (ph1hint->id && ph1hint->id->l && p->id && p->id->l &&
206                                   (ph1hint->id->l != p->id->l ||
207                                    memcmp(ph1hint->id->v, p->id->v, p->id->l) != 0)) {
208                                         plog(LLV_DEBUG2, LOCATION, NULL,
209                                              "local identity does not match hint\n");
210                                         continue;
211                               }
212                               if (ph1hint->id_p && ph1hint->id_p->l &&
213                                   p->id_p && p->id_p->l &&
214                                   (ph1hint->id_p->l != p->id_p->l ||
215                                    memcmp(ph1hint->id_p->v, p->id_p->v, p->id_p->l) != 0)) {
216                                         plog(LLV_DEBUG2, LOCATION, NULL,
217                                              "remote identity does not match hint\n");
218                                         continue;
219                               }
220                     }
221 
222                     plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
223                     return p;
224           }
225 
226           plog(LLV_DEBUG2, LOCATION, NULL, "no match\n");
227 
228           return NULL;
229 }
230 
231 int
resolveph1rmconf(struct ph1handle * iph1)232 resolveph1rmconf(struct ph1handle *iph1)
233 {
234           struct remoteconf *rmconf;
235 
236           /* INITIATOR is always expected to know the exact rmconf. */
237           if (iph1->side == INITIATOR)
238                     return 0;
239 
240           rmconf = getrmconf_by_ph1(iph1);
241           if (rmconf == NULL)
242                     return -1;
243           if (rmconf == RMCONF_ERR_MULTIPLE)
244                     return 1;
245 
246           if (iph1->rmconf != NULL) {
247                     if (rmconf != iph1->rmconf) {
248                               plog(LLV_ERROR, LOCATION, NULL,
249                                    "unexpected rmconf switch; killing ph1\n");
250                               return -1;
251                     }
252           } else {
253                     iph1->rmconf = rmconf;
254           }
255 
256           return 0;
257 }
258 
259 
260 /*
261  * move phase2s from old_iph1 to new_iph1
262  */
263 void
migrate_ph12(struct ph1handle * old_iph1,struct ph1handle * new_iph1)264 migrate_ph12(struct ph1handle *old_iph1, struct ph1handle *new_iph1)
265 {
266           struct ph2handle *p, *next;
267 
268           /* Relocate phase2s to better phase1s or request a new phase1. */
269           for (p = LIST_FIRST(&old_iph1->ph2tree); p; p = next) {
270                     next = LIST_NEXT(p, ph1bind);
271 
272                     if (p->status != PHASE2ST_ESTABLISHED)
273                               continue;
274 
275                     unbindph12(p);
276                     bindph12(new_iph1, p);
277           }
278 }
279 
280 /*
281  * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1
282  */
migrate_dying_ph12(struct ph1handle * iph1)283 void migrate_dying_ph12(struct ph1handle *iph1)
284 {
285           struct ph1handle *p;
286 
287           LIST_FOREACH(p, &ph1tree, chain) {
288                     if (p == iph1)
289                               continue;
290                     if (p->status < PHASE1ST_DYING)
291                               continue;
292 
293                     if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH
294                      && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH)
295                               migrate_ph12(p, iph1);
296           }
297 }
298 
299 
300 /*
301  * dump isakmp-sa
302  */
303 vchar_t *
dumpph1()304 dumpph1()
305 {
306           struct ph1handle *iph1;
307           struct ph1dump *pd;
308           int cnt = 0;
309           vchar_t *buf;
310 
311           /* get length of buffer */
312           LIST_FOREACH(iph1, &ph1tree, chain)
313                     cnt++;
314 
315           buf = vmalloc(cnt * sizeof(struct ph1dump));
316           if (buf == NULL) {
317                     plog(LLV_ERROR, LOCATION, NULL,
318                               "failed to get buffer\n");
319                     return NULL;
320           }
321           pd = (struct ph1dump *)buf->v;
322 
323           LIST_FOREACH(iph1, &ph1tree, chain) {
324                     memcpy(&pd->index, &iph1->index, sizeof(iph1->index));
325                     pd->status = iph1->status;
326                     pd->side = iph1->side;
327                     memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote));
328                     memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local));
329                     pd->version = iph1->version;
330                     pd->etype = iph1->etype;
331                     pd->created = iph1->created;
332                     pd->ph2cnt = iph1->ph2cnt;
333                     pd++;
334           }
335 
336           return buf;
337 }
338 
339 /*
340  * create new isakmp Phase 1 status record to handle isakmp in Phase1
341  */
342 struct ph1handle *
newph1()343 newph1()
344 {
345           struct ph1handle *iph1;
346 
347           /* create new iph1 */
348           iph1 = racoon_calloc(1, sizeof(*iph1));
349           if (iph1 == NULL)
350                     return NULL;
351 
352           iph1->status = PHASE1ST_SPAWN;
353 
354 #ifdef ENABLE_DPD
355           iph1->dpd_support = 0;
356           iph1->dpd_seq = 0;
357           iph1->dpd_fails = 0;
358 #endif
359           evt_list_init(&iph1->evt_listeners);
360 
361           return iph1;
362 }
363 
364 /*
365  * delete new isakmp Phase 1 status record to handle isakmp in Phase1
366  */
367 void
delph1(struct ph1handle * iph1)368 delph1(struct ph1handle *iph1)
369 {
370           if (iph1 == NULL)
371                     return;
372 
373           /* SA down shell script hook */
374           script_hook(iph1, SCRIPT_PHASE1_DOWN);
375           evt_list_cleanup(&iph1->evt_listeners);
376 
377 #ifdef ENABLE_NATT
378           if (iph1->natt_flags & NAT_KA_QUEUED)
379                     natt_keepalive_remove (iph1->local, iph1->remote);
380 
381           if (iph1->natt_options) {
382                     racoon_free(iph1->natt_options);
383                     iph1->natt_options = NULL;
384           }
385 #endif
386 
387 #ifdef ENABLE_HYBRID
388           if (iph1->mode_cfg)
389                     isakmp_cfg_rmstate(iph1);
390 #endif
391 
392 #ifdef ENABLE_DPD
393           sched_cancel(&iph1->dpd_r_u);
394 #endif
395           sched_cancel(&iph1->sce);
396           sched_cancel(&iph1->scr);
397 
398           if (iph1->remote) {
399                     racoon_free(iph1->remote);
400                     iph1->remote = NULL;
401           }
402           if (iph1->local) {
403                     racoon_free(iph1->local);
404                     iph1->local = NULL;
405           }
406           if (iph1->approval) {
407                     delisakmpsa(iph1->approval);
408                     iph1->approval = NULL;
409           }
410 
411           VPTRINIT(iph1->authstr);
412           VPTRINIT(iph1->sendbuf);
413           VPTRINIT(iph1->dhpriv);
414           VPTRINIT(iph1->dhpub);
415           VPTRINIT(iph1->dhpub_p);
416           VPTRINIT(iph1->dhgxy);
417           VPTRINIT(iph1->nonce);
418           VPTRINIT(iph1->nonce_p);
419           VPTRINIT(iph1->skeyid);
420           VPTRINIT(iph1->skeyid_d);
421           VPTRINIT(iph1->skeyid_a);
422           VPTRINIT(iph1->skeyid_e);
423           VPTRINIT(iph1->key);
424           VPTRINIT(iph1->hash);
425           VPTRINIT(iph1->sig);
426           VPTRINIT(iph1->sig_p);
427           VPTRINIT(iph1->cert);
428           VPTRINIT(iph1->cert_p);
429           VPTRINIT(iph1->crl_p);
430           VPTRINIT(iph1->cr_p);
431           VPTRINIT(iph1->id);
432           VPTRINIT(iph1->id_p);
433 
434           if(iph1->approval != NULL)
435                     delisakmpsa(iph1->approval);
436 
437           if (iph1->ivm) {
438                     oakley_delivm(iph1->ivm);
439                     iph1->ivm = NULL;
440           }
441 
442           VPTRINIT(iph1->sa);
443           VPTRINIT(iph1->sa_ret);
444 
445 #ifdef HAVE_GSSAPI
446           VPTRINIT(iph1->gi_i);
447           VPTRINIT(iph1->gi_r);
448 
449           gssapi_free_state(iph1);
450 #endif
451 
452           racoon_free(iph1);
453 }
454 
455 /*
456  * create new isakmp Phase 1 status record to handle isakmp in Phase1
457  */
458 int
insph1(struct ph1handle * iph1)459 insph1(struct ph1handle *iph1)
460 {
461           /* validity check */
462           if (iph1->remote == NULL) {
463                     plog(LLV_ERROR, LOCATION, NULL,
464                               "invalid isakmp SA handler. no remote address.\n");
465                     return -1;
466           }
467           LIST_INSERT_HEAD(&ph1tree, iph1, chain);
468 
469           return 0;
470 }
471 
472 void
remph1(struct ph1handle * iph1)473 remph1(struct ph1handle *iph1)
474 {
475           LIST_REMOVE(iph1, chain);
476 }
477 
478 /*
479  * flush isakmp-sa
480  */
481 void
flushph1()482 flushph1()
483 {
484           struct ph1handle *p, *next;
485 
486           for (p = LIST_FIRST(&ph1tree); p; p = next) {
487                     next = LIST_NEXT(p, chain);
488 
489                     /* send delete information */
490                     if (p->status >= PHASE1ST_ESTABLISHED)
491                               isakmp_info_send_d1(p);
492 
493                     remph1(p);
494                     delph1(p);
495           }
496 }
497 
498 void
initph1tree()499 initph1tree()
500 {
501           LIST_INIT(&ph1tree);
502 }
503 
504 int
ph1_rekey_enabled(struct ph1handle * iph1)505 ph1_rekey_enabled(struct ph1handle *iph1)
506 {
507           if (iph1->rmconf == NULL)
508                     return 0;
509           if (iph1->rmconf->rekey == REKEY_FORCE)
510                     return 1;
511 #ifdef ENABLE_DPD
512           if (iph1->rmconf->rekey == REKEY_ON && iph1->dpd_support &&
513               iph1->rmconf->dpd_interval)
514                     return 1;
515 #endif
516           return 0;
517 }
518 
519 /* %%% management phase 2 handler */
520 
521 int
enumph2(struct ph2selector * sel,int (* enum_func)(struct ph2handle * ph2,void * arg),void * enum_arg)522 enumph2(struct ph2selector *sel,
523     int (*enum_func)(struct ph2handle *ph2, void *arg), void *enum_arg)
524 {
525           struct ph2handle *p;
526           int ret;
527 
528           LIST_FOREACH(p, &ph2tree, chain) {
529                     if (sel != NULL) {
530                               if (sel->spid != 0 && sel->spid != p->spid)
531                                         continue;
532 
533                               if (sel->src != NULL &&
534                                   cmpsaddr(sel->src, p->src) != CMPSADDR_MATCH)
535                                         continue;
536 
537                               if (sel->dst != NULL &&
538                                   cmpsaddr(sel->dst, p->dst) != CMPSADDR_MATCH)
539                                         continue;
540                     }
541 
542                     if ((ret = enum_func(p, enum_arg)) != 0)
543                               return ret;
544           }
545 
546           return 0;
547 }
548 
549 /*
550  * search ph2handle with sequence number.
551  */
552 struct ph2handle *
getph2byseq(uint32_t seq)553 getph2byseq(uint32_t seq)
554 {
555           struct ph2handle *p;
556 
557           LIST_FOREACH(p, &ph2tree, chain) {
558                     if (p->seq == seq)
559                               return p;
560           }
561 
562           return NULL;
563 }
564 
565 /*
566  * search ph2handle with message id.
567  */
568 struct ph2handle *
getph2bymsgid(struct ph1handle * iph1,uint32_t msgid)569 getph2bymsgid(struct ph1handle *iph1, uint32_t msgid)
570 {
571           struct ph2handle *p;
572 
573           LIST_FOREACH(p, &iph1->ph2tree, ph1bind) {
574                     if (p->msgid == msgid && p->ph1 == iph1)
575                               return p;
576           }
577 
578           return NULL;
579 }
580 
581 /* Note that src and dst are not the selectors of the SP
582  * but the source and destination addresses used for
583  * for SA negotiation (best example is tunnel mode SA
584  * where src and dst are the endpoints). There is at most
585  * a unique match because racoon does not support bundles
586  * which makes that there is at most a single established
587  * SA for a given spid. One could say that src and dst
588  * are in fact useless ...
589  */
590 struct ph2handle *
getph2byid(struct sockaddr * src,struct sockaddr * dst,uint32_t spid)591 getph2byid(struct sockaddr *src, struct sockaddr *dst, uint32_t spid)
592 {
593           struct ph2handle *p, *next;
594 
595           for (p = LIST_FIRST(&ph2tree); p; p = next) {
596                     next = LIST_NEXT(p, chain);
597 
598                     if (spid == p->spid &&
599                         cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
600                         cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH){
601                               /* Sanity check to detect zombie handlers
602                                * XXX Sould be done "somewhere" more interesting,
603                                * because we have lots of getph2byxxxx(), but this one
604                                * is called by pk_recvacquire(), so is the most important.
605                                */
606                               if(p->status < PHASE2ST_ESTABLISHED &&
607                                  p->retry_counter == 0
608                                  && p->sce.func == NULL && p->scr.func == NULL) {
609                                         plog(LLV_DEBUG, LOCATION, NULL,
610                                                    "Zombie ph2 found, expiring it\n");
611                                         isakmp_ph2expire(p);
612                               }else
613                                         return p;
614                     }
615           }
616 
617           return NULL;
618 }
619 
620 struct ph2handle *
getph2bysaddr(struct sockaddr * src,struct sockaddr * dst)621 getph2bysaddr(struct sockaddr *src, struct sockaddr *dst)
622 {
623           struct ph2handle *p;
624 
625           LIST_FOREACH(p, &ph2tree, chain) {
626                     if (cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
627                         cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH)
628                               return p;
629           }
630 
631           return NULL;
632 }
633 
634 /*
635  * call by pk_recvexpire().
636  */
637 /*ARGSUSED*/
638 struct ph2handle *
getph2bysaidx(struct sockaddr * src __unused,struct sockaddr * dst __unused,u_int proto_id,uint32_t spi)639 getph2bysaidx(struct sockaddr *src __unused, struct sockaddr *dst __unused,
640     u_int proto_id, uint32_t spi)
641 {
642           struct ph2handle *iph2;
643           struct saproto *pr;
644 
645           LIST_FOREACH(iph2, &ph2tree, chain) {
646                     if (iph2->proposal == NULL && iph2->approval == NULL)
647                               continue;
648                     if (iph2->approval != NULL) {
649                               for (pr = iph2->approval->head; pr != NULL;
650                                    pr = pr->next) {
651                                         if (proto_id != pr->proto_id)
652                                                   break;
653                                         if (spi == pr->spi || spi == pr->spi_p)
654                                                   return iph2;
655                               }
656                     } else if (iph2->proposal != NULL) {
657                               for (pr = iph2->proposal->head; pr != NULL;
658                                    pr = pr->next) {
659                                         if (proto_id != pr->proto_id)
660                                                   break;
661                                         if (spi == pr->spi)
662                                                   return iph2;
663                               }
664                     }
665           }
666 
667           return NULL;
668 }
669 
670 /*
671  * create new isakmp Phase 2 status record to handle isakmp in Phase2
672  */
673 struct ph2handle *
newph2()674 newph2()
675 {
676           struct ph2handle *iph2 = NULL;
677 
678           /* create new iph2 */
679           iph2 = racoon_calloc(1, sizeof(*iph2));
680           if (iph2 == NULL)
681                     return NULL;
682 
683           iph2->status = PHASE1ST_SPAWN;
684           evt_list_init(&iph2->evt_listeners);
685 
686           return iph2;
687 }
688 
689 /*
690  * initialize ph2handle
691  * NOTE: don't initialize src/dst.
692  *       SPI in the proposal is cleared.
693  */
694 void
initph2(struct ph2handle * iph2)695 initph2(struct ph2handle *iph2)
696 {
697           evt_list_cleanup(&iph2->evt_listeners);
698           unbindph12(iph2);
699 
700           sched_cancel(&iph2->sce);
701           sched_cancel(&iph2->scr);
702 
703           VPTRINIT(iph2->sendbuf);
704           VPTRINIT(iph2->msg1);
705 
706           /* clear spi, keep variables in the proposal */
707           if (iph2->proposal) {
708                     struct saproto *pr;
709                     for (pr = iph2->proposal->head; pr != NULL; pr = pr->next)
710                               pr->spi = 0;
711           }
712 
713           /* clear approval */
714           if (iph2->approval) {
715                     flushsaprop(iph2->approval);
716                     iph2->approval = NULL;
717           }
718 
719           /* clear the generated policy */
720           if (iph2->spidx_gen) {
721                     delsp_bothdir((struct policyindex *)iph2->spidx_gen);
722                     racoon_free(iph2->spidx_gen);
723                     iph2->spidx_gen = NULL;
724           }
725 
726           if (iph2->pfsgrp) {
727                     oakley_dhgrp_free(iph2->pfsgrp);
728                     iph2->pfsgrp = NULL;
729           }
730 
731           VPTRINIT(iph2->dhpriv);
732           VPTRINIT(iph2->dhpub);
733           VPTRINIT(iph2->dhpub_p);
734           VPTRINIT(iph2->dhgxy);
735           VPTRINIT(iph2->id);
736           VPTRINIT(iph2->id_p);
737           VPTRINIT(iph2->nonce);
738           VPTRINIT(iph2->nonce_p);
739           VPTRINIT(iph2->sa);
740           VPTRINIT(iph2->sa_ret);
741 
742           if (iph2->ivm) {
743                     oakley_delivm(iph2->ivm);
744                     iph2->ivm = NULL;
745           }
746 
747 #ifdef ENABLE_NATT
748           if (iph2->natoa_src) {
749                     racoon_free(iph2->natoa_src);
750                     iph2->natoa_src = NULL;
751           }
752           if (iph2->natoa_dst) {
753                     racoon_free(iph2->natoa_dst);
754                     iph2->natoa_dst = NULL;
755           }
756 #endif
757 }
758 
759 /*
760  * delete new isakmp Phase 2 status record to handle isakmp in Phase2
761  */
762 void
delph2(struct ph2handle * iph2)763 delph2(struct ph2handle *iph2)
764 {
765           initph2(iph2);
766 
767           if (iph2->src) {
768                     racoon_free(iph2->src);
769                     iph2->src = NULL;
770           }
771           if (iph2->dst) {
772                     racoon_free(iph2->dst);
773                     iph2->dst = NULL;
774           }
775           if (iph2->sa_src) {
776                     racoon_free(iph2->sa_src);
777                     iph2->sa_src = NULL;
778           }
779           if (iph2->sa_dst) {
780                     racoon_free(iph2->sa_dst);
781                     iph2->sa_dst = NULL;
782           }
783 #ifdef ENABLE_NATT
784           if (iph2->natoa_src) {
785                     racoon_free(iph2->natoa_src);
786                     iph2->natoa_src = NULL;
787           }
788           if (iph2->natoa_dst) {
789                     racoon_free(iph2->natoa_dst);
790                     iph2->natoa_dst = NULL;
791           }
792 #endif
793 
794           if (iph2->proposal) {
795                     flushsaprop(iph2->proposal);
796                     iph2->proposal = NULL;
797           }
798 
799           racoon_free(iph2);
800 }
801 
802 /*
803  * create new isakmp Phase 2 status record to handle isakmp in Phase2
804  */
805 int
insph2(struct ph2handle * iph2)806 insph2(struct ph2handle *iph2)
807 {
808           LIST_INSERT_HEAD(&ph2tree, iph2, chain);
809 
810           return 0;
811 }
812 
813 void
remph2(struct ph2handle * iph2)814 remph2(struct ph2handle *iph2)
815 {
816           unbindph12(iph2);
817           LIST_REMOVE(iph2, chain);
818 }
819 
820 void
initph2tree(void)821 initph2tree(void)
822 {
823           LIST_INIT(&ph2tree);
824 }
825 
826 void
flushph2()827 flushph2()
828 {
829           struct ph2handle *p, *next;
830 
831           plog(LLV_DEBUG2, LOCATION, NULL,
832                      "flushing all ph2 handlers...\n");
833 
834           for (p = LIST_FIRST(&ph2tree); p; p = next) {
835                     next = LIST_NEXT(p, chain);
836 
837                     /* send delete information */
838                     if (p->status == PHASE2ST_ESTABLISHED){
839                               plog(LLV_DEBUG2, LOCATION, NULL,
840                                          "got a ph2 handler to flush...\n");
841                               isakmp_info_send_d2(p);
842                     }else{
843                               plog(LLV_DEBUG2, LOCATION, NULL,
844                                          "skipping ph2 handler (state %d)\n", p->status);
845                     }
846 
847                     delete_spd(p, 0);
848                     remph2(p);
849                     delph2(p);
850           }
851 }
852 
853 /*
854  * Delete all Phase 2 handlers for this src/dst/proto.  This
855  * is used during INITIAL-CONTACT processing (so no need to
856  * send a message to the peer).
857  */
858 /*ARGSUSED*/
859 void
deleteallph2(struct sockaddr * src __unused,struct sockaddr * dst __unused,u_int proto_id)860 deleteallph2(struct sockaddr *src __unused, struct sockaddr *dst __unused,
861     u_int proto_id)
862 {
863           struct ph2handle *iph2, *next;
864           struct saproto *pr;
865 
866           for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) {
867                     next = LIST_NEXT(iph2, chain);
868                     if (iph2->proposal == NULL && iph2->approval == NULL)
869                               continue;
870                     if (iph2->approval != NULL) {
871                               for (pr = iph2->approval->head; pr != NULL;
872                                    pr = pr->next) {
873                                         if (proto_id == pr->proto_id)
874                                                   goto zap_it;
875                               }
876                     } else if (iph2->proposal != NULL) {
877                               for (pr = iph2->proposal->head; pr != NULL;
878                                    pr = pr->next) {
879                                         if (proto_id == pr->proto_id)
880                                                   goto zap_it;
881                               }
882                     }
883                     continue;
884  zap_it:
885                     remph2(iph2);
886                     delph2(iph2);
887           }
888 }
889 
890 /* %%% */
891 void
bindph12(struct ph1handle * iph1,struct ph2handle * iph2)892 bindph12(struct ph1handle *iph1, struct ph2handle *iph2)
893 {
894           unbindph12(iph2);
895 
896           iph2->ph1 = iph1;
897           iph1->ph2cnt++;
898           LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind);
899 }
900 
901 void
unbindph12(struct ph2handle * iph2)902 unbindph12(struct ph2handle *iph2)
903 {
904           if (iph2->ph1 != NULL) {
905                     LIST_REMOVE(iph2, ph1bind);
906                     iph2->ph1->ph2cnt--;
907                     iph2->ph1 = NULL;
908           }
909 }
910 
911 /* %%% management contacted list */
912 /*
913  * search contacted list.
914  */
915 struct contacted *
getcontacted(struct sockaddr * remote)916 getcontacted(struct sockaddr *remote)
917 {
918           struct contacted *p;
919 
920           LIST_FOREACH(p, &ctdtree, chain) {
921                     if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH)
922                               return p;
923           }
924 
925           return NULL;
926 }
927 
928 /*
929  * create new isakmp Phase 2 status record to handle isakmp in Phase2
930  */
931 int
inscontacted(struct sockaddr * remote)932 inscontacted(struct sockaddr *remote)
933 {
934           struct contacted *new;
935 
936           /* create new iph2 */
937           new = racoon_calloc(1, sizeof(*new));
938           if (new == NULL)
939                     return -1;
940 
941           new->remote = dupsaddr(remote);
942           if (new->remote == NULL) {
943                     plog(LLV_ERROR, LOCATION, NULL,
944                               "failed to allocate buffer.\n");
945                     racoon_free(new);
946                     return -1;
947           }
948 
949           LIST_INSERT_HEAD(&ctdtree, new, chain);
950 
951           return 0;
952 }
953 
954 void
remcontacted(struct sockaddr * remote)955 remcontacted(struct sockaddr *remote)
956 {
957           struct contacted *p, *next;
958 
959           for (p = LIST_FIRST(&ctdtree); p; p = next) {
960                     next = LIST_NEXT(p, chain);
961 
962                     if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH) {
963                               LIST_REMOVE(p, chain);
964                               racoon_free(p->remote);
965                               racoon_free(p);
966                               break;
967                     }
968           }
969 }
970 
971 void
initctdtree()972 initctdtree()
973 {
974           LIST_INIT(&ctdtree);
975 }
976 
977 /*
978  * check the response has been sent to the peer.  when not, simply reply
979  * the buffered packet to the peer.
980  * OUT:
981  *         0:       the packet is received at the first time.
982  *         1:       the packet was processed before.
983  *         2:       the packet was processed before, but the address mismatches.
984  *        -1:       error happened.
985  */
986 /*ARGSUSED*/
987 int
check_recvdpkt(struct sockaddr * remote,struct sockaddr * local __unused,vchar_t * rbuf)988 check_recvdpkt(struct sockaddr *remote, struct sockaddr *local __unused, vchar_t *rbuf)
989 {
990           vchar_t *hash;
991           struct recvdpkt *r;
992           struct timeval now, diff;
993           int len, s;
994 
995           hash = eay_md5_one(rbuf);
996           if (!hash) {
997                     plog(LLV_ERROR, LOCATION, NULL,
998                               "failed to allocate buffer.\n");
999                     return -1;
1000           }
1001 
1002           LIST_FOREACH(r, &rcptree, chain) {
1003                     if (memcmp(hash->v, r->hash->v, r->hash->l) == 0)
1004                               break;
1005           }
1006           vfree(hash);
1007 
1008           /* this is the first time to receive the packet */
1009           if (r == NULL)
1010                     return 0;
1011 
1012           /*
1013            * the packet was processed before, but the remote address mismatches.
1014            */
1015           if (cmpsaddr(remote, r->remote) != CMPSADDR_MATCH)
1016                     return 2;
1017 
1018           /*
1019            * it should not check the local address because the packet
1020            * may arrive at other interface.
1021            */
1022 
1023           /* check the previous time to send */
1024           sched_get_monotonic_time(&now);
1025           timersub(&now, &r->time_send, &diff);
1026           if (diff.tv_sec == 0) {
1027                     plog(LLV_WARNING, LOCATION, NULL,
1028                               "the packet retransmitted in a short time from %s\n",
1029                               saddr2str(remote));
1030                     /*XXX should it be error ? */
1031           }
1032 
1033           /* select the socket to be sent */
1034           s = myaddr_getfd(r->local);
1035           if (s == -1)
1036                     return -1;
1037 
1038           /* resend the packet if needed */
1039           len = sendfromto(s, r->sendbuf->v, r->sendbuf->l,
1040                               r->local, r->remote, lcconf->count_persend);
1041           if (len == -1) {
1042                     plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
1043                     return -1;
1044           }
1045 
1046           /* check the retry counter */
1047           r->retry_counter--;
1048           if (r->retry_counter <= 0) {
1049                     rem_recvdpkt(r);
1050                     del_recvdpkt(r);
1051                     plog(LLV_DEBUG, LOCATION, NULL,
1052                               "deleted the retransmission packet to %s.\n",
1053                               saddr2str(remote));
1054           } else
1055                     r->time_send = now;
1056 
1057           return 1;
1058 }
1059 
1060 /*
1061  * adding a hash of received packet into the received list.
1062  */
1063 int
add_recvdpkt(struct sockaddr * remote,struct sockaddr * local,vchar_t * sbuf,vchar_t * rbuf)1064 add_recvdpkt(struct sockaddr *remote, struct sockaddr *local, vchar_t *sbuf,
1065     vchar_t *rbuf)
1066 {
1067           struct recvdpkt *new = NULL;
1068 
1069           if (lcconf->retry_counter == 0) {
1070                     /* no need to add it */
1071                     return 0;
1072           }
1073 
1074           new = racoon_calloc(1, sizeof(*new));
1075           if (!new) {
1076                     plog(LLV_ERROR, LOCATION, NULL,
1077                               "failed to allocate buffer.\n");
1078                     return -1;
1079           }
1080 
1081           new->hash = eay_md5_one(rbuf);
1082           if (!new->hash) {
1083                     plog(LLV_ERROR, LOCATION, NULL,
1084                               "failed to allocate buffer.\n");
1085                     del_recvdpkt(new);
1086                     return -1;
1087           }
1088           new->remote = dupsaddr(remote);
1089           if (new->remote == NULL) {
1090                     plog(LLV_ERROR, LOCATION, NULL,
1091                               "failed to allocate buffer.\n");
1092                     del_recvdpkt(new);
1093                     return -1;
1094           }
1095           new->local = dupsaddr(local);
1096           if (new->local == NULL) {
1097                     plog(LLV_ERROR, LOCATION, NULL,
1098                               "failed to allocate buffer.\n");
1099                     del_recvdpkt(new);
1100                     return -1;
1101           }
1102           new->sendbuf = vdup(sbuf);
1103           if (new->sendbuf == NULL) {
1104                     plog(LLV_ERROR, LOCATION, NULL,
1105                               "failed to allocate buffer.\n");
1106                     del_recvdpkt(new);
1107                     return -1;
1108           }
1109 
1110           new->retry_counter = lcconf->retry_counter;
1111           sched_get_monotonic_time(&new->time_send);
1112 
1113           LIST_INSERT_HEAD(&rcptree, new, chain);
1114 
1115           return 0;
1116 }
1117 
1118 void
del_recvdpkt(struct recvdpkt * r)1119 del_recvdpkt(struct recvdpkt *r)
1120 {
1121           if (r->remote)
1122                     racoon_free(r->remote);
1123           if (r->local)
1124                     racoon_free(r->local);
1125           if (r->hash)
1126                     vfree(r->hash);
1127           if (r->sendbuf)
1128                     vfree(r->sendbuf);
1129           racoon_free(r);
1130 }
1131 
1132 void
rem_recvdpkt(struct recvdpkt * r)1133 rem_recvdpkt(struct recvdpkt *r)
1134 {
1135           LIST_REMOVE(r, chain);
1136 }
1137 
1138 /*ARGSUSED*/
1139 static void
sweep_recvdpkt(struct sched * dummy __unused)1140 sweep_recvdpkt(struct sched *dummy __unused)
1141 {
1142           struct recvdpkt *r, *next;
1143           struct timeval now, diff, sweep;
1144 
1145           sched_get_monotonic_time(&now);
1146 
1147           /* calculate sweep time; delete entries older than this */
1148           diff.tv_sec = lcconf->retry_counter * lcconf->retry_interval;
1149           diff.tv_usec = 0;
1150           timersub(&now, &diff, &sweep);
1151 
1152           for (r = LIST_FIRST(&rcptree); r; r = next) {
1153                     next = LIST_NEXT(r, chain);
1154 
1155                     if (timercmp(&r->time_send, &sweep, <)) {
1156                               rem_recvdpkt(r);
1157                               del_recvdpkt(r);
1158                     }
1159           }
1160 
1161           sched_schedule(&sc_sweep, diff.tv_sec, sweep_recvdpkt);
1162 }
1163 
1164 void
init_recvdpkt()1165 init_recvdpkt()
1166 {
1167           time_t lt = lcconf->retry_counter * lcconf->retry_interval;
1168 
1169           LIST_INIT(&rcptree);
1170 
1171           sched_schedule(&sc_sweep, lt, sweep_recvdpkt);
1172 }
1173 
1174 #ifdef ENABLE_HYBRID
1175 /*
1176  * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
1177  * This should be in isakmp_cfg.c but ph1tree being private, it must be there
1178  */
1179 int
exclude_cfg_addr(const struct sockaddr * addr)1180 exclude_cfg_addr(const struct sockaddr *addr)
1181 {
1182           struct ph1handle *p;
1183           const struct sockaddr_in *sin;
1184 
1185           LIST_FOREACH(p, &ph1tree, chain) {
1186                     if ((p->mode_cfg != NULL) &&
1187                         (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) &&
1188                         (addr->sa_family == AF_INET)) {
1189                               sin = (const struct sockaddr_in *)addr;
1190                               if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr)
1191                                         return 0;
1192                     }
1193           }
1194 
1195           return 1;
1196 }
1197 #endif
1198 
1199 
1200 
1201 /*
1202  * Reload conf code
1203  */
revalidate_ph2(struct ph2handle * iph2)1204 static int revalidate_ph2(struct ph2handle *iph2){
1205           struct sainfoalg *alg;
1206           int found, check_level;
1207           struct sainfo *sainfo;
1208           struct saprop *approval;
1209           struct ph1handle *iph1;
1210 
1211           /*
1212            * Get the new sainfo using values of the old one
1213            */
1214           if (iph2->sainfo != NULL) {
1215                     iph2->sainfo = getsainfo(iph2->sainfo->idsrc,
1216                                                     iph2->sainfo->iddst, iph2->sainfo->id_i,
1217                                                     NULL, iph2->sainfo->remoteid);
1218           }
1219           approval = iph2->approval;
1220           sainfo = iph2->sainfo;
1221 
1222           if (sainfo == NULL) {
1223                     /*
1224                      * Sainfo has been removed
1225                      */
1226                     plog(LLV_DEBUG, LOCATION, NULL,
1227                                "Reload: No sainfo for ph2\n");
1228                     return 0;
1229           }
1230 
1231           if (approval == NULL) {
1232                     /*
1233                      * XXX why do we have a NULL approval sometimes ???
1234                      */
1235                     plog(LLV_DEBUG, LOCATION, NULL,
1236                                "No approval found !\n");
1237                     return 0;
1238           }
1239 
1240           /*
1241            * Don't care about proposals, should we do something ?
1242            * We have to keep iph2->proposal valid at least for initiator,
1243            * for pk_sendgetspi()
1244            */
1245 
1246           plog(LLV_DEBUG, LOCATION, NULL, "active single bundle:\n");
1247           printsaprop0(LLV_DEBUG, approval);
1248 
1249           /*
1250            * Validate approval against sainfo
1251            * Note: we must have an updated ph1->rmconf before doing that,
1252            * we'll set check_level to EXACT if we don't have a ph1
1253            * XXX try tu find the new remote section to get the new check level ?
1254            * XXX lifebyte
1255            */
1256           if (iph2->ph1 != NULL)
1257                     iph1=iph2->ph1;
1258           else
1259                     iph1=getph1byaddr(iph2->src, iph2->dst, 0);
1260 
1261           if(iph1 != NULL && iph1->rmconf != NULL) {
1262                     check_level = iph1->rmconf->pcheck_level;
1263           } else {
1264                     if(iph1 != NULL)
1265                               plog(LLV_DEBUG, LOCATION, NULL, "No phase1 rmconf found !\n");
1266                     else
1267                               plog(LLV_DEBUG, LOCATION, NULL, "No phase1 found !\n");
1268                     check_level = PROP_CHECK_EXACT;
1269           }
1270 
1271           switch (check_level) {
1272           case PROP_CHECK_OBEY:
1273                     plog(LLV_DEBUG, LOCATION, NULL,
1274                                "Reload: OBEY for ph2, ok\n");
1275                     return 1;
1276 
1277           case PROP_CHECK_STRICT:
1278                     /* FALLTHROUGH */
1279           case PROP_CHECK_CLAIM:
1280                     if (sainfo->lifetime < approval->lifetime) {
1281                               plog(LLV_DEBUG, LOCATION, NULL,
1282                                          "Reload: lifetime mismatch\n");
1283                               return 0;
1284                     }
1285 
1286 #if 0
1287                     /* Lifebyte is deprecated, just ignore it
1288                      */
1289                     if (sainfo->lifebyte < approval->lifebyte) {
1290                               plog(LLV_DEBUG, LOCATION, NULL,
1291                                          "Reload: lifebyte mismatch\n");
1292                               return 0;
1293                     }
1294 #endif
1295 
1296                     if (sainfo->pfs_group &&
1297                        sainfo->pfs_group != approval->pfs_group) {
1298                               plog(LLV_DEBUG, LOCATION, NULL,
1299                                          "Reload: PFS group mismatch\n");
1300                               return 0;
1301                     }
1302                     break;
1303 
1304           case PROP_CHECK_EXACT:
1305                     if (sainfo->lifetime != approval->lifetime ||
1306 #if 0
1307                               /* Lifebyte is deprecated, just ignore it
1308                                */
1309                         sainfo->lifebyte != approval->lifebyte ||
1310 #endif
1311                         sainfo->pfs_group != iph2->approval->pfs_group) {
1312                               plog(LLV_DEBUG, LOCATION, NULL,
1313                                   "Reload: lifetime | pfs mismatch\n");
1314                               return 0;
1315                     }
1316                     break;
1317 
1318           default:
1319                     plog(LLV_DEBUG, LOCATION, NULL,
1320                                "Reload: Shouldn't be here !\n");
1321                     return 0;
1322           }
1323 
1324           for (alg = sainfo->algs[algclass_ipsec_auth]; alg; alg = alg->next) {
1325                     if (alg->alg == approval->head->head->authtype)
1326                               break;
1327           }
1328           if (alg == NULL) {
1329                     plog(LLV_DEBUG, LOCATION, NULL,
1330                                "Reload: alg == NULL (auth)\n");
1331                     return 0;
1332           }
1333 
1334           found = 0;
1335           for (alg = sainfo->algs[algclass_ipsec_enc];
1336               (found == 0 && alg != NULL); alg = alg->next) {
1337                     plog(LLV_DEBUG, LOCATION, NULL,
1338                                "Reload: next ph2 enc alg...\n");
1339 
1340                     if (alg->alg != approval->head->head->trns_id){
1341                               plog(LLV_DEBUG, LOCATION, NULL,
1342                                          "Reload: encmode mismatch (%d / %d)\n",
1343                                          alg->alg, approval->head->head->trns_id);
1344                               continue;
1345                     }
1346 
1347                     switch (check_level){
1348                     /* PROP_CHECK_STRICT cannot happen here */
1349                     case PROP_CHECK_EXACT:
1350                               if (alg->encklen != approval->head->head->encklen) {
1351                                         plog(LLV_DEBUG, LOCATION, NULL,
1352                                                    "Reload: enclen mismatch\n");
1353                                         continue;
1354                               }
1355                               break;
1356 
1357                     case PROP_CHECK_CLAIM:
1358                               /* FALLTHROUGH */
1359                     case PROP_CHECK_STRICT:
1360                               if (alg->encklen > approval->head->head->encklen) {
1361                                         plog(LLV_DEBUG, LOCATION, NULL,
1362                                                    "Reload: enclen mismatch\n");
1363                                         continue;
1364                               }
1365                               break;
1366 
1367                     default:
1368                               plog(LLV_ERROR, LOCATION, NULL,
1369                                   "unexpected check_level\n");
1370                               continue;
1371                     }
1372                     found = 1;
1373           }
1374 
1375           if (!found){
1376                     plog(LLV_DEBUG, LOCATION, NULL,
1377                                "Reload: No valid enc\n");
1378                     return 0;
1379           }
1380 
1381           /*
1382            * XXX comp
1383            */
1384           plog(LLV_DEBUG, LOCATION, NULL,
1385                      "Reload: ph2 check ok\n");
1386 
1387           return 1;
1388 }
1389 
1390 
1391 static void
remove_ph2(struct ph2handle * iph2)1392 remove_ph2(struct ph2handle *iph2)
1393 {
1394           uint32_t spis[2];
1395 
1396           if(iph2 == NULL)
1397                     return;
1398 
1399           plog(LLV_DEBUG, LOCATION, NULL,
1400                      "Deleting a Ph2...\n");
1401 
1402           if (iph2->status == PHASE2ST_ESTABLISHED)
1403                     isakmp_info_send_d2(iph2);
1404 
1405           if(iph2->approval != NULL && iph2->approval->head != NULL){
1406                     spis[0]=iph2->approval->head->spi;
1407                     spis[1]=iph2->approval->head->spi_p;
1408 
1409                     /* purge_ipsec_spi() will do all the work:
1410                      * - delete SPIs in kernel
1411                      * - delete generated SPD
1412                      * - unbind / rem / del ph2
1413                      */
1414                     purge_ipsec_spi(iph2->dst, iph2->approval->head->proto_id,
1415                                                             spis, 2);
1416           }else{
1417                     remph2(iph2);
1418                     delph2(iph2);
1419           }
1420 }
1421 
remove_ph1(struct ph1handle * iph1)1422 static void remove_ph1(struct ph1handle *iph1){
1423           struct ph2handle *iph2, *iph2_next;
1424 
1425           if(iph1 == NULL)
1426                     return;
1427 
1428           plog(LLV_DEBUG, LOCATION, NULL,
1429                      "Removing PH1...\n");
1430 
1431           if (iph1->status == PHASE1ST_ESTABLISHED ||
1432               iph1->status == PHASE1ST_DYING) {
1433                     for (iph2 = LIST_FIRST(&iph1->ph2tree); iph2; iph2 = iph2_next) {
1434                               iph2_next = LIST_NEXT(iph2, ph1bind);
1435                               remove_ph2(iph2);
1436                     }
1437                     isakmp_info_send_d1(iph1);
1438           }
1439           iph1->status = PHASE1ST_EXPIRED;
1440           /* directly call isakmp_ph1delete to avoid as possible a race
1441            * condition where we'll try to access iph1->rmconf after it has
1442            * freed
1443            */
1444           isakmp_ph1delete(iph1);
1445 }
1446 
1447 
revalidate_ph1tree_rmconf(void)1448 static int revalidate_ph1tree_rmconf(void)
1449 {
1450           struct ph1handle *p, *next;
1451           struct remoteconf *rmconf;
1452 
1453           for (p = LIST_FIRST(&ph1tree); p; p = next) {
1454                     next = LIST_NEXT(p, chain);
1455 
1456                     if (p->status >= PHASE1ST_EXPIRED)
1457                               continue;
1458                     if (p->rmconf == NULL)
1459                               continue;
1460 
1461                     rmconf = getrmconf_by_ph1(p);
1462                     if (rmconf == NULL || rmconf == RMCONF_ERR_MULTIPLE)
1463                               remove_ph1(p);
1464                     else
1465                               p->rmconf = rmconf;
1466           }
1467 
1468           return 1;
1469 }
1470 
revalidate_ph2tree(void)1471 static int revalidate_ph2tree(void){
1472           struct ph2handle *p, *next;
1473 
1474           for (p = LIST_FIRST(&ph2tree); p; p = next) {
1475                     next = LIST_NEXT(p, chain);
1476 
1477                     if (p->status == PHASE2ST_EXPIRED)
1478                               continue;
1479 
1480                     if(!revalidate_ph2(p)){
1481                               plog(LLV_DEBUG, LOCATION, NULL,
1482                                          "PH2 not validated, removing it\n");
1483                               remove_ph2(p);
1484                     }
1485           }
1486 
1487           return 1;
1488 }
1489 
1490 int
revalidate_ph12(void)1491 revalidate_ph12(void)
1492 {
1493 
1494           revalidate_ph1tree_rmconf();
1495           revalidate_ph2tree();
1496 
1497           return 1;
1498 }
1499 
1500 #ifdef ENABLE_HYBRID
1501 struct ph1handle *
getph1bylogin(char * login)1502 getph1bylogin(char *login)
1503 {
1504           struct ph1handle *p;
1505 
1506           LIST_FOREACH(p, &ph1tree, chain) {
1507                     if (p->mode_cfg == NULL)
1508                               continue;
1509                     if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0)
1510                               return p;
1511           }
1512 
1513           return NULL;
1514 }
1515 
1516 int
purgeph1bylogin(char * login)1517 purgeph1bylogin(char *login)
1518 {
1519           struct ph1handle *p, *next;
1520           int found = 0;
1521 
1522           for (p = LIST_FIRST(&ph1tree); p; p = next) {
1523                     next = LIST_NEXT(p, chain);
1524 
1525                     if (p->mode_cfg == NULL)
1526                               continue;
1527                     if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) {
1528                               if (p->status >= PHASE1ST_EXPIRED)
1529                                         continue;
1530 
1531                               if (p->status >= PHASE1ST_ESTABLISHED)
1532                                         isakmp_info_send_d1(p);
1533                               purge_remote(p);
1534                               found++;
1535                     }
1536           }
1537 
1538           return found;
1539 }
1540 #endif
1541