Welcome, guest | Sign In | My Account | Store | Cart

Sometimes it's useful to perform System Authentication against a Local System using the /etc/shadow or /etc/passwd password databases. This recipe provides a simple function that does exactly that.

Python, 34 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python

from os import path
from crypt import crypt
from re import compile as compile_regex


def check_auth(user, password):
    """Perform authentication against the local systme.

    This function will perform authentication against the local system's
    /etc/shadow or /etc/passwd database for a given user and password.

    :param user: The username to perform authentication with
    :type user: str

    :param password: The password (plain text) for the given user
    :type password: str

    :returns: True if successful, None otherwise.
    :rtype: True or None
    """

    salt_pattern = compile_regex(r"\$.*\$.*\$")
    passwd = "/etc/shadow" if path.exists("/etc/shadow") else "/etc/passwd"

    with open(passwd, "r") as f:
        rows = (line.strip().split(":") for line in f)
        records = [row for row in rows if row[0] == user]

    hash = records and records[0][1]
    salt = salt_pattern.match(hash).group()

    return crypt(password, salt) == hash

2 comments

Oren Tirosh 8 years, 6 months ago  # | flag

You can use the pwd/spwd built-in modules instead of accessing /etc files directly. This will also work with LDAP authentication, for example.

No need to split the salt from the salted password - crypt is happy to accept the complete salted password as the second parameter.

James Mills (author) 8 years, 6 months ago  # | flag

@Oren: Yes you are quite right of course! I'll fork this Recipe to utilize pwd/spwg instead. I posted this based on old code I had lying around before spwd module was available in the Python std. lib (2.5). --JamesMills / prologic