On 28 Feb 2005 20:17:58 EST, Tim Daneliuk <[EMAIL PROTECTED]> wrote: [...] >Given a username and a password (plain text): > > 1) Validate that the password is correct for that user *without actually > logging in*. > The naive solution is to use the 'crypt' module to encrypt the alleged password, use 'pwd.getpwuid' or 'pwd.getpwnam' to get the user's encrypted password (assuming the python process has appropriate access privileges) and compare the two. This is naive in that: * 'pwd.getpw*' may not retrieve the encrypted password even though the current process has appropriate access privileges * the password may be for an encryption or authentication scheme other than that provided by 'crypt'. Using the local authentication scheme shouldn't have these shortcomings.
There may not be a Python module which handles your local authentication scheme (there's a 'krb5' module for Kerberos authentication), so you may need to write one. This could be done by an extension module in C or C++ which wraps around whatever local authentication functions are appropriate (e.g. a 'pam' module for PAM, an 'auth' module for BSD). You'd only need to wrap the functions needed for simple pass/fail authentication (e.g. 'auth_userokay'), but the other functions could easily be added to the extension later if needed. If you're not sure what authentication scheme your system uses, try `man -s 3 authenticate` or examine "/usr/src/usr.bin/login/login.c". Whichever approach you use, the process that calls the authentication functions needs special access privileges so that the functions can succesfully accept or reject the password. The man pages for the authentication functions should have details. For example, 'getpwnam' (used by 'auth_userokay' and the 'pwd' module) requires the effective uid to be 0 (or, on some systems, the user to be in the "_shadow" group) for it to include the encrypted password in the returned passwd entry. 'crypt' and 'pwd' modules: http://www.python.org/doc/2.4/lib/module-crypt.html http://www.python.org/doc/2.4/lib/module-pwd.html extending Python: http://www.python.org/doc/2.4/ext/ext.html Python/C API: http://www.python.org/doc/2.4/api/api.html Information on Linux-PAM http://www.kernel.org/pub/linux/libs/pam/ You could even add support for the full authentication API to your module and contribute the extension to the Python community. http://www.python.org/download/Contributed.html. > 2) If the password is valid, return a list of all the groups the user > belongs to. > Otherwise, return some error string. > [...] >I can do 2) by brute force - just parse through /etc/group - but this >misses the primary group a given user may belong to - and that requires >also scanning /etc/passwd and then looking up the corresponding primary >group in /etc/group. Is there a better way? > Slightly better would be to use the 'grp' and 'pwd' modules. One advantage of this is it should support networked user databases (such as YP). http://www.python.org/doc/2.4/lib/module-grp.html http://www.python.org/doc/2.4/lib/module-pwd.html If you've grabbed the password entry for a user during authentication, you've already got the login group but you'll still need to check for additional groups. You could create a dictionary which maps user names or IDs to groups. This would still require processing all groups (via 'grp.getpwall()'), but is more efficient if you need to fetch the groups of more than one user in the life of the process (from the outline, I'm guessing this will only be the case if the program is a server of some sort). Just make sure you have a method to re-process the group database into the group dictionary in case the group file changes. Even better would be to write an extension or add to the grp module to wrap around local group database access functions (e.g. getgrouplist). See the 'getgrouplist' man page for more information and examine the source of the `groups` command (probably "/usr/src/usr.bin/groups/groups.c") or `id` command (should be "/usr/src/usr.bin/id/id.c") for other group DB access functions. You could also call the `groups` command via 'os.popen(...)'. -- http://mail.python.org/mailman/listinfo/python-list