How to check the password entered is a valid password for this user?











up vote
12
down vote

favorite
4












The scenario:



In a bash script, I have to check if a password given by a user is a valid user password.



I.e suppose I have a user A with password PA.. In the script I asked user A to enter his password, So how to check if the string entered is really his password?...










share|improve this question
























  • What do you mean with a valid password? Want to test if it really is the user's password?
    – A.B.
    Apr 20 '15 at 10:51












  • @A.B. valid password=login password whatever you want to call... I mean its a password for this user
    – Maythux
    Apr 20 '15 at 10:51










  • @A.B. I know it will be a security hole but here you already know the user name also... In other words its just a test if the password is for this user..
    – Maythux
    Apr 20 '15 at 10:54






  • 3




    Here is your answer: unix.stackexchange.com/a/21728/107084
    – A.B.
    Apr 20 '15 at 10:54










  • A solution based on expect at stackoverflow.com/a/1503831/320594.
    – Jaime Hablutzel
    Feb 1 at 16:25

















up vote
12
down vote

favorite
4












The scenario:



In a bash script, I have to check if a password given by a user is a valid user password.



I.e suppose I have a user A with password PA.. In the script I asked user A to enter his password, So how to check if the string entered is really his password?...










share|improve this question
























  • What do you mean with a valid password? Want to test if it really is the user's password?
    – A.B.
    Apr 20 '15 at 10:51












  • @A.B. valid password=login password whatever you want to call... I mean its a password for this user
    – Maythux
    Apr 20 '15 at 10:51










  • @A.B. I know it will be a security hole but here you already know the user name also... In other words its just a test if the password is for this user..
    – Maythux
    Apr 20 '15 at 10:54






  • 3




    Here is your answer: unix.stackexchange.com/a/21728/107084
    – A.B.
    Apr 20 '15 at 10:54










  • A solution based on expect at stackoverflow.com/a/1503831/320594.
    – Jaime Hablutzel
    Feb 1 at 16:25















up vote
12
down vote

favorite
4









up vote
12
down vote

favorite
4






4





The scenario:



In a bash script, I have to check if a password given by a user is a valid user password.



I.e suppose I have a user A with password PA.. In the script I asked user A to enter his password, So how to check if the string entered is really his password?...










share|improve this question















The scenario:



In a bash script, I have to check if a password given by a user is a valid user password.



I.e suppose I have a user A with password PA.. In the script I asked user A to enter his password, So how to check if the string entered is really his password?...







bash






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 7 '15 at 11:46

























asked Apr 20 '15 at 10:45









Maythux

50.1k32164214




50.1k32164214












  • What do you mean with a valid password? Want to test if it really is the user's password?
    – A.B.
    Apr 20 '15 at 10:51












  • @A.B. valid password=login password whatever you want to call... I mean its a password for this user
    – Maythux
    Apr 20 '15 at 10:51










  • @A.B. I know it will be a security hole but here you already know the user name also... In other words its just a test if the password is for this user..
    – Maythux
    Apr 20 '15 at 10:54






  • 3




    Here is your answer: unix.stackexchange.com/a/21728/107084
    – A.B.
    Apr 20 '15 at 10:54










  • A solution based on expect at stackoverflow.com/a/1503831/320594.
    – Jaime Hablutzel
    Feb 1 at 16:25




















  • What do you mean with a valid password? Want to test if it really is the user's password?
    – A.B.
    Apr 20 '15 at 10:51












  • @A.B. valid password=login password whatever you want to call... I mean its a password for this user
    – Maythux
    Apr 20 '15 at 10:51










  • @A.B. I know it will be a security hole but here you already know the user name also... In other words its just a test if the password is for this user..
    – Maythux
    Apr 20 '15 at 10:54






  • 3




    Here is your answer: unix.stackexchange.com/a/21728/107084
    – A.B.
    Apr 20 '15 at 10:54










  • A solution based on expect at stackoverflow.com/a/1503831/320594.
    – Jaime Hablutzel
    Feb 1 at 16:25


















What do you mean with a valid password? Want to test if it really is the user's password?
– A.B.
Apr 20 '15 at 10:51






What do you mean with a valid password? Want to test if it really is the user's password?
– A.B.
Apr 20 '15 at 10:51














@A.B. valid password=login password whatever you want to call... I mean its a password for this user
– Maythux
Apr 20 '15 at 10:51




@A.B. valid password=login password whatever you want to call... I mean its a password for this user
– Maythux
Apr 20 '15 at 10:51












@A.B. I know it will be a security hole but here you already know the user name also... In other words its just a test if the password is for this user..
– Maythux
Apr 20 '15 at 10:54




@A.B. I know it will be a security hole but here you already know the user name also... In other words its just a test if the password is for this user..
– Maythux
Apr 20 '15 at 10:54




3




3




Here is your answer: unix.stackexchange.com/a/21728/107084
– A.B.
Apr 20 '15 at 10:54




Here is your answer: unix.stackexchange.com/a/21728/107084
– A.B.
Apr 20 '15 at 10:54












A solution based on expect at stackoverflow.com/a/1503831/320594.
– Jaime Hablutzel
Feb 1 at 16:25






A solution based on expect at stackoverflow.com/a/1503831/320594.
– Jaime Hablutzel
Feb 1 at 16:25












3 Answers
3






active

oldest

votes

















up vote
11
down vote



accepted










Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:





  • rozcietrzewiacz's answer on generating a password hash that matches an entry in /etc/shadow gives part of the solution.


  • Daniel Alder's comment explains the different syntax of the mkpasswd command present in Debian (and Ubuntu).


To manually check if a string is really some user's password, you must hash it with the same hash algorithm as in the user's shadow entry, with the same salt as in the user's shadow entry. Then it can be compared with the password hash stored there.



I've written a complete, working script demonstrating how to do this.




  • If you name it chkpass, you can run chkpass user and it will read a line from standard input and check if it's user's password.

  • Install the whois Install whois package to obtain the mkpasswd utility on which this script depends.

  • This script must be run as root to succeed.

  • Before using this script or any part of it to do real work, please see Security Notes below.


#!/usr/bin/env bash

xcorrect=0 xwrong=1 enouser=2 enodata=3 esyntax=4 ehash=5 IFS=$
die() {
printf '%s: %sn' "$0" "$2" >&2
exit $1
}
report() {
if (($1 == xcorrect))
then echo 'Correct password.'
else echo 'Wrong password.'
fi
exit $1
}

