コード例 #1
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def is_domain_admin(domain, admin=None, conn=None):
    """Check whether given admin is domain admin. Return True or False."""
    if not admin:
        admin = session.get('username')

    if admin == session.get('username') and session.get('is_global_admin'):
        return True

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

        q_filter = "(&(|(domainName={})(domainAliasName={}))(domainAdmin={}))".format(
            domain,
            domain,
            admin)

        qr = conn.search_s(settings.ldap_basedn,
                           ldap.SCOPE_ONELEVEL,
                           q_filter,
                           ['dn'])

        if qr:
            return True
        else:
            return False
    except:
        return False
コード例 #2
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def is_domain_exists(domain, conn=None):
    # Return True if account is invalid or exist.
    domain = web.safestr(domain).strip().lower()

    if not iredutils.is_domain(domain):
        # Return False if invalid.
        return False

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

    query_filter = '(&'
    query_filter += '(objectClass=mailDomain)'
    query_filter += '(|(domainName={})(domainAliasName={}))'.format(domain, domain)
    query_filter += ')'

    # Check domainName and domainAliasName.
    try:
        qr = conn.search_s(settings.ldap_basedn,
                           ldap.SCOPE_ONELEVEL,
                           query_filter,
                           ['dn'])

        if qr:
            # Domain name exist.
            return True
        else:
            return False
    except:
        # Account 'EXISTS' (fake) if lookup failed.
        return True
