summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/NEWS85
-rw-r--r--debian/changelog9
-rw-r--r--debian/control2
-rw-r--r--debian/libpam-modules.NEWS15
-rw-r--r--debian/patches-applied/systemd-pam-time625
-rw-r--r--debian/patches/PAM-manpage-section6
-rw-r--r--debian/patches/ftbfs-implicit-function-declaration11
-rw-r--r--doc/man/pam_get_item.34
8 files changed, 40 insertions, 717 deletions
diff --git a/debian/NEWS b/debian/NEWS
deleted file mode 100644
index c6c4f7f0..00000000
--- a/debian/NEWS
+++ /dev/null
@@ -1,85 +0,0 @@
-pam (1.1.2-1) unstable; urgency=low
-
- * Name of option for minimum Unix password length has changed
-
- The Debian-specific 'min=n' option to pam_unix for specifying minimum
- lengths for new passwords has been replaced by a new upstream option
- called 'minlen=n'. If you are using 'min=n' in
- /etc/pam.d/common-password, this will be migrated to the new option name
- for you on upgrade. If you have configured pam_unix password changing
- elsewhere on your system, such as in a PAM profile under
- /usr/share/pam-configs or in other files in /etc/pam.d, you will need to
- update them by hand for this change.
-
- -- Steve Langasek <vorlon@debian.org> Tue, 31 Aug 2010 23:09:30 -0700
-
-pam (1.1.0-3) unstable; urgency=low
-
- * pam_rhosts_auth module obsolete, symlink removed
-
- The pam_rhosts_auth module was dropped upstream prior to the lenny
- release and a compatibility symlink provided in the libpam-modules
- package, pointing at the new (and not 100% compatible) pam_rhosts
- module. This symlink has now been dropped. If you still have
- references to pam_rhosts_auth in your /etc/pam.d/* config files, you
- will need to fix these, since they no longer work.
-
- For information on using pam_rhosts, see the pam_rhosts(8) manpage.
-
- -- Steve Langasek <vorlon@debian.org> Wed, 02 Sep 2009 16:17:16 -0700
-
-pam (1.1.0-1) unstable; urgency=low
-
- * pam_cracklib no longer checks for reuse of old passwords
-
- The pam_cracklib module no longer checks /etc/security/opasswd to see
- if the proposed password is one that was previously used. This
- functionality has been split out into a new module, pam_pwhistory.
-
- The pam_unix module still does its own check of /etc/security/opasswd,
- so if you are using this module you should not need to change anything.
-
- * Change in handling of /etc/shadow fields
-
- The Debian PAM package included a patch to treat a value of 0 in certain
- fields in /etc/shadow as the same as an empty field. This patch has
- been dropped, since it caused the behavior of pam_unix to differ from
- both that of PAM upstream and that of the shadow package.
-
- The main consequences of this change are that:
-
- - a "0" in the sp_expire field will be treated as a date of Jan 1, 1970
- instead of a "never expires" value, so users with this set will be
- unable to log in
-
- - a "0" in the sp_inact field will indicate that the user should not be
- allowed to change an expired password at all, instead of being allowed
- to change an expired at any time after the expiry.
-
- See Debian bug #308229 for more information about this change.
-
- -- Steve Langasek <vorlon@debian.org> Tue, 25 Aug 2009 00:13:57 -0700
-
-pam (0.99.7.1-5) unstable; urgency=low
-
- * Default Unix minimum password length has changed
-
- Previous versions of pam_unix on Debian had a built-in minimum password
- length of 1 character, and a minimum password length configured in
- /etc/pam.d/common-password of 4 characters. This differed from the
- upstream default of 6 characters. This has been changed, so the
- default /etc/pam.d/common-password no longer overrides the compile-time
- default and the compile-time default has been raised to 6 characters.
- If you are using pam_unix but are not using the default
- /etc/pam.d/common-password file, it is recommended that you drop any
- min= options to pam_unix from your config unless you have stronger
- local password requirements that the upstream default.
-
- The password length 'max' option has also been deprecated in this
- version because it was never written to work as suggested in the
- documentation. If you are using pam_unix but are not using the default
- /etc/pam.d/common-password file, you should remove any old max= options
- to pam_unix from your config as this option will be considered an error
- in future versions of pam.
-
- -- Steve Langasek <vorlon@debian.org> Sat, 01 Sep 2007 21:27:11 -0700
diff --git a/debian/changelog b/debian/changelog
index 1dc85b51..df14a1e3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+pam (1.5.3-7) unstable; urgency=medium
+
+ * Correct Build depends for docbook5, Closes: #1065064
+ * Regenerate patches to capture date change in pam_getitem.3
+ * Depend on libdb-dev again, bringing back pam_userdb, Closes: #1065088
+ * Document pam_umask change, Closes: #1065806
+
+ -- Sam Hartman <hartmans@debian.org> Mon, 08 Apr 2024 16:35:07 -0600
+
pam (1.5.3-6) unstable; urgency=medium
[ Dan Bungert ]
diff --git a/debian/control b/debian/control
index f9426d64..33698fae 100644
--- a/debian/control
+++ b/debian/control
@@ -4,7 +4,7 @@ Priority: optional
Maintainer: Sam Hartman <hartmans@debian.org>
Uploaders: Steve Langasek <vorlon@debian.org>
Standards-Version: 4.6.2
-Build-Depends: debhelper-compat (= 13), dh-exec, flex, libcrypt-dev, libselinux1-dev [linux-any], libsystemd-dev [linux-any] <!stage1>, po-debconf, autopoint, libaudit-dev [linux-any] <!stage1>, pkg-config, libfl-dev, libfl-dev:native, docbook-xsl, docbook-xml, xsltproc, libxml2-utils, w3m
+Build-Depends: debhelper-compat (= 13), dh-exec, flex, libcrypt-dev, libdb-dev, libselinux1-dev [linux-any], libsystemd-dev [linux-any] <!stage1>, po-debconf, autopoint, libaudit-dev [linux-any] <!stage1>, pkg-config, libfl-dev, libfl-dev:native, docbook-xsl-ns, docbook5-xml, xsltproc, libxml2-utils, w3m
Build-Conflicts-Indep: fop
Build-Conflicts: libdb4.2-dev, libxcrypt-dev
Vcs-Browser: https://salsa.debian.org/vorlon/pam
diff --git a/debian/libpam-modules.NEWS b/debian/libpam-modules.NEWS
new file mode 100644
index 00000000..01dcfe1c
--- /dev/null
+++ b/debian/libpam-modules.NEWS
@@ -0,0 +1,15 @@
+pam (1.5.3-7) unstable; urgency=medium
+
+ Starting with PAM version 1.5.3, Debian supports usergroups for default
+ umask of users logging in. If the primary group name of a user
+ matches their primary user name (user pat's default group is also
+ called pat), then files will be group writable by default. To disable
+ this user a group name that differs from the user name or add
+ nousergroups to the pam_umask line in
+ /etc/pam.d/common-session:
+
+ session optional pam_umask.so nousergroups
+
+
+ -- Sam Hartman <hartmans@debian.org> Mon, 08 Apr 2024 16:15:58 -0600
+
diff --git a/debian/patches-applied/systemd-pam-time b/debian/patches-applied/systemd-pam-time
deleted file mode 100644
index ec85529e..00000000
--- a/debian/patches-applied/systemd-pam-time
+++ /dev/null
@@ -1,625 +0,0 @@
-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/PAM-manpage-section b/debian/patches/PAM-manpage-section
index 0c2f40be..705ce58e 100644
--- a/debian/patches/PAM-manpage-section
+++ b/debian/patches/PAM-manpage-section
@@ -689,7 +689,7 @@ index ba6d955..1cb7566 100644
</para>
</refsect1>
diff --git a/doc/man/pam_get_item.3 b/doc/man/pam_get_item.3
-index d08fde5..894c7f6 100644
+index d08fde5..30434bb 100644
--- a/doc/man/pam_get_item.3
+++ b/doc/man/pam_get_item.3
@@ -2,12 +2,12 @@
@@ -697,13 +697,13 @@ index d08fde5..894c7f6 100644
.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
-.\" Date: 05/07/2023
-+.\" Date: 09/15/2023
++.\" Date: 02/29/2024
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "PAM_GET_ITEM" "3" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual"
-+.TH "PAM_GET_ITEM" "3" "09/15/2023" "Linux\-PAM" "Linux\-PAM Manual"
++.TH "PAM_GET_ITEM" "3" "02/29/2024" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/debian/patches/ftbfs-implicit-function-declaration b/debian/patches/ftbfs-implicit-function-declaration
index 21dad567..c79aff51 100644
--- a/debian/patches/ftbfs-implicit-function-declaration
+++ b/debian/patches/ftbfs-implicit-function-declaration
@@ -1,7 +1,16 @@
-Description: Fix FTBFS when built with -Werror=implicit-function-declaration
+From: Sam Hartman <hartmans@debian.org>
+Date: Mon, 8 Apr 2024 15:40:35 -0600
+Subject: Fix FTBFS when built with -Werror=implicit-function-declaration
+
Bug-Ubuntu: https://bugs.launchpad.net/bugs/2055453
Forwarded: no
Last-Update: 2024-02-29
+---
+ modules/pam_unix/support.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
+index e15ee98..9c065c5 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -6,6 +6,7 @@
diff --git a/doc/man/pam_get_item.3 b/doc/man/pam_get_item.3
index 894c7f6d..30434bbd 100644
--- a/doc/man/pam_get_item.3
+++ b/doc/man/pam_get_item.3
@@ -2,12 +2,12 @@
.\" Title: pam_get_item
.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
-.\" Date: 09/15/2023
+.\" Date: 02/29/2024
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "PAM_GET_ITEM" "3" "09/15/2023" "Linux\-PAM" "Linux\-PAM Manual"
+.TH "PAM_GET_ITEM" "3" "02/29/2024" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------