diff options
author | Steve Langasek <steve.langasek@ubuntu.com> | 2024-02-29 13:56:32 -0700 |
---|---|---|
committer | Steve Langasek <steve.langasek@ubuntu.com> | 2024-02-29 13:56:32 -0700 |
commit | 87fa5bbc755951d15878f3ca728e73d84df0b47e (patch) | |
tree | 64c3dcc1a66f70693a179ccd1d0ce3e3d5b73985 /debian | |
parent | 9ce4649a1b8795d971a69f023306503b676c0300 (diff) | |
parent | 887e5e2372e75895b9b73957ff0d22963fb54de3 (diff) |
Record pam (1.5.3-6) in archive suite sid
Diffstat (limited to 'debian')
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | debian/patches-applied/systemd-pam-time | 625 | ||||
-rw-r--r-- | debian/patches/ftbfs-implicit-function-declaration | 14 | ||||
-rw-r--r-- | debian/patches/series | 1 |
4 files changed, 647 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog index c102c04c..1dc85b51 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +pam (1.5.3-6) unstable; urgency=medium + + [ Dan Bungert ] + * Fix FTBFS when built with -Werror=implicit-function-declaration + + -- Steve Langasek <steve.langasek@ubuntu.com> Thu, 29 Feb 2024 12:56:32 -0800 + pam (1.5.3-5) unstable; urgency=medium * Revert renaming libpam0g to libpam0t64 for time_t transition: apt diff --git a/debian/patches-applied/systemd-pam-time b/debian/patches-applied/systemd-pam-time new file mode 100644 index 00000000..ec85529e --- /dev/null +++ b/debian/patches-applied/systemd-pam-time @@ -0,0 +1,625 @@ +Index: pam/configure.ac +=================================================================== +--- pam.orig/configure.ac ++++ pam/configure.ac +@@ -334,6 +334,9 @@ + esac + AC_SUBST(LIBDL) + ++AC_CHECK_LIB(m, log2, LIBM=-lm, LIBM="") ++AC_SUBST(LIBM) ++ + dnl Look for Linux Auditing library - see documentation + AC_ARG_ENABLE([audit], + AS_HELP_STRING([--disable-audit],[do not enable audit support]), +Index: pam/modules/pam_time/Makefile.am +=================================================================== +--- pam.orig/modules/pam_time/Makefile.am ++++ pam/modules/pam_time/Makefile.am +@@ -23,7 +23,7 @@ + if HAVE_VERSIONING + AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map + endif +-pam_time_la_LIBADD = $(top_builddir)/libpam/libpam.la ++pam_time_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBM@ + + securelib_LTLIBRARIES = pam_time.la + dist_secureconf_DATA = time.conf +@@ -32,3 +32,7 @@ + dist_noinst_DATA = README + -include $(top_srcdir)/Make.xml.rules + endif ++ ++noinst_HEADERS = time-util.h ++ ++pam_time_la_SOURCES = pam_time.c time-util.c +Index: pam/modules/pam_time/pam_time.c +=================================================================== +--- pam.orig/modules/pam_time/pam_time.c ++++ pam/modules/pam_time/pam_time.c +@@ -21,7 +21,9 @@ + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> ++#include <math.h> + #include <netdb.h> ++#include <sys/param.h> + + #include <security/_pam_macros.h> + #include <security/pam_modules.h> +@@ -33,6 +35,8 @@ + #include <libaudit.h> + #endif + ++#include "time-util.h" ++ + #define PAM_TIME_BUFLEN 1000 + #define FIELD_SEPARATOR ';' /* this is new as of .02 */ + +@@ -48,6 +52,13 @@ + + typedef enum { AND, OR } operator; + ++static void cleanup(pam_handle_t *handle UNUSED, void *data, int err UNUSED) ++{ ++ if (!data) ++ return; ++ free(data); ++} ++ + static int + _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, const char **conffile) + { +@@ -286,8 +297,9 @@ + + static int + logic_field(pam_handle_t *pamh, const void *me, const char *x, int rule, ++ void *data, + int (*agrees)(pam_handle_t *pamh, +- const void *, const char *, int, int)) ++ const void *, const char *, int, int, void *)) + { + int left=FALSE, right, not=FALSE; + operator oper=OR; +@@ -302,7 +314,7 @@ + not = !not; + else if (isalpha(c) || c == '*' || isdigit(c) || c == '_' + || c == '-' || c == '.' || c == '/' || c == ':') { +- right = not ^ agrees(pamh, me, x+at, l, rule); ++ right = not ^ agrees(pamh, me, x+at, l, rule, data); + if (oper == AND) + left &= right; + else +@@ -340,7 +352,7 @@ + + static int + is_same(pam_handle_t *pamh UNUSED, const void *A, const char *b, +- int len, int rule UNUSED) ++ int len, int rule UNUSED, void *data UNUSED) + { + int i; + const char *a; +@@ -405,12 +417,19 @@ + /* take the current date and see if the range "date" passes it */ + static int + check_time(pam_handle_t *pamh, const void *AT, const char *times, +- int len, int rule) ++ int len, int rule, void *data) + { + int not,pass; + int marked_day, time_start, time_end; + const TIME *at; + int i,j=0; ++ struct tm tm; ++ time_t current_time; ++ time_t *time_limit = data; ++ ++ current_time = time(NULL); ++ // ignore failures, shouldn't really be possible ++ localtime_r(¤t_time, &tm); + + at = AT; + D(("chcking: 0%o/%.4d vs. %s", at->day, at->minute, times)); +@@ -503,6 +522,59 @@ + } + } + ++ if (pass && !not) { ++ int numdays = 0; ++ if (time_start == 0 && time_end == 2400) { ++ // special case where access is allowed for at least one full ++ // day, so we have to examine the days until we find one that's ++ // not allowed (or until we loop around) ++ for (i = at->day; ; ) { ++ i <<= 1; ++ if (i > 0100) ++ i = 1; ++ if (! (i & marked_day)) ++ break; ++ if (i == at->day) ++ break; ++ } ++ ++ // access allowed all day, every day... ++ if (i == at->day) ++ return (not ^ pass); ++ ++ if (i < at->day) ++ i <<= 7; ++ numdays = lrint(log2(i))-lrint((at->day)); ++ } else if (time_end < time_start) ++ numdays = 1; ++ ++ // if the end time is not today, walk the days 1 at a time to ++ // increment. This method avoids problems with both DST and ++ // end of month / end of year boundaries. ++ while (numdays > 0) { ++ tm.tm_hour = 23; ++ tm.tm_min = 59; ++ *time_limit = mktime(&tm); ++ *time_limit += 60*60; // 00:59 the next day ++ localtime_r(time_limit, &tm); ++ numdays--; ++ } ++ ++ tm.tm_hour = time_end / 100; ++ tm.tm_min = time_end % 100; ++ tm.tm_sec = 0; ++ // tm_hour = 24 is not legal, so get the timestamp for 23:59 ++ // and add 60 seconds ++ if (time_end == 2400) ++ { ++ tm.tm_hour -= 1; ++ tm.tm_min -= 1; ++ } ++ *time_limit = mktime(&tm); ++ if (time_end == 2400) ++ *time_limit += 60; ++ } ++ + return (not ^ pass); + } + +@@ -515,6 +587,7 @@ + int count=0; + TIME here_and_now; + int retval=PAM_SUCCESS; ++ time_t end_time = 0, time_buf = 0; + + here_and_now = time_now(); /* find current time */ + do { +@@ -535,7 +608,7 @@ + continue; + } + +- good = logic_field(pamh, service, buffer, count, is_same); ++ good = logic_field(pamh, service, buffer, count, NULL, is_same); + D(("with service: %s", good ? "passes":"fails" )); + + /* here we get the terminal name field */ +@@ -546,7 +619,7 @@ + "%s: malformed rule #%d", file, count); + continue; + } +- good &= logic_field(pamh, tty, buffer, count, is_same); ++ good &= logic_field(pamh, tty, buffer, count, NULL, is_same); + D(("with tty: %s", good ? "passes":"fails" )); + + /* here we get the username field */ +@@ -565,7 +638,7 @@ + pam_syslog (pamh, LOG_ERR, "pam_time does not have netgroup support"); + #endif + else +- good &= logic_field(pamh, user, buffer, count, is_same); ++ good &= logic_field(pamh, user, buffer, count, NULL, is_same); + D(("with user: %s", good ? "passes":"fails" )); + + /* here we get the time field */ +@@ -577,7 +650,8 @@ + continue; + } + +- intime = logic_field(pamh, &here_and_now, buffer, count, check_time); ++ intime = logic_field(pamh, &here_and_now, buffer, count, &time_buf, ++ check_time); + D(("with time: %s", intime ? "passes":"fails" )); + + if (good && !intime) { +@@ -587,10 +661,49 @@ + */ + retval = PAM_PERM_DENIED; + } else { ++ if (good) ++ end_time = time_buf; + D(("rule passed")); + } + } while (state != STATE_EOF); + ++ if (end_time != 0) { ++ const char *current_limit = NULL; ++ char *runtime_max_sec = NULL; ++ time_t curtime = time(NULL); ++ usec_t timeval = 0, old_timeval = 0; ++ ++ // unlikely, but could happen if we were already close to the limit ++ if (end_time <= curtime) ++ return PAM_PERM_DENIED; ++ timeval = (end_time - curtime) * USEC_PER_SEC; ++ ++ // get current limit, if any ++ pam_get_data(pamh, "systemd.runtime_max_sec", ++ (const void **)¤t_limit); ++ if (current_limit) { ++ retval = parse_time(current_limit, &old_timeval, USEC_PER_SEC); ++ timeval = MIN(old_timeval, timeval); ++ } ++ if (timeval != old_timeval) ++ { ++ runtime_max_sec = malloc(FORMAT_TIMESPAN_MAX); ++ if (!format_timespan(runtime_max_sec, FORMAT_TIMESPAN_MAX, ++ timeval, USEC_PER_SEC)) { ++ free((void *)runtime_max_sec); ++ return PAM_PERM_DENIED; ++ } ++ pam_syslog(pamh, LOG_DEBUG, "user %s session limited to %s", ++ user, runtime_max_sec); ++ retval = pam_set_data(pamh, "systemd.runtime_max_sec", ++ (void *)runtime_max_sec, cleanup); ++ if (retval != PAM_SUCCESS) { ++ free((void *)runtime_max_sec); ++ return PAM_PERM_DENIED; ++ } ++ } ++ } ++ + return retval; + } + +Index: pam/modules/pam_time/time-util.c +=================================================================== +--- /dev/null ++++ pam/modules/pam_time/time-util.c +@@ -0,0 +1,314 @@ ++/* ++ * ++ * Copyright (c) 2012-2015 Lennart Poettering, ++ * 2014-2023 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>, ++ * 2022-2023 Yu Watanabe ++ * ++ * pam_session_timelimit is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public License as ++ * published by the Free Software Foundation; either version 3 of the ++ * License, or (at your option) any later version. ++ * ++ * pam_session_timelimit is distributed in the hope that it will be ++ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <assert.h> ++#include <errno.h> ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <sys/param.h> ++ ++#include "time-util.h" ++ ++/* What is interpreted as whitespace? */ ++#define WHITESPACE " \t\n\r" ++#define DIGITS "0123456789" ++ ++#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) ++ ++#define ELEMENTSOF(x) \ ++ (__builtin_choose_expr( \ ++ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ ++ sizeof(x)/sizeof((x)[0]), \ ++ ((void)0))) ++ ++ ++static const char *startswith(const char *s, const char *prefix) { ++ size_t l; ++ ++ assert(s); ++ assert(prefix); ++ ++ l = strlen(prefix); ++ if (!strneq(s, prefix, l)) ++ return NULL; ++ ++ return s + l; ++} ++ ++ ++static const char* extract_multiplier(const char *p, usec_t *ret) { ++ static const struct { ++ const char *suffix; ++ usec_t usec; ++ } table[] = { ++ { "seconds", USEC_PER_SEC }, ++ { "second", USEC_PER_SEC }, ++ { "sec", USEC_PER_SEC }, ++ { "s", USEC_PER_SEC }, ++ { "minutes", USEC_PER_MINUTE }, ++ { "minute", USEC_PER_MINUTE }, ++ { "min", USEC_PER_MINUTE }, ++ { "months", USEC_PER_MONTH }, ++ { "month", USEC_PER_MONTH }, ++ { "M", USEC_PER_MONTH }, ++ { "msec", USEC_PER_MSEC }, ++ { "ms", USEC_PER_MSEC }, ++ { "m", USEC_PER_MINUTE }, ++ { "hours", USEC_PER_HOUR }, ++ { "hour", USEC_PER_HOUR }, ++ { "hr", USEC_PER_HOUR }, ++ { "h", USEC_PER_HOUR }, ++ { "days", USEC_PER_DAY }, ++ { "day", USEC_PER_DAY }, ++ { "d", USEC_PER_DAY }, ++ { "weeks", USEC_PER_WEEK }, ++ { "week", USEC_PER_WEEK }, ++ { "w", USEC_PER_WEEK }, ++ { "years", USEC_PER_YEAR }, ++ { "year", USEC_PER_YEAR }, ++ { "y", USEC_PER_YEAR }, ++ { "usec", 1ULL }, ++ { "us", 1ULL }, ++ { "µs", 1ULL }, ++ }; ++ ++ assert(p); ++ assert(ret); ++ ++ for (size_t i = 0; i < ELEMENTSOF(table); i++) { ++ const char *e; ++ ++ e = startswith(p, table[i].suffix); ++ if (e) { ++ *ret = table[i].usec; ++ return e; ++ } ++ } ++ ++ return p; ++} ++ ++ ++int parse_time(const char *t, usec_t *usec, usec_t default_unit) { ++ const char *p, *s; ++ usec_t r = 0; ++ bool something = false; ++ ++ assert(t); ++ assert(default_unit > 0); ++ ++ p = t; ++ ++ p += strspn(p, WHITESPACE); ++ s = startswith(p, "infinity"); ++ if (s) { ++ s += strspn(s, WHITESPACE); ++ if (*s != 0) ++ return -EINVAL; ++ ++ if (usec) ++ *usec = USEC_INFINITY; ++ return 0; ++ } ++ ++ for (;;) { ++ usec_t multiplier = default_unit, k; ++ long long l; ++ char *e; ++ ++ p += strspn(p, WHITESPACE); ++ ++ if (*p == 0) { ++ if (!something) ++ return -EINVAL; ++ ++ break; ++ } ++ ++ if (*p == '-') /* Don't allow "-0" */ ++ return -ERANGE; ++ ++ errno = 0; ++ l = strtoll(p, &e, 10); ++ if (errno > 0) ++ return -errno; ++ if (l < 0) ++ return -ERANGE; ++ ++ if (*e == '.') { ++ p = e + 1; ++ p += strspn(p, DIGITS); ++ } else if (e == p) ++ return -EINVAL; ++ else ++ p = e; ++ ++ s = extract_multiplier(p + strspn(p, WHITESPACE), &multiplier); ++ if (s == p && *s != '\0') ++ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56' */ ++ return -EINVAL; ++ ++ p = s; ++ ++ if ((usec_t) l >= USEC_INFINITY / multiplier) ++ return -ERANGE; ++ ++ k = (usec_t) l * multiplier; ++ if (k >= USEC_INFINITY - r) ++ return -ERANGE; ++ ++ r += k; ++ ++ something = true; ++ ++ if (*e == '.') { ++ usec_t m = multiplier / 10; ++ const char *b; ++ ++ for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) { ++ k = (usec_t) (*b - '0') * m; ++ if (k >= USEC_INFINITY - r) ++ return -ERANGE; ++ ++ r += k; ++ } ++ ++ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge" */ ++ if (b == e + 1) ++ return -EINVAL; ++ } ++ } ++ ++ if (usec) ++ *usec = r; ++ return 0; ++} ++ ++ ++char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { ++ static const struct { ++ const char *suffix; ++ usec_t usec; ++ } table[] = { ++ { "y", USEC_PER_YEAR }, ++ { "month", USEC_PER_MONTH }, ++ { "w", USEC_PER_WEEK }, ++ { "d", USEC_PER_DAY }, ++ { "h", USEC_PER_HOUR }, ++ { "min", USEC_PER_MINUTE }, ++ { "s", USEC_PER_SEC }, ++ { "ms", USEC_PER_MSEC }, ++ { "us", 1 }, ++ }; ++ ++ char *p = buf; ++ bool something = false; ++ ++ if (!p) ++ return NULL; ++ ++ assert(l > 0); ++ ++ if (t == USEC_INFINITY) { ++ strncpy(p, "infinity", l-1); ++ p[l-1] = 0; ++ return p; ++ } ++ ++ if (t <= 0) { ++ strncpy(p, "0", l-1); ++ p[l-1] = 0; ++ return p; ++ } ++ ++ /* The result of this function can be parsed with parse_sec */ ++ ++ for (size_t i = 0; i < ELEMENTSOF(table); i++) { ++ int k = 0; ++ size_t n; ++ bool done = false; ++ usec_t a, b; ++ ++ if (t <= 0) ++ break; ++ ++ if (t < accuracy && something) ++ break; ++ ++ if (t < table[i].usec) ++ continue; ++ ++ if (l <= 1) ++ break; ++ ++ a = t / table[i].usec; ++ b = t % table[i].usec; ++ ++ /* Let's see if we should shows this in dot notation */ ++ if (t < USEC_PER_MINUTE && b > 0) { ++ signed char j = 0; ++ ++ for (usec_t cc = table[i].usec; cc > 1; cc /= 10) ++ j++; ++ ++ for (usec_t cc = accuracy; cc > 1; cc /= 10) { ++ b /= 10; ++ j--; ++ } ++ ++ if (j > 0) { ++ k = snprintf(p, l, ++ "%s"USEC_FMT".%0*"PRI_USEC"%s", ++ p > buf ? " " : "", ++ a, ++ j, ++ b, ++ table[i].suffix); ++ ++ t = 0; ++ done = true; ++ } ++ } ++ ++ /* No? Then let's show it normally */ ++ if (!done) { ++ k = snprintf(p, l, ++ "%s"USEC_FMT"%s", ++ p > buf ? " " : "", ++ a, ++ table[i].suffix); ++ ++ t = b; ++ } ++ ++ n = MIN((size_t) k, l-1); ++ ++ l -= n; ++ p += n; ++ ++ something = true; ++ } ++ ++ *p = 0; ++ ++ return buf; ++} +Index: pam/modules/pam_time/time-util.h +=================================================================== +--- /dev/null ++++ pam/modules/pam_time/time-util.h +@@ -0,0 +1,24 @@ ++#include <inttypes.h> ++ ++typedef uint64_t usec_t; ++ ++#define PRI_USEC PRIu64 ++#define USEC_FMT "%" PRI_USEC ++ ++#define USEC_INFINITY ((usec_t) UINT64_MAX) ++ ++#define USEC_PER_SEC ((usec_t) 1000000ULL) ++#define USEC_PER_MSEC ((usec_t) 1000ULL) ++ ++#define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC)) ++#define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE)) ++#define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR)) ++#define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY)) ++#define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC)) ++#define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC)) ++ ++#define FORMAT_TIMESPAN_MAX 64U ++ ++int parse_time(const char *t, usec_t *ret, usec_t default_unit); ++char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) ++ __attribute__((__warn_unused_result__)); diff --git a/debian/patches/ftbfs-implicit-function-declaration b/debian/patches/ftbfs-implicit-function-declaration new file mode 100644 index 00000000..21dad567 --- /dev/null +++ b/debian/patches/ftbfs-implicit-function-declaration @@ -0,0 +1,14 @@ +Description: Fix FTBFS when built with -Werror=implicit-function-declaration +Bug-Ubuntu: https://bugs.launchpad.net/bugs/2055453 +Forwarded: no +Last-Update: 2024-02-29 +--- a/modules/pam_unix/support.h ++++ b/modules/pam_unix/support.h +@@ -6,6 +6,7 @@ + #define _PAM_UNIX_SUPPORT_H + + #include <pwd.h> ++#include "libpam/include/pam_inline.h" + + /* + * File to read value of ENCRYPT_METHOD from. diff --git a/debian/patches/series b/debian/patches/series index dd734f94..590e2847 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -20,3 +20,4 @@ fix-autoreconf.patch nullok_secure-compat.patch pam_mkhomedir_stat_before_opendir pam_namespace_o_directory +ftbfs-implicit-function-declaration |