Operating System‎ > ‎Linux‎ > ‎Linux Shell Script‎ > ‎

Lab 7-8 Shell Script to lock a user account


Lab 7-8 Simulate the steps that happen internally in the system when system admin locks a user account

Lab7-8 Script Requirement


Lab 7-8 Shell Script Solution

** Module 7 **

#!/bin/bash
# Name: ABC, Lab7
# Module 7

# needed variable
userChoice=0
userID=""

# if incorrect argument
if (( $# != 1 ))
then
echo "Incorrect argument - Usage: ./lab7 shadowinputfile"
exit 10 # assumption since not given in lab requirement
fi

testFileName=$1
#echo $testFileName

##############################
# Function 1: - Prompt and read in a user id - Check whether the id has whitespace in it. If it does, keep prompting for an id until you have an id without whitespace - When there is a valid id, check whether the id is in the shadow file. - Return a Boolean to indicate whether the id exists or not in the shadow file (note that this function doesn’t print the result to the user)
getID( )
{
local isIDFoundFrmFile=0 # return value from function
local boolAskID=1 # flag to ask userID without white space
while (( $boolAskID == 1 ))
do
echo -n "user id: "
read userID
regExp="[ ]"
if [[ $userID =~ $regExp ]]
then
echo "white space is not allowed, enter userid again"
else
boolAskID=0
#echo -$userID-
fi
done
# chech whether userID is in shadow file or not
if grep -q "^$userID:" "$testFileName"; then # -q to keep grep output silent, userid should be at the beginning of line and end with :
isIDFoundFrmFile=1
#echo "Found"
else
isIDFoundFrmFile=0
#echo "Not Found"
fi

return $isIDFoundFrmFile
}
##############################

##############################
# Function 2: 
lock( )
{
getID
#echo "Found ID: " $? # don't run OR you will loose value of ? variable
local isUserIDFound=$?
if (( isUserIDFound == 1 ))
then
local strFoundPwd=`grep "^$userID:" $testFileName | cut -f2 -d':'`
local strFoundIDandPwd=$userID:$strFoundPwd # Used id and pwd combination in case if two encrypted passwords match in a file
local strLockedIDandPwd=$userID:*$strFoundPwd
echo $strFoundIDandPwd
echo $strLockedIDandPwd
#cat $testFileName | sed -e "s/$strFoundIDandPwd/$strLockedIDandPwd/g" >> $testFileName
sed -i -e "s/$strFoundIDandPwd/$strLockedIDandPwd/g" $testFileName # might work as an extra credit
echo $userID "account is Locked"
else
echo "User ID not found, try again."
fi
}
##############################

##############################
# Function 3: The display function - Call the getID function - If the getID function shows that the user id is not in the password file, print an error message and return to the loop in main
# - If the getID function shows that user id is in the password file, print all fields of the corresponding record,  with these extra conditions: oFor field 2: Instead of printing the encrypted password, which has little meaning, print the status of the password as P (usable password) or L (account is locked) o For field 3: The time since the last password change is epoch time, which means the time is expressed as the number of seconds since Jan 1, 1970. To make the time more user friendly, use the date command to convert from epoch time and print with the format: dd/mm/yyyy. To convert the $field3 string, use: date   -d  @$field3   +%FORMAT  where FORMAT is the format character(s) of the date command to produce the dd/mm/yyyy 
display( )
{
getID
#echo "Found ID: " $? # don't run OR you will loose value of ? variable
local isUserIDFound=$?
if (( isUserIDFound == 1 ))
then
#echo "Display Record"
local strFoundRecord=`grep "^$userID:" $testFileName`
local strGetField2=`echo $strFoundRecord | cut -f2 -d':'` # password
local strGetField3=`echo $strFoundRecord | cut -f3 -d':'` # datetime
local strGetRestOfFields=`echo $strFoundRecord | cut -f4-9 -d':'` # rest of the fields
echo $strGetField2
echo $strGetField3
echo $strGetRestOfFields
charPwd=-${strGetField2:0:1} # QUESTION: NOT SURE WHY BUT GETTING AN ISSUE WITH "*" CHAR - APPENDED "-" IN FRONT TO SOLVE TEMPORARYLY
#echo $charPwd
if [ $charPwd == "-*" ]
then
strGetField2="L"
else
strGetField2="P"
fi
strGetField3=$(date -d "@$strGetField3" +%m-%d-%Y) # converted epoch time to gived datetime format
displayOut=$userID:$strGetField2:$strGetField3:$strGetRestOfFields
echo ${displayOut//:/ } # QUESTION: HOW TO GET MORE THAN ONE SPACE
else
echo "User ID not found, try again."
fi
}
##############################

if [ ! -e $testFileName ]
then
echo "Test file is not exist"
exit 20 # assumption since not given in lab requirement
elif [ ! -f $testFileName ]
then
echo "Given argument is not a regular file"
exit 30
else
while (( userChoice != 3 ))
do
##############################
# Here Document (end token must be at the beginning of line and no space/tab)
cat << menu
1. lock user account
2. show user password status
3. quit
menu
##############################
echo -n "Your choice: "
read userChoice
if (( userChoice == 1 ))
then
#echo "1"
lock
elif (( userChoice == 2 ))
then
#echo "2"
display
elif (( userChoice == 3 ))
then
echo "3. Quit"
else
echo "Invalid Choice"
fi
done
fi



** Module 8 **


#!/bin/bash
# Name: ABC, Lab7-8
# Module 8

# needed variable
userChoice=0
userID=""
tmpShadowFileName=""
strPrevExistFile=""

# SIGINT handling function
intHandling()
{
#echo "SIGINT handling"
echo -n "Do you want to exit script without saving any changes [y/n]? "
local tmpUserChoice=""
read tmpUserChoice
if [ $tmpUserChoice == "y" ]
then
if [ ! -z $tmpShadowFileName ]
then
# no copy from temporary to original file this time
rm -f $tmpShadowFileName # removed temporary file
fi
exit
elif [ $tmpUserChoice == "n" ]
then
echo "Press Enter to continue"
else
echo "Invalid Choice. Press Enter to continue"
fi
}

trap '' TERM TSTP               # ignore SIGTERM and control-z
trap 'intHandling' INT # call handling function for control-c

##############################
# Function 1: - Prompt and read in a user id - Check whether the id has whitespace in it. If it does, keep prompting for an id until you have an id without whitespace - When there is a valid id, check whether the id is in the shadow file. - Return a Boolean to indicate whether the id exists or not in the shadow file (note that this function doesn.t print the result to the user)
getID( )
{
local isIDFoundFrmFile=0 # return value from function
local boolAskID=1 # flag to ask userID without white space
while (( $boolAskID == 1 ))
do
echo -n "user id: "
read userID
regExp="[ ]"
if [[ $userID =~ $regExp ]]
then
echo "white space is not allowed, enter userid again"
else
boolAskID=0
#echo -$userID-
fi
done
# chech whether userID is in shadow file or not
if grep -q "^$userID:" "$tmpShadowFileName"; then # -q to keep grep output silent, userid should be at the beginning of line and end with :
isIDFoundFrmFile=1
#echo "Found"
else
isIDFoundFrmFile=0
#echo "Not Found"
fi

return $isIDFoundFrmFile
}
##############################

##############################
# Function 2: 
lock( )
{
getID
#echo "Found ID: " $? # don't run OR you will loose value of ? variable
local isUserIDFound=$?
if (( isUserIDFound == 1 ))
then
#cat $tmpShadowFileName
local strFoundPwd=`grep "^$userID:" $tmpShadowFileName | cut -f2 -d':'`
local strFoundIDandPwd=$userID:$strFoundPwd # Used id and pwd combination in case if two encrypted passwords match in a file
local strLockedIDandPwd=$userID:*$strFoundPwd
#echo $strFoundIDandPwd
#echo $strLockedIDandPwd
local charPwd=-${strFoundPwd:0:1} # QUESTION: NOT SURE WHY BUT GETTING AN ISSUE WITH "*" CHAR - APPENDED "-" IN FRONT TO SOLVE TEMPORARYLY
#echo $charPwd
if [ $charPwd == "-*" ]
then
echo $userID "account is already locked"
else
#cat $tmpShadowFileName | sed -e "s/$strFoundIDandPwd/$strLockedIDandPwd/g" > $tmpShadowFileName
#sed -i -e "s/$strFoundIDandPwd/$strLockedIDandPwd/g" $tmpShadowFileName # Having an issue if few characters in pwd
#cat $tmpShadowFileName
#sed -i -e "s/$(echo $strFoundIDandPwd | sed -e 's/[]\/()$*.^|[]/\\&/g')/$(echo $strLockedIDandPwd | sed -e 's/[\/&]/\\&/g')/g" $tmpShadowFileName
# Extra Credit
sed -i -e "s/$(echo $strFoundIDandPwd | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g')/$(echo $strLockedIDandPwd | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g')/g" $tmpShadowFileName
echo $userID "account is Locked"
fi
else
echo "User ID not found, try again."
fi
}
##############################

##############################
# Function 3: The display function - Call the getID function - If the getID function shows that the user id is not in the password file, print an error message and return to the loop in main
# - If the getID function shows that user id is in the password file, print all fields of the corresponding record,  with these extra conditions: oFor field 2: Instead of printing the encrypted password, which has little meaning, print the status of the password as P (usable password) or L (account is locked) o For field 3: The time since the last password change is epoch time, which means the time is expressed as the number of seconds since Jan 1, 1970. To make the time more user friendly, use the date command to convert from epoch time and print with the format: dd/mm/yyyy. To convert the $field3 string, use: date   -d  @$field3   +%FORMAT  where FORMAT is the format character(s) of the date command to produce the dd/mm/yyyy 
display( )
{
getID
#echo "Found ID: " $? # don't run OR you will loose value of ? variable
local isUserIDFound=$?
if (( isUserIDFound == 1 ))
then
#echo "Display Record"
local strFoundRecord=`grep "^$userID:" $tmpShadowFileName`
local strGetField2=`echo $strFoundRecord | cut -f2 -d':'` # password
local strGetField3=`echo $strFoundRecord | cut -f3 -d':'` # datetime
local strGetRestOfFields=`echo $strFoundRecord | cut -f4-9 -d':'` # rest of the fields
#echo $strGetField2
#echo $strGetField3
#echo $strGetRestOfFields
local charPwd=-${strGetField2:0:1} # QUESTION: NOT SURE WHY BUT GETTING AN ISSUE WITH "*" CHAR - APPENDED "-" IN FRONT TO SOLVE TEMPORARYLY
#echo $charPwd
if [ $charPwd == "-*" ]
then
strGetField2="L"
else
strGetField2="P"
fi
strGetField3=$(date -d "@$strGetField3" +%m-%d-%Y) # converted epoch time to gived datetime format
displayOut=$userID:$strGetField2:$strGetField3:$strGetRestOfFields
echo ${displayOut//:/ } # QUESTION: HOW TO GET MORE THAN ONE SPACE
else
echo "User ID not found, try again."
fi
}
##############################
# Main Function #
# if incorrect argument
if (( $# != 1 ))
then
echo "Incorrect argument - Usage: ./lab7 shadowinputfile"
exit 10 # assumption since not given in lab requirement
fi

shadowFileName=$1
#echo $shadowFileName

if [ ! -e $shadowFileName ]
then
echo "Test file is not exist"
exit 20 # assumption since not given in lab requirement
elif [ ! -f $shadowFileName ]
then
echo "Given argument is not a regular file"
exit 30
else
# Ask user if newer version of shadow file exist when connection was dropped
strPrevExistFile=`ls -t *.Temp??* 2> /dev/null | head -1` | tr -d ' ' # sorted by time to get latest temporary file -- silent error by redirect error to /dev/null
#echo -$strPrevExistFile-
if [ ! -z $strPrevExistFile ]
then
echo -n "there is a newer shadow file, Do you want to use it? [y/n]: "
read isUsePrevFile
if [ $isUsePrevFile == "y" ]
then
echo "Use newer shadow file"
cp $strPrevExistFile $shadowFileName
rm -f $strPrevExistFile
elif [ $isUsePrevFile == "n" ]
then
echo "Discarded previous shadow file changes"
rm -f $isUsePrevFile # remove all old files using rm -f *.Temp?* # Temp file name format: *.Temp[PID]
else
echo "Invalid Choice" # To Do: Need to handle this, need loop and only go further if valid choice
fi
fi

# Create temporary file and use it throught the session
tmpShadowFileName=$shadowFileName.Temp$$
#echo $tmpShadowFileName
cp $shadowFileName $tmpShadowFileName

while (( userChoice != 3 ))
do
##############################
# Here Document (end token must be at the beginning of line and no space/tab)
cat << menu
1. lock user account
2. show user password status
3. quit
menu
##############################
echo -n "Your choice: "
read userChoice
if (( userChoice == 1 ))
then
#echo "1"
lock # Function Call: lock()
elif (( userChoice == 2 ))
then
#echo "2"
display # Function Call: display()
elif (( userChoice == 3 ))
then
echo "3. Quit"
# Lab8 modification
cp $tmpShadowFileName $shadowFileName # copy temporary file to original file before quit
rm -f $tmpShadowFileName # removed temporary file

# reset to default signal handling
trap  TSTP
trap  TERM
else
echo "Invalid Choice"
fi
done
fi




Comments