Re: Validating A User/Password Pair + Getting Groups On Unix
On Tue, 1 Mar 2005 09:45:26 -0600, Skip Montanaro [EMAIL PROTECTED] wrote: 1) Validate that the password is correct for that user *without actually logging in*. Kanenas The 'pwd' module probably won't be able (and won't try) to read Kanenas the shadow password file, so 'pwd' won't be of use. Note that an spwd module was recently added to Python's CVS repository. I imagine it will be in 2.5. Skip It turns out 'pwd' uses the system 'getpwuid' and 'getpwnam' rather than parsing /etc/passwd, so it can get the encrypted password if the getpw* functions read the shadow passwd and the Python process has EUID 0 (or whatever access rights getpw* use to determine when to return the encrypted passwd). I misread (was misled by?) the 'pwd' documentation: However most modern unices use a so-called shadow password system. On those unices the field pw_passwd only contains a asterisk ('*') or the letter x where the encrypted password is stored in a file /etc/shadow which is not world readable. This is true if the getpw* don't read from the shadow passwd, which is the case for Solaris and Linux. Linux and Solaris use getsp*, which 'spwd' is based on, to manage the shadow passwd. On OpenBSD and FreeBSD, getpw* read from the shadow passwd and the getsp* don't exist. In summation, use 'pwd' to retrieve encrypted password on OpenBSD and FreeBSD (and others?), 'spwd' on Linux and Solaris (and others?). Assuming one goes this route. -- Kanenas -- http://mail.python.org/mailman/listinfo/python-list
Re: Validating A User/Password Pair + Getting Groups On Unix
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 'pwd' module probably won't be able (and won't try) to read the shadow password file, so 'pwd' won't be of use. 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. The best approach may be to write 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. The process that calls the authentication functions will probably need 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, auth_userokay calls getpwnam, which 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 passwd entry. 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. 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: http://www.python.org/doc/2.4/lib/module-grp.html http://www.python.org/doc/2.4/lib/module-pwd.html 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
Re: Validating A User/Password Pair + Getting Groups On Unix
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
Re: Decimal, __radd__, and custom numeric types...
On 28 Feb 2005 12:11:33 -0800, Blake T. Garretson [EMAIL PROTECTED] wrote: [...] From the Python docs (specifically sections 3.3.7 and 3.3.8), I thought that the left object should try its own __add__, and if it doesn't know what to do, THEN try the right object's __radd__ method. To me it reads more like the interpreter is responsible for picking which method to call. Specifically, section 3.3.8 of the reference manual states that y.__rop__() will be called if x.__op__() is not implemented or returns NotImplemented. The decision to call y.__rop__() is made outside the x.__op__() method, implying that x.__op__() doesn't handle a call to y.__rop__() in this case. The other rules dealing with whether x.__op__() or y.__rop__() is called don't apply to your situation (but they could, keep reading). I guess Decimal objects don't do this? Is there a way to change this behavior? If Decimal objects prematurely throw a TypeError before trying the __rop__, is Decimal broken, or was it designed this way? I think I'm missing something... You could change the behavior of Decimal.__add__ by patching it or you could use subclassing. If your classes are subclasses of Decimal, their __rop__ methods will be called before Decimal.__op__ is tried. I'm guessing your matrix and rational classes don't use decimal representation, which makes this an OOP style-breaking kludge. -- http://mail.python.org/mailman/listinfo/python-list
Re: deepcopy chokes with TypeError on dynamically assigned instance method
On Sun, 13 Feb 2005 12:01:42 +1000, Nick Coghlan [EMAIL PROTECTED] wrote: True. It wouldn't cause a problem within my __init__, since the attribute is reassigned after the deepcopy, though should anyone else deepcopy an instance... Definitely better that the deepcopy throws the TypeError. But why shouldn't we be able to copy a non-method function? I honestly don't know, although I'm hard-pressed to see how doing so would ever be *useful*. Duplicating *parts* of a function would seem to make sense (to build a new function which is similar, but not identical), but duplicating the whole thing seems rather pointless. Although I guess you could just pickle it and then unpickle the result to make a copy :) It's not so much that copying a function is useful as it would be nice if copy and deepcopy didn't fail on plain functions, as there are cases where objects would need to store references to such functions. Imagine classes implementing operations on functions such as numeric differentiation and integration (while symbolic differentiation integration would probably be better for production code, the example still stands). As it is, a little extra work would be needed to support deepcopying such classes. And it's always nice to avoid work. Thanks for your help and feedback on this. -- http://mail.python.org/mailman/listinfo/python-list
Re: deepcopy chokes with TypeError on dynamically assigned instance method
On Thu, 10 Feb 2005 23:50:09 +1000, Nick Coghlan [EMAIL PROTECTED] wrote: def __init__(self, l=[]): Change this too: def __init__(self, l=None): if l is None: l = [] Same error. The only ways of not getting the TypeError I've found are not to call deepcopy or not assign an instancemethod to an instance attribute (assigning an instancemethod to a class attribute is fine). -- http://mail.python.org/mailman/listinfo/python-list
Re: deepcopy chokes with TypeError on dynamically assigned instance method
On Thu, 10 Feb 2005 00:54:04 -0800, Kanenas kanenas @t comcast d.t net wrote: When an instance has a dynamically assigned instance method, deepcopy throws a TypeError with the message TypeError: instancemethod expected at least 2 arguments, got 0. I forgot to mention that the TypeError is thrown only when constructing an instance from another instance in the same class, e.g. Foo('bar') is fine but Foo(Foo('bar')) will fail. -- http://mail.python.org/mailman/listinfo/python-list