Checking user password linux

How to check password with Linux?

I want to check, from the linux command line, if a given cleartext password is the same of a crypted password on a /etc/shadow (I need this to authenticate web users. I’m running an embedded linux.) I have access to the /etc/shadow file itself.

9 Answers 9

You can easily extract the encrypted password with awk. You then need to extract the prefix $algorithm$salt$ (assuming that this system isn’t using the traditional DES, which is strongly deprecated because it can be brute-forced these days).

For password checking, the underlying C function is crypt , but there’s no standard shell command to access it.

On the command line, you can use a Perl one-liner to invoke crypt on the password.

supplied=$(echo "$password" | perl -e '$_ = ; chomp; print crypt($_, $ARGV[0])' "$prefix") if [ "$supplied" = "$correct" ]; then … 

Since this can’t be done in pure shell tools, if you have Perl available, you might as well do it all in Perl. (Or Python, Ruby, … whatever you have available that can call the crypt function.) Warning, untested code.

#!/usr/bin/env perl use warnings; use strict; my @pwent = getpwnam($ARGV[0]); if (!@pwent) my $supplied = ; chomp($supplied); if (crypt($supplied, $pwent[1]) eq $pwent[1]) < exit(0); >else

On an embedded system without Perl, I’d use a small, dedicated C program. Warning, typed directly into the browser, I haven’t even tried to compile. This is meant to illustrate the necessary steps, not as a robust implementation!

/* Usage: echo password | check_password username */ #include #include #include #include #include #include int main(int argc, char *argv[]) < char password[100]; struct spwd shadow_entry; char *p, *correct, *supplied, *salt; if (argc < 2) return 2; /* Read the password from stdin */ p = fgets(password, sizeof(password), stdin); if (p == NULL) return 2; *p = 0; /* Read the correct hash from the shadow entry */ shadow_entry = getspnam(username); if (shadow_entry == NULL) return 1; correct = shadow_entry->sp_pwdp; /* Extract the salt. Remember to free the memory. */ salt = strdup(correct); if (salt == NULL) return 2; p = strchr(salt + 1, '$'); if (p == NULL) return 2; p = strchr(p + 1, '$'); if (p == NULL) return 2; p[1] = 0; /*Encrypt the supplied password with the salt and compare the results*/ supplied = crypt(password, salt); if (supplied == NULL) return 2; return !!strcmp(supplied, correct); > 

A different approach is to use an existing program such as su or login . In fact, if you can, it would be ideal to arrange for the web application to perform whatever it needs via su -c somecommand username . The difficulty here is to feed the password to su ; this requires a terminal. The usual tool to emulate a terminal is expect, but it’s a big dependency for an embedded system. Also, while su is in BusyBox, it’s often omitted because many of its uses require the BusyBox binary to be setuid root. Still, if you can do it, this is the most robust approach from a security point of view.

Читайте также:  Astra linux directory доверительные отношения

Have a look at man 5 shadow and man 3 crypt . From the latter, you can learn that password hashes in /etc/shadow have the following form:

where id defines the type of encryption and, reading further, can be one of

 ID | Method --------------------------------------------------------- 1 | MD5 2a | Blowfish (not in mainline glibc; added in some | Linux distributions) 5 | SHA-256 (since glibc 2.7) 6 | SHA-512 (since glibc 2.7) 

Depending on the type of hash, you need to use the appropriate function/tool for generating and verifying the password «by hand». If the system contains mkpasswd program, you can use it as suggested here. (You take the salt from the shadow file, if that wasn’t obvious.) For example, with md5 passwords :

will generate the string that should match /etc/shadow entry.

On my Debian wheezy I had a completely different syntax for the command mkpasswd , which I had to install using apt-get install whois . The command line for the shadow line :$6$$: was mkpasswd -msha-512

