diff options
author | Steve Langasek <steve.langasek@canonical.com> | 2022-08-16 22:06:15 -0700 |
---|---|---|
committer | Steve Langasek <steve.langasek@canonical.com> | 2022-08-16 22:06:15 -0700 |
commit | 99d0d1c5c4f07332daa86e73981267a761bc966e (patch) | |
tree | a56fe41110023676d7082028cbaa47ca4b6e6164 /modules/pam_unix | |
parent | f6d08ed47a3da3c08345bce2ca366e961c52ad7c (diff) | |
parent | 40f7d85f3736d058c26de1dafa4fed46de7d75ef (diff) | |
download | pam-99d0d1c5c4f07332daa86e73981267a761bc966e.tar.gz pam-99d0d1c5c4f07332daa86e73981267a761bc966e.tar.bz2 pam-99d0d1c5c4f07332daa86e73981267a761bc966e.zip |
New upstream version 1.5.2
Diffstat (limited to 'modules/pam_unix')
-rw-r--r-- | modules/pam_unix/Makefile.am | 8 | ||||
-rw-r--r-- | modules/pam_unix/Makefile.in | 42 | ||||
-rw-r--r-- | modules/pam_unix/README | 6 | ||||
-rw-r--r-- | modules/pam_unix/bigcrypt.c | 10 | ||||
-rw-r--r-- | modules/pam_unix/lckpwdf.-c | 10 | ||||
-rw-r--r-- | modules/pam_unix/md5.c | 40 | ||||
-rw-r--r-- | modules/pam_unix/md5.h | 10 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix.8 | 10 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix.8.xml | 6 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix_acct.c | 6 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix_passwd.c | 2 | ||||
-rw-r--r-- | modules/pam_unix/passverify.c | 173 | ||||
-rw-r--r-- | modules/pam_unix/passverify.h | 4 | ||||
-rw-r--r-- | modules/pam_unix/support.c | 48 | ||||
-rw-r--r-- | modules/pam_unix/unix_chkpwd.8 | 4 | ||||
-rw-r--r-- | modules/pam_unix/unix_chkpwd.c | 9 | ||||
-rw-r--r-- | modules/pam_unix/unix_update.8 | 4 | ||||
-rw-r--r-- | modules/pam_unix/unix_update.c | 13 |
18 files changed, 187 insertions, 218 deletions
diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am index 6463872a..1658735b 100644 --- a/modules/pam_unix/Makefile.am +++ b/modules/pam_unix/Makefile.am @@ -47,14 +47,14 @@ bigcrypt_LDADD = @LIBCRYPT@ unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \ passverify.c -unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" -unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ +unix_chkpwd_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" +unix_chkpwd_LDFLAGS = @EXE_LDFLAGS@ unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@ unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \ passverify.c -unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\" -unix_update_LDFLAGS = @PIE_LDFLAGS@ +unix_update_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\" +unix_update_LDFLAGS = @EXE_LDFLAGS@ unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@ if ENABLE_REGENERATE_MAN diff --git a/modules/pam_unix/Makefile.in b/modules/pam_unix/Makefile.in index bfc1a252..4dcfdf64 100644 --- a/modules/pam_unix/Makefile.in +++ b/modules/pam_unix/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -100,18 +100,21 @@ sbin_PROGRAMS = unix_chkpwd$(EXEEXT) unix_update$(EXEEXT) noinst_PROGRAMS = bigcrypt$(EXEEXT) subdir = modules/pam_unix ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ - $(top_srcdir)/m4/japhar_grep_cflags.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/jh_path_xml_catalog.m4 \ $(top_srcdir)/m4/ld-O1.m4 $(top_srcdir)/m4/ld-as-needed.m4 \ - $(top_srcdir)/m4/ld-no-undefined.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/ld-no-undefined.m4 \ + $(top_srcdir)/m4/ld-z-now.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libprelude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/warn_lang_flags.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \ @@ -431,6 +434,7 @@ am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log @@ -475,6 +479,9 @@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPT_CFLAGS = @CRYPT_CFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -488,6 +495,8 @@ ECONF_CFLAGS = @ECONF_CFLAGS@ ECONF_LIBS = @ECONF_LIBS@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +EXE_CFLAGS = @EXE_CFLAGS@ +EXE_LDFLAGS = @EXE_LDFLAGS@ FGREP = @FGREP@ FO2PDF = @FO2PDF@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ @@ -507,7 +516,6 @@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAUDIT = @LIBAUDIT@ -LIBCRACK = @LIBCRACK@ LIBCRYPT = @LIBCRYPT@ LIBDB = @LIBDB@ LIBDL = @LIBDL@ @@ -554,8 +562,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PIE_CFLAGS = @PIE_CFLAGS@ -PIE_LDFLAGS = @PIE_LDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -566,6 +572,7 @@ SECUREDIR = @SECUREDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +STRINGPARAM_HMAC = @STRINGPARAM_HMAC@ STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@ STRIP = @STRIP@ TIRPC_CFLAGS = @TIRPC_CFLAGS@ @@ -615,7 +622,6 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ -libc_cv_fpie = @libc_cv_fpie@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ @@ -623,9 +629,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -pam_cv_ld_O1 = @pam_cv_ld_O1@ -pam_cv_ld_as_needed = @pam_cv_ld_as_needed@ -pam_cv_ld_no_undefined = @pam_cv_ld_no_undefined@ pam_xauth_path = @pam_xauth_path@ pdfdir = @pdfdir@ prefix = @prefix@ @@ -635,6 +638,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemdunitdir = @systemdunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ @@ -670,14 +674,14 @@ bigcrypt_LDADD = @LIBCRYPT@ unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \ passverify.c -unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" -unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ +unix_chkpwd_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" +unix_chkpwd_LDFLAGS = @EXE_LDFLAGS@ unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@ unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \ passverify.c -unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\" -unix_update_LDFLAGS = @PIE_LDFLAGS@ +unix_update_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\" +unix_update_LDFLAGS = @EXE_LDFLAGS@ unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@ @ENABLE_REGENERATE_MAN_TRUE@dist_noinst_DATA = README all: all-am @@ -1254,7 +1258,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ - echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ diff --git a/modules/pam_unix/README b/modules/pam_unix/README index a87f34a5..67a2d215 100644 --- a/modules/pam_unix/README +++ b/modules/pam_unix/README @@ -99,7 +99,7 @@ use_authtok When password changing enforce the module to set the new password to the one provided by a previously stacked password module (this is used in the - example of the stacking of the pam_cracklib module documented below). + example of the stacking of the pam_passwdqc module documented below). authtok_type=type @@ -194,8 +194,8 @@ auth required pam_unix.so # Ensure users account and password are still active account required pam_unix.so # Change the user's password, but at first check the strength -# with pam_cracklib(8) -password required pam_cracklib.so retry=3 minlen=6 difok=3 +# with pam_passwdqc(8) +password required pam_passwdqc.so config=/etc/passwdqc.conf password required pam_unix.so use_authtok nullok yescrypt session required pam_unix.so diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c index e08e4098..d8d61a4b 100644 --- a/modules/pam_unix/bigcrypt.c +++ b/modules/pam_unix/bigcrypt.c @@ -29,9 +29,7 @@ #include <string.h> #include <stdlib.h> #include <security/_pam_macros.h> -#ifdef HAVE_LIBXCRYPT -#include <xcrypt.h> -#elif defined(HAVE_CRYPT_H) +#ifdef HAVE_CRYPT_H #include <crypt.h> #endif @@ -111,6 +109,9 @@ char *bigcrypt(const char *key, const char *salt) #endif if (tmp_ptr == NULL) { free(dec_c2_cryptbuf); +#ifdef HAVE_CRYPT_R + free(cdata); +#endif return NULL; } /* and place in the static area */ @@ -137,6 +138,9 @@ char *bigcrypt(const char *key, const char *salt) if (tmp_ptr == NULL) { _pam_overwrite(dec_c2_cryptbuf); free(dec_c2_cryptbuf); +#ifdef HAVE_CRYPT_R + free(cdata); +#endif return NULL; } diff --git a/modules/pam_unix/lckpwdf.-c b/modules/pam_unix/lckpwdf.-c index 7145617e..c3e63155 100644 --- a/modules/pam_unix/lckpwdf.-c +++ b/modules/pam_unix/lckpwdf.-c @@ -73,17 +73,17 @@ static int lckpwdf(void) lockfd = open(LOCKFILE, O_WRONLY); if(lockfd == -1 && errno == ENOENT) { - security_context_t create_context; + char *create_context_raw; int rc; - if(getfilecon("/etc/passwd", &create_context)) + if(getfilecon_raw("/etc/passwd", &create_context_raw)) return -1; - rc = setfscreatecon(create_context); - freecon(create_context); + rc = setfscreatecon_raw(create_context_raw); + freecon(create_context_raw); if(rc) return -1; lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); - if(setfscreatecon(NULL)) + if(setfscreatecon_raw(NULL)) return -1; } } diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c index 9954536f..593d6dc3 100644 --- a/modules/pam_unix/md5.c +++ b/modules/pam_unix/md5.c @@ -52,10 +52,10 @@ static void byteReverse(uint8_aligned *buf, unsigned longs) */ void MD5Name(MD5Init)(struct MD5Context *ctx) { - ctx->buf[0] = 0x67452301U; - ctx->buf[1] = 0xefcdab89U; - ctx->buf[2] = 0x98badcfeU; - ctx->buf[3] = 0x10325476U; + ctx->buf.i[0] = 0x67452301U; + ctx->buf.i[1] = 0xefcdab89U; + ctx->buf.i[2] = 0x98badcfeU; + ctx->buf.i[3] = 0x10325476U; ctx->bits[0] = 0; ctx->bits[1] = 0; @@ -81,7 +81,7 @@ void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsign /* Handle any leading odd-sized chunks */ if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; + unsigned char *p = ctx->in.c + t; t = 64 - t; if (len < t) { @@ -89,24 +89,24 @@ void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsign return; } memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + byteReverse(ctx->in.c, 16); + MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + memcpy(ctx->in.c, buf, 64); + byteReverse(ctx->in.c, 16); + MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ - memcpy(ctx->in, buf, len); + memcpy(ctx->in.c, buf, len); } /* @@ -123,7 +123,7 @@ void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ - p = ctx->in + count; + p = ctx->in.c + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ @@ -133,23 +133,23 @@ void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + byteReverse(ctx->in.c, 16); + MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i); /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); + memset(ctx->in.c, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } - byteReverse(ctx->in, 14); + byteReverse(ctx->in.c, 14); /* Append length in bits and transform */ - memcpy((uint32 *)ctx->in + 14, ctx->bits, 2*sizeof(uint32)); + memcpy(ctx->in.i + 14, ctx->bits, 2*sizeof(uint32)); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); + MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i); + byteReverse(ctx->buf.c, 4); + memcpy(digest, ctx->buf.c, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } diff --git a/modules/pam_unix/md5.h b/modules/pam_unix/md5.h index d9186b7f..3dc54bd2 100644 --- a/modules/pam_unix/md5.h +++ b/modules/pam_unix/md5.h @@ -7,9 +7,15 @@ typedef unsigned int uint32; struct MD5Context { - uint32 buf[4]; + union { + uint32 i[4]; + unsigned char c[16] PAM_ATTRIBUTE_ALIGNED(4); + } buf; uint32 bits[2]; - unsigned char in[64] PAM_ATTRIBUTE_ALIGNED(4); + union { + uint32 i[16]; + unsigned char c[64] PAM_ATTRIBUTE_ALIGNED(4); + } in; }; void GoodMD5Init(struct MD5Context *); diff --git a/modules/pam_unix/pam_unix.8 b/modules/pam_unix/pam_unix.8 index b396b66c..d9cdea5a 100644 --- a/modules/pam_unix/pam_unix.8 +++ b/modules/pam_unix/pam_unix.8 @@ -2,12 +2,12 @@ .\" Title: pam_unix .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 06/08/2020 +.\" Date: 09/03/2021 .\" Manual: Linux-PAM Manual .\" Source: Linux-PAM Manual .\" Language: English .\" -.TH "PAM_UNIX" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "PAM_UNIX" "8" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -126,7 +126,7 @@ This argument can be used to discourage the authentication component from reques When password changing enforce the module to set the new password to the one provided by a previously stacked \fBpassword\fR module (this is used in the example of the stacking of the -\fBpam_cracklib\fR +\fBpam_passwdqc\fR module documented below)\&. .RE .PP @@ -264,8 +264,8 @@ auth required pam_unix\&.so # Ensure users account and password are still active account required pam_unix\&.so # Change the user\*(Aqs password, but at first check the strength -# with pam_cracklib(8) -password required pam_cracklib\&.so retry=3 minlen=6 difok=3 +# with pam_passwdqc(8) +password required pam_passwdqc\&.so config=/etc/passwdqc\&.conf password required pam_unix\&.so use_authtok nullok yescrypt session required pam_unix\&.so diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index fa02c3a6..9f9c8185 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -223,7 +223,7 @@ When password changing enforce the module to set the new password to the one provided by a previously stacked <option>password</option> module (this is used in the - example of the stacking of the <command>pam_cracklib</command> + example of the stacking of the <command>pam_passwdqc</command> module documented below). </para> </listitem> @@ -465,8 +465,8 @@ auth required pam_unix.so # Ensure users account and password are still active account required pam_unix.so # Change the user's password, but at first check the strength -# with pam_cracklib(8) -password required pam_cracklib.so retry=3 minlen=6 difok=3 +# with pam_passwdqc(8) +password required pam_passwdqc.so config=/etc/passwdqc.conf password required pam_unix.so use_authtok nullok yescrypt session required pam_unix.so </programlisting> diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index de8d65c1..8f5ed3e0 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -189,7 +189,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) unsigned long long ctrl; const void *void_uname; const char *uname; - int retval, daysleft; + int retval, daysleft = -1; char buf[256]; D(("called.")); @@ -252,6 +252,10 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) _("Your account has expired; please contact your system administrator.")); break; case PAM_AUTHTOK_ERR: + /* + * We ignore "password changed too early" error + * as it is relevant only for password change. + */ retval = PAM_SUCCESS; /* fallthrough */ case PAM_SUCCESS: diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index e988b2e3..a20e919e 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -577,7 +577,7 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh } } - if (strlen(pass_new) > MAXPASS) { + if (strlen(pass_new) > PAM_MAX_RESP_SIZE) { remark = _("You must choose a shorter password."); D(("length exceeded [%s]", remark)); } else if (off(UNIX__IAMROOT, ctrl)) { diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index a571b4f7..f2474a5b 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -19,9 +19,7 @@ #include <sys/time.h> #include <sys/stat.h> #include <fcntl.h> -#ifdef HAVE_LIBXCRYPT -#include <xcrypt.h> -#elif defined(HAVE_CRYPT_H) +#ifdef HAVE_CRYPT_H #include <crypt.h> #endif @@ -243,12 +241,15 @@ PAMH_ARG_DECL(int get_account_info, * ...and shadow password file entry for this user, * if shadowing is enabled */ + *spwdent = pam_modutil_getspnam(pamh, name); + if (*spwdent == NULL) { #ifndef HELPER_COMPILE - if (geteuid() || SELINUX_ENABLED) + /* still a chance the user can authenticate */ return PAM_UNIX_RUN_HELPER; #endif - *spwdent = pam_modutil_getspnam(pamh, name); - if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) + return PAM_AUTHINFO_UNAVAIL; + } + if ((*spwdent)->sp_pwdp == NULL) return PAM_AUTHINFO_UNAVAIL; } } else { @@ -289,13 +290,7 @@ PAMH_ARG_DECL(int check_shadow_expiry, D(("account expired")); return PAM_ACCT_EXPIRED; } -#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE - if (spent->sp_lstchg == 0 || - crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_LEGACY || - crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_TOO_CHEAP) { -#else if (spent->sp_lstchg == 0) { -#endif D(("need a new password")); *daysleft = 0; return PAM_NEW_AUTHTOK_REQD; @@ -452,7 +447,7 @@ PAMH_ARG_DECL(char * create_password_hash, algoid = "$6$"; } else { /* must be crypt/bigcrypt */ char tmppass[9]; - char *crypted; + char *hashed; crypt_make_salt(salt, 2); if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) { @@ -460,10 +455,10 @@ PAMH_ARG_DECL(char * create_password_hash, tmppass[sizeof(tmppass)-1] = '\0'; password = tmppass; } - crypted = bigcrypt(password, salt); + hashed = bigcrypt(password, salt); memset(tmppass, '\0', sizeof(tmppass)); password = NULL; - return crypted; + return hashed; } #if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY @@ -473,23 +468,11 @@ PAMH_ARG_DECL(char * create_password_hash, */ sp = crypt_gensalt_rn(algoid, rounds, NULL, 0, salt, sizeof(salt)); #else -#ifdef HAVE_CRYPT_GENSALT_R - if (on(UNIX_BLOWFISH_PASS, ctrl)) { - char entropy[17]; - crypt_make_salt(entropy, sizeof(entropy) - 1); - sp = crypt_gensalt_r (algoid, rounds, - entropy, sizeof(entropy), - salt, sizeof(salt)); - } else { -#endif - sp = stpcpy(salt, algoid); - if (on(UNIX_ALGO_ROUNDS, ctrl)) { - sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds); - } - crypt_make_salt(sp, 16); -#ifdef HAVE_CRYPT_GENSALT_R + sp = stpcpy(salt, algoid); + if (on(UNIX_ALGO_ROUNDS, ctrl)) { + sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds); } -#endif + crypt_make_salt(sp, 16); #endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */ #ifdef HAVE_CRYPT_R sp = NULL; @@ -650,7 +633,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, struct stat st; size_t len = strlen(forwho); #ifdef WITH_SELINUX - security_context_t prev_context=NULL; + char *prev_context_raw = NULL; #endif if (howmany < 0) { @@ -665,20 +648,20 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - security_context_t passwd_context=NULL; - if (getfilecon("/etc/passwd",&passwd_context)<0) { + char *passwd_context_raw = NULL; + if (getfilecon_raw("/etc/passwd",&passwd_context_raw)<0) { return PAM_AUTHTOK_ERR; }; - if (getfscreatecon(&prev_context)<0) { - freecon(passwd_context); + if (getfscreatecon_raw(&prev_context_raw)<0) { + freecon(passwd_context_raw); return PAM_AUTHTOK_ERR; } - if (setfscreatecon(passwd_context)) { - freecon(passwd_context); - freecon(prev_context); + if (setfscreatecon_raw(passwd_context_raw)) { + freecon(passwd_context_raw); + freecon(prev_context_raw); return PAM_AUTHTOK_ERR; } - freecon(passwd_context); + freecon(passwd_context_raw); } #endif pwfile = fopen(OPW_TMPFILE, "w"); @@ -796,12 +779,12 @@ done: } #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { + if (setfscreatecon_raw(prev_context_raw)) { err = 1; } - if (prev_context) - freecon(prev_context); - prev_context=NULL; + if (prev_context_raw) + freecon(prev_context_raw); + prev_context_raw = NULL; } #endif if (!err) { @@ -821,26 +804,26 @@ PAMH_ARG_DECL(int unix_update_passwd, int err = 1; int oldmask; #ifdef WITH_SELINUX - security_context_t prev_context=NULL; + char *prev_context_raw = NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - security_context_t passwd_context=NULL; - if (getfilecon("/etc/passwd",&passwd_context)<0) { + char *passwd_context_raw = NULL; + if (getfilecon_raw("/etc/passwd",&passwd_context_raw)<0) { return PAM_AUTHTOK_ERR; }; - if (getfscreatecon(&prev_context)<0) { - freecon(passwd_context); + if (getfscreatecon_raw(&prev_context_raw)<0) { + freecon(passwd_context_raw); return PAM_AUTHTOK_ERR; } - if (setfscreatecon(passwd_context)) { - freecon(passwd_context); - freecon(prev_context); + if (setfscreatecon_raw(passwd_context_raw)) { + freecon(passwd_context_raw); + freecon(prev_context_raw); return PAM_AUTHTOK_ERR; } - freecon(passwd_context); + freecon(passwd_context_raw); } #endif pwfile = fopen(PW_TMPFILE, "w"); @@ -919,12 +902,12 @@ done: } #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { + if (setfscreatecon_raw(prev_context_raw)) { err = 1; } - if (prev_context) - freecon(prev_context); - prev_context=NULL; + if (prev_context_raw) + freecon(prev_context_raw); + prev_context_raw = NULL; } #endif if (!err) { @@ -945,27 +928,27 @@ PAMH_ARG_DECL(int unix_update_shadow, int oldmask; int wroteentry = 0; #ifdef WITH_SELINUX - security_context_t prev_context=NULL; + char *prev_context_raw = NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - security_context_t shadow_context=NULL; - if (getfilecon("/etc/shadow",&shadow_context)<0) { + char *shadow_context_raw = NULL; + if (getfilecon_raw("/etc/shadow",&shadow_context_raw)<0) { return PAM_AUTHTOK_ERR; }; - if (getfscreatecon(&prev_context)<0) { - freecon(shadow_context); + if (getfscreatecon_raw(&prev_context_raw)<0) { + freecon(shadow_context_raw); return PAM_AUTHTOK_ERR; } - if (setfscreatecon(shadow_context)) { - freecon(shadow_context); - freecon(prev_context); + if (setfscreatecon_raw(shadow_context_raw)) { + freecon(shadow_context_raw); + freecon(prev_context_raw); return PAM_AUTHTOK_ERR; } - freecon(shadow_context); + freecon(shadow_context_raw); } #endif pwfile = fopen(SH_TMPFILE, "w"); @@ -1065,12 +1048,12 @@ PAMH_ARG_DECL(int unix_update_shadow, #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { + if (setfscreatecon_raw(prev_context_raw)) { err = 1; } - if (prev_context) - freecon(prev_context); - prev_context=NULL; + if (prev_context_raw) + freecon(prev_context_raw); + prev_context_raw = NULL; } #endif @@ -1096,6 +1079,12 @@ helper_verify_password(const char *name, const char *p, int nullok) if (pwd == NULL || hash == NULL) { helper_log_err(LOG_NOTICE, "check pass; user unknown"); retval = PAM_USER_UNKNOWN; + } else if (p[0] == '\0' && nullok) { + if (hash[0] == '\0') { + retval = PAM_SUCCESS; + } else { + retval = PAM_AUTH_ERR; + } } else { retval = verify_pwd_hash(p, hash, nullok); } @@ -1111,6 +1100,7 @@ helper_verify_password(const char *name, const char *p, int nullok) } void +PAM_FORMAT((printf, 2, 3)) helper_log_err(int err, const char *format, ...) { va_list args; @@ -1180,49 +1170,6 @@ getuidname(uid_t uid) return username; } -int -read_passwords(int fd, int npass, char **passwords) -{ - /* The passwords array must contain npass preallocated - * buffers of length MAXPASS + 1 - */ - int rbytes = 0; - int offset = 0; - int i = 0; - char *pptr; - while (npass > 0) { - rbytes = read(fd, passwords[i]+offset, MAXPASS+1-offset); - - if (rbytes < 0) { - if (errno == EINTR) continue; - break; - } - if (rbytes == 0) - break; - - while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes)) - != NULL) { - rbytes -= pptr - (passwords[i]+offset) + 1; - i++; - offset = 0; - npass--; - if (rbytes > 0) { - if (npass > 0) - memcpy(passwords[i], pptr+1, rbytes); - memset(pptr+1, '\0', rbytes); - } - } - offset += rbytes; - } - - /* clear up */ - if (offset > 0 && npass > 0) { - memset(passwords[i], '\0', offset); - } - - return i; -} - #endif /* ****************************************************************** * * Copyright (c) Jan Rękorajski 1999. diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index e9a88fbf..c07037d2 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -8,8 +8,6 @@ #define PAM_UNIX_RUN_HELPER PAM_CRED_INSUFFICIENT -#define MAXPASS PAM_MAX_RESP_SIZE /* the maximum length of a password */ - #define OLD_PASSWORDS_FILE "/etc/security/opasswd" int @@ -50,8 +48,6 @@ setup_signals(void); char * getuidname(uid_t uid); -int -read_passwords(int fd, int npass, char **passwords); #endif #ifdef HELPER_COMPILE diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 41db1f04..27ca7127 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -601,6 +601,9 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name char *salt = NULL; int daysleft; int retval; + int blank = 0; + int execloop; + int nonexistent_check = 1; D(("called")); @@ -624,32 +627,35 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name /* UNIX passwords area */ - retval = get_pwd_hash(pamh, name, &pwd, &salt); - - if (retval == PAM_UNIX_RUN_HELPER) { - /* salt will not be set here so we can return immediately */ - if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS) - return 1; - else - return 0; - } + /* + * Execute this loop twice: one checking the password hash of an existing + * user and another one for a non-existing user. This way the runtimes + * are equal, making it more difficult to differentiate existing from + * non-existing users. + */ + for (execloop = 0; execloop < 2; ++execloop) { + retval = get_pwd_hash(pamh, name, &pwd, &salt); - /* Does this user have a password? */ - if (salt == NULL) { - retval = 0; - } else { - if (strlen(salt) == 0) - retval = 1; - else - retval = 0; + if (retval == PAM_UNIX_RUN_HELPER) { + if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS) + blank = nonexistent_check; + } else if (retval == PAM_USER_UNKNOWN) { + name = "root"; + nonexistent_check = 0; + continue; + } else if (salt != NULL) { + if (strlen(salt) == 0) + blank = nonexistent_check; + } + name = "pam_unix_non_existent:"; + /* non-existent user check will not affect the blank value */ } /* tidy up */ - if (salt) _pam_delete(salt); - return retval; + return blank; } int _unix_verify_password(pam_handle_t * pamh, const char *name @@ -658,7 +664,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name struct passwd *pwd = NULL; char *salt = NULL; char *data_name; - char pw[MAXPASS + 1]; + char pw[PAM_MAX_RESP_SIZE + 1]; int retval; @@ -685,7 +691,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name); } - if (p != NULL && strlen(p) > MAXPASS) { + if (p != NULL && strlen(p) > PAM_MAX_RESP_SIZE) { memset(pw, 0, sizeof(pw)); p = strncpy(pw, p, sizeof(pw) - 1); } diff --git a/modules/pam_unix/unix_chkpwd.8 b/modules/pam_unix/unix_chkpwd.8 index e5d40ad3..93c95bd6 100644 --- a/modules/pam_unix/unix_chkpwd.8 +++ b/modules/pam_unix/unix_chkpwd.8 @@ -2,12 +2,12 @@ .\" Title: unix_chkpwd .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 06/08/2020 +.\" Date: 09/03/2021 .\" Manual: Linux-PAM Manual .\" Source: Linux-PAM Manual .\" Language: English .\" -.TH "UNIX_CHKPWD" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "UNIX_CHKPWD" "8" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index 88647e58..3931bab2 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -33,6 +33,7 @@ #include <security/_pam_macros.h> #include "passverify.h" +#include "pam_inline.h" static int _check_expiry(const char *uname) { @@ -89,7 +90,7 @@ static int _audit_log(int type, const char *uname, int rc) int main(int argc, char *argv[]) { - char pass[MAXPASS + 1]; + char pass[PAM_MAX_RESP_SIZE + 1]; char *option; int npass, nullok; int blankpass = 0; @@ -136,7 +137,7 @@ int main(int argc, char *argv[]) user = getuidname(getuid()); /* if the caller specifies the username, verify that user matches it */ - if (strcmp(user, argv[1])) { + if (user == NULL || strcmp(user, argv[1])) { user = argv[1]; /* no match -> permanently change to the real user and proceed */ if (setuid(getuid()) != 0) @@ -162,7 +163,7 @@ int main(int argc, char *argv[]) } /* read the password from stdin (a pipe from the pam_unix module) */ - npass = read_passwords(STDIN_FILENO, 1, passwords); + npass = pam_read_passwords(STDIN_FILENO, 1, passwords); if (npass != 1) { /* is it a valid password? */ helper_log_err(LOG_DEBUG, "no password supplied"); @@ -175,7 +176,7 @@ int main(int argc, char *argv[]) retval = helper_verify_password(user, pass, nullok); - memset(pass, '\0', MAXPASS); /* clear memory of the password */ + memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */ /* return pass or fail */ diff --git a/modules/pam_unix/unix_update.8 b/modules/pam_unix/unix_update.8 index 4a7a3d1b..b1f5ac71 100644 --- a/modules/pam_unix/unix_update.8 +++ b/modules/pam_unix/unix_update.8 @@ -2,12 +2,12 @@ .\" Title: unix_update .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 06/08/2020 +.\" Date: 09/03/2021 .\" Manual: Linux-PAM Manual .\" Source: Linux-PAM Manual .\" Language: English .\" -.TH "UNIX_UPDATE" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "UNIX_UPDATE" "8" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c index 6ea7ea51..3559972b 100644 --- a/modules/pam_unix/unix_update.c +++ b/modules/pam_unix/unix_update.c @@ -32,14 +32,15 @@ #include <security/_pam_macros.h> #include "passverify.h" +#include "pam_inline.h" static int set_password(const char *forwho, const char *shadow, const char *remember) { struct passwd *pwd = NULL; int retval; - char pass[MAXPASS + 1]; - char towhat[MAXPASS + 1]; + char pass[PAM_MAX_RESP_SIZE + 1]; + char towhat[PAM_MAX_RESP_SIZE + 1]; int npass = 0; /* we don't care about number format errors because the helper should be called internally only */ @@ -49,12 +50,12 @@ set_password(const char *forwho, const char *shadow, const char *remember) /* read the password from stdin (a pipe from the pam_unix module) */ - npass = read_passwords(STDIN_FILENO, 2, passwords); + npass = pam_read_passwords(STDIN_FILENO, 2, passwords); if (npass != 2) { /* is it a valid password? */ if (npass == 1) { helper_log_err(LOG_DEBUG, "no new password supplied"); - memset(pass, '\0', MAXPASS); + memset(pass, '\0', PAM_MAX_RESP_SIZE); } else { helper_log_err(LOG_DEBUG, "no valid passwords supplied"); } @@ -97,8 +98,8 @@ set_password(const char *forwho, const char *shadow, const char *remember) } done: - memset(pass, '\0', MAXPASS); - memset(towhat, '\0', MAXPASS); + memset(pass, '\0', PAM_MAX_RESP_SIZE); + memset(towhat, '\0', PAM_MAX_RESP_SIZE); unlock_pwdf(); |