File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / policy.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: policy.c,v 1.12 2011/03/14 17:18:13 tteras Exp $	*/
    2: 
    3: /*	$KAME: policy.c,v 1.46 2001/11/16 04:08:10 sakane 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/param.h>
   37: #include <sys/types.h>
   38: #include <sys/socket.h>
   39: #include <sys/queue.h>
   40: 
   41: #include <netinet/in.h>
   42: #include PATH_IPSEC_H
   43: 
   44: #include <stdlib.h>
   45: #include <stdio.h>
   46: #include <string.h>
   47: #include <errno.h>
   48: 
   49: #include "var.h"
   50: #include "misc.h"
   51: #include "vmbuf.h"
   52: #include "plog.h"
   53: #include "sockmisc.h"
   54: #include "debug.h"
   55: 
   56: #include "policy.h"
   57: #include "localconf.h"
   58: #include "isakmp_var.h"
   59: #include "isakmp.h"
   60: #include "oakley.h"
   61: #include "handler.h"
   62: #include "strnames.h"
   63: #include "gcmalloc.h"
   64: 
   65: static TAILQ_HEAD(_sptree, secpolicy) sptree;
   66: 
   67: /* perform exact match against security policy table. */
   68: struct secpolicy *
   69: getsp(spidx)
   70: 	struct policyindex *spidx;
   71: {
   72: 	struct secpolicy *p;
   73: 
   74: 	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
   75: 		if (!cmpspidxstrict(spidx, &p->spidx))
   76: 			return p;
   77: 	}
   78: 
   79: 	return NULL;
   80: }
   81: 
   82: /*
   83:  * perform non-exact match against security policy table, only if this is
   84:  * transport mode SA negotiation.  for example, 0.0.0.0/0 -> 0.0.0.0/0
   85:  * entry in policy.txt can be returned when we're negotiating transport
   86:  * mode SA.  this is how the kernel works.
   87:  */
   88: #if 1
   89: struct secpolicy *
   90: getsp_r(spidx)
   91: 	struct policyindex *spidx;
   92: {
   93: 	struct secpolicy *p;
   94: 	struct secpolicy *found = NULL;
   95: 
   96: 	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
   97: 		if (!cmpspidxstrict(spidx, &p->spidx))
   98: 			return p;
   99: 
  100: 		if (!found && !cmpspidxwild(spidx, &p->spidx))
  101: 			found = p;
  102: 	}
  103: 
  104: 	return found;
  105: }
  106: #else
  107: struct secpolicy *
  108: getsp_r(spidx, iph2)
  109: 	struct policyindex *spidx;
  110: 	struct ph2handle *iph2;
  111: {
  112: 	struct secpolicy *p;
  113: 	u_int8_t prefixlen;
  114: 
  115: 	plog(LLV_DEBUG, LOCATION, NULL, "checking for transport mode\n");
  116: 
  117: 	if (spidx->src.ss_family != spidx->dst.ss_family) {
  118: 		plog(LLV_ERROR, LOCATION, NULL,
  119: 			"address family mismatch, src:%d dst:%d\n",
  120: 				spidx->src.ss_family,
  121: 				spidx->dst.ss_family);
  122: 		return NULL;
  123: 	}
  124: 	switch (spidx->src.ss_family) {
  125: 	case AF_INET:
  126: 		prefixlen = sizeof(struct in_addr) << 3;
  127: 		break;
  128: #ifdef INET6
  129: 	case AF_INET6:
  130: 		prefixlen = sizeof(struct in6_addr) << 3;
  131: 		break;
  132: #endif
  133: 	default:
  134: 		plog(LLV_ERROR, LOCATION, NULL,
  135: 			"invalid family: %d\n", spidx->src.ss_family);
  136: 		return NULL;
  137: 	}
  138: 
  139: 	/* is it transport mode SA negotiation? */
  140: 	plog(LLV_DEBUG, LOCATION, NULL, "src1: %s\n",
  141: 		saddr2str(iph2->src));
  142: 	plog(LLV_DEBUG, LOCATION, NULL, "src2: %s\n",
  143: 		saddr2str((struct sockaddr *)&spidx->src));
  144: 
  145: 	if (cmpsaddr(iph2->src, (struct sockaddr *) &spidx->src) != CMPSADDR_MATCH ||
  146: 	    spidx->prefs != prefixlen)
  147: 		return NULL;
  148: 
  149: 	plog(LLV_DEBUG, LOCATION, NULL, "dst1: %s\n",
  150: 		saddr2str(iph2->dst));
  151: 	plog(LLV_DEBUG, LOCATION, NULL, "dst2: %s\n",
  152: 		saddr2str((struct sockaddr *)&spidx->dst));
  153: 
  154: 	if (cmpsaddr(iph2->dst, (struct sockaddr *) &spidx->dst) != CMPSADDR_MATCH ||
  155: 	    spidx->prefd != prefixlen)
  156: 		return NULL;
  157: 
  158: 	plog(LLV_DEBUG, LOCATION, NULL, "looks to be transport mode\n");
  159: 
  160: 	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
  161: 		if (!cmpspidx_wild(spidx, &p->spidx))
  162: 			return p;
  163: 	}
  164: 
  165: 	return NULL;
  166: }
  167: #endif
  168: 
  169: struct secpolicy *
  170: getspbyspid(spid)
  171: 	u_int32_t spid;
  172: {
  173: 	struct secpolicy *p;
  174: 
  175: 	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
  176: 		if (p->id == spid)
  177: 			return p;
  178: 	}
  179: 
  180: 	return NULL;
  181: }
  182: 
  183: /*
  184:  * compare policyindex.
  185:  * a: subject b: db
  186:  * OUT:	0:	equal
  187:  *	1:	not equal
  188:  */
  189: int
  190: cmpspidxstrict(a, b)
  191: 	struct policyindex *a, *b;
  192: {
  193: 	plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
  194: 	plog(LLV_DEBUG, LOCATION, NULL, "db :%p: %s\n", b, spidx2str(b));
  195: 
  196: 	/* XXX don't check direction now, but it's to be checked carefully. */
  197: 	if (a->dir != b->dir
  198: 	 || a->prefs != b->prefs
  199: 	 || a->prefd != b->prefd
  200: 	 || a->ul_proto != b->ul_proto)
  201: 		return 1;
  202: 
  203: 	if (cmpsaddr((struct sockaddr *) &a->src,
  204: 		     (struct sockaddr *) &b->src) != CMPSADDR_MATCH)
  205: 		return 1;
  206: 	if (cmpsaddr((struct sockaddr *) &a->dst,
  207: 		     (struct sockaddr *) &b->dst) != CMPSADDR_MATCH)
  208: 		return 1;
  209: 
  210: #ifdef HAVE_SECCTX
  211: 	if (a->sec_ctx.ctx_alg != b->sec_ctx.ctx_alg
  212: 	    || a->sec_ctx.ctx_doi != b->sec_ctx.ctx_doi
  213: 	    || !within_range(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str))
  214: 		return 1;
  215: #endif
  216: 	return 0;
  217: }
  218: 
  219: /*
  220:  * compare policyindex, with wildcard address/protocol match.
  221:  * a: subject b: db, can contain wildcard things.
  222:  * OUT:	0:	equal
  223:  *	1:	not equal
  224:  */
  225: int
  226: cmpspidxwild(a, b)
  227: 	struct policyindex *a, *b;
  228: {
  229: 	struct sockaddr_storage sa1, sa2;
  230: 
  231: 	plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
  232: 	plog(LLV_DEBUG, LOCATION, NULL, "db: %p: %s\n", b, spidx2str(b));
  233: 
  234: 	if (!(b->dir == IPSEC_DIR_ANY || a->dir == b->dir))
  235: 		return 1;
  236: 
  237: 	if (!(b->ul_proto == IPSEC_ULPROTO_ANY ||
  238: 	      a->ul_proto == b->ul_proto))
  239: 		return 1;
  240: 
  241: 	if (a->src.ss_family != b->src.ss_family)
  242: 		return 1;
  243: 	if (a->dst.ss_family != b->dst.ss_family)
  244: 		return 1;
  245: 
  246: #ifndef __linux__
  247: 	/* compare src address */
  248: 	if (sizeof(sa1) < a->src.ss_len || sizeof(sa2) < b->src.ss_len) {
  249: 		plog(LLV_ERROR, LOCATION, NULL,
  250: 			"unexpected error: "
  251: 			"src.ss_len:%d dst.ss_len:%d\n",
  252: 			a->src.ss_len, b->src.ss_len);
  253: 		return 1;
  254: 	}
  255: #endif
  256: 	mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->src,
  257: 		b->prefs);
  258: 	mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->src,
  259: 		b->prefs);
  260: 	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
  261: 		a, b->prefs, saddr2str((struct sockaddr *)&sa1));
  262: 	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
  263: 		b, b->prefs, saddr2str((struct sockaddr *)&sa2));
  264: 	if (cmpsaddr((struct sockaddr *)&sa1, (struct sockaddr *)&sa2) > CMPSADDR_WILDPORT_MATCH)
  265: 		return 1;
  266: 
  267: #ifndef __linux__
  268: 	/* compare dst address */
  269: 	if (sizeof(sa1) < a->dst.ss_len || sizeof(sa2) < b->dst.ss_len) {
  270: 		plog(LLV_ERROR, LOCATION, NULL, "unexpected error\n");
  271: 		exit(1);
  272: 	}
  273: #endif
  274: 	mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->dst,
  275: 		b->prefd);
  276: 	mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->dst,
  277: 		b->prefd);
  278: 	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
  279: 		a, b->prefd, saddr2str((struct sockaddr *)&sa1));
  280: 	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
  281: 		b, b->prefd, saddr2str((struct sockaddr *)&sa2));
  282: 	if (cmpsaddr((struct sockaddr *)&sa1, (struct sockaddr *)&sa2) > CMPSADDR_WILDPORT_MATCH)
  283: 		return 1;
  284: 
  285: #ifdef HAVE_SECCTX
  286: 	if (a->sec_ctx.ctx_alg != b->sec_ctx.ctx_alg
  287: 	    || a->sec_ctx.ctx_doi != b->sec_ctx.ctx_doi
  288: 	    || !within_range(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str))
  289: 		return 1;
  290: #endif
  291: 	return 0;
  292: }
  293: 
  294: struct secpolicy *
  295: newsp()
  296: {
  297: 	struct secpolicy *new;
  298: 
  299: 	new = racoon_calloc(1, sizeof(*new));
  300: 	if (new == NULL)
  301: 		return NULL;
  302: 
  303: 	return new;
  304: }
  305: 
  306: void
  307: delsp(sp)
  308: 	struct secpolicy *sp;
  309: {
  310: 	struct ipsecrequest *req = NULL, *next;
  311: 
  312: 	for (req = sp->req; req; req = next) {
  313: 		next = req->next;
  314: 		racoon_free(req);
  315: 	}
  316: 	
  317: 	if (sp->local)
  318: 		racoon_free(sp->local);
  319: 	if (sp->remote)
  320: 		racoon_free(sp->remote);
  321: 
  322: 	racoon_free(sp);
  323: }
  324: 
  325: void
  326: delsp_bothdir(spidx0)
  327: 	struct policyindex *spidx0;
  328: {
  329: 	struct policyindex spidx;
  330: 	struct secpolicy *sp;
  331: 	struct sockaddr_storage src, dst;
  332: 	u_int8_t prefs, prefd;
  333: 
  334: 	memcpy(&spidx, spidx0, sizeof(spidx));
  335: 	switch (spidx.dir) {
  336: 	case IPSEC_DIR_INBOUND:
  337: #ifdef HAVE_POLICY_FWD
  338: 	case IPSEC_DIR_FWD:
  339: #endif
  340: 		src   = spidx.src;
  341: 		dst   = spidx.dst;
  342: 		prefs = spidx.prefs;
  343: 		prefd = spidx.prefd;
  344: 		break;
  345: 	case IPSEC_DIR_OUTBOUND:
  346: 		src   = spidx.dst;
  347: 		dst   = spidx.src;
  348: 		prefs = spidx.prefd;
  349: 		prefd = spidx.prefs;
  350: 		break;
  351: 	default:
  352: 		return;
  353: 	}
  354: 
  355: 	spidx.src   = src;
  356: 	spidx.dst   = dst;
  357: 	spidx.prefs = prefs;
  358: 	spidx.prefd = prefd;
  359: 	spidx.dir   = IPSEC_DIR_INBOUND;
  360: 
  361: 	sp = getsp(&spidx);
  362: 	if (sp) {
  363: 		remsp(sp);
  364: 		delsp(sp);
  365: 	}
  366: 
  367: #ifdef HAVE_POLICY_FWD
  368: 	spidx.dir   = IPSEC_DIR_FWD;
  369: 
  370: 	sp = getsp(&spidx);
  371: 	if (sp) {
  372: 		remsp(sp);
  373: 		delsp(sp);
  374: 	}
  375: #endif
  376: 
  377: 	spidx.src   = dst;
  378: 	spidx.dst   = src;
  379: 	spidx.prefs = prefd;
  380: 	spidx.prefd = prefs;
  381: 	spidx.dir   = IPSEC_DIR_OUTBOUND;
  382: 
  383: 	sp = getsp(&spidx);
  384: 	if (sp) {
  385: 		remsp(sp);
  386: 		delsp(sp);
  387: 	}
  388: }
  389: 
  390: void
  391: inssp(new)
  392: 	struct secpolicy *new;
  393: {
  394: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  395: 	struct secpolicy *p;
  396: 
  397: 	TAILQ_FOREACH(p, &sptree, chain) {
  398: 		if (new->spidx.priority < p->spidx.priority) {
  399: 			TAILQ_INSERT_BEFORE(p, new, chain);
  400: 			return;
  401: 		}
  402: 	}
  403: 	if (p == NULL)
  404: #endif
  405: 		TAILQ_INSERT_TAIL(&sptree, new, chain);
  406: 
  407: 	return;
  408: }
  409: 
  410: void
  411: remsp(sp)
  412: 	struct secpolicy *sp;
  413: {
  414: 	TAILQ_REMOVE(&sptree, sp, chain);
  415: }
  416: 
  417: void
  418: flushsp()
  419: {
  420: 	struct secpolicy *p, *next;
  421: 
  422: 	for (p = TAILQ_FIRST(&sptree); p; p = next) {
  423: 		next = TAILQ_NEXT(p, chain);
  424: 		remsp(p);
  425: 		delsp(p);
  426: 	}
  427: }
  428: 
  429: void
  430: initsp()
  431: {
  432: 	TAILQ_INIT(&sptree);
  433: }
  434: 
  435: struct ipsecrequest *
  436: newipsecreq()
  437: {
  438: 	struct ipsecrequest *new;
  439: 
  440: 	new = racoon_calloc(1, sizeof(*new));
  441: 	if (new == NULL)
  442: 		return NULL;
  443: 
  444: 	return new;
  445: }
  446: 
  447: const char *
  448: spidx2str(spidx)
  449: 	const struct policyindex *spidx;
  450: {
  451: 	/* addr/pref[port] addr/pref[port] ul dir act */
  452: 	static char buf[256];
  453: 	char *p, *a, *b;
  454: 	int blen, i;
  455: 
  456: 	blen = sizeof(buf) - 1;
  457: 	p = buf;
  458: 
  459: 	a = saddr2str((const struct sockaddr *)&spidx->src);
  460: 	for (b = a; *b != '\0'; b++)
  461: 		if (*b == '[') {
  462: 			*b = '\0';
  463: 			b++;
  464: 			break;
  465: 		}
  466: 	i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefs, b);
  467: 	if (i < 0 || i >= blen)
  468: 		return NULL;
  469: 	p += i;
  470: 	blen -= i;
  471: 
  472: 	a = saddr2str((const struct sockaddr *)&spidx->dst);
  473: 	for (b = a; *b != '\0'; b++)
  474: 		if (*b == '[') {
  475: 			*b = '\0';
  476: 			b++;
  477: 			break;
  478: 		}
  479: 	i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefd, b);
  480: 	if (i < 0 || i >= blen)
  481: 		return NULL;
  482: 	p += i;
  483: 	blen -= i;
  484: 
  485: 	i = snprintf(p, blen, "proto=%s dir=%s",
  486: 		s_proto(spidx->ul_proto), s_direction(spidx->dir));
  487: 
  488: #ifdef HAVE_SECCTX
  489: 	if (spidx->sec_ctx.ctx_strlen) {
  490: 		p += i;
  491: 		blen -= i;
  492: 		snprintf(p, blen, " sec_ctx:doi=%d,alg=%d,len=%d,str=%s",
  493: 			 spidx->sec_ctx.ctx_doi, spidx->sec_ctx.ctx_alg,
  494: 			 spidx->sec_ctx.ctx_strlen, spidx->sec_ctx.ctx_str);
  495: 	}
  496: #endif
  497: 	return buf;
  498: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>