def check_domain(self, domain, timeout=3, ttl=7200, **options): """Check specified domain.""" mx_list = list( models.MXRecord.objects.get_or_create_for_domain(domain, ttl)) if param_tools.get_global_parameter("enable_mx_checks"): self.check_valid_mx(domain, mx_list, **options) condition = ( not param_tools.get_global_parameter("enable_dnsbl_checks") or options["no_dnsbl"] is True) if condition or not mx_list: return mx_by_ip = {} for mx in mx_list: if mx.address not in mx_by_ip: mx_by_ip[mx.address] = [mx] elif mx not in mx_by_ip[mx.address]: mx_by_ip[mx.address].append(mx) jobs = [ gevent.spawn(self.query_dnsbl, mx_by_ip, provider) for provider in self.providers ] gevent.joinall(jobs, timeout) for job in jobs: if not job.successful(): continue provider, results = job.value self.store_dnsbl_result(domain, provider, results, **options)
def check_domain(self, domain, timeout=3, ttl=7200, **options): """Check specified domain.""" mx_list = list( models.MXRecord.objects.get_or_create_for_domain(domain, ttl)) if param_tools.get_global_parameter("enable_mx_checks"): self.check_valid_mx(domain, mx_list, **options) condition = ( not param_tools.get_global_parameter("enable_dnsbl_checks") or options["no_dnsbl"] is True) if condition or not mx_list: return mx_by_ip = {} for mx in mx_list: if mx.address not in mx_by_ip: mx_by_ip[mx.address] = [mx] elif mx not in mx_by_ip[mx.address]: mx_by_ip[mx.address].append(mx) jobs = [ gevent.spawn(self.query_dnsbl, mx_by_ip, provider) for provider in self.providers] gevent.joinall(jobs, timeout) for job in jobs: if not job.successful(): continue provider, results = job.value self.store_dnsbl_result(domain, provider, results, **options)
def handle(self, *args, **options): if options["logfile"] is None: options["logfile"] = param_tools.get_global_parameter( "logfile", app="maillog") greylist = param_tools.get_global_parameter("greylist", raise_exception=False) p = LogParser(options, param_tools.get_global_parameter("rrd_rootdir"), None, greylist) p.process()
def handle(self, *args, **options): Stats().load() if options["logfile"] is None: options["logfile"] = param_tools.get_global_parameter( "logfile", app="modoboa_stats") p = LogParser( options, param_tools.get_global_parameter("rrd_rootdir", app="modoboa_stats")) p.process()
def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) try: serializer.is_valid(raise_exception=True) except TokenError as e: logger.warning( _("Failed connection attempt from '%s' as user '%s'"), request.META["REMOTE_ADDR"], escape(serializer.data["username"]) ) raise InvalidToken(e.args[0]) user = serializer.user logger.info( _("User '%s' successfully logged in"), user.username ) if user and user.is_active: condition = ( user.is_local and param_tools.get_global_parameter( "update_scheme", raise_exception=False) ) if condition: # check if password scheme is correct scheme = param_tools.get_global_parameter( "password_scheme", raise_exception=False) # use SHA512CRYPT as default fallback if scheme is None: pwhash = get_password_hasher("sha512crypt")() else: pwhash = get_password_hasher(scheme)() if not user.password.startswith(pwhash.scheme): logger.info( _("Password scheme mismatch. Updating %s password"), user.username ) user.set_password(request.data["password"]) user.save() if pwhash.needs_rehash(user.password): logger.info( _("Password hash parameter missmatch. " "Updating %s password"), user.username ) user.set_password(serializer.data["password"]) user.save() return response.Response( serializer.validated_data, status=status.HTTP_200_OK)
def account_auto_created(user): from modoboa.core.models import User from modoboa.lib.permissions import grant_access_to_object from .lib import check_if_domain_exists if not param_tools.get_global_parameter("auto_create_domain_and_mailbox"): return localpart, domname = split_mailbox(user.username) if user.role != 'SimpleUsers' and domname is None: return sadmins = User.objects.filter(is_superuser=True) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: label = check_if_domain_exists( domname, [(DomainAlias, _('domain alias'))]) if label is not None: return domain = Domain(name=domname, enabled=True, quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, domain) try: mb = Mailbox.objects.get(domain=domain, address=localpart) except Mailbox.DoesNotExist: mb = Mailbox( address=localpart, domain=domain, user=user, use_domain_quota=True ) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, mb)
def fill_domain_instances(user, domain, instances): """Set domain instance for resources form.""" if not param_tools.get_global_parameter("enable_domain_limits"): return if not user.has_perm("admin.change_domain"): return instances["resources"] = domain
def get_static_content(caller, st_type, user): condition = (not param_tools.get_global_parameter("enable_admin_limits") or caller not in ["domains", "identities"] or user.role in ["SuperAdmins", "SimpleUsers"]) if condition: return [] if st_type == "css": return [ """<style> .resource { padding: 10px 15px; } .resource .progress { margin-bottom: 0px; } .resource .progress .bar { color: #000000; } </style> """ ] return [ """ <script type="text/javascript"> $(document).ready(function() { $(".progress").tooltip(); }); </script> """ ]
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not param_tools.get_global_parameter("enable_domain_limits", app="limits"): return self.fields["resources"] = DomainResourceSerializer( many=True, source="domainobjectlimit_set", required=False)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not param_tools.get_global_parameter("enable_admin_limits", app="limits"): return self.fields["resources"] = WritableResourceSerializer(many=True, required=False)
def get_static_content(sender, caller, st_type, user, **kwargs): """Add extra static content.""" condition = ( not param_tools.get_global_parameter("enable_admin_limits") or caller not in ["domains", "identities"] or user.role in ["SuperAdmins", "SimpleUsers"] ) if condition: return "" if st_type == "css": return """<style> .resource { padding: 10px 15px; } .resource .progress { margin-bottom: 0px; } .resource .progress .bar { color: #000000; } </style> """ return """
def notify_admins_pending_requests(self): self.sender = param_tools.get_global_parameter( "notifications_sender", app="modoboa_amavis") self.baseurl = self.options["baseurl"].strip("/") self.listingurl = self.baseurl \ + reverse("modoboa_amavis:_mail_list") \ + "?viewrequests=1" for da in User.objects.filter(groups__name="DomainAdmins"): if not hasattr(da, "mailbox"): continue rcpt = da.mailbox.full_address reqs = get_connector().get_domains_pending_requests( Domain.objects.get_for_admin(da) ) if reqs.count(): self.send_pr_notification(rcpt, reqs) reqs = Msgrcpt.objects.filter(rs='p') if not reqs.count(): if self.options["verbose"]: print("No release request currently pending") return for su in User.objects.filter(is_superuser=True): if not hasattr(su, "mailbox"): continue rcpt = su.mailbox.full_address self.send_pr_notification(rcpt, reqs)
def user_can_set_role(sender, user, role, account=None, **kwargs): """Check if the user can still set this role. The only interesting case concerns resellers defining new domain administrators. We want to check if they are allowed to do this operation before any modification is made to :keyword:`account`. :param ``User`` user: connected user :param str role: role to check :param ``User`` account: account modified (None on creation) """ condition = ( not param_tools.get_global_parameter("enable_admin_limits") or role != "DomainAdmins") if condition: return True lname = "domain_admins" condition = ( user.is_superuser or not user.userobjectlimit_set.get(name=lname).is_exceeded() ) if condition: return True if account is not None and account.role == role: return True return False
def clean_quota(self): """Check quota value.""" if self.cleaned_data["quota"] is None: return param_tools.get_global_parameter("default_domain_quota") if self.cleaned_data["quota"] < 0: raise forms.ValidationError(_("Must be a positive integer")) return self.cleaned_data["quota"]
def get_static_content(caller, st_type, user): condition = ( not param_tools.get_global_parameter("enable_admin_limits") or caller not in ["domains", "identities"] or user.role in ["SuperAdmins", "SimpleUsers"] ) if condition: return [] if st_type == "css": return ["""<style> .resource { padding: 10px 15px; } .resource .progress { margin-bottom: 0px; } .resource .progress .bar { color: #000000; } </style> """] return [""" <script type="text/javascript"> $(document).ready(function() { $(".progress").tooltip(); }); </script> """]
def _generate_file(self, target): """ A user must not declare a rule for his direct admin! """ self._cfgfile = open(target, "w") self._cfgfile.write("""# Rights management file for Radicale # This file was generated by Modoboa on %s # DO NOT EDIT MANUALLY! """ % datetime.datetime.today()) allow_calendars_administration = param_tools.get_global_parameter( "allow_calendars_administration", app="modoboa_radicale") if allow_calendars_administration: self._super_admin_rules() self._domain_admin_rules() self._generate_acr("domain-shared-calendars", r"^(.+)@(.+)$", r"{1}/.+$", comment="Access rule to domain shared calendars") self._generate_acr("owners-access", r".+", r"{user}(/.*)?", comment="Read/Write permission for calendar owners") self._user_access_rules() self._token_access_rules() self._cfgfile.close()
def create_new_dkim_key(self, domain): """Create a new DKIM key.""" storage_dir = param_tools.get_global_parameter("dkim_keys_storage_dir") pkey_path = os.path.join(storage_dir, "{}.pem".format(domain.name)) key_size = (domain.dkim_key_length if domain.dkim_key_length else self.default_key_length) code, output = sysutils.exec_cmd("openssl genrsa -out {} {}".format( pkey_path, key_size)) if code: print( "Failed to generate DKIM private key for domain {}: {}".format( domain.name, smart_text(output))) domain.dkim_private_key_path = pkey_path code, output = sysutils.exec_cmd( "openssl rsa -in {} -pubout".format(pkey_path)) if code: print( "Failed to generate DKIM public key for domain {}: {}".format( domain.name, smart_text(output))) public_key = "" for cpt, line in enumerate(smart_text(output).splitlines()): if cpt == 0 or line.startswith("-----"): continue public_key += line domain.dkim_public_key = public_key domain.save(update_fields=["dkim_public_key", "dkim_private_key_path"])
def fill_domain_instances(sender, user, domain, **kwargs): """Set domain instance for resources form.""" condition = (not param_tools.get_global_parameter("enable_domain_limits") or not user.has_perm("admin.change_domain")) if condition: return {} return {"resources": domain}
def account_auto_created(user): from modoboa.core.models import User from modoboa.lib.permissions import grant_access_to_object from .lib import check_if_domain_exists if not param_tools.get_global_parameter("auto_create_domain_and_mailbox"): return localpart, domname = split_mailbox(user.username) if user.role != 'SimpleUsers' and domname is None: return sadmins = User.objects.filter(is_superuser=True) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: label = check_if_domain_exists(domname, [(DomainAlias, _('domain alias'))]) if label is not None: return domain = Domain(name=domname, enabled=True, quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, domain) try: mb = Mailbox.objects.get(domain=domain, address=localpart) except Mailbox.DoesNotExist: mb = Mailbox(address=localpart, domain=domain, user=user, use_domain_quota=True) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, mb)
def handle(self, *args, **options): """Command entry point.""" inactive_account_threshold = param_tools.get_global_parameter( "inactive_account_threshold") qset = models.User.objects.filter( is_active=True, is_superuser=False, last_login__lt=timezone.now() - relativedelta(days=inactive_account_threshold)) if not qset.exists(): return if options["verbose"]: self._log_inactive_accounts(qset) if options["dry_run"]: return action = "delete" if options["delete"] else "disable" if not options["silent"]: answer = input( "Do you want to {} those accounts? (y/N) ".format(action)) if not answer.lower().startswith("y"): return if action == "disable": qset.update(is_active=False) else: qset.delete()
def release_selfservice(request, mail_id): """Release view, self-service mode.""" rcpt = request.GET.get("rcpt", None) secret_id = request.GET.get("secret_id", None) if rcpt is None or secret_id is None: raise BadRequest(_("Invalid request")) connector = SQLconnector() try: msgrcpt = connector.get_recipient_message(rcpt, mail_id) except Msgrcpt.DoesNotExist: raise BadRequest(_("Invalid request")) if secret_id != smart_text(msgrcpt.mail.secret_id): raise BadRequest(_("Invalid request")) if not param_tools.get_global_parameter("user_can_release"): connector.set_msgrcpt_status(rcpt, mail_id, "p") msg = _("Request sent") else: amr = AMrelease() result = amr.sendreq(mail_id, secret_id, rcpt) if result: connector.set_msgrcpt_status(rcpt, mail_id, "R") msg = _("Message released") else: raise BadRequest(result) return render_to_json_response(msg)
def load_from_master_cf(self): """Load services from the master.cf file. Parse the configuration file to update the service table. New entries are saved and outdated ones (ie. present in the database but not in the file) are removed. """ with open(param_tools.get_global_parameter("master_cf_path")) as fp: content = fp.read() services = [] for line in content.split('\n'): if not line or line.startswith('#'): continue parts = line.strip().split() if len(parts) != 8: continue if parts[7] != 'smtp': continue srv, created = self.get_or_create(name=parts[0]) services.append(parts[0]) to_delete = [] for service in self.all(): if service.name not in services: to_delete.append(service.name) Service.objects.filter(name__in=to_delete).delete()
def account_auto_created(sender, user, **kwargs): """New account has been auto-created, build the rest.""" if not param_tools.get_global_parameter("auto_create_domain_and_mailbox"): return localpart, domname = split_mailbox(user.username) if user.role != "SimpleUsers" and domname is None: return sadmins = core_models.User.objects.filter(is_superuser=True) try: domain = models.Domain.objects.get(name=domname) except models.Domain.DoesNotExist: label = lib.check_if_domain_exists( domname, [(models.DomainAlias, _("domain alias"))]) if label is not None: return domain = models.Domain(name=domname, enabled=True, default_mailbox_quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: permissions.grant_access_to_object(su, domain) qset = models.Mailbox.objects.filter(domain=domain, address=localpart) if not qset.exists(): mb = models.Mailbox(address=localpart, domain=domain, user=user, use_domain_quota=True) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) user.email = mb.full_address user.save(update_fields=["email"]) for su in sadmins[1:]: permissions.grant_access_to_object(su, mb)
def display_pool_usage(user, target, currentpage): condition = ( not param_tools.get_global_parameter("enable_admin_limits") or target != "leftcol" or user.is_superuser) if condition: return [] if currentpage == "identities": names = ["mailboxes", "mailbox_aliases"] if user.has_perm("admin.add_domain"): names += ["domain_admins"] else: exceptions = ["domain_admins", "mailboxes", "mailbox_aliases"] names = [ name for name, tpl in utils.get_user_limit_templates() if name not in exceptions and ("required_role" not in tpl or tpl["required_role"] == user.role) ] limits = user.userobjectlimit_set.filter(name__in=names, max_value__gt=0) if len(limits) == 0: return [] return [ render_to_string("limits/poolusage.html", dict(limits=limits)) ]
def account_auto_created(sender, user, **kwargs): """New account has been auto-created, build the rest.""" if not param_tools.get_global_parameter("auto_create_domain_and_mailbox"): return localpart, domname = split_mailbox(user.username) if user.role != 'SimpleUsers' and domname is None: return sadmins = core_models.User.objects.filter(is_superuser=True) try: domain = models.Domain.objects.get(name=domname) except models.Domain.DoesNotExist: label = lib.check_if_domain_exists( domname, [(models.DomainAlias, _("domain alias"))]) if label is not None: return domain = models.Domain( name=domname, enabled=True, default_mailbox_quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: permissions.grant_access_to_object(su, domain) qset = models.Mailbox.objects.filter(domain=domain, address=localpart) if not qset.exists(): mb = models.Mailbox( address=localpart, domain=domain, user=user, use_domain_quota=True ) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: permissions.grant_access_to_object(su, mb)
def user_can_set_role(user, role, account=None): """Check if the user can still set this role. The only interesting case concerns resellers defining new domain administrators. We want to check if they are allowed to do this operation before any modification is made to :keyword:`account`. :param ``User`` user: connected user :param ``User`` account: account modified (None on creation) :param str newrole: role to check """ condition = ( not param_tools.get_global_parameter("enable_admin_limits") or role != "DomainAdmins") if condition: return [True] lname = "domain_admins" condition = ( user.is_superuser or not user.userobjectlimit_set.get(name=lname).is_exceeded() ) if condition: return [True] if account is not None and account.role == role: return [True] return [False]
def url(self): server_location = param_tools.get_global_parameter( "server_location", app="modoboa_radicale") if not server_location: raise lib_exceptions.InternalError( _("Server location is not set, please fix it.")) return os.path.join(server_location, self.user.username, self._path)
def make_password(): """Create a random password.""" length = int( param_tools.get_global_parameter("random_password_length", app="core")) return "".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(length))
def __init__(self, user, *args, **kwargs): self.mb = kwargs.pop("instance", None) self.user = user super().__init__(*args, **kwargs) self.field_widths = {"quota": 3} if self.mb is not None: self.fields["email"].required = True qset = self.mb.aliasrecipient_set.filter(alias__internal=False) for cpt, ralias in enumerate(qset): name = "aliases_{}".format(cpt + 1) self._create_field(lib_fields.UTF8AndEmptyUserEmailField, name, ralias.alias.address) for cpt, saddress in enumerate(self.mb.senderaddress_set.all()): name = "senderaddress_{}".format(cpt + 1) self._create_field(lib_fields.UTF8AndEmptyUserEmailField, name, saddress.address) self.fields["email"].initial = self.mb.full_address self.fields["quota_act"].initial = self.mb.use_domain_quota if not self.mb.use_domain_quota and self.mb.quota: self.fields["quota"].initial = self.mb.quota if self.mb.message_limit: self.fields["message_limit"].initial = self.mb.message_limit self.fields["create_alias_with_old_address"].initial = ( param_tools.get_global_parameter("create_alias_on_mbox_rename") ) else: del self.fields["create_alias_with_old_address"] self.fields["quota_act"].initial = True if len(args) and isinstance(args[0], QueryDict): self._load_from_qdict(args[0], "aliases", lib_fields.UTF8AndEmptyUserEmailField) self._load_from_qdict(args[0], "senderaddress", lib_fields.UTF8AndEmptyUserEmailField)
def _create_mailbox(self, creator, account, data): """Create a new Mailbox instance.""" full_address = data.pop("full_address") address, domain_name = email_utils.split_mailbox(full_address) domain = get_object_or_404( admin_models.Domain, name=domain_name) if not creator.can_access(domain): raise serializers.ValidationError({ "domain": _("Permission denied.")}) try: core_signals.can_create_object.send( sender=self.__class__, context=creator, klass=admin_models.Mailbox) core_signals.can_create_object.send( sender=self.__class__, context=domain, object_type="mailboxes") except lib_exceptions.ModoboaException as inst: raise serializers.ValidationError({ "domain": force_text(inst)}) quota = data.pop("quota", None) mb = admin_models.Mailbox( user=account, address=address, domain=domain, **data) mb.set_quota(quota, creator.has_perm("admin.add_domain")) default_msg_limit = param_tools.get_global_parameter( "default_mailbox_message_limit") if default_msg_limit is not None: mb.message_limit = default_msg_limit mb.save(creator=creator) account.email = full_address return mb
def display_pool_usage(sender, user, location, currentpage, **kwargs): """Display current usage.""" condition = ( not param_tools.get_global_parameter("enable_admin_limits") or location != "leftcol" or user.is_superuser) if condition: return [] if currentpage == "identities": names = ["mailboxes", "mailbox_aliases"] if user.has_perm("admin.add_domain"): names += ["domain_admins"] else: exceptions = ["domain_admins", "mailboxes", "mailbox_aliases"] names = [ name for name, tpl in utils.get_user_limit_templates() if name not in exceptions and ("required_role" not in tpl or tpl["required_role"] == user.role) ] limits = user.userobjectlimit_set.filter(name__in=names, max_value__gt=0) if len(limits) == 0: return [] return [ render_to_string("limits/poolusage.html", {"limits": limits}) ]
def create_new_dkim_key(self, domain): """Create a new DKIM key.""" storage_dir = param_tools.get_global_parameter("dkim_keys_storage_dir") pkey_path = os.path.join(storage_dir, "{}.pem".format(domain.name)) key_size = ( domain.dkim_key_length if domain.dkim_key_length else self.default_key_length) code, output = sysutils.exec_cmd( "openssl genrsa -out {} {}".format(pkey_path, key_size)) if code: print("Failed to generate DKIM private key for domain {}: {}" .format(domain.name, smart_text(output))) domain.dkim_private_key_path = pkey_path code, output = sysutils.exec_cmd( "openssl rsa -in {} -pubout".format(pkey_path)) if code: print("Failed to generate DKIM public key for domain {}: {}" .format(domain.name, smart_text(output))) public_key = "" for cpt, line in enumerate(smart_text(output).splitlines()): if cpt == 0 or line.startswith("-----"): continue public_key += line domain.dkim_public_key = public_key domain.save(update_fields=["dkim_public_key", "dkim_private_key_path"])
def valid_mxs(self): """Return valid MXs set in admin.""" valid_mxs = param_tools.get_global_parameter("valid_mxs") return [ ipaddress.ip_network(u"{}".format(v.strip())) for v in valid_mxs.split() if v.strip() ]
def wrapped_f(request, *args, **kwargs): secret_id = request.GET.get("secret_id") if not secret_id and request.user.is_authenticated: return f(request, *args, **kwargs) if not param_tools.get_global_parameter("self_service"): return redirect_to_login(reverse("modoboa_amavis:index")) return ssfunc(request, *args, **kwargs)
def create(self, validated_data): """Create administrator and other stuff if needed.""" domain_admin = validated_data.pop("domain_admin", None) domain = super().create(validated_data) if not domain_admin: return domain # 1. Create a domain administrator username = "******" % (domain_admin["username"], domain.name) try: da = core_models.User.objects.get(username=username) except core_models.User.DoesNotExist: pass else: raise lib_exceptions.Conflict( _("User '%s' already exists") % username) user = self.context["request"].user core_signals.can_create_object.send(self.__class__, context=user, klass=models.Mailbox) da = core_models.User(username=username, email=username, is_active=True) password = domain_admin.get("password") if password is None: password = param_tools.get_global_parameter("default_password", app="core") da.set_password(password) da.save() da.role = "DomainAdmins" da.post_create(user) # 2. Create mailbox if needed if domain_admin["with_mailbox"]: dom_admin_username = domain_admin["username"] mb = models.Mailbox(address=dom_admin_username, domain=domain, user=da, use_domain_quota=True) mb.set_quota(override_rules=user.has_perm("admin.change_domain")) mb.save(creator=user) # 3. Create aliases if needed condition = (domain.type == "domain" and domain_admin["with_aliases"] and dom_admin_username != "postmaster") if condition: core_signals.can_create_object.send(self.__class__, context=user, klass=models.Alias) address = u"postmaster@{}".format(domain.name) alias = models.Alias.objects.create(address=address, domain=domain, enabled=True) alias.set_recipients([mb.full_address]) alias.post_create(user) domain.add_admin(da) return domain
def make_password(): """Create a random password.""" length = int( param_tools.get_global_parameter("random_password_length", app="core") ) return "".join( random.SystemRandom().choice( string.ascii_letters + string.digits) for _ in range(length))
def check_object_limit(sender, context, object_type, **kwargs): """Check if user can create a new object.""" if context.__class__.__name__ == "User": if not param_tools.get_global_parameter("enable_admin_limits"): return if context.is_superuser: return True limit = context.userobjectlimit_set.get(name=object_type) elif context.__class__.__name__ == "Domain": if not param_tools.get_global_parameter("enable_domain_limits"): return limit = context.domainobjectlimit_set.get(name=object_type) else: raise NotImplementedError count = kwargs.get("count", 1) if limit.is_exceeded(count): raise lib.LimitReached(limit)
def _crypt_password(self, raw_value): """Crypt the local password using the appropriate scheme. In case we don't find the scheme (for example when the management framework is used), we load the parameters and try one more time. """ scheme = param_tools.get_global_parameter( "password_scheme", raise_exception=False) if scheme is None: from modoboa.core.apps import load_core_settings load_core_settings() scheme = param_tools.get_global_parameter( "password_scheme", raise_exception=False) raw_value = smart_bytes(raw_value) return get_password_hasher(scheme.upper())().encrypt(raw_value)
def decrypt(ciph): obj = AES.new( param_tools.get_global_parameter( "secret_key", app="core"), AES.MODE_ECB ) ciph = base64.b64decode(ciph) clear = obj.decrypt(ciph) return clear.rstrip(' ')
def _crypt_password(self, raw_value): """Crypt the local password using the appropriate scheme. In case we don't find the scheme (for example when the management framework is used), we load the parameters and try one more time. """ scheme = param_tools.get_global_parameter("password_scheme", raise_exception=False) if scheme is None: from modoboa.core.apps import load_core_settings load_core_settings() scheme = param_tools.get_global_parameter("password_scheme", raise_exception=False) raw_value = smart_bytes(raw_value) return get_password_hasher(scheme.upper())().encrypt(raw_value)
def get_dns_resolver(): """Return a DNS resolver object.""" dns_server = param_tools.get_global_parameter("custom_dns_server") if dns_server: resolver = dns.resolver.Resolver() resolver.nameservers = [dns_server] else: resolver = dns.resolver return resolver
def fill_domain_instances(sender, user, domain, **kwargs): """Set domain instance for resources form.""" condition = ( not param_tools.get_global_parameter("enable_domain_limits") or not user.has_perm("admin.change_domain") ) if condition: return {} return {"resources": domain}
def rename_dir(self, old_mail_home): """Rename local directory if needed.""" hm = param_tools.get_global_parameter( "handle_mailboxes", raise_exception=False) if not hm: return MailboxOperation.objects.create( mailbox=self, type="rename", argument=old_mail_home )
def encrypt(clear): key = param_tools.get_global_parameter("secret_key", app="core") obj = AES.new(key, AES.MODE_ECB) if type(clear) is unicode: clear = clear.encode("utf-8") if len(clear) % AES.block_size: clear += " " * (AES.block_size - len(clear) % AES.block_size) ciph = obj.encrypt(clear) ciph = base64.b64encode(ciph) return ciph
def clean_oldpassword(self): if self.cleaned_data["oldpassword"] == "": return self.cleaned_data["oldpassword"] if param_tools.get_global_parameter("authentication_type") != "local": return self.cleaned_data["oldpassword"] if not self.instance.check_password(self.cleaned_data["oldpassword"]): raise forms.ValidationError(_("Old password mismatchs")) return self.cleaned_data["oldpassword"]
def check_object_limit(sender, context, **kwargs): """Check if user can create a new object.""" if context.__class__.__name__ == "User": if not param_tools.get_global_parameter("enable_admin_limits"): return if context.is_superuser: return True ct = ContentType.objects.get_for_model(kwargs.get("klass")) limits = context.userobjectlimit_set.filter(content_type=ct) elif context.__class__.__name__ == "Domain": if not param_tools.get_global_parameter("enable_domain_limits"): return object_type = kwargs.get("object_type") limits = context.domainobjectlimit_set.filter(name=object_type) else: raise NotImplementedError for limit in limits: if limit.is_exceeded(kwargs.get("count", 1), kwargs.get("instance")): raise lib.LimitReached(limit)
def fill_account_instances(sender, user, account, **kwargs): """Set account instance for resources form.""" condition = ( not param_tools.get_global_parameter("enable_admin_limits") or (not user.is_superuser and user.role != "Resellers") or account.role not in ["Resellers", "DomainAdmins"] ) if condition: return {} return {"resources": account}
def extra_domain_form(user, domain): """Include domain limits form.""" if not param_tools.get_global_parameter("enable_domain_limits"): return [] if not user.has_perm("admin.change_domain"): return [] return [{ "id": "resources", "title": _("Resources"), "cls": forms.DomainLimitsForm }]
def fill_account_instances(user, account, instances): condition = ( not param_tools.get_global_parameter("enable_admin_limits") or (not user.is_superuser and user.role != "Resellers") ) if condition: return if account.role not in ["Resellers", "DomainAdmins"]: return instances["resources"] = account
def handle(self, *args, **options): """Entry point.""" self.default_key_length = param_tools.get_global_parameter( "dkim_default_key_length") qset = models.Domain.objects.filter( enable_dkim=True, dkim_private_key_path="") for domain in qset: self.create_new_dkim_key(domain) if qset.exists(): signals.new_dkim_keys.send(sender=self.__class__, domains=qset)
def clean_enable_dkim(self): """Check prerequisites.""" enabled = self.cleaned_data.get("enable_dkim") if not enabled: return enabled storage_dir = param_tools.get_global_parameter("dkim_keys_storage_dir") if not storage_dir: raise forms.ValidationError( _("DKIM keys storage directory not configured")) return enabled
def display_domain_limits(sender, user, domain, **kwargs): """Display resources usage for domain.""" if not param_tools.get_global_parameter("enable_domain_limits"): return [] return [{ "column": "right", "template": "limits/resources_widget.html", "context": { "limits": domain.domainobjectlimit_set.all() } }]
def domain_has_authorized_mx(name): """Check if domain has authorized mx record at least.""" valid_mxs = param_tools.get_global_parameter("valid_mxs") valid_mxs = [ipaddress.ip_network(smart_text(v.strip())) for v in valid_mxs.split() if v.strip()] domain_mxs = get_domain_mx_list(name) for _mx_addr, mx_ip_addr in domain_mxs: for subnet in valid_mxs: if mx_ip_addr in subnet: return True return False
def check_domain(self, domain, timeout=3, ttl=7200, **options): """Check specified domain.""" mx_list = list(self.get_mx_records_for_domain(domain, ttl=ttl)) if param_tools.get_global_parameter("enable_mx_checks"): self.check_valid_mx(domain, mx_list, **options) condition = ( not param_tools.get_global_parameter("enable_dnsbl_checks") or options["no_dnsbl"] is True) if condition or not mx_list: return jobs = [ gevent.spawn(self.query_dnsbl, mx_list, provider) for provider in self.providers] gevent.joinall(jobs, timeout) for job in jobs: if not job.successful(): continue provider, results = job.value self.store_dnsbl_result(domain, provider, results, **options)
def handle(self, *args, **options): if options["debug"]: l = logging.getLogger("django.db.backends") l.setLevel(logging.DEBUG) l.addHandler(logging.StreamHandler()) self.verbose = options["verbose"] log_maximum_age = param_tools.get_global_parameter("log_maximum_age") self.__vprint("Deleting logs older than %d days..." % log_maximum_age) limit = timezone.now() - datetime.timedelta(log_maximum_age) Log.objects.filter(date_created__lt=limit).delete() self.__vprint("Done.")
def __init__(self, user, *args, **kwargs): super(AccountFormGeneral, self).__init__(*args, **kwargs) self.fields = OrderedDict( (key, self.fields[key]) for key in ["role", "username", "first_name", "last_name", "password1", "password2", "master_user", "is_active"] ) self.user = user condition = ( user.role == "DomainAdmins" or user.role == "Resellers" and self.instance == user ) if condition: self.fields["role"] = forms.CharField( label="", widget=forms.HiddenInput(attrs={"class": "form-control"}), required=False ) else: self.fields["role"].choices += ( get_account_roles(user, self.instance) if self.instance.pk else get_account_roles(user) ) if not user.is_superuser: del self.fields["master_user"] if not self.instance.pk: return domain_disabled = ( hasattr(self.instance, "mailbox") and not self.instance.mailbox.domain.enabled ) if domain_disabled: self.fields["is_active"].widget.attrs["disabled"] = "disabled" if args: empty_password = ( args[0].get("password1", "") == "" and args[0].get("password2", "") == "") if empty_password: self.fields["password1"].required = False self.fields["password2"].required = False if domain_disabled: del self.fields["is_active"] self.fields["role"].initial = self.instance.role condition = ( not self.instance.is_local and param_tools.get_global_parameter( "ldap_auth_method", app="core") == "directbind") if condition: del self.fields["password1"] del self.fields["password2"]