X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=userapps%2Fopensource%2Fipsec-tools%2Fsrc%2Fracoon%2Fremoteconf.c;fp=userapps%2Fopensource%2Fipsec-tools%2Fsrc%2Fracoon%2Fremoteconf.c;h=eb26e56a1ebe5b1854f13c1c5df51f944af98f63;hb=864458111a0e69d94bbae210d5b7349ca072a6b7;hp=0000000000000000000000000000000000000000;hpb=57a096f051259ceaefd5977f30d269884e1dd248;p=bcm963xx.git diff --git a/userapps/opensource/ipsec-tools/src/racoon/remoteconf.c b/userapps/opensource/ipsec-tools/src/racoon/remoteconf.c new file mode 100755 index 00000000..eb26e56a --- /dev/null +++ b/userapps/opensource/ipsec-tools/src/racoon/remoteconf.c @@ -0,0 +1,596 @@ +/* $Id: remoteconf.c,v 1.24 2004/12/01 10:59:41 vanhu Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include + +#ifndef HAVE_NETINET6_IPSEC +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include "var.h" +#include "misc.h" +#include "vmbuf.h" +#include "plog.h" +#include "sockmisc.h" +#include "genlist.h" +#include "debug.h" + +#include "isakmp_var.h" +#include "isakmp.h" +#include "ipsec_doi.h" +#include "oakley.h" +#include "remoteconf.h" +#include "localconf.h" +#include "grabmyaddr.h" +#include "proposal.h" +#include "vendorid.h" +#include "gcmalloc.h" +#include "strnames.h" +#include "algorithm.h" +#include "nattraversal.h" +#include "genlist.h" + +static TAILQ_HEAD(_rmtree, remoteconf) rmtree; + +/* + * Script hook names + */ +char *script_names[SCRIPT_MAX + 1] = { "phase1_up", "phase1_down" }; + +/*%%%*/ +/* + * search remote configuration. + * don't use port number to search if its value is either IPSEC_PORT_ANY. + * If matching anonymous entry, then new entry is copied from anonymous entry. + * If no anonymous entry found, then return NULL. + * OUT: NULL: NG + * Other: remote configuration entry. + */ +struct remoteconf * +getrmconf_strict(remote, allow_anon) + struct sockaddr *remote; + int allow_anon; +{ + struct remoteconf *p; + struct remoteconf *anon = NULL; + int withport; + char buf[NI_MAXHOST + NI_MAXSERV + 10]; + char addr[NI_MAXHOST], port[NI_MAXSERV]; + + withport = 0; + + switch (remote->sa_family) { + case AF_INET: + if (((struct sockaddr_in *)remote)->sin_port != IPSEC_PORT_ANY) + withport = 1; + break; +#ifdef INET6 + case AF_INET6: + if (((struct sockaddr_in6 *)remote)->sin6_port != IPSEC_PORT_ANY) + withport = 1; + break; +#endif + case AF_UNSPEC: + break; + + default: + plog(LLV_ERROR, LOCATION, NULL, + "invalid family: %d\n", remote->sa_family); + exit(1); + } + + if (remote->sa_family == AF_UNSPEC) + snprintf (buf, sizeof(buf), "%s", "anonymous"); + else { + GETNAMEINFO(remote, addr, port); + snprintf(buf, sizeof(buf), "%s%s%s%s", addr, + withport ? "[" : "", + withport ? port : "", + withport ? "]" : ""); + } + + TAILQ_FOREACH(p, &rmtree, chain) { + if ((remote->sa_family == AF_UNSPEC + && remote->sa_family == p->remote->sa_family) + || (!withport && cmpsaddrwop(remote, p->remote) == 0) + || (withport && cmpsaddrstrict(remote, p->remote) == 0)) { + plog(LLV_DEBUG, LOCATION, NULL, + "configuration found for %s.\n", buf); + return p; + } + + /* save the pointer to the anonymous configuration */ + if (p->remote->sa_family == AF_UNSPEC) + anon = p; + } + + if (allow_anon && anon != NULL) { + plog(LLV_DEBUG, LOCATION, NULL, + "anonymous configuration selected for %s.\n", buf); + return anon; + } + + plog(LLV_DEBUG, LOCATION, NULL, + "no remote configuration found.\n"); + + return NULL; +} + +struct remoteconf * +getrmconf(remote) + struct sockaddr *remote; +{ + return getrmconf_strict(remote, 1); +} + +struct remoteconf * +newrmconf() +{ + struct remoteconf *new; + + new = racoon_calloc(1, sizeof(*new)); + if (new == NULL) + return NULL; + + new->proposal = NULL; + + /* set default */ + new->doitype = IPSEC_DOI; + new->sittype = IPSECDOI_SIT_IDENTITY_ONLY; + new->idvtype = IDTYPE_UNDEFINED; + new->idvl_p = genlist_init(); + new->nonce_size = DEFAULT_NONCE_SIZE; + new->passive = FALSE; + new->ike_frag = FALSE; + new->ini_contact = TRUE; + new->mode_cfg = FALSE; + new->pcheck_level = PROP_CHECK_STRICT; + new->verify_identifier = FALSE; + new->verify_cert = TRUE; + new->getcert_method = ISAKMP_GETCERT_PAYLOAD; + new->getcacert_method = ISAKMP_GETCERT_LOCALFILE; + new->cacerttype = ISAKMP_CERT_X509SIGN; + new->cacertfile = NULL; + new->send_cert = TRUE; + new->send_cr = TRUE; + new->support_proxy = FALSE; + bzero(&new->script[0], sizeof(char *) * (SCRIPT_MAX + 1)); + new->gen_policy = FALSE; + new->retry_counter = lcconf->retry_counter; + new->retry_interval = lcconf->retry_interval; + new->nat_traversal = FALSE; + new->rsa_private = genlist_init(); + new->rsa_public = genlist_init(); + new->idv = NULL; + new->key = NULL; + + new->dpd = TRUE; /* Enable DPD support by default */ + new->dpd_interval = 0; /* Disable DPD checks by default */ + new->dpd_retry = 5; + new->dpd_maxfails = 5; + + return new; +} + +struct remoteconf * +copyrmconf(remote) + struct sockaddr *remote; +{ + struct remoteconf *new, *old; + + old = getrmconf_strict (remote, 0); + if (old == NULL) { + plog (LLV_ERROR, LOCATION, NULL, + "Remote configuration for '%s' not found!\n", + saddr2str (remote)); + return NULL; + } + + new = duprmconf (old); + + return new; +} + +void * +dupidvl(entry, arg) + void *entry; + void *arg; +{ + struct idspec *id; + struct idspec *old = (struct idspec *) entry; + id = newidspec(); + if (!id) return (void *) -1; + + if (set_identifier(&id->id, old->idtype, old->id) != 0) + return (void *) -1; + + id->idtype = old->idtype; + + genlist_append(arg, id); + return NULL; +} + +struct remoteconf * +duprmconf (rmconf) + struct remoteconf *rmconf; +{ + struct remoteconf *new; + + new = racoon_calloc(1, sizeof(*new)); + if (new == NULL) + return NULL; + memcpy (new, rmconf, sizeof (*new)); + // FIXME: We should duplicate the proposal as well. + // This is now handled in the cfparse.y + // new->proposal = ...; + + /* duplicate dynamic structures */ + if (new->etypes) + new->etypes=dupetypes(new->etypes); + new->idvl_p = genlist_init(); + genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p); + + return new; +} + +static void +idspec_free(void *data) +{ + vfree (((struct idspec *)data)->id); + free (data); +} + +void +delrmconf(rmconf) + struct remoteconf *rmconf; +{ + if (rmconf->etypes) + deletypes(rmconf->etypes); + if (rmconf->idvl_p) + genlist_free(rmconf->idvl_p, idspec_free); + if (rmconf->dhgrp) + oakley_dhgrp_free(rmconf->dhgrp); + if (rmconf->proposal) + delisakmpsa(rmconf->proposal); + racoon_free(rmconf); +} + +void +delisakmpsa(sa) + struct isakmpsa *sa; +{ + if (sa->dhgrp) + oakley_dhgrp_free(sa->dhgrp); + if (sa->next) + delisakmpsa(sa->next); +#ifdef HAVE_GSSAPI + if (sa->gssid) + vfree(sa->gssid); +#endif + racoon_free(sa); +} + +struct etypes * +dupetypes(orig) + struct etypes *orig; +{ + struct etypes *new; + + if (!orig) + return NULL; + + new = racoon_malloc(sizeof(struct etypes)); + if (new == NULL) + return NULL; + + new->type = orig->type; + new->next = NULL; + + if (orig->next) + new->next=dupetypes(orig->next); + + return new; +} + +void +deletypes(e) + struct etypes *e; +{ + if (e->next) + deletypes(e->next); + racoon_free(e); +} + +/* + * insert into head of list. + */ +void +insrmconf(new) + struct remoteconf *new; +{ + TAILQ_INSERT_HEAD(&rmtree, new, chain); +} + +void +remrmconf(rmconf) + struct remoteconf *rmconf; +{ + TAILQ_REMOVE(&rmtree, rmconf, chain); +} + +void +flushrmconf() +{ + struct remoteconf *p, *next; + + for (p = TAILQ_FIRST(&rmtree); p; p = next) { + next = TAILQ_NEXT(p, chain); + remrmconf(p); + delrmconf(p); + } +} + +void +initrmconf() +{ + TAILQ_INIT(&rmtree); +} + +/* check exchange type to be acceptable */ +struct etypes * +check_etypeok(rmconf, etype) + struct remoteconf *rmconf; + u_int8_t etype; +{ + struct etypes *e; + + for (e = rmconf->etypes; e != NULL; e = e->next) { + if (e->type == etype) + break; + } + + return e; +} + +/*%%%*/ +struct isakmpsa * +newisakmpsa() +{ + struct isakmpsa *new; + + new = racoon_calloc(1, sizeof(*new)); + if (new == NULL) + return NULL; + + /* + * Just for sanity, make sure this is initialized. This is + * filled in for real when the ISAKMP proposal is configured. + */ + new->vendorid = VENDORID_UNKNOWN; + + new->next = NULL; + new->rmconf = NULL; +#ifdef HAVE_GSSAPI + new->gssid = NULL; +#endif + + return new; +} + +/* + * insert into tail of list. + */ +void +insisakmpsa(new, rmconf) + struct isakmpsa *new; + struct remoteconf *rmconf; +{ + struct isakmpsa *p; + + new->rmconf = rmconf; + + if (rmconf->proposal == NULL) { + rmconf->proposal = new; + return; + } + + for (p = rmconf->proposal; p->next != NULL; p = p->next) + ; + p->next = new; + + return; +} + +struct remoteconf * +foreachrmconf(rmconf_func_t rmconf_func, void *data) +{ + struct remoteconf *p, *ret = NULL; + + TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) { + ret = (*rmconf_func)(p, data); + if (ret) + break; + } + + return ret; +} + +static void * +dump_peers_identifiers (void *entry, void *arg) +{ + struct idspec *id = (struct idspec*) entry; + char buf[1024], *pbuf; + pbuf = buf; + pbuf += sprintf (pbuf, "\tpeers_identifier %s", + s_idtype (id->idtype)); + if (id->id) + pbuf += sprintf (pbuf, " \"%s\"", id->id->v); + plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf); + return NULL; +} + +static struct remoteconf * +dump_rmconf_single (struct remoteconf *p, void *data) +{ + struct etypes *etype = p->etypes; + struct isakmpsa *prop = p->proposal; + char buf[1024], *pbuf; + + pbuf = buf; + pbuf += sprintf(pbuf, "remote %s", saddr2str(p->remote)); + if (p->inherited_from) + pbuf += sprintf(pbuf, " inherit %s", + saddr2str(p->inherited_from->remote)); + plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf); + pbuf = buf; + pbuf += sprintf(pbuf, "\texchange_type "); + while (etype) { + pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type), + etype->next != NULL ? ", " : ";\n"); + etype = etype->next; + } + plog(LLV_INFO, LOCATION, NULL, "%s", buf); + plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype)); + pbuf = buf; + pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype)); + if (p->idvtype == IDTYPE_ASN1DN) { + plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf); + plog(LLV_INFO, LOCATION, NULL, "\tcertificate_type %s \"%s\" \"%s\";\n", + p->certtype == ISAKMP_CERT_X509SIGN ? "x509" : "*UNKNOWN*", + p->mycertfile, p->myprivfile); + switch (p->getcert_method) { + case 0: + break; + case ISAKMP_GETCERT_PAYLOAD: + plog(LLV_INFO, LOCATION, NULL, "\t/* peers certificate from payload */\n"); + break; + case ISAKMP_GETCERT_LOCALFILE: + plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile \"%s\";\n", p->peerscertfile); + break; + case ISAKMP_GETCERT_DNS: + plog(LLV_INFO, LOCATION, NULL, "\tpeer_certfile dnssec;\n"); + break; + default: + plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile *UNKNOWN* (%d)\n", p->getcert_method); + } + } + else { + if (p->idv) + pbuf += sprintf (pbuf, " \"%s\"", p->idv->v); + plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf); + genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL); + } + + plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n", + s_switch (p->send_cert)); + plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n", + s_switch (p->send_cr)); + plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n", + s_switch (p->verify_cert)); + plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n", + s_switch (p->verify_identifier)); + plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n", + p->nat_traversal == NATT_FORCE ? + "force" : s_switch (p->nat_traversal)); + plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n", + p->nonce_size); + plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n", + s_switch (p->passive)); + plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n", + s_switch (p->ike_frag)); + plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n", + s_switch (p->ini_contact)); + plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n", + s_switch (p->gen_policy)); + plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n", + s_switch (p->support_proxy)); + + while (prop) { + plog(LLV_INFO, LOCATION, NULL, "\n"); + plog(LLV_INFO, LOCATION, NULL, + "\t/* prop_no=%d, trns_no=%d, rmconf=%s */\n", + prop->prop_no, prop->trns_no, + saddr2str(prop->rmconf->remote)); + plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n"); + plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n", + (long)prop->lifetime); + plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n", + prop->lifebyte); + plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n", + alg_oakley_dhdef_name(prop->dh_group)); + plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n", + alg_oakley_encdef_name(prop->enctype)); + plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n", + alg_oakley_hashdef_name(prop->hashtype)); + plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n", + alg_oakley_authdef_name(prop->authmethod)); + plog(LLV_INFO, LOCATION, NULL, "\t}\n"); + prop = prop->next; + } + plog(LLV_INFO, LOCATION, NULL, "}\n"); + plog(LLV_INFO, LOCATION, NULL, "\n"); + + return NULL; +} + +void +dumprmconf() +{ + foreachrmconf (dump_rmconf_single, NULL); +} + +struct idspec * +newidspec() +{ + struct idspec *new; + + new = racoon_calloc(1, sizeof(*new)); + if (new == NULL) + return NULL; + new->idtype = IDTYPE_ADDRESS; + + return new; +} +