Commits

Thomas Waldmann committed aff38f7

remove old password hashing code + support lib, replace it with dummy code

  • Participants
  • Parent commits a1c0c90

Comments (0)

Files changed (6)

MoinMoin/_tests/test_user.py

         theUser = user.User(name=name, password=password)
         assert theUser.valid
 
-    def test_auth_with_ssha_stored_password(self):
+    def test_login(self):
         """
-        Create user with {SSHA} password and check that user can login.
+        Create user with some password and check that user can login.
         """
         # Create test user
         name = u'Test User'
-        # pass = 12345
-        # salt = salt
-        password = '{SSHA}x4YEGdfI4i0qROaY3NTHCmwSJY5zYWx0'
-        self.createUser(name, password, True)
+        password = '12345'
+        salt = 'salt'
+        pw_hash = ''
+        self.createUser(name, pw_hash, True)
 
         # Try to "login"
-        theuser = user.User(name=name, password='12345')
-        assert theuser.valid
-
-    def test_auth_with_apr1_stored_password(self):
-        """
-        Create user with {APR1} password and check that user can login.
-        """
-        # Create test user
-        name = u'Test User'
-        # generated with "htpasswd -nbm blaze 12345"
-        password = '{APR1}$apr1$NG3VoiU5$PSpHT6tV0ZMKkSZ71E3qg.' # 12345
-        self.createUser(name, password, True)
-
-        # Try to "login"
-        theuser = user.User(name=name, password='12345')
-        assert theuser.valid
-
-    def test_auth_with_md5_stored_password(self):
-        """
-        Create user with {MD5} password and check that user can login.
-        """
-        # Create test user
-        name = u'Test User'
-        password = '{MD5}$1$salt$etVYf53ma13QCiRbQOuRk/' # 12345
-        self.createUser(name, password, True)
-
-        # Try to "login"
-        theuser = user.User(name=name, password='12345')
-        assert theuser.valid
-
-    def test_auth_with_des_stored_password(self):
-        """
-        Create user with {DES} password and check that user can login.
-        """
-        # Create test user
-        name = u'Test User'
-        # generated with "htpasswd -nbd blaze 12345"
-        password = '{DES}gArsfn7O5Yqfo' # 12345
-        self.createUser(name, password, True)
-
-        try:
-            import crypt
-            # Try to "login"
-            theuser = user.User(name=name, password='12345')
-            assert theuser.valid
-        except ImportError:
-            pytest.skip("Platform does not provide crypt module!")
-
-    def test_auth_with_ssha256_stored_password(self):
-        """
-        Create user with {SSHA256} password and check that user can login.
-        """
-        # Create test user
-        name = u'Test User'
-        # generated with online sha256 tool
-        # pass: 12345
-        # salt: salt
-        # base64 encoded
-        password = '{SSHA256}r4ONZUfEyn9MUkcyDQkQ5MBNpdIerM24MasxFpuQBaFzYWx0'
-
-        self.createUser(name, password, True)
-
-        # Try to "login"
-        theuser = user.User(name=name, password='12345')
-        assert theuser.valid
-
-    def test_regression_user_password_started_with_sha(self):
-        # This is regression test for bug in function 'user.create_user'.
-        #
-        # This function does not encode passwords which start with '{SHA}'
-        # It treats them as already encoded SHA hashes.
-        #
-        # If user during registration specifies password starting with '{SHA}'
-        # this password will not get encoded and user object will get saved with empty enc_password
-        # field.
-        #
-        # Such situation leads to "KeyError: 'enc_password'" during
-        # user authentication.
-
-        # Any Password begins with the {SHA} symbols led to
-        # "KeyError: 'enc_password'" error during user authentication.
-        user_name = u'moin'
-        user_password = u'{SHA}LKM56'
-        user.create_user(user_name, user_password, u'moin@moinmo.in', u'')
-
-        # Try to "login"
-        theuser = user.User(name=user_name, password=user_password)
+        theuser = user.User(name=name, password=password)
         assert theuser.valid
 
     def testSubscriptionSubscribedPage(self):
         theUser.subscribe(pagename)
         assert not theUser.is_subscribed_to([testPagename]) # list(!) of pages to check
 
