https://man.liquidfiles.com
LiquidFiles Documentation

It seems that nothing gets security professionals more rallied up than the issue of setting a password policy.

LiquidFiles aims to have a "strong enough" default security policy and also the ability for you define your own policy in various complexities.

Default Password Policy

LiquidFiles uses a password scoring system for detecting strong passwords, the score is as follows:

  • Password longer than 7 characters +1 point
  • Password longer than 10 characters +1 point
  • Password longer than 14 characters +1 point
  • Password contains both upper and lower case characters +1 point
  • Password contains digits +1 point
  • Password contains any of the following characters: !,@,#,$,%,^,&,*,?,_,~,-,(,) +1 point

A password needs 3 points or more to be valid.

With this password scoring system, the longer you make your password, the less complex it needs to be, and the shorter, the more complex you need to make it.

The thinking behind this is that allows long wordy password like correcthorsebatterystaple which in fact are stronger than shorter and more complex passwords like Tr0ub4dor&3 as highlighted in this brilliant meme from XKCD.

Custom Password Policy

If you don't like the default password policy, you can create your own. LiquidFiles has two different password policy functions. The simplest way to change password policy is to define a Regular Expression that matches your desired password policy.

We offer a couple of examples below but cannot assist with requests on how to create a Regular Expression that matches your specific password policy requirements. For anything beyond the examples below, you are best off starting with a web search such as: https://duckduckgo.com/?q=regex+password+validation.

To change to your own password validation, please go to Admin → Settings on your LiquidFiles system and enter your password policy. Please note that entering your own password policy will disable the default one.

Regular Expression Password Complexity Examples:

  • ^[A-Za-z]\w{6,}[A-Za-z]$ — the password needs to start and end with a letter, and be minimum 8 characters in total.
  • ^(?!.*\s).{7,}$ — the password needs to be any 7+ characters, with no spaces.
  • ^\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*$ — the password can be of any length as long as it contains at least 1 number, at least 1 lower case letter, and at least 1 upper case letter.
  • ^.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$ — the password needs to be at least 10 characters, contain at least one one lower case letter, one upper case letter, one digit and one special character, special characters are: @#$%^&+=

As you can see, you can get very specific, and very creative. To make it easy to test, a password validation feature is available. You can enter a password that should match what you want it to, and then change the regular expression until it matches. Please see the video below for an example of working with the password validation:

Changing Password Description

When you have changed your password policy it is a good idea to also change the wording of your password policy. This is what gets displayed to your users when they are prompted to enter a password.

To change the wording of the password policy, please go to Admin → System → Locales, select your language and click "Edit". Since there's a lot of strings that can be changed, the easiest to find the password policy one is to search in the page for: "password complexity description" (without quotation marks).

As an example, here we've changed the password complexity description to match the first regular expression above:

Password Complexity Description Example

Advanced Password Policy

Sometimes it isn't possible to define your password policy with a simple regular expression and for those use cases LiquidFiles also provides the facility of checking the password complexity using a external script.

On the LiquidFiles system, if there's a executable script in /usr/local/bin/validate_password it will be executed instead of the default server side password validation. A couple of things to note:

  • The client side will still use the regular expression or default checking. We assume that you will be having a password policy that is too complex to write in regular expression so client side validation doesn't really work anyway, and it can still provide a first level check.
  • The server side validation will be replaced by your script. They won't be checked in parallel.
  • You will have access to the environment variables PASSWORD, EMAIL and GROUP so that you can have different policies for different users or different groups if you want. Please note that all environment variables will be escaped using the shell escape method as described here: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape.
  • The script needs to send an exit code of zero (0) for any valid password, and nonzero (1 for instance) for any invalid password. If you output any string, this will be added in the interface as the error message if the result is nonzero. The output string will be silently discarded if the password was valid.
  • We won't be able to help you write a script for you to match your policy. Please get a programmer involved if you don't know how to do this yourself.

Please have a look at the following as an example:

#!/bin/bash
#
# Installed as /usr/local/bin/validate_password
#
# Available environment variables:
#   $PASSWORD = the users password
#   $EMAIL = the users email
#   $GROUP = the users group they belong to, or will belong to
#
# Please note that then environment variables will be escaped 
# using the shellescape method as described here:
# http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape
#
# Exit codes:
# 0: Everything is ok
# 1: Password is not permitted
#
# The text output will be listed as the password error
#
if [[ $GROUP == "System Administrators" ]]; then
 echo "Sysadmins never select bad passwords"
 exit 0
elif [[ $PASSWORD == $EMAIL ]]; then
 echo "You can't use your email as password"
 exit 1
elif [[ $PASSWORD == "password" ]]; then
 echo "You got to be joking!"
 exit 1
elif [[ `echo $PASSWORD | /usr/sbin/cracklib-check | egrep "\: OK$" | wc -l` -eq 0 ]]; then
 echo $PASSWORD | /usr/sbin/cracklib-check | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
 exit 1
else
 echo "All good"
 exit 0
fi

This should obviously serve as an example of how to write the script, not as example of a good password policy. The script should be pretty self explanatory. And if we step through it step by step:

  • First check if the users group is "System Administrators" and if it is just permit the password (exit 0).
  • Check if the password is the same as the email address and don't permit it if it is.
  • Simple string checking if someone tries to use use the password "password".
  • The next example is probably the most interesting from a security perspective, where passwords are checked against the password database cracklib (http://cracklib.sourceforge.net), and if the password is not listed as OK, it will be blocked. The complex "awk" script simply removes the first word (the password in cleartext) from the output.
  • If nothing has blocked the password at this point, just allow it.

To test the password validation, the easiest is just to run some tests on the command line like:

[root@liquidfiles current]# env GROUP="System Administrators" EMAIL=a@x.com PASSWORD=password /usr/local/bin/validate_password; echo $?
Sysadmins never select bad passwords
0
[root@liquidfiles current]# env GROUP="x" EMAIL=a@x.com PASSWORD=a@x.com /usr/local/bin/validate_password; echo $?
You can't use your email as password
1
[root@liquidfiles current]# env GROUP="x" EMAIL=a@x.com PASSWORD=password /usr/local/bin/validate_password; echo $?
You got to be joking!
1
[root@liquidfiles current]# env GROUP="x" EMAIL=a@x.com PASSWORD=p@ssword /usr/local/bin/validate_password; echo $?
it is based on a dictionary word
1
[root@liquidfiles current]# env GROUP="x" EMAIL=a@x.com PASSWORD=r2mpelst1lstkin /usr/local/bin/validate_password; echo $?
All good
0

Every time you'll see a zero (0), the password would have been permitted. Every time you see a one (1), the password would have been blocked and the message would have been fed back to the user as the password error.

As you can see, you can now write as complex a policy as your company demands. If you want store user passwords (lets say you want to create a policy that users can't reuse the previous 5 passwords), the best way is to use a hash algorithm like SHA1 (in bash, you can run: echo $PASSWORD | sha1sum | awk '{print $1}' to get the password hash). You can then store the passwords somewhere in /var/data where the script will be able to write to, or possibly use something like a SQLite database to store the passwords. Please note that when the script executes, it's because the users password is about to be changed, if the script you write has an exit code of zero (0), it will be changed. The script is the final validation.

Even if the example here is written in bourne shell (sh), you can write in pretty much any language available on the system that you're familiar with. Such as bash, perl, ruby, python or c. Anything really that you can execute as in the example above and that can give exit codes of zero (0) or one (1) for valid/invalid passwords respectively.