diff --git a/AUTHORS b/AUTHORS index 6f5b94a..dbcc2c1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,3 +11,4 @@ Nikhil Lanjewar Sahil Muthoo Sahil Aggarwal Saager Mhatre +Iain Douglas diff --git a/tests/p_passwd/0_install_passwd b/tests/p_passwd/0_install_passwd new file mode 100755 index 0000000..62e1bba --- /dev/null +++ b/tests/p_passwd/0_install_passwd @@ -0,0 +1,6 @@ +#!/bin/bash +# Author: Iain Douglas + +# Ensure packages we use are installed +t_Log "Running $0 installing required packages" +t_InstallPackage passwd expect diff --git a/tests/p_passwd/10_passwd_basic_test b/tests/p_passwd/10_passwd_basic_test new file mode 100755 index 0000000..d33545b --- /dev/null +++ b/tests/p_passwd/10_passwd_basic_test @@ -0,0 +1,8 @@ +#!/bin/bash +#Author: Iain Douglas +# +t_Log "Running $0 - Basic passwd functionality checks" + +userdel -rf passtest; useradd passtest &>/dev/null +echo passtest | passwd --stdin passtest &>/dev/null +t_CheckExitStatus $? diff --git a/tests/p_passwd/20_root_tests b/tests/p_passwd/20_root_tests new file mode 100755 index 0000000..c2cb9a1 --- /dev/null +++ b/tests/p_passwd/20_root_tests @@ -0,0 +1,122 @@ +#!/bin/bash +# Author: Iain Douglas +# + +function ExitFail +{ + t_Log "FAIL" + exit $FAIL +} +# +# Test the command line options for passwd that are restricted to root. +# + +t_Log "Running $0 - Check root only actions" +t_Log "Create test user passtest" +userdel -rf passtest; useradd passtest && echo passtest | passwd --stdin passtest &>/dev/null +t_CheckExitStatus $? + +# Check that passwd -l locks the password - the field in /etc/shadow has +# a ! prepended +t_Log "Check account can be locked" +passwd -l passtest &>/dev/null + +if [ $? -eq "0" ] +then + getent shadow passtest | cut -f2 -d: | grep '^!' &>/dev/null + t_CheckExitStatus $? +else + ExitFail +fi + +# Check that passwd -u will unlock the account - removes the ! from the +# start of the password field in /etc/shadow +t_Log "Check account can be unlocked" +passwd -u passtest &>/dev/null + +if [ $? -eq "0" ] +then + getent shadow passtest | cut -f2 -d: | grep -v '^!' &>/dev/null + t_CheckExitStatus $? +else + ExitFail +fi + +# Check that passwd -e expires an account. Field 3 of /etc/shadow is set to 0 +t_Log "Check password can be expired" +passwd -e passtest &>/dev/null + +if [ $? -eq "0" ] +then + getent shadow passtest | cut -f3 -d: | grep '^0' &>/dev/null + t_CheckExitStatus $? + echo passtest | passwd --stdin passtest &>/dev/null +else + ExitFail +fi + +# Check that passwd -n, -x, -w -i set the mindays, maxdays, warndays and +# inactive fields (4-7) in /etc/shadow +t_Log "Check password aging data can be set" +passwd -n 11 -x 22 -w 33 -i 44 passtest &>/dev/null + +if [ $? -eq "0" ] +then + getent shadow passtest | cut -f4-7 -d: | grep '^11:22:33:44' &>/dev/null + t_CheckExitStatus $? +else + ExitFail +fi + +# Check that passwd -d deletes the password - the field in /etc/shadow is +# cleared +t_Log "Check password can be deleted" +passwd -d passtest &>/dev/null + +if [ $? -eq "0" ] +then + password=$(getent shadow passtest | cut -f2 -d:) + if [ -z "${password}" ] + then + t_Log "PASS" + else + ExitFail + fi +else + ExitFail +fi + +# Passwd won't, without being forced, unlock an account with a blank password +# so check this is the case. +t_Log "Check blank password cannot be unlocked" +passwd -l passtest &>/dev/null +passwd -u passtest &>/dev/null + +if [ $? -ne "0" ] +then + t_Log PASS +else + ExitFail +fi + +# Force passwd to unlock an account with a blank password passwd -uf. +t_Log "Check blank password can be force unlocked" +passwd -uf passtest &>/dev/null +t_CheckExitStatus $? + +# Check the output of passwd -S at this point it should be +# passtest NP YYYY-MM-DD 11 22 33 44 (Empty password.) +# It's possible that this will run on a different side of midnight to earlier +# commands so if checking the output for today fails check yesterday too +t_Log "Check output of passwd -S" + +expected="passtest NP "$(date +'%F')" 11 22 33 44 (Empty password.)" +passwd -S passtest | grep "$expected" &>/dev/null +if [ $? -eq "0" ] +then + t_Log "PASS" +else + expected="passtest NP "$(date +'%F' -d yesterday)" 11 22 33 44 (Empty password.)" + passwd -S passtest | grep "$expected" &>/dev/null + t_CheckExitStatus $? +fi diff --git a/tests/p_passwd/30_user_tests b/tests/p_passwd/30_user_tests new file mode 100755 index 0000000..b9714ec --- /dev/null +++ b/tests/p_passwd/30_user_tests @@ -0,0 +1,82 @@ +#!/bin/bash +# Author: Iain Douglas +# + +function ExitFail { + t_Log "FAIL" + exit $FAIL +} + +t_Log "Runing $0 - normal user password tests" +# Check that the passtest user cannot use the root only options + +t_Log "Checking a normal user cannot use root options" + +su passtest -c "passwd -l passtest" &>/dev/null && ExitFail +su passtest -c "passwd -u passtest" &>/dev/null && ExitFail +su passtest -c "passwd -e passtest" &>/dev/null && ExitFail +su passtest -c "passwd -n 10 passtest" &>/dev/null && ExitFail +su passtest -d "passwd -d passtest" &>/dev/null && ExitFail +su passtest -d "passwd -S passtest" &>/dev/null && ExitFail +t_Log "Pass" + +# Check the user can change their own password. Reset it to passtest and +# turn off min change days before trying. Password becomes ano24ther + +t_Log "Test user can change own password" + +echo "passtest" | passwd --stdin passtest &>/dev/null +passwd -n 0 passtest &>/dev/null +./tests/p_passwd/_user_password.expect &>/dev/null +t_CheckExitStatus $? + +# Check that sending the wrong current password fails we send passtest + +t_Log "Check sending incorrect current password fails" +./tests/p_passwd/_user_password.expect &>/dev/null + +if [ $? -eq "3" ] +then + t_Log "PASS" +else + ExitFail +fi + +# Check that user cannot immediately change password if minimum password +# lifeftime is enabled. + +t_Log "Testing Minimum password lifetine is enforced" +echo "passtest" | passwd --stdin passtest &>/dev/null +passwd -n 1 passtest &>/dev/null +./tests/p_passwd/_user_password.expect &>/dev/null + +if [ $? -eq "2" ] +then + t_Log "PASS" +else + ExitFail +fi + +# Password complexity tests +echo "passtest" | passwd --stdin passtest &>/dev/null +passwd -n 0 passtest &>/dev/null + +# Check very short password is rejected (single letter) +t_Log "Test very short password is rejected (1 character)" +./tests/p_passwd/_password_complexity.expect a &>/dev/null +t_CheckExitStatus $? + +# Check a short password is rejected (4 chars) +t_Log "Test short password is rejected (4 charaters)" +./tests/p_passwd/_password_complexity.expect athe &>/dev/null +t_CheckExitStatus $? + +# Check password is rejected with insufficient complexity +t_Log "Test insufficiently complex password is rejected" +./tests/p_passwd/_password_complexity.expect betabeta &>/dev/null +t_CheckExitStatus $? + +# Check palindromic password is rejected +t_Log "Check palindromic password is rejected" +./tests/p_passwd/_password_complexity.expect qwe123321ewq &>/dev/null +t_CheckExitStatus $? diff --git a/tests/p_passwd/TODO b/tests/p_passwd/TODO new file mode 100644 index 0000000..b49d195 --- /dev/null +++ b/tests/p_passwd/TODO @@ -0,0 +1,3 @@ +# I don't understand what -k is supposed to do. +# Without changing the date and time I can't think of a way to test +# that -x -w and -i are working diff --git a/tests/p_passwd/_password_complexity.expect b/tests/p_passwd/_password_complexity.expect new file mode 100755 index 0000000..6b73c62 --- /dev/null +++ b/tests/p_passwd/_password_complexity.expect @@ -0,0 +1,22 @@ +#!/usr/bin/expect -f +# Author: Iain Douglas +# + +set testpassword [lindex $argv 0] +set timeout 10 +match_max 6000 + +spawn su passtest -c passwd +expect "UNIX password:" { send -- "passtest\r" } +expect { + "password:" { + send "$testpassword\r" + expect { + "BAD PASSWORD: it is WAY too short" { exit 0 } + "BAD PASSWORD: it is too short" { exit 0 } + "BAD PASSWORD: it does not contain enough DIFFERENT characters" { exit 0 } + "BAD PASSWORD: is a palindrome" { exit 0 } + } + } +} +exit 1 diff --git a/tests/p_passwd/_user_password.expect b/tests/p_passwd/_user_password.expect new file mode 100755 index 0000000..04a78c2 --- /dev/null +++ b/tests/p_passwd/_user_password.expect @@ -0,0 +1,24 @@ +#!/usr/bin/expect -f +# Author: Iain Douglas + +set timeout 10 +match_max 6000 +spawn su passtest -c passwd +expect "UNIX password:" { send -- "passtest\r" } +expect { + "You must wait longer to change your password" + { + exit 2 + } + "Authentication token manipulation error" + { + exit 3 + } + "password:" + { + send -- "ano24ther\r" + expect "*?password:*" + send -- "ano24ther\r" + expect eof + } + }