summaryrefslogtreecommitdiff
path: root/modules/pam_unix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_unix')
-rw-r--r--modules/pam_unix/Makefile.am11
-rw-r--r--modules/pam_unix/Makefile.in33
-rw-r--r--modules/pam_unix/README36
-rw-r--r--modules/pam_unix/README.xml32
-rw-r--r--modules/pam_unix/bigcrypt.c13
-rw-r--r--modules/pam_unix/md5.c29
-rw-r--r--modules/pam_unix/md5_crypt.c4
-rw-r--r--modules/pam_unix/obscure.c198
-rw-r--r--modules/pam_unix/pam_unix.891
-rw-r--r--modules/pam_unix/pam_unix.8.xml168
-rw-r--r--modules/pam_unix/pam_unix_passwd.c27
-rw-r--r--modules/pam_unix/passverify.c26
-rw-r--r--modules/pam_unix/passverify.h2
-rw-r--r--modules/pam_unix/support.c4
-rw-r--r--modules/pam_unix/support.h89
-rw-r--r--modules/pam_unix/unix_chkpwd.88
-rw-r--r--modules/pam_unix/unix_chkpwd.8.xml23
-rw-r--r--modules/pam_unix/unix_chkpwd.c5
-rw-r--r--modules/pam_unix/unix_update.88
-rw-r--r--modules/pam_unix/unix_update.8.xml23
-rw-r--r--modules/pam_unix/unix_update.c11
-rw-r--r--modules/pam_unix/yppasswd.h81
-rw-r--r--modules/pam_unix/yppasswd_xdr.c52
23 files changed, 667 insertions, 307 deletions
diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am
index 1658735b..ddba63c5 100644
--- a/modules/pam_unix/Makefile.am
+++ b/modules/pam_unix/Makefile.am
@@ -5,7 +5,7 @@
CLEANFILES = *~
MAINTAINERCLEANFILES = $(MANS) README
-EXTRA_DIST = md5.c md5_crypt.c lckpwdf.-c $(XMLS) CHANGELOG
+EXTRA_DIST = md5.c md5_crypt.c lckpwdf.-c yppasswd_xdr.c $(XMLS) CHANGELOG
if HAVE_DOC
dist_man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8
@@ -15,7 +15,11 @@ dist_check_SCRIPTS = tst-pam_unix
TESTS = $(dist_check_SCRIPTS)
securelibdir = $(SECUREDIR)
+if HAVE_VENDORDIR
+secureconfdir = $(VENDOR_SCONFIGDIR)
+else
secureconfdir = $(SCONFIGDIR)
+endif
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
@@ -39,7 +43,10 @@ noinst_PROGRAMS = bigcrypt
pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \
pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \
- passverify.c yppasswd_xdr.c md5_good.c md5_broken.c
+ passverify.c md5_good.c md5_broken.c obscure.c
+if HAVE_NIS
+ pam_unix_la_SOURCES += yppasswd_xdr.c
+endif
bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c
bigcrypt_CFLAGS = $(AM_CFLAGS)
diff --git a/modules/pam_unix/Makefile.in b/modules/pam_unix/Makefile.in
index 4dcfdf64..1de5b72b 100644
--- a/modules/pam_unix/Makefile.in
+++ b/modules/pam_unix/Makefile.in
@@ -98,6 +98,7 @@ host_triplet = @host@
@HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map
sbin_PROGRAMS = unix_chkpwd$(EXEEXT) unix_update$(EXEEXT)
noinst_PROGRAMS = bigcrypt$(EXEEXT)
+@HAVE_NIS_TRUE@am__append_2 = yppasswd_xdr.c
subdir = modules/pam_unix
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
@@ -156,9 +157,13 @@ am__uninstall_files_from_dir = { \
}
LTLIBRARIES = $(securelib_LTLIBRARIES)
pam_unix_la_DEPENDENCIES = $(top_builddir)/libpam/libpam.la
+am__pam_unix_la_SOURCES_DIST = bigcrypt.c pam_unix_acct.c \
+ pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \
+ passverify.c md5_good.c md5_broken.c yppasswd_xdr.c
+@HAVE_NIS_TRUE@am__objects_1 = yppasswd_xdr.lo
am_pam_unix_la_OBJECTS = bigcrypt.lo pam_unix_acct.lo pam_unix_auth.lo \
pam_unix_passwd.lo pam_unix_sess.lo support.lo passverify.lo \
- yppasswd_xdr.lo md5_good.lo md5_broken.lo
+ md5_good.lo md5_broken.lo $(am__objects_1)
pam_unix_la_OBJECTS = $(am_pam_unix_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -247,7 +252,7 @@ am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(pam_unix_la_SOURCES) $(bigcrypt_SOURCES) \
$(unix_chkpwd_SOURCES) $(unix_update_SOURCES)
-DIST_SOURCES = $(pam_unix_la_SOURCES) $(bigcrypt_SOURCES) \
+DIST_SOURCES = $(am__pam_unix_la_SOURCES_DIST) $(bigcrypt_SOURCES) \
$(unix_chkpwd_SOURCES) $(unix_update_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
@@ -486,6 +491,7 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOCBOOK_RNG = @DOCBOOK_RNG@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
@@ -498,11 +504,13 @@ EXEEXT = @EXEEXT@
EXE_CFLAGS = @EXE_CFLAGS@
EXE_LDFLAGS = @EXE_LDFLAGS@
FGREP = @FGREP@
+FILECMD = @FILECMD@
FO2PDF = @FO2PDF@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
+HTML_STYLESHEET = @HTML_STYLESHEET@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -534,12 +542,14 @@ LIBSELINUX = @LIBSELINUX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
+LOGIND_CFLAGS = @LOGIND_CFLAGS@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
+MAN_STYLESHEET = @MAN_STYLESHEET@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
@@ -562,6 +572,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PDF_STYLESHEET = @PDF_STYLESHEET@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -572,12 +583,16 @@ SECUREDIR = @SECUREDIR@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
-STRINGPARAM_HMAC = @STRINGPARAM_HMAC@
+STRINGPARAM_PROFILECONDITIONS = @STRINGPARAM_PROFILECONDITIONS@
STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@
STRIP = @STRIP@
+SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
TIRPC_CFLAGS = @TIRPC_CFLAGS@
TIRPC_LIBS = @TIRPC_LIBS@
+TXT_STYLESHEET = @TXT_STYLESHEET@
USE_NLS = @USE_NLS@
+VENDOR_SCONFIGDIR = @VENDOR_SCONFIGDIR@
VERSION = @VERSION@
WARN_CFLAGS = @WARN_CFLAGS@
XGETTEXT = @XGETTEXT@
@@ -645,13 +660,14 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
CLEANFILES = *~
MAINTAINERCLEANFILES = $(MANS) README
-EXTRA_DIST = md5.c md5_crypt.c lckpwdf.-c $(XMLS) CHANGELOG
+EXTRA_DIST = md5.c md5_crypt.c lckpwdf.-c yppasswd_xdr.c $(XMLS) CHANGELOG
@HAVE_DOC_TRUE@dist_man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8
XMLS = README.xml pam_unix.8.xml unix_chkpwd.8.xml unix_update.8.xml
dist_check_SCRIPTS = tst-pam_unix
TESTS = $(dist_check_SCRIPTS)
securelibdir = $(SECUREDIR)
-secureconfdir = $(SCONFIGDIR)
+@HAVE_VENDORDIR_FALSE@secureconfdir = $(SCONFIGDIR)
+@HAVE_VENDORDIR_TRUE@secureconfdir = $(VENDOR_SCONFIGDIR)
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
-DUPDATE_HELPER=\"$(sbindir)/unix_update\" \
@@ -664,10 +680,9 @@ pam_unix_la_LIBADD = $(top_builddir)/libpam/libpam.la \
securelib_LTLIBRARIES = pam_unix.la
noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h
-pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \
- pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \
- passverify.c yppasswd_xdr.c md5_good.c md5_broken.c
-
+pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c pam_unix_auth.c \
+ pam_unix_passwd.c pam_unix_sess.c support.c passverify.c \
+ md5_good.c md5_broken.c $(am__append_2)
bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c
bigcrypt_CFLAGS = $(AM_CFLAGS)
bigcrypt_LDADD = @LIBCRYPT@
diff --git a/modules/pam_unix/README b/modules/pam_unix/README
index 67a2d215..be11095f 100644
--- a/modules/pam_unix/README
+++ b/modules/pam_unix/README
@@ -171,8 +171,40 @@ broken_shadow
minlen=n
- Set a minimum password length of n characters. The max. for DES crypt based
- passwords are 8 characters.
+ Set a minimum password length of n characters. The default value is 6. The
+ maximum for DES crypt-based passwords is 8 characters.
+
+obscure
+
+ Enable some extra checks on password strength. These checks are based on
+ the "obscure" checks in the original shadow package. The behavior is
+ similar to the pam_cracklib module, but for non-dictionary-based checks.
+ The following checks are implemented:
+
+ Palindrome
+
+ Verifies that the new password is not a palindrome of (i.e., the
+ reverse of) the previous one.
+
+ Case Change Only
+
+ Verifies that the new password isn't the same as the old one with a
+ change of case.
+
+ Similar
+
+ Verifies that the new password isn't too much like the previous one.
+
+ Simple
+
+ Is the new password too simple? This is based on the length of the
+ password and the number of different types of characters (alpha,
+ numeric, etc.) used.
+
+ Rotated
+
+ Is the new password a rotated version of the old password? (E.g.,
+ "billy" and "illyb")
no_pass_expiry
diff --git a/modules/pam_unix/README.xml b/modules/pam_unix/README.xml
index 7fd340b3..49a65946 100644
--- a/modules/pam_unix/README.xml
+++ b/modules/pam_unix/README.xml
@@ -1,41 +1,27 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-"http://www.docbook.org/xml/4.3/docbookx.dtd"
-[
-<!--
-<!ENTITY pamaccess SYSTEM "pam_unix.8.xml">
--->
-]>
+<article xmlns="http://docbook.org/ns/docbook" version="5.0">
-<article>
-
- <articleinfo>
+ <info>
<title>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_unix.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_unix-name"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_unix.8.xml" xpointer='xpointer(id("pam_unix-name")/*)'/>
</title>
- </articleinfo>
+ </info>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-description"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_unix.8.xml" xpointer='xpointer(id("pam_unix-description")/*)'/>
</section>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-options"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_unix.8.xml" xpointer='xpointer(id("pam_unix-options")/*)'/>
</section>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-examples"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_unix.8.xml" xpointer='xpointer(id("pam_unix-examples")/*)'/>
</section>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-author"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_unix.8.xml" xpointer='xpointer(id("pam_unix-author")/*)'/>
</section>
-</article>
+</article> \ No newline at end of file
diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c
index d8d61a4b..c1028668 100644
--- a/modules/pam_unix/bigcrypt.c
+++ b/modules/pam_unix/bigcrypt.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdlib.h>
#include <security/_pam_macros.h>
+#include "pam_inline.h"
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
@@ -56,12 +57,12 @@ char *bigcrypt(const char *key, const char *salt)
#endif
unsigned long int keylen, n_seg, j;
char *cipher_ptr, *plaintext_ptr, *tmp_ptr, *salt_ptr;
- char keybuf[KEYBUF_SIZE + 1];
+ char keybuf[KEYBUF_SIZE + 1] = {};
D(("called with key='%s', salt='%s'.", key, salt));
/* reset arrays */
- dec_c2_cryptbuf = malloc(CBUF_SIZE);
+ dec_c2_cryptbuf = calloc(1, CBUF_SIZE);
if (!dec_c2_cryptbuf) {
return NULL;
}
@@ -73,8 +74,6 @@ char *bigcrypt(const char *key, const char *salt)
}
cdata->initialized = 0;
#endif
- memset(keybuf, 0, KEYBUF_SIZE + 1);
- memset(dec_c2_cryptbuf, 0, CBUF_SIZE);
/* fill KEYBUF_SIZE with key */
strncpy(keybuf, key, KEYBUF_SIZE);
@@ -116,6 +115,7 @@ char *bigcrypt(const char *key, const char *salt)
}
/* and place in the static area */
strncpy(cipher_ptr, tmp_ptr, 13);
+ pam_overwrite_string(tmp_ptr);
cipher_ptr += ESEGMENT_SIZE + SALT_SIZE;
plaintext_ptr += SEGMENT_SIZE; /* first block of SEGMENT_SIZE */
@@ -136,9 +136,10 @@ char *bigcrypt(const char *key, const char *salt)
tmp_ptr = crypt(plaintext_ptr, salt_ptr);
#endif
if (tmp_ptr == NULL) {
- _pam_overwrite(dec_c2_cryptbuf);
+ pam_overwrite_string(dec_c2_cryptbuf);
free(dec_c2_cryptbuf);
#ifdef HAVE_CRYPT_R
+ pam_overwrite_object(cdata);
free(cdata);
#endif
return NULL;
@@ -146,6 +147,7 @@ char *bigcrypt(const char *key, const char *salt)
/* skip the salt for seg!=0 */
strncpy(cipher_ptr, (tmp_ptr + SALT_SIZE), ESEGMENT_SIZE);
+ pam_overwrite_string(tmp_ptr);
cipher_ptr += ESEGMENT_SIZE;
plaintext_ptr += SEGMENT_SIZE;
@@ -155,6 +157,7 @@ char *bigcrypt(const char *key, const char *salt)
D(("key=|%s|, salt=|%s|\nbuf=|%s|\n", key, salt, dec_c2_cryptbuf));
#ifdef HAVE_CRYPT_R
+ pam_overwrite_object(cdata);
free(cdata);
#endif
diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c
index 593d6dc3..95b8de4c 100644
--- a/modules/pam_unix/md5.c
+++ b/modules/pam_unix/md5.c
@@ -21,26 +21,27 @@
#include <string.h>
#include "md5.h"
+#include "pam_inline.h"
+
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
#else
-typedef unsigned char PAM_ATTRIBUTE_ALIGNED(4) uint8_aligned;
-
-static void byteReverse(uint8_aligned *buf, unsigned longs);
+static void byteReverse(uint32 *buf, unsigned longs);
#ifndef ASM_MD5
/*
* Note: this code is harmless on little-endian machines.
*/
-static void byteReverse(uint8_aligned *buf, unsigned longs)
+static void byteReverse(uint32 *buf, unsigned longs)
{
uint32 t;
do {
- t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32 *) buf = t;
- buf += 4;
+ unsigned char *p = (unsigned char *) buf;
+ t = (uint32) ((unsigned) p[3] << 8 | p[2]) << 16 |
+ ((unsigned) p[1] << 8 | p[0]);
+ *buf = t;
+ ++buf;
} while (--longs);
}
#endif
@@ -89,7 +90,7 @@ void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsign
return;
}
memcpy(p, buf, t);
- byteReverse(ctx->in.c, 16);
+ byteReverse(ctx->in.i, 16);
MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i);
buf += t;
len -= t;
@@ -98,7 +99,7 @@ void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsign
while (len >= 64) {
memcpy(ctx->in.c, buf, 64);
- byteReverse(ctx->in.c, 16);
+ byteReverse(ctx->in.i, 16);
MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i);
buf += 64;
len -= 64;
@@ -133,7 +134,7 @@ 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.c, 16);
+ byteReverse(ctx->in.i, 16);
MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i);
/* Now fill the next block with 56 bytes */
@@ -142,15 +143,15 @@ void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx)
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
- byteReverse(ctx->in.c, 14);
+ byteReverse(ctx->in.i, 14);
/* Append length in bits and transform */
memcpy(ctx->in.i + 14, ctx->bits, 2*sizeof(uint32));
MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i);
- byteReverse(ctx->buf.c, 4);
+ byteReverse(ctx->buf.i, 4);
memcpy(digest, ctx->buf.c, 16);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+ pam_overwrite_object(ctx); /* In case it's sensitive */
}
#ifndef ASM_MD5
diff --git a/modules/pam_unix/md5_crypt.c b/modules/pam_unix/md5_crypt.c
index 94f7b434..ed5ecda4 100644
--- a/modules/pam_unix/md5_crypt.c
+++ b/modules/pam_unix/md5_crypt.c
@@ -87,7 +87,7 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt)
MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl);
/* Don't leave anything around in vm they could use. */
- memset(final, 0, sizeof final);
+ pam_overwrite_array(final);
/* Then something really weird... */
for (j = 0, i = strlen(pw); i; i >>= 1)
@@ -151,7 +151,7 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt)
*p = '\0';
/* Don't leave anything around in vm they could use. */
- memset(final, 0, sizeof final);
+ pam_overwrite_array(final);
return passwd;
}
diff --git a/modules/pam_unix/obscure.c b/modules/pam_unix/obscure.c
new file mode 100644
index 00000000..2ffac920
--- /dev/null
+++ b/modules/pam_unix/obscure.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 1989 - 1994, Julianne Frances Haugh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH 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.
+ */
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <security/pam_modules.h>
+#include <security/_pam_macros.h>
+
+
+#include "support.h"
+
+/* can't be a palindrome - like `R A D A R' or `M A D A M' */
+static int palindrome(const char *old, const char *new) {
+ int i, j;
+
+ i = strlen (new);
+
+ for (j = 0;j < i;j++)
+ if (new[i - j - 1] != new[j])
+ return 0;
+
+ return 1;
+}
+
+/* more than half of the characters are different ones. */
+static int similar(const char *old, const char *new) {
+ int i, j;
+
+ /*
+ * XXX - sometimes this fails when changing from a simple password
+ * to a really long one (MD5). For now, I just return success if
+ * the new password is long enough. Please feel free to suggest
+ * something better... --marekm
+ */
+ if (strlen(new) >= 8)
+ return 0;
+
+ for (i = j = 0; new[i] && old[i]; i++)
+ if (strchr(new, old[i]))
+ j++;
+
+ if (i >= j * 2)
+ return 0;
+
+ return 1;
+}
+
+/* a nice mix of characters. */
+static int simple(const char *old, const char *new) {
+ int digits = 0;
+ int uppers = 0;
+ int lowers = 0;
+ int others = 0;
+ int size;
+ int i;
+
+ for (i = 0;new[i];i++) {
+ if (isdigit (new[i]))
+ digits++;
+ else if (isupper (new[i]))
+ uppers++;
+ else if (islower (new[i]))
+ lowers++;
+ else
+ others++;
+ }
+
+ /*
+ * The scam is this - a password of only one character type
+ * must be 8 letters long. Two types, 7, and so on.
+ */
+
+ size = 9;
+ if (digits) size--;
+ if (uppers) size--;
+ if (lowers) size--;
+ if (others) size--;
+
+ if (size <= i)
+ return 0;
+
+ return 1;
+}
+
+static char *str_lower(char *string) {
+ char *cp;
+
+ for (cp = string; *cp; cp++)
+ *cp = tolower(*cp);
+ return string;
+}
+
+static const char * password_check(const char *old, const char *new,
+ const struct passwd *pwdp) {
+ const char *msg = NULL;
+ char *oldmono, *newmono, *wrapped;
+
+ if (strcmp(new, old) == 0)
+ return _("Bad: new password must be different than the old one");
+
+ newmono = str_lower(strdup(new));
+ oldmono = str_lower(strdup(old));
+ wrapped = (char *)malloc(strlen(oldmono) * 2 + 1);
+ strcpy (wrapped, oldmono);
+ strcat (wrapped, oldmono);
+
+ if (palindrome(oldmono, newmono)) {
+ msg = _("Bad: new password cannot be a palindrome");
+ } else if (strcmp(oldmono, newmono) == 0) {
+ msg = _("Bad: new and old password must differ by more than just case");
+ } else if (similar(oldmono, newmono)) {
+ msg = _("Bad: new and old password are too similar");
+ } else if (simple(old, new)) {
+ msg = _("Bad: new password is too simple");
+ } else if (strstr(wrapped, newmono)) {
+ msg = _("Bad: new password is just a wrapped version of the old one");
+ }
+
+ _pam_delete(newmono);
+ _pam_delete(oldmono);
+ _pam_delete(wrapped);
+
+ return msg;
+}
+
+const char *obscure_msg(const char *old, const char *new,
+ const struct passwd *pwdp, unsigned int ctrl) {
+ int oldlen, newlen;
+ char *new1, *old1;
+ const char *msg;
+
+ if (old == NULL)
+ return NULL; /* no check if old is NULL */
+
+ oldlen = strlen(old);
+ newlen = strlen(new);
+
+ /* Remaining checks are optional. */
+ if (off(UNIX_OBSCURE_CHECKS,ctrl))
+ return NULL;
+
+ if ((msg = password_check(old, new, pwdp)) != NULL)
+ return msg;
+
+ /* The traditional crypt() truncates passwords to 8 chars. It is
+ possible to circumvent the above checks by choosing an easy
+ 8-char password and adding some random characters to it...
+ Example: "password$%^&*123". So check it again, this time
+ truncated to the maximum length. Idea from npasswd. --marekm */
+
+ if (!UNIX_DES_CRYPT(ctrl))
+ return NULL; /* unlimited password length */
+
+ if (oldlen <= 8 && newlen <= 8)
+ return NULL;
+
+ new1 = strndup(new,8);
+ old1 = strndup(old,8);
+
+ msg = password_check(old1, new1, pwdp);
+
+ _pam_delete(new1);
+ _pam_delete(old1);
+
+ return msg;
+}
diff --git a/modules/pam_unix/pam_unix.8 b/modules/pam_unix/pam_unix.8
index d9cdea5a..07f8308f 100644
--- a/modules/pam_unix/pam_unix.8
+++ b/modules/pam_unix/pam_unix.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: pam_unix
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 09/03/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
+.\" Date: 05/07/2023
.\" Manual: Linux-PAM Manual
-.\" Source: Linux-PAM Manual
+.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "PAM_UNIX" "8" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "PAM_UNIX" "8" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -71,31 +71,31 @@ Remaining arguments, supported by others functions of this module, are silently
\fBsyslog\fR(3)\&.
.SH "OPTIONS"
.PP
-\fBdebug\fR
+debug
.RS 4
Turns on debugging via
\fBsyslog\fR(3)\&.
.RE
.PP
-\fBaudit\fR
+audit
.RS 4
A little more extreme than debug\&.
.RE
.PP
-\fBquiet\fR
+quiet
.RS 4
Turns off informational messages namely messages about session open and close via
\fBsyslog\fR(3)\&.
.RE
.PP
-\fBnullok\fR
+nullok
.RS 4
The default action of this module is to not permit the user access to a service if their official password is blank\&. The
\fBnullok\fR
argument overrides this default\&.
.RE
.PP
-\fBnullresetok\fR
+nullresetok
.RS 4
Allow users to authenticate with blank password if password reset is enforced even if
\fBnullok\fR
@@ -104,24 +104,24 @@ is not set\&. If password reset is not required and
is not set the authentication with blank password will be denied\&.
.RE
.PP
-\fBtry_first_pass\fR
+try_first_pass
.RS 4
Before prompting the user for their password, the module first tries the previous stacked module\*(Aqs password in case that satisfies this module as well\&.
.RE
.PP
-\fBuse_first_pass\fR
+use_first_pass
.RS 4
The argument
\fBuse_first_pass\fR
forces the module to use a previous stacked modules password and will never prompt the user \- if no password is available or the password is not appropriate, the user will be denied access\&.
.RE
.PP
-\fBnodelay\fR
+nodelay
.RS 4
This argument can be used to discourage the authentication component from requesting a delay should the authentication as a whole fail\&. The default action is for the module to request a delay\-on\-failure of the order of two second\&.
.RE
.PP
-\fBuse_authtok\fR
+use_authtok
.RS 4
When password changing enforce the module to set the new password to the one provided by a previously stacked
\fBpassword\fR
@@ -130,17 +130,17 @@ module (this is used in the example of the stacking of the
module documented below)\&.
.RE
.PP
-\fBauthtok_type=\fR\fB\fItype\fR\fR
+authtok_type=type
.RS 4
This argument can be used to modify the password prompt when changing passwords to include the type of the password\&. Empty by default\&.
.RE
.PP
-\fBnis\fR
+nis
.RS 4
NIS RPC is used for setting new passwords\&.
.RE
.PP
-\fBremember=\fR\fB\fIn\fR\fR
+remember=n
.RS 4
The last
\fIn\fR
@@ -151,75 +151,106 @@ in order to force password change history and keep the user from alternating bet
module should be used\&.
.RE
.PP
-\fBshadow\fR
+shadow
.RS 4
Try to maintain a shadow based system\&.
.RE
.PP
-\fBmd5\fR
+md5
.RS 4
When a user changes their password next, encrypt it with the MD5 algorithm\&.
.RE
.PP
-\fBbigcrypt\fR
+bigcrypt
.RS 4
When a user changes their password next, encrypt it with the DEC C2 algorithm\&.
.RE
.PP
-\fBsha256\fR
+sha256
.RS 4
When a user changes their password next, encrypt it with the SHA256 algorithm\&. The SHA256 algorithm must be supported by the
\fBcrypt\fR(3)
function\&.
.RE
.PP
-\fBsha512\fR
+sha512
.RS 4
When a user changes their password next, encrypt it with the SHA512 algorithm\&. The SHA512 algorithm must be supported by the
\fBcrypt\fR(3)
function\&.
.RE
.PP
-\fBblowfish\fR
+blowfish
.RS 4
When a user changes their password next, encrypt it with the blowfish algorithm\&. The blowfish algorithm must be supported by the
\fBcrypt\fR(3)
function\&.
.RE
.PP
-\fBgost_yescrypt\fR
+gost_yescrypt
.RS 4
When a user changes their password next, encrypt it with the gost\-yescrypt algorithm\&. The gost\-yescrypt algorithm must be supported by the
\fBcrypt\fR(3)
function\&.
.RE
.PP
-\fByescrypt\fR
+yescrypt
.RS 4
When a user changes their password next, encrypt it with the yescrypt algorithm\&. The yescrypt algorithm must be supported by the
\fBcrypt\fR(3)
function\&.
.RE
.PP
-\fBrounds=\fR\fB\fIn\fR\fR
+rounds=n
.RS 4
Set the optional number of rounds of the SHA256, SHA512, blowfish, gost\-yescrypt, and yescrypt password hashing algorithms to
\fIn\fR\&.
.RE
.PP
-\fBbroken_shadow\fR
+broken_shadow
.RS 4
Ignore errors reading shadow information for users in the account management module\&.
.RE
.PP
-\fBminlen=\fR\fB\fIn\fR\fR
+minlen=n
.RS 4
Set a minimum password length of
\fIn\fR
-characters\&. The max\&. for DES crypt based passwords are 8 characters\&.
+characters\&. The default value is 6\&. The maximum for DES crypt\-based passwords is 8 characters\&.
+.RE
+.PP
+\fBobscure\fR
+.RS 4
+Enable some extra checks on password strength\&. These checks are based on the "obscure" checks in the original shadow package\&. The behavior is similar to the pam_cracklib module, but for non\-dictionary\-based checks\&. The following checks are implemented:
+.PP
+\fBPalindrome\fR
+.RS 4
+Verifies that the new password is not a palindrome of (i\&.e\&., the reverse of) the previous one\&.
+.RE
+.PP
+\fBCase Change Only\fR
+.RS 4
+Verifies that the new password isn\*(Aqt the same as the old one with a change of case\&.
+.RE
+.PP
+\fBSimilar\fR
+.RS 4
+Verifies that the new password isn\*(Aqt too much like the previous one\&.
+.RE
+.PP
+\fBSimple\fR
+.RS 4
+Is the new password too simple? This is based on the length of the password and the number of different types of characters (alpha, numeric, etc\&.) used\&.
+.RE
+.PP
+\fBRotated\fR
+.RS 4
+Is the new password a rotated version of the old password? (E\&.g\&., "billy" and "illyb")
+.RE
+.sp
.RE
.PP
-\fBno_pass_expiry\fR
+no_pass_expiry
.RS 4
When set ignore password expiration as defined by the
\fIshadow\fR
@@ -279,7 +310,7 @@ session required pam_unix\&.so
\fBlogin.defs\fR(5),
\fBpam.conf\fR(5),
\fBpam.d\fR(5),
-\fBpam\fR(8)
+\fBpam\fR(7)
.SH "AUTHOR"
.PP
pam_unix was written by various people\&.
diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
index 9f9c8185..a025c0ef 100644
--- a/modules/pam_unix/pam_unix.8.xml
+++ b/modules/pam_unix/pam_unix.8.xml
@@ -1,30 +1,27 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
- "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-
-<refentry id="pam_unix">
+<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pam_unix">
<refmeta>
<refentrytitle>pam_unix</refentrytitle>
<manvolnum>8</manvolnum>
- <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ <refmiscinfo class="source">Linux-PAM</refmiscinfo>
+ <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo>
</refmeta>
- <refnamediv id="pam_unix-name">
+ <refnamediv xml:id="pam_unix-name">
<refname>pam_unix</refname>
<refpurpose>Module for traditional password authentication</refpurpose>
</refnamediv>
<refsynopsisdiv>
- <cmdsynopsis id="pam_unix-cmdsynopsis">
+ <cmdsynopsis xml:id="pam_unix-cmdsynopsis" sepchar=" ">
<command>pam_unix.so</command>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
...
</arg>
</cmdsynopsis>
</refsynopsisdiv>
- <refsect1 id="pam_unix-description">
+ <refsect1 xml:id="pam_unix-description">
<title>DESCRIPTION</title>
@@ -42,7 +39,7 @@
<emphasis>shadow</emphasis> elements: expire, last_change, max_change,
min_change, warn_change. In the case of the latter, it may offer advice
to the user on changing their password or, through the
- <emphasis remap='B'>PAM_AUTHTOKEN_REQD</emphasis> return, delay
+ <emphasis remap="B">PAM_AUTHTOKEN_REQD</emphasis> return, delay
giving service to the user until they have established a new password.
The entries listed above are documented in the <citerefentry>
<refentrytitle>shadow</refentrytitle><manvolnum>5</manvolnum>
@@ -89,7 +86,7 @@
<para>
The password component of this module performs the task of updating
the user's password. The default encryption hash is taken from the
- <emphasis remap='B'>ENCRYPT_METHOD</emphasis> variable from
+ <emphasis remap="B">ENCRYPT_METHOD</emphasis> variable from
<emphasis>/etc/login.defs</emphasis>
</para>
@@ -107,13 +104,13 @@
</para>
</refsect1>
- <refsect1 id="pam_unix-options">
+ <refsect1 xml:id="pam_unix-options">
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>
- <option>debug</option>
+ debug
</term>
<listitem>
<para>
@@ -127,7 +124,7 @@
<varlistentry>
<term>
- <option>audit</option>
+ audit
</term>
<listitem>
<para>
@@ -138,7 +135,7 @@
<varlistentry>
<term>
- <option>quiet</option>
+ quiet
</term>
<listitem>
<para>
@@ -153,7 +150,7 @@
<varlistentry>
<term>
- <option>nullok</option>
+ nullok
</term>
<listitem>
<para>
@@ -165,7 +162,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>nullresetok</option>
+ nullresetok
</term>
<listitem>
<para>
@@ -178,7 +175,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>try_first_pass</option>
+ try_first_pass
</term>
<listitem>
<para>
@@ -190,7 +187,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>use_first_pass</option>
+ use_first_pass
</term>
<listitem>
<para>
@@ -203,7 +200,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>nodelay</option>
+ nodelay
</term>
<listitem>
<para>
@@ -216,7 +213,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>use_authtok</option>
+ use_authtok
</term>
<listitem>
<para>
@@ -230,7 +227,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>authtok_type=<replaceable>type</replaceable></option>
+ authtok_type=type
</term>
<listitem>
<para>
@@ -242,7 +239,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>nis</option>
+ nis
</term>
<listitem>
<para>
@@ -252,7 +249,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>remember=<replaceable>n</replaceable></option>
+ remember=n
</term>
<listitem>
<para>
@@ -269,7 +266,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>shadow</option>
+ shadow
</term>
<listitem>
<para>
@@ -279,7 +276,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>md5</option>
+ md5
</term>
<listitem>
<para>
@@ -290,7 +287,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>bigcrypt</option>
+ bigcrypt
</term>
<listitem>
<para>
@@ -301,7 +298,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>sha256</option>
+ sha256
</term>
<listitem>
<para>
@@ -315,7 +312,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>sha512</option>
+ sha512
</term>
<listitem>
<para>
@@ -329,7 +326,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>blowfish</option>
+ blowfish
</term>
<listitem>
<para>
@@ -343,7 +340,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>gost_yescrypt</option>
+ gost_yescrypt
</term>
<listitem>
<para>
@@ -357,7 +354,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>yescrypt</option>
+ yescrypt
</term>
<listitem>
<para>
@@ -371,7 +368,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>rounds=<replaceable>n</replaceable></option>
+ rounds=n
</term>
<listitem>
<para>
@@ -384,7 +381,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>broken_shadow</option>
+ broken_shadow
</term>
<listitem>
<para>
@@ -395,19 +392,92 @@
</varlistentry>
<varlistentry>
<term>
- <option>minlen=<replaceable>n</replaceable></option>
+ minlen=n
</term>
<listitem>
<para>
Set a minimum password length of <replaceable>n</replaceable>
- characters. The max. for DES crypt based passwords are 8
- characters.
+ characters. The default value is 6. The maximum for DES
+ crypt-based passwords is 8 characters.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>obscure</option>
+ </term>
+ <listitem>
+ <para>
+ Enable some extra checks on password strength. These checks
+ are based on the "obscure" checks in the original shadow
+ package. The behavior is similar to the pam_cracklib
+ module, but for non-dictionary-based checks. The following
+ checks are implemented:
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>Palindrome</option>
+ </term>
+ <listitem>
+ <para>
+ Verifies that the new password is not a palindrome
+ of (i.e., the reverse of) the previous one.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>Case Change Only</option>
+ </term>
+ <listitem>
+ <para>
+ Verifies that the new password isn't the same as the
+ old one with a change of case.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>Similar</option>
+ </term>
+ <listitem>
+ <para>
+ Verifies that the new password isn't too much like
+ the previous one.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>Simple</option>
+ </term>
+ <listitem>
+ <para>
+ Is the new password too simple? This is based on
+ the length of the password and the number of
+ different types of characters (alpha, numeric, etc.)
+ used.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>Rotated</option>
+ </term>
+ <listitem>
+ <para>
+ Is the new password a rotated version of the old
+ password? (E.g., "billy" and "illyb")
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
- <option>no_pass_expiry</option>
+ no_pass_expiry
</term>
<listitem>
<para>
@@ -418,9 +488,9 @@
meaning that other authentication source or method succeeded.
The example can be public key authentication in
<emphasis>sshd</emphasis>. The module will return
- <emphasis remap='B'>PAM_SUCCESS</emphasis> instead of eventual
- <emphasis remap='B'>PAM_NEW_AUTHTOK_REQD</emphasis> or
- <emphasis remap='B'>PAM_AUTHTOK_EXPIRED</emphasis>.
+ <emphasis remap="B">PAM_SUCCESS</emphasis> instead of eventual
+ <emphasis remap="B">PAM_NEW_AUTHTOK_REQD</emphasis> or
+ <emphasis remap="B">PAM_AUTHTOK_EXPIRED</emphasis>.
</para>
</listitem>
</varlistentry>
@@ -432,7 +502,7 @@
</para>
</refsect1>
- <refsect1 id="pam_unix-types">
+ <refsect1 xml:id="pam_unix-types">
<title>MODULE TYPES PROVIDED</title>
<para>
All module types (<option>account</option>, <option>auth</option>,
@@ -440,7 +510,7 @@
</para>
</refsect1>
- <refsect1 id='pam_unix-return_values'>
+ <refsect1 xml:id="pam_unix-return_values">
<title>RETURN VALUES</title>
<variablelist>
<varlistentry>
@@ -454,7 +524,7 @@
</variablelist>
</refsect1>
- <refsect1 id='pam_unix-examples'>
+ <refsect1 xml:id="pam_unix-examples">
<title>EXAMPLES</title>
<para>
An example usage for <filename>/etc/pam.d/login</filename>
@@ -473,7 +543,7 @@ session required pam_unix.so
</para>
</refsect1>
- <refsect1 id='pam_unix-see_also'>
+ <refsect1 xml:id="pam_unix-see_also">
<title>SEE ALSO</title>
<para>
<citerefentry>
@@ -486,16 +556,16 @@ session required pam_unix.so
<refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
<citerefentry>
- <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ <refentrytitle>pam</refentrytitle><manvolnum>7</manvolnum>
</citerefentry>
</para>
</refsect1>
- <refsect1 id='pam_unix-author'>
+ <refsect1 xml:id="pam_unix-author">
<title>AUTHOR</title>
<para>
pam_unix was written by various people.
</para>
</refsect1>
-</refentry>
+</refentry> \ No newline at end of file
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index a20e919e..652f3c5a 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -66,35 +66,29 @@
#include <security/pam_ext.h>
#include <security/pam_modutil.h>
+#include "pam_inline.h"
#include "pam_cc_compat.h"
#include "md5.h"
#include "support.h"
#include "passverify.h"
#include "bigcrypt.h"
-#if (HAVE_YP_GET_DEFAULT_DOMAIN || HAVE_GETDOMAINNAME) && HAVE_YP_MASTER
-# define HAVE_NIS
-#endif
-
#ifdef HAVE_NIS
# include <rpc/rpc.h>
-
-# if HAVE_RPCSVC_YP_PROT_H
-# include <rpcsvc/yp_prot.h>
-# endif
-
-# if HAVE_RPCSVC_YPCLNT_H
-# include <rpcsvc/ypclnt.h>
-# endif
+# include <rpcsvc/yp_prot.h>
+# include <rpcsvc/ypclnt.h>
# include "yppasswd.h"
-# if !HAVE_DECL_GETRPCPORT &&!HAVE_RPCB_GETADDR
+# if !defined(HAVE_DECL_GETRPCPORT) &&!defined(HAVE_RPCB_GETADDR)
extern int getrpcport(const char *host, unsigned long prognum,
unsigned long versnum, unsigned int proto);
# endif /* GNU libc 2.1 */
#endif
+extern const char *obscure_msg(const char *, const char *, const struct passwd *,
+ unsigned int);
+
/*
How it works:
Gets in username (has to be done) from the calling program
@@ -593,6 +587,11 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
return retval;
}
}
+ if (!remark && pass_old != NULL) { /* only check if we don't already have a failure */
+ struct passwd *pwd;
+ pwd = pam_modutil_getpwnam(pamh, user);
+ remark = (char *)obscure_msg(pass_old,pass_new,pwd,ctrl); /* do obscure checks */
+ }
}
if (remark) {
_make_remark(pamh, ctrl, PAM_ERROR_MSG, remark);
@@ -608,7 +607,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
int retval;
int remember = -1;
int rounds = 0;
- int pass_min_len = 0;
+ int pass_min_len = 6;
/* <DO NOT free() THESE> */
const char *user;
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index f2474a5b..7ff8bf07 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -96,7 +96,7 @@ PAMH_ARG_DECL(int verify_pwd_hash,
} else if (*hash != '$' && hash_len >= 13) {
pp = bigcrypt(p, hash);
if (pp && hash_len == 13 && strlen(pp) > hash_len) {
- _pam_overwrite(pp + hash_len);
+ pam_overwrite_string(pp + hash_len);
}
} else {
/*
@@ -147,7 +147,7 @@ PAMH_ARG_DECL(int verify_pwd_hash,
if (cdata != NULL) {
cdata->initialized = 0;
pp = x_strdup(crypt_r(p, hash, cdata));
- memset(cdata, '\0', sizeof(*cdata));
+ pam_overwrite_object(cdata);
free(cdata);
}
#else
@@ -334,7 +334,7 @@ PAMH_ARG_DECL(int check_shadow_expiry,
#define PW_TMPFILE "/etc/npasswd"
#define SH_TMPFILE "/etc/nshadow"
-#define OPW_TMPFILE "/etc/security/nopasswd"
+#define OPW_TMPFILE SCONFIGDIR "/nopasswd"
/*
* i64c - convert an integer to a radix 64 character
@@ -427,7 +427,7 @@ PAMH_ARG_DECL(char * create_password_hash,
#else
char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
#endif
- char *sp;
+ char *sp, *ret;
#ifdef HAVE_CRYPT_R
struct crypt_data *cdata = NULL;
#endif
@@ -456,7 +456,7 @@ PAMH_ARG_DECL(char * create_password_hash,
password = tmppass;
}
hashed = bigcrypt(password, salt);
- memset(tmppass, '\0', sizeof(tmppass));
+ pam_overwrite_array(tmppass);
password = NULL;
return hashed;
}
@@ -494,18 +494,21 @@ PAMH_ARG_DECL(char * create_password_hash,
on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
if(sp) {
- memset(sp, '\0', strlen(sp));
+ pam_overwrite_string(sp);
}
#ifdef HAVE_CRYPT_R
+ pam_overwrite_object(cdata);
free(cdata);
#endif
return NULL;
}
- sp = x_strdup(sp);
+ ret = strdup(sp);
+ pam_overwrite_string(sp);
#ifdef HAVE_CRYPT_R
+ pam_overwrite_object(cdata);
free(cdata);
#endif
- return sp;
+ return ret;
}
#ifdef WITH_SELINUX
@@ -801,7 +804,7 @@ PAMH_ARG_DECL(int unix_update_passwd,
struct passwd *tmpent = NULL;
struct stat st;
FILE *pwfile, *opwfile;
- int err = 1;
+ int err = 1, found = 0;
int oldmask;
#ifdef WITH_SELINUX
char *prev_context_raw = NULL;
@@ -872,6 +875,7 @@ PAMH_ARG_DECL(int unix_update_passwd,
tmpent->pw_passwd = assigned_passwd.charp;
err = 0;
+ found = 1;
}
if (putpwent(tmpent, pwfile)) {
D(("error writing entry to password file: %m"));
@@ -914,7 +918,7 @@ done:
return PAM_SUCCESS;
} else {
unlink(PW_TMPFILE);
- return PAM_AUTHTOK_ERR;
+ return found ? PAM_AUTHTOK_ERR : PAM_USER_UNKNOWN;
}
}
@@ -1090,7 +1094,7 @@ helper_verify_password(const char *name, const char *p, int nullok)
}
if (hash) {
- _pam_overwrite(hash);
+ pam_overwrite_string(hash);
_pam_drop(hash);
}
diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
index c07037d2..463ef185 100644
--- a/modules/pam_unix/passverify.h
+++ b/modules/pam_unix/passverify.h
@@ -8,7 +8,7 @@
#define PAM_UNIX_RUN_HELPER PAM_CRED_INSUFFICIENT
-#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
+#define OLD_PASSWORDS_FILE SCONFIGDIR "/opasswd"
int
is_pwd_shadowed(const struct passwd *pwd);
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index 27ca7127..043273d2 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -19,7 +19,7 @@
#include <ctype.h>
#include <syslog.h>
#include <sys/resource.h>
-#ifdef HAVE_RPCSVC_YPCLNT_H
+#ifdef HAVE_NIS
#include <rpcsvc/ypclnt.h>
#endif
@@ -805,7 +805,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
cleanup:
- memset(pw, 0, sizeof(pw)); /* clear memory of the password */
+ pam_overwrite_array(pw); /* clear memory of the password */
if (data_name)
_pam_delete(data_name);
if (salt)
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index 19754dc1..9c065c5c 100644
--- 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.
@@ -101,60 +102,64 @@ typedef struct {
#define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */
#define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */
#define UNIX_NULLRESETOK 33 /* allow empty password if password reset is enforced */
+#define UNIX_OBSCURE_CHECKS 34 /* enable obscure checks on passwords */
+#define UNIX_NULLOK_SECURE 35 /* deprecated alias for nullok */
/* -------------- */
-#define UNIX_CTRLS_ 34 /* number of ctrl arguments defined */
+#define UNIX_CTRLS_ 36 /* number of ctrl arguments defined */
#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl))
static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
{
-/* symbol token name ctrl mask ctrl *
- * --------------------------- -------------------- ------------------------- ---------------- */
-
-/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0},
-/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0},
-/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0},
-/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0},
-/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060ULL), 020, 0},
-/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060ULL), 040, 0},
-/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0},
-/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600ULL), 0200, 0},
-/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600ULL), 0400, 0},
-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
-/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
-/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
-/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
-/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1},
-/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0},
-/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0},
-/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0},
-/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0},
-/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1},
-/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0},
-/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0},
-/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0},
-/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0},
-/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1},
-/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1},
-/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0},
-/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1},
-/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0},
-/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0},
-/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0},
-/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1},
-/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1},
-/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1},
-/* UNIX_NULLRESETOK */ {"nullresetok", _ALL_ON_, 020000000000, 0},
+/* symbol token name ctrl mask ctrl *
+ * --------------------------- -------------------- ------------------------- ------------ */
+
+/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 0x1, 0},
+/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 0x2, 0},
+/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 0x4, 0},
+/* UNIX_AUDIT */ {"audit", _ALL_ON_, 0x8, 0},
+/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(0x30ULL), 0x10, 0},
+/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(0x30ULL), 0x20, 0},
+/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0x40, 0},
+/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0x180ULL), 0x80, 0},
+/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0x180ULL), 0x100, 0},
+/* UNIX__NONULL */ {NULL, _ALL_ON_, 0x200, 0},
+/* UNIX__QUIET */ {NULL, _ALL_ON_, 0x400, 0},
+/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 0x800, 0},
+/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 0x1000, 0},
+/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0x6EC22000ULL), 0x2000, 1},
+/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(0x200ULL), 0, 0},
+/* UNIX_DEBUG */ {"debug", _ALL_ON_, 0x4000, 0},
+/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0x8000, 0},
+/* UNIX_NIS */ {"nis", _ALL_ON_, 0x10000, 0},
+/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0x6EC22000ULL), 0x20000, 1},
+/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 0x40000, 0},
+/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 0x80000, 0},
+/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 0x100000, 0},
+/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 0x200000, 0},
+/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0x6EC22000ULL), 0x400000, 1},
+/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0x6EC22000ULL), 0x800000, 1},
+/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0x1000000, 0},
+/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0x6EC22000ULL), 0x2000000, 1},
+/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0x4000000, 0},
+/* UNIX_QUIET */ {"quiet", _ALL_ON_, 0x8000000, 0},
+/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 0x10000000, 0},
+/* UNIX_DES */ {"des", _ALL_ON_^(0x6EC22000ULL), 0, 1},
+/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(0x6EC22000ULL), 0x20000000, 1},
+/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(0x6EC22000ULL), 0x40000000, 1},
+/* UNIX_NULLRESETOK */ {"nullresetok", _ALL_ON_, 0x80000000, 0},
+/* UNIX_OBSCURE_CHECKS */ {"obscure", _ALL_ON_, 0x100000000, 0},
+/* UNIX_NULLOK_SECURE */ {"nullok_secure", _ALL_ON_^(0x200ULL), 0, 0},
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
/* use this to free strings. ESPECIALLY password strings */
-#define _pam_delete(xx) \
-{ \
- _pam_overwrite(xx); \
- _pam_drop(xx); \
+#define _pam_delete(xx) \
+{ \
+ pam_overwrite_string(xx); \
+ _pam_drop(xx); \
}
extern int _make_remark(pam_handle_t * pamh, unsigned long long ctrl,
diff --git a/modules/pam_unix/unix_chkpwd.8 b/modules/pam_unix/unix_chkpwd.8
index 93c95bd6..7c1963b3 100644
--- a/modules/pam_unix/unix_chkpwd.8
+++ b/modules/pam_unix/unix_chkpwd.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: unix_chkpwd
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 09/03/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
+.\" Date: 05/07/2023
.\" Manual: Linux-PAM Manual
-.\" Source: Linux-PAM Manual
+.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "UNIX_CHKPWD" "8" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "UNIX_CHKPWD" "8" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/modules/pam_unix/unix_chkpwd.8.xml b/modules/pam_unix/unix_chkpwd.8.xml
index a10dbe33..ca0fa109 100644
--- a/modules/pam_unix/unix_chkpwd.8.xml
+++ b/modules/pam_unix/unix_chkpwd.8.xml
@@ -1,30 +1,27 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
- "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-
-<refentry id="unix_chkpwd">
+<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="unix_chkpwd">
<refmeta>
<refentrytitle>unix_chkpwd</refentrytitle>
<manvolnum>8</manvolnum>
- <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ <refmiscinfo class="source">Linux-PAM</refmiscinfo>
+ <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo>
</refmeta>
- <refnamediv id="unix_chkpwd-name">
+ <refnamediv xml:id="unix_chkpwd-name">
<refname>unix_chkpwd</refname>
<refpurpose>Helper binary that verifies the password of the current user</refpurpose>
</refnamediv>
<refsynopsisdiv>
- <cmdsynopsis id="unix_chkpwd-cmdsynopsis">
+ <cmdsynopsis xml:id="unix_chkpwd-cmdsynopsis" sepchar=" ">
<command>unix_chkpwd</command>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
...
</arg>
</cmdsynopsis>
</refsynopsisdiv>
- <refsect1 id="unix_chkpwd-description">
+ <refsect1 xml:id="unix_chkpwd-description">
<title>DESCRIPTION</title>
@@ -48,7 +45,7 @@
</para>
</refsect1>
- <refsect1 id='unix_chkpwd-see_also'>
+ <refsect1 xml:id="unix_chkpwd-see_also">
<title>SEE ALSO</title>
<para>
<citerefentry>
@@ -57,11 +54,11 @@
</para>
</refsect1>
- <refsect1 id='unix_chkpwd-author'>
+ <refsect1 xml:id="unix_chkpwd-author">
<title>AUTHOR</title>
<para>
Written by Andrew Morgan and other various people.
</para>
</refsect1>
-</refentry>
+</refentry> \ No newline at end of file
diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c
index 3931bab2..5e7b571e 100644
--- a/modules/pam_unix/unix_chkpwd.c
+++ b/modules/pam_unix/unix_chkpwd.c
@@ -138,9 +138,10 @@ int main(int argc, char *argv[])
/* if the caller specifies the username, verify that user
matches it */
if (user == NULL || strcmp(user, argv[1])) {
+ gid_t gid = getgid();
user = argv[1];
/* no match -> permanently change to the real user and proceed */
- if (setuid(getuid()) != 0)
+ if (setresgid(gid, gid, gid) != 0 || setuid(getuid()) != 0)
return PAM_AUTH_ERR;
}
}
@@ -176,7 +177,7 @@ int main(int argc, char *argv[])
retval = helper_verify_password(user, pass, nullok);
- memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */
+ pam_overwrite_array(pass); /* 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 b1f5ac71..b3b7a28f 100644
--- a/modules/pam_unix/unix_update.8
+++ b/modules/pam_unix/unix_update.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: unix_update
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 09/03/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
+.\" Date: 05/07/2023
.\" Manual: Linux-PAM Manual
-.\" Source: Linux-PAM Manual
+.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "UNIX_UPDATE" "8" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "UNIX_UPDATE" "8" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/modules/pam_unix/unix_update.8.xml b/modules/pam_unix/unix_update.8.xml
index 6c7467b9..1a968652 100644
--- a/modules/pam_unix/unix_update.8.xml
+++ b/modules/pam_unix/unix_update.8.xml
@@ -1,30 +1,27 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
- "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-
-<refentry id="unix_update">
+<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="unix_update">
<refmeta>
<refentrytitle>unix_update</refentrytitle>
<manvolnum>8</manvolnum>
- <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ <refmiscinfo class="source">Linux-PAM</refmiscinfo>
+ <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo>
</refmeta>
- <refnamediv id="unix_update-name">
+ <refnamediv xml:id="unix_update-name">
<refname>unix_update</refname>
<refpurpose>Helper binary that updates the password of a given user</refpurpose>
</refnamediv>
<refsynopsisdiv>
- <cmdsynopsis id="unix_update-cmdsynopsis">
+ <cmdsynopsis xml:id="unix_update-cmdsynopsis" sepchar=" ">
<command>unix_update</command>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
...
</arg>
</cmdsynopsis>
</refsynopsisdiv>
- <refsect1 id="unix_update-description">
+ <refsect1 xml:id="unix_update-description">
<title>DESCRIPTION</title>
@@ -48,7 +45,7 @@
</para>
</refsect1>
- <refsect1 id='unix_update-see_also'>
+ <refsect1 xml:id="unix_update-see_also">
<title>SEE ALSO</title>
<para>
<citerefentry>
@@ -57,11 +54,11 @@
</para>
</refsect1>
- <refsect1 id='unix_update-author'>
+ <refsect1 xml:id="unix_update-author">
<title>AUTHOR</title>
<para>
Written by Tomas Mraz and other various people.
</para>
</refsect1>
-</refentry>
+</refentry> \ No newline at end of file
diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c
index 3559972b..49a70ff3 100644
--- a/modules/pam_unix/unix_update.c
+++ b/modules/pam_unix/unix_update.c
@@ -55,15 +55,18 @@ set_password(const char *forwho, const char *shadow, const char *remember)
if (npass != 2) { /* is it a valid password? */
if (npass == 1) {
helper_log_err(LOG_DEBUG, "no new password supplied");
- memset(pass, '\0', PAM_MAX_RESP_SIZE);
+ pam_overwrite_array(pass);
} else {
helper_log_err(LOG_DEBUG, "no valid passwords supplied");
}
return PAM_AUTHTOK_ERR;
}
- if (lock_pwdf() != PAM_SUCCESS)
+ if (lock_pwdf() != PAM_SUCCESS) {
+ pam_overwrite_array(pass);
+ pam_overwrite_array(towhat);
return PAM_AUTHTOK_LOCK_BUSY;
+ }
pwd = getpwnam(forwho);
@@ -98,8 +101,8 @@ set_password(const char *forwho, const char *shadow, const char *remember)
}
done:
- memset(pass, '\0', PAM_MAX_RESP_SIZE);
- memset(towhat, '\0', PAM_MAX_RESP_SIZE);
+ pam_overwrite_array(pass);
+ pam_overwrite_array(towhat);
unlock_pwdf();
diff --git a/modules/pam_unix/yppasswd.h b/modules/pam_unix/yppasswd.h
index 5f947071..dc686cd7 100644
--- a/modules/pam_unix/yppasswd.h
+++ b/modules/pam_unix/yppasswd.h
@@ -1,28 +1,20 @@
/*
- * yppasswdd
- * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@lst.de>
- *
- * This program is covered by the GNU General Public License, version 2
- * or later. It is provided in the hope that it is useful. However, the author
- * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details.
- *
- * This file was generated automatically by rpcgen from yppasswd.x, and
- * editied manually.
+ * Please do not edit this file.
+ * It was generated using rpcgen.
*/
-#ifndef _YPPASSWD_H_
-#define _YPPASSWD_H_
+#ifndef _YPPASSWD_H_RPCGEN
+#define _YPPASSWD_H_RPCGEN
-#define YPPASSWDPROG ((u_long)100009)
-#define YPPASSWDVERS ((u_long)1)
-#define YPPASSWDPROC_UPDATE ((u_long)1)
+#include <rpc/rpc.h>
-/*
- * The password struct passed by the update call. I renamed it to
- * xpasswd to avoid a type clash with the one defined in <pwd.h>.
- */
-#ifndef __sgi
-typedef struct xpasswd {
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct xpasswd {
char *pw_name;
char *pw_passwd;
int pw_uid;
@@ -30,22 +22,45 @@ typedef struct xpasswd {
char *pw_gecos;
char *pw_dir;
char *pw_shell;
-} xpasswd;
-
-#else
-#include <pwd.h>
+};
typedef struct xpasswd xpasswd;
-#endif
-/* The updated password information, plus the old password.
- */
-typedef struct yppasswd {
+struct yppasswd {
char *oldpass;
xpasswd newpw;
-} yppasswd;
+};
+typedef struct yppasswd yppasswd;
-/* XDR encoding/decoding routines */
-bool_t xdr_xpasswd(XDR * xdrs, xpasswd * objp);
-bool_t xdr_yppasswd(XDR * xdrs, yppasswd * objp);
+#define YPPASSWDPROG 100009
+#define YPPASSWDVERS 1
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define YPPASSWDPROC_UPDATE 1
+extern int * yppasswdproc_update_1(yppasswd *, CLIENT *);
+extern int * yppasswdproc_update_1_svc(yppasswd *, struct svc_req *);
+extern int yppasswdprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define YPPASSWDPROC_UPDATE 1
+extern int * yppasswdproc_update_1();
+extern int * yppasswdproc_update_1_svc();
+extern int yppasswdprog_1_freeresult ();
+#endif /* K&R C */
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern bool_t xdr_passwd (XDR *, xpasswd*);
+extern bool_t xdr_yppasswd (XDR *, yppasswd*);
+
+#else /* K&R C */
+extern bool_t xdr_passwd ();
+extern bool_t xdr_yppasswd ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
-#endif /* _YPPASSWD_H_ */
+#endif /* !_YPPASSWD_H_RPCGEN */
diff --git a/modules/pam_unix/yppasswd_xdr.c b/modules/pam_unix/yppasswd_xdr.c
index f2b86a56..0523d523 100644
--- a/modules/pam_unix/yppasswd_xdr.c
+++ b/modules/pam_unix/yppasswd_xdr.c
@@ -1,40 +1,36 @@
/*
- * yppasswdd
- * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@lst.de>
- *
- * This program is covered by the GNU General Public License, version 2
- * or later. It is provided in the hope that it is useful. However, the author
- * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details.
- *
- * This file was generated automatically by rpcgen from yppasswd.x, and
- * editied manually.
+ * Please do not edit this file.
+ * It was generated using rpcgen.
*/
-#include "config.h"
-
-#ifdef HAVE_RPC_RPC_H
-
-#include <rpc/rpc.h>
#include "yppasswd.h"
bool_t
-xdr_xpasswd(XDR * xdrs, xpasswd * objp)
+xdr_passwd (XDR *xdrs, xpasswd *objp)
{
- return xdr_string(xdrs, &objp->pw_name, ~0)
- && xdr_string(xdrs, &objp->pw_passwd, ~0)
- && xdr_int(xdrs, &objp->pw_uid)
- && xdr_int(xdrs, &objp->pw_gid)
- && xdr_string(xdrs, &objp->pw_gecos, ~0)
- && xdr_string(xdrs, &objp->pw_dir, ~0)
- && xdr_string(xdrs, &objp->pw_shell, ~0);
+ if (!xdr_string (xdrs, &objp->pw_name, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pw_passwd, ~0))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->pw_uid))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->pw_gid))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pw_gecos, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pw_dir, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pw_shell, ~0))
+ return FALSE;
+ return TRUE;
}
-
bool_t
-xdr_yppasswd(XDR * xdrs, yppasswd * objp)
+xdr_yppasswd (XDR *xdrs, yppasswd *objp)
{
- return xdr_string(xdrs, &objp->oldpass, ~0)
- && xdr_xpasswd(xdrs, &objp->newpw);
+ if (!xdr_string (xdrs, &objp->oldpass, ~0))
+ return FALSE;
+ if (!xdr_passwd (xdrs, &objp->newpw))
+ return FALSE;
+ return TRUE;
}
-
-#endif