diff --git a/roundup/password.py b/roundup/password.py
index cc76c31b7edb0c6b00834bc2911bba5c740cac7c..a267e4223a211dc54d7fca773943cf3d519d76f1 100644 (file)
--- a/roundup/password.py
+++ b/roundup/password.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: password.py,v 1.1 2001-10-09 07:25:59 richard Exp $
+# $Id: password.py,v 1.11 2004-02-11 23:55:08 richard Exp $
-import sha, re
+"""Password handling (encoding, decoding).
+"""
+__docformat__ = 'restructuredtext'
-def encodePassword(plaintext, scheme):
+import sha, re, string, random
+try:
+ import crypt
+except:
+ crypt = None
+ pass
+
+class PasswordValueError(ValueError):
+ ''' The password value is not valid '''
+ pass
+
+def encodePassword(plaintext, scheme, other=None):
'''Encrypt the plaintext password.
'''
+ if plaintext is None:
+ plaintext = ""
if scheme == 'SHA':
s = sha.sha(plaintext).hexdigest()
+ elif scheme == 'crypt' and crypt is not None:
+ if other is not None:
+ salt = other[:2]
+ else:
+ saltchars = './0123456789'+string.letters
+ salt = random.choice(saltchars) + random.choice(saltchars)
+ s = crypt.crypt(plaintext, salt)
elif scheme == 'plaintext':
- pass
+ s = plaintext
else:
- raise ValueError, 'Unknown encryption scheme "%s"'%scheme
+ raise PasswordValueError, 'unknown encryption scheme %r'%scheme
return s
+def generatePassword(length=8):
+ chars = string.letters+string.digits
+ return ''.join([random.choice(chars) for x in range(length)])
+
class Password:
'''The class encapsulates a Password property type value in the database.
default_scheme = 'SHA' # new encryptions use this scheme
pwre = re.compile(r'{(\w+)}(.+)')
- def __init__(self, plaintext=None):
+ def __init__(self, plaintext=None, scheme=None):
'''Call setPassword if plaintext is not None.'''
+ if scheme is None:
+ scheme = self.default_scheme
if plaintext is not None:
self.password = encodePassword(plaintext, self.default_scheme)
self.scheme = self.default_scheme
self.password = m.group(2)
else:
# currently plaintext - encrypt
- self.password = encodePassword(plaintext, self.default_scheme)
+ self.password = encodePassword(encrypted, self.default_scheme)
self.scheme = self.default_scheme
- def setPassword(self, plaintext):
+ def setPassword(self, plaintext, scheme=None):
'''Sets encrypts plaintext.'''
- self.password = encodePassword(plaintext, self.scheme)
+ if scheme is None:
+ scheme = self.default_scheme
+ self.password = encodePassword(plaintext, scheme)
+
+ def __cmp__(self, other):
+ '''Compare this password against another password.'''
+ # check to see if we're comparing instances
+ if isinstance(other, Password):
+ if self.scheme != other.scheme:
+ return cmp(self.scheme, other.scheme)
+ return cmp(self.password, other.password)
- def __cmp__(self, plaintext):
- '''Compare this password against the plaintext.'''
+ # assume password is plaintext
if self.password is None:
raise ValueError, 'Password not set'
- return cmp(self.password, encodePassword(plaintext, self.scheme))
+ return cmp(self.password, encodePassword(other, self.scheme,
+ self.password))
def __str__(self):
'''Stringify the encrypted password for database storage.'''
return '{%s}%s'%(self.scheme, self.password)
def test():
+ # SHA
p = Password('sekrit')
assert p == 'sekrit'
assert p != 'not sekrit'
assert 'sekrit' == p
assert 'not sekrit' != p
+ # crypt
+ p = Password('sekrit', 'crypt')
+ assert p == 'sekrit'
+ assert p != 'not sekrit'
+ assert 'sekrit' == p
+ assert 'not sekrit' != p
+
if __name__ == '__main__':
test()
-#
-# $Log: not supported by cvs2svn $
-#
-#
# vim: set filetype=python ts=4 sw=4 et si