#!/bin/bash # # login.sh $USERNAME $PASSWORD #this script doesn't work if it is run as root, since then we don't have to specify a pw for 'su' if [ $(id -u) -eq 0 ]; then echo "This script can't be run as root." 1>&2 exit 1 fi if [ ! $# -eq 2 ]; then echo "Wrong Number of Arguments (expected 2, got $#)" 1>&2 exit 1 fi USERNAME=$1 PASSWORD=$2 #since we use expect inside a bash-script, we have to escape tcl-$. expect  < exit [lindex \$wait_result 3] >else < exit 1 >EOF 

Bear in mind that, assuming the system is properly configured, the program will need to be run as root.

A better solution than reading the shadow file directly and writing your own code around crypt would be to just use the pam bindings.

The squid tarball used to come with a simple CLI tool for verifying usernames/passwords using stdio — so simple to adapt to using arguments — although the version I hacked previously was hardly a pin-up poster for structured programming. A quick google and it looks like the more recent versions have been cleaned up significantly but still a few ‘goto’s in there.

The C code of the person I’m responding to has bugs. Never understand why people publish code here without checking it works first, because there’s ALWAYS bugs. Not like I don’t have to check my code. Largest file I’ve ever made without a (syntax) bug on the first try was 1000 lines, and that’s in 30 years of experience.

Читайте также:  Linux меняет время windows

I’ve tested this under KDE Neon, it needs to be run as root because you need elevated privileges to read /etc/shadow or the user calling it needs to belong to the «shadow» group (that’s the group that /etc/shadow belongs to). It takes the username as an argument.

#define _GNU_SOURCE #include #include #include #include #include #include #include #define DBG() \ do < \ char buf[100]; \ sprintf (buf, "error: %d\n", __LINE__); \ perror (buf); \ >while (0) void chomp (char *str) < while (*str != '\0' && *str != '\n') < str++; >*str = '\0'; > int main(int argc, char *argv[]) < char password[100]; struct spwd *shadow_entry; char *p, *correct, *supplied, *salt; if (argc < 2) < DBG (); return 2; >/* Read the password from stdin */ p = fgets(password, sizeof(password), stdin); if (p == NULL) < DBG (); return 2; >//*p = 0; - this was a pretty obvious error chomp (p); // this is what was intended above printf ("password = %s\n", p); /* Read the correct hash from the shadow entry */ shadow_entry = getspnam( argv[1] ); if (shadow_entry == NULL) < DBG (); return 1; >correct = shadow_entry->sp_pwdp; /* Extract the salt. Remember to free the memory. */ salt = strdup(correct); if (salt == NULL) < DBG (); return 2; >p = strchr(salt + 1, '$'); if (p == NULL) < DBG (); return 2; >p = strchr(p + 1, '$'); if (p == NULL) < DBG (); return 2; >p[1] = 0; /*Encrypt the supplied password with the salt and compare the results*/ supplied = crypt(password, salt); if (supplied == NULL) < DBG (); return 2; >if (strcmp(supplied, correct) == 0) < printf ("pass\n %s\n %s\n", supplied, correct); return (0); >else < printf ("fail\n %s\n %s\n", supplied, correct); return (1); >> 

You can remove the printf functions and remove calls to DBG(); but both are useful until you can verify that the program is working properly. I had to add them in to see how and where it was failing. Every error exit should be a different number as well, but that’s just me being anal retentive.

Источник

check password linux user

I am on debian 9. I have a problem to check the password of a linux user in my scripts. I realized that the different linux tools for creating and modifying a user password gave results of different pattern in /etc/shadow To create a user

