How to check ! $ & present in password variable in Shell script - bash

I am writing shell script which will validate entered password which should not accept ! $ & sign in password. I need to throw error messages. Kindly help me here.
Here problem occurring when I give password like yt!$&
It is not throwing me error messages
echo "enter password which do not include ! $ & sign"
read -s password
if [[ $password != *"&"* || $password != *"!"* || $password != *"$"* ]];
then
echo "Do not enter ! $ & in password" else
echo $password
fi

x!=a || x!=b || x!=c is equivalent to !(x==a && x==b && x==c).
This is only true when none of the three conditions match.
However, I guess you wish to fail if even a single condition matches.
For that you should use: !(x==a || x==b || x==c).
Or equivalently: x!=a && x!=b && x!=c
After that, it should be clear that you also need to invert the test.
You can combine the tests and shorten to:
if [[ $password == *[\&!$]* ]]; then
echo "Do not enter ! $ & in password"
else
echo $password
fi
(& has to be escaped.)

You just need to fix your condition:
if [[ $password == *"&"* || $password == *"!"* || $password == *"$"* ]]; then
echo "Do not enter ! $ & in password"
fi

Related

Authentication issue with bash script

It works ("klist -A" shows valid principal):
password="<some_pwd>"
user="karim"
department="JUS"
echo $password | kinit $user#$domain.GOV
Password for karim#JUS.GOV:
But with the script I got the error:
Enter Password :Password for karim#JUS.GOV: kinit: Password incorrect while getting initial credentials
*Password for karim#JUS.GOV: kinit: Password incorrect while getting initial credentials
*Password for karim#JUS.GOV: kinit: Password incorrect while getting initial credentials
Each password's letter typing leads to the above message.
Script:
#!/bin/bash
password=""
echo "Provide user: "
read user
echo "Provide department's name (JUS, FIN, MIL): "
read department
pass_var="Provide password:"
while IFS= read -p "$pass_var" -r -s -n letter
do
if [[ $letter == $'\0' ]]
then
break
fi
password=password+"$letter"
pass_var="*"
if [[ $department == JUS ]];then
echo $password | kinit $user#$department.GOV
fi
done
Also, if user specify the department as JUS, FIN or MIL then the kinit command should be executed with the correct set department. I tried something like that but it does not work:
if [[ $department == JUS || FIN || MIL ]];then
Just fixing obvious errors:
#!/bin/bash
password=""
read -p "Provide username: " user
read -p "Provide department's name (JUS, FIN, MIL): " department
pass_var="Provide password: "
while IFS= read -p "$pass_var" -r -s -n 1 letter
do
if [[ $letter == $'\0' ]]
then
break
fi
password="$password$letter"
pass_var="*"
done
echo
if [[ $department == JUS ]]
then
echo "$password" | kinit "$user#$department.GOV"
fi
You can use a case or bash's =~ to match departments:
# ...
if [[ $department =~ JUS|FIN|MIL ]]
then
echo ...
fi
# ...
case "$department" in
JUS|FIN|MIL) echo ... ;;
esac

My bash script verification code does not work

I am trying to write a program where the user can enter a username and password, then the code should check if the username and password are correct unfortunately whenever it checks no matter if the username/password is correct of not it will echo "Username Verified".
#!/bin/bash
echo "Username"
read username
echo "Password"
read password
sleep 1
correct_u=user
correct_p=pass
if [[ $username -eq $correct_u ]]
then
echo "Username Verified..."
else
echo "Username Incorect..."
fi
sleep 1
if [[ $correct_p -eq $password ]]
then
sleep 1
echo "Password Verified..."
else
echo "Password Incorect..."
fi
I have tired checking that all the variables work
Unless username and correct_u consist solely of digits, [[ $username -eq $correct_u ]] will always evaluate to true, since -eq forces the arguments to be numbers, and if there are no number, the arguments are treated as zero.
To do a string comparision, do
[[ $username == "$correct_u" ]]
Quoting the right-hand side is important here, to avoid that it is interpreted as glob-pattern, since == in general does a wildcard match.
You should use = instead of -eq when comparing strings in bash. = is used for string comparison while -eq is used for integer comparison:
#!/bin/bash
echo "Username"
read username
echo "Password"
read password
sleep 1
correct_u=user
correct_p=pass
if [[ "$username" = "$correct_u" ]]
then
echo "Username Verified..."
else
echo "Username Incorrect..."
fi
sleep 1
if [[ "$correct_p" = "$password" ]]
then
sleep 1
echo "Password Verified..."
else
echo "Password Incorrect..."
fi
Embedding your name & pw in cleartext in the file isn't ideal. The user ID must be able to read it to execute the commands in it; executable permissions won't help if you take away read.
Use that to your advantage. Set the user/group/world permissions appropriately. Then the user and password are entered at login...
You might want to combine methods from here and here, reading the right password securely from a vault file and comparing that to the one you read silently from the user.
But first, as already mentioned - fix your test.
$: [[ "one" -eq "two" ]] && echo same || echo no
same
$: [[ "one" == "two" ]] && echo same || echo no
no
$: [[ "one" == "one" ]] && echo same || echo no
same

