Hello everyone, I’m planning to solve the problems in the Advanced Bash-Scripting Guide, say like one problem per week. Why am I doing this?
1. The problems there are very interesting.
2. Working in windows all the time, I feel I’m losing my shell scripting abilities. This will keep me updated.
The problem we are going to solve this week is “Testing Passwords”. The problem statement is as follows.
Write a script to check and validate passwords. The object is to flag “weak” or easily guessed password candidates.
A trial password will be input to the script as a command-line parameter. To be considered acceptable, a password must meet the following minimum qualifications:
1. Minimum length of 8 characters
2. Must contain at least one numeric character
3. Must contain at least one of the following non-alphabetic characters: @, #, $, %, &, *, +, -, =
Optional:
Do a dictionary check on every sequence of at least four consecutive alphabetic characters in the password under test. This will eliminate passwords containing embedded “words” found in a standard dictionary.
Enable the script to check all the passwords on your system. These probably do not reside in /etc/passwd.
The command I’m planning to use for this is grep, with a few for loop constructs and string operations.
Let’s check the constraints one by one.
#Minimum length of 8 characters
if [ ${#password} -lt 8 ]
then
echo "$password: $weakString"
return
fi
#Must contain at least one numeric character
if [ `echo $password | grep -c -E "[0-9]+"` -eq 0 ]
then
echo "$password: $weakString"
return
fi
#Must contain at least one of the following non-alphabetic characters: @, #, $, %, &, *, +, -, =
if [ `echo $password | grep -c -E "[@#$%&*=+-]+"` -eq 0 ]
then
echo "$password: $weakString"
return
fi
#Do a dictionary check on every sequence of at least four consecutive alphabetic characters in the password under test. This will eliminate passwords containing embedded "words" found in a standard dictionary.
for((i=4;i<=${#password};i++))
do
for((j=0;j<=${#password}-$i;j++))
do
if [ `grep -c -E "^${password:$j:$i}$" dict.txt` -gt 0 ]
then
echo "$password: $weakString"
return
fi
done
done
That’s about it, we have checked all the constraints. Now, we will combine all the checks in one function and then we will pass all the command line parameters to this function one by one.
You can take a look at the final script here.
Can you make it any better or reduce the code size? Feel free to add it in the comments section.
Pingback: Tweets that mention sp2hari@weblog… » Blog Archive » Advanced Bash Scripting – Part 1 -- Topsy.com
Pingback: Siddharth
Nice Series 🙂 Something I can relate to 😛
Regarding this script, well you can check for special character check all in one go ! And also, should the dict checking be case sensitive or insensitive ?
~S
He he 🙂
Yeah, probably I could’ve added the special character check with the numeric character check, but wanted to keep the code clean. And not sure about the case sensitive check. Nothing was mentioned in the problem. I have coded it as case sensitive checking.
Nice post .. looking up to further posts 🙂 🙂
One small suggestion for the last part check .. instead of having the inner loop on index and outer loop on the length , if they are swapped, the complexity will reduce in the worst case.. For each index, we start checking for lengths from 4 to ${#password} instead of checking all 4 letter substrings and all 5 letter and so on till ${#password} …