Example #1
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))
Example #2
0
def change_password(dn,
                    old_password,
                    new_password,
                    require_cur_passwd=True,
                    conn=None):
    """Change account password.

    If very possible that `old_password` will be set to None/False/<empty>,
    to prevent updating password without old password, we use argument
    `require_old_password=False` instead of use `old_password=None`.
    """

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

    try:
        # Reference: RFC3062 - LDAP Password Modify Extended Operation
        if require_cur_passwd:
            conn.passwd_s(dn, old_password, new_password)
        else:
            # Generate password hash and replace value of 'userPassword' attr.
            pw_hash = iredpwd.generate_password_hash(new_password)

            mod_attr = ldaputils.mod_replace('userPassword', pw_hash)
            conn.modify_s(dn, mod_attr)

        return (True, )
    except ldap.UNWILLING_TO_PERFORM:
        return (False, 'INCORRECT_OLDPW')
    except Exception as e:
        return (False, repr(e))
Example #3
0
def __num_accounts_under_domain(domain,
                                account_type='user',
                                disabled_only=False,
                                first_char=None,
                                update_statistics=False,
                                conn=None):
    """Get number of accounts under specified domain.

    :param domain: domain name you want to query.
    :param account_type: one of 'user', 'list', 'alias', 'ml', 'mixed_ml'.
    :param conn: ldap connection cursor.
    """
    domain = str(domain).lower()
    if not iredutils.is_domain(domain):
        return (False, 'INVALID_DOMAIN_NAME')

    dn_domain = ldaputils.rdn_value_to_domain_dn(domain)

    statistics_attr = None
    if account_type == 'user':
        search_filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % domain
        statistics_attr = 'domainCurrentUserNumber'
    else:
        search_filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % domain

    if disabled_only:
        search_filter = '(&' + search_filter + '(accountStatus=disabled)' + ')'

    if first_char:
        search_filter = '(&' + search_filter + '(|(cn=%s*)(mail=%s*))' + ')'

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

    try:
        qr = conn.search_s(dn_domain,
                           ldap.SCOPE_SUBTREE,
                           search_filter,
                           ['dn'])

        num = len(qr)

        if update_statistics and statistics_attr:
            mod_attr = ldaputils.mod_replace(statistics_attr, num)
            try:
                conn.modify_s(dn_domain, mod_attr)
            except:
                log_traceback()

        return num
    except:
        log_traceback()
        return 0
Example #4
0
def update_attr_with_single_value(dn, attr, value, conn=None):
    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    if isinstance(value, list):
        pass
    elif isinstance(value, (tuple, set)):
        value = list(value)
    elif isinstance(value, int):
        value = [str(value)]
    else:
        value = [str(value)]

    try:
        mod_attr = ldaputils.mod_replace(attr, value)
        conn.modify_s(dn, mod_attr)
        return (True, )
    except ldap.NO_SUCH_OBJECT:
        return (False, 'NO_SUCH_ACCOUNT')
    except Exception as e:
        return (False, repr(e))
Example #5
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)
Example #6
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))
Example #7
0
def update_profile(form, mail, profile_type, conn=None):
    mail = web.safestr(mail).lower()
    username = mail.split('@', 1)[0]

    if (not session.get('is_global_admin')) and (session.get('username') !=
                                                 mail):
        # Don't allow to view/update other admins' profile.
        return (False, 'PERMISSION_DENIED')

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

    dn = ldaputils.rdn_value_to_admin_dn(mail)

    mod_attrs = []
    if profile_type == 'general':
        # Get preferredLanguage.
        lang = form_utils.get_language(form)
        mod_attrs += ldaputils.mod_replace('preferredLanguage', lang)

        # Get cn.
        cn = form.get('cn', None)
        mod_attrs += ldaputils.mod_replace(attr='cn',
                                           value=cn,
                                           default=username)

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

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

        # Get account setting
        _qr = ldap_lib_general.get_admin_account_setting(mail=mail,
                                                         profile=None,
                                                         conn=conn)
        if not _qr[0]:
            return _qr

        _as = _qr[1]

        # Update timezone
        tz_name = form_utils.get_timezone(form)

        if tz_name:
            _as['timezone'] = tz_name

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

        if session.get('is_global_admin'):
            # check account status.
            account_status = 'disabled'
            if 'accountStatus' in form:
                account_status = 'active'

            mod_attrs += ldaputils.mod_replace('accountStatus', account_status)

            # Get domainGlobalAdmin.
            if 'domainGlobalAdmin' in form:
                mod_attrs += ldaputils.mod_replace('domainGlobalAdmin', 'yes')
            else:
                mod_attrs += ldaputils.mod_replace('domainGlobalAdmin', None)

        try:
            # Modify profiles.
            conn.modify_s(dn, mod_attrs)

            if session.get('username') == mail and session.get('lang') != lang:
                session['lang'] = lang
        except Exception as e:
            return (False, repr(e))

    elif profile_type == 'password':
        cur_passwd = web.safestr(form.get('oldpw', ''))
        newpw = web.safestr(form.get('newpw', ''))
        confirmpw = web.safestr(form.get('confirmpw', ''))

        _qr = iredpwd.verify_new_password(newpw, confirmpw)
        if _qr[0]:
            passwd = _qr[1]
        else:
            return _qr

        # Change password.
        if session.get('is_global_admin'):
            # Reset password without verify old password.
            cur_passwd = None

        _qr = ldap_lib_general.change_password(dn=dn,
                                               old_password=cur_passwd,
                                               new_password=passwd,
                                               conn=conn)

        if _qr[0]:
            return (True, )
        else:
            return _qr
    usage()

total = len(users)
logger.info('%d users in total.' % 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, _pw) in users:
        logger.info('(%d/%d) Updating %s' % (count, total, _email))

        dn = rdn_value_to_user_dn(_email)
        pw_hash = generate_password_hash(_pw)
        mod_attrs = mod_replace('userPassword', pw_hash)
        try:
            conn.modify_s(dn, mod_attrs)
        except Exception as e:
            print("<<< ERROR >>> {}".format(repr(e)))
elif backend in ['mysql', 'pgsql']:
    conn = get_db_conn('vmail')
    for (_email, _pw) in users:
        logger.info('(%d/%d) Updating %s' % (count, total, _email))
        pw_hash = generate_password_hash(_pw)
        conn.update('mailbox',
                    password=pw_hash,
                    where="username='******'" % _email)