Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 1 addition & 11 deletions etc/login.defs
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,6 @@ PASS_CHANGE_TRIES 5
#
PASS_ALWAYS_WARN yes

#
# Number of significant characters in the password for crypt().
# Default is 8, don't change unless your crypt() is better.
# Only used for DES encryption algorithm.
#
#PASS_MAX_LEN 8

#
# Require password before chfn(1)/chsh(1) can make any changes.
#
Expand All @@ -302,18 +295,15 @@ CHFN_RESTRICT rwh

#
# Only works if compiled with ENCRYPTMETHOD_SELECT defined:
# If set to MD5, MD5-based algorithm will be used for encrypting password
# If set to SHA256, SHA256-based algorithm will be used for encrypting password
# If set to SHA512, SHA512-based algorithm will be used for encrypting password
# If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password
# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password
# If set to DES, DES-based algorithm will be used for encrypting password (default)
# MD5 and DES should not be used for new hashes, see crypt(5) for recommendations.
#
# Note: if you use PAM, it is recommended to use a value consistent with
# the PAM modules configuration.
#
#ENCRYPT_METHOD DES
#ENCRYPT_METHOD SHA512

#
# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
Expand Down
10 changes: 1 addition & 9 deletions lib/chkhash.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ is_valid_hash(const char *hash)
return true;

// Minimum hash length
if (strlen(hash) < 13)
if (strlen(hash) < 48)
return false;

// Yescrypt: $y$ + algorithm parameters + $ + salt + $ + 43-char hash
Expand All @@ -69,14 +69,6 @@ is_valid_hash(const char *hash)
if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash))
return true;

