Browse Source

feat(api): ban registering reserved direct children of public suffixes

Peter Thomassen 5 years ago
parent
commit
d0be2e239a
2 changed files with 21 additions and 1 deletions
  1. 8 1
      api/desecapi/models.py
  2. 13 0
      api/desecapi/tests/test_domains.py

+ 8 - 1
api/desecapi/models.py

@@ -273,13 +273,20 @@ class Domain(ExportModelOperationsMixin('Domain'), models.Model):
         Otherwise, True is returned.
         """
         self.clean()  # ensure .name is a domain name
+        private_generation = self.name.count('.') - self.public_suffix.count('.')
+        assert private_generation >= 0
 
         # .internal is reserved
         if f'.{self.name}'.endswith('.internal'):
             return False
 
         # Public suffixes can only be registered if they are local
-        if self.name == self.public_suffix and self.name not in settings.LOCAL_PUBLIC_SUFFIXES:
+        if private_generation == 0 and self.name not in settings.LOCAL_PUBLIC_SUFFIXES:
+            return False
+
+        # Disallow _acme-challenge.dedyn.io and the like. Rejects reserved direct children of public suffixes.
+        reserved_prefixes = ('_', 'autoconfig.', 'autodiscover.',)
+        if private_generation == 1 and any(self.name.startswith(prefix) for prefix in reserved_prefixes):
             return False
 
         # Domains covered by another user's zone can't be registered

+ 13 - 0
api/desecapi/tests/test_domains.py

@@ -73,6 +73,19 @@ class IsRegistrableTestCase(DesecTestCase, PublicSuffixMockMixin):
                 self.assertRegistrable(local_public_suffix)
             self.assertRegistrable('foo.bar.com')
 
+    def test_cant_register_reserved_children_of_public_suffix(self):
+        global_public_suffixes = ['global.public.suffix']
+        local_public_suffixes = ['local.public.suffix']
+        reserved_labels = ['_acme-challenge', '_tcp', '_foobar', 'autodiscover', 'autoconfig']
+        with self.mock(
+            global_public_suffixes=global_public_suffixes,
+            local_public_suffixes=local_public_suffixes,
+        ):
+            for suffix in local_public_suffixes + global_public_suffixes:
+                for label in reserved_labels:
+                    self.assertNotRegistrable(f'{label}.{suffix}')
+                    self.assertRegistrable(f'{label}.sub.{suffix}')
+
     def test_cant_register_descendants_of_children_of_public_suffixes(self):
         with self.mock(
             global_public_suffixes={'public.suffix'},