コード例 #3
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def enable_disable_mail_accounts(mails, account_type, action, conn=None):
    """Enable (action='enable') or disable (action='disable') given mail users.

    :param mails: a list/tuple/set of user mail addresses
    :param account_type: user, maillist, alias.
    :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

    mapping = {'user': ldaputils.rdn_value_to_user_dn}

    for mail in mails:
        _func = mapping[account_type]
        dn = _func(mail)

        qr = enable_disable_account_by_dn(dn=dn,
                                          action=action,
                                          conn=conn)
        if not qr[0]:
            return qr

    return (True, )
コード例 #4
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def is_global_admin(admin, conn=None):
    if not admin:
        return False

    if admin == session.get('username'):
        if session.get('is_global_admin'):
            return True
        else:
            return False

    # Not logged admin.
    try:
        if not conn:
            _wrap = LDAPWrap()
            conn = _wrap.conn

        _filter = '(&'
        _filter += '(domainGlobalAdmin=yes)'
        _filter += '(|(objectClass=mailUser)(objectClass=mailAdmin))'
        _filter += '(|(mail={})(shadowAddress={}))'.format(admin, admin)
        _filter += ')'

        qr = conn.search_s(settings.ldap_basedn,
                           ldap.SCOPE_BASE,
                           _filter,
                           ['domainGlobalAdmin'])

        if qr:
            return True
        else:
            return False
    except:
        return False
コード例 #5
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
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))
コード例 #6
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def get_profile_by_dn(dn, query_filter=None, attributes=None, conn=None):
    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    if not attributes:
        attributes = ['*']

    if not filter:
        query_filter = "(objectClass=*)"

    try:
        # Query standalone admin account
        qr = conn.search_s(dn,
                           ldap.SCOPE_BASE,
                           query_filter,
                           attributes)

        if qr:
            (_dn, _ldif) = qr[0]
            _ldif = iredutils.bytes2str(_ldif)
            return (True, {'dn': _dn, 'ldif': _ldif})
        else:
            return (False, 'NO_SUCH_ACCOUNT')
    except ldap.NO_SUCH_OBJECT:
        return (False, 'NO_SUCH_ACCOUNT')
    except Exception as e:
        return (False, repr(e))
コード例 #7
0
ファイル: user.py プロジェクト: tellustheguru/iRedAdmin
    def POST(self, profile_type, mail):
        mail = str(mail).lower()
        domain = mail.split('@', 1)[-1]

        _wrap = LDAPWrap()
        conn = _wrap.conn

        # - Allow global admin
        # - normal admin who manages this domain
        # - allow normal admin who doesn't manage this domain, but is updating its own profile
        if not ldap_lib_general.is_domain_admin(
                domain=domain, admin=session.get('username'), conn=conn):
            raise web.seeother('/domains?msg=PERMISSION_DENIED')

        form = web.input(
            domainName=[],  # Managed domains
            oldDomainName=[],  # Old managed domains
            enabledService=[],
            mobile=[],
            title=[],
            telephoneNumber=[],
        )

        result = ldap_lib_user.update(profile_type=profile_type,
                                      mail=mail,
                                      form=form,
                                      conn=conn)

        if result[0]:
            raise web.seeother('/profile/user/{}/{}?msg=UPDATED'.format(
                profile_type, mail))
        else:
            raise web.seeother('/profile/user/{}/{}?msg={}'.format(
                profile_type, mail, web.urlquote(result[1])))
コード例 #8
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def get_allocated_domain_quota(domain, conn=None):
    domain = web.safestr(domain).strip().lower()

    if not iredutils.is_domain(domain):
        return (False, 'INVALID_DOMAIN_NAME')

    dn = ldaputils.rdn_value_to_domain_dn(domain)

    allocated_quota = 0

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

    try:
        # Use '(!([email protected]))' to exclude catch-all account.
        qr = conn.search_s(attrs.DN_BETWEEN_USER_AND_DOMAIN + dn,
                           ldap.SCOPE_SUBTREE,
                           '(objectClass=mailUser)',
                           ['mailQuota'])

        for (_dn, _ldif) in qr:
            _ldif = iredutils.bytes2str(_ldif)
            quota = _ldif.get('mailQuota', ['0'])[0]
            if quota.isdigit():
                allocated_quota += int(quota)

        return (True, allocated_quota)
    except ldap.NO_SUCH_OBJECT:
        return (False, 'NO_SUCH_ACCOUNT')
    except ldap.SIZELIMIT_EXCEEDED:
        return (False, 'EXCEEDED_LDAP_SERVER_SIZELIMIT')
    except Exception as e:
        return (False, repr(e))
コード例 #9
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def add_or_remove_attr_values(dn,
                              attr,
                              values,
                              action,
                              ignore_no_such_object=False,
                              conn=None):
    """Add or remove value of attribute which can handle multiple values.

    :param dn: dn of ldap object
    :param attr: ldap attribute name we need to update
    :param values: values of attribute name
    :param action: to add value, use one of: add, assign, enable
                   to delete value, use one of: del, delete, remove, disable
    :param ignore_no_such_object: do nothing if target object doesn't exist.
    :param conn: ldap connection cursor
    """
    if isinstance(values, (list, tuple, set)):
        values = values
    elif values is None:
        values = None
    else:
        values = [values]

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

    msg = ''
    if action in ['add', 'assign', 'enable']:
        try:
            _ldif = ldaputils.attr_ldif(attr, values, mode='add')
            conn.modify_s(dn, _ldif)
        except ldap.NO_SUCH_OBJECT:
            if ignore_no_such_object:
                pass
            else:
                return (False, 'NO_SUCH_OBJECT')
        except ldap.TYPE_OR_VALUE_EXISTS:
            pass
        except Exception as e:
            msg = repr(e)
    elif action in ['del', 'delete', 'remove', 'disable']:
        try:
            _ldif = ldaputils.attr_ldif(attr, values, mode='delete')
            conn.modify_s(dn, _ldif)
        except ldap.NO_SUCH_OBJECT:
            pass
        except ldap.NO_SUCH_ATTRIBUTE:
            pass
        except Exception as e:
            msg = repr(e)
    else:
        return (False, 'UNKNOWN_ACTION')

    if not msg:
        return (True, )
    else:
        return (False, msg)
コード例 #10
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def filter_existing_emails(mails, base_dn=None, conn=None):
    """
    Remove non-existing addresses from given list of mail addresses, return a
    list of existing ones.

    :param mails: list of email addresses
    :param base_dn: if not present, search from `settings.ldap_basedn`
    :param conn: ldap connection cursor
    """
    mails = [str(v).lower()
             for v in mails
             if iredutils.is_email(v)]
    mails = list(set(mails))

    result = {'exist': [], 'nonexist': []}

    if not mails:
        return result

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

    _filter = '(&'
    _filter += '(|(objectClass=mailUser)(objectClass=mailList)(objectClass=mailAlias))'
    _filter += '(|'
    for addr in mails:
        _filter += '(mail={})(shadowAddress={})'.format(addr, addr)

    _filter += '))'

    if not base_dn:
        base_dn = settings.ldap_basedn

    try:
        qr = conn.search_s(base_dn,
                           ldap.SCOPE_SUBTREE,
                           _filter,
                           ['mail', 'shadowAddress'])

        if not qr:
            # None of them exists.
            result['nonexist'] = mails
        else:
            for (_dn, _ldif) in qr:
                _ldif = iredutils.bytes2str(_ldif)
                result['exist'] += _ldif.get('mail', []) + _ldif.get('shadowAddress', [])

            result['nonexist'] = [v for v in mails if v not in result['exist']]

        # Remove duplicates and sort.
        result['exist'] = list(set(result['exist']))
        result['nonexist'] = list(set(result['nonexist']))
    except:
        log_traceback()

    return result
コード例 #11
0
ファイル: admin.py プロジェクト: tellustheguru/iRedAdmin
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))
コード例 #12
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def __update_num_domain_current_accounts(domain,
                                         increase=False,
                                         decrease=False,
                                         step_number=1,
                                         account_type='user',
                                         conn=None):
    """Increase or decrease number of existing accounts in domain profile."""
    if not isinstance(step_number, int):
        step_number = 1

    if step_number <= 0:
        step_number = 1

    attr_map = {
        'user': '******',
        'alias': 'domainCurrentAliasNumber',
        'maillist': 'domainCurrentListNumber',
    }
    attr_count = attr_map[account_type]

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

    dn = ldaputils.rdn_value_to_domain_dn(domain)

    # Get domain profile first
    try:
        qr = conn.search_s(dn,
                           ldap.SCOPE_BASE,
                           '(&(objectClass=mailDomain)(domainName=%s))' % domain,
                           [attr_count])

    except Exception as e:
        log_traceback()
        return (False, repr(e))

    if qr:
        _ldif = iredutils.bytes2str(qr[0][1])
        _current = int(_ldif.get(attr_count, [0])[0])

        _num = _current
        if increase:
            _num = _current + step_number
        elif decrease:
            _num = _current - step_number

        if _num < 0:
            _num = 0

        # Update count
        update_attr_with_single_value(dn=dn,
                                      attr=attr_count,
                                      value=_num,
                                      conn=conn)

    return (True, )
コード例 #13
0
ファイル: admin.py プロジェクト: tellustheguru/iRedAdmin
def add(form, conn=None):
    """Add new standalone admin account."""
    mail = form_utils.get_single_value(form=form,
                                       input_name='mail',
                                       to_lowercase=True,
                                       to_string=True)

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

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

    # Make sure it's not hosted domain
    domain = mail.split('@', 1)[-1]
    if ldap_lib_general.is_domain_exists(domain=domain, conn=conn):
        return (False, 'CAN_NOT_BE_LOCAL_DOMAIN')

    name = form_utils.get_single_value(form=form, input_name='cn')
    account_status = form_utils.get_single_value(form=form,
                                                 input_name='accountStatus',
                                                 default_value='active',
                                                 to_string=True)
    lang = form_utils.get_single_value(form=form,
                                       input_name='preferredLanguage',
                                       to_string=True)

    # Check password.
    newpw = web.safestr(form.get('newpw'))
    confirmpw = web.safestr(form.get('confirmpw'))

    result = iredpwd.verify_new_password(newpw, confirmpw)
    if result[0] is True:
        passwd = iredpwd.generate_password_hash(result[1])
    else:
        return result

    ldif = iredldif.ldif_mailadmin(mail=mail,
                                   passwd=passwd,
                                   cn=name,
                                   account_status=account_status,
                                   preferred_language=lang)

    dn = ldaputils.rdn_value_to_admin_dn(mail)

    try:
        conn.add_s(dn, ldif)
        log_activity(msg="Create admin: %s." % (mail), event='create')
        return (True, )
    except ldap.ALREADY_EXISTS:
        return (False, 'ALREADY_EXISTS')
    except Exception as e:
        return (False, repr(e))
コード例 #14
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
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
コード例 #15
0
ファイル: admin.py プロジェクト: tellustheguru/iRedAdmin
def get_managed_domains(admin,
                        attributes=None,
                        domain_name_only=True,
                        conn=None):
    """Get domains managed by given admin.

    :param admin: email address of domain admin
    :param attributes: LDAP attribute names used when `domain_name_only=False`.
    :param domain_name_only: If `True`, return a list of domain names.
                             Otherwise return full LDIF data (dict).
    :param conn: ldap connection cursor
    """
    admin = str(admin).lower()
    if not iredutils.is_email(admin):
        return (False, 'INVALID_ADMIN')

    if admin == session.get('username') and session.get('is_global_admin'):
        _filter = '(objectClass=mailDomain)'
    else:
        _filter = '(&(objectClass=mailDomain)(domainAdmin=%s))' % admin

    if not attributes:
        attributes = list(attrs.ADMIN_ATTRS_ALL)

    # We need attr 'domainName'
    if 'domainName' not in attributes:
        attributes.append('domainName')

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

        qr = conn.search_s(settings.ldap_basedn, ldap.SCOPE_ONELEVEL, _filter,
                           attributes)

        if domain_name_only:
            # Return list of domain names.
            domains = []
            for (_dn, _ldif) in qr:
                _ldif = iredutils.bytes2str(_ldif)
                domains += _ldif.get('domainName', [])

            domains = [d.lower() for d in domains]
            domains.sort()

            return (True, domains)
        else:
            qr = iredutils.bytes2str(qr)
            qr.sort()
            return (True, qr)
    except Exception as e:
        return (False, repr(e))
コード例 #16
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def check_account_existence(mail, account_type='mail', conn=None):
    """Return tuple `(True,  )` if object exists, `(False, )` if not exists,
    (None, "<reason>") if something wrong happened.

    @param mail: full email address.
    @param account_type: must be one of: mail, user, alias, ml.
    @param conn: ldap connection cursor.
    """
    if account_type not in ['mail', 'user', 'alias', 'ml']:
        return (None, 'INVALID_ACCOUNT_TYPE')

    mail = str(mail).lower()
    mail = iredutils.strip_mail_ext_address(mail)

    if not iredutils.is_email(mail):
        return (None, 'INVALID_MAIL')

    # Filter used to search account.
    _filter = '(&'
    if account_type == 'mail':
        # mail user, mail alias, mailing list, mlmmj mailing list.
        _filter += '(|(objectClass=mailUser)(objectClass=mailList)(objectClass=mailAlias))'
        _filter += '(|(mail={})(shadowAddress={}))'.format(mail, mail)
    elif account_type == 'user':
        # mail user
        _filter += '(objectClass=mailUser)'
        _filter += '(|(mail={})(shadowAddress={}))'.format(mail, mail)

    _filter += ')'

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

        qr = conn.search_s(settings.ldap_basedn,
                           ldap.SCOPE_SUBTREE,
                           _filter,
                           ['dn'])

        if qr:
            return (True, )
        else:
            return (False, )
    except Exception as e:
        # Account 'EXISTS' (fake) if lookup failed.
        logger.error("Error while checking account existence: "
                     "mail={}, account_type={}, "
                     "error={}".format(mail, account_type, e))

        return (None, 'ERROR_WHILE_QUERYING_DB')
コード例 #17
0
ファイル: domain.py プロジェクト: tellustheguru/iRedAdmin
    def GET(self, profile_type, domain):
        form = web.input()
        domain = web.safestr(domain).lower()

        _wrap = LDAPWrap()
        conn = _wrap.conn

        qr = ldap_lib_domain.get_profile(domain=domain, conn=conn)

        if not qr[0]:
            raise web.seeother('/domains?msg=' + web.urlquote(qr[1]))

        domain_profile = qr[1]['ldif']

        r = ldap_lib_domain.list_accounts(attributes=['domainName'], conn=conn)
        if r[0] is True:
            all_domains = r[1]
        else:
            return r

        domain_account_settings = ldaputils.get_account_setting_from_profile(
            domain_profile)

        (min_passwd_length,
         max_passwd_length) = ldap_lib_general.get_domain_password_lengths(
             domain=domain,
             account_settings=domain_account_settings,
             fallback_to_global_settings=False)

        # Get settings from db.
        _settings = iredutils.get_settings_from_db(
            params=['min_passwd_length', 'max_passwd_length'])
        global_min_passwd_length = _settings['min_passwd_length']
        global_max_passwd_length = _settings['max_passwd_length']

        return web.render(
            'ldap/domain/profile.html',
            cur_domain=domain,
            allDomains=all_domains,
            domain_account_settings=domain_account_settings,
            profile=domain_profile,
            profile_type=profile_type,
            global_min_passwd_length=global_min_passwd_length,
            global_max_passwd_length=global_max_passwd_length,
            min_passwd_length=min_passwd_length,
            max_passwd_length=max_passwd_length,
            timezones=TIMEZONES,
            default_mta_transport=settings.default_mta_transport,
            languagemaps=iredutils.get_language_maps(),
            msg=form.get('msg', None),
        )
コード例 #18
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))
コード例 #19
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))
コード例 #20
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))
コード例 #21
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def filter_existing_domains(domains, conn=None):
    """
    Remove non-existing domains from given list of domains , return a
    dict of existing ones and non-existing ones.

    :param domains: list of domain names
    :param conn: ldap connection cursor
    """
    domains = list({str(v).lower() for v in domains if iredutils.is_domain(v)})

    exist = []
    nonexist = []

    if not domains:
        return {'exist': exist, 'nonexist': nonexist}

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

    _filter = '(&(objectClass=mailDomain)'
    _filter += '(|'
    for d in domains:
        _filter += '(domainName={})(domainAliasName={})'.format(d, d)

    _filter += '))'

    try:
        qr = conn.search_s(settings.ldap_basedn,
                           ldap.SCOPE_ONELEVEL,
                           _filter,
                           ['domainName', 'domainAliasName'])

        if not qr:
            # All are not exist
            nonexist = domains
        else:
            for (_dn, _ldif) in qr:
                _ldif = iredutils.bytes2str(_ldif)
                exist += _ldif.get('domainName', []) + _ldif.get('domainAliasName', [])

            nonexist = [v for v in domains if v not in exist]
    except:
        log_traceback()

    return {'exist': exist, 'nonexist': nonexist}
コード例 #22
0
ファイル: user.py プロジェクト: tellustheguru/iRedAdmin
    def GET(self, domain):
        domain = str(domain).lower()
        form = web.input()

        _wrap = LDAPWrap()
        conn = _wrap.conn

        _attrs = ['domainName', 'accountSetting', 'domainCurrentQuotaSize']
        result = ldap_lib_domain.list_accounts(attributes=_attrs, conn=conn)
        if result[0] is True:
            allDomains = result[1]

            # Get accountSetting of current domain.
            allAccountSettings = ldaputils.get_account_settings_from_qr(
                allDomains)
            domainAccountSetting = allAccountSettings.get(domain, {})

            defaultUserQuota = ldap_lib_domain.get_default_user_quota(
                domain=domain, domain_account_setting=domainAccountSetting)
        else:
            raise web.seeother('/domains?msg=' + web.urlquote(result[1]))

        # Get number of account limit.
        numberOfCurrentAccounts = ldap_lib_general.num_users_under_domain(
            domain=domain, conn=conn)

        (min_passwd_length,
         max_passwd_length) = ldap_lib_general.get_domain_password_lengths(
             domain=domain,
             account_settings=domainAccountSetting,
             fallback_to_global_settings=True,
         )

        return web.render(
            'ldap/user/create.html',
            cur_domain=domain,
            allDomains=allDomains,
            defaultUserQuota=defaultUserQuota,
            domainAccountSetting=domainAccountSetting,
            min_passwd_length=min_passwd_length,
            max_passwd_length=max_passwd_length,
            store_password_in_plain_text=settings.STORE_PASSWORD_IN_PLAIN_TEXT,
            password_policies=iredutils.get_password_policies(),
            numberOfCurrentAccounts=numberOfCurrentAccounts,
            languagemaps=iredutils.get_language_maps(),
            msg=form.get('msg'))
コード例 #23
0
def get_user_forwardings(mail, profile=None, conn=None):
    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    if not profile:
        _qr = get_profile(mail=mail,
                          attributes=['mailForwardingAddress'],
                          conn=conn)
        if not _qr[0]:
            return _qr

        profile = _qr[1]['ldif']

    _addresses = [i.lower() for i in profile.get('mailForwardingAddress', [])]
    _addresses = list(set(_addresses))

    return (True, _addresses)
コード例 #24
0
ファイル: admin.py プロジェクト: tellustheguru/iRedAdmin
def num_managed_domains(admin=None, conn=None):
    if not admin:
        admin = session.get('username')
    else:
        admin = str(admin).lower()
        if not iredutils.is_email(admin):
            return 0

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

    qr = get_managed_domains(admin=admin, conn=conn, attributes=['domainName'])
    if qr[0]:
        domains = qr[1]
        return len(domains)
    else:
        return 0
コード例 #25
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def get_all_domains(attributes=None,
                    search_filter=None,
                    names_only=False,
                    disabled_only=False,
                    starts_with=None,
                    conn=None):
    admin = session['username']

    if not attributes:
        attributes = list(attrs.DOMAIN_SEARCH_ATTRS)

    if not search_filter:
        search_filter = '(&(objectClass=mailDomain)(domainAdmin=%s))' % (admin)
        if session.get('is_global_admin'):
            search_filter = '(objectClass=mailDomain)'

    if disabled_only is True:
        # use "is True" here to prevent client input invalid value in url.
        search_filter = '(&' + search_filter + '(accountStatus=disabled)' + ')'

    if starts_with:
        if iredutils.is_valid_account_first_char(starts_with):
            search_filter = '(&' + search_filter + ('(domainName=%s*)' % starts_with) + ')'

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

    try:
        qr = conn.search_s(settings.ldap_basedn,
                           ldap.SCOPE_ONELEVEL,
                           search_filter,
                           attributes)
        if names_only:
            domain_names = []
            for (_dn, _ldif) in qr:
                _ldif = iredutils.bytes2str(_ldif)
                domain_names += _ldif['domainName']

            return (True, domain_names)
        else:
            return (True, iredutils.bytes2str(qr))
    except Exception as e:
        return (False, repr(e))
コード例 #26
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
def delete_ldap_tree(dn, conn=None):
    """Recursively delete entries under given dn (given dn will be removed too)."""
    errors = {}
    try:
        if not conn:
            _wrap = LDAPWrap()
            conn = _wrap.conn

        qr = conn.search_s(dn,
                           ldap.SCOPE_ONELEVEL,
                           '(objectClass=*)',
                           ['hasSubordinates'])

        dn_without_leaf = []
        dn_with_leaf = []
        for (_dn, _ldif) in qr:
            _ldif = iredutils.bytes2str(_ldif)
            if _ldif['hasSubordinates'][0] == 'TRUE':
                dn_with_leaf.append(_dn)
            else:
                dn_without_leaf.append(_dn)

        if dn_without_leaf:
            for _dn in dn_without_leaf:
                try:
                    conn.delete_s(_dn)
                except Exception as e:
                    errors[_dn] = repr(e)

        for _dn in dn_with_leaf:
            delete_ldap_tree(_dn, conn=conn)

        conn.delete_s(dn)
    except ldap.NO_SUCH_OBJECT:
        pass
    except Exception as e:
        errors[dn] = repr(e)

    if errors:
        return (False, repr(errors))
    else:
        return (True, )
コード例 #27
0
def __unmark_user_as_admin(user, domains=None, all_domains=False, conn=None):
    user = str(user).lower()
    if not iredutils.is_email(user):
        return (False, 'INVALID_MAIL')

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

    if domains:
        try:
            for d in domains:
                domain_dn = ldaputils.rdn_value_to_domain_dn(d)
                qr = ldap_lib_general.remove_attr_values(dn=domain_dn,
                                                         attr='domainAdmin',
                                                         values=[user],
                                                         conn=conn)
                if not qr[0]:
                    return qr

            return (True, )
        except Exception as e:
            return (False, repr(e))
    else:
        if all_domains:
            # Remove this user admin from all domains by default.
            qr_filter = '(&(objectClass=mailDomain)(domainAdmin=%s))' % user

            qr = conn.search_s(settings.ldap_basedn, ldap.SCOPE_ONELEVEL,
                               qr_filter, ['dn'])

            for (dn, _ldif) in qr:
                try:
                    ldap_lib_general.remove_attr_values(dn=dn,
                                                        attr='domainAdmin',
                                                        values=[user],
                                                        conn=conn)
                except Exception as e:
                    return (False, repr(e))

        return (True, )
コード例 #28
0
ファイル: admin.py プロジェクト: tellustheguru/iRedAdmin
def get_standalone_admin_emails(conn=None):
    """Return a list of standalone admins' email addresses."""
    emails = []
    try:
        if not conn:
            _wrap = LDAPWrap()
            conn = _wrap.conn

        qr = conn.search_s(settings.ldap_domainadmin_dn, ldap.SCOPE_ONELEVEL,
                           '(objectClass=mailAdmin)', ['mail'])

        for (_dn, _ldif) in qr:
            _ldif = iredutils.bytes2str(_ldif)
            emails += _ldif['mail']

        # Sort and remove duplicate emails.
        emails = list(set(emails))

        return (True, emails)
    except Exception as e:
        return (False, repr(e))
