File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / match_addr.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years, 3 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

    1: /*
    2:  * Copyright (c) 1996, 1998-2005, 2007-2013
    3:  *	Todd C. Miller <Todd.Miller@courtesan.com>
    4:  *
    5:  * Permission to use, copy, modify, and distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   17:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   18:  *
   19:  * Sponsored in part by the Defense Advanced Research Projects
   20:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   21:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
   22:  */
   23: 
   24: #include <config.h>
   25: 
   26: #include <sys/types.h>
   27: #include <sys/socket.h>
   28: #include <stdio.h>
   29: #ifdef STDC_HEADERS
   30: # include <stdlib.h>
   31: # include <stddef.h>
   32: #else
   33: # ifdef HAVE_STDLIB_H
   34: #  include <stdlib.h>
   35: # endif
   36: #endif /* STDC_HEADERS */
   37: #ifdef HAVE_STRING_H
   38: # include <string.h>
   39: #endif /* HAVE_STRING_H */
   40: #ifdef HAVE_STRINGS_H
   41: # include <strings.h>
   42: #endif /* HAVE_STRINGS_H */
   43: #ifdef HAVE_UNISTD_H
   44: # include <unistd.h>
   45: #endif /* HAVE_UNISTD_H */
   46: #include <netinet/in.h>
   47: #include <arpa/inet.h>
   48: 
   49: #include "sudoers.h"
   50: #include "interfaces.h"
   51: 
   52: static bool
   53: addr_matches_if(const char *n)
   54: {
   55:     union sudo_in_addr_un addr;
   56:     struct interface *ifp;
   57: #ifdef HAVE_STRUCT_IN6_ADDR
   58:     unsigned int j;
   59: #endif
   60:     unsigned int family;
   61:     debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)
   62: 
   63: #ifdef HAVE_STRUCT_IN6_ADDR
   64:     if (inet_pton(AF_INET6, n, &addr.ip6) == 1) {
   65: 	family = AF_INET6;
   66:     } else
   67: #endif /* HAVE_STRUCT_IN6_ADDR */
   68:     if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
   69: 	family = AF_INET;
   70:     } else {
   71: 	debug_return_bool(false);
   72:     }
   73: 
   74:     SLIST_FOREACH(ifp, get_interfaces(), entries) {
   75: 	if (ifp->family != family)
   76: 	    continue;
   77: 	switch (family) {
   78: 	    case AF_INET:
   79: 		if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
   80: 		    (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
   81: 		    == addr.ip4.s_addr)
   82: 		    debug_return_bool(true);
   83: 		break;
   84: #ifdef HAVE_STRUCT_IN6_ADDR
   85: 	    case AF_INET6:
   86: 		if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
   87: 		    sizeof(addr.ip6.s6_addr)) == 0)
   88: 		    debug_return_bool(true);
   89: 		for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
   90: 		    if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
   91: 			break;
   92: 		}
   93: 		if (j == sizeof(addr.ip6.s6_addr))
   94: 		    debug_return_bool(true);
   95: 		break;
   96: #endif /* HAVE_STRUCT_IN6_ADDR */
   97: 	}
   98:     }
   99: 
  100:     debug_return_bool(false);
  101: }
  102: 
  103: static bool
  104: addr_matches_if_netmask(const char *n, const char *m)
  105: {
  106:     unsigned int i;
  107:     union sudo_in_addr_un addr, mask;
  108:     struct interface *ifp;
  109: #ifdef HAVE_STRUCT_IN6_ADDR
  110:     unsigned int j;
  111: #endif
  112:     unsigned int family;
  113:     const char *errstr;
  114:     debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)
  115: 
  116: #ifdef HAVE_STRUCT_IN6_ADDR
  117:     if (inet_pton(AF_INET6, n, &addr.ip6) == 1)
  118: 	family = AF_INET6;
  119:     else
  120: #endif /* HAVE_STRUCT_IN6_ADDR */
  121:     if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
  122: 	family = AF_INET;
  123:     } else {
  124: 	debug_return_bool(false);
  125:     }
  126: 
  127:     if (family == AF_INET) {
  128: 	if (strchr(m, '.')) {
  129: 	    if (inet_pton(AF_INET, m, &mask.ip4) != 1) {
  130: 		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
  131: 		    "IPv4 netmask %s: %s", m, "invalid value");
  132: 		debug_return_bool(false);
  133: 	    }
  134: 	} else {
  135: 	    i = strtonum(m, 0, 32, &errstr);
  136: 	    if (errstr != NULL) {
  137: 		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
  138: 		    "IPv4 netmask %s: %s", m, errstr);
  139: 		debug_return_bool(false);
  140: 	    }
  141: 	    if (i == 0)
  142: 		mask.ip4.s_addr = 0;
  143: 	    else if (i == 32)
  144: 		mask.ip4.s_addr = 0xffffffff;
  145: 	    else
  146: 		mask.ip4.s_addr = 0xffffffff - (1 << (32 - i)) + 1;
  147: 	    mask.ip4.s_addr = htonl(mask.ip4.s_addr);
  148: 	}
  149: 	addr.ip4.s_addr &= mask.ip4.s_addr;
  150:     }
  151: #ifdef HAVE_STRUCT_IN6_ADDR
  152:     else {
  153: 	if (inet_pton(AF_INET6, m, &mask.ip6) != 1) {
  154: 	    j = strtonum(m, 0, 128, &errstr);
  155: 	    if (errstr != NULL) {
  156: 		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
  157: 		    "IPv6 netmask %s: %s", m, errstr);
  158: 		debug_return_bool(false);
  159: 	    }
  160: 	    for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
  161: 		if (j < i * 8)
  162: 		    mask.ip6.s6_addr[i] = 0;
  163: 		else if (i * 8 + 8 <= j)
  164: 		    mask.ip6.s6_addr[i] = 0xff;
  165: 		else
  166: 		    mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8);
  167: 		addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i];
  168: 	    }
  169: 	}
  170:     }
  171: #endif /* HAVE_STRUCT_IN6_ADDR */
  172: 
  173:     SLIST_FOREACH(ifp, get_interfaces(), entries) {
  174: 	if (ifp->family != family)
  175: 	    continue;
  176: 	switch (family) {
  177: 	    case AF_INET:
  178: 		if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
  179: 		    debug_return_bool(true);
  180: 		break;
  181: #ifdef HAVE_STRUCT_IN6_ADDR
  182: 	    case AF_INET6:
  183: 		for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
  184: 		    if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
  185: 			break;
  186: 		}
  187: 		if (j == sizeof(addr.ip6.s6_addr))
  188: 		    debug_return_bool(true);
  189: 		break;
  190: #endif /* HAVE_STRUCT_IN6_ADDR */
  191: 	}
  192:     }
  193: 
  194:     debug_return_bool(false);
  195: }
  196: 
  197: /*
  198:  * Returns true if "n" is one of our ip addresses or if
  199:  * "n" is a network that we are on, else returns false.
  200:  */
  201: bool
  202: addr_matches(char *n)
  203: {
  204:     char *m;
  205:     bool rc;
  206:     debug_decl(addr_matches, SUDO_DEBUG_MATCH)
  207: 
  208:     /* If there's an explicit netmask, use it. */
  209:     if ((m = strchr(n, '/'))) {
  210: 	*m++ = '\0';
  211: 	rc = addr_matches_if_netmask(n, m);
  212: 	*(m - 1) = '/';
  213:     } else
  214: 	rc = addr_matches_if(n);
  215: 
  216:     sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
  217: 	"IP address %s matches local host: %s", n, rc ? "true" : "false");
  218:     debug_return_bool(rc);
  219: }

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