Control: tags -1 - moreinfo Hi Adam,
Sorry for the slow reply, I got my other -pu uploads through the finish line and forgot I had another one inflight >_>' On Fri, Jul 26, 2019 at 04:13:20PM -0300, Adam D. Barratt wrote: > On 2019-07-20 11:15, Nicolas Braud-Santoni wrote: > > Here is an updated debdiff; the only modification is in the changelog, > > as I forgot to close #930047 there. > > + * Backport a reliability fix > + pam-u2f could previously segfault following a failure to allocate a > buffer. > > I assume this is backported from the version of the package currently in > unstable? Yes, all the fixes are backported from upstream's 1.0.8, which is currently in sid and bullseye. The backporting itself was simply cherry-picking the correct commits: upstream's latest release mostly just included those changes (plus a huge diff due to regenerating the build system with a more recent version of autotools; obviously I didn't include that). > +pam-u2f (1.0.7-1+deb10u1) buster-proposed-updates; urgency=high > > Just "buster", please. Fixed, thanks for the catch. May I go ahead and upload? Updated debdiff attached. Best, nicoo
diff -Nru pam-u2f-1.0.7/debian/changelog pam-u2f-1.0.7/debian/changelog --- pam-u2f-1.0.7/debian/changelog 2018-05-29 14:33:06.000000000 +0200 +++ pam-u2f-1.0.7/debian/changelog 2019-08-13 01:06:31.000000000 +0200 @@ -1,3 +1,15 @@ +pam-u2f (1.0.7-1+deb10u1) buster; urgency=high + + * Backport multiple security fixes + + Fix insecure debug file handling CVE-2019-12209. (Closes: #930021) + + Fix debug file descriptor leak CVE-2019-12210. (Closes: #930023) + + Fix a non-critical buffer out-of-bounds access. (Closes: #930047) + + * Backport a reliability fix + pam-u2f could previously segfault following a failure to allocate a buffer. + + -- Nicolas Braud-Santoni <ni...@debian.org> Tue, 13 Aug 2019 01:06:31 +0200 + pam-u2f (1.0.7-1) unstable; urgency=high * New upstream version 1.0.7 (2018-05-15) diff -Nru pam-u2f-1.0.7/debian/patches/0001-Do-not-leak-file-descriptor-when-doing-exec.patch pam-u2f-1.0.7/debian/patches/0001-Do-not-leak-file-descriptor-when-doing-exec.patch --- pam-u2f-1.0.7/debian/patches/0001-Do-not-leak-file-descriptor-when-doing-exec.patch 1970-01-01 01:00:00.000000000 +0100 +++ pam-u2f-1.0.7/debian/patches/0001-Do-not-leak-file-descriptor-when-doing-exec.patch 2019-08-13 01:06:31.000000000 +0200 @@ -0,0 +1,164 @@ +Subject: Do not leak file descriptor when doing exec + +When opening a custom debug file, the descriptor would stay +open when calling exec and leak to the child process. + +Make sure all files are opened with close-on-exec. + +This fixes CVE-2019-12210. + +Thanks to Matthias Gerstner of the SUSE Security Team for reporting +the issue. +--- + pam-u2f.c | 35 +++++++++++++++++++++++++---------- + util.c | 10 +++++++--- + util.h | 3 ++- + 3 files changed, 34 insertions(+), 14 deletions(-) + +diff --git a/pam-u2f.c b/pam-u2f.c +index 55d5708..071d005 100644 +Origin: commit:18b1914e32b74ff52000f10e97067e841e5fff62 +Bug: 930023 +From: Gabriel Kihlman <g.kihl...@yubico.com> +Reviewed-by: Nicolas Braud-Santoni <ni...@debian.org> +Last-Update: 2019-07-20 +Applied-Upstream: b0c6b7216f064e051c1dd42629ca062f721eea5f + +--- a/pam-u2f.c ++++ b/pam-u2f.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2014-2018 Yubico AB - See COPYING ++ * Copyright (C) 2014-2019 Yubico AB - See COPYING + */ + + /* Define which PAM interfaces we provide */ +@@ -31,7 +31,11 @@ char *secure_getenv(const char *name) { + #endif + + static void parse_cfg(int flags, int argc, const char **argv, cfg_t *cfg) { ++ struct stat st; ++ FILE *file = NULL; ++ int fd = -1; + int i; ++ + memset(cfg, 0, sizeof(cfg_t)); + cfg->debug_file = stderr; + +@@ -76,14 +80,14 @@ static void parse_cfg(int flags, int argc, const char **argv, cfg_t *cfg) { + cfg->debug_file = (FILE *)-1; + } + else { +- struct stat st; +- FILE *file; +- if(lstat(filename, &st) == 0) { +- if(S_ISREG(st.st_mode)) { +- file = fopen(filename, "a"); +- if(file != NULL) { +- cfg->debug_file = file; +- } ++ fd = open(filename, O_WRONLY | O_APPEND | O_CLOEXEC | O_NOFOLLOW | O_NOCTTY); ++ if (fd >= 0 && (fstat(fd, &st) == 0) && S_ISREG(st.st_mode)) { ++ file = fdopen(fd, "a"); ++ if(file != NULL) { ++ cfg->debug_file = file; ++ cfg->is_custom_debug_file = 1; ++ file = NULL; ++ fd = -1; + } + } + } +@@ -111,6 +115,12 @@ static void parse_cfg(int flags, int argc, const char **argv, cfg_t *cfg) { + D(cfg->debug_file, "appid=%s", cfg->appid ? cfg->appid : "(null)"); + D(cfg->debug_file, "prompt=%s", cfg->prompt ? cfg->prompt : "(null)"); + } ++ ++ if (fd != -1) ++ close(fd); ++ ++ if (file != NULL) ++ fclose(file); + } + + #ifdef DBG +@@ -317,7 +327,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + DBG("Using file '%s' for emitting touch request notifications", cfg->authpending_file); + + // Open (or create) the authpending_file to indicate that we start waiting for a touch +- authpending_file_descriptor = open(cfg->authpending_file, O_RDONLY | O_CREAT, 0664); ++ authpending_file_descriptor = ++ open(cfg->authpending_file, O_RDONLY | O_CREAT | O_CLOEXEC | O_NOFOLLOW | O_NOCTTY, 0664); + if (authpending_file_descriptor < 0) { + DBG("Unable to emit 'authentication started' notification by opening the file '%s', (%s)", + cfg->authpending_file, strerror(errno)); +@@ -385,6 +396,10 @@ done: + } + DBG("done. [%s]", pam_strerror(pamh, retval)); + ++ if (cfg->is_custom_debug_file) { ++ fclose(cfg->debug_file); ++ } ++ + return retval; + } + +diff --git a/util.c b/util.c +index e7d8ecc..c17a0e6 100644 +--- a/util.c ++++ b/util.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2014-2018 Yubico AB - See COPYING ++ * Copyright (C) 2014-2019 Yubico AB - See COPYING + */ + + #include "util.h" +@@ -36,7 +36,7 @@ int get_devices_from_authfile(const char *authfile, const char *username, + /* Ensure we never return uninitialized count. */ + *n_devs = 0; + +- fd = open(authfile, O_RDONLY, 0); ++ fd = open(authfile, O_RDONLY | O_CLOEXEC | O_NOCTTY); + if (fd < 0) { + if (verbose) + D(debug_file, "Cannot open file: %s (%s)", authfile, strerror(errno)); +@@ -83,6 +83,8 @@ int get_devices_from_authfile(const char *authfile, const char *username, + if (verbose) + D(debug_file, "fdopen: %s", strerror(errno)); + goto err; ++ } else { ++ fd = -1; /* fd belongs to opwfile */ + } + + buf = malloc(sizeof(char) * (DEVSIZE * max_devs)); +@@ -211,8 +213,10 @@ out: + + if (opwfile) + fclose(opwfile); +- else if (fd >= 0) ++ ++ if (fd != -1) + close(fd); ++ + return retval; + } + +diff --git a/util.h b/util.h +index 82c3542..d2e7a4d 100644 +--- a/util.h ++++ b/util.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2014-2018 Yubico AB - See COPYING ++ * Copyright (C) 2014-2019 Yubico AB - See COPYING + */ + + #ifndef UTIL_H +@@ -45,6 +45,7 @@ typedef struct { + const char *appid; + const char *prompt; + FILE *debug_file; ++ int is_custom_debug_file; + } cfg_t; + + typedef struct { diff -Nru pam-u2f-1.0.7/debian/patches/0002-Drop-privileges-by-default-when-opening-user-related.patch pam-u2f-1.0.7/debian/patches/0002-Drop-privileges-by-default-when-opening-user-related.patch --- pam-u2f-1.0.7/debian/patches/0002-Drop-privileges-by-default-when-opening-user-related.patch 1970-01-01 01:00:00.000000000 +0100 +++ pam-u2f-1.0.7/debian/patches/0002-Drop-privileges-by-default-when-opening-user-related.patch 2019-08-13 01:06:31.000000000 +0200 @@ -0,0 +1,407 @@ +Subject: Drop privileges by default when opening user-related files + +The module is typically executed as root and would sometimes +open files or follow symlinks that could be controlled from the +outside. + +Drop privileges to the target user before opening any files. + +Fixes CVE-2019-12209. + +Thanks to Matthias Gerstner of the SUSE Security Team for reporting +the issue. +--- + Makefile.am | 1 + + README | 18 +++++++++ + configure.ac | 4 ++ + drop_privs.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + drop_privs.h | 64 +++++++++++++++++++++++++++++ + pam-u2f.c | 31 +++++++++----- + 6 files changed, 238 insertions(+), 9 deletions(-) + create mode 100644 drop_privs.c + create mode 100644 drop_privs.h + +diff --git a/Makefile.am b/Makefile.am +index c0d2d1e..d761939 100644 +Origin: commit:7db3386fcdb454e33a3ea30dcfb8e8960d4c3aa3 +Bug: 930021 +From: Gabriel Kihlman <g.kihl...@yubico.com> +Reviewed-by: Nicolas Braud-Santoni <ni...@debian.org> +Last-Update: 2019-07-20 +Applied-Upstream: b0c6b7216f064e051c1dd42629ca062f721eea5f + +--- a/Makefile.am ++++ b/Makefile.am +@@ -13,6 +13,7 @@ lib_LTLIBRARIES = pam_u2f.la + + pam_u2f_la_SOURCES = pam-u2f.c + pam_u2f_la_SOURCES += util.c util.h ++pam_u2f_la_SOURCES += drop_privs.h drop_privs.c + + pam_u2f_la_LIBADD = -lpam + pam_u2f_la_LIBADD += $(LIBU2FHOST_LIBS) $(LIBU2FSERVER_LIBS) +diff --git a/README b/README +index 1589f7e..ac2cae2 100644 +--- a/README ++++ b/README +@@ -114,6 +114,8 @@ openasuser:: + Setuid to the authenticating user when opening the authfile. Useful when the + user's home is stored on an NFS volume mounted with the root_squash option + (which maps root to nobody which will not be able to read the file). ++Note that after release 1.0.8 this is done by default when no global ++authfile or XDG_CONFIG_HOME environment variable has been set. + + alwaysok:: + Set to enable all authentication attempts to succeed (aka presentation mode). +@@ -164,6 +166,11 @@ mappings will not be used and the opposite applies if user home directory + mappings are being used, the central authorization mappings file will not + be used. + ++By default the mapping file inside a home directory will be opened as ++the target user, whereas the central file will be opened as `root`. If ++the `XDG_CONFIG_HOME` variable is set, privileges will not be dropped ++unless the `openasuser` configuration setting is set. ++ + IMPORTANT: Using pam-u2f to secure the login to a computer while + storing the mapping file in an encrypted home directory, will result + in the impossibility of logging into the system. The partition is +@@ -184,6 +191,10 @@ looks like: + + auth sufficient pam_u2f.so authfile=/etc/u2f_mappings + ++If you do not set the `openasuser` setting, the authfile will be opened ++and parsed as `root` so make sure it has the correct owner and ++permissions set. ++ + IMPORTANT: On dynamics networks (e.g. where hostnames are set by DHCP), + users should not rely on the default origin and appid ("pam://$HOSTNAME") + but set those parameters explicitly to the same value. +@@ -197,6 +208,13 @@ line: + + This is much the same concept as the SSH authorized_keys file. + ++In this case, pam-u2f will drop privileges and read the mapping file ++as that user. This happens regardless of the `openasuser` option being ++set. ++ ++Note that if you set the XDG_CONFIG_HOME variable, privileges will not ++be dropped by default. Consider also setting `openasuser` in that case. ++ + [[registration]] + Obtaining key-handles and public keys + ------------------------------------- +diff --git a/configure.ac b/configure.ac +index 63be054..d4b090e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -37,6 +37,8 @@ AC_CHECK_HEADERS([security/pam_modules.h security/_pam_macros.h security/pam_mod + #include <security/pam_appl.h>]) + AC_CHECK_LIB([pam], [pam_start]) + ++AC_SEARCH_LIBS([pam_modutil_drop_priv], ["pam"], [AC_DEFINE([HAVE_PAM_MODUTIL_DROP_PRIV], [1])]) ++ + case "$host" in + *darwin*) PAMDIR="/usr/lib/pam";; + *linux*) PAMDIR="/lib/x86_64-linux-gnu/security";; +@@ -71,6 +73,8 @@ AC_ARG_VAR([CWFLAGS], [Warning flags]) + AX_CHECK_COMPILE_FLAG([-Wall], [CWFLAGS="-Wall"]) + AX_CHECK_COMPILE_FLAG([-Wextra], [CWFLAGS="$CWFLAGS -Wextra"]) + AX_CHECK_COMPILE_FLAG([-Wconversion], [CWFLAGS="$CWFLAGS -Wconversion"]) ++# Because pam headers are doing sign-conversion, see PAM_MODUTIL_DEF_PRIVS in pam_modutil.h ++AX_CHECK_COMPILE_FLAG([-Wconversion], [CWFLAGS="$CWFLAGS -Wno-sign-conversion"]) + AX_CHECK_COMPILE_FLAG([-Wpedantic], [CWFLAGS="$CWFLAGS -Wpedantic"]) + AX_CHECK_COMPILE_FLAG([-Wformat=2], [CWFLAGS="$CWFLAGS -Wformat=2"]) + AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], [CWFLAGS="$CWFLAGS -Wstrict-prototypes"]) +diff --git a/drop_privs.c b/drop_privs.c +new file mode 100644 +index 0000000..7fe35c5 +--- /dev/null ++++ b/drop_privs.c +@@ -0,0 +1,129 @@ ++/* Written by Ricky Zhou <ri...@fedoraproject.org> ++ * Fredrik Thulin <fred...@yubico.com> implemented pam_modutil_drop_priv ++ * ++ * Copyright (c) 2011-2014 Yubico AB ++ * Copyright (c) 2011 Ricky Zhou <ri...@fedoraproject.org> ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are ++ * met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * * Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following ++ * disclaimer in the documentation and/or other materials provided ++ * with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef HAVE_PAM_MODUTIL_DROP_PRIV ++ ++#include <unistd.h> ++#include <pwd.h> ++#include <grp.h> ++#include <errno.h> ++#include <string.h> ++#include <stdlib.h> ++ ++#include "drop_privs.h" ++#include "util.h" ++ ++#ifdef HAVE_SECURITY_PAM_APPL_H ++#include <security/pam_appl.h> ++#endif ++#ifdef HAVE_SECURITY_PAM_MODULES_H ++#include <security/pam_modules.h> ++#endif ++ ++ ++int pam_modutil_drop_priv(pam_handle_t *pamh, struct _ykpam_privs *privs, struct passwd *pw) { ++ privs->saved_euid = geteuid(); ++ privs->saved_egid = getegid(); ++ ++ if ((privs->saved_euid == pw->pw_uid) && (privs->saved_egid == pw->pw_gid)) { ++ D (privs->debug_file, "Privilges already dropped, pretend it is all right"); ++ return 0; ++ } ++ ++ privs->saved_groups_length = getgroups(0, NULL); ++ if (privs->saved_groups_length < 0) { ++ D (privs->debug_file, "getgroups: %s", strerror(errno)); ++ return -1; ++ } ++ ++ if (privs->saved_groups_length > SAVED_GROUPS_MAX_LEN) { ++ D (privs->debug_file, "too many groups, limiting."); ++ privs->saved_groups_length = SAVED_GROUPS_MAX_LEN; ++ } ++ ++ if (privs->saved_groups_length > 0) { ++ if (getgroups(privs->saved_groups_length, privs->saved_groups) < 0) { ++ D (privs->debug_file, "getgroups: %s", strerror(errno)); ++ goto free_out; ++ } ++ } ++ ++ if (initgroups(pw->pw_name, pw->pw_gid) < 0) { ++ D (privs->debug_file, "initgroups: %s", strerror(errno)); ++ goto free_out; ++ } ++ ++ if (setegid(pw->pw_gid) < 0) { ++ D (privs->debug_file, "setegid: %s", strerror(errno)); ++ goto free_out; ++ } ++ ++ if (seteuid(pw->pw_uid) < 0) { ++ D (privs->debug_file, "seteuid: %s", strerror(errno)); ++ goto free_out; ++ } ++ ++ return 0; ++free_out: ++ return -1; ++} ++ ++int pam_modutil_regain_priv(pam_handle_t *pamh, struct _ykpam_privs *privs) { ++ if ((privs->saved_euid == geteuid()) && (privs->saved_egid == getegid())) { ++ D (privs->debug_file, "Privilges already as requested, pretend it is all right"); ++ return 0; ++ } ++ ++ if (seteuid(privs->saved_euid) < 0) { ++ D (privs->debug_file, "seteuid: %s", strerror(errno)); ++ return -1; ++ } ++ ++ if (setegid(privs->saved_egid) < 0) { ++ D (privs->debug_file, "setegid: %s", strerror(errno)); ++ return -1; ++ } ++ ++ if (setgroups(privs->saved_groups_length, privs->saved_groups) < 0) { ++ D (privs->debug_file, "setgroups: %s", strerror(errno)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++#else ++ ++// drop_privs.c:124: warning: ISO C forbids an empty translation unit [-Wpedantic] ++typedef int make_iso_compilers_happy; ++ ++#endif // HAVE_PAM_MODUTIL_DROP_PRIV +diff --git a/drop_privs.h b/drop_privs.h +new file mode 100644 +index 0000000..2d25a19 +--- /dev/null ++++ b/drop_privs.h +@@ -0,0 +1,64 @@ ++/* Copyright (c) 2011-2014 Yubico AB ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are ++ * met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * * Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following ++ * disclaimer in the documentation and/or other materials provided ++ * with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef __PAM_U2F_DROP_PRIVS_H_INCLUDED__ ++#define __PAM_U2F_DROP_PRIVS_H_INCLUDED__ ++ ++#ifdef HAVE_PAM_MODUTIL_DROP_PRIV ++#include <security/pam_modutil.h> ++#else ++ ++#include <pwd.h> ++#include <stdio.h> ++ ++#ifdef HAVE_SECURITY_PAM_APPL_H ++#include <security/pam_appl.h> ++#endif ++#ifdef HAVE_SECURITY_PAM_MODULES_H ++#include <security/pam_modules.h> ++#endif ++ ++#define SAVED_GROUPS_MAX_LEN 64 /* as pam_modutil.. */ ++ ++struct _ykpam_privs { ++ uid_t saved_euid; ++ gid_t saved_egid; ++ gid_t *saved_groups; ++ int saved_groups_length; ++ FILE *debug_file; ++}; ++ ++#define PAM_MODUTIL_DEF_PRIVS(n) \ ++ gid_t n##_saved_groups[SAVED_GROUPS_MAX_LEN]; \ ++ struct _ykpam_privs n = {-1, -1, n##_saved_groups, SAVED_GROUPS_MAX_LEN, cfg->debug_file} ++ ++int pam_modutil_drop_priv(pam_handle_t *, struct _ykpam_privs *, struct passwd *); ++int pam_modutil_regain_priv(pam_handle_t *, struct _ykpam_privs *); ++ ++#endif ++#endif +diff --git a/pam-u2f.c b/pam-u2f.c +index 071d005..b01697c 100644 +--- a/pam-u2f.c ++++ b/pam-u2f.c +@@ -20,6 +20,7 @@ + #include <errno.h> + + #include "util.h" ++#include "drop_privs.h" + + /* If secure_getenv is not defined, define it here */ + #ifndef HAVE_SECURE_GETENV +@@ -148,11 +149,12 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + int retval = PAM_IGNORE; + device_t *devices = NULL; + unsigned n_devices = 0; +- int openasuser; ++ int openasuser = 0; + int should_free_origin = 0; + int should_free_appid = 0; + int should_free_auth_file = 0; + int should_free_authpending_file = 0; ++ PAM_MODUTIL_DEF_PRIVS(privs); + + parse_cfg(flags, argc, argv, cfg); + +@@ -235,6 +237,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + goto done; + } + ++ /* Opening a file in a users $HOME, need to drop privs for security */ ++ openasuser = geteuid() == 0 ? 1 : 0; ++ + snprintf(buf, authfile_dir_len, + "%s/.config%s", pw->pw_dir, DEFAULT_AUTHFILE); + } else { +@@ -250,9 +255,14 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + + snprintf(buf, authfile_dir_len, + "%s%s", authfile_dir, DEFAULT_AUTHFILE); ++ ++ if (!openasuser) { ++ DBG("WARNING: not dropping privileges when reading %s, please " ++ "consider setting openasuser=1 in the module configuration", buf); ++ } + } + +- DBG("Using default authentication file %s", buf); ++ DBG("Using authentication file %s", buf); + + cfg->auth_file = buf; /* cfg takes ownership */ + should_free_auth_file = 1; +@@ -261,25 +271,28 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + DBG("Using authentication file %s", cfg->auth_file); + } + +- openasuser = geteuid() == 0 && cfg->openasuser; ++ if (!openasuser) { ++ openasuser = geteuid() == 0 && cfg->openasuser; ++ } + if (openasuser) { +- if (seteuid(pw_s.pw_uid)) { +- DBG("Unable to switch user to uid %i", pw_s.pw_uid); ++ DBG("Dropping privileges"); ++ if (pam_modutil_drop_priv(pamh, &privs, pw)) { ++ DBG("Unable to switch user to uid %i", pw->pw_uid); + retval = PAM_IGNORE; + goto done; + } +- DBG("Switched to uid %i", pw_s.pw_uid); ++ DBG("Switched to uid %i", pw->pw_uid); + } + retval = get_devices_from_authfile(cfg->auth_file, user, cfg->max_devs, + cfg->debug, cfg->debug_file, + devices, &n_devices); + if (openasuser) { +- if (seteuid(0)) { +- DBG("Unable to switch back to uid 0"); ++ if (pam_modutil_regain_priv(pamh, &privs)) { ++ DBG("could not restore privileges"); + retval = PAM_IGNORE; + goto done; + } +- DBG("Switched back to uid 0"); ++ DBG("Restored privileges"); + } + + if (retval != 1) { diff -Nru pam-u2f-1.0.7/debian/patches/0003-Fix-out-of-bound-accesses.patch pam-u2f-1.0.7/debian/patches/0003-Fix-out-of-bound-accesses.patch --- pam-u2f-1.0.7/debian/patches/0003-Fix-out-of-bound-accesses.patch 1970-01-01 01:00:00.000000000 +0100 +++ pam-u2f-1.0.7/debian/patches/0003-Fix-out-of-bound-accesses.patch 2019-08-13 01:06:31.000000000 +0200 @@ -0,0 +1,52 @@ +Subject: Fix out-of-bound accesses + +--- + util.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/util.c b/util.c +index c17a0e6..de48963 100644 +Origin: commit:aab0c31a3bfed8912a271685d6ec909f61380155 +From: Gabriel Kihlman <g.kihl...@yubico.com> +Reviewed-by: Nicolas Braud-Santoni <ni...@debian.org> +Last-Update: 2019-07-20 +Applied-Upstream: b0c6b7216f064e051c1dd42629ca062f721eea5f + +--- a/util.c ++++ b/util.c +@@ -97,8 +97,9 @@ int get_devices_from_authfile(const char *authfile, const char *username, + retval = -2; + while (fgets(buf, (int)(DEVSIZE * (max_devs - 1)), opwfile)) { + char *saveptr = NULL; +- if (buf[strlen(buf) - 1] == '\n') +- buf[strlen(buf) - 1] = '\0'; ++ size_t len = strlen(buf); ++ if (len > 0 && buf[len - 1] == '\n') ++ buf[len - 1] = '\0'; + + if (verbose) + D(debug_file, "Authorization line: %s", buf); +@@ -121,17 +122,17 @@ int get_devices_from_authfile(const char *authfile, const char *username, + + i = 0; + while ((s_token = strtok_r(NULL, ",", &saveptr))) { +- devices[i].keyHandle = NULL; +- devices[i].publicKey = NULL; +- +- if ((*n_devs)++ > MAX_DEVS - 1) { +- *n_devs = MAX_DEVS; ++ if ((*n_devs)++ > max_devs - 1) { ++ *n_devs = max_devs; + if (verbose) + D(debug_file, "Found more than %d devices, ignoring the remaining ones", +- MAX_DEVS); ++ max_devs); + break; + } + ++ devices[i].keyHandle = NULL; ++ devices[i].publicKey = NULL; ++ + if (verbose) + D(debug_file, "KeyHandle for device number %d: %s", i + 1, s_token); + diff -Nru pam-u2f-1.0.7/debian/patches/0004-Handle-malloc-failing-when-logging.patch pam-u2f-1.0.7/debian/patches/0004-Handle-malloc-failing-when-logging.patch --- pam-u2f-1.0.7/debian/patches/0004-Handle-malloc-failing-when-logging.patch 1970-01-01 01:00:00.000000000 +0100 +++ pam-u2f-1.0.7/debian/patches/0004-Handle-malloc-failing-when-logging.patch 2019-08-13 01:06:31.000000000 +0200 @@ -0,0 +1,38 @@ +Subject: Handle malloc failing when logging + +If the size of string to log was bigger than BUFSIZE we use malloc +but if malloc fails we should try and handle it gracefully by +logging that we failed to allocate instead of segfaulting. +--- + util.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/util.c b/util.c +index de48963..6e2b311 100644 +Origin: commit:525aacfb821e86ffef3c960ba13173dab825fd3c +From: Gabriel Kihlman <g.kihl...@yubico.com> +Reviewed-by: Nicolas Braud-Santoni <ni...@debian.org> +Last-Update: 2019-07-20 +Applied-Upstream: db86a442a624b9e13d9f833c518e92abf354827e + +--- a/util.c ++++ b/util.c +@@ -565,9 +565,15 @@ void _debug(FILE *debug_file, const char *file, int line, const char *func, cons + out = malloc(size); + } + +- size = (unsigned int)sprintf(out, DEBUG_STR, file, line, func); +- vsprintf(&out[size], fmt, ap); +- va_end(ap); ++ if (out) { ++ size = (unsigned int)sprintf(out, DEBUG_STR, file, line, func); ++ vsprintf(&out[size], fmt, ap); ++ va_end(ap); ++ } ++ else { ++ out = buffer; ++ sprintf(out, "debug(pam_u2f): malloc failed when trying to log\n"); ++ } + + if (debug_file == (FILE *)-1) { + syslog(LOG_AUTHPRIV | LOG_DEBUG, "%s", out); diff -Nru pam-u2f-1.0.7/debian/patches/series pam-u2f-1.0.7/debian/patches/series --- pam-u2f-1.0.7/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ pam-u2f-1.0.7/debian/patches/series 2019-08-13 01:06:31.000000000 +0200 @@ -0,0 +1,4 @@ +0001-Do-not-leak-file-descriptor-when-doing-exec.patch +0002-Drop-privileges-by-default-when-opening-user-related.patch +0003-Fix-out-of-bound-accesses.patch +0004-Handle-malloc-failing-when-logging.patch
signature.asc
Description: PGP signature