Ejemplo n.º 1
0
def delete(mails, revoke_admin_privilege_from_user=True, conn=None):
    """
    Delete standalone domain admin accounts, or revoke admin privilege from
    mail user which is domain admin.

    :param mails: list of domain admin email addresses
    :param revoke_admin_privilege_from_user: if @mails contains mail user which
              has domain admin privilege, we should revoke the privilege.
    :param conn: ldap connection cursor
    """
    mails = [str(i).lower() for i in mails if iredutils.is_email(i)]
    if not mails:
        return (True, )

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    result = {}

    for mail in mails:
        # Get dn of admin account under o=domainAdmins
        dn = ldaputils.rdn_value_to_admin_dn(mail)

        try:
            conn.delete_s(dn)
            log_activity(msg="Delete admin: %s." % (mail), event='delete')
        except ldap.NO_SUCH_OBJECT:
            if revoke_admin_privilege_from_user:
                # This is a mail user admin
                dn = ldaputils.rdn_value_to_user_dn(mail)
                try:
                    # Delete enabledService=domainadmin
                    ldap_lib_general.remove_attr_values(dn=dn,
                                                        attr='enabledService',
                                                        values=['domainadmin'],
                                                        conn=conn)

                    # Delete domainGlobalAdmin=yes
                    ldap_lib_general.remove_attr_values(
                        dn=dn,
                        attr='domainGlobalAdmin',
                        values=['yes'],
                        conn=conn)

                    log_activity(msg="Revoke domain admin privilege: %s." %
                                 (mail),
                                 event='delete')
                except Exception as e:
                    result[mail] = str(e)
        except ldap.LDAPError as e:
            result[mail] = str(e)

    if result == {}:
        return (True, )
    else:
        return (False, repr(result))
Ejemplo n.º 2
0
def get_user_account_setting(mail, profile=None, conn=None):
    mail = str(mail).lower()
    if not iredutils.is_email(mail):
        return (False, 'INVALID_MAIL')

    if profile:
        dn = None
    else:
        dn = ldaputils.rdn_value_to_user_dn(mail)

    return __get_account_setting_by_dn(dn=dn, profile=profile, conn=conn)
Ejemplo n.º 3
0
def get_profile(mail, attributes=None, conn=None):
    """Get user profile.

    :param mail: full email address or '@domain.com' (catch-all account)
    :param attributes: list of LDAP attribute names
    :param conn: LDAP connection cursor

    Returned data:

    - (True, {'dn': '<full_dn>', 'ldif': dict})
    - (False, <error_reason>)
    """
    if not attributes:
        attributes = list(attrs.USER_ATTRS_ALL)

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    try:
        dn = ldaputils.rdn_value_to_user_dn(mail)
        _filter = '(&(objectClass=mailUser)(mail=%s))' % (mail)

        qr = ldap_lib_general.get_profile_by_dn(dn=dn,
                                                query_filter=_filter,
                                                attributes=attributes,
                                                conn=conn)

        if not qr[0]:
            return qr

        _dn = qr[1]['dn']
        _ldif = qr[1]['ldif']

        # Normal domain admin is not allowed to view/update global admin profile
        if not session.get('is_global_admin'):
            if _ldif.get('domainGlobalAdmin', ['no']) == ['yes']:
                return (False, 'PERMISSION_DENIED_UPDATE_GLOBAL_ADMIN_PROFILE')

        # Sort some lists
        for k in ['shadowAddress', 'mailForwardingAddress']:
            if k in _ldif:
                _addrs = _ldif[k]
                _addrs.sort()
                _ldif[k] = _addrs

        return (True, {'dn': _dn, 'ldif': _ldif})
    except ldap.NO_SUCH_OBJECT:
        return (False, 'NO_SUCH_ACCOUNT')
    except Exception as e:
        return (False, repr(e))
