Linux gives you lots of ways to create complexity in passwords that include a lot more than just length, such as mixing upper- and lower-case letters with numerals and punctuation marks along with other restrictions. Credit: Thinkstock Deploying password-quality checking on your Debian-based Linux servers can help ensure that your users assign reasonably secure passwords to their accounts, but the settings themselves can be a bit misleading. For example, setting a minimum password length of 12 characters does not necessarily mean that all your users’ passwords will actually have 12 or more characters. Let’s stroll down Complexity Boulevard and see how the settings work and examine some that are worth considering. The files that contain the settings we’re going to look at will be: /etc/pam.d/common-password on Debian-base systems /etc/security/pwquality.conf on RedHat Complexity settings Here’s how it works. You can set a minimum password length to insure strength, but this might not work exactly as you’d expect. In fact, passwords with the most characters aren’t necessarily the most secure or easy to use and remember. In fact your users can set themselves up with shorter passwords that are just as secure if they incorporate certain restrictions and categories of characters that make them harder to crack and get credit for doing so. Here are complexity settings you can require in addition to length: uppercase characters lowercase characters digits other characters (e.g., punctuation marks) a mix of the above a restriction on the number of characters in any particular class (uppercase, lowercase, etc.) a restriction on how many times the same character can be used the number of characters that have to be different from those used in the previous password restrictions on password re-use The settings include: minlen = minimum password length minclass = the minimum number of character types that must be used (i.e., uppercase, lowercase, digits, other) maxrepeat = the maximum number of times a single character may be repeated maxclassrepeat = the maximum number of characters in a row that can be in the same class lcredit = maximum number of lowercase characters that will generate a credit ucredit = maximum number of uppercase characters that will generate a credit dcredit = maximum number of digits that will generate a credit ocredit = maximum number of other characters that will generate a credit difok = the minimum number of characters that must be different from the old password remember = the number of passwords that will be remembered by the system so that they cannot be used again gecoscheck = whether to check for the words from the passwd entry GECOS string of the user (enabled if the value is not 0) dictcheck = whether to check for the words from the cracklib dictionary (enabled if the value is not 0) usercheck = whether to check if the password contains the user name in some form (enabled if the value is not 0) enforcing = new password is rejected if it fails the check and the value is not 0 dictpath = path to the cracklib dictionaries. Default is to use the cracklib default. These settings on a Red Hat system might look like this. The credit settings mean your users will get credits for using a mix of character types that can reduce the password length requirement. $ grep “=” /etc/security/pwquality.conf # difok = 1 minlen = 12 dcredit = -1 ucredit = 1 lcredit = 1 ocredit = 1 # minclass = 0 # maxrepeat = 0 # maxclassrepeat = 0 # gecoscheck = 0 # dictcheck = 1 # usercheck = 1 # enforcing = 1 # dictpath = The same settings on a Debian system might look like this: $ grep ^password common-password password requisite pam_pwquality.so retry=3 minlen=12 difok=1 remember=3 lcredit=1 ucredit=1 ocredit=1 dcredit=-1 Note that, regardless of the value you set for minlen, passwords cannot have fewer than six characters. That is, even if you set minlen equal to 4 and give credit for many types of characters, passwords with fewer than six characters will be rejected. Getting credit for complexity The idea of “credits” (e.g., lcredit and ucredit) is very interesting. Basically, a shorter password might be acceptable if it’s more complex with respect to the mix of characters. As an example, a password like “hijlmqrazp” might pass a minlen=10 test. If dcredit is set to 2, on the other hand, the password “hijlmq99” would also pass. Why? Because you’d get two credits for the digits. So, eight characters plus credits is valued as highly as 10 characters without credits. If dcredit were set to 1, you would need an additional character. However, we can also grant credits for uppercase, lowercase, and non-alphanumeric characters like punctuation marks. Note, however, that you can only get credit for so many of the different characters. Maybe you will get credit for only one digit or two uppercase characters. Maybe you don’t get any credit for lowercase characters. It all depends on your settings. Mixing character classes One other setting that comes into play is the minclass setting, which determines how many different classes of characters must be used for a password to be acceptable. If minclass is set to 2, a password containing all lowercase, all uppercase, all digits, or all any other class of characters wouldn’t work. If set to 2, minclass would require you to use characters from two classes, like uppercase and lowercase, or lowercase and digits. With minclass set to 4, passwords would have to include all four types of characters–like “howzit2B?”–and, if we get credit for uppercase, digits or other characters, we’d be OK even with the minlen set to 12. You can also put a cap on the number of characters of any particular class. Set the maxclassrepeat setting to 4 and passwords cannot contain more than four lowercase, uppercase, digits, or other characters in succession. The meaning of negative values Setting any of the lcredit, ucredit, dcredit, or ocredit settings to a negative number means that you MUST have some of that type of character for a password to be acceptable. Setting dcredit to -1, for example, would mean that you have to include at least one digit. Other passward-strength checks Linux’s password-quality checking includes a number of other checks that help ensure that passwords are fairly secure. It can check to see if a password is a palindrome, like “racecar”, whether a new password is the same as the old password but with a change of case only, if the old and new passwords are too similar or rotations of each other, and whether a password contains the user’s name. (It’s getting to the point that it might actually be difficult to assign oneself a really poor password.) For example, if a user doesn’t meet all the specified criteria, a password changing attempt might look like this: $ passwd Changing password for shs. Current password: New password: BAD PASSWORD: The password is a palindrome New password: BAD PASSWORD: The password contains less than 1 uppercase letters New password: BAD PASSWORD: The password contains less than 1 non-alphanumeric characters passwd: Have exhausted maximum number of retries for service passwd: password unchanged Password quality testing If you change the settings in the top lines of the following Perl script, you will get a feel for the kind of passwords that will pass your quality tests. In this example, the minimum length for a password has been set to 12. One credit is given for lowercase and uppercase letters, but none for special characters (just to demonstrate the difference). In addition, a digit must be included (setting -1). #!/usr/bin/perl -w # — set your complexity preferences here — $minlen=12; $lcredit=1; $ucredit=1; $dcredit=-1; $ocredit=0; # — initialize the counters — $score=0; $lcase=0; $ucase=0; $digits=0; $other=0; # — set fail to false — $fail=0; # — check for argument — if ( $#ARGV print “argument expectedn”; exit; } else { $password=$ARGV[0]; } # — determine if any character settings are mandatory (if negative) if ($lcredit $lneeded=-1 * $lcredit; $lextra=$lneeded; } else { $lneeded=0; $lextra=$lcredit; } if ($ucredit $uneeded=-1 * $ucredit; $uextra=$uneeded; } else { $uneeded=0; $uextra=$ucredit; } if ($dcredit $dneeded=-1 * $dcredit; $dextra=$dneeded; } else { $dneeded=0; $dextra=$dcredit; } if ($ocredit $oneeded=-1 * $ocredit; $oextra=$oneeded; } else { $oneeded=0; $oextra=$ocredit; } $score=length($password); # 1 point for each character # — password MUST contain at least 6 characters if ($score print “password MUST contain at least 6 charactersn”; exit; } # — count the characters of each type — foreach $char (split //, $password) { if ($char =~ /d/) { $digits++; # digits } elsif ($char !~ /w/) { $other++; # special characters } elsif ($char eq lc($char)) { $lcase++; # lowercase } elsif ($char eq uc($char)) { $ucase++; # uppercase } else { print “Error: unrecognized character. Please fix this script!n”; } } if ($lcase print “password failure: need $lneeded lowercase character(s)n”; $fail=1; } if ($ucase print “password failure: need $uneeded uppercase character(s)n”; $fail=1; } if ($digits print “password failure: need $dneeded digit(s)n”; $fail=1; } if ($other print “password failure: need $oneeded special character(s)n”; $fail=1; } if ($fail > 0) { exit; } # — reduce credits to number allowed — if ($lcase > $lextra) { $lcase=$lextra; } if ($ucase > $uextra) { $ucase=$uextra; } if ($digits > $dextra) { $digits=$dextra; } if ($other > $oextra) { $other=$oextra; } print “$score + $lcase + $ucase + $digits + $othern”; $score=$score + $lcase + $ucase + $digits + $other; if ($score >= $minlen) { print “password passes with score of $scoren”; } else { print “password fails with score of $scoren”; } Notice that the password “2Good4me?” passes even though it’s only 9 characters long. This is because we got one credit each for the uppercase G, one for the use of lowercase letters and one for the digit. We’d have passed with a 13 if we had been given credit for the “?” as well. The “9 + 1 + 1 + 1 + 0” line displays the list of credits: $ pwquality 2Good4me? 9 + 1 + 1 + 1 + 0 password passes with score of 12 Password complexity and PAM Support for password complexity is provided through the pluggable authentication module (PAM). If you have a file named /etc/pam.d/system-auth on a RedHat system, look for lines that look like those shown below. $ grep password /etc/pam.d/system-auth password requisite pam_pwquality.so try_first_pass local_users_only password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok password sufficient pam_sss.so use_authtok password required pam_deny.so On Debian systems like Ubuntu, this command will show you whether PAM is installed and ready to be used: $ apt-cache policy *pam-pwquality* libpam-pwquality: Installed: 1.4.2-1build1 Candidate: 1.4.2-1build1 Version table: *** 1.4.2-1build1 500 500 http://us.archive.ubuntu.com/ubuntu focal/main amd64 Packages 100 /var/lib/dpkg/status If the response on your system shows “Installed: (none)”, you can install it with this command: $ sudo apt install libpam-pwquality Related content how-to Compressing files using the zip command on Linux The zip command lets you compress files to preserve them or back them up, and you can require a password to extract the contents of a zip file. By Sandra Henry-Stocker May 13, 2024 4 mins Linux opinion NSA, FBI warn of email spoofing threat Email spoofing is acknowledged by experts as a very credible threat. By Sandra Henry-Stocker May 13, 2024 3 mins Linux how-to The logic of && and || on Linux These AND and OR equivalents can be used in scripts to determine next actions. By Sandra Henry-Stocker May 02, 2024 4 mins Linux how-to Using the apropos command on Linux By Sandra Henry-Stocker Apr 24, 2024 3 mins Linux PODCASTS VIDEOS RESOURCES EVENTS NEWSLETTERS Newsletter Promo Module Test Description for newsletter promo module. Please enter a valid email address Subscribe