-    def test_upgrade_password_from_ssha_to_ssha256(self):
-        """
-        Create user with {SSHA} password and check that logging in
-        upgrades to {SSHA256}.
-        """
-        name = u'/no such user/'
-        # pass = 'MoinMoin', salt = '12345'
-        password = '{SSHA}xkDIIx1I7A4gC98Vt/+UelIkTDYxMjM0NQ=='
-        self.createUser(name, password, True)
-
-        theuser = user.User(name=name, password='MoinMoin')
-        assert theuser.enc_password[:9] == '{SSHA256}'
-
-    def test_upgrade_password_from_sha_to_ssha256(self):
-        """
-        Create user with {SHA} password and check that logging in
-        upgrades to {SSHA256}.
-        """
-        name = u'/no such user/'
-        password = '{SHA}jLIjfQZ5yojbZGTqxg2pY0VROWQ=' # 12345
-        self.createUser(name, password, True)
-
-        theuser = user.User(name=name, password='12345')
-        assert theuser.enc_password[:9] == '{SSHA256}'
-
-    def test_upgrade_password_from_apr1_to_ssha256(self):
-        """
-        Create user with {APR1} password and check that logging in
-        upgrades to {SSHA256}.
-        """
-        # Create test user
-        name = u'Test User'
-        # generated with "htpasswd -nbm blaze 12345"
-        password = '{APR1}$apr1$NG3VoiU5$PSpHT6tV0ZMKkSZ71E3qg.' # 12345
-        self.createUser(name, password, True)
-
-        theuser = user.User(name=name, password='12345')
-        assert theuser.enc_password[:9] == '{SSHA256}'
-
-    def test_upgrade_password_from_md5_to_ssha256(self):
-        """
-        Create user with {MD5} password and check that logging in
-        upgrades to {SSHA}.
-        """
-        # Create test user
-        name = u'Test User'
-        password = '{MD5}$1$salt$etVYf53ma13QCiRbQOuRk/' # 12345
-        self.createUser(name, password, True)
-
-        theuser = user.User(name=name, password='12345')
-        assert theuser.enc_password[:9] == '{SSHA256}'
-
-    def test_upgrade_password_from_des_to_ssha256(self):
-        """
-        Create user with {DES} password and check that logging in
-        upgrades to {SSHA}.
-        """
-        # Create test user
-        name = u'Test User'
-        # generated with "htpasswd -nbd blaze 12345"
-        password = '{DES}gArsfn7O5Yqfo' # 12345
-        self.createUser(name, password, True)
-
-        theuser = user.User(name=name, password='12345')
-        assert theuser.enc_password[:9] == '{SSHA256}'
-
     # Bookmarks -------------------------------------------------------
 
     def test_bookmark(self):

MoinMoin/util/_tests/test_crypto.py

         assert result == expected, ('Expected length "%(expected)s" but got "%(result)s"') % locals()
 
 
