From 4616de0e3156ca162a5411e55540447aa761f058 Mon Sep 17 00:00:00 2001 From: kzak Date: Jul 16 2006 22:37:37 +0000 Subject: IPv6 and keyring support --- diff --git a/sudo-1.6.8p12-ipv6.patch b/sudo-1.6.8p12-ipv6.patch new file mode 100644 index 0000000..bf0ec83 --- /dev/null +++ b/sudo-1.6.8p12-ipv6.patch @@ -0,0 +1,611 @@ +--- sudo-1.6.8p12/Makefile.in.ipv6 2005-11-08 19:21:58.000000000 +0100 ++++ sudo-1.6.8p12/Makefile.in 2006-07-16 23:33:58.000000000 +0200 +@@ -187,14 +187,14 @@ + @DEV@PARSESRCS = sudo.tab.h sudo.tab.c lex.yy.c def_data.c def_data.h + + # Uncomment the following if you intend to modify parse.yacc +-@DEV@sudo.tab.c sudo.tab.h: parse.yacc +-@DEV@ rm -f sudo.tab.h sudo.tab.c +-@DEV@ $(YACC) -d -b sudo $(srcdir)/parse.yacc ++sudo.tab.c sudo.tab.h: parse.yacc ++ rm -f sudo.tab.h sudo.tab.c ++ $(YACC) -d -b sudo $(srcdir)/parse.yacc + + # Uncomment the following if you intend to modify parse.lex +-@DEV@lex.yy.c: parse.lex +-@DEV@ rm -f lex.yy.c +-@DEV@ $(LEX) $(srcdir)/parse.lex ++lex.yy.c: parse.lex ++ rm -f lex.yy.c ++ $(LEX) $(srcdir)/parse.lex + + # Uncomment the following if you intend to modify def_data.in + @DEV@def_data.h def_data.c: def_data.in +--- sudo-1.6.8p12/visudo.c.ipv6 2004-11-25 18:32:40.000000000 +0100 ++++ sudo-1.6.8p12/visudo.c 2006-07-16 23:33:58.000000000 +0200 +@@ -87,6 +87,7 @@ + static int check_syntax __P((int)); + int command_matches __P((char *, char *)); + int addr_matches __P((char *)); ++int addr6_matches __P((char *)); + int hostname_matches __P((char *, char *, char *)); + int netgr_matches __P((char *, char *, char *, char *)); + int usergr_matches __P((char *, char *, struct passwd *)); +@@ -515,6 +516,12 @@ + return(TRUE); + } + ++int addr6_matches(n) ++ char *n; ++{ ++ return(TRUE); ++} ++ + int + hostname_matches(s, l, p) + char *s, *l, *p; +--- sudo-1.6.8p12/parse.lex.ipv6 2004-05-17 22:51:13.000000000 +0200 ++++ sudo-1.6.8p12/parse.lex 2006-07-16 23:33:58.000000000 +0200 +@@ -84,6 +84,29 @@ + + OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]) + DOTTEDQUAD {OCTET}(\.{OCTET}){3} ++ ++IPV6_8HEX ([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4} ++ ++IPV6_COMP0 :(:[0-9A-Fa-f]{1,4}){1,7} ++IPV6_COMP1 ([0-9A-Fa-f]{1,4}){1}:(:[0-9A-Fa-f]{1,4}){0,6} ++IPV6_COMP2 ([0-9A-Fa-f]{1,4}){2}:(:[0-9A-Fa-f]{1,4}){0,5} ++IPV6_COMP3 ([0-9A-Fa-f]{1,4}){3}:(:[0-9A-Fa-f]{1,4}){0,4} ++IPV6_COMP4 ([0-9A-Fa-f]{1,4}){4}:(:[0-9A-Fa-f]{1,4}){0,3} ++IPV6_COMP5 ([0-9A-Fa-f]{1,4}){5}:(:[0-9A-Fa-f]{1,4}){0,2} ++IPV6_COMP6 ([0-9A-Fa-f]{1,4}){6}:(:[0-9A-Fa-f]{1,4}){0,1} ++IPV6_COMPHEX {IPV6_COMP0}|{IPV6_COMP1}|{IPV6_COMP2}|{IPV6_COMP3}|{IPV6_COMP4}|{IPV6_COMP5}|{IPV6_COMP6} ++ ++IPV6_6H4D [0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){5}{DOTTEDQUAD} ++ ++IPV6_COMP6H4D0 ([0-9A-Fa-f]{1,4}){1}:(:[0-9A-Fa-f]{1,4}){1,4}:{DOTTEDQUAD} ++IPV6_COMP6H4D1 ([0-9A-Fa-f]{1,4}){2}:(:[0-9A-Fa-f]{1,4}){1,3}:{DOTTEDQUAD} ++IPV6_COMP6H4D2 ([0-9A-Fa-f]{1,4}){3}:(:[0-9A-Fa-f]{1,4}){1,2}:{DOTTEDQUAD} ++IPV6_COMP6H4D3 ([0-9A-Fa-f]{1,4}){4}:(:[0-9A-Fa-f]{1,4}){1}:{DOTTEDQUAD} ++IPV6_COMP6H4D {IPV6_COMP6H4D0}|{IPV6_COMP6H4D1}|{IPV6_COMP6H4D2}|{IPV6_COMP6H4D3} ++ ++IPV6ADDR {IPV6_8HEX}|{IPV6_COMPHEX}|{IPV6_6H4D}|{IPV6_COMP6H4D} ++IPV6PREFIX [1-9]|[1-9][0-9]|10[0-9]|11[0-9]|12[0-8] ++ + HOSTNAME [[:alnum:]_-]+ + WORD ([^#>@!=:,\(\) \t\n\\]|\\[^\n])+ + ENVAR ([^#!=, \t\n\\]|\\[^\n])([^#=, \t\n\\]|\\[^\n])* +@@ -253,6 +276,11 @@ + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } ++{IPV6ADDR}(\/{IPV6PREFIX})? { ++ fill(yytext, yyleng); ++ LEXTRACE("NTWKADDR6 "); ++ return(NTWKADDR6); ++ } + + \( { + BEGIN GOTRUNAS; +--- sudo-1.6.8p12/ldap.c.ipv6 2006-07-16 23:45:35.000000000 +0200 ++++ sudo-1.6.8p12/ldap.c 2006-07-16 23:59:56.000000000 +0200 +@@ -160,6 +160,7 @@ + if ( + !strcasecmp(*p,"ALL") || + addr_matches(*p) || ++ addr6_matches(*p) || + netgr_matches(*p,user_host,user_shost,NULL) || + !hostname_matches(user_shost,user_host,*p) + ) +--- sudo-1.6.8p12/parse.h.ipv6 2005-06-19 20:58:19.000000000 +0200 ++++ sudo-1.6.8p12/parse.h 2006-07-16 23:33:58.000000000 +0200 +@@ -93,6 +93,7 @@ + * Prototypes + */ + int addr_matches __P((char *)); ++int addr6_matches __P((char *)); + int command_matches __P((char *, char *)); + int hostname_matches __P((char *, char *, char *)); + int netgr_matches __P((char *, char *, char *, char *)); +--- sudo-1.6.8p12/interfaces.h.ipv6 2004-02-13 22:36:43.000000000 +0100 ++++ sudo-1.6.8p12/interfaces.h 2006-07-16 23:33:58.000000000 +0200 +@@ -27,8 +27,11 @@ + * IP address and netmask pairs for checking against local interfaces. + */ + struct interface { +- struct in_addr addr; ++ struct in_addr addr; /* IPv4 */ + struct in_addr netmask; ++ struct in6_addr addr6; /* IPv6 */ ++ struct in6_addr netmask6; ++ sa_family_t sa_family; /* AF_INET ? AF_INET6 */ + }; + + /* +--- sudo-1.6.8p12/parse.c.ipv6 2005-06-19 22:03:24.000000000 +0200 ++++ sudo-1.6.8p12/parse.c 2006-07-16 23:57:20.000000000 +0200 +@@ -370,38 +370,134 @@ + int i; + char *m; + struct in_addr addr, mask; ++ struct addrinfo hints, *ai; ++ ++ memset(&hints, '\0', sizeof(hints)); ++ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; ++ hints.ai_family = AF_INET; + + /* If there's an explicit netmask, use it. */ + if ((m = strchr(n, '/'))) { ++ + *m++ = '\0'; +- addr.s_addr = inet_addr(n); ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr.s_addr, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, ++ sizeof(struct in_addr)); ++ freeaddrinfo(ai); ++ + if (strchr(m, '.')) +- mask.s_addr = inet_addr(m); +- else { +- i = 32 - atoi(m); +- mask.s_addr = 0xffffffff; +- mask.s_addr >>= i; +- mask.s_addr <<= i; +- mask.s_addr = htonl(mask.s_addr); ++ { ++ if (getaddrinfo(m, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&mask.s_addr, /* IPv4 netmask from dotted quad */ ++ &((struct sockaddr_in *)ai->ai_addr)->sin_addr, ++ sizeof(struct in_addr)); + } ++ else ++ { ++ i = 32 - atoi(m); /* IPv4 netmask from CIDR */ ++ mask.s_addr = 0xffffffff; ++ mask.s_addr >>= i; ++ mask.s_addr <<= i; ++ mask.s_addr = htonl(mask.s_addr); ++ } ++ + *(m - 1) = '/'; + +- for (i = 0; i < num_interfaces; i++) +- if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr) +- return(TRUE); ++ for (i = 0; i < num_interfaces; ++i) ++ if (interfaces[i].sa_family == AF_INET) /* IPv4 intf. only */ ++ if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr) ++ return (TRUE); + } else { +- addr.s_addr = inet_addr(n); ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr.s_addr, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, ++ sizeof(struct in_addr)); ++ freeaddrinfo(ai); + + 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); ++ if (interfaces[i].sa_family == AF_INET) /* IPv4 intf. only */ ++ if (interfaces[i].addr.s_addr == addr.s_addr || ++ (interfaces[i].addr.s_addr & interfaces[i].netmask.s_addr) ++ == addr.s_addr) ++ return(TRUE); + } + + return(FALSE); + } + ++int ++addr6_matches(n) ++char *n; ++{ ++ int i, j; ++ uint32_t msk[4] = {0, 0, 0, 0}; /* 32x4 */ ++ uint32_t addr[4], i_msk[4], i_addr[4]; ++ char *m; ++ struct addrinfo hints, *ai; ++ ++ memset(&hints, '\0', sizeof(hints)); ++ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; ++ hints.ai_family = AF_INET6; ++ ++ /* we have IPv6 prefix */ ++ if ((m = strchr(n, '/'))) { ++ *m++ = '\0'; ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, 16); ++ freeaddrinfo(ai); ++ ++ for (i=0; i < (atoi(m)/32); ++i) ++ msk[i] = 0xffffffff; ++ if (atoi(m)<128 && (atoi(m) % 32)) ++ { ++ msk[atoi(m)/32] = 0xffffffff; ++ msk[atoi(m)/32] >>= ( 32 - (atoi(m) % 32) ); ++ msk[atoi(m)/32] <<= ( 32 - (atoi(m) % 32) ); ++ } ++ for (i=0; i<4; ++i) ++ msk[i] = htonl(msk[i]); ++ ++ *(m - 1) = '/'; ++ ++ for (i=0; i < num_interfaces; i++) ++ if (interfaces[i].sa_family == AF_INET6) /* compare only IPv6 intf. */ ++ { ++ /* nasty */ ++ memcpy(&i_addr, &interfaces[i].addr6, 16); ++ if ( ((i_addr[0] & msk[0]) == addr[0]) && ++ ((i_addr[1] & msk[1]) == addr[1]) && ++ ((i_addr[2] & msk[2]) == addr[2]) && ++ ((i_addr[3] & msk[3]) == addr[3])) ++ return(TRUE); ++ } ++ } else { ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, 16); ++ freeaddrinfo(ai); ++ ++ for (i=0; i < num_interfaces; ++i) ++ if (interfaces[i].sa_family == AF_INET6) /* IPv6 intf. only */ ++ { ++ memcpy(&i_addr, &interfaces[i].addr6, 16); ++ if ((i_addr[0] == addr[0]) && (i_addr[1] == addr[1]) && ++ (i_addr[2] == addr[2]) && (i_addr[3] == addr[3])) ++ return(TRUE); /* found my own address in sudoers */ ++ ++ memcpy(&i_msk, &interfaces[i].netmask6, 16); ++ if (((i_addr[0]&i_msk[0]) == addr[0]) && ++ ((i_addr[1]&i_msk[1]) == addr[1]) && ++ ((i_addr[2]&i_msk[2]) == addr[2]) && ++ ((i_addr[3]&i_msk[3]) == addr[3])) ++ return(TRUE); /* found my netw. address in sudoers */ ++ } ++ } ++ return(FALSE); ++} ++ + /* + * Returns 0 if the hostname matches the pattern and non-zero otherwise. + */ +--- sudo-1.6.8p12/sudo.c.ipv6 2006-07-16 23:33:58.000000000 +0200 ++++ sudo-1.6.8p12/sudo.c 2006-07-16 23:33:58.000000000 +0200 +@@ -1007,24 +1007,34 @@ + void + set_fqdn() + { +- struct hostent *hp; ++ struct addrinfo hints, *ai; + char *p; + +- if (!(hp = gethostbyname(user_host))) { +- log_error(MSG_ONLY|NO_EXIT, +- "unable to lookup %s via gethostbyname()", user_host); +- } else { +- if (user_shost != user_host) ++ memset(&hints, '\0', sizeof(hints)); ++ hints.ai_flags = AI_ADDRCONFIG; ++ ++ if (getaddrinfo(user_host, NULL, &hints, &ai) != 0) ++ { ++ log_error(MSG_ONLY|NO_EXIT, ++ "unable to lookup %s via gethostbyname()", user_host); ++ } ++ else ++ { ++ char h_name[NI_MAXHOST]; ++ ++ if (user_host != user_host) + free(user_shost); ++ ++ getnameinfo(ai->ai_addr, ai->ai_addrlen, h_name, sizeof(h_name), NULL, 0, 0); + free(user_host); +- user_host = estrdup(hp->h_name); ++ user_host = estrdup(h_name); + } + if ((p = strchr(user_host, '.'))) { +- *p = '\0'; +- user_shost = estrdup(user_host); +- *p = '.'; ++ *p = '\0'; ++ user_shost = estrdup(user_host); ++ *p = '.'; + } else { +- user_shost = user_host; ++ user_shost = user_host; + } + } + +--- sudo-1.6.8p12/parse.yacc.ipv6 2005-06-19 20:24:32.000000000 +0200 ++++ sudo-1.6.8p12/parse.yacc 2006-07-16 23:33:58.000000000 +0200 +@@ -250,6 +250,7 @@ + %token RUNASALIAS /* Runas_Alias keyword */ + %token ':' '=' ',' '!' '+' '-' /* union member tokens */ + %token ERROR ++%token NTWKADDR6 /* IPv6 address */ + + /* + * NOTE: these are not true booleans as there are actually 4 possible values: +@@ -395,6 +396,13 @@ + $$ = NOMATCH; + free($1); + } ++ | NTWKADDR6 { ++ if (addr6_matches($1)) ++ $$ = TRUE; ++ else ++ $$ = NOMATCH; ++ free($1); ++ } + | NETGROUP { + if (netgr_matches($1, user_host, user_shost, NULL)) + $$ = TRUE; +--- sudo-1.6.8p12/testsudoers.c.ipv6 2004-08-02 20:44:58.000000000 +0200 ++++ sudo-1.6.8p12/testsudoers.c 2006-07-17 00:03:50.000000000 +0200 +@@ -175,6 +175,10 @@ + } + } + ++/* ++ * 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; +@@ -182,39 +186,136 @@ + int i; + char *m; + struct in_addr addr, mask; ++ struct addrinfo hints, *ai; ++ ++ memset(&hints, '\0', sizeof(hints)); ++ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; ++ hints.ai_family = AF_INET; + + /* If there's an explicit netmask, use it. */ + if ((m = strchr(n, '/'))) { +- *m++ = '\0'; +- addr.s_addr = inet_addr(n); +- if (strchr(m, '.')) +- mask.s_addr = inet_addr(m); +- else { +- i = 32 - atoi(m); +- mask.s_addr = 0xffffffff; +- mask.s_addr >>= i; +- mask.s_addr <<= i; +- mask.s_addr = htonl(mask.s_addr); +- } +- *(m - 1) = '/'; + +- for (i = 0; i < num_interfaces; i++) +- if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr) +- return(TRUE); ++ *m++ = '\0'; ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr.s_addr, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, ++ sizeof(struct in_addr)); ++ freeaddrinfo(ai); ++ ++ if (strchr(m, '.')) ++ { ++ if (getaddrinfo(m, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&mask.s_addr, /* IPv4 netmask from dotted quad */ ++ &((struct sockaddr_in *)ai->ai_addr)->sin_addr, ++ sizeof(struct in_addr)); ++ } ++ else ++ { ++ i = 32 - atoi(m); /* IPv4 netmask from CIDR */ ++ mask.s_addr = 0xffffffff; ++ mask.s_addr >>= i; ++ mask.s_addr <<= i; ++ mask.s_addr = htonl(mask.s_addr); ++ } ++ ++ *(m - 1) = '/'; ++ ++ for (i = 0; i < num_interfaces; ++i) ++ if (interfaces[i].sa_family == AF_INET) /* IPv4 intf. only */ ++ 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); ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr.s_addr, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, ++ sizeof(struct in_addr)); ++ freeaddrinfo(ai); ++ ++ for (i = 0; i < num_interfaces; i++) ++ if (interfaces[i].sa_family == AF_INET) /* IPv4 intf. only */ ++ if (interfaces[i].addr.s_addr == addr.s_addr || ++ (interfaces[i].addr.s_addr & interfaces[i].netmask.s_addr) ++ == addr.s_addr) ++ return(TRUE); + } + + return(FALSE); + } + + int ++addr6_matches(n) ++char *n; ++{ ++ int i, j; ++ uint32_t msk[4] = {0, 0, 0, 0}; /* 32x4 */ ++ uint32_t addr[4], i_msk[4], i_addr[4]; ++ char *m; ++ struct addrinfo hints, *ai; ++ ++ memset(&hints, '\0', sizeof(hints)); ++ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; ++ hints.ai_family = AF_INET6; ++ ++ /* we have IPv6 prefix */ ++ if ((m = strchr(n, '/'))) { ++ *m++ = '\0'; ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, 16); ++ freeaddrinfo(ai); ++ ++ for (i=0; i < (atoi(m)/32); ++i) ++ msk[i] = 0xffffffff; ++ if (atoi(m)<128 && (atoi(m) % 32)) ++ { ++ msk[atoi(m)/32] = 0xffffffff; ++ msk[atoi(m)/32] >>= ( 32 - (atoi(m) % 32) ); ++ msk[atoi(m)/32] <<= ( 32 - (atoi(m) % 32) ); ++ } ++ for (i=0; i<4; ++i) ++ msk[i] = htonl(msk[i]); ++ ++ *(m - 1) = '/'; ++ ++ for (i=0; i < num_interfaces; i++) ++ if (interfaces[i].sa_family == AF_INET6) /* compare only IPv6 intf. */ ++ { ++ /* nasty */ ++ memcpy(&i_addr, &interfaces[i].addr6, 16); ++ if ( ((i_addr[0] & msk[0]) == addr[0]) && ++ ((i_addr[1] & msk[1]) == addr[1]) && ++ ((i_addr[2] & msk[2]) == addr[2]) && ++ ((i_addr[3] & msk[3]) == addr[3])) ++ return (TRUE); ++ } ++ } else { ++ if (getaddrinfo(n, NULL, &hints, &ai)!=0) ++ return(FALSE); ++ memcpy(&addr, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, 16); ++ freeaddrinfo(ai); ++ ++ for (i=0; i < num_interfaces; ++i) ++ if (interfaces[i].sa_family == AF_INET6) /* IPv6 intf. only */ ++ { ++ memcpy(&i_addr, &interfaces[i].addr6, 16); ++ if ((i_addr[0] == addr[0]) && (i_addr[1] == addr[1]) && ++ (i_addr[2] == addr[2]) && (i_addr[3] == addr[3])) ++ return (TRUE); /* found my own address in sudoers */ ++ ++ memcpy(&i_msk, &interfaces[i].netmask6, 16); ++ if (((i_addr[0]&i_msk[0]) == addr[0]) && ++ ((i_addr[1]&i_msk[1]) == addr[1]) && ++ ((i_addr[2]&i_msk[2]) == addr[2]) && ++ ((i_addr[3]&i_msk[3]) == addr[3])) ++ return (TRUE); /* found my netw. address in sudoers */ ++ } ++ } ++ return(FALSE); ++} ++ ++ ++int + hostname_matches(shost, lhost, pattern) + char *shost; + char *lhost; +--- sudo-1.6.8p12/interfaces.c.ipv6 2004-02-13 22:36:43.000000000 +0100 ++++ sudo-1.6.8p12/interfaces.c 2006-07-16 23:33:58.000000000 +0200 +@@ -102,7 +102,7 @@ + load_interfaces() + { + struct ifaddrs *ifa, *ifaddrs; +- /* XXX - sockaddr_in6 sin6; */ ++ struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + int i; + +@@ -117,12 +117,15 @@ + continue; + + switch(ifa->ifa_addr->sa_family) { +- /* XXX - AF_INET6 */ + case AF_INET: + num_interfaces++; + break; ++ case AF_INET6: ++ num_interfaces++; ++ break; + } + } ++ + if (num_interfaces == 0) + return; + interfaces = +@@ -136,8 +139,8 @@ + continue; + + switch(ifa->ifa_addr->sa_family) { +- /* XXX - AF_INET6 */ + case AF_INET: ++ interfaces[i].sa_family = AF_INET; + sin = (struct sockaddr_in *)ifa->ifa_addr; + memcpy(&interfaces[i].addr, &sin->sin_addr, + sizeof(struct in_addr)); +@@ -146,6 +149,16 @@ + sizeof(struct in_addr)); + i++; + break; ++ case AF_INET6: ++ interfaces[i].sa_family = AF_INET6; ++ sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; ++ memcpy(&interfaces[i].addr6, &sin6->sin6_addr, ++ sizeof(struct in6_addr)); ++ sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask; ++ memcpy(&interfaces[i].netmask6, &sin6->sin6_addr, ++ sizeof(struct in6_addr)); ++ i++; ++ break; + } + } + #ifdef HAVE_FREEIFADDRS +@@ -306,10 +319,30 @@ + void + dump_interfaces() + { +- int i; ++ int i, j, ip6_prefix=0; /* for counting IPv6 prefix length (in bits!!) */ ++ uint8_t u6_addr8[16]; /* for storing IPv6 netmask */ + + 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)); ++ { ++ char name[NI_MAXHOST], netmask[NI_MAXHOST]; ++ ip6_prefix=0; ++ ++ switch (interfaces[i].sa_family) ++ { ++ case AF_INET: ++ inet_ntop(AF_INET, &interfaces[i].addr, name, NI_MAXHOST); ++ inet_ntop(AF_INET, &interfaces[i].netmask, netmask, NI_MAXHOST); ++ printf("\t%s / %s\n", name, netmask); ++ break; ++ case AF_INET6: ++ inet_ntop(AF_INET6, &interfaces[i].addr6, name, NI_MAXHOST); ++ memcpy(u6_addr8, &interfaces[i].netmask6, 16); ++ for (j=0; j<16; ++j) ++ if (u6_addr8[j] == 255) /* 255 == 0xff */ ++ ip6_prefix=ip6_prefix+8; /* eight bits */ ++ printf("\t%s / %d\n", name, ip6_prefix); ++ break; ++ } ++ } + } diff --git a/sudo-1.6.8p12-pam-login.patch b/sudo-1.6.8p12-pam-login.patch new file mode 100644 index 0000000..acd62e4 --- /dev/null +++ b/sudo-1.6.8p12-pam-login.patch @@ -0,0 +1,116 @@ +--- sudo-1.6.8p12/configure.in.login 2006-07-16 15:25:33.000000000 +0200 ++++ sudo-1.6.8p12/configure.in 2006-07-16 15:49:08.000000000 +0200 +@@ -357,6 +357,17 @@ + ;; + esac]) + ++AC_ARG_WITH(pam-login, [ --with-pam-login enable specific PAM session for sudo -i], ++[case $with_pam_login in ++ yes) AC_DEFINE(HAVE_PAM_LOGIN) ++ AC_MSG_CHECKING(whether to use PAM login) ++ AC_MSG_RESULT(yes) ++ ;; ++ no) ;; ++ *) AC_MSG_ERROR(["--with-pam-login does not take an argument."]) ++ ;; ++esac]) ++ + AC_ARG_WITH(AFS, [ --with-AFS enable AFS support], + [case $with_AFS in + yes) AC_DEFINE(HAVE_AFS) +--- sudo-1.6.8p12/sudo.c.login 2006-07-16 15:39:26.000000000 +0200 ++++ sudo-1.6.8p12/sudo.c 2006-07-16 15:41:42.000000000 +0200 +@@ -109,7 +109,7 @@ + static struct passwd *get_authpw __P((void)); + extern int sudo_edit __P((int, char **)); + extern void list_matches __P((void)); +-extern char **rebuild_env __P((char **, int, int)); ++extern char **rebuild_env __P((char **, int)); + extern char **zero_env __P((char **)); + extern struct passwd *sudo_getpwnam __P((const char *)); + extern struct passwd *sudo_getpwuid __P((uid_t)); +@@ -140,6 +140,7 @@ + #endif /* HAVE_BSD_AUTH_H */ + sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld; + void (*set_perms) __P((int)); ++int sudo_mode; + + + int +@@ -151,7 +152,6 @@ + int validated; + int fd; + int cmnd_status; +- int sudo_mode; + int pwflag; + char **new_environ; + sigaction_t sa; +@@ -368,7 +368,7 @@ + + /* Build a new environment that avoids any nasty bits if we have a cmnd. */ + if (ISSET(sudo_mode, MODE_RUN)) +- new_environ = rebuild_env(envp, sudo_mode, ISSET(validated, FLAG_NOEXEC)); ++ new_environ = rebuild_env(envp, ISSET(validated, FLAG_NOEXEC)); + else + new_environ = envp; + +--- sudo-1.6.8p12/auth/pam.c.login 2006-07-16 15:41:59.000000000 +0200 ++++ sudo-1.6.8p12/auth/pam.c 2006-07-16 15:45:15.000000000 +0200 +@@ -89,7 +89,12 @@ + if (auth != NULL) + auth->data = (VOID *) &pam_status; + pam_conv.conv = sudo_conv; +- pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); ++#ifdef HAVE_PAM_LOGIN ++ if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) ++ pam_status = pam_start("sudo-i", pw->pw_name, &pam_conv, &pamh); ++ else ++#endif ++ pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); + if (pam_status != PAM_SUCCESS) { + log_error(USE_ERRNO|NO_EXIT|NO_MAIL, "unable to initialize PAM"); + return(AUTH_FATAL); +--- sudo-1.6.8p12/env.c.login 2006-07-16 15:40:14.000000000 +0200 ++++ sudo-1.6.8p12/env.c 2006-07-16 15:57:19.000000000 +0200 +@@ -77,7 +77,7 @@ + /* + * Prototypes + */ +-char **rebuild_env __P((char **, int, int)); ++char **rebuild_env __P((char **, int)); + char **zero_env __P((char **)); + static void insert_env __P((char *, int)); + static char *format_env __P((char *, ...)); +@@ -321,9 +321,8 @@ + * Also adds sudo-specific variables (SUDO_*). + */ + char ** +-rebuild_env(envp, sudo_mode, noexec) ++rebuild_env(envp, noexec) + char **envp; +- int sudo_mode; + int noexec; + { + char **ep, *cp, *ps1; +--- sudo-1.6.8p12/sudo.h.login 2006-07-16 15:59:08.000000000 +0200 ++++ sudo-1.6.8p12/sudo.h 2006-07-16 15:59:38.000000000 +0200 +@@ -251,6 +251,7 @@ + extern FILE *sudoers_fp; + extern int tgetpass_flags; + extern uid_t timestamp_uid; ++extern int sudo_mode; + + extern void (*set_perms) __P((int)); + #endif +--- sudo-1.6.8p12/config.h.in.login 2006-07-16 15:32:09.000000000 +0200 ++++ sudo-1.6.8p12/config.h.in 2006-07-16 15:32:56.000000000 +0200 +@@ -230,6 +230,9 @@ + /* Define to 1 if you use PAM authentication. */ + #undef HAVE_PAM + ++/* Define to 1 if you use specific PAM session for sodo -i. */ ++#undef HAVE_PAM_LOGIN ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_PAM_PAM_APPL_H + diff --git a/sudo.spec b/sudo.spec index 98b2e9b..5bc3517 100644 --- a/sudo.spec +++ b/sudo.spec @@ -1,7 +1,7 @@ Summary: Allows restricted root access for specified users. Name: sudo Version: 1.6.8p12 -Release: 6.1 +Release: 7 License: BSD Group: Applications/System Source: http://www.courtesan.com/sudo/dist/sudo-%{version}.tar.gz @@ -12,6 +12,8 @@ Requires: /etc/pam.d/system-auth, vim-minimal BuildRequires: pam-devel BuildRequires: groff BuildRequires: openldap-devel +BuildRequires: flex +BuildRequires: bison # 154511 - sudo does not use limits.conf Patch2: sudo-1.6.8p8-pam-sess.patch @@ -21,6 +23,10 @@ Patch3: sudo-1.6.7p5-strip.patch Patch4: sudo-1.6.8p12-env-reset.patch # Default sudoers; require tty (#190062) Patch5: sudo-1.6.8p12-requiretty.patch +# Use specific PAM session for sudo -i (#198755) +Patch6: sudo-1.6.8p12-pam-login.patch +# IPv6 support +Patch7: sudo-1.6.8p12-ipv6.patch %description Sudo (superuser do) allows a system administrator to give certain @@ -39,6 +45,8 @@ on many different machines. %patch3 -p1 -b .strip %patch4 -p1 -b .env_reset %patch5 -p1 -b .tty +%patch6 -p1 -b .login +%patch7 -p1 -b .ipv6 %build %ifarch s390 s390x @@ -47,7 +55,10 @@ F_PIE=-fPIE F_PIE=-fpie %endif -export CFLAGS="$RPM_OPT_FLAGS $F_PIE" LDFLAGS="-pie" +# Note: there is a problem rebuild the ./configure script (for pam-login patch), +# so we use -DHAVE_PAM_LOGIN rather than --with-pam-login... +# (it's workaround that should be fixed) +export CFLAGS="$RPM_OPT_FLAGS $F_PIE -DHAVE_PAM_LOGIN" LDFLAGS="-pie" %configure \ --prefix=%{_prefix} \ @@ -75,6 +86,16 @@ cat > $RPM_BUILD_ROOT/etc/pam.d/sudo << EOF auth include system-auth account include system-auth password include system-auth +session optional pam_keyinit.so revoke +session required pam_limits.so +EOF + +cat > $RPM_BUILD_ROOT/etc/pam.d/sudo-i << EOF +#%PAM-1.0 +auth include sudo +account include sudo +password include sudo +session optional pam_keyinit.so force revoke session required pam_limits.so EOF @@ -87,6 +108,7 @@ rm -rf $RPM_BUILD_ROOT %doc BUGS CHANGES HISTORY LICENSE README RUNSON TODO TROUBLESHOOTING UPGRADE *.pod %attr(0440,root,root) %config(noreplace) /etc/sudoers %config(noreplace) /etc/pam.d/sudo +%config(noreplace) /etc/pam.d/sudo-i %dir /var/run/sudo %attr(4111,root,root) %{_bindir}/sudo %attr(4111,root,root) %{_bindir}/sudoedit @@ -102,6 +124,11 @@ rm -rf $RPM_BUILD_ROOT /bin/chmod 0440 /etc/sudoers || : %changelog +* Sun Jul 16 2006 Karel Zak 1.6.8p12-7 +- fix #198755 - make login processes (sudo -i) initialise session keyring + (thanks for PAM config files to David Howells) +- add IPv6 support (patch by Milan Zazrivec) + * Wed Jul 12 2006 Jesse Keating - 1.6.8p12-6.1 - rebuild