summaryrefslogtreecommitdiff
path: root/debian
diff options
context:
space:
mode:
authorSteve Langasek <steve.langasek@ubuntu.com>2024-02-29 13:56:32 -0700
committerSteve Langasek <steve.langasek@ubuntu.com>2024-02-29 13:56:32 -0700
commit87fa5bbc755951d15878f3ca728e73d84df0b47e (patch)
tree64c3dcc1a66f70693a179ccd1d0ce3e3d5b73985 /debian
parent9ce4649a1b8795d971a69f023306503b676c0300 (diff)
parent887e5e2372e75895b9b73957ff0d22963fb54de3 (diff)
Record pam (1.5.3-6) in archive suite sid
Diffstat (limited to 'debian')
-rw-r--r--debian/changelog7
-rw-r--r--debian/patches-applied/systemd-pam-time625
-rw-r--r--debian/patches/ftbfs-implicit-function-declaration14
-rw-r--r--debian/patches/series1
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(&current_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 **)&current_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