[Zope-Checkins] CVS: Zope/lib/python/AccessControl - AuthEncoding.py:1.3 User.py:1.155

Shane Hathaway shane@digicool.com
Mon, 10 Sep 2001 14:29:56 -0400


Update of /cvs-repository/Zope/lib/python/AccessControl
In directory cvs.zope.org:/tmp/cvs-serv23739

Modified Files:
	AuthEncoding.py User.py 
Log Message:
Added user password encryption capability, fulfilling the needs
described in the proposal at:
http://dev.zope.org/Wikis/DevSite/Proposals/EncryptedUserfolderPasswords
There is now a "properties" tab in user folders where you can
select whether passwords are stored encrypted.  The only question is
whether it should be initially on or off.


=== Zope/lib/python/AccessControl/AuthEncoding.py 1.2 => 1.3 ===
     return result
 
-def pw_encode(pw, encoding='SHA'):
-    """Encode the provided plain text password using the encoding if provided
+def is_encrypted(pw):
+    return pw[:5] == '{SHA}' or pw[:7] == '{CRYPT}'
+
+def pw_encrypt(pw, encoding='SHA'):
+    """Encrypt the provided plain text password using the encoding if provided
     and return it in an LDAP-style representation."""
+    if encoding == 'SHA':
+        return '{SHA}' + binascii.b2a_base64(sha.new(pw).digest())[:-1]
+    else:
+        raise ValueError, 'Not supported: %s' % encoding
 
-    pass
+pw_encode = pw_encrypt  # backward compatibility


=== Zope/lib/python/AccessControl/User.py 1.154 => 1.155 ===
 from Role import RoleManager
 from PermissionRole import _what_not_even_god_should_do, rolesForPermissionOn
-from AuthEncoding import pw_validate
+import AuthEncoding
 from AccessControl import getSecurityManager, Unauthorized
 from AccessControl.SecurityManagement import newSecurityManager
 from AccessControl.SecurityManagement import noSecurityManager
@@ -192,7 +192,7 @@
     
     def authenticate(self, password, request):
         passwrd=self._getPassword()
-        result = pw_validate(passwrd, password)
+        result = AuthEncoding.pw_validate(passwrd, password)
         domains=self.getDomains()
         if domains:
             return result and domainSpecMatch(domains, request)
@@ -480,10 +480,14 @@
     isPrincipiaFolderish=1
     isAUserFolder=1
 
+    encrypt_passwords = 0
+
     manage_options=(
         (
         {'label':'Contents', 'action':'manage_main',
          'help':('OFSP','User-Folder_Contents.stx')},
+        {'label':'Properties', 'action':'manage_userFolderProperties',
+         'help':('OFSP','User-Folder_Properties.stx')},
         )
         +RoleManager.manage_options
         +Item.manage_options
@@ -750,6 +754,51 @@
     manage=manage_main=_mainUser
     manage_main._setName('manage_main')
 
+    _userFolderProperties = DTMLFile('dtml/userFolderProps', globals())
+
+    def manage_userFolderProperties(self, REQUEST=None,
+                                    manage_tabs_message=None):
+        """
+        """
+        return self._userFolderProperties(
+            self, REQUEST, manage_tabs_message=manage_tabs_message,
+            management_view='Properties')
+
+    def manage_setUserFolderProperties(self, encrypt_passwords=0,
+                                       update_passwords=0, REQUEST=None):
+        """
+        Sets the properties of the user folder.
+        """
+        self.encrypt_passwords = not not encrypt_passwords
+        if encrypt_passwords and update_passwords:
+            changed = 0
+            for u in self.getUsers():
+                pw = u._getPassword()
+                if not self._isPasswordEncrypted(pw):
+                    pw = self._encryptPassword(pw)
+                    self._doChangeUser(u.getUserName(), pw, u.getRoles(),
+                                       u.getDomains())
+                    changed = changed + 1
+            if REQUEST is not None:
+                if not changed:
+                    msg = 'All passwords already encrypted.'
+                else:
+                    msg = 'Encrypted %d password(s).' % changed
+                return self.manage_userFolderProperties(
+                    REQUEST, manage_tabs_message=msg)
+            else:
+                return changed
+        else:
+            if REQUEST is not None:
+                return self.manage_userFolderProperties(
+                    REQUEST, manage_tabs_message='Saved changes.')
+
+    def _isPasswordEncrypted(self, pw):
+        return AuthEncoding.is_encrypted(pw)
+
+    def _encryptPassword(self, pw):
+        return AuthEncoding.pw_encrypt(pw, 'SHA')
+
     def domainSpecValidate(self, spec):
         for ob in spec:
             sz=len(ob)
@@ -796,7 +845,9 @@
                    title  ='Illegal value', 
                    message='Illegal domain specification',
                    action ='manage_main')
-        self._doAddUser(name, password, roles, domains)        
+        if self.encrypt_passwords:
+            password = self._encryptPassword(password)
+        self._doAddUser(name, password, roles, domains)
         if REQUEST: return self._mainUser(self, REQUEST)
 
 
@@ -834,6 +885,8 @@
                    title  ='Illegal value', 
                    message='Illegal domain specification',
                    action ='manage_main')
+        if password is not None and self.encrypt_passwords:
+            password = self._encryptPassword(password)
         self._doChangeUser(name, password, roles, domains)
         if REQUEST: return self._mainUser(self, REQUEST)