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:
2
gram.y
2
gram.y
@@ -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 */
|
||||
|
46
interfaces.c
46
interfaces.c
@@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
interfaces.h
15
interfaces.h
@@ -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
154
match.c
@@ -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
|
||||
*/
|
||||
|
@@ -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
17
toke.l
@@ -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 ");
|
||||
|
Reference in New Issue
Block a user