diff --git a/docs/releases/4.5.0.rst b/docs/releases/4.5.0.rst index 6b6201a90..2560d5a61 100644 --- a/docs/releases/4.5.0.rst +++ b/docs/releases/4.5.0.rst @@ -66,6 +66,8 @@ Other changes This makes it easier to delete objects created under a legacy IRRD that do not meet current validation requirements. Authentication requirements have not been changed. +* Authoritative creation or updating of route(6) objects for 0.0.0.0/0, + 0.0.0.0/32, ::/0 and ::/128 is no longer allowed. * The ``sources.{name}.nrtm_query_serial_days_limit`` setting was added to limit the age of the oldest serial that can be requested over NRTMv3. * The ``irrd_update_database`` command now starts counting serials from diff --git a/irrd/updates/tests/test_validators.py b/irrd/updates/tests/test_validators.py index 0626e1833..6d3b525af 100644 --- a/irrd/updates/tests/test_validators.py +++ b/irrd/updates/tests/test_validators.py @@ -851,6 +851,14 @@ def prepare_mocks(self, monkeypatch): validator = RulesValidator(mock_dh) yield validator, mock_dsq, mock_dh + def test_check_rejects_default_gateway_route(self, prepare_mocks): + validator, mock_dsq, mock_dh = prepare_mocks + route = rpsl_object_from_text(SAMPLE_ROUTE.replace("192.0.02.0/24", "0.0.0.0/0")) + invalid = validator.validate(route, UpdateRequestType.CREATE) + assert not invalid.is_valid() + assert set(invalid.error_messages) == {"Route(6) objects for 0.0.0.0/0 are not permitted."} + assert validator.validate(route, UpdateRequestType.DELETE).is_valid() + def test_check_suspended_mntner_with_same_pk(self, prepare_mocks, monkeypatch): validator, mock_dsq, mock_dh = prepare_mocks monkeypatch.setattr( diff --git a/irrd/updates/validators.py b/irrd/updates/validators.py index d2b7e4a9d..dbbccfea2 100644 --- a/irrd/updates/validators.py +++ b/irrd/updates/validators.py @@ -13,6 +13,8 @@ from irrd.rpsl.rpsl_objects import ( PROTECTED_NAME_OBJECT_CLASSES, RPSLMntner, + RPSLRoute, + RPSLRoute6, RPSLSet, rpsl_object_from_text, ) @@ -694,15 +696,29 @@ class RulesValidator: This means: anything that is not authentication, references, RPKI or scope filter. """ + BLOCKLIST_ROUTES = [ + IP("0.0.0.0/0"), + IP("0.0.0.0/32"), + IP("::/0"), + IP("::/128"), + ] + def __init__(self, database_handler: DatabaseHandler) -> None: self.database_handler = database_handler def validate(self, rpsl_obj: RPSLObject, request_type: UpdateRequestType) -> ValidatorResult: result = ValidatorResult() + if ( + request_type != UpdateRequestType.DELETE + and (isinstance(rpsl_obj, RPSLRoute) or isinstance(rpsl_obj, RPSLRoute6)) + and rpsl_obj.prefix in self.BLOCKLIST_ROUTES + ): + result.error_messages.add(f"Route(6) objects for {rpsl_obj.prefix} are not permitted.") + if ( request_type == UpdateRequestType.CREATE - and rpsl_obj.rpsl_object_class == "mntner" + and isinstance(rpsl_obj, RPSLMntner) and self._check_suspended_mntner_with_same_pk(rpsl_obj.pk(), rpsl_obj.source()) ): result.error_messages.add(