-class TestEncodePassword(object):
-    """crypto: encode passwords tests"""
-
-    def testAscii(self):
-        """user: encode ascii password"""
-        # u'MoinMoin' and 'MoinMoin' should be encoded to same result
-        expected = "{SSHA256}n0JB8FCTQCpQeg0bmdgvTGwPKvxm8fVNjSRD+JGNs50xMjM0NQ=="
-
-        result = crypto.crypt_password("MoinMoin", salt='12345')
-        assert result == expected
-        result = crypto.crypt_password(u"MoinMoin", salt='12345')
-        assert result == expected
-
-    def testUnicode(self):
-        """ user: encode unicode password """
-        result = crypto.crypt_password(u'סיסמה סודית בהחלט', salt='12345') # Hebrew
-        expected = "{SSHA256}pdYvYv+4Vph259sv/HAm7zpZTv4sBKX9ITOX/m00HMsxMjM0NQ=="
-        assert result == expected
-
-    def testupgradepassword(self):
-        """ return new password hash with better hash """
-        result = crypto.upgrade_password(u'MoinMoin', "junk_hash")
-        assert result.startswith('{SSHA256}')
-
-    def testvalidpassword(self):
-        """ validate user password """
-        hash_val = crypto.crypt_password(u"MoinMoin", salt='12345')
-        result = crypto.valid_password(u'MoinMoin', hash_val)
-        assert result
-        with pytest.raises(ValueError):
-            invalid_result = crypto.valid_password("MoinMoin", '{junk_value}')
-
-    def testvalidpassword2(self):
-        """ validate user password """
-        hash_val = crypto.crypt_password(u"MoinMoin")
-        result = crypto.valid_password('MoinMoin', hash_val)
-        assert result
-        result = crypto.valid_password('WrongPassword', hash_val)
-        assert not result
-        with pytest.raises(ValueError):
-            invalid_result = crypto.valid_password("MoinMoin", '{junk_value}')
-
-
 class TestToken(object):
     """ tests for the generated tokens """
 

MoinMoin/util/_tests/test_md5crypt.py

-# -*- coding: utf-8 -*-
-# Copyright: 2011 Prashant Kumar <contactprashantat AT gmail DOT com>
-# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
-
-"""
-MoinMoin - MoinMoin.util.md5crypt Tests
-"""
-
-
-import pytest
-from MoinMoin.util import md5crypt
-
-def test_unix_md5_crypt():
-    # when magic != None
-    result = md5crypt.unix_md5_crypt('test_pass', 'Moin_test', '$test_magic$')
-    expected = '$test_magic$Moin_tes$JRfmeHgnmCVhVYW.bTtiY1'
-    assert result == expected
-
-    # when magic == None
-    result = md5crypt.unix_md5_crypt('test_pass', 'Moin_test', None)
-    expected = '$1$Moin_tes$hArc67BzmDWtyWWKO5uxQ1'
-    assert result == expected
-
-def test_apache_md5_crypt():
-    # Here magic == '$apr1$'
-    result = md5crypt.apache_md5_crypt('test_pass', 'Moin_test')
-    expected = '$apr1$Moin_tes$4/5zV8nADrNv3BJcY1rZX1'
-    assert result == expected

MoinMoin/util/crypto.py

 
 - generate strong, salted cryptographic password hashes for safe pw storage
 - verify cleartext password against any supported crypto (see METHODS)
-- support old (weak) password crypto so one can import existing password
-  databases
 - supports password hash upgrades to stronger methods if the cleartext
   password is available (usually at login time)
 - generate password recovery tokens
 
 from __future__ import absolute_import, division
 
-import base64
 import hashlib
 import hmac
 import random
 import time
 
-# Note: have the (strong) method that crypt_password() uses at index 0:
-METHODS = ['{SSHA256}', '{SSHA}', '{SHA}', ]
-
-try:
-    from . import md5crypt
-    METHODS.extend(['{APR1}', '{MD5}', ])
-except ImportError:
-    pass
-
-try:
-    import crypt
-    METHODS.extend(['{DES}', ])
-except ImportError:
-    pass
-
 from uuid import uuid4
 
 make_uuid = lambda: unicode(uuid4().hex)
     :param password: cleartext password [unicode]
     :param salt: salt for the password [str] or None to generate a random salt
     :rtype: str
-    :returns: the SSHA256 password hash
+    :returns: the password hash
     """
-    password = password.encode('utf-8')
-    if salt is None:
-        salt = random_string(32)
-    assert isinstance(salt, str)
-    h = hashlib.new('sha256', password)
-    h.update(salt)
-    return '{SSHA256}' + base64.encodestring(h.digest() + salt).rstrip()
+    return 'foobar' # TODO
 
 
 def upgrade_password(password, pw_hash):
     :rtype: str
     :returns: new password hash (or None, if unchanged)
     """
