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

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