Revision: 8174
http://svn.sourceforge.net/mailman/?rev=8174&view=rev
Author: bwarsaw
Date: 2007-03-21 21:29:31 -0700 (Wed, 21 Mar 2007)
Log Message:
-----------
Restore the use of passwords.Schemes enum for selection of password hashing
scheme. Fix mmsitepass and test cases accordingly. Details:
- set_global_password(): Instead of taking a string for 'scheme' argument,
take None and then coerce that into passwords.Schemes.ssha
- Add a base PasswordError and a BadPasswordSchemeError error that derives
from that. For consistency, multiply inherit MMBadPasswordError and
MMPasswordsMustMatch from PasswordError.
- Add a passwords.lookup_scheme() method which turns scheme_names into scheme
enum constants. It returns None if the lookup fails.
- passwords.py: change the internal representation of _SCHEMES_BY_TAG
dictionary to map scheme names to scheme enum values. Change internal uses
of this dictionary to then turn those enum values into hash classes, or
whatever else we need.
- make_secret(): Raise BadPasswordSchemeErrorif the given schema (which should
be an enum value) is invalid.
- TestBase.tearDown(): Clear out any <site> locks that might hang around after
a test case runs.
Modified Paths:
--------------
trunk/mailman/Mailman/Errors.py
trunk/mailman/Mailman/Utils.py
trunk/mailman/Mailman/bin/mmsitepass.py
trunk/mailman/Mailman/passwords.py
trunk/mailman/Mailman/testing/base.py
trunk/mailman/Mailman/testing/test_handlers.py
trunk/mailman/Mailman/testing/test_membership.py
trunk/mailman/Mailman/testing/test_passwords.py
trunk/mailman/Mailman/testing/test_security_mgr.py
Modified: trunk/mailman/Mailman/Errors.py
===================================================================
--- trunk/mailman/Mailman/Errors.py 2007-03-21 21:31:59 UTC (rev 8173)
+++ trunk/mailman/Mailman/Errors.py 2007-03-22 04:29:31 UTC (rev 8174)
@@ -58,8 +58,6 @@
# Exception hierarchy for various authentication failures, can be
# raised from functions in SecurityManager.py
class MMAuthenticationError(MailmanException): pass
-class MMBadPasswordError(MMAuthenticationError): pass
-class MMPasswordsMustMatch(MMAuthenticationError): pass
class MMCookieError(MMAuthenticationError): pass
class MMExpiredCookieError(MMCookieError): pass
class MMInvalidCookieError(MMCookieError): pass
@@ -191,3 +189,26 @@
from Mailman.Version import DATABASE_SCHEMA_VERSION
return 'Incompatible database schema version (got: %d, expected: %d)' \
% (self._got, DATABASE_SCHEMA_VERSION)
+
+
+
+class PasswordError(MailmanError):
+ """A password related error."""
+
+
+class MMBadPasswordError(PasswordError, MMAuthenticationError):
+ """A bad password was given."""
+
+
+class MMPasswordsMustMatch(PasswordError, MMAuthenticationError):
+ """The given passwords don't match."""
+
+
+class BadPasswordSchemeError(PasswordError):
+ """A bad password scheme was given."""
+
+ def __init__(self, scheme_name='unknown'):
+ self.scheme_name = scheme_name
+
+ def __str__(self):
+ return 'A bad password scheme was given: %s' % self.scheme_name
Modified: trunk/mailman/Mailman/Utils.py
===================================================================
--- trunk/mailman/Mailman/Utils.py 2007-03-21 21:31:59 UTC (rev 8173)
+++ trunk/mailman/Mailman/Utils.py 2007-03-22 04:29:31 UTC (rev 8174)
@@ -335,7 +335,9 @@
-def set_global_password(pw, siteadmin=True, scheme='ssha'):
+def set_global_password(pw, siteadmin=True, scheme=None):
+ if scheme is None:
+ scheme = passwords.Schemes.ssha
if siteadmin:
filename = config.SITE_PW_FILE
else:
Modified: trunk/mailman/Mailman/bin/mmsitepass.py
===================================================================
--- trunk/mailman/Mailman/bin/mmsitepass.py 2007-03-21 21:31:59 UTC (rev
8173)
+++ trunk/mailman/Mailman/bin/mmsitepass.py 2007-03-22 04:29:31 UTC (rev
8174)
@@ -68,7 +68,7 @@
parser.error(_('Unexpected arguments'))
if opts.list_hash_schemes:
for label in passwords.Schemes:
- print label.upper()
+ print str(label).upper()
sys.exit(0)
return parser, opts, args
@@ -77,9 +77,10 @@
# shoule be checked after config is loaded.
if password_scheme == '':
password_scheme = config.PASSWORD_SCHEME
- if password_scheme.lower() not in passwords.Schemes:
+ scheme = passwords.lookup_scheme(password_scheme.lower())
+ if not scheme:
parser.error(_('Invalid password scheme'))
- return password_scheme
+ return scheme
Modified: trunk/mailman/Mailman/passwords.py
===================================================================
--- trunk/mailman/Mailman/passwords.py 2007-03-21 21:31:59 UTC (rev 8173)
+++ trunk/mailman/Mailman/passwords.py 2007-03-22 04:29:31 UTC (rev 8174)
@@ -29,6 +29,7 @@
from base64 import urlsafe_b64decode as decode
from base64 import urlsafe_b64encode as encode
+from Mailman import Errors
from Mailman.enum import Enum
SALT_LENGTH = 20 # bytes
@@ -202,8 +203,8 @@
# Some scheme tags have arguments, but the key for this dictionary should just
# be the lowercased scheme name.
-_SCHEMES_BY_TAG = dict((c.TAG.split(' ')[0].lower(), c)
- for c in _SCHEMES_BY_ENUM.values())
+_SCHEMES_BY_TAG = dict((_SCHEMES_BY_ENUM[e].TAG.split(' ')[0].lower(), e)
+ for e in _SCHEMES_BY_ENUM)
_DEFAULT_SCHEME = NoPasswordScheme
@@ -218,7 +219,9 @@
# be a unicode.
if isinstance(password, unicode):
password = password.encode('utf-8')
- scheme_class = _SCHEMES_BY_TAG.get(scheme, _DEFAULT_SCHEME)
+ scheme_class = _SCHEMES_BY_ENUM.get(scheme)
+ if not scheme_class:
+ raise Errors.BadPasswordSchemeError(scheme)
secret = scheme_class.make_secret(password)
return '{%s}%s' % (scheme_class.TAG, secret)
@@ -235,8 +238,10 @@
scheme_group, rest_group = mo.group('scheme', 'rest')
scheme_parts = scheme_group.split()
scheme = scheme_parts[0].lower()
- scheme_class = _SCHEMES_BY_TAG.get(scheme, _DEFAULT_SCHEME)
- if isinstance(rest_group, unicode):
- # decode() fails. (challenge is from database)
- rest_group = str(rest_group)
+ scheme_enum = _SCHEMES_BY_TAG.get(scheme, _DEFAULT_SCHEME)
+ scheme_class = _SCHEMES_BY_ENUM[scheme_enum]
return scheme_class.check_response(rest_group, response, *scheme_parts[1:])
+
+
+def lookup_scheme(scheme_name):
+ return _SCHEMES_BY_TAG.get(scheme_name.lower())
Modified: trunk/mailman/Mailman/testing/base.py
===================================================================
--- trunk/mailman/Mailman/testing/base.py 2007-03-21 21:31:59 UTC (rev
8173)
+++ trunk/mailman/Mailman/testing/base.py 2007-03-22 04:29:31 UTC (rev
8174)
@@ -118,3 +118,9 @@
archives=True, quiet=True)
os.unlink(self._config)
os.unlink(self._dbfile)
+ # Clear out any site locks, which can be left over if tests fail.
+ for filename in os.listdir(config.LOCK_DIR):
+ if filename.startswith('<site>'):
+ path = os.path.join(config.LOCK_DIR, filename)
+ print >> sys.stderr, '@@@@@ removing:', path
+ os.unlink(path)
Modified: trunk/mailman/Mailman/testing/test_handlers.py
===================================================================
--- trunk/mailman/Mailman/testing/test_handlers.py 2007-03-21 21:31:59 UTC
(rev 8173)
+++ trunk/mailman/Mailman/testing/test_handlers.py 2007-03-22 04:29:31 UTC
(rev 8174)
@@ -59,7 +59,7 @@
def password(cleartext):
- return passwords.make_secret(cleartext, 'ssha')
+ return passwords.make_secret(cleartext, passwords.Schemes.ssha)
Modified: trunk/mailman/Mailman/testing/test_membership.py
===================================================================
--- trunk/mailman/Mailman/testing/test_membership.py 2007-03-21 21:31:59 UTC
(rev 8173)
+++ trunk/mailman/Mailman/testing/test_membership.py 2007-03-22 04:29:31 UTC
(rev 8174)
@@ -33,7 +33,7 @@
def password(cleartext):
- return passwords.make_secret(cleartext, 'ssha')
+ return passwords.make_secret(cleartext, passwords.Schemes.ssha)
Modified: trunk/mailman/Mailman/testing/test_passwords.py
===================================================================
--- trunk/mailman/Mailman/testing/test_passwords.py 2007-03-21 21:31:59 UTC
(rev 8173)
+++ trunk/mailman/Mailman/testing/test_passwords.py 2007-03-22 04:29:31 UTC
(rev 8174)
@@ -19,6 +19,7 @@
import unittest
+from Mailman import Errors
from Mailman import passwords
@@ -72,6 +73,27 @@
scheme = -1
def test_passwords(self):
+ self.assertRaises(Errors.BadPasswordSchemeError,
+ passwords.make_secret, self.pw8a, self.scheme)
+
+ def test_unicode_passwords(self):
+ self.assertRaises(Errors.BadPasswordSchemeError,
+ passwords.make_secret, self.pwua, self.scheme)
+
+ def test_passwords_with_funky_chars(self):
+ self.assertRaises(Errors.BadPasswordSchemeError,
+ passwords.make_secret, self.pw8b, self.scheme)
+
+ def test_unicode_passwords_with_funky_chars(self):
+ self.assertRaises(Errors.BadPasswordSchemeError,
+ passwords.make_secret, self.pwub, self.scheme)
+
+
+
+class TestNonePasswords(TestPasswordsBase):
+ scheme = passwords.Schemes.no_scheme
+
+ def test_passwords(self):
failif = self.failIf
secret = passwords.make_secret(self.pw8a, self.scheme)
failif(passwords.check_response(secret, self.pw8a))
@@ -97,27 +119,36 @@
-class TestNonePasswords(TestBogusPasswords):
- scheme = 'no_scheme'
-
-
class TestCleartextPasswords(TestPasswordsBase):
- scheme = 'cleartext'
+ scheme = passwords.Schemes.cleartext
class TestSHAPasswords(TestPasswordsBase):
- scheme = 'sha'
+ scheme = passwords.Schemes.sha
class TestSSHAPasswords(TestPasswordsBase):
- scheme = 'ssha'
+ scheme = passwords.Schemes.ssha
class TestPBKDF2Passwords(TestPasswordsBase):
- scheme = 'pbkdf2'
+ scheme = passwords.Schemes.pbkdf2
+class TestSchemeLookup(unittest.TestCase):
+ def test_scheme_name_lookup(self):
+ unless = self.failUnless
+ unless(passwords.lookup_scheme('NONE') is passwords.Schemes.no_scheme)
+ unless(passwords.lookup_scheme('CLEARTEXT') is
+ passwords.Schemes.cleartext)
+ unless(passwords.lookup_scheme('SHA') is passwords.Schemes.sha)
+ unless(passwords.lookup_scheme('SSHA') is passwords.Schemes.ssha)
+ unless(passwords.lookup_scheme('PBKDF2') is passwords.Schemes.pbkdf2)
+ unless(passwords.lookup_scheme(' -bogus- ') is None)
+
+
+
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestBogusPasswords))
@@ -126,4 +157,5 @@
suite.addTest(unittest.makeSuite(TestSHAPasswords))
suite.addTest(unittest.makeSuite(TestSSHAPasswords))
suite.addTest(unittest.makeSuite(TestPBKDF2Passwords))
+ suite.addTest(unittest.makeSuite(TestSchemeLookup))
return suite
Modified: trunk/mailman/Mailman/testing/test_security_mgr.py
===================================================================
--- trunk/mailman/Mailman/testing/test_security_mgr.py 2007-03-21 21:31:59 UTC
(rev 8173)
+++ trunk/mailman/Mailman/testing/test_security_mgr.py 2007-03-22 04:29:31 UTC
(rev 8174)
@@ -36,7 +36,7 @@
def password(cleartext):
- return passwords.make_secret(cleartext, 'ssha')
+ return passwords.make_secret(cleartext, passwords.Schemes.ssha)
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe:
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org