460 lines
19 KiB
Diff
460 lines
19 KiB
Diff
From: Sam Hartman <hartmans@debian.org>
|
|
Date: Mon, 11 Sep 2023 14:00:42 -0600
|
|
Subject: pam_unix: obscure checks
|
|
|
|
* Bring in the obscure checks that used to live in shadow so we can still support them
|
|
---
|
|
modules/module-meson.build | 1 +
|
|
modules/pam_unix/obscure.c | 199 +++++++++++++++++++++++++++++++++++++
|
|
modules/pam_unix/pam_unix.8.xml | 75 +++++++++++++-
|
|
modules/pam_unix/pam_unix_passwd.c | 10 +-
|
|
modules/pam_unix/support.h | 79 ++++++++-------
|
|
5 files changed, 324 insertions(+), 40 deletions(-)
|
|
create mode 100644 modules/pam_unix/obscure.c
|
|
|
|
diff --git a/modules/module-meson.build b/modules/module-meson.build
|
|
index d55dad2..edf9d57 100644
|
|
--- a/modules/module-meson.build
|
|
+++ b/modules/module-meson.build
|
|
@@ -106,6 +106,7 @@ if module == 'pam_unix'
|
|
'pam_unix_auth.c',
|
|
'pam_unix_passwd.c',
|
|
'pam_unix_sess.c',
|
|
+ 'obscure.c',
|
|
'support.c',
|
|
'passverify.c',
|
|
'md5_good.c',
|
|
diff --git a/modules/pam_unix/obscure.c b/modules/pam_unix/obscure.c
|
|
new file mode 100644
|
|
index 0000000..9dbbe6e
|
|
--- /dev/null
|
|
+++ b/modules/pam_unix/obscure.c
|
|
@@ -0,0 +1,199 @@
|
|
+/*
|
|
+ * 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 "pam_i18n.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.xml b/modules/pam_unix/pam_unix.8.xml
|
|
index d2cd198..d02320b 100644
|
|
--- a/modules/pam_unix/pam_unix.8.xml
|
|
+++ b/modules/pam_unix/pam_unix.8.xml
|
|
@@ -402,6 +402,79 @@
|
|
</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>
|
|
no_pass_expiry
|
|
@@ -495,4 +568,4 @@ session required pam_unix.so
|
|
</para>
|
|
</refsect1>
|
|
|
|
-</refentry>
|
|
\ No newline at end of file
|
|
+</refentry>
|
|
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
|
|
index 4a3784a..ea941fe 100644
|
|
--- a/modules/pam_unix/pam_unix_passwd.c
|
|
+++ b/modules/pam_unix/pam_unix_passwd.c
|
|
@@ -87,6 +87,9 @@ extern int getrpcport(const char *host, unsigned long prognum,
|
|
# 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
|
|
@@ -588,6 +591,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);
|
|
@@ -603,7 +611,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;
|
|
struct passwd *pwd;
|
|
|
|
/* <DO NOT free() THESE> */
|
|
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
|
|
index e8f629d..425ff66 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 "pam_inline.h"
|
|
|
|
/*
|
|
* File to read value of ENCRYPT_METHOD from.
|
|
@@ -101,50 +102,52 @@ 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_CTRLS_ 34 /* number of ctrl arguments defined */
|
|
+#define UNIX_CTRLS_ 35 /* 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},
|
|
};
|
|
|
|
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
|