VirtualMailManager/password.py
author Pascal Volk <user@localhost.localdomain.org>
Sat, 15 Feb 2014 17:39:24 +0000
branchv0.7.x
changeset 726 46b37d7c848a
parent 725 300b76de5ad0
child 731 77561c118f42
permissions -rw-r--r--
VMM/account: Added method Account.update_password.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
     1
# -*- coding: UTF-8 -*-
703
58815c004a61 Updated copyright notices to include the year 2014.
Pascal Volk <user@localhost.localdomain.org>
parents: 675
diff changeset
     2
# Copyright (c) 2010 - 2014, Pascal Volk
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
     3
# See COPYING for distribution information.
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
     4
"""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
     5
    VirtualMailManager.password
320
011066435e6f VMM/*: Made all modules names lowercase, adjusted imports.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 316
diff changeset
     6
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
     7
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
     8
    VirtualMailManager's password module to generate password hashes from
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
     9
    passwords or random passwords. This module provides following
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
    10
    functions:
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    11
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    12
        hashed_password = pwhash(password[, scheme][, user])
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    13
        random_password = randompw()
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
    14
        scheme, encoding = verify_scheme(scheme)
461
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
    15
        schemes, encodings = list_schemes()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    16
"""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    17
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
    18
import hashlib
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
    19
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
    20
from base64 import b64encode
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
    21
from binascii import b2a_hex
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    22
from crypt import crypt
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
    23
from random import SystemRandom
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    24
from subprocess import Popen, PIPE
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    25
272
446483386914 VMM/Config: Added method Config.install() -> global cfg_dget().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 268
diff changeset
    26