How to run through password function twice with different variables?

I have a password function that I borrowed from How do I echo stars (*) when reading password with read?
I tried to adapt it so that I can run through the function twice to do a password confirmation and then evaluate the 2 passwords to determine if they match but I seem to be missing some basics of how bash works in this case.
I tried replacing PASSWORD with $1 but kept getting command not found errors
passWord() {
unset PASSWORD
unset CHARCOUNT
stty -echo
CHARCOUNT=0
while IFS= read -p "$PROMPT" -r -s -n 1 CHAR; do
# Enter - accept password
if [[ $CHAR == $'\0' ]] ; then
break
fi
# Backspace
if [[ $CHAR == $'\177' ]] ; then
if [ $CHARCOUNT -gt 0 ] ; then
CHARCOUNT=$((CHARCOUNT-1))
PROMPT=$'\b \b'
PASSWORD="${PASSWORD%?}"
else
PROMPT=''
fi
else
CHARCOUNT=$((CHARCOUNT+1))
PROMPT='*'
PASSWORD+="$CHAR"
fi
done
stty echo; echo
${1}=${PASSWORD}
}
echo -n "Enter the password > "
passWord passOne
echo -n "Please re-enter the password > "
passWord passTwo
if [[ $passOne == $passTwo ]]; then
PASSWORD=$passOne
else
echo "Passwords did not match, please try again."
fi
Update
Here is the script with the latest updates
#!/bin/bash
passWord() {
unset password
local prompt char
stty -echo
charcount=0
while IFS= read -p "$prompt" -r -s -n 1 CHAR; do
# Enter - accept password
if [[ $char == $'\0' ]] ; then
break
fi
# Backspace
if [[ $char == $'\177' ]] ; then
if [ $charcount -gt 0 ] ; then
charcount=$((CHARCOUNT-1))
prompt=$'\b \b'
password="${password%?}"
else
prompt=''
fi
else
charcount=$((charcount+1))
prompt='*'
password+="$char"
fi
done
stty echo; echo
}
echo -n "Enter the password > "
passWord
pass1=$password
echo -n "Please re-enter the password > "
passWord
pass2=$password
if [[ "$pass1" == "$pass2" ]]; then
PassWord=$pass1
else
echo "Passwords did not match, please try again."
fi
You are missing a declaration of your shell.
Please add a shebang as the first line:
#!/bin/bash
The assignment of variables (the line ${1}=${PASSWORD}) doesn't work.
One way to solve it (not recomended) is to add eval:
eval "${1}=${PASSWORD}" # don't use quite risky.
But as that makes any input a security issue, you should use some other line.
One solution is to use declare (bash 4.2+):
declare -g "${1}=${PASSWORD}"
The -g is required (required and available since bash 4.2) to change General variables (not local to the function).
Or use printf (since bash 3.1):
printf -v "${1}" '%s' "${PASSWORD}"
Other than that, you should add a local command for variables used inside the function to avoid conflicts with external variables and should add a PROMPT='' just before the loop to avoid the printing of an initial asterisk when calling the function a second time.
It should be said that using variables in CAPS should be avoided. Variables in CAPS denote environment variables, the rest of variables use lower case to avoid conflicts.

How to add predefined users to a specific group in linux/bash script

