2 * Copyright (c) 1996, 1998-2005, 2007-2015
3 * Todd C. Miller <Todd.Miller@sudo.ws>
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.
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.
17 * Sponsored in part by the Defense Advanced Research Projects
18 * Agency (DARPA) and Air Force Research Laboratory, Air Force
19 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
23 * This is an open source non-commercial project. Dear PVS-Studio, please check it.
24 * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
29 #include <sys/types.h>
30 #include <sys/socket.h>
35 #endif /* HAVE_STRING_H */
38 #endif /* HAVE_STRINGS_H */
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
43 # include <arpa/nameser.h>
45 #endif /* NEED_RESOLV_H */
48 #include "interfaces.h"
51 addr_matches_if(const char *n)
53 union sudo_in_addr_un addr;
54 struct interface *ifp;
55 #ifdef HAVE_STRUCT_IN6_ADDR
59 debug_decl(addr_matches_if, SUDOERS_DEBUG_MATCH)
61 #ifdef HAVE_STRUCT_IN6_ADDR
62 if (inet_pton(AF_INET6, n, &addr.ip6) == 1) {
65 #endif /* HAVE_STRUCT_IN6_ADDR */
66 if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
69 debug_return_bool(false);
72 SLIST_FOREACH(ifp, get_interfaces(), entries) {
73 if (ifp->family != family)
77 if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
78 (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
80 debug_return_bool(true);
82 #ifdef HAVE_STRUCT_IN6_ADDR
84 if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
85 sizeof(addr.ip6.s6_addr)) == 0)
86 debug_return_bool(true);
87 for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
88 if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
91 if (j == sizeof(addr.ip6.s6_addr))
92 debug_return_bool(true);
94 #endif /* HAVE_STRUCT_IN6_ADDR */
98 debug_return_bool(false);
102 addr_matches_if_netmask(const char *n, const char *m)
105 union sudo_in_addr_un addr, mask;
106 struct interface *ifp;
107 #ifdef HAVE_STRUCT_IN6_ADDR
112 debug_decl(addr_matches_if, SUDOERS_DEBUG_MATCH)
114 #ifdef HAVE_STRUCT_IN6_ADDR
115 if (inet_pton(AF_INET6, n, &addr.ip6) == 1)
118 #endif /* HAVE_STRUCT_IN6_ADDR */
119 if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
122 debug_return_bool(false);
125 if (family == AF_INET) {
126 if (strchr(m, '.')) {
127 if (inet_pton(AF_INET, m, &mask.ip4) != 1) {
128 sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
129 "IPv4 netmask %s: %s", m, "invalid value");
130 debug_return_bool(false);
133 i = strtonum(m, 1, 32, &errstr);
134 if (errstr != NULL) {
135 sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
136 "IPv4 netmask %s: %s", m, errstr);
137 debug_return_bool(false);
139 mask.ip4.s_addr = htonl(0xffffffffU << (32 - i));
141 addr.ip4.s_addr &= mask.ip4.s_addr;
143 #ifdef HAVE_STRUCT_IN6_ADDR
145 if (inet_pton(AF_INET6, m, &mask.ip6) != 1) {
146 j = strtonum(m, 1, 128, &errstr);
147 if (errstr != NULL) {
148 sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
149 "IPv6 netmask %s: %s", m, errstr);
150 debug_return_bool(false);
152 for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
154 mask.ip6.s6_addr[i] = 0;
155 else if (i * 8 + 8 <= j)
156 mask.ip6.s6_addr[i] = 0xff;
158 mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8);
159 addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i];
163 #endif /* HAVE_STRUCT_IN6_ADDR */
165 SLIST_FOREACH(ifp, get_interfaces(), entries) {
166 if (ifp->family != family)
170 if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
171 debug_return_bool(true);
173 #ifdef HAVE_STRUCT_IN6_ADDR
175 for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
176 if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
179 if (j == sizeof(addr.ip6.s6_addr))
180 debug_return_bool(true);
182 #endif /* HAVE_STRUCT_IN6_ADDR */
186 debug_return_bool(false);
190 * Returns true if "n" is one of our ip addresses or if
191 * "n" is a network that we are on, else returns false.
194 addr_matches(char *n)
198 debug_decl(addr_matches, SUDOERS_DEBUG_MATCH)
200 /* If there's an explicit netmask, use it. */
201 if ((m = strchr(n, '/'))) {
203 rc = addr_matches_if_netmask(n, m);
206 rc = addr_matches_if(n);
208 sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
209 "IP address %s matches local host: %s", n, rc ? "true" : "false");
210 debug_return_bool(rc);