Annotation of embedaddon/sudo/plugins/sudoers/match_addr.c, revision 1.1.1.3

1.1       misho       1: /*
1.1.1.3 ! misho       2:  * Copyright (c) 1996, 1998-2005, 2007-2013
1.1       misho       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: 
1.1.1.2   misho      52: static bool
1.1       misho      53: addr_matches_if(char *n)
                     54: {
                     55:     union sudo_in_addr_un addr;
                     56:     struct interface *ifp;
1.1.1.2   misho      57: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho      58:     int j;
                     59: #endif
                     60:     int family;
1.1.1.2   misho      61:     debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)
1.1       misho      62: 
1.1.1.2   misho      63: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho      64:     if (inet_pton(AF_INET6, n, &addr.ip6) > 0) {
                     65:        family = AF_INET6;
                     66:     } else
1.1.1.2   misho      67: #endif /* HAVE_STRUCT_IN6_ADDR */
1.1       misho      68:     {
                     69:        family = AF_INET;
                     70:        addr.ip4.s_addr = inet_addr(n);
                     71:     }
                     72: 
1.1.1.3 ! misho      73:     for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) {
1.1       misho      74:        if (ifp->family != family)
                     75:            continue;
1.1.1.2   misho      76:        switch (family) {
1.1       misho      77:            case AF_INET:
                     78:                if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
                     79:                    (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
                     80:                    == addr.ip4.s_addr)
1.1.1.2   misho      81:                    debug_return_bool(true);
1.1       misho      82:                break;
1.1.1.2   misho      83: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho      84:            case AF_INET6:
                     85:                if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
                     86:                    sizeof(addr.ip6.s6_addr)) == 0)
1.1.1.2   misho      87:                    debug_return_bool(true);
1.1       misho      88:                for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
                     89:                    if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
                     90:                        break;
                     91:                }
                     92:                if (j == sizeof(addr.ip6.s6_addr))
1.1.1.2   misho      93:                    debug_return_bool(true);
                     94:                break;
                     95: #endif /* HAVE_STRUCT_IN6_ADDR */
1.1       misho      96:        }
                     97:     }
                     98: 
1.1.1.2   misho      99:     debug_return_bool(false);
1.1       misho     100: }
                    101: 
1.1.1.2   misho     102: static bool
1.1       misho     103: addr_matches_if_netmask(char *n, char *m)
                    104: {
                    105:     int i;
                    106:     union sudo_in_addr_un addr, mask;
                    107:     struct interface *ifp;
1.1.1.2   misho     108: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho     109:     int j;
                    110: #endif
                    111:     int family;
1.1.1.2   misho     112:     debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)
1.1       misho     113: 
1.1.1.2   misho     114: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho     115:     if (inet_pton(AF_INET6, n, &addr.ip6) > 0)
                    116:        family = AF_INET6;
                    117:     else
1.1.1.2   misho     118: #endif /* HAVE_STRUCT_IN6_ADDR */
1.1       misho     119:     {
                    120:        family = AF_INET;
                    121:        addr.ip4.s_addr = inet_addr(n);
                    122:     }
                    123: 
                    124:     if (family == AF_INET) {
                    125:        if (strchr(m, '.')) {
                    126:            mask.ip4.s_addr = inet_addr(m);
                    127:        } else {
                    128:            i = atoi(m);
                    129:            if (i == 0)
                    130:                mask.ip4.s_addr = 0;
                    131:            else if (i == 32)
                    132:                mask.ip4.s_addr = 0xffffffff;
                    133:            else
                    134:                mask.ip4.s_addr = 0xffffffff - (1 << (32 - i)) + 1;
                    135:            mask.ip4.s_addr = htonl(mask.ip4.s_addr);
                    136:        }
                    137:        addr.ip4.s_addr &= mask.ip4.s_addr;
                    138:     }
1.1.1.2   misho     139: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho     140:     else {
                    141:        if (inet_pton(AF_INET6, m, &mask.ip6) <= 0) {
                    142:            j = atoi(m);
                    143:            for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
                    144:                if (j < i * 8)
                    145:                    mask.ip6.s6_addr[i] = 0;
                    146:                else if (i * 8 + 8 <= j)
                    147:                    mask.ip6.s6_addr[i] = 0xff;
                    148:                else
                    149:                    mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8);
                    150:                addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i];
                    151:            }
                    152:        }
                    153:     }
1.1.1.2   misho     154: #endif /* HAVE_STRUCT_IN6_ADDR */
1.1       misho     155: 
1.1.1.3 ! misho     156:     for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) {
1.1       misho     157:        if (ifp->family != family)
                    158:            continue;
1.1.1.2   misho     159:        switch (family) {
1.1       misho     160:            case AF_INET:
                    161:                if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
1.1.1.2   misho     162:                    debug_return_bool(true);
                    163:                break;
                    164: #ifdef HAVE_STRUCT_IN6_ADDR
1.1       misho     165:            case AF_INET6:
                    166:                for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
                    167:                    if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
                    168:                        break;
                    169:                }
                    170:                if (j == sizeof(addr.ip6.s6_addr))
1.1.1.2   misho     171:                    debug_return_bool(true);
                    172:                break;
                    173: #endif /* HAVE_STRUCT_IN6_ADDR */
1.1       misho     174:        }
                    175:     }
                    176: 
1.1.1.2   misho     177:     debug_return_bool(false);
1.1       misho     178: }
                    179: 
                    180: /*
1.1.1.2   misho     181:  * Returns true if "n" is one of our ip addresses or if
                    182:  * "n" is a network that we are on, else returns false.
1.1       misho     183:  */
1.1.1.2   misho     184: bool
1.1       misho     185: addr_matches(char *n)
                    186: {
                    187:     char *m;
1.1.1.2   misho     188:     bool retval;
                    189:     debug_decl(addr_matches, SUDO_DEBUG_MATCH)
1.1       misho     190: 
                    191:     /* If there's an explicit netmask, use it. */
                    192:     if ((m = strchr(n, '/'))) {
                    193:        *m++ = '\0';
                    194:        retval = addr_matches_if_netmask(n, m);
                    195:        *(m - 1) = '/';
                    196:     } else
                    197:        retval = addr_matches_if(n);
                    198: 
1.1.1.2   misho     199:     debug_return_bool(retval);
1.1       misho     200: }

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