-    if not pw_hash.startswith('{SSHA256}'):
-        # pw_hash using some old hash method, upgrade to better method
-        return crypt_password(password)
-
+    # TODO
 
 def valid_password(password, pw_hash):
     """
     :rtype: bool
     :returns: password is valid
     """
-    # encode password
-    pw_utf8 = password.encode('utf-8')
-
-    for method in METHODS:
-        if pw_hash.startswith(method):
-            d = pw_hash[len(method):]
-            if method == '{SSHA256}':
-                ph = base64.decodestring(d)
-                # ph is of the form "<hash><salt>"
-                salt = ph[32:]
-                h = hashlib.new('sha256', pw_utf8)
-                h.update(salt)
-                enc = base64.encodestring(h.digest() + salt).rstrip()
-            elif method == '{SSHA}':
-                ph = base64.decodestring(d)
-                # ph is of the form "<hash><salt>"
-                salt = ph[20:]
-                h = hashlib.new('sha1', pw_utf8)
-                h.update(salt)
-                enc = base64.encodestring(h.digest() + salt).rstrip()
-            elif method == '{SHA}':
-                h = hashlib.new('sha1', pw_utf8)
-                enc = base64.encodestring(h.digest()).rstrip()
-            elif method == '{APR1}':
-                # d is of the form "$apr1$<salt>$<hash>"
-                salt = d.split('$')[2]
-                enc = md5crypt.apache_md5_crypt(pw_utf8, salt.encode('ascii'))
-            elif method == '{MD5}':
-                # d is of the form "$1$<salt>$<hash>"
-                salt = d.split('$')[2]
-                enc = md5crypt.unix_md5_crypt(pw_utf8, salt.encode('ascii'))
-            elif method == '{DES}':
-                # d is 2 characters salt + 11 characters hash
-                salt = d[:2]
-                enc = crypt.crypt(pw_utf8, salt.encode('ascii'))
-            else:
-                raise ValueError("missing password hash method {0} handler".format(method))
-            return pw_hash == method + enc
-    else:
-        idx = pw_hash.index('}') + 1
-        raise ValueError("unsupported password hash method {0!r}".format(pw_hash[:idx]))
+    return True # TODO
 
 
 # password recovery token

MoinMoin/util/md5crypt.py