(($# == 1)) || die $esyntax "Usage: $(basename "$0") <username>"
case "$(getent passwd "$1" | awk -F: '{print $2}')" in
x) ;;
'') die $enouser "error: user '$1' not found";;
*) die $enodata "error: $1's password appears unshadowed!";;
esac

if [ -t 0 ]; then
IFS= read -rsp "[$(basename "$0")] password for $1: " pass
printf 'n'
else
IFS= read -r pass
fi

set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f
case "${ent[1]}" in
1) hashtype=md5;; 5) hashtype=sha-256;; 6) hashtype=sha-512;;
'') case "${ent[0]}" in
*|!) report $xwrong;;
'') die $enodata "error: no shadow entry (are you root?)";;
*) die $enodata 'error: failure parsing shadow entry';;
esac;;
*) die $ehash "error: password hash type is unsupported";;
esac

if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]
then report $xcorrect
else report $xwrong
fi


Security Notes



It might not be the right approach.



Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).



It has not been audited.



Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore...



Another user who's "watching" may be able to discover the user's salt.



Due to limitations in how mkpasswd accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from the shadow database, is given as a command-line argument to mkpasswd, since this is the only way that utility accepts a salt as input.



If




  • another user on the system, or

  • anyone who has the ability to make any user account (e.g., www-data) run their code, or

  • anyone who otherwise can view information about running processes (including by manually inspecting entries in /proc)


is able to check the command-line arguments to mkpasswd as it is run by this script, then they can obtain a copy of the the user's salt from the shadow database. They might have to be able to guess when that command is run, but that is sometimes achievable.



An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.



Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from /etc/shadow to a non-root user.



You can avoid this problem completely by:




  • writing part of your script in Perl or some other language that lets you call C functions, as shown in Gilles's answer to the related Unix.SE question, or

  • writing your whole script/program in such a language, rather than using bash. (Based on the way you've tagged the question, it appears you prefer to use bash.)


Be careful how you call this script.



If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.



See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.



Other Notes



It supports reading hashes from the shadow database only.



Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate /etc/shadow file that only root can read, not in /etc/passwd).



This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from passwd as well as shadow.



Keep IFS in mind when modifying this script.



I set IFS=$ at the beginning, since the three data in the hash field of a shadow entry are separated by $.




  • They also have a leading $, which is why the hash type and salt are "${ent[1]}" and "${ent[2]}" rather than "${ent[0]}" and "${ent[1]}", respectively.


The only places in this script where $IFS determines how the shell splits or combines words are





  • when these data are split into an array, by initializing it from the unquoted $( ) command substitution in:



    set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f



  • when the array is reconstituted into a string to compare to the full field from shadow, the "${ent[*]}" expression in:



    if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]



If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set IFS to different values for different commands or different parts of the script.



If you don't keep this in mind and assume $IFS is set to the usual whitespace ($' tn'), you could end up making your script behave in some pretty weird-seeming ways.