Ejemplo n.º 4
0
def reset_forwardings(mail, forwardings=None, conn=None):
    if forwardings:
        _addresses = [
            str(v).lower() for v in forwardings if iredutils.is_email(v)
        ]
    else:
        _addresses = []

    # Remove duplicate addresses
    if _addresses:
        _addresses = list(set(_addresses))

    # Remove non-existing addresses in same domain.
    domain = mail.split('@', 1)[-1]
    addrs_in_domain = set()
    addrs_not_in_domain = set()

    for addr in _addresses:
        if addr.endswith('@' + domain):
            addrs_in_domain.add(addr)
        else:
            addrs_not_in_domain.add(addr)

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    # Get existing addresses
    valid_addrs_in_domain = set()
    if addrs_in_domain:
        dn = ldaputils.rdn_value_to_domain_dn(domain)
        _qr = ldap_lib_general.filter_existing_emails(mails=addrs_in_domain,
                                                      base_dn=dn,
                                                      conn=conn)

        valid_addrs_in_domain = set(_qr['exist'])

    fwd_addrs = list(valid_addrs_in_domain | addrs_not_in_domain)

    if fwd_addrs:
        mod_attr = ldaputils.mod_replace('mailForwardingAddress', fwd_addrs)
    else:
        mod_attr = ldaputils.mod_replace('mailForwardingAddress', None)

    try:
        dn = ldaputils.rdn_value_to_user_dn(mail)
        conn.modify_s(dn, mod_attr)
        return (True, )
    except Exception as e:
        return (False, repr(e))
Ejemplo n.º 5
0
def mark_unmark_as_admin(domain, mails, action, conn=None):
    domain = str(domain).lower()
    mails = [
        str(v).lower() for v in mails
        if iredutils.is_email(v) and v.endswith('@' + domain)
    ]

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    result = {}
    for mail in mails:
        dn = ldaputils.rdn_value_to_user_dn(mail)

        if action in ['markasadmin', 'unmarkasadmin']:
            update_attribute = 'enabledService'
            update_value = 'domainadmin'
            update_action = 'delete'

            if action == 'markasadmin':
                update_action = 'add'
        elif action in ['markasglobaladmin', 'unmarkasglobaladmin']:
            # Require global admin
            if not session.get('is_global_admin'):
                return (False, 'PERMISSION_DENIED')

            update_attribute = 'domainGlobalAdmin'
            update_value = 'yes'
            update_action = 'delete'

            if action == 'markasglobaladmin':
                update_action = 'add'

        try:
            ldap_lib_general.add_or_remove_attr_values(dn=dn,
                                                       attr=update_attribute,
                                                       values=[update_value],
                                                       action=update_action,
                                                       conn=conn)
        except Exception as e:
            result[mail] = str(e)

    if result == {}:
        return (True, )
    else:
        return (False, repr(result))
Ejemplo n.º 6
0
def enable_disable_admins(mails, action, conn=None):
    """Enable (action='enable') or disable (action='disable') given mail admins.

    :param mails: a list/tuple/set of mail addresses of mail admin accounts
    :param action: enable, disable.
    :param conn: ldap connection cursor
    """
    mails = [str(v).lower() for v in mails if iredutils.is_email(v)]
    action = action.lower()
    if action not in ['enable', 'disable']:
        return (False, 'INVALID_ACTION')

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    for mail in mails:
        # Standalone admin account
        dn = ldaputils.rdn_value_to_admin_dn(mail)
        qr = enable_disable_account_by_dn(dn=dn,
                                          action=action,
                                          conn=conn)

        if not qr[0]:
            if qr[0] == 'NO_SUCH_ACCOUNT':
                # Admin is a normal mail user.
                dn = ldaputils.rdn_value_to_user_dn(mail)
                add_or_remove_attr_values(dn=dn,
                                          attr='enabledService',
                                          values='domainadmin',
                                          action=action,
                                          conn=conn)

                add_or_remove_attr_values(dn=dn,
                                          attr='domainGlobalAdmin',
                                          values='yes',
                                          action=action,
                                          conn=conn)

    return (True, )
