diff --git a/pam-1.0.90-access-no-resolve.patch b/pam-1.0.90-access-no-resolve.patch new file mode 100644 index 0000000..c005795 --- /dev/null +++ b/pam-1.0.90-access-no-resolve.patch @@ -0,0 +1,199 @@ +Index: modules/pam_access/pam_access.c +=================================================================== +RCS file: /cvsroot/pam/Linux-PAM/modules/pam_access/pam_access.c,v +retrieving revision 1.31 +diff -u -p -r1.31 pam_access.c +--- modules/pam_access/pam_access.c 21 Apr 2008 11:21:12 -0000 1.31 ++++ modules/pam_access/pam_access.c 24 Feb 2009 16:27:58 -0000 +@@ -627,44 +627,10 @@ from_match (pam_handle_t *pamh UNUSED, c + } + freeaddrinfo (res); + } +- } else if (isipaddr(string, NULL, NULL) == YES) { ++ } else { + /* Assume network/netmask with a IP of a host. */ + if (network_netmask_match(pamh, tok, string, item->debug)) + return YES; +- } else { +- /* Assume network/netmask with a name of a host. */ +- struct addrinfo *res; +- struct addrinfo hint; +- +- memset (&hint, '\0', sizeof (hint)); +- hint.ai_flags = AI_CANONNAME; +- hint.ai_family = AF_UNSPEC; +- +- if (getaddrinfo (string, NULL, &hint, &res) != 0) +- return NO; +- else +- { +- struct addrinfo *runp = res; +- +- while (runp != NULL) +- { +- char buf[INET6_ADDRSTRLEN]; +- +- inet_ntop (runp->ai_family, +- runp->ai_family == AF_INET +- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr +- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, +- buf, sizeof (buf)); +- +- if (network_netmask_match(pamh, tok, buf, item->debug)) +- { +- freeaddrinfo (res); +- return YES; +- } +- runp = runp->ai_next; +- } +- freeaddrinfo (res); +- } + } + + return NO; +@@ -701,69 +667,99 @@ string_match (pam_handle_t *pamh, const + + + /* network_netmask_match - match a string against one token +- * where string is an ip (v4,v6) address and tok represents +- * whether a single ip (v4,v6) address or a network/netmask ++ * where string is a hostname or ip (v4,v6) address and tok ++ * represents either a single ip (v4,v6) address or a network/netmask + */ + static int + network_netmask_match (pam_handle_t *pamh, + const char *tok, const char *string, int debug) + { +- if (debug) ++ char *netmask_ptr; ++ char netmask_string[MAXHOSTNAMELEN + 1]; ++ int addr_type; ++ ++ if (debug) + pam_syslog (pamh, LOG_DEBUG, + "network_netmask_match: tok=%s, item=%s", tok, string); ++ /* OK, check if tok is of type addr/mask */ ++ if ((netmask_ptr = strchr(tok, '/')) != NULL) ++ { ++ long netmask = 0; ++ ++ /* YES */ ++ *netmask_ptr = 0; ++ netmask_ptr++; ++ ++ if (isipaddr(tok, &addr_type, NULL) == NO) ++ { /* no netaddr */ ++ return NO; ++ } + +- if (isipaddr(string, NULL, NULL) == YES) +- { +- char *netmask_ptr = NULL; +- static char netmask_string[MAXHOSTNAMELEN + 1] = ""; +- int addr_type; +- +- /* OK, check if tok is of type addr/mask */ +- if ((netmask_ptr = strchr(tok, '/')) != NULL) +- { +- long netmask = 0; +- +- /* YES */ +- *netmask_ptr = 0; +- netmask_ptr++; +- +- if (isipaddr(tok, &addr_type, NULL) == NO) +- { /* no netaddr */ +- return(NO); +- } +- +- /* check netmask */ +- if (isipaddr(netmask_ptr, NULL, NULL) == NO) +- { /* netmask as integre value */ +- char *endptr = NULL; +- netmask = strtol(netmask_ptr, &endptr, 0); +- if ((endptr == NULL) || (*endptr != '\0')) ++ /* check netmask */ ++ if (isipaddr(netmask_ptr, NULL, NULL) == NO) ++ { /* netmask as integre value */ ++ char *endptr = NULL; ++ netmask = strtol(netmask_ptr, &endptr, 0); ++ if ((endptr == NULL) || (*endptr != '\0')) + { /* invalid netmask value */ +- return(NO); ++ return NO; + } +- if ((netmask < 0) || (netmask >= 128)) ++ if ((netmask < 0) || (netmask >= 128)) + { /* netmask value out of range */ +- return(NO); ++ return NO; + } + +- netmask_ptr = number_to_netmask(netmask, addr_type, +- netmask_string, MAXHOSTNAMELEN); +- } +- +- /* Netmask is now an ipv4/ipv6 address. +- * This works also if netmask_ptr is NULL. +- */ +- return (are_addresses_equal(string, tok, netmask_ptr)); ++ netmask_ptr = number_to_netmask(netmask, addr_type, ++ netmask_string, MAXHOSTNAMELEN); ++ } + } +- else ++ else + /* NO, then check if it is only an addr */ +- if (isipaddr(tok, NULL, NULL) == YES) +- { /* check if they are the same, no netmask */ +- return(are_addresses_equal(string, tok, NULL)); ++ if (isipaddr(tok, NULL, NULL) != YES) ++ { ++ return NO; + } +- } + +- return (NO); ++ if (isipaddr(string, NULL, NULL) != YES) ++ { ++ /* Assume network/netmask with a name of a host. */ ++ struct addrinfo *res; ++ struct addrinfo hint; ++ ++ memset (&hint, '\0', sizeof (hint)); ++ hint.ai_flags = AI_CANONNAME; ++ hint.ai_family = AF_UNSPEC; ++ ++ if (getaddrinfo (string, NULL, &hint, &res) != 0) ++ return NO; ++ else ++ { ++ struct addrinfo *runp = res; ++ ++ while (runp != NULL) ++ { ++ char buf[INET6_ADDRSTRLEN]; ++ ++ inet_ntop (runp->ai_family, ++ runp->ai_family == AF_INET ++ ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr ++ : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, ++ buf, sizeof (buf)); ++ ++ if (are_addresses_equal(buf, tok, netmask_ptr)) ++ { ++ freeaddrinfo (res); ++ return YES; ++ } ++ runp = runp->ai_next; ++ } ++ freeaddrinfo (res); ++ } ++ } ++ else ++ return (are_addresses_equal(string, tok, netmask_ptr)); ++ ++ return NO; + } + + diff --git a/pam-1.0.90-strtok-unsigned.patch b/pam-1.0.90-strtok-unsigned.patch new file mode 100644 index 0000000..077dbf3 --- /dev/null +++ b/pam-1.0.90-strtok-unsigned.patch @@ -0,0 +1,102 @@ +--- libpam/pam_misc.c 6 Dec 2007 20:20:07 -0000 1.9 ++++ libpam/pam_misc.c 25 Feb 2009 13:48:23 -0000 +@@ -59,10 +59,11 @@ + + /* initialize table */ + for (i=1; i<256; table[i++] = '\0'); +- for (i=0; format[i] ; table[(int)format[i++]] = 'y'); ++ for (i=0; format[i] ; ++ table[(unsigned char)format[i++]] = 'y'); + + /* look for first non-format char */ +- while (*from && table[(int)*from]) { ++ while (*from && table[(unsigned char)*from]) { + ++from; + } + +@@ -92,7 +93,7 @@ + remains */ + } else if (*from) { + /* simply look for next blank char */ +- for (end=from; *end && !table[(int)*end]; ++end); ++ for (end=from; *end && !table[(unsigned char)*end]; ++end); + } else { + return (*next = NULL); /* no tokens left */ + } +--- tests/Makefile.am 2 Sep 2007 17:02:53 -0000 1.5 ++++ tests/Makefile.am 25 Feb 2009 13:48:24 -0000 +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2006 Thorsten Kukuk ++# Copyright (c) 2006, 2009 Thorsten Kukuk + # + + AM_CFLAGS = -DLIBPAM_COMPILE -I$(top_srcdir)/libpam/include \ +@@ -11,9 +11,9 @@ + TESTS = tst-pam_start tst-pam_end tst-pam_fail_delay tst-pam_open_session \ + tst-pam_close_session tst-pam_acct_mgmt tst-pam_authenticate \ + tst-pam_chauthtok tst-pam_setcred tst-pam_get_item tst-pam_set_item \ +- tst-pam_getenvlist tst-pam_get_user tst-pam_set_data ++ tst-pam_getenvlist tst-pam_get_user tst-pam_set_data \ ++ tst-pam_mkargv + + check_PROGRAMS = ${TESTS} tst-dlopen + + tst_dlopen_LDADD = -ldl +- +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ tests/tst-pam_mkargv.c 25 Feb 2009 13:48:24 -0000 +@@ -0,0 +1,52 @@ ++/* ++ Copyright (C) Thorsten Kukuk 2009 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation in version 2 of the License ++ ++*/ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++ ++#include "libpam/pam_misc.c" ++ ++/* Simple program to see if _pam_mkargv() would succeed. */ ++int main(void) ++{ ++ char *argvstring = "user = XENDT\\userĪ± user=XENDT\\user1"; ++ const char *argvresult[] = {"user", "=", "XENDT\\userĪ±", ++ "user=XENDT\\user1"}; ++ int myargc; ++ char **myargv; ++ int argvlen; ++ int i; ++ ++ argvlen = _pam_mkargv(argvstring, &myargv, &myargc); ++ ++#if 0 ++ printf ("argvlen=%i, argc=%i", argvlen, myargc); ++ for (i = 0; i < myargc; i++) { ++ printf(", argv[%d]=%s", i, myargv[i]); ++ } ++ printf ("\n"); ++#endif ++ ++ if (argvlen != 333) ++ return 1; ++ ++ if (myargc != 4) ++ return 1; ++ ++ for (i = 0; i < 4; i++) ++ { ++ if (strcmp (myargv[i], argvresult[i]) != 0) ++ return 1; ++ } ++ ++ return 0; ++} + diff --git a/pam-1.0.90-unix-mindays.patch b/pam-1.0.90-unix-mindays.patch new file mode 100644 index 0000000..2bdbf6e --- /dev/null +++ b/pam-1.0.90-unix-mindays.patch @@ -0,0 +1,42 @@ +Index: modules/pam_unix/pam_unix_acct.c +=================================================================== +RCS file: /cvsroot/pam/Linux-PAM/modules/pam_unix/pam_unix_acct.c,v +retrieving revision 1.24 +diff -u -r1.24 pam_unix_acct.c +--- modules/pam_unix/pam_unix_acct.c 11 Jul 2008 15:29:00 -0000 1.24 ++++ modules/pam_unix/pam_unix_acct.c 24 Feb 2009 09:57:31 -0000 +@@ -249,6 +249,9 @@ + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _("Your account has expired; please contact your system administrator")); + break; ++ case PAM_AUTHTOK_ERR: ++ retval = PAM_SUCCESS; ++ /* fallthrough */ + case PAM_SUCCESS: + if (daysleft >= 0) { + pam_syslog(pamh, LOG_DEBUG, +Index: modules/pam_unix/passverify.c +=================================================================== +RCS file: /cvsroot/pam/Linux-PAM/modules/pam_unix/passverify.c,v +retrieving revision 1.8 +diff -u -r1.8 passverify.c +--- modules/pam_unix/passverify.c 1 Dec 2008 12:40:41 -0000 1.8 ++++ modules/pam_unix/passverify.c 24 Feb 2009 09:57:32 -0000 +@@ -272,8 +272,16 @@ + *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); + D(("warn before expiry")); + } ++ if ((curdays - spent->sp_lstchg < spent->sp_min) ++ && (spent->sp_min != -1)) { ++ /* ++ * The last password change was too recent. This error will be ignored ++ * if no password change is attempted. ++ */ ++ D(("password change too recent")); ++ return PAM_AUTHTOK_ERR; ++ } + return PAM_SUCCESS; +- + } + + /* passwd/salt conversion macros */ diff --git a/pam.spec b/pam.spec index 400d215..dc40404 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.0.90 -Release: 3%{?dist} +Release: 4%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, # pam_rhosts_auth module is BSD with advertising @@ -21,6 +21,9 @@ Source10: config-util.5 Source11: 90-nproc.conf Patch1: pam-1.0.90-redhat-modules.patch Patch2: pam-1.0.90-mkhomedir-helper.patch +Patch3: pam-1.0.90-unix-mindays.patch +Patch4: pam-1.0.90-access-no-resolve.patch +Patch5: pam-1.0.90-strtok-unsigned.patch %define _sbindir /sbin %define _moduledir /%{_lib}/security @@ -84,6 +87,9 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch1 -p1 -b .redhat-modules %patch2 -p1 -b .mkhomedir-helper +%patch3 -p0 -b .mindays +%patch4 -p0 -b .no-resolve +%patch5 -p0 -b .strtok-unsigned autoreconf @@ -316,6 +322,11 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Fri Feb 27 2009 Tomas Mraz 1.0.90-4 +- fix parsing of config files containing non-ASCII characters +- fix CVE-2009-0579 (mininimum days for password change ignored) (#487216) +- pam_access: improve handling of hostname resolution + * Thu Feb 26 2009 Fedora Release Engineering - 1.0.90-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild