Search code examples
python-3.xlinuxsubprocesscgi

authenticate a user from local linux host using python script


I want to authenticate a user from a local linux host using subprocess. I have used this code and i doubt login is the perfect command to do because login command prompts for password and I want to provide the password upfront. login man

If not login then is there any other linux command through which I can authenticate a local user ?

#!/usr/bin/python3
import subprocess
import cgi

print()

cred = cgi.FieldStorage()

username = cred.getvalue("user")
password = cred.getvalue("password")

# print(username)
# print(password)

cmd = f"echo {password} | sudo /usr/bin/login {username}"
# cmd = "ls -la"

print(cmd)

output = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, text=True)

print(output)


This is the output I am getting as of now.

CompletedProcess(args='echo ashu234 | sudo /usr/bin/login ashu', returncode=1, stdout='')

Solution

  • You can use pexpect. Unless you are running your script as root you will need to supply a password to sudo (as you will have to for any answer that uses sudo). To make the script more portable also supply a sudo user name but you could hard code this if using root. This code was written for Ubuntu 21.10 and may need the strings updating for other distributions. I think the code is self-explanatory, you spawn a process, interact with it and expect certain responses during exection.

    import pexpect
    
    sudo_user = 'whatever your sudo user name is'
    sudo_password = "whatever your sudo user password is"
    user_name = "whatever local user name is"
    password = "whatever local user password is"
    
    child = pexpect.spawn(f'/usr/bin/sudo /usr/bin/login {user_name}', encoding='utf-8')
    child.expect_exact(f'[sudo] password for {sudo_user}: ')
    child.sendline(sudo_password)
    return_code = child.expect(['Sorry, try again', 'Password: '])
    if return_code == 0:
        print('Can\'t sudo')
        print(child.after)  # debug
        child.kill(0)
    else:
        child.sendline(password)
        return_code = child.expect(['Login incorrect', '[#\\$] '])
        if return_code == 0:
            print('Can\'t login')
            print(child.after)  # debug
            child.kill(0)
        elif return_code == 1:
            print('Login OK.')
            print('Shell command prompt', child.after)
    

    For more detail see the docs https://pexpect.readthedocs.io/en/stable/overview.html