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