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 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 __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 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))
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)
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))
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)