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
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
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, )
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
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))
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))
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])))
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))
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)
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
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))
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, )
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))
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
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))
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')
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), )
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))
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))
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))
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}
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'))
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)
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
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))
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, )
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, )
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))
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, )
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))