aboutsummaryrefslogtreecommitdiff
path: root/debian/patches-applied/007_modules_pam_unix
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-applied/007_modules_pam_unix')
-rw-r--r--debian/patches-applied/007_modules_pam_unix712
1 files changed, 712 insertions, 0 deletions
diff --git a/debian/patches-applied/007_modules_pam_unix b/debian/patches-applied/007_modules_pam_unix
new file mode 100644
index 00000000..a0c1857a
--- /dev/null
+++ b/debian/patches-applied/007_modules_pam_unix
@@ -0,0 +1,712 @@
+Index: pam.deb/modules/pam_unix/pam_unix_passwd.c
+===================================================================
+--- pam.deb.orig/modules/pam_unix/pam_unix_passwd.c
++++ pam.deb/modules/pam_unix/pam_unix_passwd.c
+@@ -87,6 +87,9 @@
+ unsigned long versnum, unsigned int proto);
+ #endif /* GNU libc 2.1 */
+
++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
+@@ -457,7 +460,8 @@
+ static int _pam_unix_approve_pass(pam_handle_t * pamh
+ ,unsigned int ctrl
+ ,const char *pass_old
+- ,const char *pass_new)
++ ,const char *pass_new,
++ int pass_min_len)
+ {
+ const void *user;
+ const char *remark = NULL;
+@@ -488,7 +492,7 @@
+ }
+ }
+ if (off(UNIX__IAMROOT, ctrl)) {
+- if (strlen(pass_new) < 6)
++ if (strlen(pass_new) < pass_min_len)
+ remark = _("You must choose a longer password");
+ D(("length check [%s]", remark));
+ if (on(UNIX_REMEMBER_PASSWD, ctrl)) {
+@@ -500,6 +504,11 @@
+ 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);
+@@ -516,6 +525,7 @@
+ int retval;
+ int remember = -1;
+ int rounds = -1;
++ int pass_min_len = 6;
+
+ /* <DO NOT free() THESE> */
+ const char *user;
+@@ -524,7 +534,8 @@
+
+ D(("called."));
+
+- ctrl = _set_ctrl(pamh, flags, &remember, &rounds, argc, argv);
++ ctrl = _set_ctrl(pamh, flags, &remember, &rounds, &pass_min_len,
++ argc, argv);
+
+ /*
+ * First get the name of a user
+@@ -724,7 +735,8 @@
+ if (*(const char *)pass_new == '\0') { /* "\0" password = NULL */
+ pass_new = NULL;
+ }
+- retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
++ retval = _pam_unix_approve_pass(pamh, ctrl, pass_old,
++ pass_new, pass_min_len);
+
+ if (retval != PAM_SUCCESS && off(UNIX_NOT_SET_PASS, ctrl)) {
+ pam_set_item(pamh, PAM_AUTHTOK, NULL);
+@@ -757,7 +769,8 @@
+ return retval;
+ }
+
+- retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
++ retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new,
++ pass_min_len);
+ if (retval != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_NOTICE,
+ "new password not acceptable 2");
+Index: pam.deb/modules/pam_unix/pam_unix_acct.c
+===================================================================
+--- pam.deb.orig/modules/pam_unix/pam_unix_acct.c
++++ pam.deb/modules/pam_unix/pam_unix_acct.c
+@@ -191,7 +191,7 @@
+
+ D(("called."));
+
+- ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
++ ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv);
+
+ retval = pam_get_item(pamh, PAM_USER, &void_uname);
+ uname = void_uname;
+Index: pam.deb/modules/pam_unix/support.c
+===================================================================
+--- pam.deb.orig/modules/pam_unix/support.c
++++ pam.deb/modules/pam_unix/support.c
+@@ -55,7 +55,7 @@
+ */
+
+ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
+- int argc, const char **argv)
++ int *pass_min_len, int argc, const char **argv)
+ {
+ unsigned int ctrl;
+
+@@ -81,6 +81,7 @@
+ D(("SILENT"));
+ set(UNIX__QUIET, ctrl);
+ }
++
+ /* now parse the arguments to this module */
+
+ while (argc-- > 0) {
+@@ -90,7 +91,8 @@
+
+ for (j = 0; j < UNIX_CTRLS_; ++j) {
+ if (unix_args[j].token
+- && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) {
++ && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token)))
++ {
+ break;
+ }
+ }
+@@ -102,15 +104,16 @@
+ ctrl &= unix_args[j].mask; /* for turning things off */
+ ctrl |= unix_args[j].flag; /* for turning things on */
+
+- if (remember != NULL) {
+- if (j == UNIX_REMEMBER_PASSWD) {
+- *remember = strtol(*argv + 9, NULL, 10);
+- if ((*remember == INT_MIN) || (*remember == INT_MAX))
+- *remember = -1;
+- if (*remember > 400)
+- *remember = 400;
+- }
+- }
++ /* special cases */
++ if (remember != NULL && j == UNIX_REMEMBER_PASSWD) {
++ *remember = strtol(*argv + 9, NULL, 10);
++ if ((*remember == INT_MIN) || (*remember == INT_MAX))
++ *remember = -1;
++ if (*remember > 400)
++ *remember = 400;
++ } else if (pass_min_len && j == UNIX_MIN_PASS_LEN) {
++ *pass_min_len = atoi(*argv + 4);
++ }
+ if (rounds != NULL && j == UNIX_ALGO_ROUNDS)
+ *rounds = strtol(*argv + 7, NULL, 10);
+ }
+@@ -118,6 +121,10 @@
+ ++argv; /* step to next argument */
+ }
+
++ if (off(UNIX_HASH_MASK,ctrl)
++ && pass_min_len && *pass_min_len > 8)
++ *pass_min_len = 8;
++
+ if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
+ D(("DISALLOW_NULL_AUTHTOK"));
+ set(UNIX__NONULL, ctrl);
+Index: pam.deb/modules/pam_unix/support.h
+===================================================================
+--- pam.deb.orig/modules/pam_unix/support.h
++++ pam.deb/modules/pam_unix/support.h
+@@ -89,41 +89,49 @@
+ #define UNIX_ALGO_ROUNDS 25 /* optional number of rounds for new
+ password hash algorithms */
+ #define UNIX_BLOWFISH_PASS 26 /* new password hashes will use blowfish */
++#define UNIX_MAX_PASS_LEN 27 /* internal, for compatibility only */
++#define UNIX_MIN_PASS_LEN 28 /* min length for password */
++#define UNIX_OBSCURE_CHECKS 29 /* enable obscure checks on passwords */
+ /* -------------- */
+-#define UNIX_CTRLS_ 27 /* number of ctrl arguments defined */
++#define UNIX_CTRLS_ 30 /* number of ctrl arguments defined */
++
++#define UNIX_HASH_MASK (UNIX_MD5_PASS|UNIX_BIGCRYPT|UNIX_SHA256_PASS|UNIX_SHA512_PASS|UNIX_BLOWFISH_PASS)
+
+ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
+ {
+ /* symbol token name ctrl mask ctrl *
+ * ----------------------- ------------------- --------------------- -------- */
+
+-/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01},
+-/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02},
+-/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04},
+-/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010},
+-/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020},
+-/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040},
+-/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0100},
+-/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200},
+-/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400},
+-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000},
+-/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000},
+-/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000},
+-/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000},
+-/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000},
+-/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0},
+-/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000},
+-/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000},
+-/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000},
+-/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000},
+-/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000},
+-/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000},
+-/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000},
+-/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000},
+-/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000},
+-/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000},
+-/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000},
+-/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000},
++/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 0x1},
++/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 0x2},
++/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 0x4},
++/* UNIX_AUDIT */ {"audit", _ALL_ON_, 0x8},
++/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(0x30), 0x10},
++/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(0x30), 0x20},
++/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0x40},
++/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0x180), 0x80},
++/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0x180), 0x100},
++/* UNIX__NONULL */ {NULL, _ALL_ON_, 0x200},
++/* UNIX__QUIET */ {NULL, _ALL_ON_, 0x400},
++/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 0x800},
++/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 0x1000},
++/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0x2C22000), 0x2000},
++/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(0x200), 0},
++/* UNIX_DEBUG */ {"debug", _ALL_ON_, 0x4000},
++/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0x8000},
++/* UNIX_NIS */ {"nis", _ALL_ON_, 0x10000},
++/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0x2C22000), 0x20000},
++/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 0x40000},
++/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 0x80000},
++/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 0x100000},
++/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 0x200000},
++/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0x2C22000), 0x400000},
++/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0x2C22000), 0x800000},
++/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0x1000000},
++/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0x2C22000),0x2000000},
++/* UNIX_MAX_PASS_LEN */ {"max=", _ALL_ON_, 0},
++/* UNIX_MIN_PASS_LEN */ {"min=", _ALL_ON_, 0x4000000},
++/* UNIX_OBSCURE_CHECKS */ {"obscure", _ALL_ON_, 0x8000000},
+ };
+
+ #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
+@@ -141,7 +149,7 @@
+ extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl
+ ,int type, const char *text);
+ extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int *rounds,
+- int argc, const char **argv);
++ int *pass_min_len, int argc, const char **argv);
+ extern int _unix_getpwnam (pam_handle_t *pamh,
+ const char *name, int files, int nis,
+ struct passwd **ret);
+Index: pam.deb/modules/pam_unix/pam_unix.8.xml
+===================================================================
+--- pam.deb.orig/modules/pam_unix/pam_unix.8.xml
++++ pam.deb/modules/pam_unix/pam_unix.8.xml
+@@ -326,6 +326,90 @@
+ </para>
+ </listitem>
+ </varlistentry>
++ <varlistentry>
++ <term>
++ <option>min=<replaceable>n</replaceable></option>
++ </term>
++ <listitem>
++ <para>
++ Set a minimum password length of <replaceable>n</replaceable>
++ characters. The default value is 6.
++ </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>
+ </variablelist>
+ <para>
+ Invalid arguments are logged with <citerefentry>
+Index: pam.deb/modules/pam_unix/obscure.c
+===================================================================
+--- /dev/null
++++ pam.deb/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 (on(UNIX_HASH_MASK,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;
++}
+Index: pam.deb/modules/pam_unix/Makefile.am
+===================================================================
+--- pam.deb.orig/modules/pam_unix/Makefile.am
++++ pam.deb/modules/pam_unix/Makefile.am
+@@ -41,7 +41,7 @@
+
+ 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 yppasswd_xdr.c md5_good.c md5_broken.c obscure.c
+
+ bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c
+ bigcrypt_CFLAGS = $(AM_CFLAGS)
+Index: pam.deb/modules/pam_unix/pam_unix_auth.c
+===================================================================
+--- pam.deb.orig/modules/pam_unix/pam_unix_auth.c
++++ pam.deb/modules/pam_unix/pam_unix_auth.c
+@@ -109,7 +109,7 @@
+
+ D(("called."));
+
+- ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
++ ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv);
+
+ /* Get a few bytes so we can pass our return value to
+ pam_sm_setcred(). */
+Index: pam.deb/modules/pam_unix/pam_unix_sess.c
+===================================================================
+--- pam.deb.orig/modules/pam_unix/pam_unix_sess.c
++++ pam.deb/modules/pam_unix/pam_unix_sess.c
+@@ -73,7 +73,7 @@
+
+ D(("called."));
+
+- ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
++ ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv);
+
+ retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
+ if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
+@@ -107,7 +107,7 @@
+
+ D(("called."));
+
+- ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
++ ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv);
+
+ retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
+ if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
+Index: pam.deb/modules/pam_unix/pam_unix.8
+===================================================================
+--- pam.deb.orig/modules/pam_unix/pam_unix.8
++++ pam.deb/modules/pam_unix/pam_unix.8
+@@ -166,13 +166,11 @@
+ .\" -----------------------------------------------------------------
+ .\" * MAIN CONTENT STARTS HERE *
+ .\" -----------------------------------------------------------------
+-.SH "Name"
++.SH "NAME"
+ pam_unix \- Module for traditional password authentication
+-.SH "Synopsis"
+-.fam C
++.SH "SYNOPSIS"
+ .HP \w'\fBpam_unix\&.so\fR\ 'u
+ \fBpam_unix\&.so\fR [\&.\&.\&.]
+-.fam
+ .SH "DESCRIPTION"
+ .PP
+ This is the standard Unix authentication module\&. It uses standard calls from the system\'s libraries to retrieve and set account information as well as authentication\&. Usually this is obtained from the /etc/passwd and the /etc/shadow file as well if shadow is enabled\&.
+@@ -264,7 +262,7 @@
+ The last
+ \fIn\fR
+ passwords for each user are saved in
+-\FC/etc/security/opasswd\F[]
++/etc/security/opasswd
+ in order to force password change history and keep the user from alternating between the same password too frequently\&.
+ .RE
+ .PP
+@@ -315,6 +313,44 @@
+ Ignore errors reading shadow information for users in the account management module\&.
+ .RE
+ .PP
++\fBmin=\fR\fB\fIn\fR\fR
++.RS 4
++Set a minimum password length of
++\fIn\fR
++characters\&. The default value is 6\&.
++.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\'t the same as the old one with a change of case\&.
++.RE
++.PP
++\fBSimilar\fR
++.RS 4
++Verifies that the new password isn\'t 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
+ Invalid arguments are logged with
+ \fBsyslog\fR(3)\&.
+ .SH "MODULE TYPES PROVIDED"
+@@ -333,21 +369,13 @@
+ .SH "EXAMPLES"
+ .PP
+ An example usage for
+-\FC/etc/pam\&.d/login\F[]
++/etc/pam\&.d/login
+ would be:
+ .sp
+ .if n \{\
+ .RS 4
+ .\}
+-.fam C
+-.ps -1
+ .nf
+-.if t \{\
+-.sp -1
+-.\}
+-.BB lightgray adjust-for-leading-newline
+-.sp -1
+-
+ # Authenticate the user
+ auth required pam_unix\&.so
+ # Ensure users account and password are still active
+@@ -358,13 +386,7 @@
+ password required pam_unix\&.so use_authtok nullok md5
+ session required pam_unix\&.so
+
+-.EB lightgray adjust-for-leading-newline
+-.if t \{\
+-.sp 1
+-.\}
+ .fi
+-.fam
+-.ps +1
+ .if n \{\
+ .RE
+ .\}