Ejemplo n.º 7
0
def get_admin_account_setting(mail, profile=None, conn=None):
    """Get per-admin account settings from account profile (dict of LDIF data).

    :param mail: email address of domain admin
    :param profile: dict of admin profile LDIF data
    :param conn: ldap connection cursor
    """
    mail = str(mail).lower()
    if not iredutils.is_email(mail):
        return (False, 'INVALID_MAIL')

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    if profile:
        _as = ldaputils.get_account_setting_from_profile(profile)
        return (True, _as)
    else:
        # Query standalone admin account first
        dn = ldaputils.rdn_value_to_admin_dn(mail)
        _filter = '(&(objectClass=mailAdmin)(mail=%s))' % mail
        qr = __get_account_setting_by_dn(dn=dn,
                                         query_filter=_filter,
                                         conn=conn)

        if not qr[0]:
            # Query mail user
            dn = ldaputils.rdn_value_to_user_dn(mail)
            _filter = '(&(objectClass=mailUser)(|(enabledService=domainadmin)(domainGlobalAdmin=yes)))'
            qr = __get_account_setting_by_dn(dn=dn,
                                             query_filter=_filter,
                                             conn=conn)
            if not qr[0]:
                return qr

        return (True, qr[1])
Ejemplo n.º 8
0
def update_managed_user_attrs(domain, mail, mod_attrs, conn=None):
    """Update custom LDAP attributes of mail user account.

    @domain - the domain which contains specified user (@mail)
    @mail - full email address of mail user
    @mod_attrs - a list of ldap.MOD_REPLACE actions
    @conn - LDAP connection cursor
    """
    if not mail.endswith('@' + domain):
        raise web.seeother('/domains?msg=PERMISSION_DENIED')

    if not mod_attrs:
        return (True, )

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    try:
        dn = ldaputils.rdn_value_to_user_dn(mail)
        conn.modify_s(dn, mod_attrs)
        return (True, )
    except Exception as e:
        return (False, repr(e))
Ejemplo n.º 9
0
def user_is_global_admin(mail, user_profile=None, conn=None):
    if not user_profile:
        if not conn:
            _wrap = LDAPWrap()
            conn = _wrap.conn

        dn = ldaputils.rdn_value_to_user_dn(mail)
        search_filter = '(&(objectClass=mailUser)(mail=%s))' % (mail)
        search_scope = ldap.SCOPE_BASE
        try:
            qr = conn.search_s(dn, search_scope, search_filter,
                               ['domainGlobalAdmin'])

            if qr:
                user_profile = iredutils.bytes2str(qr[0][1])
        except ldap.NO_SUCH_OBJECT:
            return False
        except:
            return False

    if user_profile.get('domainGlobalAdmin', ['no'])[0] == 'yes':
        return True
    else:
        return False
Ejemplo n.º 10
0
else:
    usage()

total = len(users)
logger.info('{} users in total.'.format(total))

count = 1
if backend == 'ldap':
    from libs.ldaplib.core import LDAPWrap
    from libs.ldaplib.ldaputils import rdn_value_to_user_dn, mod_replace
    _wrap = LDAPWrap()
    conn = _wrap.conn

    for (_email, _quota) in users:
        logger.info('(%d/%d) Updating %s -> %s' %
                    (count, total, _email, _quota))
        dn = rdn_value_to_user_dn(_email)
        mod_attrs = mod_replace('mailQuota', _quota)
        try:
            conn.modify_s(dn, mod_attrs)
        except Exception as e:
            print("<<< ERROR >>> {}".format(e))
elif backend in ['mysql', 'pgsql']:
    conn = get_db_conn('vmail')
    for (_email, _quota) in users:
        logger.info('(%d/%d) Updating %s -> %s' %
                    (count, total, _email, _quota))
        conn.update('mailbox',
                    quota=int(_quota),
                    where="username='******'" % _email)
