diff options
Diffstat (limited to 'modules/pam_unix')
-rw-r--r-- | modules/pam_unix/Makefile.am | 11 | ||||
-rw-r--r-- | modules/pam_unix/Makefile.in | 33 | ||||
-rw-r--r-- | modules/pam_unix/README | 36 | ||||
-rw-r--r-- | modules/pam_unix/README.xml | 32 | ||||
-rw-r--r-- | modules/pam_unix/bigcrypt.c | 13 | ||||
-rw-r--r-- | modules/pam_unix/md5.c | 29 | ||||
-rw-r--r-- | modules/pam_unix/md5_crypt.c | 4 | ||||
-rw-r--r-- | modules/pam_unix/obscure.c | 198 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix.8 | 91 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix.8.xml | 168 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix_passwd.c | 27 | ||||
-rw-r--r-- | modules/pam_unix/passverify.c | 26 | ||||
-rw-r--r-- | modules/pam_unix/passverify.h | 2 | ||||
-rw-r--r-- | modules/pam_unix/support.c | 4 | ||||
-rw-r--r-- | modules/pam_unix/support.h | 89 | ||||
-rw-r--r-- | modules/pam_unix/unix_chkpwd.8 | 8 | ||||
-rw-r--r-- | modules/pam_unix/unix_chkpwd.8.xml | 23 | ||||
-rw-r--r-- | modules/pam_unix/unix_chkpwd.c | 5 | ||||
-rw-r--r-- | modules/pam_unix/unix_update.8 | 8 | ||||
-rw-r--r-- | modules/pam_unix/unix_update.8.xml | 23 | ||||
-rw-r--r-- | modules/pam_unix/unix_update.c | 11 | ||||
-rw-r--r-- | modules/pam_unix/yppasswd.h | 81 | ||||
-rw-r--r-- | modules/pam_unix/yppasswd_xdr.c | 52 |
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 |