from VirtualMailManager import ENCODING
320
011066435e6f VMM/*: Made all modules names lowercase, adjusted imports.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 316
diff changeset
    27
from VirtualMailManager.emailaddress import EmailAddress
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    28
from VirtualMailManager.common import get_unicode, version_str
316
31d8931dc535 VMM/constants: Replaced the constants subpackage by a module.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 292
diff changeset
    29
from VirtualMailManager.constants import VMM_ERROR
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    30
from VirtualMailManager.errors import VMMError
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    31
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    32
SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    33
PASSWDCHARS = '._-+#*23456789abcdefghikmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    34
DEFAULT_B64 = (None, 'B64', 'BASE64')
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    35
DEFAULT_HEX = (None, 'HEX')
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    36
CRYPT_ID_MD5 = 1
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    37
CRYPT_ID_BLF = '2a'
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    38
CRYPT_ID_SHA256 = 5
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    39
CRYPT_ID_SHA512 = 6
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    40
CRYPT_SALT_LEN = 2
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    41
CRYPT_BLF_ROUNDS_MIN = 4
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    42
CRYPT_BLF_ROUNDS_MAX = 31
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    43
CRYPT_BLF_SALT_LEN = 22
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    44
CRYPT_MD5_SALT_LEN = 8
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    45
CRYPT_SHA2_ROUNDS_DEFAULT = 5000
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    46
CRYPT_SHA2_ROUNDS_MIN = 1000
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    47
CRYPT_SHA2_ROUNDS_MAX = 999999999
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    48
CRYPT_SHA2_SALT_LEN = 16
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    49
SALTED_ALGO_SALT_LEN = 4
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    50
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    51
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    52
_ = lambda msg: msg
272
446483386914 VMM/Config: Added method Config.install() -> global cfg_dget().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 268
diff changeset
    53
cfg_dget = lambda option: None
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
    54
_sys_rand = SystemRandom()
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
    55
_choice = _sys_rand.choice
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
    56
_get_salt = lambda s_len: ''.join(_choice(SALTCHARS) for x in range(s_len))
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
    57
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
    58
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
    59
def _doveadmpw(password, scheme, encoding):
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
    60
    """Communicates with Dovecot's doveadm and returns
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    61
    the hashed password: {scheme[.encoding]}hash
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    62
    """
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    63
    if encoding:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    64
        scheme = '.'.join((scheme, encoding))
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
    65
    cmd_args = [cfg_dget('bin.doveadm'), 'pw', '-s', scheme, '-p',
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    66
                get_unicode(password)]
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    67
    process = Popen(cmd_args, stdout=PIPE, stderr=PIPE)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    68
    stdout, stderr = process.communicate()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    69
    if process.returncode:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
    70
        raise VMMError(stderr.strip().decode(ENCODING), VMM_ERROR)
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
    71
    hashed = stdout.strip().decode(ENCODING)
274
45ec5c3cfef4 VMM/password: added small output check on _dovecotpw().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 272
diff changeset
    72
    if not hashed.startswith('{%s}' % scheme):
45ec5c3cfef4 VMM/password: added small output check on _dovecotpw().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 272
diff changeset
    73
        raise VMMError('Unexpected result from %s: %s' %
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
    74
                       (cfg_dget('bin.doveadm'), hashed), VMM_ERROR)
274
45ec5c3cfef4 VMM/password: added small output check on _dovecotpw().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 272
diff changeset
    75
    return hashed
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    76
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    77
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    78
def _md4_new():
655
2bf68600e914 VMM/password: Code cleanups:
Pascal Volk <user@localhost.localdomain.org>
parents: 651
diff changeset
    79
    """Returns an new MD4-hash object if supported by the hashlib -
2bf68600e914 VMM/password: Code cleanups:
Pascal Volk <user@localhost.localdomain.org>
parents: 651
diff changeset
    80
    otherwise `None`.
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    81
    """
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    82
    try:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    83
        return hashlib.new('md4')
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
    84
    except ValueError as err:
655
2bf68600e914 VMM/password: Code cleanups:
Pascal Volk <user@localhost.localdomain.org>
parents: 651
diff changeset
    85
        if err.args[0].startswith('unsupported hash type'):
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    86
            return None
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    87
        else:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    88
            raise
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    89
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    90
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    91
def _format_digest(digest, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    92
    """Formats the arguments to a string: {scheme[.encoding]}digest."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    93
    if not encoding:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    94
        return '{%s}%s' % (scheme, digest)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    95
    return '{%s.%s}%s' % (scheme, encoding, digest)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    96
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    97
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    98
def _clear_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
    99
    """Generates a (encoded) CLEARTEXT/PLAIN 'hash'."""
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   100
    password = password.decode(ENCODING)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   101
    if encoding:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   102
        if encoding == 'HEX':
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   103
            password = b2a_hex(password.encode()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   104
        else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   105
            password = b64encode(password.encode()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   106
        return _format_digest(password, scheme, encoding)
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   107
    return '{%s}%s' % (scheme, password)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   108
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   109
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   110
def _get_crypt_blowfish_salt():
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   111
    """Generates a salt for Blowfish crypt."""
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   112
    rounds = cfg_dget('misc.crypt_blowfish_rounds')
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   113
    if rounds < CRYPT_BLF_ROUNDS_MIN:
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   114
        rounds = CRYPT_BLF_ROUNDS_MIN
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   115
    elif rounds > CRYPT_BLF_ROUNDS_MAX:
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   116
        rounds = CRYPT_BLF_ROUNDS_MAX
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   117
    return '$%s$%02d$%s' % (CRYPT_ID_BLF, rounds,
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   118
                            _get_salt(CRYPT_BLF_SALT_LEN))
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   119
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   120
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   121
def _get_crypt_sha2_salt(crypt_id):
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   122
    """Generates a salt for crypt using the SHA-256 or SHA-512 encryption
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   123
    method.
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   124
    *crypt_id* must be either `5` (SHA-256) or `6` (SHA-512).
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   125
    """
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   126
    assert crypt_id in (CRYPT_ID_SHA256, CRYPT_ID_SHA512), 'invalid crypt ' \
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   127
           'id: %r' % crypt_id
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   128
    if crypt_id is CRYPT_ID_SHA512:
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   129
        rounds = cfg_dget('misc.crypt_sha512_rounds')
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   130
    else:
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   131
        rounds = cfg_dget('misc.crypt_sha256_rounds')
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   132
    if rounds < CRYPT_SHA2_ROUNDS_MIN:
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   133
        rounds = CRYPT_SHA2_ROUNDS_MIN
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   134
    elif rounds > CRYPT_SHA2_ROUNDS_MAX:
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   135
        rounds = CRYPT_SHA2_ROUNDS_MAX
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   136
    if rounds == CRYPT_SHA2_ROUNDS_DEFAULT:
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   137
        return '$%d$%s' % (crypt_id, _get_salt(CRYPT_SHA2_SALT_LEN))
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   138
    return '$%d$rounds=%d$%s' % (crypt_id, rounds,
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   139
                                 _get_salt(CRYPT_SHA2_SALT_LEN))
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   140
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   141
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   142
def _crypt_hash(password, scheme, encoding):
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   143
    """Generates (encoded) CRYPT/MD5/{BLF,MD5,SHA{256,512}}-CRYPT hashes."""
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   144
    if scheme == 'CRYPT':
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   145
        salt = _get_salt(CRYPT_SALT_LEN)
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   146
    elif scheme == 'BLF-CRYPT':
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   147
        salt = _get_crypt_blowfish_salt()
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   148
    elif scheme in ('MD5-CRYPT', 'MD5'):
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   149
        salt = '$%d$%s' % (CRYPT_ID_MD5, _get_salt(CRYPT_MD5_SALT_LEN))
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   150
    elif scheme == 'SHA256-CRYPT':
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   151
        salt = _get_crypt_sha2_salt(CRYPT_ID_SHA256)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   152
    else:
292
619dadc0fd25 VMM/password: added some CRYPT_* constants.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 291
diff changeset
   153
        salt = _get_crypt_sha2_salt(CRYPT_ID_SHA512)
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   154
    encrypted = crypt(password.decode(ENCODING), salt)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   155
    if encoding:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   156
        if encoding == 'HEX':
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   157
            encrypted = b2a_hex(encrypted.encode()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   158
        else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   159
            encrypted = b64encode(encrypted.encode()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   160
    return _format_digest(encrypted, scheme, encoding)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   161
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   162
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   163
def _md4_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   164
    """Generates encoded PLAIN-MD4 hashes."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   165
    md4 = _md4_new()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   166
    if md4:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   167
        md4.update(password)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   168
        if encoding in DEFAULT_HEX:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   169
            digest = md4.hexdigest()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   170
        else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   171
            digest = b64encode(md4.digest()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   172
        return _format_digest(digest, scheme, encoding)
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   173
    return _doveadmpw(password, scheme, encoding)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   174
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   175
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   176
def _md5_hash(password, scheme, encoding, user=None):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   177
    """Generates DIGEST-MD5 aka PLAIN-MD5 and LDAP-MD5 hashes."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   178
    md5 = hashlib.md5()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   179
    if scheme == 'DIGEST-MD5':
691
932cd76bf879 VMM: Dropped support for Dovecot versions before v1.2.0.
Pascal Volk <user@localhost.localdomain.org>
parents: 676
diff changeset
   180
        md5.update(user.localpart.encode() + b':' +
932cd76bf879 VMM: Dropped support for Dovecot versions before v1.2.0.
Pascal Volk <user@localhost.localdomain.org>
parents: 676
diff changeset
   181
                   user.domainname.encode() + b':')
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   182
    md5.update(password)
290
e2785e04f92e VMM/…: re-indented long queries and error messages.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 289
diff changeset
   183
    if (scheme in ('PLAIN-MD5', 'DIGEST-MD5') and encoding in DEFAULT_HEX) or \
e2785e04f92e VMM/…: re-indented long queries and error messages.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 289
diff changeset
   184
       (scheme == 'LDAP-MD5' and encoding == 'HEX'):
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   185
        digest = md5.hexdigest()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   186
    else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   187
        digest = b64encode(md5.digest()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   188
    return _format_digest(digest, scheme, encoding)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   189
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   190
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   191
def _ntlm_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   192
    """Generates NTLM hashes."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   193
    md4 = _md4_new()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   194
    if md4:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   195
        password = b''.join(bytes(x)
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   196
                            for x in zip(password, bytes(len(password))))
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   197
        md4.update(password)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   198
        if encoding in DEFAULT_HEX:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   199
            digest = md4.hexdigest()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   200
        else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   201
            digest = b64encode(md4.digest()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   202
        return _format_digest(digest, scheme, encoding)
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   203
    return _doveadmpw(password, scheme, encoding)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   204
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   205
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   206
def _sha1_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   207
    """Generates SHA1 aka SHA hashes."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   208
    sha1 = hashlib.sha1(password)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   209
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   210
        digest = b64encode(sha1.digest()).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   211
    else:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   212
        digest = sha1.hexdigest()
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   213
    return _format_digest(digest, scheme, encoding)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   214
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   215
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   216
def _sha256_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   217
    """Generates SHA256 hashes."""
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   218
    sha256 = hashlib.sha256(password)
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   219
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   220
        digest = b64encode(sha256.digest()).decode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   221
    else:
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   222
        digest = sha256.hexdigest()
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   223
    return _format_digest(digest, scheme, encoding)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   224
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   225
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   226
def _sha512_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   227
    """Generates SHA512 hashes."""
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   228
    sha512 = hashlib.sha512(password)
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   229
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   230
        digest = b64encode(sha512.digest()).decode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   231
    else:
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   232
        digest = sha512.hexdigest()
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   233
    return _format_digest(digest, scheme, encoding)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   234
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   235
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   236
def _smd5_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   237
    """Generates SMD5 (salted PLAIN-MD5) hashes."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   238
    md5 = hashlib.md5(password)
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   239
    salt = _get_salt(SALTED_ALGO_SALT_LEN).encode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   240
    md5.update(salt)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   241
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   242
        digest = b64encode(md5.digest() + salt).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   243
    else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   244
        digest = md5.hexdigest() + b2a_hex(salt).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   245
    return _format_digest(digest, scheme, encoding)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   246
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   247
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   248
def _ssha1_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   249
    """Generates SSHA (salted SHA/SHA1) hashes."""
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   250
    sha1 = hashlib.sha1(password)
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   251
    salt = _get_salt(SALTED_ALGO_SALT_LEN).encode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   252
    sha1.update(salt)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   253
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   254
        digest = b64encode(sha1.digest() + salt).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   255
    else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   256
        digest = sha1.hexdigest() + b2a_hex(salt).decode()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   257
    return _format_digest(digest, scheme, encoding)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   258
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   259
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   260
def _ssha256_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   261
    """Generates SSHA256 (salted SHA256) hashes."""
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   262
    sha256 = hashlib.sha256(password)
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   263
    salt = _get_salt(SALTED_ALGO_SALT_LEN).encode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   264
    sha256.update(salt)
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   265
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   266
        digest = b64encode(sha256.digest() + salt).decode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   267
    else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   268
        digest = sha256.hexdigest() + b2a_hex(salt).decode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   269
    return _format_digest(digest, scheme, encoding)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   270
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   271
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   272
def _ssha512_hash(password, scheme, encoding):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   273
    """Generates SSHA512 (salted SHA512) hashes."""
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   274
    salt = _get_salt(SALTED_ALGO_SALT_LEN).encode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   275
    sha512 = hashlib.sha512(password + salt)
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   276
    if encoding in DEFAULT_B64:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   277
        digest = b64encode(sha512.digest() + salt).decode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   278
    else:
651
6937cb38db71 VMM/password: Post-2to3 fixes.
Pascal Volk <user@localhost.localdomain.org>
parents: 643
diff changeset
   279
        digest = sha512.hexdigest() + b2a_hex(salt).decode()
636
27334cfc0c90 VMM/pycompat: Removed module hashlib.
Pascal Volk <user@localhost.localdomain.org>
parents: 633
diff changeset
   280
    return _format_digest(digest, scheme, encoding)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   281
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   282
_scheme_info = {
664
b5cc967a45ad VMM/password: Added scheme CLEAR.
Pascal Volk <user@localhost.localdomain.org>
parents: 655
diff changeset
   283
    'CLEAR': (_clear_hash, 0x2010df00),
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   284
    'CLEARTEXT': (_clear_hash, 0x10000f00),
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   285
    'CRAM-MD5': (_doveadmpw, 0x10000f00),
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   286
    'CRYPT': (_crypt_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   287
    'DIGEST-MD5': (_md5_hash, 0x10000f00),
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   288
    'HMAC-MD5': (_doveadmpw, 0x10000f00),
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   289
    'LANMAN': (_doveadmpw, 0x10000f00),
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   290
    'LDAP-MD5': (_md5_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   291
    'MD5': (_crypt_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   292
    'MD5-CRYPT': (_crypt_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   293
    'NTLM': (_ntlm_hash, 0x10000f00),
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   294
    'OTP': (_doveadmpw, 0x10100a01),
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   295
    'PLAIN': (_clear_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   296
    'PLAIN-MD4': (_md4_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   297
    'PLAIN-MD5': (_md5_hash, 0x10000f00),
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   298
    'RPA': (_doveadmpw, 0x10000f00),
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   299
    'SCRAM-SHA-1': (_doveadmpw, 0x20200a01),
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   300
    'SHA': (_sha1_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   301
    'SHA1': (_sha1_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   302
    'SHA256': (_sha256_hash, 0x10100a01),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   303
    'SHA512': (_sha512_hash, 0x20000b03),
722
e37f60b0e3b5 VMM/password: Renamed _dovecotpw() -> _doveadmpw()
Pascal Volk <user@localhost.localdomain.org>
parents: 711
diff changeset
   304
    'SKEY': (_doveadmpw, 0x10100a01),
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   305
    'SMD5': (_smd5_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   306
    'SSHA': (_ssha1_hash, 0x10000f00),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   307
    'SSHA256': (_ssha256_hash, 0x10200a04),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   308
    'SSHA512': (_ssha512_hash, 0x20000b03),
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   309
}
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   310
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   311
461
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   312
def list_schemes():
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   313
    """Returns the tuple (schemes, encodings).
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   314
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   315
    `schemes` is an iterator for all supported password schemes (depends on
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   316
    the used Dovecot version and features of the libc).
691
932cd76bf879 VMM: Dropped support for Dovecot versions before v1.2.0.
Pascal Volk <user@localhost.localdomain.org>
parents: 676
diff changeset
   317
    `encodings` is a tuple with all usable encoding suffixes.
461
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   318
    """
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   319
    dcv = cfg_dget('misc.dovecot_version')
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
   320
    schemes = (k for (k, v) in _scheme_info.items() if v[1] <= dcv)
691
932cd76bf879 VMM: Dropped support for Dovecot versions before v1.2.0.
Pascal Volk <user@localhost.localdomain.org>
parents: 676
diff changeset
   321
    encodings = ('.B64', '.BASE64', '.HEX')
461
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   322
    return schemes, encodings
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   323
cabdf94ec580 VMM/password: Added function list_schemes().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 417
diff changeset
   324
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   325
def verify_scheme(scheme):
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   326
    """Checks if the password scheme *scheme* is known and supported by the
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   327
    configured `misc.dovecot_version`.
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   328
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   329
    The *scheme* maybe a password scheme's name (e.g.: 'PLAIN') or a scheme
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   330
    name with a encoding suffix (e.g. 'PLAIN.BASE64').  If the scheme is
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   331
    known and supported by the used Dovecot version,
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   332
    a tuple ``(scheme, encoding)`` will be returned.
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   333
    The `encoding` in the tuple may be `None`.
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   334
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   335
    Raises a `VMMError` if the password scheme:
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   336
      * is unknown
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   337
      * depends on a newer Dovecot version
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   338
      * has a unknown encoding suffix
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   339
    """
655
2bf68600e914 VMM/password: Code cleanups:
Pascal Volk <user@localhost.localdomain.org>
parents: 651
diff changeset
   340
    assert isinstance(scheme, str), 'Not a str: {!r}'.format(scheme)
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   341
    scheme_encoding = scheme.upper().split('.')
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   342
    scheme = scheme_encoding[0]
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   343
    if scheme not in _scheme_info:
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
   344
        raise VMMError(_("Unsupported password scheme: '%s'") % scheme,
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   345
                       VMM_ERROR)
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   346
    if cfg_dget('misc.dovecot_version') < _scheme_info[scheme][1]:
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
   347
        raise VMMError(_("The password scheme '%(scheme)s' requires Dovecot "
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
   348
                         ">= v%(version)s.") % {'scheme': scheme,
290
e2785e04f92e VMM/…: re-indented long queries and error messages.
Pascal Volk <neverseen@users.sourceforge.net>
parents: 289
diff changeset
   349
                       'version': version_str(_scheme_info[scheme][1])},
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   350
                       VMM_ERROR)
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   351
    if len(scheme_encoding) > 1:
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   352
        if scheme_encoding[1] not in ('B64', 'BASE64', 'HEX'):
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
   353
            raise VMMError(_("Unsupported password encoding: '%s'") %
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   354
                           scheme_encoding[1], VMM_ERROR)
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   355
        encoding = scheme_encoding[1]
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   356
    else:
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   357
        encoding = None
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   358
    return scheme, encoding
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   359
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   360
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   361
def pwhash(password, scheme=None, user=None):
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   362
    """Generates a password hash from the plain text *password* string.
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   363
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   364
    If no *scheme* is given the password scheme from the configuration will
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   365
    be used for the hash generation.  When 'DIGEST-MD5' is used as scheme,
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   366
    also an EmailAddress instance must be given as *user* argument.
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   367
    """
643
df1e3b67882a Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents: 638
diff changeset
   368
    if not isinstance(password, str):
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   369
        raise TypeError('Password is not a string: %r' % password)
655
2bf68600e914 VMM/password: Code cleanups:
Pascal Volk <user@localhost.localdomain.org>
parents: 651
diff changeset
   370
    password = password.encode(ENCODING).strip()
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   371
    if not password:
417
8209da83e256 VMM: Updated some messages. (doesn't, isn't) -> (does not, is not)
Pascal Volk <neverseen@users.sourceforge.net>
parents: 366
diff changeset
   372
        raise ValueError("Could not accept empty password.")
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   373
    if scheme is None:
272
446483386914 VMM/Config: Added method Config.install() -> global cfg_dget().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 268
diff changeset
   374
        scheme = cfg_dget('misc.password_scheme')
287
1e77dd639fa3 VMM/password: moved the 'scheme check' code from pwhash() to the
Pascal Volk <neverseen@users.sourceforge.net>
parents: 284
diff changeset
   375
    scheme, encoding = verify_scheme(scheme)
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   376
    if scheme == 'DIGEST-MD5':
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   377
        assert isinstance(user, EmailAddress)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   378
        return _md5_hash(password, scheme, encoding, user)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   379
    return _scheme_info[scheme][0](password, scheme, encoding)
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   380
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   381
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   382
def randompw():
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   383
    """Generates a plain text random password.
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   384
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   385
    The length of the password can be configured in the ``vmm.cfg``
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   386
    (account.password_length).
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   387
    """
272
446483386914 VMM/Config: Added method Config.install() -> global cfg_dget().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 268
diff changeset
   388
    pw_len = cfg_dget('account.password_length')
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   389
    if pw_len < 8:
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   390
        pw_len = 8
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   391
    return ''.join(_sys_rand.sample(PASSWDCHARS, pw_len))
268
beb8f4421f92 VMM: added new modules password and pycompat.hashlib.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff changeset
   392
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   393
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   394
def _test_crypt_algorithms():
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   395
    """Check for Blowfish/SHA-256/SHA-512 support in crypt.crypt()."""
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   396
    _blowfish = '$2a$04$0123456789abcdefABCDE.N.drYX5yIAL1LkTaaZotW3yI0hQhZru'
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   397
    _sha256 = '$5$rounds=1000$0123456789abcdef$K/DksR0DT01hGc8g/kt9McEgrbFMKi\
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   398
9qrb1jehe7hn4'
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   399
    _sha512 = '$6$rounds=1000$0123456789abcdef$ZIAd5WqfyLkpvsVCVUU1GrvqaZTqvh\
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   400
JoouxdSqJO71l9Ld3tVrfOatEjarhghvEYADkq//LpDnTeO90tcbtHR1'
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   401
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   402
    if crypt('08/15!test~4711', '$2a$04$0123456789abcdefABCDEF$') == _blowfish:
725
300b76de5ad0 VMM/password: Dropped Dovecot v1 compatibility code.
Pascal Volk <user@localhost.localdomain.org>
parents: 722
diff changeset
   403
        _scheme_info['BLF-CRYPT'] = (_crypt_hash, 0x20000b06)
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   404
    if crypt('08/15!test~4711', '$5$rounds=1000$0123456789abcdef$') == _sha256:
725
300b76de5ad0 VMM/password: Dropped Dovecot v1 compatibility code.
Pascal Volk <user@localhost.localdomain.org>
parents: 722
diff changeset
   405
        _scheme_info['SHA256-CRYPT'] = (_crypt_hash, 0x20000b06)
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   406
    if crypt('08/15!test~4711', '$6$rounds=1000$0123456789abcdef$') == _sha512:
725
300b76de5ad0 VMM/password: Dropped Dovecot v1 compatibility code.
Pascal Volk <user@localhost.localdomain.org>
parents: 722
diff changeset
   407
        _scheme_info['SHA512-CRYPT'] = (_crypt_hash, 0x20000b06)
291
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   408
7ef3f117a230 VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent
Pascal Volk <neverseen@users.sourceforge.net>
parents: 290
diff changeset
   409
_test_crypt_algorithms()
284
ec1966828246 VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt().
Pascal Volk <neverseen@users.sourceforge.net>
parents: 274
diff changeset
   410
del _, cfg_dget, _test_crypt_algorithms