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