Code

added "crypt" password encoding and ability to set password with
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 26 Sep 2002 07:39:21 +0000 (07:39 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 26 Sep 2002 07:39:21 +0000 (07:39 +0000)
already encrypted password through roundup-admin

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1263 57a73879-2fb5-44c3-a270-3262357dd7e2

roundup/admin.py
roundup/password.py

index ff961b77eb63c50084f049ff32a7d8835e20ba46..86047930343885667ef2f73bb4c923bfb73a25f8 100644 (file)
@@ -16,7 +16,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: admin.py,v 1.32 2002-09-24 01:36:04 richard Exp $
+# $Id: admin.py,v 1.33 2002-09-26 07:39:21 richard Exp $
 
 import sys, os, getpass, getopt, re, UserDict, shlex, shutil
 try:
@@ -397,7 +397,7 @@ Command help:
         return 0
 
 
-    def do_set(self, args):
+    def do_set(self, args, pwre = re.compile(r'{(\w+)}(.+)')):
         '''Usage: set [items] property=value property=value ...
         Set the given properties of one or more items(s).
 
@@ -447,7 +447,15 @@ Command help:
                 elif isinstance(proptype, hyperdb.String):
                     continue
                 elif isinstance(proptype, hyperdb.Password):
-                    props[key] = password.Password(value)
+                    m = pwre.match(value)
+                    if m:
+                        # password is being given to us encrypted
+                        p = password.Password()
+                        p.scheme = m.group(1)
+                        p.password = m.group(2)
+                        props[key] = p
+                    else:
+                        props[key] = password.Password(value)
                 elif isinstance(proptype, hyperdb.Date):
                     try:
                         props[key] = date.Date(value)
@@ -469,6 +477,7 @@ Command help:
             try:
                 apply(cl.set, (itemid, ), props)
             except (TypeError, IndexError, ValueError), message:
+                import traceback; traceback.print_exc()
                 raise UsageError, message
         return 0
 
index 1caa8a83438c2cc8506078d48ddf78dcee5b293e..0ba2c5e39f3c7d3b37ffa83c95297e27d2679907 100644 (file)
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: password.py,v 1.5 2002-09-10 00:18:20 richard Exp $
+# $Id: password.py,v 1.6 2002-09-26 07:39:21 richard Exp $
 
 __doc__ = """
 Password handling (encoding, decoding).
 """
 
-import sha, re
+import sha, re, string
+try:
+    import crypt:
+except:
+    crypt = None
+    pass
 
-def encodePassword(plaintext, scheme):
+def encodePassword(plaintext, scheme, other=None):
     '''Encrypt the plaintext password.
     '''
     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
     return s
@@ -60,8 +72,10 @@ class Password:
     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
@@ -82,22 +96,25 @@ class Password:
             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
+                return cmp(self.scheme, other.scheme)
             return cmp(self.password, other.password)
 
         # assume password is plaintext
         if self.password is None:
             raise ValueError, 'Password not set'
-        return cmp(self.password, encodePassword(other, self.scheme))
+        return cmp(self.password, encodePassword(other, self.scheme,
+            self.password))
 
     def __str__(self):
         '''Stringify the encrypted password for database storage.'''
@@ -106,12 +123,20 @@ class Password:
         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()