diff --git a/pkilint/cabf/cabf_name.py b/pkilint/cabf/cabf_name.py index 87f9406..485ea4b 100644 --- a/pkilint/cabf/cabf_name.py +++ b/pkilint/cabf/cabf_name.py @@ -59,7 +59,7 @@ class CabfOrganizationIdentifierValidatorBase( "cabf.invalid_organization_identifier_country", ) - # the attribute name for this finding is prefixed with an underscore so it's not flagged by the "validation report" + # the attribute name for this finding is prefixed with an underscore, so it's not flagged by the "validation report" # test _VALIDATION_ORGANIZATION_ID_INVALID_SP_FORMAT = validation.ValidationFinding( validation.ValidationFindingSeverity.ERROR, @@ -191,12 +191,18 @@ def __init__( typing.Mapping[str, organization_id.OrganizationIdentifierElementAllowance] ] = None, enforce_strict_state_province_format=True, + additional_validations: typing.Optional[ + typing.List[validation.ValidationFinding] + ] = None, ): + if additional_validations is None: + additional_validations = [] + super().__init__( self.VALIDATION_ORGANIZATION_ID_INVALID_FORMAT, additional_schemes, enforce_strict_state_province_format, - [self.VALIDATION_ORGANIZATION_ID_INVALID_ENCODING], + [self.VALIDATION_ORGANIZATION_ID_INVALID_ENCODING] + additional_validations, pdu_class=x520_name.X520OrganizationIdentifier, ) diff --git a/pkilint/cabf/smime/smime_name.py b/pkilint/cabf/smime/smime_name.py index dcb9bd2..80aca4a 100644 --- a/pkilint/cabf/smime/smime_name.py +++ b/pkilint/cabf/smime/smime_name.py @@ -264,6 +264,17 @@ class CabfSmimeOrganizationIdentifierAttributeValidator( "cabf.smime.prohibited_organization_identifier_reference_present_for_scheme", ) + """ + From SMBR 7.1.4.2.2 (d): + + For the NTR Registration Scheme, where the Legal Entity is registered within a European country, the NTR + Registration Scheme SHALL be assigned at the country level. + """ + VALIDATION_ORG_ID_NTR_WITH_EU_COUNTRY_AND_STATE_PROVINCE = validation.ValidationFinding( + validation.ValidationFindingSeverity.ERROR, + "cabf.smime.organization_id_has_ntr_scheme_with_eu_country_code_and_state_province", + ) + _LEI_SCHEME = organization_id.OrganizationIdentifierElementAllowance( country_codes=( {organization_id.COUNTRY_CODE_GLOBAL_SCHEME}, @@ -289,6 +300,37 @@ class CabfSmimeOrganizationIdentifierAttributeValidator( reference=_REFERENCE_PROHIBITED, ) + _EU_MEMBER_STATE_COUNTRY_CODES = { + "AT", # Austria + "BE", # Belgium + "BG", # Bulgaria + "HR", # Croatia + "CY", # Cyprus + "CZ", # Czech Republic + "DE", # Germany + "DK", # Denmark + "EE", # Estonia + "ES", # Spain + "FI", # Finland + "FR", # France + "GR", # Greece + "HR", # Croatia + "HU", # Hungary + "IE", # Ireland + "IT", # Italy + "LT", # Lithuania + "LU", # Luxembourg + "LV", # Latvia + "MT", # Malta + "NL", # Netherlands + "PL", # Poland + "PT", # Portugal + "RO", # Romania + "SK", # Slovakia + "SI", # Slovenia + "SE", # Sweden + } + def __init__(self): super().__init__( { @@ -297,8 +339,28 @@ def __init__(self): "INT": self._INT_SCHEME, }, enforce_strict_state_province_format=False, + additional_validations=[ + self.VALIDATION_ORG_ID_NTR_WITH_EU_COUNTRY_AND_STATE_PROVINCE + ], ) + def validate_with_parsed_value(self, node, parsed): + result = super().validate_with_parsed_value(node, parsed) + + if any(result.finding_descriptions): + return validation.ValidationResult(self, node, result.finding_descriptions) + + if ( + parsed.scheme == "NTR" + and parsed.country in self._EU_MEMBER_STATE_COUNTRY_CODES + and parsed.state_province + ): + raise validation.ValidationFindingEncountered( + self.VALIDATION_ORG_ID_NTR_WITH_EU_COUNTRY_AND_STATE_PROVINCE, + f'Organization identifier has NTR scheme with EU member state "{parsed.country}" and ' + f'state/province "{parsed.state_province}": "{parsed.raw}"', + ) + class SubscriberAttributeDependencyValidator(validation.Validator): VALIDATION_MISSING_REQUIRED_ATTRIBUTE = validation.ValidationFinding( diff --git a/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_eu_country_with_state.crttest b/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_eu_country_with_state.crttest new file mode 100644 index 0000000..2b6ffdc --- /dev/null +++ b/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_eu_country_with_state.crttest @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIGXjCCBEagAwIBAgIUT0nGRo909AMp7EmYVoILmgwKMsQwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0 +ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMzA0MjgwMDAwMDBaFw0y +MzA3MjcyMzU5NTlaMHMxJzAlBgNVBGETHk5UUkZSK1BBUi1BRVlFMDBFS1hFU1Za +VVVFQlA2NzEeMBwGA1UEChMVQWNtZSBJbmR1c3RyaWVzLCBMdGQuMSgwJgYJKoZI +hvcNAQkBFhloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAV +SPtRkqsotWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrN +H6l5hvFE89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxq +dMoPvNNUl86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7i +HjVjBd9sB6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3 +tSTT3P593VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABo4ICEzCCAg8w +DAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwHwYDVR0jBBgwFoAU1kQAMnyo +Df+sT2tm7rWumyzFOFQwHQYDVR0OBBYEFIkZWV4O8Wn1y71H4TT84pjMaTCRMBQG +A1UdIAQNMAswCQYHZ4EMAQUCAjA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js +LmNhLmV4YW1wbGUuY29tL2lzc3VpbmdfY2FfY3JsLmNybDBLBggrBgEFBQcBAQQ/ +MD0wOwYIKwYBBQUHMAKGL2h0dHA6Ly9yZXBvc2l0b3J5LmNhLmV4YW1wbGUuY29t +L2lzc3VpbmdfY2EuZGVyMB0GA1UdJQQWMBQGCCsGAQUFBwMEBggrBgEFBQcDAjCB +yAYDVR0RBIHAMIG9gRloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29toCkGCisGAQQB +gjcUAgOgGwwZaGFuYWtvLnlhbWFkYUBleGFtcGxlLmNvbaAmBggrBgEFBQcICaAa +DBjlsbHnlLDoirHlrZBAZXhhbXBsZS5jb22kTTBLMSMwIQYDVQRhExpMRUlYRy1B +RVlFMDBFS1hFU1ZaVVVFQlA2NzEkMCIGA1UECgwb44Ki44Kv44Of5bel5qWt5qCq +5byP5Lya56S+MCMGCSsGAQQBg5gqAQQWExRBRVlFMDBFS1hFU1ZaVVVFQlA2NzAN +BgkqhkiG9w0BAQsFAAOCAgEAALJ+FR219frGJUfrL8xWFfRuFCnLdyzM78Ey0qJq +ZES199XlYozXhMzCUKYN/zbmery90uWNyuJtYGJYl0lhfzBxMmMHk88gCDkLyj8h +4a+r2NiQsiN2bXXp1t5CStQeoaljZL9r2IIERGB+MigR1Rz7g1ECvVo7+llr3/Ew +qV9aa88OtnmQoroSlk86hTGjdEUuixhR2T+/VMEpdlxmimg88E8afa05yc+GBGnx +hyk2zk+nbusC1TrEnMsF2zIaMGlHjMP/v3Gsl1VucFutU06xhItWmWYcHeVr0wLO +/gMDdSbIUgsxobvWynh52D4D1gJsHpnelc5EyGCxhLp7X9tjIy7pSXQAA9fy63cd +Sk6xbpYtlCU/S0PGm+gMMKAydAunL2WgqEwpFB0TwuE+obw3jJI2eO15YFJU5qEt +5eNM2H7KzO0R5lZE0wnbmhgggYGrc6SFsVzgCocwHOtG9hETci6imtbQ8XoiY86K +LUaxYcR4ilXoFj3yhKy8qP7LHdg+sI3/2sIVkoohmnIEidKmO4lhGqavh8bSVLy0 +0PiebItEVoD4hgMtrcl3c8yM7C/cpXtmlRvk49RnJJiSPnSS+34I2DKmhS7ZCqHR +PyUdE6ebULW+ZCNc3vG4yleapzJQiFdUbWgLm8XfBNHSAWs3NvdzV/MqQUERWI3V +EdQ= +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_method_1_identified, +certificate.tbsCertificate.subject.rdnSequence.0.0.value.x520OrganizationIdentifier,CabfSmimeOrganizationIdentifierAttributeValidator,ERROR,cabf.smime.organization_id_has_ntr_scheme_with_eu_country_code_and_state_province,"Organization identifier has NTR scheme with EU member state ""FR"" and state/province ""PAR"": ""NTRFR+PAR-AEYE00EKXESVZUUEBP67""" diff --git a/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_with_3letter_state.crttest b/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_with_3letter_state.crttest index db1cfc2..606fee9 100644 --- a/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_with_3letter_state.crttest +++ b/tests/integration_certificate/smime_br/organization/multipurpose/orgid_ntr_with_3letter_state.crttest @@ -2,7 +2,7 @@ MIIGXjCCBEagAwIBAgIUT0nGRo909AMp7EmYVoILmgwKMsQwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0 ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMzA0MjgwMDAwMDBaFw0y -MzA3MjcyMzU5NTlaMHMxJzAlBgNVBGETHk5UUkZSK1BBUi1BRVlFMDBFS1hFU1Za +MzA3MjcyMzU5NTlaMHMxJzAlBgNVBGETHk5UUlVTK1BBUi1BRVlFMDBFS1hFU1Za VVVFQlA2NzEeMBwGA1UEChMVQWNtZSBJbmR1c3RyaWVzLCBMdGQuMSgwJgYJKoZI hvcNAQkBFhloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAV diff --git a/tests/integration_certificate/test_cabf_smime_cert.py b/tests/integration_certificate/test_cabf_smime_cert.py index d3d2212..b0eb1d8 100644 --- a/tests/integration_certificate/test_cabf_smime_cert.py +++ b/tests/integration_certificate/test_cabf_smime_cert.py @@ -1,9 +1,7 @@ -import functools import glob import sys from os import path -import tests.integration_test_common from pkilint.cabf import smime from pkilint.cabf.smime import smime_constants from pkilint.pkix import certificate diff --git a/tests/integration_certificate/test_etsi_cert.py b/tests/integration_certificate/test_etsi_cert.py index 4db542b..bf4da7a 100644 --- a/tests/integration_certificate/test_etsi_cert.py +++ b/tests/integration_certificate/test_etsi_cert.py @@ -1,9 +1,7 @@ -import functools import glob import sys from os import path -import tests.integration_test_common from pkilint import etsi from pkilint.etsi import etsi_constants from pkilint.pkix import certificate diff --git a/tests/integration_certificate/test_pkix_cert.py b/tests/integration_certificate/test_pkix_cert.py index 94d78b4..668b8d1 100644 --- a/tests/integration_certificate/test_pkix_cert.py +++ b/tests/integration_certificate/test_pkix_cert.py @@ -1,9 +1,7 @@ -import functools import glob import sys from os import path -import tests.integration_test_common from pkilint.pkix import certificate, name, extension from tests.integration_certificate import register_test