Re: Validating A User/Password Pair + Getting Groups On Unix

2005-03-01 Thread Kanenas
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

2005-02-28 Thread Kanenas
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

2005-02-28 Thread Kanenas
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...

2005-02-28 Thread Kanenas
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

2005-02-15 Thread Kanenas
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

2005-02-10 Thread Kanenas
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

2005-02-10 Thread Kanenas
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