How to check the password entered is a valid password for this user?
up vote
12
down vote
favorite
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
add a comment |
up vote
12
down vote
favorite
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
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 onexpect
at stackoverflow.com/a/1503831/320594.
– Jaime Hablutzel
Feb 1 at 16:25
add a comment |
up vote
12
down vote
favorite
up vote
12
down vote
favorite
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
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
bash
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 onexpect
at stackoverflow.com/a/1503831/320594.
– Jaime Hablutzel
Feb 1 at 16:25
add a comment |
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 onexpect
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
add a comment |
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 themkpasswd
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 runchkpass user
and it will read a line from standard input and check if it'suser
's password. - Install the 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.
add a comment |
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
orrunaspw
is set
listpw
isnever
- 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 havesudo
privileges so that you can runsudo -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.
2
This way looks excellent. Though it won't work on systems with uncommonsudo
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 settingIFS=
forread
, 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 bashismsread -s
and&>
, usingif 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 thoughtsudo -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
add a comment |
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
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 casegetent
+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 usedmkpasswd
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 implementingmkpasswd
's most important functionality and used that. I recommend you setIFS=
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
|
show 1 more comment
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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 themkpasswd
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 runchkpass user
and it will read a line from standard input and check if it'suser
's password. - Install the 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.
add a comment |
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 themkpasswd
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 runchkpass user
and it will read a line from standard input and check if it'suser
's password. - Install the 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.
add a comment |
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 themkpasswd
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 runchkpass user
and it will read a line from standard input and check if it'suser
's password. - Install the 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.
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 themkpasswd
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 runchkpass user
and it will read a line from standard input and check if it'suser
's password. - Install the 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.
edited May 11 '15 at 21:01
answered May 10 '15 at 21:01
Eliah Kagan
81.1k20227364
81.1k20227364
add a comment |
add a comment |
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
orrunaspw
is set
listpw
isnever
- 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 havesudo
privileges so that you can runsudo -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.
2
This way looks excellent. Though it won't work on systems with uncommonsudo
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 settingIFS=
forread
, 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 bashismsread -s
and&>
, usingif 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 thoughtsudo -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
add a comment |
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
orrunaspw
is set
listpw
isnever
- 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 havesudo
privileges so that you can runsudo -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.
2
This way looks excellent. Though it won't work on systems with uncommonsudo
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 settingIFS=
forread
, 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 bashismsread -s
and&>
, usingif 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 thoughtsudo -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
add a comment |
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
orrunaspw
is set
listpw
isnever
- 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 havesudo
privileges so that you can runsudo -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.
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
orrunaspw
is set
listpw
isnever
- 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 havesudo
privileges so that you can runsudo -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.
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 uncommonsudo
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 settingIFS=
forread
, 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 bashismsread -s
and&>
, usingif 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 thoughtsudo -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
add a comment |
2
This way looks excellent. Though it won't work on systems with uncommonsudo
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 settingIFS=
forread
, 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 bashismsread -s
and&>
, usingif 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 thoughtsudo -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
add a comment |
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
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 casegetent
+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 usedmkpasswd
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 implementingmkpasswd
's most important functionality and used that. I recommend you setIFS=
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
|
show 1 more comment
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
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 casegetent
+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 usedmkpasswd
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 implementingmkpasswd
's most important functionality and used that. I recommend you setIFS=
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
|
show 1 more comment
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
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
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 casegetent
+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 usedmkpasswd
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 implementingmkpasswd
's most important functionality and used that. I recommend you setIFS=
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
|
show 1 more comment
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 casegetent
+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 usedmkpasswd
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 implementingmkpasswd
's most important functionality and used that. I recommend you setIFS=
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
|
show 1 more comment
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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