pwLinux="abcdef1234" userLinux="toto02" pwCrypt=$(perl -e 'print crypt($ARGV[0], "zzz")' $pwLinux) useradd -m -G adm,dip,plugdev,www-data,sudo -p $pwCrypt $userLinux 
toto02:zzDxrNjXuUs3U:17469:0:99999:7. 
USERNAME="toto02" PASSWD="abcdef1234" ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2` ORIGPASS=`echo $ORIGPASS | cut -d"$" -f2` GENPASS=$(perl -e 'print crypt($ARGV[0], "zzz")' $PASSWD) if [ "$GENPASS" == "$ORIGPASS" ]; then echo "Valid Password" exit 0 else echo "Invalid Password" exit 1 fi 
# username "toto02", newPwd "aabbcc" echo "$:$" | chpasswd 
toto02:$6$rLklwx9K$Brv4lvNjR.S7f8i.Lmt8.iv8pgcbKhwDgINzhT1XwCBbD7XkB98lCtwUK3/4hdylkganoLuh/eIc38PtMArgZ/:17469:0:99999:7. 

If i want to check this password i must use a different script.
First problem how to have the same pattern of password in both cases? i use:

#!/bin/bash USERNAME="toto02" PASSWD="aabbcc" ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2` export ALGO=`echo $ORIGPASS | cut -d"$" -f2` export SALT=`echo $ORIGPASS | cut -d"$" -f3` echo "algo: -$ALGO-" echo "salt: -$SALT-" echo "pwd entré: -$PASSWD-" echo "shadow: -$ORIGPASS-" GENPASS="$(perl -e 'print crypt("$ENV","\$$ENV\$$ENV\$")')" echo "pwd généré: -$GENPASS-" if [ "$GENPASS" == "$ORIGPASS" ]; then echo "Valid Password" exit 0 else echo "Invalid Password" exit 1 fi 
algo: -6- salt: -rLklwx9K- pwd entré: -aabbcc- shadow: -$6$rLklwx9K$Brv4lvNjR.S7f8i.Lmt8.iv8pgcbKhwDgINzhT1XwCBbD7XkB98lCtwUK3/4hdylkganoLuh/eIc38PtMArgZ/- pwd généré: -$6$rLklwx9K$AIX1bUMAK9bwdd2g3ST5VtXTvHlHXHxnh4Xj.fLdxjaEkAAvHeeN5islid0wtmZN5u1zWQBup./IP8IH9i6W7/- Invalid Password 

Источник

Читайте также:  Linux scripting if exist

Check username/password in Linux without root

If I have a username and password pair how can I verify that they are actually correct in a Linux system? I know I can use passwd to do so but I want to do it programatically using C. I should not require root privileges (so reading the shadow file is not an option). Thank you.

@Stargateur I see no problem with that. It can be a kernel-mode driver or syscall to service that function.

2 Answers 2

If you are using a PAM , you might be able to make use of checkpassword-pam .

The manual has an example command (with debugging) which should give you a good place to start.

echo -e "username\0password\0timestamp\0" \ | checkpassword-pam -s SERVICE \ --debug --stdout -- /usr/bin/id 3 

I see that the function doing the check is authenticate_using_pam (const char* service_name, const char* username, const char* password) What should be the service_name parameter there? AFAIK at least to install a PAM module you need to be root. Don't you to use that API?

This is a simple example to check the password with some python code. No root privilegs are needed.

#!/usr/bin/python3 # simple linux password checker with # standard python import os, pty def check_pass(user, passw): # returns: 0 if check ok # 1 check failed # 2 account locked if type(passw) is str: passw = passw.encode() pid, fd = pty.fork() # try to su a fake shell which returns '-c OK' on ok if not pid: # child argv = ('su', '-c', 'OK', '-s', '/bin/echo', user) os.execlp(argv[0], *argv) return # SHOULD NEVER REACHED okflg = False locked = False while True: try: data = os.read(fd, 1024) ##print('data:', data, flush=True) except OSError: break if not data: break data = data.strip() if data == b'Password:': os.write(fd, passw + b'\r\n') elif data.endswith(b'OK'): okflg = True break elif data.find(b'locked') > -1: # show that account is locked locked = True print(data, flush=True) break os.close(fd) # check result from su and okflg if (not os.waitpid(pid, 0)[1]) and okflg: return 0 return 2 if locked else 1 if __name__ == '__main__': print(check_pass('xx', 'yy')) 

Источник

Оцените статью
Adblock
detector