// MD5: $1$ + salt + $ + 22-char hash
if (match_regex("^\\$1\\$[^$:\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash))
return true;

// DES: exactly 13 characters from [A-Za-z0-9./]
if (match_regex("^[./A-Za-z0-9]{13}$", hash))
return true;

// Not a valid hash
return false;
}
1 change: 0 additions & 1 deletion lib/getdef.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ struct itemdef {
{"OBSCURE_CHECKS_ENAB", NULL}, \
{"PASS_ALWAYS_WARN", NULL}, \
{"PASS_CHANGE_TRIES", NULL}, \
{"PASS_MAX_LEN", NULL}, \
{"PASS_MIN_LEN", NULL}, \
{"PORTTIME_CHECKS_ENAB", NULL}, \
{"QUOTAS_ENAB", NULL}, \
Expand Down
93 changes: 8 additions & 85 deletions lib/obscure.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@


#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

Expand All @@ -26,10 +27,6 @@
#include "string/strdup/strdup.h"


#if WITH_LIBBSD == 0
#include "freezero.h"
#endif /* WITH_LIBBSD */

/*
* can't be a palindrome - like `R A D A R' or `M A D A M'
*/
Expand Down Expand Up @@ -59,7 +56,7 @@ static bool similar (/*@notnull@*/const char *old, /*@notnull@*/const char *new)

/*
* XXX - sometimes this fails when changing from a simple password
* to a really long one (MD5). For now, I just return success if
* to a really long one. For now, I just return success if
* the new password is long enough. Please feel free to suggest
* something better... --marekm
*/
Expand Down Expand Up @@ -115,19 +112,8 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
/*@notnull@*/const char *old,
/*@notnull@*/const char *new)
{
int maxlen, minlen;
size_t oldlen, newlen;
char *new1, *old1;
const char *msg;

oldlen = strlen (old);
newlen = strlen (new);

obscure_get_range(&minlen, &maxlen);

if (newlen < (size_t) minlen) {
if (strlen(new) < pass_min_len())
return _("too short");
}

/*
* Remaining checks are optional.
Expand All @@ -136,39 +122,7 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
return NULL;
}

msg = password_check(old, new);
if (NULL != msg) {
return msg;
}

if (maxlen == -1) {
return NULL;
}

/* 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 ( (oldlen <= (size_t) maxlen)
&& (newlen <= (size_t) maxlen)) {
return NULL;
}

new1 = xstrdup (new);
old1 = xstrdup (old);
if (newlen > (size_t) maxlen)
stpcpy(&new1[maxlen], "");
if (oldlen > (size_t) maxlen)
stpcpy(&old1[maxlen], "");

msg = password_check(old1, new1);

freezero (new1, newlen);
freezero (old1, oldlen);

return msg;
return password_check(old, new);
}

/*
Expand All @@ -191,43 +145,12 @@ obscure(const char *old, const char *new)
return true;
}

/*
* obscure_get_range - retrieve min and max password lengths
*
* Returns minimum and maximum allowed lengths of a password
* to pass obscure checks.
*/
void
obscure_get_range(int *minlen, int *maxlen)
size_t
pass_min_len(void)
{
int val;
const char *method;
int val;

/* Minimum length is 0, even if -1 is configured. */
val = getdef_num("PASS_MIN_LEN", 0);
*minlen = val == -1 ? 0 : val;

/* Maximum password length check is optional. */
*maxlen = -1;

if (!getdef_bool("OBSCURE_CHECKS_ENAB")) {
return;
}

method = getdef_str ("ENCRYPT_METHOD");
if (NULL != method) {
if ( streq(method, "MD5")
|| streq(method, "SHA256")
|| streq(method, "SHA512")
#ifdef USE_BCRYPT
|| streq(method, "BCRYPT")
#endif
#ifdef USE_YESCRYPT
|| streq(method, "YESCRYPT")
#endif
) {
return;
}
}
*maxlen = getdef_num ("PASS_MAX_LEN", 8);
return val == -1 ? 0 : val;
}
2 changes: 1 addition & 1 deletion lib/prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ extern int do_pam_passwd_non_interactive (const char *pam_service,

/* obscure.c */
extern bool obscure (const char *, const char *);
extern void obscure_get_range(int *, int *);
extern size_t pass_min_len(void);

/* pam_pass.c */
#ifdef USE_PAM
Expand Down
40 changes: 10 additions & 30 deletions lib/salt.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@
#define Y_COST_MAX 11
#endif

/* Fixed salt len for md5crypt. */
#define MD5_CRYPT_SALT_SIZE 8

/* Generate salt of size salt_size. */
#define MAX_SALT_SIZE 44
#define MIN_SALT_SIZE 8
Expand Down Expand Up @@ -355,12 +352,13 @@ static /*@observer@*/const char *gensalt (size_t salt_size)

bzero(result, GENSALT_SETTING_SIZE);

method = meth ?: getdef_str("ENCRYPT_METHOD") ?: "DES";
method = meth ?: getdef_str("ENCRYPT_METHOD") ?: "SHA512";

if (streq(method, "MD5")) {
MAGNUM(result, '1');
salt_len = MD5_CRYPT_SALT_SIZE;
rounds = 0;
if (streq(method, "SHA256")) {
MAGNUM(result, '5');
salt_len = SHA_CRYPT_SALT_SIZE;
rounds = SHA_get_salt_rounds (arg);
SHA_salt_rounds_to_buf (result, rounds);
#ifdef USE_BCRYPT
} else if (streq(method, "BCRYPT")) {
BCRYPTMAGNUM(result);
Expand All @@ -375,39 +373,21 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
rounds = YESCRYPT_get_salt_cost (arg);
YESCRYPT_salt_cost_to_buf (result, rounds);
#endif /* USE_YESCRYPT */
} else if (streq(method, "SHA256")) {
MAGNUM(result, '5');
salt_len = SHA_CRYPT_SALT_SIZE;
rounds = SHA_get_salt_rounds (arg);
SHA_salt_rounds_to_buf (result, rounds);
} else if (streq(method, "SHA512")) {
sha512:
MAGNUM(result, '6');
salt_len = SHA_CRYPT_SALT_SIZE;
rounds = SHA_get_salt_rounds (arg);
SHA_salt_rounds_to_buf (result, rounds);
} else if (!streq(method, "DES")) {
} else {
fprintf (log_get_logfd(),
_("Invalid ENCRYPT_METHOD value: '%s'.\n"
"Defaulting to DES.\n"),
"Defaulting to SHA512.\n"),
method);
salt_len = MAX_SALT_SIZE;
rounds = 0;
bzero(result, GENSALT_SETTING_SIZE);
goto sha512;
}

#if USE_XCRYPT_GENSALT
/*
* Prepare DES setting for crypt_gensalt(), if result
* has not been filled with anything previously.
*/
if (streq(result, "")) {
/* Avoid -Wunused-but-set-variable. */
salt_len = GENSALT_SETTING_SIZE - 1;
rounds = 0;
memset(result, '.', salt_len);
stpcpy(&result[salt_len], "");
}

char *retval = crypt_gensalt (result, rounds, NULL, 0);

/* Should not happen, but... */
Expand Down
2 changes: 1 addition & 1 deletion lib/valid.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
/*
* valid - compare encrypted passwords
*
* Valid() compares the DES encrypted password from the password file
* Valid() compares the hashed password from the password file
* against the password which the user has entered after it has been
* encrypted using the same salt as the original. Entries which do
* not have a password file entry have a NULL pw_name field and this
Expand Down
2 changes: 1 addition & 1 deletion man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ login_defs_v = \
PASS_ALWAYS_WARN.xml \
PASS_CHANGE_TRIES.xml \
PASS_MAX_DAYS.xml \
PASS_MAX_LEN.xml \
PASS_MIN_LEN.xml \
PASS_MIN_DAYS.xml \
PASS_WARN_AGE.xml \
PORTTIME_CHECKS_ENAB.xml \
Expand Down
2 changes: 0 additions & 2 deletions man/chgpasswd.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@
<para>
The available methods are <phrase condition="bcrypt">
<replaceable>BCRYPT</replaceable>,</phrase>
<replaceable>DES</replaceable>,
<replaceable>MD5</replaceable>,
<replaceable>SHA256</replaceable>,
<replaceable>SHA512</replaceable>,
<phrase condition="yescrypt">
Expand Down
2 changes: 0 additions & 2 deletions man/chpasswd.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@
<para>
The available methods are <phrase condition="bcrypt">
<replaceable>BCRYPT</replaceable>,</phrase>
<replaceable>DES</replaceable>,
<replaceable>MD5</replaceable>,
<replaceable>SHA256</replaceable>,
<replaceable>SHA512</replaceable>,
<phrase condition="yescrypt">
Expand Down
4 changes: 1 addition & 3 deletions man/login.defs.d/ENCRYPT_METHOD.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@
<para>
It can take one of these values: <phrase condition="bcrypt">
<replaceable>BCRYPT</replaceable>,</phrase>
<replaceable>DES</replaceable> (default),
<replaceable>MD5</replaceable>,
<replaceable>SHA256</replaceable>,
<replaceable>SHA512</replaceable>,
<phrase condition="yescrypt">
<replaceable>YESCRYPT</replaceable></phrase>.
MD5 and DES should not be used for new hashes, see
See
<refentrytitle>crypt</refentrytitle><manvolnum>5</manvolnum>
for recommendations.
</para>
Expand Down
34 changes: 0 additions & 34 deletions man/login.defs.d/PASS_MAX_LEN.xml

This file was deleted.

12 changes: 12 additions & 0 deletions man/login.defs.d/PASS_MIN_LEN.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!--
SPDX-FileCopyrightText: 2025, Alejandro Colomar <alx@kernel.org>
SPDX-License-Identifier: BSD-3-Clause
-->
<varlistentry condition="no_pam">
<term><option>PASS_MIN_LEN</option> (number)</term>
<listitem>
<para>
Minimum allowed length of a password.
</para>
</listitem>
</varlistentry>
2 changes: 1 addition & 1 deletion man/newusers.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@
<listitem>
<para>Use the specified method to encrypt the passwords.</para>
<para>
The available methods are DES, MD5, NONE, and SHA256 or SHA512
The available methods are NONE, and SHA256 or SHA512
if your libc support these methods.
</para>
</listitem>
Expand Down
Loading
Loading