Beispiel #1
0
    def test_filter_qname(self):
        user1, user2 = self.create_user(), self.create_user()
        domains = {
            user1: ['domain.dedyn.io', 'foobar.example'],
            user2: ['dedyn.io', 'desec.io'],
        }
        for user, names in domains.items():
            for name in names:
                Domain(name=name, owner=user).save()

        config = {
            'domain.dedyn.io': {
                None: ['domain.dedyn.io', 'dedyn.io'],
                user1: ['domain.dedyn.io'],
                user2: ['dedyn.io'],
            },
            'foo.bar.baz.foobar.example': {
                None: ['foobar.example'],
                user1: ['foobar.example'],
                user2: [],
            },
            'dedyn.io': {
                None: ['dedyn.io'],
                user1: [],
                user2: ['dedyn.io'],
            },
            'foobar.desec.io': {
                None: ['desec.io'],
                user1: [],
                user2: ['desec.io'],
            },
        }
        config['sub.domain.dedyn.io'] = config['domain.dedyn.io']

        for qname, cases in config.items():
            for owner, expected in cases.items():
                filter_kwargs = dict(owner=owner) if owner is not None else {}
                qs = Domain.objects.filter_qname(
                    qname, **filter_kwargs).values_list('name', flat=True)
                self.assertListEqual(list(qs), expected)
    def test_create_domain_under_public_suffix_with_private_parent(self):
        name = 'amazonaws.com'
        with self.assertPdnsRequests(
                self.requests_desec_domain_creation(name)
            [:-1]), PDNSChangeTracker():
            Domain(owner=self.create_user(), name=name).save()
            self.assertTrue(Domain.objects.filter(name=name).exists())

        # If amazonaws.com is owned by another user, we cannot register test.s4.amazonaws.com
        name = 'test.s4.amazonaws.com'
        response = self.client.post(self.reverse('v1:domain-list'),
                                    {'name': name})
        self.assertStatus(response, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(response.data['name'][0].code, 'name_unavailable')

        # s3.amazonaws.com is a public suffix. Therefore, test.s3.amazonaws.com can be
        # registered even if the parent zone amazonaws.com is owned by another user
        name = 'test.s3.amazonaws.com'
        psl_cm = self.get_psl_context_manager('s3.amazonaws.com')
        with psl_cm, self.assertPdnsRequests(
                self.requests_desec_domain_creation(name)):
            response = self.client.post(self.reverse('v1:domain-list'),
                                        {'name': name})
            self.assertStatus(response, status.HTTP_201_CREATED)
 def assertNotRegistrable(self, domain_name, user=None):
     """ Raises if the given user (fresh if None) can register the given domain name. """
     self.assertFalse(
         Domain.is_registrable(domain_name, user or self.create_user()),
         f'{domain_name} was expected to be not registrable for {user or "a new user"}, but was.'
     )
Beispiel #4
0
    def perform_create(self, serializer):
        domain_name = serializer.validated_data['name']

        pattern = patternDyn if self.request.user.dyn else patternNonDyn
        if pattern.match(domain_name) is None:
            ex = ValidationError(
                detail={
                    "detail":
                    "This domain name is not well-formed, by policy.",
                    "code": "domain-illformed"
                })
            ex.status_code = status.HTTP_409_CONFLICT
            raise ex

        # Check if domain is a public suffix
        try:
            public_suffix = self.psl.get_public_suffix(domain_name)
            is_public_suffix = self.psl.is_public_suffix(domain_name)
        except psl_dns.exceptions.UnsupportedRule as e:
            # It would probably be fine to just create the domain (with the TLD acting as the
            # public suffix and setting both public_suffix and is_public_suffix accordingly).
            # However, in order to allow to investigate the situation, it's better not catch
            # this exception. Our error handler turns it into a 503 error and makes sure
            # admins are notified.
            raise e

        is_restricted_suffix = is_public_suffix and domain_name not in settings.LOCAL_PUBLIC_SUFFIXES

        # Generate a list of all domains connecting this one and its public suffix.
        # If another user owns a zone with one of these names, then the requested
        # domain is unavailable because it is part of the other user's zone.
        private_components = domain_name.rsplit(public_suffix,
                                                1)[0].rstrip('.')
        private_components = private_components.split(
            '.') if private_components else []
        private_components += [public_suffix]
        private_domains = [
            '.'.join(private_components[i:])
            for i in range(0,
                           len(private_components) - 1)
        ]
        assert is_public_suffix or domain_name == private_domains[0]

        # Deny registration for non-local public suffixes and for domains covered by other users' zones
        queryset = Domain.objects.filter(
            Q(name__in=private_domains) & ~Q(owner=self.request.user))
        if is_restricted_suffix or queryset.exists():
            ex = ValidationError(
                detail={
                    "detail": "This domain name is unavailable.",
                    "code": "domain-unavailable"
                })
            ex.status_code = status.HTTP_409_CONFLICT
            raise ex

        if (self.request.user.limit_domains is not None
                and self.request.user.domains.count() >=
                self.request.user.limit_domains):
            ex = ValidationError(
                detail={
                    "detail":
                    "You reached the maximum number of domains allowed for your account.",
                    "code": "domain-limit"
                })
            ex.status_code = status.HTTP_403_FORBIDDEN
            raise ex

        parent_domain_name = Domain.partition_name(domain_name)[1]
        domain_is_local = parent_domain_name in settings.LOCAL_PUBLIC_SUFFIXES
        try:
            with PDNSChangeTracker():
                domain_kwargs = {'owner': self.request.user}
                if domain_is_local:
                    domain_kwargs['minimum_ttl'] = 60
                domain = serializer.save(**domain_kwargs)
            if domain_is_local:
                parent_domain = Domain.objects.get(name=parent_domain_name)
                # NOTE we need two change trackers here, as the first transaction must be committed to
                # pdns in order to have keys available for the delegation
                with PDNSChangeTracker():
                    parent_domain.update_delegation(domain)
        except PDNSException as e:
            if not str(e).endswith(' already exists'):
                raise e
            ex = ValidationError(
                detail={
                    "detail": "This domain name is unavailable.",
                    "code": "domain-unavailable"
                })
            ex.status_code = status.HTTP_400_BAD_REQUEST
            raise ex

        def send_dyn_dns_email():
            content_tmpl = get_template('emails/domain-dyndns/content.txt')
            subject_tmpl = get_template('emails/domain-dyndns/subject.txt')
            from_tmpl = get_template('emails/from.txt')
            context = {
                'domain': domain_name,
                'url': 'https://update.dedyn.io/',
                'username': domain_name,
                'password': self.request.auth.key
            }
            email = EmailMessage(subject_tmpl.render(context),
                                 content_tmpl.render(context),
                                 from_tmpl.render(context),
                                 [self.request.user.email])
            email.send()

        if domain.name.endswith('.dedyn.io'):
            send_dyn_dns_email()
Beispiel #5
0
 def create_domain(cls, suffix=None, **kwargs):
     kwargs.setdefault('owner', cls.create_user())
     kwargs.setdefault('name', cls.random_domain_name(suffix))
     domain = Domain(**kwargs)
     domain.save()
     return domain
Beispiel #6
0
 def createDomain(cls, owner=None, port=80):
     if owner is None:
         owner = cls.createUser(username=None)
     domain = Domain(name=cls.generateDomainname(), owner=owner)
     domain.save()
     return domain