Ejemplo n.º 11
0
def update(profile_type, mail, form, conn=None):
    profile_type = web.safestr(profile_type)
    mail = str(mail).lower()
    (username, domain) = mail.split('@', 1)

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    # Get account dn.
    dn_user = ldaputils.rdn_value_to_user_dn(mail)

    mod_attrs = []

    qr = ldap_lib_general.get_domain_account_setting(domain=domain, conn=conn)
    if qr[0]:
        domainAccountSetting = qr[1]
    else:
        return qr

    qr = get_profile(mail=mail, conn=conn)
    if qr[0]:
        user_profile = qr[1]['ldif']
        user_account_setting = ldaputils.get_account_setting_from_profile(
            user_profile)
    else:
        return qr

    if profile_type == 'general':
        # Update domainGlobalAdmin=yes
        if session.get('is_global_admin'):
            # Update domainGlobalAdmin=yes
            if 'domainGlobalAdmin' in form:
                mod_attrs = ldaputils.mod_replace('domainGlobalAdmin', 'yes')

                if user_profile.get('domainGlobalAdmin') != ['yes']:
                    log_activity(msg="User %s is marked as global admin." %
                                 mail,
                                 username=mail,
                                 domain=domain,
                                 event='grant')
            else:
                mod_attrs = ldaputils.mod_replace('domainGlobalAdmin', None)

                if user_profile.get('domainGlobalAdmin') == ['yes']:
                    log_activity(msg="User %s is not a global admin anymore." %
                                 mail,
                                 username=mail,
                                 domain=domain,
                                 event='revoke')

        # Get full name, first name, last name.
        # Note: cn, givenName, sn are required by objectClass `inetOrgPerson`.
        cn = form_utils.get_name(form=form, input_name="cn")
        first_name = form_utils.get_single_value(form=form,
                                                 input_name="first_name")
        last_name = form_utils.get_single_value(form=form,
                                                input_name="last_name")

        mod_attrs += ldaputils.mod_replace(attr="cn",
                                           value=cn,
                                           default=username)

        mod_attrs += ldaputils.mod_replace(attr='givenName',
                                           value=first_name,
                                           default=username)

        mod_attrs += ldaputils.mod_replace(attr='sn',
                                           value=last_name,
                                           default=username)

        # Get preferred language: short lang code. e.g. en_US, de_DE.
        preferred_language = form_utils.get_language(form)
        # Must be equal to or less than 5 characters.
        if not (preferred_language in iredutils.get_language_maps()):
            preferred_language = None

        mod_attrs += ldaputils.mod_replace('preferredLanguage',
                                           preferred_language)

        # Update language immediately.
        if session.get('username') == mail and \
           session.get('lang', 'en_US') != preferred_language:
            session['lang'] = preferred_language

        # Update timezone
        tz_name = form_utils.get_timezone(form)

        if qr[0]:
            user_account_setting['timezone'] = tz_name

            if session['username'] == mail and tz_name:
                session['timezone'] = TIMEZONES[tz_name]

        # Update employeeNumber, mobile, title.
        mod_attrs += ldaputils.mod_replace('employeeNumber',
                                           form.get('employeeNumber'))

        ############
        # Reset quota
        #
        # Get new mail quota from web form.
        quota = form_utils.get_single_value(form=form,
                                            input_name='mailQuota',
                                            default_value=0,
                                            is_integer=True)

        # quota must be stored in bytes.
        mod_attrs += ldaputils.mod_replace('mailQuota', quota * 1024 * 1024)

        # Get telephoneNumber, mobile.
        # - multi values are allowed.
        # - non-ascii characters are not allowed.
        for k in ['mobile', 'telephoneNumber']:
            mod_attrs += ldaputils.form_mod_attrs_from_api(form=form,
                                                           input_name=k,
                                                           attr=k,
                                                           to_string=True)

        # Get title, with multiple values.
        for _attr in ['title']:
            _values = [v for v in form.get(_attr, []) if v]

            # Remove duplicate entries
            _values = list(set(_values))

            mod_attrs += ldaputils.mod_replace(attr=_attr, value=_values)

        # check account status.
        accountStatus = 'disabled'
        if 'accountStatus' in form:
            accountStatus = 'active'
        mod_attrs += ldaputils.mod_replace('accountStatus', accountStatus)

    elif profile_type == 'password':
        # Get password length from @domainAccountSetting.
        (min_pw_len,
         max_pw_len) = ldap_lib_general.get_domain_password_lengths(
             domain=domain,
             account_settings=domainAccountSetting,
             fallback_to_global_settings=False,
             conn=conn)

        # Get new passwords from user input.
        newpw = web.safestr(form.get('newpw', ''))
        confirmpw = web.safestr(form.get('confirmpw', ''))

        result = iredpwd.verify_new_password(newpw=newpw,
                                             confirmpw=confirmpw,
                                             min_passwd_length=min_pw_len,
                                             max_passwd_length=max_pw_len)

        if result[0] is True:
            if 'store_password_in_plain_text' in form and settings.STORE_PASSWORD_IN_PLAIN_TEXT:
                passwd = iredpwd.generate_password_hash(result[1],
                                                        pwscheme='PLAIN')
            else:
                passwd = iredpwd.generate_password_hash(result[1])

            mod_attrs += ldaputils.mod_replace('userPassword', passwd)
            mod_attrs += ldaputils.mod_replace(
                'shadowLastChange', ldaputils.get_days_of_shadow_last_change())

            # Always store plain password in another attribute.
            if settings.STORE_PLAIN_PASSWORD_IN_ADDITIONAL_ATTR:
                mod_attrs += ldaputils.mod_replace(
                    settings.STORE_PLAIN_PASSWORD_IN_ADDITIONAL_ATTR, newpw)
        else:
            return result

    # accountSetting
    list_of_account_setting = ldaputils.account_setting_dict_to_list(
        user_account_setting)
    mod_attrs += ldaputils.mod_replace('accountSetting',
                                       list_of_account_setting)

    try:
        conn.modify_s(dn_user, mod_attrs)

        log_activity(msg="Update user profile ({}): {}.".format(
            profile_type, mail),
                     admin=session.get('username'),
                     username=mail,
                     domain=domain,
                     event='update')

        return (True, {})
    except Exception as e:
        return (False, repr(e))
