2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-31 14:25:15 +00:00

Add IPv6 support; adapted from patches by YOSHIFUJI Hideaki

This commit is contained in:
Todd C. Miller
2007-08-13 16:29:25 +00:00
parent 0a96fe4076
commit d65602ca6f
6 changed files with 205 additions and 34 deletions

2
gram.y
View File

@@ -113,7 +113,7 @@ yyerror(s)
%token <command> COMMAND /* absolute pathname w/ optional args */
%token <string> ALIAS /* an UPPERCASE alias name */
%token <string> DEFVAR /* a Defaults variable name */
%token <string> NTWKADDR /* w.x.y.z */
%token <string> NTWKADDR /* ipv4 or ipv6 address */
%token <string> NETGROUP /* a netgroup (+NAME) */
%token <string> USERGROUP /* a usergroup (%NAME) */
%token <string> WORD /* a word */

View File

@@ -98,8 +98,10 @@ void
load_interfaces()
{
struct ifaddrs *ifa, *ifaddrs;
/* XXX - sockaddr_in6 sin6; */
struct sockaddr_in *sin;
#ifdef AF_INET6
struct sockaddr_in6 *sin6;
#endif
int i;
if (getifaddrs(&ifaddrs))
@@ -113,8 +115,10 @@ load_interfaces()
continue;
switch(ifa->ifa_addr->sa_family) {
/* XXX - AF_INET6 */
case AF_INET:
#ifdef AF_INET6
case AF_INET6:
#endif
num_interfaces++;
break;
}
@@ -132,7 +136,6 @@ load_interfaces()
continue;
switch(ifa->ifa_addr->sa_family) {
/* XXX - AF_INET6 */
case AF_INET:
sin = (struct sockaddr_in *)ifa->ifa_addr;
memcpy(&interfaces[i].addr, &sin->sin_addr,
@@ -140,8 +143,21 @@ load_interfaces()
sin = (struct sockaddr_in *)ifa->ifa_netmask;
memcpy(&interfaces[i].netmask, &sin->sin_addr,
sizeof(struct in_addr));
interfaces[i].family = AF_INET;
i++;
break;
#ifdef AF_INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
memcpy(&interfaces[i].addr, &sin6->sin6_addr,
sizeof(struct in6_addr));
sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask;
memcpy(&interfaces[i].netmask, &sin6->sin6_addr,
sizeof(struct in6_addr));
interfaces[i].family = AF_INET6;
i++;
break;
#endif /* AF_INET6 */
}
}
#ifdef HAVE_FREEIFADDRS
@@ -271,6 +287,7 @@ load_interfaces()
}
/* Only now can we be sure it was a good/interesting interface. */
interfaces[num_interfaces].family = AF_INET;
num_interfaces++;
}
@@ -303,9 +320,26 @@ void
dump_interfaces()
{
int i;
#ifdef AF_INET6
char addrbuf[INET6_ADDRSTRLEN], maskbuf[INET6_ADDRSTRLEN];
#endif
puts("Local IP address and netmask pairs:");
for (i = 0; i < num_interfaces; i++)
printf("\t%s / 0x%x\n", inet_ntoa(interfaces[i].addr),
(unsigned int)ntohl(interfaces[i].netmask.s_addr));
for (i = 0; i < num_interfaces; i++) {
switch(interfaces[i].family) {
case AF_INET:
printf("\t%s / ", inet_ntoa(interfaces[i].addr.ip4));
puts(inet_ntoa(interfaces[i].netmask.ip4));
break;
#ifdef AF_INET6
case AF_INET6:
inet_ntop(AF_INET6, &interfaces[i].addr.ip6,
addrbuf, sizeof(addrbuf));
inet_ntop(AF_INET6, &interfaces[i].netmask.ip6,
maskbuf, sizeof(maskbuf));
printf("\t%s / %s\n", addrbuf, maskbuf);
break;
#endif /* AF_INET6 */
}
}
}

View File

