/* $KAME: remoteconf.c,v 1.29 2001/12/07 08:39:39 sakane 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 #include #include #include #include #include #ifdef IPV6_INRIA_VERSION #include #else #include #endif #include #include #include #include #include "var.h" #include "misc.h" #include "vmbuf.h" #include "plog.h" #include "sockmisc.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" static LIST_HEAD(_rmtree, remoteconf) rmtree; /*%%%*/ /* * 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(remote) struct sockaddr *remote; { 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 default: plog(LLV_ERROR, LOCATION, NULL, "invalid family: %d\n", remote->sa_family); exit(1); } GETNAMEINFO(remote, addr, port); snprintf(buf, sizeof(buf), "%s%s%s%s", addr, withport ? "[" : "", withport ? port : "", withport ? "]" : ""); LIST_FOREACH(p, &rmtree, chain) { if ((!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 (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 * 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_ADDRESS; new->idvtype_p = IDTYPE_ADDRESS; new->nonce_size = DEFAULT_NONCE_SIZE; new->keepalive = FALSE; new->passive = FALSE; new->ini_contact = TRUE; new->pcheck_level = PROP_CHECK_STRICT; new->verify_identifier = FALSE; new->verify_cert = TRUE; new->getcert_method = ISAKMP_GETCERT_PAYLOAD; new->send_cert = TRUE; new->send_cr = TRUE; new->support_mip6 = FALSE; new->gen_policy = FALSE; new->retry_counter = lcconf->retry_counter; new->retry_interval = lcconf->retry_interval; return new; } void delrmconf(rmconf) struct remoteconf *rmconf; { if (rmconf->etypes) deletypes(rmconf->etypes); if (rmconf->dhgrp) oakley_dhgrp_free(rmconf->dhgrp); if (rmconf->proposal) delisakmpsa(rmconf->proposal); if (rmconf->idv) vfree(rmconf->idv); if (rmconf->idv_p) vfree(rmconf->idv_p); if (rmconf->remote) racoon_free(rmconf->remote); if (rmconf->shared_secret) vfree(rmconf->shared_secret); if (rmconf->keychainCertRef) CFRelease(rmconf->keychainCertRef); if (rmconf->open_dir_auth_group) vfree(rmconf->open_dir_auth_group); 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); } 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; { LIST_INSERT_HEAD(&rmtree, new, chain); } void remrmconf(rmconf) struct remoteconf *rmconf; { LIST_REMOVE(rmconf, chain); } void flushrmconf() { struct remoteconf *p, *next; for (p = LIST_FIRST(&rmtree); p; p = next) { next = LIST_NEXT(p, chain); remrmconf(p); delrmconf(p); } } void initrmconf() { LIST_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; } const char * rm2str(rmconf) const struct remoteconf *rmconf; { if (rmconf->remote->sa_family == AF_UNSPEC) return "anonymous"; return saddr2str(rmconf->remote); }