Ejemplo n.º 12
0
def __delete_single_user(mail, keep_mailbox_days=0, conn=None):
    mail = web.safestr(mail)
    if not iredutils.is_email(mail):
        return (False, 'INVALID_MAIL')

    # Get domain name of this account.
    domain = mail.split('@')[-1]

    # Get dn of mail user and domain.
    dn_user = ldaputils.rdn_value_to_user_dn(mail)

    try:
        keep_mailbox_days = int(keep_mailbox_days)
    except:
        if session.get('is_global_admin'):
            keep_mailbox_days = 0
        else:
            _max_days = max(settings.DAYS_TO_KEEP_REMOVED_MAILBOX)
            if keep_mailbox_days > _max_days:
                # Get the max days
                keep_mailbox_days = _max_days

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    # Log maildir path in SQL table.
    try:
        qr = get_profile(mail=mail, conn=conn)
        if not qr[0]:
            if qr[1] == 'NO_SUCH_ACCOUNT':
                # If destination user doesn't exist, don't waste time to check
                # other data.
                return (True, )

            return qr

        user_profile = qr[1]['ldif']

        if 'homeDirectory' in user_profile:
            maildir = user_profile.get('homeDirectory', [''])[0]
        else:
            storageBaseDirectory = user_profile.get('storageBaseDirectory',
                                                    [''])[0]
            mailMessageStore = user_profile.get('mailMessageStore', [''])[0]
            maildir = os.path.join(storageBaseDirectory, mailMessageStore)

        if keep_mailbox_days == 0:
            sql_keep_days = None
        else:
            # Convert keep days to string
            _now_in_seconds = time.time()
            _days_in_seconds = _now_in_seconds + (keep_mailbox_days * 24 * 60 *
                                                  60)
            sql_keep_days = time.strftime('%Y-%m-%d',
                                          time.localtime(_days_in_seconds))

        web.conn_iredadmin.insert(
            'deleted_mailboxes',
            maildir=maildir,
            username=mail,
            domain=domain,
            admin=session.get('username'),
            delete_date=sql_keep_days,
        )
    except:
        pass

    # Delete user object.
    try:
        # Delete object and its subtree.
        _qr = ldap_lib_general.delete_ldap_tree(dn=dn_user, conn=conn)
        if not _qr[0]:
            return _qr

        # Delete record from SQL database: real-time used quota.
        try:
            ldap_lib_general.delete_account_used_quota([mail])
        except:
            pass

        # Log delete action.
        log_activity(msg="Delete user: %s." % (mail),
                     domain=domain,
                     event='delete')

        return (True, )
    except ldap.LDAPError as e:
        return (False, repr(e))