share|improve this answer






























    up vote
    8
    down vote













    You can misuse sudo for this. sudo has the -l option, for testing the sudo privileges that the user has, and -S for reading in the password from stdin. However, no matter what privilege level the user has, if successfully authenticated, sudo returns with exit status 0. So, you can take any other exit status as indication that the authentication didn't work (assuming sudo itself doesn't have any problems, like permission errors or invalid sudoers configuration).



    Something like:






    #! /bin/bash
    IFS= read -rs PASSWD
    sudo -k
    if sudo -lS &> /dev/null << EOF
    $PASSWD
    EOF
    then
    echo 'Correct password.'
    else
    echo 'Wrong password.'
    fi


    This script depends quite a bit on the sudoers configuration. I have assumed the default setup. Things that can cause it to fail:





    • targetpw or runaspw is set


    • listpw is never

    • etc.


    Other problems include (thanks Eliah):




    • The incorrect attempts will be logged in /var/log/auth.log


    • sudo must be run as the user you're authenticating for. Unless you have sudo privileges so that you can run sudo -u foo sudo -lS, that means you'll have to run the script as the target user.


    Now, the reason I used here-docs is to hamper eavesdropping. A variable used as part of the command line is more easily revealed by using top or ps or other tools to inspect processes.






    share|improve this answer



















    • 2




      This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
      – Eliah Kagan
      May 11 '15 at 19:02










    • @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
      – muru
      May 11 '15 at 19:07










    • The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
      – Eliah Kagan
      May 11 '15 at 19:11












    • @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
      – muru
      May 11 '15 at 19:14










    • @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
      – muru
      May 11 '15 at 19:17


















    up vote
    3
    down vote













    Another method (probably more interesting for its theoretical contents than for its pratical applications).



    User's passwords are stored in /etc/shadow.



    The passwords stored here are encrypted, in the latest Ubuntu releases using SHA-512.



    Specifically, upon the password creation, the password in clear text is salted and encrypted through SHA-512.



    One solution would be then to salt / encrypt the given password and match it against the encrypted user's password stored in the given user's /etc/shadow entry.



    To give a quick breakdown of how the passwords are stored in each user /etc/shadow entry, here's a sample /etc/shadow entry for a user foo with password bar:



    foo:$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:16566:0:99999:7:::




    • foo: username


    • 6: password's encryption type


    • lWS1oJnmDlaXrx1F: password's encryption salt


    • h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/: SHA-512 salted / encrypted password


    In order to match the given password bar for the given user foo, the first thing to do is to get the salt:



    $ sudo getent shadow foo | cut -d$ -f3
    lWS1oJnmDlaXrx1F


    Then one should get the full salted / encrypted password:



    $ sudo getent shadow foo | cut -d: -f2
    $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


    Then the given password can be salted / encrypted and matched against the salted / encrypted user's password stored in /etc/shadow:



    $ python -c 'import crypt; print crypt.crypt("bar", "$6$lWS1oJnmDlaXrx1F")'
    $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


    They match! Everything put into a bash script:



    #!/bin/bash

    read -p "Username >" username
    IFS= read -p "Password >" password
    salt=$(sudo getent shadow $username | cut -d$ -f3)
    epassword=$(sudo getent shadow $username | cut -d: -f2)
    match=$(python -c 'import crypt; print crypt.crypt("'"${password}"'", "$6$'${salt}'")')
    [ ${match} == ${epassword} ] && echo "Password matches" || echo "Password doesn't match"


    Output:



    $ ./script.sh 
    Username >foo
    Password >bar
    Password matches
    $ ./script.sh
    Username >foo
    Password >bar1
    Password doesn't match





    share|improve this answer



















    • 1




      sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
      – muru
      May 11 '15 at 19:58










    • @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
      – kos
      May 11 '15 at 20:07






    • 1




      Eek. getent can do the searching for you. I took the liberty of editing.
      – muru
      May 11 '15 at 20:09










    • @muru Yea you should have in fact, now I see the point!
      – kos
      May 11 '15 at 20:10






    • 2




      I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
      – Eliah Kagan
      May 11 '15 at 21:18











    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "89"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f611580%2fhow-to-check-the-password-entered-is-a-valid-password-for-this-user%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    11
    down vote



    accepted










    Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:





    • rozcietrzewiacz's answer on generating a password hash that matches an entry in /etc/shadow gives part of the solution.


    • Daniel Alder's comment explains the different syntax of the mkpasswd command present in Debian (and Ubuntu).


    To manually check if a string is really some user's password, you must hash it with the same hash algorithm as in the user's shadow entry, with the same salt as in the user's shadow entry. Then it can be compared with the password hash stored there.



    I've written a complete, working script demonstrating how to do this.




    • If you name it chkpass, you can run chkpass user and it will read a line from standard input and check if it's user's password.

    • Install the whois Install whois package to obtain the mkpasswd utility on which this script depends.

    • This script must be run as root to succeed.

    • Before using this script or any part of it to do real work, please see Security Notes below.


    #!/usr/bin/env bash

    xcorrect=0 xwrong=1 enouser=2 enodata=3 esyntax=4 ehash=5 IFS=$
    die() {
    printf '%s: %sn' "$0" "$2" >&2
    exit $1
    }
    report() {
    if (($1 == xcorrect))
    then echo 'Correct password.'
    else echo 'Wrong password.'
    fi
    exit $1
    }

    (($# == 1)) || die $esyntax "Usage: $(basename "$0") <username>"
    case "$(getent passwd "$1" | awk -F: '{print $2}')" in
    x) ;;
    '') die $enouser "error: user '$1' not found";;
    *) die $enodata "error: $1's password appears unshadowed!";;
    esac

    if [ -t 0 ]; then
    IFS= read -rsp "[$(basename "$0")] password for $1: " pass
    printf 'n'
    else
    IFS= read -r pass
    fi

    set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f
    case "${ent[1]}" in
    1) hashtype=md5;; 5) hashtype=sha-256;; 6) hashtype=sha-512;;
    '') case "${ent[0]}" in
    *|!) report $xwrong;;
    '') die $enodata "error: no shadow entry (are you root?)";;
    *) die $enodata 'error: failure parsing shadow entry';;
    esac;;
    *) die $ehash "error: password hash type is unsupported";;
    esac

    if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]
    then report $xcorrect
    else report $xwrong
    fi


    Security Notes



    It might not be the right approach.



    Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).



    It has not been audited.



    Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore...



    Another user who's "watching" may be able to discover the user's salt.



    Due to limitations in how mkpasswd accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from the shadow database, is given as a command-line argument to mkpasswd, since this is the only way that utility accepts a salt as input.



    If




    • another user on the system, or

    • anyone who has the ability to make any user account (e.g., www-data) run their code, or

    • anyone who otherwise can view information about running processes (including by manually inspecting entries in /proc)


    is able to check the command-line arguments to mkpasswd as it is run by this script, then they can obtain a copy of the the user's salt from the shadow database. They might have to be able to guess when that command is run, but that is sometimes achievable.



    An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.



    Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from /etc/shadow to a non-root user.



    You can avoid this problem completely by:




    • writing part of your script in Perl or some other language that lets you call C functions, as shown in Gilles's answer to the related Unix.SE question, or

    • writing your whole script/program in such a language, rather than using bash. (Based on the way you've tagged the question, it appears you prefer to use bash.)


    Be careful how you call this script.



    If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.



    See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.



    Other Notes



    It supports reading hashes from the shadow database only.



    Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate /etc/shadow file that only root can read, not in /etc/passwd).



    This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from passwd as well as shadow.



    Keep IFS in mind when modifying this script.



    I set IFS=$ at the beginning, since the three data in the hash field of a shadow entry are separated by $.




    • They also have a leading $, which is why the hash type and salt are "${ent[1]}" and "${ent[2]}" rather than "${ent[0]}" and "${ent[1]}", respectively.


    The only places in this script where $IFS determines how the shell splits or combines words are





    • when these data are split into an array, by initializing it from the unquoted $( ) command substitution in:



      set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f



    • when the array is reconstituted into a string to compare to the full field from shadow, the "${ent[*]}" expression in:



      if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]



    If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set IFS to different values for different commands or different parts of the script.



    If you don't keep this in mind and assume $IFS is set to the usual whitespace ($' tn'), you could end up making your script behave in some pretty weird-seeming ways.






    share|improve this answer



























      up vote
      11
      down vote



      accepted










      Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:





      • rozcietrzewiacz's answer on generating a password hash that matches an entry in /etc/shadow gives part of the solution.


      • Daniel Alder's comment explains the different syntax of the mkpasswd command present in Debian (and Ubuntu).


      To manually check if a string is really some user's password, you must hash it with the same hash algorithm as in the user's shadow entry, with the same salt as in the user's shadow entry. Then it can be compared with the password hash stored there.



      I've written a complete, working script demonstrating how to do this.




      • If you name it chkpass, you can run chkpass user and it will read a line from standard input and check if it's user's password.

      • Install the whois Install whois package to obtain the mkpasswd utility on which this script depends.

      • This script must be run as root to succeed.

      • Before using this script or any part of it to do real work, please see Security Notes below.


      #!/usr/bin/env bash

      xcorrect=0 xwrong=1 enouser=2 enodata=3 esyntax=4 ehash=5 IFS=$
      die() {
      printf '%s: %sn' "$0" "$2" >&2
      exit $1
      }
      report() {
      if (($1 == xcorrect))
      then echo 'Correct password.'
      else echo 'Wrong password.'
      fi
      exit $1
      }

      (($# == 1)) || die $esyntax "Usage: $(basename "$0") <username>"
      case "$(getent passwd "$1" | awk -F: '{print $2}')" in
      x) ;;
      '') die $enouser "error: user '$1' not found";;
      *) die $enodata "error: $1's password appears unshadowed!";;
      esac

      if [ -t 0 ]; then
      IFS= read -rsp "[$(basename "$0")] password for $1: " pass
      printf 'n'
      else
      IFS= read -r pass
      fi

      set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f
      case "${ent[1]}" in
      1) hashtype=md5;; 5) hashtype=sha-256;; 6) hashtype=sha-512;;
      '') case "${ent[0]}" in
      *|!) report $xwrong;;
      '') die $enodata "error: no shadow entry (are you root?)";;
      *) die $enodata 'error: failure parsing shadow entry';;
      esac;;
      *) die $ehash "error: password hash type is unsupported";;
      esac

      if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]
      then report $xcorrect
      else report $xwrong
      fi


      Security Notes



      It might not be the right approach.



      Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).



      It has not been audited.



      Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore...



      Another user who's "watching" may be able to discover the user's salt.



      Due to limitations in how mkpasswd accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from the shadow database, is given as a command-line argument to mkpasswd, since this is the only way that utility accepts a salt as input.



      If




      • another user on the system, or

      • anyone who has the ability to make any user account (e.g., www-data) run their code, or

      • anyone who otherwise can view information about running processes (including by manually inspecting entries in /proc)


      is able to check the command-line arguments to mkpasswd as it is run by this script, then they can obtain a copy of the the user's salt from the shadow database. They might have to be able to guess when that command is run, but that is sometimes achievable.



      An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.



      Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from /etc/shadow to a non-root user.



      You can avoid this problem completely by:




      • writing part of your script in Perl or some other language that lets you call C functions, as shown in Gilles's answer to the related Unix.SE question, or

      • writing your whole script/program in such a language, rather than using bash. (Based on the way you've tagged the question, it appears you prefer to use bash.)


      Be careful how you call this script.



      If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.



      See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.



      Other Notes



      It supports reading hashes from the shadow database only.



      Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate /etc/shadow file that only root can read, not in /etc/passwd).



      This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from passwd as well as shadow.



      Keep IFS in mind when modifying this script.



      I set IFS=$ at the beginning, since the three data in the hash field of a shadow entry are separated by $.




      • They also have a leading $, which is why the hash type and salt are "${ent[1]}" and "${ent[2]}" rather than "${ent[0]}" and "${ent[1]}", respectively.


      The only places in this script where $IFS determines how the shell splits or combines words are





      • when these data are split into an array, by initializing it from the unquoted $( ) command substitution in:



        set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f



      • when the array is reconstituted into a string to compare to the full field from shadow, the "${ent[*]}" expression in:



        if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]



      If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set IFS to different values for different commands or different parts of the script.



      If you don't keep this in mind and assume $IFS is set to the usual whitespace ($' tn'), you could end up making your script behave in some pretty weird-seeming ways.






      share|improve this answer

























        up vote
        11
        down vote



        accepted







        up vote
        11
        down vote



        accepted






        Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:





        • rozcietrzewiacz's answer on generating a password hash that matches an entry in /etc/shadow gives part of the solution.


        • Daniel Alder's comment explains the different syntax of the mkpasswd command present in Debian (and Ubuntu).


        To manually check if a string is really some user's password, you must hash it with the same hash algorithm as in the user's shadow entry, with the same salt as in the user's shadow entry. Then it can be compared with the password hash stored there.



        I've written a complete, working script demonstrating how to do this.




        • If you name it chkpass, you can run chkpass user and it will read a line from standard input and check if it's user's password.

        • Install the whois Install whois package to obtain the mkpasswd utility on which this script depends.

        • This script must be run as root to succeed.

        • Before using this script or any part of it to do real work, please see Security Notes below.


        #!/usr/bin/env bash

        xcorrect=0 xwrong=1 enouser=2 enodata=3 esyntax=4 ehash=5 IFS=$
        die() {
        printf '%s: %sn' "$0" "$2" >&2
        exit $1
        }
        report() {
        if (($1 == xcorrect))
        then echo 'Correct password.'
        else echo 'Wrong password.'
        fi
        exit $1
        }

        (($# == 1)) || die $esyntax "Usage: $(basename "$0") <username>"
        case "$(getent passwd "$1" | awk -F: '{print $2}')" in
        x) ;;
        '') die $enouser "error: user '$1' not found";;
        *) die $enodata "error: $1's password appears unshadowed!";;
        esac

        if [ -t 0 ]; then
        IFS= read -rsp "[$(basename "$0")] password for $1: " pass
        printf 'n'
        else
        IFS= read -r pass
        fi

        set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f
        case "${ent[1]}" in
        1) hashtype=md5;; 5) hashtype=sha-256;; 6) hashtype=sha-512;;
        '') case "${ent[0]}" in
        *|!) report $xwrong;;
        '') die $enodata "error: no shadow entry (are you root?)";;
        *) die $enodata 'error: failure parsing shadow entry';;
        esac;;
        *) die $ehash "error: password hash type is unsupported";;
        esac

        if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]
        then report $xcorrect
        else report $xwrong
        fi


        Security Notes



        It might not be the right approach.



        Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).



        It has not been audited.



        Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore...



        Another user who's "watching" may be able to discover the user's salt.



        Due to limitations in how mkpasswd accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from the shadow database, is given as a command-line argument to mkpasswd, since this is the only way that utility accepts a salt as input.



        If




        • another user on the system, or

        • anyone who has the ability to make any user account (e.g., www-data) run their code, or

        • anyone who otherwise can view information about running processes (including by manually inspecting entries in /proc)


        is able to check the command-line arguments to mkpasswd as it is run by this script, then they can obtain a copy of the the user's salt from the shadow database. They might have to be able to guess when that command is run, but that is sometimes achievable.



        An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.



        Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from /etc/shadow to a non-root user.



        You can avoid this problem completely by:




        • writing part of your script in Perl or some other language that lets you call C functions, as shown in Gilles's answer to the related Unix.SE question, or

        • writing your whole script/program in such a language, rather than using bash. (Based on the way you've tagged the question, it appears you prefer to use bash.)


        Be careful how you call this script.



        If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.



        See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.



        Other Notes



        It supports reading hashes from the shadow database only.



        Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate /etc/shadow file that only root can read, not in /etc/passwd).



        This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from passwd as well as shadow.



        Keep IFS in mind when modifying this script.



        I set IFS=$ at the beginning, since the three data in the hash field of a shadow entry are separated by $.




        • They also have a leading $, which is why the hash type and salt are "${ent[1]}" and "${ent[2]}" rather than "${ent[0]}" and "${ent[1]}", respectively.


        The only places in this script where $IFS determines how the shell splits or combines words are





        • when these data are split into an array, by initializing it from the unquoted $( ) command substitution in:



          set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f



        • when the array is reconstituted into a string to compare to the full field from shadow, the "${ent[*]}" expression in:



          if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]



        If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set IFS to different values for different commands or different parts of the script.



        If you don't keep this in mind and assume $IFS is set to the usual whitespace ($' tn'), you could end up making your script behave in some pretty weird-seeming ways.






        share|improve this answer














        Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:





        • rozcietrzewiacz's answer on generating a password hash that matches an entry in /etc/shadow gives part of the solution.


        • Daniel Alder's comment explains the different syntax of the mkpasswd command present in Debian (and Ubuntu).


        To manually check if a string is really some user's password, you must hash it with the same hash algorithm as in the user's shadow entry, with the same salt as in the user's shadow entry. Then it can be compared with the password hash stored there.



        I've written a complete, working script demonstrating how to do this.




        • If you name it chkpass, you can run chkpass user and it will read a line from standard input and check if it's user's password.

        • Install the whois Install whois package to obtain the mkpasswd utility on which this script depends.

        • This script must be run as root to succeed.

        • Before using this script or any part of it to do real work, please see Security Notes below.


        #!/usr/bin/env bash

        xcorrect=0 xwrong=1 enouser=2 enodata=3 esyntax=4 ehash=5 IFS=$
        die() {
        printf '%s: %sn' "$0" "$2" >&2
        exit $1
        }
        report() {
        if (($1 == xcorrect))
        then echo 'Correct password.'
        else echo 'Wrong password.'
        fi
        exit $1
        }

        (($# == 1)) || die $esyntax "Usage: $(basename "$0") <username>"
        case "$(getent passwd "$1" | awk -F: '{print $2}')" in
        x) ;;
        '') die $enouser "error: user '$1' not found";;
        *) die $enodata "error: $1's password appears unshadowed!";;
        esac

        if [ -t 0 ]; then
        IFS= read -rsp "[$(basename "$0")] password for $1: " pass
        printf 'n'
        else
        IFS= read -r pass
        fi

        set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f
        case "${ent[1]}" in
        1) hashtype=md5;; 5) hashtype=sha-256;; 6) hashtype=sha-512;;
        '') case "${ent[0]}" in
        *|!) report $xwrong;;
        '') die $enodata "error: no shadow entry (are you root?)";;
        *) die $enodata 'error: failure parsing shadow entry';;
        esac;;
        *) die $ehash "error: password hash type is unsupported";;
        esac

        if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]
        then report $xcorrect
        else report $xwrong
        fi


        Security Notes



        It might not be the right approach.



        Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).



        It has not been audited.



        Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore...



        Another user who's "watching" may be able to discover the user's salt.



        Due to limitations in how mkpasswd accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from the shadow database, is given as a command-line argument to mkpasswd, since this is the only way that utility accepts a salt as input.



        If




        • another user on the system, or

        • anyone who has the ability to make any user account (e.g., www-data) run their code, or

        • anyone who otherwise can view information about running processes (including by manually inspecting entries in /proc)


        is able to check the command-line arguments to mkpasswd as it is run by this script, then they can obtain a copy of the the user's salt from the shadow database. They might have to be able to guess when that command is run, but that is sometimes achievable.



        An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.



        Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from /etc/shadow to a non-root user.



        You can avoid this problem completely by:




        • writing part of your script in Perl or some other language that lets you call C functions, as shown in Gilles's answer to the related Unix.SE question, or

        • writing your whole script/program in such a language, rather than using bash. (Based on the way you've tagged the question, it appears you prefer to use bash.)


        Be careful how you call this script.



        If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.



        See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.



        Other Notes



        It supports reading hashes from the shadow database only.



        Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate /etc/shadow file that only root can read, not in /etc/passwd).



        This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from passwd as well as shadow.



        Keep IFS in mind when modifying this script.



        I set IFS=$ at the beginning, since the three data in the hash field of a shadow entry are separated by $.




        • They also have a leading $, which is why the hash type and salt are "${ent[1]}" and "${ent[2]}" rather than "${ent[0]}" and "${ent[1]}", respectively.


        The only places in this script where $IFS determines how the shell splits or combines words are





        • when these data are split into an array, by initializing it from the unquoted $( ) command substitution in:



          set -f; ent=($(getent shadow "$1" | awk -F: '{print $2}')); set +f



        • when the array is reconstituted into a string to compare to the full field from shadow, the "${ent[*]}" expression in:



          if [[ "${ent[*]}" = "$(mkpasswd -sm $hashtype -S "${ent[2]}" <<<"$pass")" ]]



        If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set IFS to different values for different commands or different parts of the script.



        If you don't keep this in mind and assume $IFS is set to the usual whitespace ($' tn'), you could end up making your script behave in some pretty weird-seeming ways.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited May 11 '15 at 21:01

























        answered May 10 '15 at 21:01









        Eliah Kagan

        81.1k20227364




        81.1k20227364
























            up vote
            8
            down vote













            You can misuse sudo for this. sudo has the -l option, for testing the sudo privileges that the user has, and -S for reading in the password from stdin. However, no matter what privilege level the user has, if successfully authenticated, sudo returns with exit status 0. So, you can take any other exit status as indication that the authentication didn't work (assuming sudo itself doesn't have any problems, like permission errors or invalid sudoers configuration).



            Something like:






            #! /bin/bash
            IFS= read -rs PASSWD
            sudo -k
            if sudo -lS &> /dev/null << EOF
            $PASSWD
            EOF
            then
            echo 'Correct password.'
            else
            echo 'Wrong password.'
            fi


            This script depends quite a bit on the sudoers configuration. I have assumed the default setup. Things that can cause it to fail:





            • targetpw or runaspw is set


            • listpw is never

            • etc.


            Other problems include (thanks Eliah):




            • The incorrect attempts will be logged in /var/log/auth.log


            • sudo must be run as the user you're authenticating for. Unless you have sudo privileges so that you can run sudo -u foo sudo -lS, that means you'll have to run the script as the target user.


            Now, the reason I used here-docs is to hamper eavesdropping. A variable used as part of the command line is more easily revealed by using top or ps or other tools to inspect processes.






            share|improve this answer



















            • 2




              This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
              – Eliah Kagan
              May 11 '15 at 19:02










            • @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
              – muru
              May 11 '15 at 19:07










            • The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
              – Eliah Kagan
              May 11 '15 at 19:11












            • @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
              – muru
              May 11 '15 at 19:14










            • @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
              – muru
              May 11 '15 at 19:17















            up vote
            8
            down vote













            You can misuse sudo for this. sudo has the -l option, for testing the sudo privileges that the user has, and -S for reading in the password from stdin. However, no matter what privilege level the user has, if successfully authenticated, sudo returns with exit status 0. So, you can take any other exit status as indication that the authentication didn't work (assuming sudo itself doesn't have any problems, like permission errors or invalid sudoers configuration).



            Something like:






            #! /bin/bash
            IFS= read -rs PASSWD
            sudo -k
            if sudo -lS &> /dev/null << EOF
            $PASSWD
            EOF
            then
            echo 'Correct password.'
            else
            echo 'Wrong password.'
            fi


            This script depends quite a bit on the sudoers configuration. I have assumed the default setup. Things that can cause it to fail:





            • targetpw or runaspw is set


            • listpw is never

            • etc.


            Other problems include (thanks Eliah):




            • The incorrect attempts will be logged in /var/log/auth.log


            • sudo must be run as the user you're authenticating for. Unless you have sudo privileges so that you can run sudo -u foo sudo -lS, that means you'll have to run the script as the target user.


            Now, the reason I used here-docs is to hamper eavesdropping. A variable used as part of the command line is more easily revealed by using top or ps or other tools to inspect processes.






            share|improve this answer



















            • 2




              This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
              – Eliah Kagan
              May 11 '15 at 19:02










            • @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
              – muru
              May 11 '15 at 19:07










            • The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
              – Eliah Kagan
              May 11 '15 at 19:11












            • @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
              – muru
              May 11 '15 at 19:14










            • @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
              – muru
              May 11 '15 at 19:17













            up vote
            8
            down vote










            up vote
            8
            down vote









            You can misuse sudo for this. sudo has the -l option, for testing the sudo privileges that the user has, and -S for reading in the password from stdin. However, no matter what privilege level the user has, if successfully authenticated, sudo returns with exit status 0. So, you can take any other exit status as indication that the authentication didn't work (assuming sudo itself doesn't have any problems, like permission errors or invalid sudoers configuration).



            Something like:






            #! /bin/bash
            IFS= read -rs PASSWD
            sudo -k
            if sudo -lS &> /dev/null << EOF
            $PASSWD
            EOF
            then
            echo 'Correct password.'
            else
            echo 'Wrong password.'
            fi


            This script depends quite a bit on the sudoers configuration. I have assumed the default setup. Things that can cause it to fail:





            • targetpw or runaspw is set


            • listpw is never

            • etc.


            Other problems include (thanks Eliah):




            • The incorrect attempts will be logged in /var/log/auth.log


            • sudo must be run as the user you're authenticating for. Unless you have sudo privileges so that you can run sudo -u foo sudo -lS, that means you'll have to run the script as the target user.


            Now, the reason I used here-docs is to hamper eavesdropping. A variable used as part of the command line is more easily revealed by using top or ps or other tools to inspect processes.






            share|improve this answer














            You can misuse sudo for this. sudo has the -l option, for testing the sudo privileges that the user has, and -S for reading in the password from stdin. However, no matter what privilege level the user has, if successfully authenticated, sudo returns with exit status 0. So, you can take any other exit status as indication that the authentication didn't work (assuming sudo itself doesn't have any problems, like permission errors or invalid sudoers configuration).



            Something like:






            #! /bin/bash
            IFS= read -rs PASSWD
            sudo -k
            if sudo -lS &> /dev/null << EOF
            $PASSWD
            EOF
            then
            echo 'Correct password.'
            else
            echo 'Wrong password.'
            fi


            This script depends quite a bit on the sudoers configuration. I have assumed the default setup. Things that can cause it to fail:





            • targetpw or runaspw is set


            • listpw is never

            • etc.


            Other problems include (thanks Eliah):




            • The incorrect attempts will be logged in /var/log/auth.log


            • sudo must be run as the user you're authenticating for. Unless you have sudo privileges so that you can run sudo -u foo sudo -lS, that means you'll have to run the script as the target user.


            Now, the reason I used here-docs is to hamper eavesdropping. A variable used as part of the command line is more easily revealed by using top or ps or other tools to inspect processes.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 11 '15 at 19:06

























            answered May 11 '15 at 18:05









            muru

            135k19289490




            135k19289490








            • 2




              This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
              – Eliah Kagan
              May 11 '15 at 19:02










            • @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
              – muru
              May 11 '15 at 19:07










            • The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
              – Eliah Kagan
              May 11 '15 at 19:11












            • @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
              – muru
              May 11 '15 at 19:14










            • @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
              – muru
              May 11 '15 at 19:17














            • 2




              This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
              – Eliah Kagan
              May 11 '15 at 19:02










            • @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
              – muru
              May 11 '15 at 19:07










            • The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
              – Eliah Kagan
              May 11 '15 at 19:11












            • @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
              – muru
              May 11 '15 at 19:14










            • @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
              – muru
              May 11 '15 at 19:17








            2




            2




            This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
            – Eliah Kagan
            May 11 '15 at 19:02




            This way looks excellent. Though it won't work on systems with uncommon sudo configs (as you say) and clutters /var/log/auth.log with records of each attempt, this is quick, simple, and uses an existing utility, rather than reinventing the wheel (so to speak). I suggest setting IFS= for read, to prevent false successes for whitespace-padded user input and non-padded passwords, as well as false failures for whitespace-padded user input and padded passwords. (My solution had a similar bug.) You may also want to explain how it must be run as the user whose password is being checked.
            – Eliah Kagan
            May 11 '15 at 19:02












            @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
            – muru
            May 11 '15 at 19:07




            @EliahKagan each failed attempt is logged, but yes, you're right about everything else.
            – muru
            May 11 '15 at 19:07












            The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
            – Eliah Kagan
            May 11 '15 at 19:11






            The successful authentications are logged also. sudo -l causes an entry to be written with "COMMAND=list". Btw (unrelated), while it's not objectively better to do so, using a here string in place of a here document achieves the same security goal and is more compact. Since the script already uses the bashisms read -s and &>, using if sudo -lS &>/dev/null <<<"$PASSWD"; then is no less portable. I'm not suggesting you should change what you have (it's just fine). Rather, I mention it so readers know they have this option too.
            – Eliah Kagan
            May 11 '15 at 19:11














            @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
            – muru
            May 11 '15 at 19:14




            @EliahKagan ah. I thought sudo -l disabled something - perhaps it was reporting when a user tries to run a command that they aren't allowed to.
            – muru
            May 11 '15 at 19:14












            @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
            – muru
            May 11 '15 at 19:17




            @EliahKagan Indeed. I have used herestrings that way before. I was labouring under a misconception here, which led to heredocs, but then I decided to keep them anyway.
            – muru
            May 11 '15 at 19:17










            up vote
            3
            down vote













            Another method (probably more interesting for its theoretical contents than for its pratical applications).



            User's passwords are stored in /etc/shadow.



            The passwords stored here are encrypted, in the latest Ubuntu releases using SHA-512.



            Specifically, upon the password creation, the password in clear text is salted and encrypted through SHA-512.



            One solution would be then to salt / encrypt the given password and match it against the encrypted user's password stored in the given user's /etc/shadow entry.



            To give a quick breakdown of how the passwords are stored in each user /etc/shadow entry, here's a sample /etc/shadow entry for a user foo with password bar:



            foo:$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:16566:0:99999:7:::




            • foo: username


            • 6: password's encryption type


            • lWS1oJnmDlaXrx1F: password's encryption salt


            • h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/: SHA-512 salted / encrypted password


            In order to match the given password bar for the given user foo, the first thing to do is to get the salt:



            $ sudo getent shadow foo | cut -d$ -f3
            lWS1oJnmDlaXrx1F


            Then one should get the full salted / encrypted password:



            $ sudo getent shadow foo | cut -d: -f2
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            Then the given password can be salted / encrypted and matched against the salted / encrypted user's password stored in /etc/shadow:



            $ python -c 'import crypt; print crypt.crypt("bar", "$6$lWS1oJnmDlaXrx1F")'
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            They match! Everything put into a bash script:



            #!/bin/bash

            read -p "Username >" username
            IFS= read -p "Password >" password
            salt=$(sudo getent shadow $username | cut -d$ -f3)
            epassword=$(sudo getent shadow $username | cut -d: -f2)
            match=$(python -c 'import crypt; print crypt.crypt("'"${password}"'", "$6$'${salt}'")')
            [ ${match} == ${epassword} ] && echo "Password matches" || echo "Password doesn't match"


            Output:



            $ ./script.sh 
            Username >foo
            Password >bar
            Password matches
            $ ./script.sh
            Username >foo
            Password >bar1
            Password doesn't match





            share|improve this answer



















            • 1




              sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
              – muru
              May 11 '15 at 19:58










            • @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
              – kos
              May 11 '15 at 20:07






            • 1




              Eek. getent can do the searching for you. I took the liberty of editing.
              – muru
              May 11 '15 at 20:09










            • @muru Yea you should have in fact, now I see the point!
              – kos
              May 11 '15 at 20:10






            • 2




              I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
              – Eliah Kagan
              May 11 '15 at 21:18















            up vote
            3
            down vote













            Another method (probably more interesting for its theoretical contents than for its pratical applications).



            User's passwords are stored in /etc/shadow.



            The passwords stored here are encrypted, in the latest Ubuntu releases using SHA-512.



            Specifically, upon the password creation, the password in clear text is salted and encrypted through SHA-512.



            One solution would be then to salt / encrypt the given password and match it against the encrypted user's password stored in the given user's /etc/shadow entry.



            To give a quick breakdown of how the passwords are stored in each user /etc/shadow entry, here's a sample /etc/shadow entry for a user foo with password bar:



            foo:$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:16566:0:99999:7:::




            • foo: username


            • 6: password's encryption type


            • lWS1oJnmDlaXrx1F: password's encryption salt


            • h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/: SHA-512 salted / encrypted password


            In order to match the given password bar for the given user foo, the first thing to do is to get the salt:



            $ sudo getent shadow foo | cut -d$ -f3
            lWS1oJnmDlaXrx1F


            Then one should get the full salted / encrypted password:



            $ sudo getent shadow foo | cut -d: -f2
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            Then the given password can be salted / encrypted and matched against the salted / encrypted user's password stored in /etc/shadow:



            $ python -c 'import crypt; print crypt.crypt("bar", "$6$lWS1oJnmDlaXrx1F")'
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            They match! Everything put into a bash script:



            #!/bin/bash

            read -p "Username >" username
            IFS= read -p "Password >" password
            salt=$(sudo getent shadow $username | cut -d$ -f3)
            epassword=$(sudo getent shadow $username | cut -d: -f2)
            match=$(python -c 'import crypt; print crypt.crypt("'"${password}"'", "$6$'${salt}'")')
            [ ${match} == ${epassword} ] && echo "Password matches" || echo "Password doesn't match"


            Output:



            $ ./script.sh 
            Username >foo
            Password >bar
            Password matches
            $ ./script.sh
            Username >foo
            Password >bar1
            Password doesn't match





            share|improve this answer



















            • 1




              sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
              – muru
              May 11 '15 at 19:58










            • @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
              – kos
              May 11 '15 at 20:07






            • 1




              Eek. getent can do the searching for you. I took the liberty of editing.
              – muru
              May 11 '15 at 20:09










            • @muru Yea you should have in fact, now I see the point!
              – kos
              May 11 '15 at 20:10






            • 2




              I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
              – Eliah Kagan
              May 11 '15 at 21:18













            up vote
            3
            down vote










            up vote
            3
            down vote









            Another method (probably more interesting for its theoretical contents than for its pratical applications).



            User's passwords are stored in /etc/shadow.



            The passwords stored here are encrypted, in the latest Ubuntu releases using SHA-512.



            Specifically, upon the password creation, the password in clear text is salted and encrypted through SHA-512.



            One solution would be then to salt / encrypt the given password and match it against the encrypted user's password stored in the given user's /etc/shadow entry.



            To give a quick breakdown of how the passwords are stored in each user /etc/shadow entry, here's a sample /etc/shadow entry for a user foo with password bar:



            foo:$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:16566:0:99999:7:::




            • foo: username


            • 6: password's encryption type


            • lWS1oJnmDlaXrx1F: password's encryption salt


            • h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/: SHA-512 salted / encrypted password


            In order to match the given password bar for the given user foo, the first thing to do is to get the salt:



            $ sudo getent shadow foo | cut -d$ -f3
            lWS1oJnmDlaXrx1F


            Then one should get the full salted / encrypted password:



            $ sudo getent shadow foo | cut -d: -f2
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            Then the given password can be salted / encrypted and matched against the salted / encrypted user's password stored in /etc/shadow:



            $ python -c 'import crypt; print crypt.crypt("bar", "$6$lWS1oJnmDlaXrx1F")'
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            They match! Everything put into a bash script:



            #!/bin/bash

            read -p "Username >" username
            IFS= read -p "Password >" password
            salt=$(sudo getent shadow $username | cut -d$ -f3)
            epassword=$(sudo getent shadow $username | cut -d: -f2)
            match=$(python -c 'import crypt; print crypt.crypt("'"${password}"'", "$6$'${salt}'")')
            [ ${match} == ${epassword} ] && echo "Password matches" || echo "Password doesn't match"


            Output:



            $ ./script.sh 
            Username >foo
            Password >bar
            Password matches
            $ ./script.sh
            Username >foo
            Password >bar1
            Password doesn't match





            share|improve this answer














            Another method (probably more interesting for its theoretical contents than for its pratical applications).



            User's passwords are stored in /etc/shadow.



            The passwords stored here are encrypted, in the latest Ubuntu releases using SHA-512.



            Specifically, upon the password creation, the password in clear text is salted and encrypted through SHA-512.



            One solution would be then to salt / encrypt the given password and match it against the encrypted user's password stored in the given user's /etc/shadow entry.



            To give a quick breakdown of how the passwords are stored in each user /etc/shadow entry, here's a sample /etc/shadow entry for a user foo with password bar:



            foo:$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:16566:0:99999:7:::




            • foo: username


            • 6: password's encryption type


            • lWS1oJnmDlaXrx1F: password's encryption salt


            • h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/: SHA-512 salted / encrypted password


            In order to match the given password bar for the given user foo, the first thing to do is to get the salt:



            $ sudo getent shadow foo | cut -d$ -f3
            lWS1oJnmDlaXrx1F


            Then one should get the full salted / encrypted password:



            $ sudo getent shadow foo | cut -d: -f2
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            Then the given password can be salted / encrypted and matched against the salted / encrypted user's password stored in /etc/shadow:



            $ python -c 'import crypt; print crypt.crypt("bar", "$6$lWS1oJnmDlaXrx1F")'
            $6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/


            They match! Everything put into a bash script:



            #!/bin/bash

            read -p "Username >" username
            IFS= read -p "Password >" password
            salt=$(sudo getent shadow $username | cut -d$ -f3)
            epassword=$(sudo getent shadow $username | cut -d: -f2)
            match=$(python -c 'import crypt; print crypt.crypt("'"${password}"'", "$6$'${salt}'")')
            [ ${match} == ${epassword} ] && echo "Password matches" || echo "Password doesn't match"


            Output:



            $ ./script.sh 
            Username >foo
            Password >bar
            Password matches
            $ ./script.sh
            Username >foo
            Password >bar1
            Password doesn't match






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 11 '15 at 22:08

























            answered May 11 '15 at 19:54









            kos

            25.2k869119




            25.2k869119








            • 1




              sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
              – muru
              May 11 '15 at 19:58










            • @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
              – kos
              May 11 '15 at 20:07






            • 1




              Eek. getent can do the searching for you. I took the liberty of editing.
              – muru
              May 11 '15 at 20:09










            • @muru Yea you should have in fact, now I see the point!
              – kos
              May 11 '15 at 20:10






            • 2




              I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
              – Eliah Kagan
              May 11 '15 at 21:18














            • 1




              sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
              – muru
              May 11 '15 at 19:58










            • @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
              – kos
              May 11 '15 at 20:07






            • 1




              Eek. getent can do the searching for you. I took the liberty of editing.
              – muru
              May 11 '15 at 20:09










            • @muru Yea you should have in fact, now I see the point!
              – kos
              May 11 '15 at 20:10






            • 2




              I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
              – Eliah Kagan
              May 11 '15 at 21:18








            1




            1




            sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
            – muru
            May 11 '15 at 19:58




            sudo getent shadow >> sudo grep .... Otherwise, nice. This is what I thought of originally, then got too lazy.
            – muru
            May 11 '15 at 19:58












            @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
            – kos
            May 11 '15 at 20:07




            @muru Thanks. Definetly feels nicer, so updated, but still I'm not sure if in this case getent+grep+cut > grep+cut
            – kos
            May 11 '15 at 20:07




            1




            1




            Eek. getent can do the searching for you. I took the liberty of editing.
            – muru
            May 11 '15 at 20:09




            Eek. getent can do the searching for you. I took the liberty of editing.
            – muru
            May 11 '15 at 20:09












            @muru Yea you should have in fact, now I see the point!
            – kos
            May 11 '15 at 20:10




            @muru Yea you should have in fact, now I see the point!
            – kos
            May 11 '15 at 20:10




            2




            2




            I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
            – Eliah Kagan
            May 11 '15 at 21:18




            I think this is actually quite practical, though I may be biased: it's the same method I used. Your implementation and presentation are quite different though--this is definitely a valuable answer. Whereas I used mkpasswd to generate a hash from user input and the existing salt (and included additional features and diagnostics), you've instead coded a simple Python program implementing mkpasswd's most important functionality and used that. I recommend you set IFS= when reading password input, and quote ${password} with ", so password attempts with whitespace don't break the script.
            – Eliah Kagan
            May 11 '15 at 21:18


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Ask Ubuntu!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f611580%2fhow-to-check-the-password-entered-is-a-valid-password-for-this-user%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            數位音樂下載

            When can things happen in Etherscan, such as the picture below?

            格利澤436b