@@ -27,8 +27,19 @@
* IP address and netmask pairs for checking against local interfaces.
*/
struct interface {
struct in_addr addr;
struct in_addr netmask;
int family; /* AF_INET or AF_INET6 */
union {
struct in_addr ip4;
#ifdef AF_INET6
struct in6_addr ip6;
#endif
} addr;
union {
struct in_addr ip4;
#ifdef AF_INET6
struct in6_addr ip6;
#endif
} netmask;
};
/*

154
match.c
View File

@@ -24,6 +24,7 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef STDC_HEADERS
@@ -418,22 +419,85 @@ command_matches(sudoers_cmnd, sudoers_args)
}
}
/*
* Returns TRUE if "n" is one of our ip addresses or if
* "n" is a network that we are on, else returns FALSE.
*/
int
addr_matches(n)
static int
addr_matches_if(n)
char *n;
{
int i;
char *m;
struct in_addr addr, mask;
struct in_addr addr;
struct interface *ifp;
#ifdef AF_INET6
struct in6_addr addr6;
int j;
#endif
int family = AF_UNSPEC;
/* If there's an explicit netmask, use it. */
if ((m = strchr(n, '/'))) {
*m++ = '\0';
#ifdef AF_INET6
if (inet_pton(AF_INET6, n, &addr6) > 0) {
family = AF_INET6;
} else
#else
{
family = AF_INET;
addr.s_addr = inet_addr(n);
}
#endif
for (i = 0; i < num_interfaces; i++) {
ifp = &interfaces[i];
if (ifp->family != family)
continue;
switch(family) {
case AF_INET:
if (ifp->addr.ip4.s_addr == addr.s_addr ||
(ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
== addr.s_addr)
return(TRUE);
break;
#ifdef AF_INET6
case AF_INET6:
if (memcmp(ifp->addr.ip6.s6_addr, addr6.s6_addr,
sizeof(addr6.s6_addr)) == 0)
return(TRUE);
for (j = 0; j < sizeof(addr6.s6_addr); j++) {
if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr6.s6_addr[j])
break;
}
if (j == sizeof(addr6.s6_addr))
return(TRUE);
#endif
}
}
return(FALSE);
}
static int
addr_matches_if_netmask(n, m)
char *n;
char *m;
{
int i;
struct in_addr addr, mask;
struct interface *ifp;
#ifdef AF_INET6
struct in6_addr addr6, mask6;
int j;
#endif
int family = AF_UNSPEC;
#ifdef AF_INET6
if (inet_pton(AF_INET6, n, &addr6) > 0)
family = AF_INET6;
else
#else
{
family = AF_INET;
addr.s_addr = inet_addr(n);
}
#endif
if (family == AF_INET) {
if (strchr(m, '.'))
mask.s_addr = inet_addr(m);
else {
@@ -443,24 +507,68 @@ addr_matches(n)
mask.s_addr <<= i;
mask.s_addr = htonl(mask.s_addr);
}
*(m - 1) = '/';
}
#ifdef AF_INET6
else {
if (inet_pton(AF_INET6, m, &mask6) <= 0) {
j = atoi(m);
for (i = 0; i < 16; i++) {
if (j < i * 8)
mask6.s6_addr[i] = 0;
else if (i * 8 + 8 <= j)
mask6.s6_addr[i] = 0xff;
else
mask6.s6_addr[i] = 0xff00 >> (j - i * 8);
}
}
}
#endif /* AF_INET6 */
for (i = 0; i < num_interfaces; i++)
if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr)
return(TRUE);
} else {
addr.s_addr = inet_addr(n);
for (i = 0; i < num_interfaces; i++)
if (interfaces[i].addr.s_addr == addr.s_addr ||
(interfaces[i].addr.s_addr & interfaces[i].netmask.s_addr)
== addr.s_addr)
return(TRUE);
for (i = 0; i < num_interfaces; i++) {
ifp = &interfaces[i];
if (ifp->family != family)
continue;
switch(family) {
case AF_INET:
if ((ifp->addr.ip4.s_addr & mask.s_addr) == addr.s_addr)
return(TRUE);
#ifdef AF_INET6
case AF_INET6:
for (j = 0; j < sizeof(addr6.s6_addr); j++) {
if ((ifp->addr.ip6.s6_addr[j] & mask6.s6_addr[j]) != addr6.s6_addr[j])
break;
}
if (j == sizeof(addr6.s6_addr))
return(TRUE);
#endif /* AF_INET6 */
}
}
return(FALSE);
}
/*
* Returns TRUE if "n" is one of our ip addresses or if
* "n" is a network that we are on, else returns FALSE.
*/
int
addr_matches(n)
char *n;
{
char *m;
int retval;
/* If there's an explicit netmask, use it. */
if ((m = strchr(n, '/'))) {
*m++ = '\0';
retval = addr_matches_if_netmask(n, m);
*(m - 1) = '/';
} else
retval = addr_matches_if(n);
return(retval);
}
/*
* Returns TRUE if the hostname matches the pattern, else FALSE
*/

