Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
 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()
Пример #4
0
 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()
Пример #5
0
    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)
Пример #6
0
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)
Пример #7
0
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
Пример #8
0
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>
"""
    ]
Пример #9
0
 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)
Пример #10
0
 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)
Пример #11
0
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 """
Пример #12
0
    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)
Пример #13
0
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
Пример #14
0
 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"]
Пример #15
0
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>
"""]
Пример #16
0
    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()
Пример #17
0
 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"])
Пример #18
0
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}
Пример #19
0
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 """
Пример #20
0
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)
Пример #21
0
 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()
Пример #22
0
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)
Пример #23
0
    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()
Пример #24
0
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)
Пример #25
0
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))
    ]
Пример #26
0
    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()
Пример #27
0
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)
Пример #28
0
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
Пример #29
0
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]
Пример #30
0
 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)
Пример #31
0
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))
Пример #32
0
    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)
Пример #33
0
 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
Пример #34
0
 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"]
Пример #35
0
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})
    ]
Пример #36
0
 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"])
Пример #37
0
 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()
     ]
Пример #38
0
 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)
Пример #39
0
    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
Пример #40
0
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))
Пример #41
0
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)
Пример #42
0
    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)
Пример #43
0
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(' ')
Пример #44
0
    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)
Пример #45
0
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
Пример #46
0
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}
Пример #47
0
 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
     )
Пример #48
0
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
Пример #49
0
    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"]
Пример #50
0
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)
Пример #51
0
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}
Пример #52
0
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
    }]
Пример #53
0
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
Пример #54
0
 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)
Пример #55
0
 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
Пример #56
0
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()
        }
    }]
Пример #57
0
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
Пример #58
0
    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)
Пример #59
0
    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.")
Пример #60
0
    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"]