I have been trying to implement a code that makes a predefined user created, be put into a specific groups (first 5 in MyMembers, next 5 in MyGroup, and last 5 to MyMinions), but I always got lost in coding it.
So far this is my code in creating predefined user.
#!/bin/bash
#This script adds a user with a hidden password to your #system.
ans=yes
while [[ "$ans" = yes ]] ;
do
if [ $(id -u) -eq 0 ];
then
read -p "Enter username: " username
read -s -p "Enter password: " password
egrep "^$username" /etc/passwd >/dev/null
if [ $? -eq 0 ];
then
echo "$username already exists!"
exit 1
else
pass=$(perl -e 'print crypt ($ARGV[0], "password")' $password)
useradd -m -p $pass $username
[ $? -eq 0 ] && echo -e "\nUser has been added to your system!" || echo "\nFailed to add the user!"
fi
else
echo "Only root may add a user to the system"
exit 2
fi
echo -e "\nDo you still want to add more users?. \nType yes to continue adding. \nType yes or any key to exit"
read ans
done
exit

How to prompt for yes or no in bash? [duplicate]

This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 28 days ago.
How do I ask a yes/no type question in Bash?
I ask the question... echo "Do you like pie?"
And receive the answer... read pie
How do I do something if the answer is yes, or starts with y (so yes and yeah, etc, will work too).
I like to use the following function:
function yes_or_no {
while true; do
read -p "$* [y/n]: " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*) echo "Aborted" ; return 1 ;;
esac
done
}
So in your script you can use like this:
yes_or_no "$message" && do_something
In case the user presses any key other than [yYnN] it will repeat the message.
This works too:
read -e -p "Do you like pie? " choice
[[ "$choice" == [Yy]* ]] && echo "doing something" || echo "that was a no"
Pattern starting with Y or y will be taken as yes.
I like Jahid's oneliner. Here is a slight simplification of it:
[[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]]
Here are some tests:
$ [[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping
Continue? [y/N]> yes
Continuing
$ for test_string in y Y yes YES no ''; do echo "Test String: '$test_string'"; echo $test_string | [[ "$(read -e -p 'Continue? [y/N]>'; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping; done
Test String: 'y'
Continuing
Test String: 'Y'
Continuing
Test String: 'yes'
Continuing
Test String: 'YES'
Continuing
Test String: 'no'
Stopping
Test String: ''
Stopping
Update
In response to a comment, I'm going to add an adaptation to make this work in zsh.
Disclaimer
I would never write a shell script in zsh even though it is now my primary interactive shell. I still write all scripts in bash or sh. However, since you sometimes need to script modifications to your interactive shell (ex: source ~/dev/set_env), you might want to include prompting.
#! /usr/bin/env zsh
[[ "$(echo -n 'Continue? [y/N]> ' >&2; read; echo $REPLY)" == [Yy]* ]] \
&& echo Continuing \
|| echo Stopping
This works:
echo "Do you like pie?"
read pie
if [[ $pie == y* ]]; then
echo "You do! Awesome."
else
echo "I don't like it much, either."
fi
[[ $pie == y* ]] tests to see of the variable $pie starts with y.
Feel free to make this better if you'd like.
In contrast to the other answers this function gives you the possibility to set a default:
function askYesNo {
QUESTION=$1
DEFAULT=$2
if [ "$DEFAULT" = true ]; then
OPTIONS="[Y/n]"
DEFAULT="y"
else
OPTIONS="[y/N]"
DEFAULT="n"
fi
read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT
INPUT=${INPUT:-${DEFAULT}}
echo ${INPUT}
if [[ "$INPUT" =~ ^[yY]$ ]]; then
ANSWER=true
else
ANSWER=false
fi
}
askYesNo "Do it?" true
DOIT=$ANSWER
if [ "$DOIT" = true ]; then
< do some stuff >
fi
On the command line you would see
Do it? [Y/n] y
Here is a short function:
prompt(){ read -p "$1" a; return $(test $a = "y"); }
Usage (if the answer is y then do_something executed):
prompt "Do you want it?" && do_something
Usage with multiple commands:
prompt "Do you want it?" && {
do_something1
do_something2
}

Resources