Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I am trying to create a very simple login console for a script that I have, this is just for fun to see if it works.

Basically what I thought would be possible is this.

I will read in the file $password_file and the file $username_file if there is a certain pattern. Let's say I put in both files "bryan" on the first line (or whatever line). Now I want to put this piece of code before the script continues to its basic functions.

echo "Welcome"
echo "Ur username is:"
read username
echo "Ur password is:"
read password
if sed -n "/$username/" $username_file; then
    if sed -n "/$password" $password_file; then

else
    exit;
    fi
fi

I think I am doing something wrong here, because I am getting an error that there is an unexpected token near the else.

So basically I just want the if-statement to first read $username_file, then if the pattern bryan is in that file, I want it to read the $password_file, after that I want the script to continue to go to a certain line in the script on which the normal script that I wrote starts.

I hope I explained it right, so that you can understand me.

(I can also expand this little script by adding something like, if username or password is not in that file echo "not found, script will reload try again".)

share|improve this question
    
I don't understand this part: after that I want the script to continue to go to a certain line in the script on which the normal script that I wrote starts. Can you please clarify what you want this script to do if the username and password are both found? –  Kirk Jun 5 '11 at 22:49
    
Of course, reading your password in from a plaintext, local file, from a plaintext, local, readable shell script, is not going to stop anybody. –  Phoshi Jun 5 '11 at 23:35
add comment

3 Answers

The problem is that bash is interpreting it as then; else; put a : in that line.

If each line is only composed of what you're looking for, you can also use fgrep -x:

echo "Welcome"
echo "Username:"
read username
echo "Password:"
read password
if ! (fgrep -qx "$username" $username_file && fgrep -qx "$password" $password_file); then
    exit
fi
share|improve this answer
add comment

There are a number of problems here:

  • There are no commands in the then portion of your inner if statement, which is causing the error you see. You could solve this by either using the placeholder pseudocommand : in the then portion, or by negating the test and leaving out the else section.

  • The sed command is also invalid, and it's the wrong tool for the job anyway. To search a file for a particular line, grep is generally the command of choice. In this case, grep -Fx to do a plaintext (-F) whole-line (-x) match is probably best.

  • The if ... if ... else logic is off, also. I presume you want to exit if either the username or password isn't found, but (as written) the else clause only runs if the username was found, and the password wasn't. To fix this, use something like this:

    if ! grep -Fxq "$username" "$username_file" || ! grep -Fxq "$password" "$password_file"; then
        echo "Invalid login"
        exit 1
    fi
    

    Or maybe:

    if ! grep -Fxq "$username" "$username_file"; then
        echo "User $username not found"
        exit 1
    elif ! grep -Fxq "$password" "$password_file"; then
        echo "Incorrect password"
        exit 1
    fi
    
  • Actually, that logic is still wrong; all it checks is that the username and password exist in their respective files, not that they go together. I could type in my password and someone else's username, and it'd let me in. You need to make sure the username and password go together, probably by putting them both in the same file and searching for both at once:

    if ! grep -Fxq "$username:$password" "$user_file" ; then
        echo "Invalid login"
        exit 1
    fi
    
  • Finally, storing passwords (even in a file only root can read) is a really bad idea -- hash the password and store the hash instead. Actually, for best security you should use a salted hash, which complicates searching -- you have to find the user entry, figure out the salt that was used with its password, hash what the user typed with the same salt, and compare that with what's in the file. This in turn means that grep -Fx won't work anymore, we need to use grep in a mode that does pattern matching and be careful to avoid pattern metacharacters in the username...

Here's a quick stab at this, assuming you have openssl available:

echo "Welcome"
read -p "Ur username is: " username
if [[ "$username" =~ "[][(){}*.?+|^\$]" ]]; then
    echo "Illegal character in username"
    exit 1
fi

# Find the user's record in the file
user_record="$(grep "^$username:" "$user_file")"
if [[ -z "$user_record" ]]; then
    echo "User $username not found"
    exit 1
fi
# Parse out the user's hashed password and salt
recordedhash="${user_record#*:}"
if [[ "$recordedhash" != '$1$'* ]]; then
    echo "Invalid user record for $username"
    exit 1
fi
salt="${recordedhash#\$1\$}"
salt="${salt%\$*}"

read -p "Ur password is: " -s password
echo
if [[ "$(printf "%s" "$password" | openssl passwd -1 -stdin -salt "$salt")" != "$recordedhash" ]]; then
    echo "Incorrect password"
    exit 1
fi

To create entries in the user file, use something like this:

read -p "Ur username is: " username
if [[ "$username" =~ "[][(){}*.?+|^\$]" ]]; then
    echo "Illegal character in username"
    exit 1
fi
read -p "Ur password is: " -s password
echo
hashedpw="$(printf "%s" "$password" | openssl passwd -1 -stdin)"
user_record="$username:$hashedpw"
# Then do something to add $user_record to the file, or replace the existing record if there is one

I make no promises that the above is bug-free; I've just done some very basic tests on it.

share|improve this answer
add comment

This sounds like an X Y problem.

Why do you want to do this? As @Gordon Davisson's excellent answer shows, this is more difficult than you think. Not only are there security issues to think about, unix passwords are not all stored in /etc/passwd. So either you'll have to redo a lot of what PAM already does.

A quick idea, maybe you want to do something like

PASSED=$(su $USER -c "echo LOGIN")

If the su fails, then they don't have the password. Then PASSED will be blank. By using su, you'll go through all the normal password routines, using pam if needed, and you won't need to maintain anything.

share|improve this answer
    
Security is not really an required thing in what I want to do. This is just something that I can do for extra credit at school. I will look @Gordon Davisson's answer this afternoon. Thanks alot guys for your help. I did notice that there was nothing in the second if to do if it is true. –  bryan Jun 6 '11 at 4:55
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.