View File

@@ -157,8 +157,9 @@ If you do not specify a netmask along with the network number,
B<sudo> will query each of the local host's network interfaces and,
if the network number corresponds to one of the hosts's network
interfaces, the corresponding netmask will be used. The netmask
may be specified either in dotted quad notation (e.g.E<nbsp>255.255.255.0)
or CIDR notation (number of bits, e.g.E<nbsp>24). A hostname may
may be specified either in standard IP address notation
(e.g.E<nbsp>255.255.255.0 or ffff:ffff:ffff:ffff::),
or CIDR notation (number of bits, e.g.E<nbsp>24 or 64). A hostname may
include shell-style wildcards (see the L<Wildcards> section below),
but unless the C<hostname> command on your machine returns the fully
qualified hostname, you'll need to use the I<fqdn> option for

17
toke.l
View File

@@ -84,8 +84,11 @@ extern void yyerror __P((const char *));
#endif
%}
HEXDIGIT [0-9A-Fa-f]{1,4}
OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
DOTTEDQUAD {OCTET}(\.{OCTET}){3}
IPV6ADDR \:\:|({HEXDIGIT}\:){7}{HEXDIGIT}|({HEXDIGIT}\:){5}{HEXDIGIT}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,7}\:|({HEXDIGIT}\:){1,6}(\:{HEXDIGIT}){1}|({HEXDIGIT}\:){1,5}(\:{HEXDIGIT}){2}|({HEXDIGIT}\:){1,2}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,4}(\:{HEXDIGIT}){3}|({HEXDIGIT}\:){1,4}(\:{HEXDIGIT}){1}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,3}(\:{HEXDIGIT}){4}|({HEXDIGIT}\:){1,3}(\:{HEXDIGIT}){2}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,2}(\:{HEXDIGIT}){5}|({HEXDIGIT}\:){1,2}(\:{HEXDIGIT}){3}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1}(\:{HEXDIGIT}){6}|({HEXDIGIT}\:){1}(\:{HEXDIGIT}){4}\:{DOTTEDQUAD}|\:(\:{HEXDIGIT}){1,7}|\:(\:{HEXDIGIT}){1,5}\:{DOTTEDQUAD}
HOSTNAME [[:alnum:]_-]+
WORD ([^#>!=:,\(\) \t\n\\]|\\[^\n])+
PATH \/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+
@@ -323,6 +326,20 @@ MONITOR[[:blank:]]*: {
return(NTWKADDR);
}
{IPV6ADDR}(\/{IPV6ADDR})? {
if (!fill(yytext, yyleng))
yyterminate();
LEXTRACE("NTWKADDR ");
return(NTWKADDR);
}
{IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) {
if (!fill(yytext, yyleng))
yyterminate();
LEXTRACE("NTWKADDR ");
return(NTWKADDR);
}
<INITIAL>\( {
BEGIN GOTRUNAS;
LEXTRACE("RUNAS ");