コード例 #29
0
ファイル: general.py プロジェクト: tellustheguru/iRedAdmin
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, )
コード例 #30
0
ファイル: admin.py プロジェクト: tellustheguru/iRedAdmin
def list_accounts(attributes=None, email_only=False, conn=None):
    """List all admin accounts."""
    if not attributes:
        attributes = list(attrs.ADMIN_SEARCH_ATTRS)

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

    try:
        # Get standalone admins
        qr_admins = conn.search_s(settings.ldap_domainadmin_dn,
                                  ldap.SCOPE_ONELEVEL,
                                  '(objectClass=mailAdmin)', attributes)

        # Get mail users with admin privileges
        _filter = '(&(objectClass=mailUser)(accountStatus=active)(domainGlobalAdmin=yes))'
        qr_users = conn.search_s(settings.ldap_basedn, ldap.SCOPE_SUBTREE,
                                 _filter, attributes)

        if email_only:
            emails = []
            for (_dn, _ldif) in qr_admins:
                _ldif = iredutils.bytes2str(_ldif)
                emails += _ldif.get('mail', [])

            for (_dn, _ldif) in qr_users:
                _ldif = iredutils.bytes2str(_ldif)
                emails += _ldif.get('mail', [])

            # Remove duplicate mail addresses.
            emails = list(set(emails))

            return (True, emails)
        else:
            return (True, iredutils.bytes2str(qr_admins) +
                    iredutils.bytes2str(qr_users))
    except Exception as e:
        return (False, repr(e))