-#########################################################
-# md5crypt.py
-#
-# 0423.2000 by michal wallace http://www.sabren.com/
-# based on perl's Crypt::PasswdMD5 by Luis Munoz (lem@cantv.net)
-# based on /usr/src/libcrypt/crypt.c from FreeBSD 2.2.5-RELEASE
-#
-# MANY THANKS TO
-#
-#  Carey Evans - http://home.clear.net.nz/pages/c.evans/
-#  Dennis Marti - http://users.starpower.net/marti1/
-#
-#  For the patches that got this thing working!
-#
-#########################################################
-"""md5crypt.py - Provides interoperable MD5-based crypt() function
-
-SYNOPSIS
-
-        import md5crypt.py
-
-        cryptedpassword = md5crypt.md5crypt(password, salt);
-
-DESCRIPTION
-
-unix_md5_crypt() provides a crypt()-compatible interface to the
-rather new MD5-based crypt() function found in modern operating systems.
-It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and
-contains the following license in it:
-
- "THE BEER-WARE LICENSE" (Revision 42):
- <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
- can do whatever you want with this stuff. If we meet some day, and you think
- this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
-
-apache_md5_crypt() provides a function compatible with Apache's
-.htpasswd files. This was contributed by Bryan Hart <bryan@eai.com>.
-
-"""
-
-MAGIC = '$1$'                   # Magic string
-ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-
-try:
-    import hashlib
-    hash_md5 = hashlib.md5
-except ImportError:
-    # maybe we have python < 2.5 (no hashlib)
-    import md5
-    hash_md5 = md5.new
-
-
-def to64(v, n):
-    ret = ''
-    while (n - 1 >= 0):
-        n = n - 1
-        ret = ret + ITOA64[v & 0x3f]
-        v = v >> 6
-    return ret
-
-
-def apache_md5_crypt(pw, salt):
-    # change the Magic string to match the one used by Apache
-    return unix_md5_crypt(pw, salt, '$apr1$')
-
-
-def unix_md5_crypt(pw, salt, magic=None):
-
-    if magic is None:
-        magic = MAGIC
-
-    # Take care of the magic string if present
-    if salt[:len(magic)] == magic:
-        salt = salt[len(magic):]
-
-
-    # salt can have up to 8 characters:
-    import string
-    salt = string.split(salt, '$', 1)[0]
-    salt = salt[:8]
-
-    ctx = pw + magic + salt
-
-    md5 = hash_md5()
-    md5.update(pw + salt + pw)
-    final = md5.digest()
-
-    for pl in range(len(pw), 0, -16):
-        if pl > 16:
-            ctx = ctx + final[:16]
-        else:
-            ctx = ctx + final[:pl]
-
-
-    # Now the 'weird' xform (??)
-
-    i = len(pw)
-    while i:
-        if i & 1:
-            ctx = ctx + chr(0)  #if ($i & 1) { $ctx->add(pack("C", 0)); }
-        else:
-            ctx = ctx + pw[0]
-        i = i >> 1
-
-    md5 = hash_md5()
-    md5.update(ctx)
-    final = md5.digest()
-
-    # The following is supposed to make
-    # things run slower.
-
-    # my question: WTF???
-
-    for i in range(1000):
-        ctx1 = ''
-        if i & 1:
-            ctx1 = ctx1 + pw
-        else:
-            ctx1 = ctx1 + final[:16]
-
-        if i % 3:
-            ctx1 = ctx1 + salt
-
-        if i % 7:
-            ctx1 = ctx1 + pw
-
-        if i & 1:
-            ctx1 = ctx1 + final[:16]
-        else:
-            ctx1 = ctx1 + pw
-
-
-        md5 = hash_md5()
-        md5.update(ctx1)
-        final = md5.digest()
-
-
-    # Final xform
-
-    passwd = ''
-
-    passwd = passwd + to64((int(ord(final[0])) << 16)
-                           |(int(ord(final[6])) << 8)
-                           |(int(ord(final[12]))), 4)
-
-    passwd = passwd + to64((int(ord(final[1])) << 16)
-                           |(int(ord(final[7])) << 8)
-                           |(int(ord(final[13]))), 4)
-
-    passwd = passwd + to64((int(ord(final[2])) << 16)
-                           |(int(ord(final[8])) << 8)
-                           |(int(ord(final[14]))), 4)
-
-    passwd = passwd + to64((int(ord(final[3])) << 16)
-                           |(int(ord(final[9])) << 8)
-                           |(int(ord(final[15]))), 4)
-
-    passwd = passwd + to64((int(ord(final[4])) << 16)
-                           |(int(ord(final[10])) << 8)
-                           |(int(ord(final[5]))), 4)
-
-    passwd = passwd + to64((int(ord(final[11]))), 2)
-
-
-    return magic + salt + '$' + passwd
-
-
-## assign a wrapper function:
-md5crypt = unix_md5_crypt
-
-if __name__ == "__main__":
-    print unix_md5_crypt("cat", "hat")

docs/admin/configure.rst

 
 Password storage
 ----------------
-Moin never stores passwords in clear text, but always as cryptographic hash
-with a random salt. Currently ssha256 is the default.
+Moin never stores passwords in clear text.
 
 
 Authorization