1 /*        $NetBSD: remoteconf.c,v 1.32 2025/03/08 16:39:08 christos Exp $       */
2 
3 /* Id: remoteconf.c,v 1.38 2006/05/06 15:52:44 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 #include <sys/queue.h>
40 
41 #include <netinet/in.h>
42 #include <netinet/in_systm.h>
43 #include <netinet/ip.h>
44 
45 #include PATH_IPSEC_H
46 
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <errno.h>
51 
52 #include "var.h"
53 #include "misc.h"
54 #include "vmbuf.h"
55 #include "plog.h"
56 #include "sockmisc.h"
57 #include "genlist.h"
58 #include "debug.h"
59 
60 #include "isakmp_var.h"
61 #ifdef ENABLE_HYBRID
62 #include "isakmp_xauth.h"
63 #endif
64 #include "isakmp.h"
65 #include "ipsec_doi.h"
66 #include "crypto_openssl.h"
67 #include "oakley.h"
68 #include "remoteconf.h"
69 #include "localconf.h"
70 #include "grabmyaddr.h"
71 #include "policy.h"
72 #include "proposal.h"
73 #include "vendorid.h"
74 #include "gcmalloc.h"
75 #include "strnames.h"
76 #include "algorithm.h"
77 #include "nattraversal.h"
78 #include "isakmp_frag.h"
79 #include "handler.h"
80 #include "genlist.h"
81 #include "rsalist.h"
82 
83 typedef TAILQ_HEAD(_rmtree, remoteconf) remoteconf_tailq_head_t;
84 static remoteconf_tailq_head_t rmtree, rmtree_save;
85 
86 /*
87  * Script hook names and script hook paths
88  */
89 const char *script_names[SCRIPT_MAX + 1] = {
90           "phase1_up", "phase1_down", "phase1_dead" };
91 
92 /*%%%*/
93 
94 int
rmconf_match_identity(struct remoteconf * rmconf,vchar_t * id_p)95 rmconf_match_identity(struct remoteconf *rmconf, vchar_t *id_p)
96 {
97           struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *) id_p->v;
98           struct sockaddr *sa;
99           caddr_t sa1, sa2;
100           vchar_t ident;
101           struct idspec *id;
102           struct genlist_entry *gpb;
103 
104           /* compare with the ID if specified. */
105           if (!genlist_next(rmconf->idvl_p, 0))
106                     return 0;
107 
108           for (id = genlist_next(rmconf->idvl_p, &gpb); id; id = genlist_next(0, &gpb)) {
109                     /* No ID specified in configuration, so it is ok */
110                     if (id->id == 0)
111                               return 0;
112 
113                     /* check the type of both IDs */
114                     if (id->idtype != doi2idtype(id_b->type))
115                               continue;  /* ID type mismatch */
116 
117                     /* compare defined ID with the ID sent by peer. */
118                     switch (id->idtype) {
119                     case IDTYPE_ASN1DN:
120                               ident.v = id_p->v + sizeof(*id_b);
121                               ident.l = id_p->l - sizeof(*id_b);
122                               if (eay_cmp_asn1dn(id->id, &ident) == 0)
123                                         return 0;
124                               break;
125                     case IDTYPE_ADDRESS:
126                               sa = (struct sockaddr *)id->id->v;
127                               sa2 = (caddr_t)(id_b + 1);
128                               switch (sa->sa_family) {
129                               case AF_INET:
130                                         if (id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
131                                                   continue;  /* ID value mismatch */
132                                         sa1 = (caddr_t) &((struct sockaddr_in *)sa)->sin_addr;
133                                         if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
134                                                   return 0;
135                                         break;
136 #ifdef INET6
137                               case AF_INET6:
138                                         if (id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
139                                                   continue;  /* ID value mismatch */
140                                         sa1 = (caddr_t) &((struct sockaddr_in6 *)sa)->sin6_addr;
141                                         if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
142                                                   return 0;
143                                         break;
144 #endif
145                               default:
146                                         break;
147                               }
148                               break;
149                     default:
150                               if (memcmp(id->id->v, id_b + 1, id->id->l) == 0)
151                                         return 0;
152                               break;
153                     }
154           }
155 
156           plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
157           if (rmconf->verify_identifier)
158                     return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
159 
160           return 0;
161 }
162 
163 static int
rmconf_match_etype_and_approval(struct remoteconf * rmconf,int etype,struct isakmpsa * approval)164 rmconf_match_etype_and_approval(struct remoteconf *rmconf, int etype,
165     struct isakmpsa *approval)
166 {
167           if (check_etypeok(rmconf, (void *) (intptr_t) etype) == 0)
168                     return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
169 
170           if (approval == NULL)
171                     return 0;
172 
173           if (etype == ISAKMP_ETYPE_AGG &&
174               approval->dh_group != rmconf->dh_group)
175                     return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
176 
177           if (checkisakmpsa(rmconf->pcheck_level, approval,
178                                 rmconf->proposal) == NULL)
179                     return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
180 
181           return 0;
182 }
183 
184 enum rmconf_match_t {
185           MATCH_NONE                    = 0,
186           MATCH_BASIC                   = 0x0000001,
187           MATCH_ADDRESS                 = 0x0000002,
188           MATCH_SA            = 0x0000004,
189           MATCH_IDENTITY                = 0x0000008,
190           MATCH_AUTH_IDENTITY = 0x0000010,
191 };
192 
193 static int
rmconf_match_type(struct rmconfselector * rmsel,struct remoteconf * rmconf)194 rmconf_match_type(struct rmconfselector *rmsel, struct remoteconf *rmconf)
195 {
196           int ret = MATCH_NONE, tmp;
197 
198           /* No match at all: unwanted anonymous */
199           if ((rmsel->flags & GETRMCONF_F_NO_ANONYMOUS) &&
200               rmconf->remote->sa_family == AF_UNSPEC){
201                     plog(LLV_DEBUG2, LOCATION, rmsel->remote,
202                          "Not matched: Anonymous conf.\n");
203                     return MATCH_NONE;
204           }
205 
206           if ((rmsel->flags & GETRMCONF_F_NO_PASSIVE) && rmconf->passive){
207                     plog(LLV_DEBUG2, LOCATION, rmsel->remote,
208                          "Not matched: passive conf.\n");
209                     return MATCH_NONE;
210           }
211 
212           ret |= MATCH_BASIC;
213 
214           /* Check address */
215           if (rmsel->remote != NULL) {
216                     if (rmconf->remote->sa_family != AF_UNSPEC) {
217                               if (cmpsaddr(rmsel->remote, rmconf->remote) == CMPSADDR_MISMATCH){
218                                         plog(LLV_DEBUG2, LOCATION, rmsel->remote,
219                                              "Not matched: address mismatch.\n");
220                                         return MATCH_NONE;
221                               }
222 
223                               /* Address matched */
224                               ret |= MATCH_ADDRESS;
225                     }
226           }
227 
228           /* Check etype and approval */
229           if (rmsel->etype != ISAKMP_ETYPE_NONE) {
230                     tmp=rmconf_match_etype_and_approval(rmconf, rmsel->etype,
231                                                                 rmsel->approval);
232                     if (tmp != 0){
233                               plog(LLV_DEBUG2, LOCATION, rmsel->remote,
234                                    "Not matched: etype (%d)/approval mismatch (%d).\n", rmsel->etype, tmp);
235                               return MATCH_NONE;
236                     }
237                     ret |= MATCH_SA;
238           }
239 
240           /* Check identity */
241           if (rmsel->identity != NULL && rmconf->verify_identifier) {
242                     if (rmconf_match_identity(rmconf, rmsel->identity) != 0){
243                               plog(LLV_DEBUG2, LOCATION, rmsel->remote,
244                                    "Not matched: identity mismatch.\n");
245                               return MATCH_NONE;
246                     }
247                     ret |= MATCH_IDENTITY;
248           }
249 
250           /* Check certificate request */
251           if (rmsel->certificate_request != NULL) {
252                     if (oakley_get_certtype(rmsel->certificate_request) !=
253                         oakley_get_certtype(rmconf->mycert)){
254                               plog(LLV_DEBUG2, LOCATION, rmsel->remote,
255                                    "Not matched: cert type mismatch.\n");
256                               return MATCH_NONE;
257                     }
258 
259                     if (rmsel->certificate_request->l > 1) {
260                               vchar_t *issuer;
261 
262                               issuer = eay_get_x509asn1issuername(rmconf->mycert);
263                               if (rmsel->certificate_request->l - 1 != issuer->l ||
264                                   memcmp(rmsel->certificate_request->v + 1,
265                                            issuer->v, issuer->l) != 0) {
266                                         vfree(issuer);
267                                         plog(LLV_DEBUG2, LOCATION, rmsel->remote,
268                                              "Not matched: cert issuer mismatch.\n");
269                                         return MATCH_NONE;
270                               }
271                               vfree(issuer);
272                     } else {
273                               if (!rmconf->match_empty_cr){
274                                         plog(LLV_DEBUG2, LOCATION, rmsel->remote,
275                                              "Not matched: empty certificate request.\n");
276                                         return MATCH_NONE;
277                               }
278                     }
279 
280                     ret |= MATCH_AUTH_IDENTITY;
281           }
282 
283           return ret;
284 }
285 
286 void
rmconf_selector_from_ph1(struct rmconfselector * rmsel,struct ph1handle * iph1)287 rmconf_selector_from_ph1(struct rmconfselector *rmsel, struct ph1handle *iph1)
288 {
289           memset(rmsel, 0, sizeof(*rmsel));
290           rmsel->flags = 0;
291           rmsel->remote = iph1->remote;
292           rmsel->etype = iph1->etype;
293           rmsel->approval = iph1->approval;
294           rmsel->identity = iph1->id_p;
295           rmsel->certificate_request = iph1->cr_p;
296 }
297 
298 int
enumrmconf(struct rmconfselector * rmsel,int (* enum_func)(struct remoteconf *,void *),void * enum_arg)299 enumrmconf(struct rmconfselector *rmsel,
300     int (*enum_func)(struct remoteconf *, void *), void *enum_arg)
301 {
302           struct remoteconf *p;
303           int ret = 0;
304 
305           RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
306                     plog(LLV_DEBUG2, LOCATION, rmsel->remote,
307                          "Checking remote conf \"%s\" %s.\n", p->name,
308                          p->remote->sa_family == AF_UNSPEC ?
309                          "anonymous" : saddr2str(p->remote));
310 
311                     if (rmsel != NULL) {
312                               if (rmconf_match_type(rmsel, p) == MATCH_NONE){
313                                         plog(LLV_DEBUG2, LOCATION, rmsel->remote,
314                                              "Not matched.\n");
315                                         continue;
316                               }
317                     }
318 
319                     plog(LLV_DEBUG2, LOCATION, NULL,
320                          "enumrmconf: \"%s\" matches.\n", p->name);
321 
322                     ret = (*enum_func)(p, enum_arg);
323                     if (ret)
324                               break;
325           }
326 
327           return ret;
328 }
329 
330 struct rmconf_find_context {
331           struct rmconfselector sel;
332 
333           struct remoteconf *rmconf;
334           int match_type;
335           int num_found;
336 };
337 
338 static int
rmconf_find(struct remoteconf * rmconf,void * ctx)339 rmconf_find(struct remoteconf *rmconf, void *ctx)
340 {
341           struct rmconf_find_context *fctx = (struct rmconf_find_context *) ctx;
342           int match_type;
343 
344           /* First matching remote conf? */
345           match_type = rmconf_match_type(&fctx->sel, rmconf);
346 
347           if (fctx->rmconf != NULL) {
348                     /* More ambiguous matches are ignored. */
349                     if (match_type < fctx->match_type)
350                               return 0;
351 
352                     if (match_type == fctx->match_type) {
353                               /* Ambiguous match */
354                               fctx->num_found++;
355                               return 0;
356                     }
357           }
358 
359           /* More exact match found */
360           fctx->match_type = match_type;
361           fctx->num_found = 1;
362           fctx->rmconf = rmconf;
363 
364           return 0;
365 }
366 
367 /*
368  * search remote configuration.
369  * don't use port number to search if its value is either IPSEC_PORT_ANY.
370  * If matching anonymous entry, then new entry is copied from anonymous entry.
371  * If no anonymous entry found, then return NULL.
372  * OUT:   NULL:     NG
373  *        Other:    remote configuration entry.
374  */
375 
376 struct remoteconf *
getrmconf(struct sockaddr * remote,int flags)377 getrmconf(struct sockaddr *remote, int flags)
378 {
379           struct rmconf_find_context ctx;
380 
381           memset(&ctx, 0, sizeof(ctx));
382           ctx.sel.flags = flags;
383           ctx.sel.remote = remote;
384 
385           if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
386                     plog(LLV_ERROR, LOCATION, remote,
387                          "multiple exact configurations.\n");
388                     return NULL;
389           }
390 
391           if (ctx.rmconf == NULL) {
392                     plog(LLV_DEBUG, LOCATION, remote,
393                          "no remote configuration found.\n");
394                     return NULL;
395           }
396 
397           if (ctx.num_found != 1) {
398                     plog(LLV_DEBUG, LOCATION, remote,
399                          "multiple non-exact configurations found.\n");
400                     return NULL;
401           }
402 
403           plog(LLV_DEBUG, LOCATION, remote,
404                "configuration \"%s\" selected.\n",
405                ctx.rmconf->name);
406 
407           return ctx.rmconf;
408 }
409 
410 struct remoteconf *
getrmconf_by_ph1(struct ph1handle * iph1)411 getrmconf_by_ph1(struct ph1handle *iph1)
412 {
413           struct rmconf_find_context ctx;
414 
415           memset(&ctx, 0, sizeof(ctx));
416           rmconf_selector_from_ph1(&ctx.sel, iph1);
417           if (loglevel >= LLV_DEBUG) {
418                     char *idstr = NULL;
419 
420                     if (iph1->id_p != NULL)
421                               idstr = ipsecdoi_id2str(iph1->id_p);
422 
423                     plog(LLV_DEBUG, LOCATION, iph1->remote,
424                               "getrmconf_by_ph1: remote %s, identity %s.\n",
425                               saddr2str(iph1->remote), idstr ? idstr : "<any>");
426 
427                     if (idstr)
428                               racoon_free(idstr);
429           }
430 
431           if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
432                     plog(LLV_ERROR, LOCATION, iph1->remote,
433                          "multiple exact configurations.\n");
434                     return RMCONF_ERR_MULTIPLE;
435           }
436 
437           if (ctx.rmconf == NULL) {
438                     plog(LLV_DEBUG, LOCATION, iph1->remote,
439                          "no remote configuration found\n");
440                     return NULL;
441           }
442 
443           if (ctx.num_found != 1) {
444                     plog(LLV_DEBUG, LOCATION, iph1->remote,
445                          "multiple non-exact configurations found.\n");
446                     return RMCONF_ERR_MULTIPLE;
447           }
448 
449           plog(LLV_DEBUG, LOCATION, iph1->remote,
450                "configuration \"%s\" selected.\n",
451                ctx.rmconf->name);
452 
453           return ctx.rmconf;
454 }
455 
456 struct remoteconf *
getrmconf_by_name(const char * name)457 getrmconf_by_name(const char *name)
458 {
459           struct remoteconf *p;
460 
461           plog(LLV_DEBUG, LOCATION, NULL,
462                "getrmconf_by_name: remote \"%s\".\n",
463                name);
464 
465           RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
466                     if (p->name == NULL)
467                               continue;
468 
469                     if (strcmp(name, p->name) == 0)
470                               return p;
471           }
472 
473           return NULL;
474 }
475 
476 struct remoteconf *
newrmconf(void)477 newrmconf(void)
478 {
479           struct remoteconf *new;
480           int i;
481 
482           new = racoon_calloc(1, sizeof(*new));
483           if (new == NULL)
484                     return NULL;
485 
486           new->proposal = NULL;
487 
488           /* set default */
489           new->doitype = IPSEC_DOI;
490           new->sittype = IPSECDOI_SIT_IDENTITY_ONLY;
491           new->idvtype = IDTYPE_UNDEFINED;
492           new->idvl_p = genlist_init();
493           new->nonce_size = DEFAULT_NONCE_SIZE;
494           new->passive = FALSE;
495           new->ike_frag = FALSE;
496           new->esp_frag = IP_MAXPACKET;
497           new->ini_contact = TRUE;
498           new->mode_cfg = FALSE;
499           new->pcheck_level = PROP_CHECK_STRICT;
500           new->verify_identifier = FALSE;
501           new->verify_cert = TRUE;
502           new->cacertfile = NULL;
503           new->send_cert = TRUE;
504           new->send_cr = TRUE;
505           new->match_empty_cr = FALSE;
506           new->support_proxy = FALSE;
507           for (i = 0; i <= SCRIPT_MAX; i++)
508                     new->script[i] = NULL;
509           new->gen_policy = FALSE;
510           new->nat_traversal = FALSE;
511           new->rsa_private = genlist_init();
512           new->rsa_public = genlist_init();
513           new->idv = NULL;
514           new->key = NULL;
515 
516           new->dpd = TRUE; /* Enable DPD support by default */
517           new->dpd_interval = 0; /* Disable DPD checks by default */
518           new->dpd_retry = 5;
519           new->dpd_maxfails = 5;
520 
521           new->rekey = REKEY_ON;
522 
523           new->weak_phase1_check = 0;
524 
525 #ifdef ENABLE_HYBRID
526           new->xauth = NULL;
527 #endif
528 
529           new->lifetime = oakley_get_defaultlifetime();
530 
531           return new;
532 }
533 
534 static void *
dupidvl(void * entry,void * arg)535 dupidvl(void *entry, void *arg)
536 {
537           struct idspec *id;
538           struct idspec *old = (struct idspec *) entry;
539           id = newidspec();
540           if (!id) return (void *) -1;
541 
542           if (set_identifier(&id->id, old->idtype, old->id) != 0) {
543                     racoon_free(id);
544                     return (void *) -1;
545           }
546 
547           id->idtype = old->idtype;
548 
549           genlist_append(arg, id);
550           return NULL;
551 }
552 
553 static void *
duprsa(void * entry,void * arg)554 duprsa(void *entry, void *arg)
555 {
556           struct rsa_key *new;
557 
558           new = rsa_key_dup((struct rsa_key *)entry);
559           if (new == NULL)
560                     return (void *) -1;
561           genlist_append(arg, new);
562 
563           /* keep genlist_foreach going */
564           return NULL;
565 }
566 
567 /* Creates shallow copy of a remote config. Used for "inherit" keyword. */
568 struct remoteconf *
duprmconf_shallow(struct remoteconf * rmconf)569 duprmconf_shallow(struct remoteconf *rmconf)
570 {
571           struct remoteconf *new;
572 
573           new = racoon_calloc(1, sizeof(*new));
574           if (new == NULL)
575                     return NULL;
576 
577           memcpy(new, rmconf, sizeof(*new));
578           new->name = NULL;
579           new->inherited_from = rmconf;
580 
581           new->proposal = NULL; /* will be filled by set_isakmp_proposal() */
582 
583           /* Better to set remote to NULL to avoid that the destination
584            * rmconf uses the same allocated memory as the source rmconf.
585            */
586           new->remote = NULL;
587 
588           return new;
589 }
590 
591 /* Copies pointer structures of an inherited remote config.
592  * Used by "inherit" mechanism in a two step copy method, necessary to
593  * prevent both double free() and memory leak during config reload.
594  */
595 int
duprmconf_finish(struct remoteconf * new)596 duprmconf_finish(struct remoteconf *new)
597 {
598           struct remoteconf *rmconf;
599           int i;
600 
601           if (new->inherited_from == NULL)
602                     return 0; /* nothing todo, no inheritance */
603 
604           rmconf = new->inherited_from;
605 
606           /* duplicate dynamic structures unless value overridden */
607           if (new->etypes != NULL && new->etypes == rmconf->etypes)
608                     new->etypes = dupetypes(new->etypes);
609           if (new->idvl_p == rmconf->idvl_p) {
610                     new->idvl_p = genlist_init();
611                     genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
612           }
613 
614           if (new->rsa_private == rmconf->rsa_private) {
615                     new->rsa_private = genlist_init();
616                     genlist_foreach(rmconf->rsa_private, duprsa, new->rsa_private);
617           }
618           if (new->rsa_public == rmconf->rsa_public) {
619                     new->rsa_public = genlist_init();
620                     genlist_foreach(rmconf->rsa_public, duprsa, new->rsa_public);
621           }
622           if (new->remote != NULL && new->remote == rmconf->remote) {
623                     new->remote = racoon_malloc(sizeof(*new->remote));
624                     if (new->remote == NULL) {
625                               plog(LLV_ERROR, LOCATION, NULL,
626                                   "duprmconf_finish: malloc failed (remote)\n");
627                               exit(1);
628                     }
629                     memcpy(new->remote, rmconf->remote, sizeof(*new->remote));
630           }
631           if (new->spspec != NULL && new->spspec == rmconf->spspec) {
632                     dupspspec_list(new, rmconf);
633           }
634 
635           /* proposal has been deep copied already from spspec's, see
636            * cfparse.y:set_isakmp_proposal, which in turn calls
637            * cfparse.y:expand_isakmpspec where the copying happens.
638            */
639 
640 #ifdef ENABLE_HYBRID
641           if (new->xauth != NULL && new->xauth == rmconf->xauth) {
642                     new->xauth = xauth_rmconf_dup(new->xauth);
643                     if (new->xauth == NULL)
644                               exit(1);
645           }
646 #endif
647 
648         /* duplicate strings unless value overridden */
649           if (new->mycertfile != NULL && new->mycertfile == rmconf->mycertfile) {
650                     new->mycertfile = racoon_strdup(new->mycertfile);
651                     STRDUP_FATAL(new->mycertfile);
652           }
653           if (new->myprivfile != NULL && new->myprivfile == rmconf->myprivfile) {
654                     new->myprivfile = racoon_strdup(new->myprivfile);
655                     STRDUP_FATAL(new->myprivfile);
656           }
657           if (new->peerscertfile != NULL && new->peerscertfile == rmconf->peerscertfile) {
658                     new->peerscertfile = racoon_strdup(new->peerscertfile);
659                     STRDUP_FATAL(new->peerscertfile);
660           }
661           if (new->cacertfile != NULL && new->cacertfile == rmconf->cacertfile) {
662                     new->cacertfile = racoon_strdup(new->cacertfile);
663                     STRDUP_FATAL(new->cacertfile);
664           }
665           if (new->idv != NULL && new->idv == rmconf->idv) {
666                     new->idv = vdup(new->idv);
667                     STRDUP_FATAL(new->idv);
668           }
669           if (new->key != NULL && new->key == rmconf->key) {
670                     new->key = vdup(new->key);
671                     STRDUP_FATAL(new->key);
672           }
673           if (new->mycert != NULL && new->mycert == rmconf->mycert) {
674                     new->mycert = vdup(new->mycert);
675                     STRDUP_FATAL(new->mycert);
676           }
677           if (new->peerscert != NULL && new->peerscert == rmconf->peerscert) {
678                     new->peerscert = vdup(new->peerscert);
679                     STRDUP_FATAL(new->peerscert);
680           }
681           if (new->cacert != NULL && new->cacert == rmconf->cacert) {
682                     new->cacert = vdup(new->cacert);
683                     STRDUP_FATAL(new->cacert);
684           }
685           for (i = 0; i <= SCRIPT_MAX; i++)
686                     if (new->script[i] != NULL && new->script[i] == rmconf->script[i]) {
687                               new->script[i] = vdup(new->script[i]);
688                               STRDUP_FATAL(new->script[i]);
689                     }
690 
691           return 0;
692 }
693 
694 static void
idspec_free(void * data)695 idspec_free(void *data)
696 {
697           vfree (((struct idspec *)data)->id);
698           free (data);
699 }
700 
701 void
delrmconf(struct remoteconf * rmconf)702 delrmconf(struct remoteconf *rmconf)
703 {
704           int i;
705 
706           if (rmconf == NULL)
707                     return;
708 
709 #ifdef ENABLE_HYBRID
710           if (rmconf->xauth)
711                     xauth_rmconf_delete(&rmconf->xauth);
712 #endif
713           if (rmconf->etypes){
714                     deletypes(rmconf->etypes);
715                     rmconf->etypes=NULL;
716           }
717           if (rmconf->idv)
718                     vfree(rmconf->idv);
719           if (rmconf->key)
720                     vfree(rmconf->key);
721           if (rmconf->idvl_p)
722                     genlist_free(rmconf->idvl_p, idspec_free);
723           if (rmconf->dhgrp)
724                     oakley_dhgrp_free(rmconf->dhgrp);
725           if (rmconf->proposal)
726                     delisakmpsa(rmconf->proposal);
727           flushspspec(rmconf);
728           if (rmconf->mycert)
729                     vfree(rmconf->mycert);
730           if (rmconf->mycertfile)
731                     racoon_free(rmconf->mycertfile);
732           if (rmconf->myprivfile)
733                     racoon_free(rmconf->myprivfile);
734           if (rmconf->peerscert)
735                     vfree(rmconf->peerscert);
736           if (rmconf->peerscertfile)
737                     racoon_free(rmconf->peerscertfile);
738           if (rmconf->cacert)
739                     vfree(rmconf->cacert);
740           if (rmconf->cacertfile)
741                     racoon_free(rmconf->cacertfile);
742           if (rmconf->rsa_private)
743                     genlist_free(rmconf->rsa_private, rsa_key_free);
744           if (rmconf->rsa_public)
745                     genlist_free(rmconf->rsa_public, rsa_key_free);
746           if (rmconf->name)
747                     racoon_free(rmconf->name);
748           if (rmconf->remote)
749                     racoon_free(rmconf->remote);
750           for (i = 0; i <= SCRIPT_MAX; i++)
751                     if (rmconf->script[i])
752                               vfree(rmconf->script[i]);
753 
754           racoon_free(rmconf);
755 }
756 
757 void
delisakmpsa(struct isakmpsa * sa)758 delisakmpsa(struct isakmpsa *sa)
759 {
760           if (sa->dhgrp)
761                     oakley_dhgrp_free(sa->dhgrp);
762           if (sa->next)
763                     delisakmpsa(sa->next);
764 #ifdef HAVE_GSSAPI
765           if (sa->gssid)
766                     vfree(sa->gssid);
767 #endif
768           racoon_free(sa);
769 }
770 
771 struct etypes *
dupetypes(struct etypes * orig)772 dupetypes(struct etypes *orig)
773 {
774           struct etypes *new;
775 
776           if (!orig)
777                     return NULL;
778 
779           new = racoon_malloc(sizeof(struct etypes));
780           if (new == NULL)
781                     return NULL;
782 
783           new->type = orig->type;
784           new->next = NULL;
785 
786           if (orig->next)
787                     new->next=dupetypes(orig->next);
788 
789           return new;
790 }
791 
792 void
deletypes(struct etypes * e)793 deletypes(struct etypes *e)
794 {
795           if (e->next)
796                     deletypes(e->next);
797           racoon_free(e);
798 }
799 
800 /*
801  * insert into head of list.
802  */
803 void
insrmconf(struct remoteconf * new)804 insrmconf(struct remoteconf *new)
805 {
806           if (new->name == NULL) {
807                     new->name = racoon_strdup(saddr2str(new->remote));
808           }
809           if (new->remote == NULL) {
810                     new->remote = newsaddr(sizeof(struct sockaddr));
811                     new->remote->sa_family = AF_UNSPEC;
812           }
813 
814           TAILQ_INSERT_HEAD(&rmtree, new, chain);
815 }
816 
817 void
remrmconf(struct remoteconf * rmconf)818 remrmconf(struct remoteconf *rmconf)
819 {
820           TAILQ_REMOVE(&rmtree, rmconf, chain);
821 }
822 
823 void
flushrmconf(void)824 flushrmconf(void)
825 {
826           struct remoteconf *p, *next;
827 
828           for (p = TAILQ_FIRST(&rmtree); p; p = next) {
829                     next = TAILQ_NEXT(p, chain);
830                     remrmconf(p);
831                     delrmconf(p);
832           }
833 }
834 
835 void
initrmconf(void)836 initrmconf(void)
837 {
838           TAILQ_INIT(&rmtree);
839 }
840 
841 void
rmconf_start_reload(void)842 rmconf_start_reload(void)
843 {
844           rmtree_save=rmtree;
845           initrmconf();
846 }
847 
848 void
rmconf_finish_reload(void)849 rmconf_finish_reload(void)
850 {
851           remoteconf_tailq_head_t rmtree_tmp;
852 
853           rmtree_tmp=rmtree;
854           rmtree=rmtree_save;
855           flushrmconf();
856           initrmconf();
857           rmtree=rmtree_tmp;
858 }
859 
860 
861 
862 /* check exchange type to be acceptable */
863 int
check_etypeok(struct remoteconf * rmconf,void * ctx)864 check_etypeok(struct remoteconf *rmconf, void *ctx)
865 {
866           u_int8_t etype = (u_int8_t) (intptr_t) ctx;
867           struct etypes *e;
868 
869           for (e = rmconf->etypes; e != NULL; e = e->next) {
870                     if (e->type == etype)
871                               return 1;
872                     plog(LLV_DEBUG2, LOCATION, NULL,
873                          "Etype mismatch: got %d, expected %d.\n", e->type, etype);
874           }
875 
876           return 0;
877 }
878 
879 /*%%%*/
880 struct isakmpsa *
newisakmpsa(void)881 newisakmpsa(void)
882 {
883           struct isakmpsa *new;
884 
885           new = racoon_calloc(1, sizeof(*new));
886           if (new == NULL)
887                     return NULL;
888 
889           /*
890            * Just for sanity, make sure this is initialized.  This is
891            * filled in for real when the ISAKMP proposal is configured.
892            */
893           new->vendorid = VENDORID_UNKNOWN;
894 
895           new->next = NULL;
896 #ifdef HAVE_GSSAPI
897           new->gssid = NULL;
898 #endif
899 
900           return new;
901 }
902 
903 /*
904  * insert into tail of list.
905  */
906 void
insisakmpsa(struct isakmpsa * new,struct remoteconf * rmconf)907 insisakmpsa(struct isakmpsa *new, struct remoteconf *rmconf)
908 {
909           struct isakmpsa *p;
910 
911           if (rmconf->proposal == NULL) {
912                     rmconf->proposal = new;
913                     return;
914           }
915 
916           for (p = rmconf->proposal; p->next != NULL; p = p->next)
917                     ;
918           p->next = new;
919 }
920 
921 /*ARGSUSED*/
922 static void *
dump_peers_identifiers(void * entry,void * arg __unused)923 dump_peers_identifiers (void *entry, void *arg __unused)
924 {
925           struct idspec *id = (struct idspec*) entry;
926           char buf[1024], *pbuf;
927           pbuf = buf;
928           pbuf += sprintf (pbuf, "\tpeers_identifier %s",
929                                s_idtype (id->idtype));
930           if (id->id)
931                     pbuf += sprintf (pbuf, " \"%s\"", id->id->v);
932           plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
933           return NULL;
934 }
935 
936 /*ARGSUSED*/
937 static int
dump_rmconf_single(struct remoteconf * p,void * data __unused)938 dump_rmconf_single (struct remoteconf *p, void *data __unused)
939 {
940           struct etypes *etype = p->etypes;
941           struct isakmpsa *prop = p->proposal;
942           char buf[1024], *pbuf;
943 
944           pbuf = buf;
945 
946           pbuf += sprintf(pbuf, "remote \"%s\"", p->name);
947           if (p->inherited_from)
948                     pbuf += sprintf(pbuf, " inherit \"%s\"",
949                                         p->inherited_from->name);
950           plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf);
951           pbuf = buf;
952           pbuf += sprintf(pbuf, "\texchange_type ");
953           while (etype) {
954                     pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type),
955                                          etype->next != NULL ? ", " : ";\n");
956                     etype = etype->next;
957           }
958           plog(LLV_INFO, LOCATION, NULL, "%s", buf);
959           plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype));
960           pbuf = buf;
961           pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype));
962           if (p->idvtype == IDTYPE_ASN1DN) {
963                     plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
964                     plog(LLV_INFO, LOCATION, NULL,
965                          "\tcertificate_type %s \"%s\" \"%s\";\n",
966                          oakley_get_certtype(p->mycert) == ISAKMP_CERT_X509SIGN
967                            ? "x509" : "*UNKNOWN*",
968                          p->mycertfile, p->myprivfile);
969 
970                     switch (oakley_get_certtype(p->peerscert)) {
971                     case ISAKMP_CERT_NONE:
972                               plog(LLV_INFO, LOCATION, NULL,
973                                    "\t/* peers certificate from payload */\n");
974                               break;
975                     case ISAKMP_CERT_X509SIGN:
976                               plog(LLV_INFO, LOCATION, NULL,
977                                    "\tpeers_certfile \"%s\";\n", p->peerscertfile);
978                               break;
979                     case ISAKMP_CERT_DNS:
980                               plog(LLV_INFO, LOCATION, NULL,
981                                    "\tpeers_certfile dnssec;\n");
982                               break;
983                     default:
984                               plog(LLV_INFO, LOCATION, NULL,
985                                    "\tpeers_certfile *UNKNOWN* (%d)\n",
986                                    oakley_get_certtype(p->peerscert));
987                               break;
988                     }
989           }
990           else {
991                     if (p->idv)
992                               pbuf += sprintf (pbuf, " \"%s\"", p->idv->v);
993                     plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
994                     genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
995           }
996 
997           plog(LLV_INFO, LOCATION, NULL, "\trekey %s;\n",
998                     p->rekey == REKEY_FORCE ? "force" : s_switch (p->rekey));
999           plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n",
1000                     s_switch (p->send_cert));
1001           plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n",
1002                     s_switch (p->send_cr));
1003           plog(LLV_INFO, LOCATION, NULL, "\tmatch_empty_cr %s;\n",
1004                     s_switch (p->match_empty_cr));
1005           plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n",
1006                     s_switch (p->verify_cert));
1007           plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n",
1008                     s_switch (p->verify_identifier));
1009           plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n",
1010                     p->nat_traversal == NATT_FORCE ?
1011                               "force" : s_switch (p->nat_traversal));
1012           plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n",
1013                     p->nonce_size);
1014           plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n",
1015                     s_switch (p->passive));
1016           plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n",
1017                     p->ike_frag == ISAKMP_FRAG_FORCE ?
1018                               "force" : s_switch (p->ike_frag));
1019           plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag);
1020           plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n",
1021                     s_switch (p->ini_contact));
1022           plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n",
1023                     s_switch (p->gen_policy));
1024           plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n",
1025                     s_switch (p->support_proxy));
1026 
1027           while (prop) {
1028                     plog(LLV_INFO, LOCATION, NULL, "\n");
1029                     plog(LLV_INFO, LOCATION, NULL,
1030                               "\t/* prop_no=%d, trns_no=%d */\n",
1031                               prop->prop_no, prop->trns_no);
1032                     plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n");
1033                     plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n",
1034                               (long)prop->lifetime);
1035                     plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n",
1036                               prop->lifebyte);
1037                     plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n",
1038                               alg_oakley_dhdef_name(prop->dh_group));
1039                     plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n",
1040                               alg_oakley_encdef_name(prop->enctype));
1041                     plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n",
1042                               alg_oakley_hashdef_name(prop->hashtype));
1043                     plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n",
1044                               alg_oakley_authdef_name(prop->authmethod));
1045                     plog(LLV_INFO, LOCATION, NULL, "\t}\n");
1046                     prop = prop->next;
1047           }
1048           plog(LLV_INFO, LOCATION, NULL, "}\n");
1049           plog(LLV_INFO, LOCATION, NULL, "\n");
1050 
1051           return 0;
1052 }
1053 
1054 void
dumprmconf(void)1055 dumprmconf(void)
1056 {
1057           enumrmconf(NULL, dump_rmconf_single, NULL);
1058 }
1059 
1060 struct idspec *
newidspec(void)1061 newidspec(void)
1062 {
1063           struct idspec *new;
1064 
1065           new = racoon_calloc(1, sizeof(*new));
1066           if (new == NULL)
1067                     return NULL;
1068           new->idtype = IDTYPE_ADDRESS;
1069           new->id = NULL;
1070           return new;
1071 }
1072 
1073 vchar_t *
script_path_add(vchar_t * path)1074 script_path_add(vchar_t *path)
1075 {
1076           char *script_dir;
1077           vchar_t *new_path;
1078           size_t len;
1079 
1080           script_dir = lcconf->pathinfo[LC_PATHTYPE_SCRIPT];
1081 
1082           /* Try to find the script in the script directory */
1083           if ((path->v[0] != '/') && (script_dir != NULL)) {
1084                     len = strlen(script_dir) + sizeof("/") + path->l + 1;
1085 
1086                     if ((new_path = vmalloc(len)) == NULL) {
1087                               plog(LLV_ERROR, LOCATION, NULL,
1088                                   "Cannot allocate memory: %s\n", strerror(errno));
1089                               return NULL;
1090                     }
1091 
1092                     new_path->v[0] = '\0';
1093                     (void)strlcat(new_path->v, script_dir, len);
1094                     (void)strlcat(new_path->v, "/", len);
1095                     (void)strlcat(new_path->v, path->v, len);
1096 
1097                     vfree(path);
1098                     path = new_path;
1099           }
1100 
1101           return path;
1102 }
1103 
1104 
1105 struct isakmpsa *
dupisakmpsa(struct isakmpsa * sa)1106 dupisakmpsa(struct isakmpsa *sa)
1107 {
1108           struct isakmpsa *res = NULL;
1109 
1110           if(sa == NULL)
1111                     return NULL;
1112 
1113           res = newisakmpsa();
1114           if(res == NULL)
1115                     return NULL;
1116 
1117           *res = *sa;
1118 #ifdef HAVE_GSSAPI
1119           if (sa->gssid != NULL)
1120                     res->gssid = vdup(sa->gssid);
1121 #endif
1122           res->next = NULL;
1123 
1124           if(sa->dhgrp != NULL)
1125                     oakley_setdhgroup(sa->dh_group, &res->dhgrp);
1126 
1127           return res;
1128 
1129 }
1130 
1131 #ifdef ENABLE_HYBRID
1132 int
isakmpsa_switch_authmethod(int authmethod)1133 isakmpsa_switch_authmethod(int authmethod)
1134 {
1135           switch(authmethod) {
1136           case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1137                     authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
1138                     break;
1139           case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1140                     authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
1141                     break;
1142           case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1143                     authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
1144                     break;
1145           case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1146                     authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
1147                     break;
1148           case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1149                     authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
1150                     break;
1151           case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1152                     authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
1153                     break;
1154           case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1155                     authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
1156                     break;
1157           default:
1158                     break;
1159           }
1160 
1161           return authmethod;
1162 }
1163 #endif
1164 
1165 /*
1166  * Given a proposed ISAKMP SA, and a list of acceptable
1167  * ISAKMP SAs, it compares using pcheck_level policy and
1168  * returns first match (if any).
1169  */
1170 struct isakmpsa *
checkisakmpsa(int pcheck_level,struct isakmpsa * proposal,struct isakmpsa * acceptable)1171 checkisakmpsa(int pcheck_level, struct isakmpsa *proposal,
1172     struct isakmpsa *acceptable)
1173 {
1174           struct isakmpsa *p;
1175 
1176           for (p = acceptable; p != NULL; p = p->next){
1177                     plog(LLV_DEBUG2, LOCATION, NULL,
1178                          "checkisakmpsa:\nauthmethod: %d / %d\n",
1179                          isakmpsa_switch_authmethod(proposal->authmethod), isakmpsa_switch_authmethod(p->authmethod));
1180                     if (isakmpsa_switch_authmethod(proposal->authmethod) != isakmpsa_switch_authmethod(p->authmethod) ||
1181                         proposal->enctype != p->enctype ||
1182                     proposal->dh_group != p->dh_group ||
1183                         proposal->hashtype != p->hashtype)
1184                               continue;
1185 
1186                     switch (pcheck_level) {
1187                     case PROP_CHECK_OBEY:
1188                               break;
1189 
1190                     case PROP_CHECK_CLAIM:
1191                     case PROP_CHECK_STRICT:
1192                               if (proposal->encklen < p->encklen ||
1193 #if 0
1194                                   proposal->lifebyte > p->lifebyte ||
1195 #endif
1196                                   proposal->lifetime > p->lifetime)
1197                                         continue;
1198                               break;
1199 
1200                     case PROP_CHECK_EXACT:
1201                               if (proposal->encklen != p->encklen ||
1202 #if 0
1203                             proposal->lifebyte != p->lifebyte ||
1204 #endif
1205                                   proposal->lifetime != p->lifetime)
1206                                         continue;
1207                               break;
1208 
1209                     default:
1210                               continue;
1211                     }
1212 
1213                     return p;
1214           }
1215 
1216           return NULL;
1217 }
1218