Ejemplo n.º 13
0
def add(domain, form, conn=None):
    # Get domain name, username, cn.
    form_domain = form_utils.get_domain_name(form)
    if not (domain == form_domain):
        return (False, 'INVALID_DOMAIN_NAME')

    username = web.safestr(form.get('username')).strip().lower()
    mail = username + '@' + domain
    mail = iredutils.strip_mail_ext_address(mail)

    if not iredutils.is_auth_email(mail):
        return (False, 'INVALID_MAIL')

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    _qr = ldap_lib_general.check_account_existence(mail=mail,
                                                   account_type='mail',
                                                   conn=conn)
    if _qr[0] is not False:
        return (False, 'ALREADY_EXISTS')

    # Get @domainAccountSetting.
    qr = ldap_lib_domain.get_profile(domain=domain, conn=conn)

    if not qr[0]:
        return qr

    domain_profile = qr[1]['ldif']
    domain_status = domain_profile.get('accountStatus', ['disabled'])[0]
    domainAccountSetting = ldaputils.get_account_setting_from_profile(
        domain_profile)

    # Check account number limit.
    _num_users = domainAccountSetting.get('numberOfUsers')
    if _num_users == '-1':
        return (False, 'NOT_ALLOWED')

    _pw_hash = form.get('password_hash', '')
    if _pw_hash:
        if not iredpwd.is_supported_password_scheme(_pw_hash):
            return (False, 'INVALID_PASSWORD_SCHEME')

        passwd_plain = ''
        passwd_hash = _pw_hash
    else:
        (min_pw_len,
         max_pw_len) = ldap_lib_general.get_domain_password_lengths(
             domain=domain,
             account_settings=domainAccountSetting,
             fallback_to_global_settings=False,
             conn=conn,
         )

        qr = form_utils.get_password(form=form,
                                     input_name='newpw',
                                     confirm_pw_input_name='confirmpw',
                                     min_passwd_length=min_pw_len,
                                     max_passwd_length=max_pw_len)

        if qr[0]:
            passwd_plain = qr[1]['pw_plain']
            passwd_hash = qr[1]['pw_hash']
        else:
            return qr

    cn = form_utils.get_name(form=form, input_name="cn")

    # Get preferred language.
    preferred_language = form_utils.get_language(form=form)
    if preferred_language not in iredutils.get_language_maps():
        preferred_language = None

    # Get user quota. Unit is MB.
    quota = form_utils.get_single_value(form=form,
                                        input_name='mailQuota',
                                        default_value=0,
                                        is_integer=True)

    quota = abs(quota)

    if quota == 0:
        # Get per-domain default user quota
        default_user_quota = ldap_lib_domain.get_default_user_quota(
            domain=domain, domain_account_setting=domainAccountSetting)

        quota = default_user_quota

    defaultStorageBaseDirectory = domainAccountSetting.get(
        'defaultStorageBaseDirectory', None)

    db_settings = iredutils.get_settings_from_db()
    # Get mailbox format and folder.
    _mailbox_format = form.get('mailboxFormat', '').lower()
    _mailbox_folder = form.get('mailboxFolder', '')
    if not iredutils.is_valid_mailbox_format(_mailbox_format):
        _mailbox_format = db_settings['mailbox_format']

    if not iredutils.is_valid_mailbox_folder(_mailbox_folder):
        _mailbox_folder = db_settings['mailbox_folder']

    # Get full maildir path
    _mailbox_maildir = form.get('maildir')

    # Get default mailing lists which set in domain accountSetting.
    ldif = iredldif.ldif_mailuser(
        domain=domain,
        username=username,
        cn=cn,
        passwd=passwd_hash,
        quota=quota,
        storage_base_directory=defaultStorageBaseDirectory,
        mailbox_format=_mailbox_format,
        mailbox_folder=_mailbox_folder,
        mailbox_maildir=_mailbox_maildir,
        language=preferred_language,
        domain_status=domain_status,
    )

    dn_user = ldaputils.rdn_value_to_user_dn(mail)

    # Store plain password in additional attribute
    if passwd_plain and settings.STORE_PLAIN_PASSWORD_IN_ADDITIONAL_ATTR:
        ldif += [(settings.STORE_PLAIN_PASSWORD_IN_ADDITIONAL_ATTR,
                  [passwd_plain])]

    try:
        conn.add_s(dn_user, ldif)

        # Update count of accounts
        ldap_lib_general.update_num_domain_current_users(domain=domain,
                                                         increase=True,
                                                         conn=conn)

        log_activity(msg="Create user: %s." % (mail),
                     domain=domain,
                     event='create')

        return (True, )
    except ldap.ALREADY_EXISTS:
        return (False, 'ALREADY_EXISTS')
    except Exception as e:
        return (False, repr(e))