VirtualMailManager/Handler.py
branchv0.6.x
changeset 278 5d229a50b115
parent 277 e50ffc0b8468
child 280 db35d2eec518
equal deleted inserted replaced
277:e50ffc0b8468 278:5d229a50b115
    19 from subprocess import Popen, PIPE
    19 from subprocess import Popen, PIPE
    20 
    20 
    21 from pyPgSQL import PgSQL  # python-pgsql - http://pypgsql.sourceforge.net
    21 from pyPgSQL import PgSQL  # python-pgsql - http://pypgsql.sourceforge.net
    22 
    22 
    23 import VirtualMailManager.constants.ERROR as ERR
    23 import VirtualMailManager.constants.ERROR as ERR
    24 from VirtualMailManager import ENCODING
       
    25 from VirtualMailManager.Account import Account
    24 from VirtualMailManager.Account import Account
    26 from VirtualMailManager.Alias import Alias
    25 from VirtualMailManager.Alias import Alias
    27 from VirtualMailManager.AliasDomain import AliasDomain
    26 from VirtualMailManager.AliasDomain import AliasDomain
    28 from VirtualMailManager.common import exec_ok
    27 from VirtualMailManager.common import exec_ok
    29 from VirtualMailManager.Config import Config as Cfg
    28 from VirtualMailManager.Config import Config as Cfg
    34 from VirtualMailManager.Relocated import Relocated
    33 from VirtualMailManager.Relocated import Relocated
    35 from VirtualMailManager.Transport import Transport
    34 from VirtualMailManager.Transport import Transport
    36 from VirtualMailManager.ext.Postconf import Postconf
    35 from VirtualMailManager.ext.Postconf import Postconf
    37 
    36 
    38 
    37 
    39 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
       
    40 RE_DOMAIN_SEARCH = """^[a-z0-9-\.]+$"""
    38 RE_DOMAIN_SEARCH = """^[a-z0-9-\.]+$"""
    41 RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$"""
    39 RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$"""
    42 TYPE_ACCOUNT = 0x1
    40 TYPE_ACCOUNT = 0x1
    43 TYPE_ALIAS = 0x2
    41 TYPE_ALIAS = 0x2
    44 TYPE_RELOCATED = 0x4
    42 TYPE_RELOCATED = 0x4
    46 
    44 
    47 
    45 
    48 class Handler(object):
    46 class Handler(object):
    49     """Wrapper class to simplify the access on all the stuff from
    47     """Wrapper class to simplify the access on all the stuff from
    50     VirtualMailManager"""
    48     VirtualMailManager"""
    51     __slots__ = ('_Cfg', '_cfgFileName', '_dbh', '_scheme', '__warnings',
    49     __slots__ = ('_Cfg', '_cfgFileName', '_dbh', '_postconf', '__warnings')
    52                  '_postconf')
       
    53 
    50 
    54     def __init__(self, skip_some_checks=False):
    51     def __init__(self, skip_some_checks=False):
    55         """Creates a new Handler instance.
    52         """Creates a new Handler instance.
    56 
    53 
    57         ``skip_some_checks`` : bool
    54         ``skip_some_checks`` : bool
    73             self._Cfg = Cfg(self._cfgFileName)
    70             self._Cfg = Cfg(self._cfgFileName)
    74             self._Cfg.load()
    71             self._Cfg.load()
    75         if not skip_some_checks:
    72         if not skip_some_checks:
    76             self._Cfg.check()
    73             self._Cfg.check()
    77             self._chkenv()
    74             self._chkenv()
    78             # will be moved to the new password module and Alias
    75             # will be moved to the Alias module
    79             #self._scheme = self._Cfg.dget('misc.password_scheme')
       
    80             #self._postconf = Postconf(self._Cfg.dget('bin.postconf'))
    76             #self._postconf = Postconf(self._Cfg.dget('bin.postconf'))
    81         self._Cfg.install()
    77         self._Cfg.install()
    82 
    78 
    83     def __findCfgFile(self):
    79     def __findCfgFile(self):
    84         for path in ['/root', '/usr/local/etc', '/etc']:
    80         for path in ['/root', '/usr/local/etc', '/etc']:
   324                     raise VMMError(_(
   320                     raise VMMError(_(
   325                         u'Detected group mismatch in domain directory.'),
   321                         u'Detected group mismatch in domain directory.'),
   326                         ERR.DOMAINDIR_GROUP_MISMATCH)
   322                         ERR.DOMAINDIR_GROUP_MISMATCH)
   327                 rmtree(domdirdirs[1], ignore_errors=True)
   323                 rmtree(domdirdirs[1], ignore_errors=True)
   328 
   324 
   329     def __getSalt(self):
       
   330         from random import choice
       
   331         salt = None
       
   332         if self._scheme == 'CRYPT':
       
   333             salt = '%s%s' % (choice(SALTCHARS), choice(SALTCHARS))
       
   334         elif self._scheme in ['MD5', 'MD5-CRYPT']:
       
   335             salt = '$1$%s$' % ''.join([choice(SALTCHARS) for x in xrange(8)])
       
   336         return salt
       
   337 
       
   338     def __pwCrypt(self, password):
       
   339         # for: CRYPT, MD5 and MD5-CRYPT
       
   340         from crypt import crypt
       
   341         return crypt(password, self.__getSalt())
       
   342 
       
   343     def __pwSHA1(self, password):
       
   344         # for: SHA/SHA1
       
   345         import sha
       
   346         from base64 import standard_b64encode
       
   347         sha1 = sha.new(password)
       
   348         return standard_b64encode(sha1.digest())
       
   349 
       
   350     def __pwMD5(self, password, emailaddress=None):
       
   351         import md5
       
   352         _md5 = md5.new(password)
       
   353         if self._scheme == 'LDAP-MD5':
       
   354             from base64 import standard_b64encode
       
   355             return standard_b64encode(_md5.digest())
       
   356         elif self._scheme == 'PLAIN-MD5':
       
   357             return _md5.hexdigest()
       
   358         elif self._scheme == 'DIGEST-MD5' and emailaddress is not None:
       
   359             # use an empty realm - works better with usenames like user@dom
       
   360             _md5 = md5.new('%s::%s' % (emailaddress, password))
       
   361             return _md5.hexdigest()
       
   362 
       
   363     def __pwMD4(self, password):
       
   364         # for: PLAIN-MD4
       
   365         from Crypto.Hash import MD4
       
   366         _md4 = MD4.new(password)
       
   367         return _md4.hexdigest()
       
   368 
       
   369     def __pwhash(self, password, scheme=None, user=None):
       
   370         if scheme is not None:
       
   371             self._scheme = scheme
       
   372         if self._scheme in ['CRYPT', 'MD5', 'MD5-CRYPT']:
       
   373             return '{%s}%s' % (self._scheme, self.__pwCrypt(password))
       
   374         elif self._scheme in ['SHA', 'SHA1']:
       
   375             return '{%s}%s' % (self._scheme, self.__pwSHA1(password))
       
   376         elif self._scheme in ['PLAIN-MD5', 'LDAP-MD5', 'DIGEST-MD5']:
       
   377             return '{%s}%s' % (self._scheme, self.__pwMD5(password, user))
       
   378         elif self._scheme == 'PLAIN-MD4':
       
   379             return '{%s}%s' % (self._scheme, self.__pwMD4(password))
       
   380         elif self._scheme in ['SMD5', 'SSHA', 'CRAM-MD5', 'HMAC-MD5',
       
   381                 'LANMAN', 'NTLM', 'RPA']:
       
   382             cmd_args = [self._Cfg.dget('bin.dovecotpw'), '-s', self._scheme,
       
   383                         '-p', password]
       
   384             if self._Cfg.dget('misc.dovecot_version') >= 0x20000a01:
       
   385                 cmd_args.insert(1, 'pw')
       
   386             return Popen(cmd_args, stdout=PIPE).communicate()[0][:-1]
       
   387         else:
       
   388             return '{%s}%s' % (self._scheme, password)
       
   389 
       
   390     def hasWarnings(self):
   325     def hasWarnings(self):
   391         """Checks if warnings are present, returns bool."""
   326         """Checks if warnings are present, returns bool."""
   392         return bool(len(self.__warnings))
   327         return bool(len(self.__warnings))
   393 
   328 
   394     def getWarnings(self):
   329     def getWarnings(self):