From e2f7cd7b82555901342cebcd14ec48e7ebaf4955 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 29 Jul 2023 03:03:51 +0200 Subject: [PATCH 1/2] vendor: golang.org/x/crypto v0.3.0 full diff: https://github.com/golang/crypto/compare/v0.2.0...v0.3.0 Signed-off-by: Sebastiaan van Stijn --- go.mod | 2 +- go.sum | 4 ++-- vendor/golang.org/x/crypto/cryptobyte/asn1.go | 4 ++-- vendor/modules.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 70a7904e34..4abc192305 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( go.etcd.io/etcd/pkg/v3 v3.5.6 go.etcd.io/etcd/raft/v3 v3.5.6 go.etcd.io/etcd/server/v3 v3.5.6 - golang.org/x/crypto v0.2.0 + golang.org/x/crypto v0.3.0 golang.org/x/net v0.10.0 golang.org/x/time v0.3.0 diff --git a/go.sum b/go.sum index 5373ad5f19..06c63ca5fa 100644 --- a/go.sum +++ b/go.sum @@ -497,8 +497,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= -golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go index 3a1674a1e5..a64c1d7526 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1.go +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go @@ -532,7 +532,7 @@ func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { return false } - paddingBits := uint8(bytes[0]) + paddingBits := bytes[0] bytes = bytes[1:] if paddingBits > 7 || len(bytes) == 0 && paddingBits != 0 || @@ -554,7 +554,7 @@ func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { return false } - paddingBits := uint8(bytes[0]) + paddingBits := bytes[0] if paddingBits != 0 { return false } diff --git a/vendor/modules.txt b/vendor/modules.txt index 3931b35381..ea8f96a327 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -345,7 +345,7 @@ go.uber.org/zap/internal/bufferpool go.uber.org/zap/internal/color go.uber.org/zap/internal/exit go.uber.org/zap/zapcore -# golang.org/x/crypto v0.2.0 +# golang.org/x/crypto v0.3.0 ## explicit; go 1.17 golang.org/x/crypto/cryptobyte golang.org/x/crypto/cryptobyte/asn1 From f39cdd802e81e149abadddfe7bd8a86acdca0673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert-Andr=C3=A9=20Mauchin?= Date: Thu, 30 Jan 2020 19:49:33 +0100 Subject: [PATCH 2/2] Convert BasicKeyRequest to KeyRequest to use cloudflare/cfssl 1.x.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is asimple patch to update cloudfare/cfssl to a versioned release. It simply moves BasicKeyRequest to KeyRequest and update the vendor directory. It was tested with go test. Fix #3076 Signed-off-by: Robert-André Mauchin Signed-off-by: Sebastiaan van Stijn --- ca/certificates.go | 4 +- ca/certificates_test.go | 4 +- ca/testutils/cautils.go | 6 +- go.mod | 6 +- go.sum | 27 +- vendor/github.com/cloudflare/cfssl/api/api.go | 6 +- .../github.com/cloudflare/cfssl/auth/auth.go | 5 +- .../cloudflare/cfssl/certdb/README.md | 12 +- .../cloudflare/cfssl/certdb/certdb.go | 46 + .../cloudflare/cfssl/config/config.go | 96 +- .../cloudflare/cfssl/crypto/pkcs7/pkcs7.go | 27 +- vendor/github.com/cloudflare/cfssl/csr/csr.go | 145 +- .../github.com/cloudflare/cfssl/errors/doc.go | 1 + .../cfssl/helpers/derhelpers/derhelpers.go | 22 +- .../cfssl/helpers/derhelpers/ed25519.go | 132 + .../cloudflare/cfssl/helpers/helpers.go | 53 +- .../cloudflare/cfssl/initca/initca.go | 4 + .../cloudflare/cfssl/signer/local/local.go | 194 +- .../cloudflare/cfssl/signer/signer.go | 44 +- vendor/github.com/jmoiron/sqlx/LICENSE | 23 + .../github.com/jmoiron/sqlx/types/README.md | 5 + vendor/github.com/jmoiron/sqlx/types/types.go | 172 + .../weppos/publicsuffix-go/LICENSE.txt | 21 + .../publicsuffix/publicsuffix.go | 544 + .../publicsuffix-go/publicsuffix/rules.go | 9188 +++++++++++++++++ vendor/github.com/zmap/zcrypto/LICENSE | 257 + vendor/github.com/zmap/zcrypto/dsa/dsa.go | 309 + .../zcrypto/internal/randutil/randutil.go | 38 + vendor/github.com/zmap/zcrypto/json/dhe.go | 130 + vendor/github.com/zmap/zcrypto/json/ecdhe.go | 107 + vendor/github.com/zmap/zcrypto/json/names.go | 113 + vendor/github.com/zmap/zcrypto/json/rsa.go | 67 + vendor/github.com/zmap/zcrypto/util/isURL.go | 77 + vendor/github.com/zmap/zcrypto/x509/README.md | 8 + .../github.com/zmap/zcrypto/x509/cert_pool.go | 171 + .../zmap/zcrypto/x509/certificate_type.go | 64 + vendor/github.com/zmap/zcrypto/x509/chain.go | 70 + .../zmap/zcrypto/x509/ct/serialization.go | 168 + .../github.com/zmap/zcrypto/x509/ct/types.go | 229 + .../github.com/zmap/zcrypto/x509/example.json | 65 + .../zmap/zcrypto/x509/extended_key_usage.go | 679 ++ .../zcrypto/x509/extended_key_usage_schema.sh | 21 + .../zmap/zcrypto/x509/extensions.go | 818 ++ .../zmap/zcrypto/x509/fingerprint.go | 61 + .../generated_certvalidationlevel_string.go | 16 + vendor/github.com/zmap/zcrypto/x509/json.go | 652 ++ vendor/github.com/zmap/zcrypto/x509/names.go | 30 + .../zmap/zcrypto/x509/pem_decrypt.go | 240 + vendor/github.com/zmap/zcrypto/x509/pkcs1.go | 121 + vendor/github.com/zmap/zcrypto/x509/pkcs8.go | 54 + .../github.com/zmap/zcrypto/x509/pkix/json.go | 279 + .../github.com/zmap/zcrypto/x509/pkix/oid.go | 74 + .../zmap/zcrypto/x509/pkix/oid_names.go | 1014 ++ .../github.com/zmap/zcrypto/x509/pkix/pkix.go | 299 + .../zmap/zcrypto/x509/qc_statements.go | 173 + vendor/github.com/zmap/zcrypto/x509/sec1.go | 105 + .../zcrypto/x509/tor_service_descriptor.go | 158 + .../zmap/zcrypto/x509/validation.go | 60 + vendor/github.com/zmap/zcrypto/x509/verify.go | 635 ++ vendor/github.com/zmap/zcrypto/x509/x509.go | 3042 ++++++ .../github.com/zmap/zlint/v3/.goreleaser.yml | 30 + vendor/github.com/zmap/zlint/v3/LICENSE | 202 + vendor/github.com/zmap/zlint/v3/lint/base.go | 96 + .../zmap/zlint/v3/lint/registration.go | 351 + .../github.com/zmap/zlint/v3/lint/result.go | 106 + .../github.com/zmap/zlint/v3/lint/source.go | 129 + .../lint_ct_sct_policy_count_unsatisfied.go | 157 + ...er_cert_valid_time_longer_than_398_days.go | 61 + ...er_cert_valid_time_longer_than_397_days.go | 67 + .../zmap/zlint/v3/lints/apple/time.go | 13 + .../cabf_br/lint_ca_common_name_missing.go | 50 + .../cabf_br/lint_ca_country_name_invalid.go | 63 + .../cabf_br/lint_ca_country_name_missing.go | 58 + .../lints/cabf_br/lint_ca_crl_sign_not_set.go | 57 + .../lint_ca_digital_signature_not_set.go | 60 + .../zlint/v3/lints/cabf_br/lint_ca_is_ca.go | 63 + .../cabf_br/lint_ca_key_cert_sign_not_set.go | 56 + .../cabf_br/lint_ca_key_usage_missing.go | 58 + .../cabf_br/lint_ca_key_usage_not_critical.go | 56 + .../lint_ca_organization_name_missing.go | 55 + .../lint_cab_dv_conflicts_with_locality.go | 52 + .../cabf_br/lint_cab_dv_conflicts_with_org.go | 62 + .../lint_cab_dv_conflicts_with_postal.go | 62 + .../lint_cab_dv_conflicts_with_province.go | 62 + .../lint_cab_dv_conflicts_with_street.go | 62 + .../lint_cab_iv_requires_personal_name.go | 63 + .../lints/cabf_br/lint_cab_ov_requires_org.go | 62 + .../lint_cert_policy_iv_requires_country.go | 63 + ...policy_iv_requires_province_or_locality.go | 64 + .../lint_cert_policy_ov_requires_country.go | 62 + ...policy_ov_requires_province_or_locality.go | 64 + .../lints/cabf_br/lint_dh_params_missing.go | 56 + .../lint_dnsname_bad_character_in_label.go | 64 + .../lint_dnsname_check_left_label_wildcard.go | 67 + .../lint_dnsname_contains_bare_iana_suffix.go | 56 + .../lint_dnsname_contains_empty_label.go | 68 + .../cabf_br/lint_dnsname_hyphen_in_sld.go | 67 + .../cabf_br/lint_dnsname_label_too_long.go | 70 + .../lint_dnsname_right_label_valid_tld.go | 56 + .../cabf_br/lint_dnsname_underscore_in_sld.go | 67 + .../cabf_br/lint_dnsname_underscore_in_trd.go | 68 + ..._dnsname_wildcard_left_of_public_suffix.go | 67 + ...int_dnsname_wildcard_only_in_left_label.go | 69 + .../lint_dsa_correct_order_in_subgroup.go | 66 + ...nt_dsa_improper_modulus_or_divisor_size.go | 57 + .../lint_dsa_shorter_than_2048_bits.go | 59 + .../lint_dsa_unique_correct_representation.go | 60 + .../lints/cabf_br/lint_ec_improper_curves.go | 71 + .../lint_ext_nc_intersects_reserved_ip.go | 63 + .../lint_ext_san_contains_reserved_ip.go | 52 + .../lint_ext_san_critical_with_subject_dn.go | 61 + .../lint_ext_san_directory_name_present.go | 60 + .../lint_ext_san_edi_party_name_present.go | 60 + .../v3/lints/cabf_br/lint_ext_san_missing.go | 57 + .../lint_ext_san_other_name_present.go | 60 + .../lint_ext_san_registered_id_present.go | 60 + .../lint_ext_san_rfc822_name_present.go | 60 + ...san_uniform_resource_identifier_present.go | 60 + ...ext_tor_service_descriptor_hash_invalid.go | 220 + .../lint_extra_subject_common_names.go | 52 + .../lint_invalid_certificate_version.go | 53 + ...sp_nocheck_ext_not_included_server_auth.go | 55 + ...old_root_ca_rsa_mod_less_than_2048_bits.go | 55 + ..._old_sub_ca_rsa_mod_less_than_1024_bits.go | 59 + ...ld_sub_cert_rsa_mod_less_than_1024_bits.go | 56 + .../lint_public_key_type_not_allowed.go | 51 + ...aints_path_len_constraint_field_present.go | 71 + .../lint_root_ca_contains_cert_policy.go | 55 + ...lint_root_ca_extended_key_usage_present.go | 55 + ...lint_root_ca_key_usage_must_be_critical.go | 51 + .../cabf_br/lint_root_ca_key_usage_present.go | 50 + ...t_rsa_mod_factors_smaller_than_752_bits.go | 59 + .../lint_rsa_mod_less_than_2048_bits.go | 54 + .../v3/lints/cabf_br/lint_rsa_mod_not_odd.go | 61 + .../lint_rsa_public_exponent_not_in_range.go | 65 + .../lint_rsa_public_exponent_not_odd.go | 59 + .../lint_rsa_public_exponent_too_small.go | 59 + .../lint_san_dns_name_onion_invalid.go | 151 + .../lint_san_dns_name_onion_not_ev_cert.go | 69 + .../lint_signature_algorithm_not_supported.go | 87 + ..._ca_aia_does_not_contain_issuing_ca_url.go | 61 + .../lint_sub_ca_aia_marked_critical.go | 51 + .../lints/cabf_br/lint_sub_ca_aia_missing.go | 58 + ...ca_certificate_policies_marked_critical.go | 56 + ...int_sub_ca_certificate_policies_missing.go | 55 + ...istribution_points_does_not_contain_url.go | 59 + ...crl_distribution_points_marked_critical.go | 56 + ..._sub_ca_crl_distribution_points_missing.go | 56 + .../lints/cabf_br/lint_sub_ca_eku_critical.go | 58 + .../lints/cabf_br/lint_sub_ca_eku_missing.go | 50 + .../cabf_br/lint_sub_ca_eku_valid_fields.go | 57 + ...nt_sub_ca_name_constraints_not_critical.go | 61 + ...ert_aia_does_not_contain_issuing_ca_url.go | 60 + ..._sub_cert_aia_does_not_contain_ocsp_url.go | 62 + .../lint_sub_cert_aia_marked_critical.go | 51 + .../cabf_br/lint_sub_cert_aia_missing.go | 59 + .../lint_sub_cert_cert_policy_empty.go | 50 + ...rt_certificate_policies_marked_critical.go | 57 + ...t_sub_cert_certificate_policies_missing.go | 56 + .../lint_sub_cert_country_name_must_appear.go | 51 + ...istribution_points_does_not_contain_url.go | 60 + ...crl_distribution_points_marked_critical.go | 58 + .../cabf_br/lint_sub_cert_eku_extra_values.go | 67 + .../cabf_br/lint_sub_cert_eku_missing.go | 58 + ...ert_eku_server_auth_client_auth_missing.go | 62 + .../lint_sub_cert_gn_sn_contains_policy.go | 52 + .../v3/lints/cabf_br/lint_sub_cert_is_ca.go | 57 + ...nt_sub_cert_key_usage_cert_sign_bit_set.go | 56 + ...int_sub_cert_key_usage_crl_sign_bit_set.go | 56 + ...lint_sub_cert_locality_name_must_appear.go | 53 + ..._sub_cert_locality_name_must_not_appear.go | 51 + .../lint_sub_cert_or_sub_ca_using_sha1.go | 54 + .../lint_sub_cert_postal_code_prohibited.go | 52 + .../lint_sub_cert_province_must_appear.go | 53 + .../lint_sub_cert_province_must_not_appear.go | 51 + .../lint_sub_cert_sha1_expiration_too_long.go | 61 + ...ub_cert_street_address_should_not_exist.go | 52 + ...b_cert_valid_time_longer_than_39_months.go | 49 + ...ub_cert_valid_time_longer_than_825_days.go | 49 + .../lint_subject_common_name_included.go | 55 + .../lint_subject_common_name_not_from_san.go | 69 + ...lint_subject_contains_malformed_arpa_ip.go | 150 + ...subject_contains_noninformational_value.go | 80 + .../lint_subject_contains_reserved_arpa_ip.go | 233 + .../lint_subject_contains_reserved_ip.go | 60 + .../cabf_br/lint_subject_country_not_iso.go | 61 + .../lint_ev_business_category_missing.go | 50 + .../cabf_ev/lint_ev_country_name_missing.go | 50 + .../lint_ev_organization_id_missing.go | 53 + .../lint_ev_organization_name_missing.go | 50 + .../cabf_ev/lint_ev_serial_number_missing.go | 49 + .../cabf_ev/lint_ev_valid_time_too_long.go | 54 + ...t_onion_subject_validity_time_too_large.go | 69 + .../lints/community/lint_ian_bare_wildcard.go | 53 + .../lint_ian_dns_name_includes_null_char.go | 53 + .../lint_ian_dns_name_starts_with_period.go | 53 + .../lint_ian_iana_pub_suffix_empty.go | 53 + .../community/lint_ian_wildcard_not_first.go | 53 + .../lints/community/lint_is_redacted_cert.go | 63 + .../lint_issuer_dn_leading_whitespace.go | 53 + .../lint_issuer_dn_trailing_whitespace.go | 53 + .../community/lint_issuer_multiple_rdn.go | 59 + .../lints/community/lint_rsa_exp_negative.go | 53 + .../lints/community/lint_rsa_no_public_key.go | 53 + .../lints/community/lint_san_bare_wildcard.go | 53 + .../community/lint_san_dns_name_duplicate.go | 58 + .../lint_san_dns_name_includes_null_char.go | 53 + .../lint_san_dns_name_starts_with_period.go | 53 + .../lint_san_iana_pub_suffix_empty.go | 67 + .../community/lint_san_wildcard_not_first.go | 53 + .../lint_subject_dn_leading_whitespace.go | 53 + .../lint_subject_dn_trailing_whitespace.go | 53 + .../community/lint_subject_multiple_rdn.go | 58 + .../lint_validity_time_not_positive.go | 49 + ...lint_qcstatem_etsi_present_qcs_critical.go | 62 + .../etsi/lint_qcstatem_etsi_type_as_statem.go | 69 + .../lint_qcstatem_mandatory_etsi_statems.go | 72 + .../etsi/lint_qcstatem_qccompliance_valid.go | 67 + .../etsi/lint_qcstatem_qclimitvalue_valid.go | 100 + .../etsi/lint_qcstatem_qcpds_lang_case.go | 91 + .../lints/etsi/lint_qcstatem_qcpds_valid.go | 101 + .../lint_qcstatem_qcretentionperiod_valid.go | 74 + .../lints/etsi/lint_qcstatem_qcsscd_valid.go | 68 + .../lints/etsi/lint_qcstatem_qctype_valid.go | 84 + .../v3/lints/etsi/lint_qcstatem_qctype_web.go | 90 + .../v3/lints/mozilla/lint_mp_allowed_eku.go | 76 + ...int_mp_authority_key_identifier_correct.go | 78 + .../lint_mp_ecdsa_pub_key_encoding_correct.go | 88 + ...int_mp_ecdsa_signature_encoding_correct.go | 121 + .../mozilla/lint_mp_exponent_cannot_be_one.go | 66 + ...nt_mp_modulus_must_be_2048_bits_or_more.go | 65 + .../lint_mp_modulus_must_be_divisible_by_8.go | 65 + ...lint_mp_pss_parameters_encoding_correct.go | 101 + .../mozilla/lint_mp_rsassa-pss_in_spki.go | 66 + .../lint_basic_constraints_not_critical.go | 66 + .../lints/rfc/lint_ca_subject_field_empty.go | 62 + .../lint_cert_contains_unique_identifier.go | 62 + .../rfc/lint_cert_extensions_version_not_3.go | 68 + ...rt_unique_identifier_version_not_2_or_3.go | 64 + .../rfc/lint_distribution_point_incomplete.go | 85 + ..._distribution_point_missing_ldap_or_uri.go | 58 + .../v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go | 99 + .../lints/rfc/lint_eku_critical_improperly.go | 67 + .../lint_ext_aia_access_location_missing.go | 64 + .../lints/rfc/lint_ext_aia_marked_critical.go | 56 + ...t_ext_authority_key_identifier_critical.go | 56 + ...nt_ext_authority_key_identifier_missing.go | 65 + ...hority_key_identifier_no_key_identifier.go | 65 + ...lint_ext_cert_policy_contains_noticeref.go | 67 + ..._policy_disallowed_any_policy_qualifier.go | 64 + .../rfc/lint_ext_cert_policy_duplicate.go | 63 + ...xt_cert_policy_explicit_text_ia5_string.go | 72 + ...t_policy_explicit_text_includes_control.go | 91 + ...t_ext_cert_policy_explicit_text_not_nfc.go | 66 + ..._ext_cert_policy_explicit_text_not_utf8.go | 73 + ..._ext_cert_policy_explicit_text_too_long.go | 82 + ...nt_ext_crl_distribution_marked_critical.go | 57 + .../lints/rfc/lint_ext_duplicate_extension.go | 88 + .../lint_ext_freshest_crl_marked_critical.go | 57 + .../v3/lints/rfc/lint_ext_ian_critical.go | 56 + .../rfc/lint_ext_ian_dns_not_ia5_string.go | 74 + .../v3/lints/rfc/lint_ext_ian_empty_name.go | 81 + .../v3/lints/rfc/lint_ext_ian_no_entries.go | 63 + .../rfc/lint_ext_ian_rfc822_format_invalid.go | 70 + .../lints/rfc/lint_ext_ian_space_dns_name.go | 67 + .../rfc/lint_ext_ian_uri_format_invalid.go | 70 + .../lint_ext_ian_uri_host_not_fqdn_or_ip.go | 72 + .../v3/lints/rfc/lint_ext_ian_uri_not_ia5.go | 60 + .../v3/lints/rfc/lint_ext_ian_uri_relative.go | 71 + ...lint_ext_key_usage_cert_sign_without_ca.go | 65 + .../rfc/lint_ext_key_usage_not_critical.go | 56 + .../rfc/lint_ext_key_usage_without_bits.go | 59 + .../lint_ext_name_constraints_not_critical.go | 63 + .../lint_ext_name_constraints_not_in_ca.go | 61 + .../rfc/lint_ext_policy_constraints_empty.go | 76 + ...int_ext_policy_constraints_not_critical.go | 56 + .../rfc/lint_ext_policy_map_any_policy.go | 65 + .../rfc/lint_ext_policy_map_not_critical.go | 57 + .../lint_ext_policy_map_not_in_cert_policy.go | 64 + .../rfc/lint_ext_san_dns_name_too_long.go | 51 + .../rfc/lint_ext_san_dns_not_ia5_string.go | 74 + .../v3/lints/rfc/lint_ext_san_empty_name.go | 81 + .../v3/lints/rfc/lint_ext_san_no_entries.go | 63 + ...nt_ext_san_not_critical_without_subject.go | 63 + .../rfc/lint_ext_san_rfc822_format_invalid.go | 70 + .../lints/rfc/lint_ext_san_space_dns_name.go | 67 + .../rfc/lint_ext_san_uri_format_invalid.go | 70 + .../lint_ext_san_uri_host_not_fqdn_or_ip.go | 79 + .../v3/lints/rfc/lint_ext_san_uri_not_ia5.go | 60 + .../v3/lints/rfc/lint_ext_san_uri_relative.go | 71 + ...int_ext_subject_directory_attr_critical.go | 58 + ...int_ext_subject_key_identifier_critical.go | 56 + ...t_ext_subject_key_identifier_missing_ca.go | 70 + ...subject_key_identifier_missing_sub_cert.go | 70 + ...neralized_time_does_not_include_seconds.go | 98 + ...eralized_time_includes_fraction_seconds.go | 98 + .../rfc/lint_generalized_time_not_in_zulu.go | 78 + .../rfc/lint_idn_dnsname_malformed_unicode.go | 60 + .../lints/rfc/lint_idn_dnsname_must_be_nfc.go | 64 + .../lint_inhibit_any_policy_not_critical.go | 64 + ..._issuer_dn_country_not_printable_string.go | 65 + .../v3/lints/rfc/lint_issuer_field_empty.go | 58 + .../lints/rfc/lint_name_constraint_empty.go | 79 + ...lint_name_constraint_maximum_not_absent.go | 128 + .../lint_name_constraint_minimum_non_zero.go | 128 + .../rfc/lint_name_constraint_not_fqdn.go | 132 + .../lint_name_constraint_on_edi_party_name.go | 62 + .../lint_name_constraint_on_registered_id.go | 62 + .../lints/rfc/lint_name_constraint_on_x400.go | 62 + ...path_len_constraint_improperly_included.go | 73 + .../lint_path_len_constraint_zero_or_less.go | 79 + ...int_serial_number_longer_than_20_octets.go | 89 + .../rfc/lint_serial_number_not_positive.go | 67 + ..._spki_rsa_encryption_parameter_not_null.go | 66 + .../lint_subject_common_name_max_length.go | 59 + ...subject_dn_country_not_printable_string.go | 65 + ...int_subject_dn_not_printable_characters.go | 74 + ...int_subject_dn_serial_number_max_length.go | 51 + ...t_dn_serial_number_not_printable_string.go | 65 + .../rfc/lint_subject_email_max_length.go | 68 + .../rfc/lint_subject_empty_without_san.go | 67 + .../rfc/lint_subject_given_name_max_length.go | 62 + ...int_subject_info_access_marked_critical.go | 54 + .../lint_subject_locality_name_max_length.go | 61 + .../zlint/v3/lints/rfc/lint_subject_not_dn.go | 61 + ...nt_subject_organization_name_max_length.go | 61 + ...ect_organizational_unit_name_max_length.go | 61 + .../lint_subject_postal_code_max_length.go | 62 + .../lint_subject_printable_string_badalpha.go | 109 + .../rfc/lint_subject_state_name_max_length.go | 61 + .../lint_subject_street_address_max_length.go | 60 + .../rfc/lint_subject_surname_max_length.go | 62 + ...ignature_alg_matches_cert_signature_alg.go | 88 + ...ature_rsa_encryption_parameter_not_null.go | 82 + .../lint_utc_time_does_not_include_seconds.go | 82 + .../v3/lints/rfc/lint_utc_time_not_in_zulu.go | 97 + .../rfc/lint_wrong_time_format_pre2050.go | 86 + vendor/github.com/zmap/zlint/v3/makefile | 42 + vendor/github.com/zmap/zlint/v3/newLint.sh | 50 + vendor/github.com/zmap/zlint/v3/resultset.go | 58 + vendor/github.com/zmap/zlint/v3/template | 45 + .../zlint/v3/util/algorithm_identifier.go | 190 + vendor/github.com/zmap/zlint/v3/util/ca.go | 64 + .../zmap/zlint/v3/util/countries.go | 51 + vendor/github.com/zmap/zlint/v3/util/eku.go | 14 + .../zmap/zlint/v3/util/encodings.go | 136 + vendor/github.com/zmap/zlint/v3/util/ev.go | 73 + vendor/github.com/zmap/zlint/v3/util/fqdn.go | 119 + vendor/github.com/zmap/zlint/v3/util/gtld.go | 120 + .../github.com/zmap/zlint/v3/util/gtld_map.go | 7880 ++++++++++++++ vendor/github.com/zmap/zlint/v3/util/ip.go | 127 + vendor/github.com/zmap/zlint/v3/util/ku.go | 18 + vendor/github.com/zmap/zlint/v3/util/names.go | 64 + vendor/github.com/zmap/zlint/v3/util/oid.go | 184 + .../github.com/zmap/zlint/v3/util/primes.go | 57 + .../github.com/zmap/zlint/v3/util/qc_stmt.go | 253 + vendor/github.com/zmap/zlint/v3/util/rdn.go | 26 + vendor/github.com/zmap/zlint/v3/util/time.go | 118 + vendor/github.com/zmap/zlint/v3/zlint.go | 62 + vendor/modules.txt | 31 +- 360 files changed, 49769 insertions(+), 145 deletions(-) create mode 100644 vendor/github.com/cloudflare/cfssl/helpers/derhelpers/ed25519.go create mode 100644 vendor/github.com/jmoiron/sqlx/LICENSE create mode 100644 vendor/github.com/jmoiron/sqlx/types/README.md create mode 100644 vendor/github.com/jmoiron/sqlx/types/types.go create mode 100644 vendor/github.com/weppos/publicsuffix-go/LICENSE.txt create mode 100644 vendor/github.com/weppos/publicsuffix-go/publicsuffix/publicsuffix.go create mode 100644 vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go create mode 100644 vendor/github.com/zmap/zcrypto/LICENSE create mode 100644 vendor/github.com/zmap/zcrypto/dsa/dsa.go create mode 100644 vendor/github.com/zmap/zcrypto/internal/randutil/randutil.go create mode 100644 vendor/github.com/zmap/zcrypto/json/dhe.go create mode 100644 vendor/github.com/zmap/zcrypto/json/ecdhe.go create mode 100644 vendor/github.com/zmap/zcrypto/json/names.go create mode 100644 vendor/github.com/zmap/zcrypto/json/rsa.go create mode 100644 vendor/github.com/zmap/zcrypto/util/isURL.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/README.md create mode 100644 vendor/github.com/zmap/zcrypto/x509/cert_pool.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/certificate_type.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/chain.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/ct/serialization.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/ct/types.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/example.json create mode 100644 vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/extended_key_usage_schema.sh create mode 100644 vendor/github.com/zmap/zcrypto/x509/extensions.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/fingerprint.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/generated_certvalidationlevel_string.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/json.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/names.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pem_decrypt.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pkcs1.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pkcs8.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pkix/json.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pkix/oid.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pkix/oid_names.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/qc_statements.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/sec1.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/validation.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/verify.go create mode 100644 vendor/github.com/zmap/zcrypto/x509/x509.go create mode 100644 vendor/github.com/zmap/zlint/v3/.goreleaser.yml create mode 100644 vendor/github.com/zmap/zlint/v3/LICENSE create mode 100644 vendor/github.com/zmap/zlint/v3/lint/base.go create mode 100644 vendor/github.com/zmap/zlint/v3/lint/registration.go create mode 100644 vendor/github.com/zmap/zlint/v3/lint/result.go create mode 100644 vendor/github.com/zmap/zlint/v3/lint/source.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/apple/time.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go create mode 100644 vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go create mode 100644 vendor/github.com/zmap/zlint/v3/makefile create mode 100644 vendor/github.com/zmap/zlint/v3/newLint.sh create mode 100644 vendor/github.com/zmap/zlint/v3/resultset.go create mode 100644 vendor/github.com/zmap/zlint/v3/template create mode 100644 vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/ca.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/countries.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/eku.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/encodings.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/ev.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/fqdn.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/gtld.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/gtld_map.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/ip.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/ku.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/names.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/oid.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/primes.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/qc_stmt.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/rdn.go create mode 100644 vendor/github.com/zmap/zlint/v3/util/time.go create mode 100644 vendor/github.com/zmap/zlint/v3/zlint.go diff --git a/ca/certificates.go b/ca/certificates.go index edf26ac1ec..0e92b2e08a 100644 --- a/ca/certificates.go +++ b/ca/certificates.go @@ -769,7 +769,7 @@ func CreateRootCA(rootCN string) (RootCA, error) { // Create a simple CSR for the CA using the default CA validator and policy req := cfcsr.CertificateRequest{ CN: rootCN, - KeyRequest: &cfcsr.BasicKeyRequest{A: RootKeyAlgo, S: RootKeySize}, + KeyRequest: &cfcsr.KeyRequest{A: RootKeyAlgo, S: RootKeySize}, CA: &cfcsr.CAConfig{Expiry: RootCAExpiration}, } @@ -919,7 +919,7 @@ func SaveRootCA(rootCA RootCA, paths CertPaths) error { // GenerateNewCSR returns a newly generated key and CSR signed with said key func GenerateNewCSR() ([]byte, []byte, error) { req := &cfcsr.CertificateRequest{ - KeyRequest: cfcsr.NewBasicKeyRequest(), + KeyRequest: cfcsr.NewKeyRequest(), } csr, key, err := cfcsr.ParseRequest(req) diff --git a/ca/certificates_test.go b/ca/certificates_test.go index 8423b9c72d..9543578920 100644 --- a/ca/certificates_test.go +++ b/ca/certificates_test.go @@ -217,7 +217,7 @@ func TestParseValidateAndSignMaliciousCSR(t *testing.T) { }, CN: "maliciousCN", Hosts: []string{"docker.com"}, - KeyRequest: &cfcsr.BasicKeyRequest{A: "ecdsa", S: 256}, + KeyRequest: &cfcsr.KeyRequest{A: "ecdsa", S: 256}, } csr, _, err := cfcsr.ParseRequest(req) @@ -1433,7 +1433,7 @@ func TestRootCACrossSignCACertificate(t *testing.T) { rsaReq := cfcsr.CertificateRequest{ CN: "rootCNRSA", - KeyRequest: &cfcsr.BasicKeyRequest{ + KeyRequest: &cfcsr.KeyRequest{ A: "rsa", S: 2048, }, diff --git a/ca/testutils/cautils.go b/ca/testutils/cautils.go index 2715c7629d..7e1231e211 100644 --- a/ca/testutils/cautils.go +++ b/ca/testutils/cautils.go @@ -344,7 +344,7 @@ func createNode(s *store.MemoryStore, nodeID, role string, csr, cert []byte) err func genSecurityConfig(s *store.MemoryStore, rootCA ca.RootCA, krw *ca.KeyReadWriter, role, org, tmpDir string, nonSigningRoot bool) (*ca.SecurityConfig, func() error, error) { req := &cfcsr.CertificateRequest{ - KeyRequest: cfcsr.NewBasicKeyRequest(), + KeyRequest: cfcsr.NewKeyRequest(), } csr, key, err := cfcsr.ParseRequest(req) @@ -447,7 +447,7 @@ func CreateRootCertAndKey(rootCN string) ([]byte, []byte, error) { // Create a simple CSR for the CA using the default CA validator and policy req := cfcsr.CertificateRequest{ CN: rootCN, - KeyRequest: cfcsr.NewBasicKeyRequest(), + KeyRequest: cfcsr.NewKeyRequest(), CA: &cfcsr.CAConfig{Expiry: ca.RootCAExpiration}, } @@ -489,7 +489,7 @@ func ReDateCert(t *testing.T, cert, signerCert, signerKey []byte, notBefore, not func CreateCertFromSigner(rootCN string, priv crypto.Signer) ([]byte, error) { req := cfcsr.CertificateRequest{ CN: rootCN, - KeyRequest: &cfcsr.BasicKeyRequest{A: ca.RootKeyAlgo, S: ca.RootKeySize}, + KeyRequest: &cfcsr.KeyRequest{A: ca.RootKeyAlgo, S: ca.RootKeySize}, CA: &cfcsr.CAConfig{Expiry: ca.RootCAExpiration}, } cert, _, err := initca.NewFromSigner(&req, priv) diff --git a/go.mod b/go.mod index 4abc192305..534f8de486 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( code.cloudfoundry.org/clock v1.0.0 github.com/Microsoft/go-winio v0.5.2 github.com/akutz/memconn v0.1.0 - github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 + github.com/cloudflare/cfssl v1.6.4 github.com/container-storage-interface/spec v1.2.0 github.com/docker/distribution v2.8.2+incompatible github.com/docker/docker v24.0.0-rc.2.0.20230714223606-37b908aa628c+incompatible // master (v25.0.0-dev) @@ -71,6 +71,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 // indirect + github.com/jmoiron/sqlx v1.3.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect @@ -80,6 +81,9 @@ require ( github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/tedsuo/ifrit v0.0.0-20220120221754-dd274de71113 // indirect + github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b // indirect + github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc // indirect + github.com/zmap/zlint/v3 v3.1.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.21.0 // indirect diff --git a/go.sum b/go.sum index 06c63ca5fa..b15c140b97 100644 --- a/go.sum +++ b/go.sum @@ -74,8 +74,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 h1:PqZ3bA4yzwywivzk7PBQWngJp2/PAS0bWRZerKteicY= -github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= +github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8= +github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= @@ -158,6 +158,7 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -271,6 +272,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 h1:i2fYnDurfLlJH8AyyMOnkLHnHeP8Ff/DDpuZA/D3bPo= github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= +github.com/jmoiron/sqlx v1.3.3 h1:j82X0bf7oQ27XeqxicSZsTU5suPwKElg3oyxNn43iTk= +github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -296,9 +299,11 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -320,6 +325,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -337,6 +343,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= @@ -399,6 +406,7 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -441,12 +449,22 @@ github.com/thecodeteam/gosync v0.1.0 h1:RcD9owCaiK0Jg1rIDPgirdcLCL1jCD6XlDVSg0Mf github.com/thecodeteam/gosync v0.1.0/go.mod h1:43QHsngcnWc8GE1aCmi7PEypslflHjCzXFleuWKEb00= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= +github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b h1:FsyNrX12e5BkplJq7wKOLk0+C6LZ+KGXvuEcKUYm5ss= +github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= +github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= +github.com/zmap/zcrypto v0.0.0-20210123152837-9cf5beac6d91/go.mod h1:R/deQh6+tSWlgI9tb4jNmXxn8nSCabl5ZQsBX9//I/E= +github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc h1:zkGwegkOW709y0oiAraH/3D8njopUR/pARHv4tZZ6pw= +github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc/go.mod h1:FM4U1E3NzlNMRnSUTU3P1UdukWhYGifqEsjk9fn7BCk= +github.com/zmap/zlint/v3 v3.1.0 h1:WjVytZo79m/L1+/Mlphl09WBob6YTGljN5IGWZFpAv0= +github.com/zmap/zlint/v3 v3.1.0/go.mod h1:L7t8s3sEKkb0A2BxGy1IWrxt1ZATa1R4QfJZaQOD3zU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= @@ -496,6 +514,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= @@ -565,6 +584,7 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= @@ -636,6 +656,7 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -652,6 +673,7 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -659,6 +681,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/vendor/github.com/cloudflare/cfssl/api/api.go b/vendor/github.com/cloudflare/cfssl/api/api.go index 98b0ec462e..462eeef833 100644 --- a/vendor/github.com/cloudflare/cfssl/api/api.go +++ b/vendor/github.com/cloudflare/cfssl/api/api.go @@ -3,7 +3,7 @@ package api import ( "encoding/json" - "io/ioutil" + "io" "net/http" "github.com/cloudflare/cfssl/errors" @@ -92,7 +92,7 @@ func (h HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func readRequestBlob(r *http.Request) (map[string]string, error) { var blob map[string]string - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { return nil, err } @@ -176,7 +176,7 @@ type Response struct { Messages []ResponseMessage `json:"messages"` } -// NewSuccessResponse is a shortcut for creating new successul API +// NewSuccessResponse is a shortcut for creating new successful API // responses. func NewSuccessResponse(result interface{}) Response { return Response{ diff --git a/vendor/github.com/cloudflare/cfssl/auth/auth.go b/vendor/github.com/cloudflare/cfssl/auth/auth.go index ecd5e5fefd..9b85bd3cae 100644 --- a/vendor/github.com/cloudflare/cfssl/auth/auth.go +++ b/vendor/github.com/cloudflare/cfssl/auth/auth.go @@ -10,7 +10,6 @@ import ( "crypto/sha256" "encoding/hex" "fmt" - "io/ioutil" "os" "strings" ) @@ -52,11 +51,11 @@ func New(key string, ad []byte) (*Standard, error) { case "env": key = os.Getenv(splitKey[1]) case "file": - data, err := ioutil.ReadFile(splitKey[1]) + data, err := os.ReadFile(splitKey[1]) if err != nil { return nil, err } - key = string(data) + key = strings.TrimSpace(string(data)) default: return nil, fmt.Errorf("unknown key prefix: %s", splitKey[0]) } diff --git a/vendor/github.com/cloudflare/cfssl/certdb/README.md b/vendor/github.com/cloudflare/cfssl/certdb/README.md index fbd941e39c..9aead39f84 100644 --- a/vendor/github.com/cloudflare/cfssl/certdb/README.md +++ b/vendor/github.com/cloudflare/cfssl/certdb/README.md @@ -27,11 +27,11 @@ Currently supported: ### Use goose to start and terminate a MySQL DB To start a MySQL using goose: - goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql up + goose -path certdb/mysql up To tear down a MySQL DB using goose - goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql down + goose -path certdb/mysql down Note: the administration of MySQL DB is not included. We assume the databases being connected to are already created and access control @@ -40,11 +40,11 @@ is properly handled. ### Use goose to start and terminate a PostgreSQL DB To start a PostgreSQL using goose: - goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/pg up + goose -path certdb/pg up To tear down a PostgreSQL DB using goose - goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/pg down + goose -path certdb/pg down Note: the administration of PostgreSQL DB is not included. We assume the databases being connected to are already created and access control @@ -53,11 +53,11 @@ is properly handled. ### Use goose to start and terminate a SQLite DB To start a SQLite DB using goose: - goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite up + goose -path certdb/sqlite up To tear down a SQLite DB using goose - goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite down + goose -path certdb/sqlite down ## CFSSL Configuration diff --git a/vendor/github.com/cloudflare/cfssl/certdb/certdb.go b/vendor/github.com/cloudflare/cfssl/certdb/certdb.go index dc8c856c3b..fc6c5767ee 100644 --- a/vendor/github.com/cloudflare/cfssl/certdb/certdb.go +++ b/vendor/github.com/cloudflare/cfssl/certdb/certdb.go @@ -1,7 +1,11 @@ package certdb import ( + "database/sql" + "encoding/json" "time" + + "github.com/jmoiron/sqlx/types" ) // CertificateRecord encodes a certificate and its metadata @@ -15,6 +19,46 @@ type CertificateRecord struct { Expiry time.Time `db:"expiry"` RevokedAt time.Time `db:"revoked_at"` PEM string `db:"pem"` + // the following fields will be empty for data inserted before migrate 002 has been run. + IssuedAt *time.Time `db:"issued_at"` + NotBefore *time.Time `db:"not_before"` + MetadataJSON types.JSONText `db:"metadata"` + SANsJSON types.JSONText `db:"sans"` + CommonName sql.NullString `db:"common_name"` +} + +// SetMetadata sets the metadata json +func (c *CertificateRecord) SetMetadata(meta map[string]interface{}) error { + marshaled, err := json.Marshal(meta) + if err != nil { + return err + } + c.MetadataJSON = types.JSONText(marshaled) + return nil +} + +// GetMetadata returns the json metadata +func (c *CertificateRecord) GetMetadata() (map[string]interface{}, error) { + var meta map[string]interface{} + err := c.MetadataJSON.Unmarshal(&meta) + return meta, err +} + +// SetSANs sets the list of sans +func (c *CertificateRecord) SetSANs(meta []string) error { + marshaled, err := json.Marshal(meta) + if err != nil { + return err + } + c.SANsJSON = types.JSONText(marshaled) + return nil +} + +// GetSANs returns the json SANs +func (c *CertificateRecord) GetSANs() ([]string, error) { + var sans []string + err := c.SANsJSON.Unmarshal(&sans) + return sans, err } // OCSPRecord encodes a OCSP response body and its metadata @@ -32,7 +76,9 @@ type Accessor interface { GetCertificate(serial, aki string) ([]CertificateRecord, error) GetUnexpiredCertificates() ([]CertificateRecord, error) GetRevokedAndUnexpiredCertificates() ([]CertificateRecord, error) + GetUnexpiredCertificatesByLabel(labels []string) (crs []CertificateRecord, err error) GetRevokedAndUnexpiredCertificatesByLabel(label string) ([]CertificateRecord, error) + GetRevokedAndUnexpiredCertificatesByLabelSelectColumns(label string) ([]CertificateRecord, error) RevokeCertificate(serial, aki string, reasonCode int) error InsertOCSP(rr OCSPRecord) error GetOCSP(serial, aki string) ([]OCSPRecord, error) diff --git a/vendor/github.com/cloudflare/cfssl/config/config.go b/vendor/github.com/cloudflare/cfssl/config/config.go index b04ed40ed5..f97d646982 100644 --- a/vendor/github.com/cloudflare/cfssl/config/config.go +++ b/vendor/github.com/cloudflare/cfssl/config/config.go @@ -8,7 +8,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "os" "regexp" "strconv" "strings" @@ -19,6 +19,9 @@ import ( "github.com/cloudflare/cfssl/helpers" "github.com/cloudflare/cfssl/log" ocspConfig "github.com/cloudflare/cfssl/ocsp/config" + // empty import of zlint/v3 required to have lints registered. + _ "github.com/zmap/zlint/v3" + "github.com/zmap/zlint/v3/lint" ) // A CSRWhitelist stores booleans for fields in the CSR. If a CSRWhitelist is @@ -32,7 +35,7 @@ import ( // mechanism. type CSRWhitelist struct { Subject, PublicKeyAlgorithm, PublicKey, SignatureAlgorithm bool - DNSNames, IPAddresses, EmailAddresses bool + DNSNames, IPAddresses, EmailAddresses, URIs bool } // OID is our own version of asn1's ObjectIdentifier, so we can define a custom @@ -81,6 +84,8 @@ type SigningProfile struct { ExpiryString string `json:"expiry"` BackdateString string `json:"backdate"` AuthKeyName string `json:"auth_key"` + CopyExtensions bool `json:"copy_extensions"` + PrevAuthKeyName string `json:"prev_auth_key"` // to support key rotation RemoteName string `json:"remote"` NotBefore time.Time `json:"not_before"` NotAfter time.Time `json:"not_after"` @@ -89,11 +94,26 @@ type SigningProfile struct { CTLogServers []string `json:"ct_log_servers"` AllowedExtensions []OID `json:"allowed_extensions"` CertStore string `json:"cert_store"` + // LintErrLevel controls preissuance linting for the signing profile. + // 0 = no linting is performed [default] + // 2..3 = reserved + // 3 = all lint results except pass are considered errors + // 4 = all lint results except pass and notice are considered errors + // 5 = all lint results except pass, notice and warn are considered errors + // 6 = all lint results except pass, notice, warn and error are considered errors. + // 7 = lint is performed, no lint results are treated as errors. + LintErrLevel lint.LintStatus `json:"lint_error_level"` + // ExcludeLints lists ZLint lint names to exclude from preissuance linting. + ExcludeLints []string `json:"ignored_lints"` + // ExcludeLintSources lists ZLint lint sources to exclude from preissuance + // linting. + ExcludeLintSources []string `json:"ignored_lint_sources"` Policies []CertificatePolicy Expiry time.Duration Backdate time.Duration Provider auth.Provider + PrevProvider auth.Provider // to suppport key rotation RemoteProvider auth.Provider RemoteServer string RemoteCAs *x509.CertPool @@ -102,6 +122,11 @@ type SigningProfile struct { NameWhitelist *regexp.Regexp ExtensionWhitelist map[string]bool ClientProvidesSerialNumbers bool + // LintRegistry is the collection of lints that should be used if + // LintErrLevel is configured. By default all ZLint lints are used. If + // ExcludeLints or ExcludeLintSources are set then this registry will be + // filtered in populate() to exclude the named lints and lint sources. + LintRegistry lint.Registry } // UnmarshalJSON unmarshals a JSON string into an OID. @@ -229,7 +254,7 @@ func (p *SigningProfile) populate(cfg *Config) error { if p.AuthKeyName != "" { log.Debug("match auth key in profile to auth_keys section") - if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok == true { + if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok { if key.Type == "standard" { p.Provider, err = auth.New(key.Key, nil) if err != nil { @@ -248,6 +273,27 @@ func (p *SigningProfile) populate(cfg *Config) error { } } + if p.PrevAuthKeyName != "" { + log.Debug("match previous auth key in profile to auth_keys section") + if key, ok := cfg.AuthKeys[p.PrevAuthKeyName]; ok { + if key.Type == "standard" { + p.PrevProvider, err = auth.New(key.Key, nil) + if err != nil { + log.Debugf("failed to create new standard auth provider: %v", err) + return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, + errors.New("failed to create new standard auth provider")) + } + } else { + log.Debugf("unknown authentication type %v", key.Type) + return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, + errors.New("unknown authentication type")) + } + } else { + return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, + errors.New("failed to find prev_auth_key in auth_keys section")) + } + } + if p.AuthRemote.AuthKeyName != "" { log.Debug("match auth remote key in profile to auth_keys section") if key, ok := cfg.AuthKeys[p.AuthRemote.AuthKeyName]; ok == true { @@ -284,6 +330,40 @@ func (p *SigningProfile) populate(cfg *Config) error { p.ExtensionWhitelist[asn1.ObjectIdentifier(oid).String()] = true } + // By default perform any required preissuance linting with all ZLint lints. + p.LintRegistry = lint.GlobalRegistry() + + // If ExcludeLintSources are present in config build a lint.SourceList while + // validating that no unknown sources were specified. + var excludedSources lint.SourceList + if len(p.ExcludeLintSources) > 0 { + for _, sourceName := range p.ExcludeLintSources { + var lintSource lint.LintSource + lintSource.FromString(sourceName) + if lintSource == lint.UnknownLintSource { + return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, + fmt.Errorf("failed to build excluded lint source list: unknown source %q", + sourceName)) + } + excludedSources = append(excludedSources, lintSource) + } + } + + opts := lint.FilterOptions{ + ExcludeNames: p.ExcludeLints, + ExcludeSources: excludedSources, + } + if !opts.Empty() { + // If ExcludeLints or ExcludeLintSources were not empty then filter out the + // lints we don't want to use for preissuance linting with this profile. + filteredRegistry, err := p.LintRegistry.Filter(opts) + if err != nil { + return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, + fmt.Errorf("failed to build filtered lint registry: %v", err)) + } + p.LintRegistry = filteredRegistry + } + return nil } @@ -404,7 +484,8 @@ func (p *SigningProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk // valid local default profile has defined at least a default expiration. // A valid remote profile (default or not) has remote signer initialized. // In addition, a remote profile must has a valid auth provider if auth -// key defined. +// key defined. A valid profile must not include a lint_error_level outside of +// [0,8). func (p *SigningProfile) validProfile(isDefault bool) bool { if p == nil { return false @@ -461,6 +542,11 @@ func (p *SigningProfile) validProfile(isDefault bool) bool { } } + if p.LintErrLevel < 0 || p.LintErrLevel >= 8 { + log.Debugf("invalid profile: lint_error_level outside of range [0,8)") + return false + } + log.Debugf("profile is valid") return true } @@ -613,7 +699,7 @@ func LoadFile(path string) (*Config, error) { return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid path")) } - body, err := ioutil.ReadFile(path) + body, err := os.ReadFile(path) if err != nil { return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("could not read configuration file")) } diff --git a/vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go b/vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go index d57daf51b5..f53d3f9330 100644 --- a/vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go +++ b/vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go @@ -3,17 +3,17 @@ // to PKCS #7 format from another encoding such as PEM conforms to this implementation. // reference: https://www.openssl.org/docs/man1.1.0/apps/crl2pkcs7.html // -// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315 +// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315 // // The full pkcs#7 cryptographic message syntax allows for cryptographic enhancements, // for example data can be encrypted and signed and then packaged through pkcs#7 to be // sent over a network and then verified and decrypted. It is asn1, and the type of // PKCS #7 ContentInfo, which comprises the PKCS #7 structure, is: // -// ContentInfo ::= SEQUENCE { -// contentType ContentType, -// content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL -// } +// ContentInfo ::= SEQUENCE { +// contentType ContentType, +// content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL +// } // // There are 6 possible ContentTypes, data, signedData, envelopedData, // signedAndEnvelopedData, digestedData, and encryptedData. Here signedData, Data, and encrypted @@ -22,15 +22,14 @@ // formats. // The ContentType signedData has the form: // -// -// signedData ::= SEQUENCE { -// version Version, -// digestAlgorithms DigestAlgorithmIdentifiers, -// contentInfo ContentInfo, -// certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL -// crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, -// signerInfos SignerInfos -// } +// signedData ::= SEQUENCE { +// version Version, +// digestAlgorithms DigestAlgorithmIdentifiers, +// contentInfo ContentInfo, +// certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL +// crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, +// signerInfos SignerInfos +// } // // As of yet signerInfos and digestAlgorithms are not parsed, as they are not relevant to // this system's use of PKCS #7 data. Version is an integer type, note that PKCS #7 is diff --git a/vendor/github.com/cloudflare/cfssl/csr/csr.go b/vendor/github.com/cloudflare/cfssl/csr/csr.go index c4ccea60b0..0ca2509944 100644 --- a/vendor/github.com/cloudflare/cfssl/csr/csr.go +++ b/vendor/github.com/cloudflare/cfssl/csr/csr.go @@ -12,8 +12,11 @@ import ( "encoding/asn1" "encoding/pem" "errors" + "fmt" "net" "net/mail" + "net/url" + "strconv" "strings" cferr "github.com/cloudflare/cfssl/errors" @@ -29,46 +32,40 @@ const ( // A Name contains the SubjectInfo fields. type Name struct { - C string // Country - ST string // State - L string // Locality - O string // OrganisationName - OU string // OrganisationalUnitName - SerialNumber string + C string `json:"C,omitempty" yaml:"C,omitempty"` // Country + ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State + L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality + O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName + OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName + E string `json:"E,omitempty" yaml:"E,omitempty"` + SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"` + OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"` } -// A KeyRequest is a generic request for a new key. -type KeyRequest interface { - Algo() string - Size() int - Generate() (crypto.PrivateKey, error) - SigAlgo() x509.SignatureAlgorithm -} - -// A BasicKeyRequest contains the algorithm and key size for a new private key. -type BasicKeyRequest struct { +// A KeyRequest contains the algorithm and key size for a new private key. +type KeyRequest struct { A string `json:"algo" yaml:"algo"` S int `json:"size" yaml:"size"` } -// NewBasicKeyRequest returns a default BasicKeyRequest. -func NewBasicKeyRequest() *BasicKeyRequest { - return &BasicKeyRequest{"ecdsa", curveP256} +// NewKeyRequest returns a default KeyRequest. +func NewKeyRequest() *KeyRequest { + return &KeyRequest{"ecdsa", curveP256} } // Algo returns the requested key algorithm represented as a string. -func (kr *BasicKeyRequest) Algo() string { +func (kr *KeyRequest) Algo() string { return kr.A } // Size returns the requested key size. -func (kr *BasicKeyRequest) Size() int { +func (kr *KeyRequest) Size() int { return kr.S } // Generate generates a key as specified in the request. Currently, // only ECDSA and RSA are supported. -func (kr *BasicKeyRequest) Generate() (crypto.PrivateKey, error) { +func (kr *KeyRequest) Generate() (crypto.PrivateKey, error) { log.Debugf("generate key from request: algo=%s, size=%d", kr.Algo(), kr.Size()) switch kr.Algo() { case "rsa": @@ -99,7 +96,7 @@ func (kr *BasicKeyRequest) Generate() (crypto.PrivateKey, error) { // SigAlgo returns an appropriate X.509 signature algorithm given the // key request's type and size. -func (kr *BasicKeyRequest) SigAlgo() x509.SignatureAlgorithm { +func (kr *KeyRequest) SigAlgo() x509.SignatureAlgorithm { switch kr.Algo() { case "rsa": switch { @@ -139,19 +136,22 @@ type CAConfig struct { // A CertificateRequest encapsulates the API interface to the // certificate request functionality. type CertificateRequest struct { - CN string - Names []Name `json:"names" yaml:"names"` - Hosts []string `json:"hosts" yaml:"hosts"` - KeyRequest KeyRequest `json:"key,omitempty" yaml:"key,omitempty"` - CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"` - SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"` + CN string `json:"CN" yaml:"CN"` + Names []Name `json:"names" yaml:"names"` + Hosts []string `json:"hosts" yaml:"hosts"` + KeyRequest *KeyRequest `json:"key,omitempty" yaml:"key,omitempty"` + CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"` + SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"` + DelegationEnabled bool `json:"delegation_enabled,omitempty" yaml:"delegation_enabled,omitempty"` + Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"` + CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"` } // New returns a new, empty CertificateRequest with a -// BasicKeyRequest. +// KeyRequest. func New() *CertificateRequest { return &CertificateRequest{ - KeyRequest: NewBasicKeyRequest(), + KeyRequest: NewKeyRequest(), } } @@ -162,8 +162,25 @@ func appendIf(s string, a *[]string) { } } +// OIDFromString creates an ASN1 ObjectIdentifier from its string representation +func OIDFromString(s string) (asn1.ObjectIdentifier, error) { + var oid []int + parts := strings.Split(s, ".") + if len(parts) < 1 { + return oid, fmt.Errorf("invalid OID string: %s", s) + } + for _, p := range parts { + i, err := strconv.Atoi(p) + if err != nil { + return nil, fmt.Errorf("invalid OID part %s", p) + } + oid = append(oid, i) + } + return oid, nil +} + // Name returns the PKIX name for the request. -func (cr *CertificateRequest) Name() pkix.Name { +func (cr *CertificateRequest) Name() (pkix.Name, error) { var name pkix.Name name.CommonName = cr.CN @@ -173,9 +190,19 @@ func (cr *CertificateRequest) Name() pkix.Name { appendIf(n.L, &name.Locality) appendIf(n.O, &name.Organization) appendIf(n.OU, &name.OrganizationalUnit) + for k, v := range n.OID { + oid, err := OIDFromString(k) + if err != nil { + return name, err + } + name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v}) + } + if n.E != "" { + name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E}) + } } name.SerialNumber = cr.SerialNumber - return name + return name, nil } // BasicConstraints CSR information RFC 5280, 4.2.1.9 @@ -193,7 +220,7 @@ type BasicConstraints struct { func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) { log.Info("received CSR") if req.KeyRequest == nil { - req.KeyRequest = NewBasicKeyRequest() + req.KeyRequest = NewKeyRequest() } log.Infof("generating key: %s-%d", req.KeyRequest.Algo(), req.KeyRequest.Size()) @@ -268,14 +295,17 @@ func getHosts(cert *x509.Certificate) []string { for _, email := range cert.EmailAddresses { hosts = append(hosts, email) } + for _, uri := range cert.URIs { + hosts = append(hosts, uri.String()) + } return hosts } // getNames returns an array of Names from the certificate -// It onnly cares about Country, Organization, OrganizationalUnit, Locality, Province +// It only cares about Country, Organization, OrganizationalUnit, Locality, Province func getNames(sub pkix.Name) []Name { - // anonymous func for finding the max of a list of interger + // anonymous func for finding the max of a list of integer max := func(v1 int, vn ...int) (max int) { max = v1 for i := 0; i < len(vn); i++ { @@ -369,8 +399,13 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable) } + subj, err := req.Name() + if err != nil { + return nil, err + } + var tpl = x509.CertificateRequest{ - Subject: req.Name(), + Subject: subj, SignatureAlgorithm: sigAlgo, } @@ -379,11 +414,15 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro tpl.IPAddresses = append(tpl.IPAddresses, ip) } else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil { tpl.EmailAddresses = append(tpl.EmailAddresses, email.Address) + } else if uri, err := url.ParseRequestURI(req.Hosts[i]); err == nil && uri != nil { + tpl.URIs = append(tpl.URIs, uri) } else { tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i]) } } + tpl.ExtraExtensions = []pkix.Extension{} + if req.CA != nil { err = appendCAInfoToCSR(req.CA, &tpl) if err != nil { @@ -392,6 +431,18 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro } } + if req.DelegationEnabled { + tpl.ExtraExtensions = append(tpl.Extensions, helpers.DelegationExtension) + } + + if req.Extensions != nil { + err = appendExtensionsToCSR(req.Extensions, &tpl) + if err != nil { + err = cferr.Wrap(cferr.CSRError, cferr.GenerationFailed, err) + return + } + } + csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv) if err != nil { log.Errorf("failed to generate a CSR: %v", err) @@ -420,13 +471,19 @@ func appendCAInfoToCSR(reqConf *CAConfig, csr *x509.CertificateRequest) error { return err } - csr.ExtraExtensions = []pkix.Extension{ - { - Id: asn1.ObjectIdentifier{2, 5, 29, 19}, - Value: val, - Critical: true, - }, - } + csr.ExtraExtensions = append(csr.ExtraExtensions, pkix.Extension{ + Id: asn1.ObjectIdentifier{2, 5, 29, 19}, + Value: val, + Critical: true, + }) return nil } + +// appendCAInfoToCSR appends user-defined extension to a CSR +func appendExtensionsToCSR(extensions []pkix.Extension, csr *x509.CertificateRequest) error { + for _, extension := range extensions { + csr.ExtraExtensions = append(csr.ExtraExtensions, extension) + } + return nil +} diff --git a/vendor/github.com/cloudflare/cfssl/errors/doc.go b/vendor/github.com/cloudflare/cfssl/errors/doc.go index 1910e2662f..e4af5f0268 100644 --- a/vendor/github.com/cloudflare/cfssl/errors/doc.go +++ b/vendor/github.com/cloudflare/cfssl/errors/doc.go @@ -7,6 +7,7 @@ It formats to a json object that consists of an error message and a 4-digit code Example: {"code":1002, "message": "Failed to decode certificate"} The index of codes are listed below: + 1XXX: CertificateError 1000: Unknown 1001: ReadFailed diff --git a/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go b/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go index bcc7418508..561691be21 100644 --- a/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go +++ b/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go @@ -5,14 +5,15 @@ package derhelpers import ( "crypto" "crypto/ecdsa" + "crypto/ed25519" "crypto/rsa" "crypto/x509" cferr "github.com/cloudflare/cfssl/errors" ) -// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve -// DER-encoded private key. The key must not be in PEM format. +// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, ECDSA, or Ed25519 DER-encoded +// private key. The key must not be in PEM format. func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) { generalKey, err := x509.ParsePKCS8PrivateKey(keyDER) if err != nil { @@ -20,12 +21,15 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) { if err != nil { generalKey, err = x509.ParseECPrivateKey(keyDER) if err != nil { - // We don't include the actual error into - // the final error. The reason might be - // we don't want to leak any info about - // the private key. - return nil, cferr.New(cferr.PrivateKeyError, - cferr.ParseFailed) + generalKey, err = ParseEd25519PrivateKey(keyDER) + if err != nil { + // We don't include the actual error into + // the final error. The reason might be + // we don't want to leak any info about + // the private key. + return nil, cferr.New(cferr.PrivateKeyError, + cferr.ParseFailed) + } } } } @@ -35,6 +39,8 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) { return generalKey.(*rsa.PrivateKey), nil case *ecdsa.PrivateKey: return generalKey.(*ecdsa.PrivateKey), nil + case ed25519.PrivateKey: + return generalKey.(ed25519.PrivateKey), nil } // should never reach here diff --git a/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/ed25519.go b/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/ed25519.go new file mode 100644 index 0000000000..bf20dc2061 --- /dev/null +++ b/vendor/github.com/cloudflare/cfssl/helpers/derhelpers/ed25519.go @@ -0,0 +1,132 @@ +package derhelpers + +import ( + "crypto" + "crypto/ed25519" + "crypto/x509/pkix" + "encoding/asn1" + "errors" +) + +var errEd25519WrongID = errors.New("incorrect object identifier") +var errEd25519WrongKeyType = errors.New("incorrect key type") + +// ed25519OID is the OID for the Ed25519 signature scheme: see +// https://datatracker.ietf.org/doc/draft-ietf-curdle-pkix-04. +var ed25519OID = asn1.ObjectIdentifier{1, 3, 101, 112} + +// subjectPublicKeyInfo reflects the ASN.1 object defined in the X.509 standard. +// +// This is defined in crypto/x509 as "publicKeyInfo". +type subjectPublicKeyInfo struct { + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString +} + +// MarshalEd25519PublicKey creates a DER-encoded SubjectPublicKeyInfo for an +// ed25519 public key, as defined in +// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04. This is analogous to +// MarshalPKIXPublicKey in crypto/x509, which doesn't currently support Ed25519. +func MarshalEd25519PublicKey(pk crypto.PublicKey) ([]byte, error) { + pub, ok := pk.(ed25519.PublicKey) + if !ok { + return nil, errEd25519WrongKeyType + } + + spki := subjectPublicKeyInfo{ + Algorithm: pkix.AlgorithmIdentifier{ + Algorithm: ed25519OID, + }, + PublicKey: asn1.BitString{ + BitLength: len(pub) * 8, + Bytes: pub, + }, + } + + return asn1.Marshal(spki) +} + +// ParseEd25519PublicKey returns the Ed25519 public key encoded by the input. +func ParseEd25519PublicKey(der []byte) (crypto.PublicKey, error) { + var spki subjectPublicKeyInfo + if rest, err := asn1.Unmarshal(der, &spki); err != nil { + return nil, err + } else if len(rest) > 0 { + return nil, errors.New("SubjectPublicKeyInfo too long") + } + + if !spki.Algorithm.Algorithm.Equal(ed25519OID) { + return nil, errEd25519WrongID + } + + if spki.PublicKey.BitLength != ed25519.PublicKeySize*8 { + return nil, errors.New("SubjectPublicKeyInfo PublicKey length mismatch") + } + + return ed25519.PublicKey(spki.PublicKey.Bytes), nil +} + +// oneAsymmetricKey reflects the ASN.1 structure for storing private keys in +// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04, excluding the optional +// fields, which we don't use here. +// +// This is identical to pkcs8 in crypto/x509. +type oneAsymmetricKey struct { + Version int + Algorithm pkix.AlgorithmIdentifier + PrivateKey []byte +} + +// curvePrivateKey is the innter type of the PrivateKey field of +// oneAsymmetricKey. +type curvePrivateKey []byte + +// MarshalEd25519PrivateKey returns a DER encoding of the input private key as +// specified in https://tools.ietf.org/html/draft-ietf-curdle-pkix-04. +func MarshalEd25519PrivateKey(sk crypto.PrivateKey) ([]byte, error) { + priv, ok := sk.(ed25519.PrivateKey) + if !ok { + return nil, errEd25519WrongKeyType + } + + // Marshal the innter CurvePrivateKey. + curvePrivateKey, err := asn1.Marshal(priv.Seed()) + if err != nil { + return nil, err + } + + // Marshal the OneAsymmetricKey. + asym := oneAsymmetricKey{ + Version: 0, + Algorithm: pkix.AlgorithmIdentifier{ + Algorithm: ed25519OID, + }, + PrivateKey: curvePrivateKey, + } + return asn1.Marshal(asym) +} + +// ParseEd25519PrivateKey returns the Ed25519 private key encoded by the input. +func ParseEd25519PrivateKey(der []byte) (crypto.PrivateKey, error) { + asym := new(oneAsymmetricKey) + if rest, err := asn1.Unmarshal(der, asym); err != nil { + return nil, err + } else if len(rest) > 0 { + return nil, errors.New("OneAsymmetricKey too long") + } + + // Check that the key type is correct. + if !asym.Algorithm.Algorithm.Equal(ed25519OID) { + return nil, errEd25519WrongID + } + + // Unmarshal the inner CurvePrivateKey. + seed := new(curvePrivateKey) + if rest, err := asn1.Unmarshal(asym.PrivateKey, seed); err != nil { + return nil, err + } else if len(rest) > 0 { + return nil, errors.New("CurvePrivateKey too long") + } + + return ed25519.NewKeyFromSeed(*seed), nil +} diff --git a/vendor/github.com/cloudflare/cfssl/helpers/helpers.go b/vendor/github.com/cloudflare/cfssl/helpers/helpers.go index 8218ba53ad..f45e63a3d1 100644 --- a/vendor/github.com/cloudflare/cfssl/helpers/helpers.go +++ b/vendor/github.com/cloudflare/cfssl/helpers/helpers.go @@ -15,14 +15,7 @@ import ( "encoding/pem" "errors" "fmt" - "io/ioutil" "os" - - "github.com/google/certificate-transparency-go" - cttls "github.com/google/certificate-transparency-go/tls" - ctx509 "github.com/google/certificate-transparency-go/x509" - "golang.org/x/crypto/ocsp" - "strings" "time" @@ -30,6 +23,11 @@ import ( cferr "github.com/cloudflare/cfssl/errors" "github.com/cloudflare/cfssl/helpers/derhelpers" "github.com/cloudflare/cfssl/log" + + ct "github.com/google/certificate-transparency-go" + cttls "github.com/google/certificate-transparency-go/tls" + ctx509 "github.com/google/certificate-transparency-go/x509" + "golang.org/x/crypto/ocsp" "golang.org/x/crypto/pkcs12" ) @@ -39,6 +37,16 @@ const OneYear = 8760 * time.Hour // OneDay is a time.Duration representing a day's worth of seconds. const OneDay = 24 * time.Hour +// DelegationUsage is the OID for the DelegationUseage extensions +var DelegationUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44} + +// DelegationExtension +var DelegationExtension = pkix.Extension{ + Id: DelegationUsage, + Critical: false, + Value: []byte{0x05, 0x00}, // ASN.1 NULL +} + // InclusiveDate returns the time.Time representation of a date - 1 // nanosecond. This allows time.After to be used inclusively. func InclusiveDate(year int, month time.Month, day int) time.Time { @@ -184,6 +192,19 @@ func HashAlgoString(alg x509.SignatureAlgorithm) string { } } +// StringTLSVersion returns underlying enum values from human names for TLS +// versions, defaults to current golang default of TLS 1.0 +func StringTLSVersion(version string) uint16 { + switch version { + case "1.2": + return tls.VersionTLS12 + case "1.1": + return tls.VersionTLS11 + default: + return tls.VersionTLS10 + } +} + // EncodeCertificatesPEM encodes a number of x509 certificates to PEM func EncodeCertificatesPEM(certs []*x509.Certificate) []byte { var buffer bytes.Buffer @@ -322,7 +343,7 @@ func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) { if certsFile == "" { return nil, nil } - pemCerts, err := ioutil.ReadFile(certsFile) + pemCerts, err := os.ReadFile(certsFile) if err != nil { return nil, err } @@ -365,7 +386,15 @@ func ParsePrivateKeyPEMWithPassword(keyPEM []byte, password []byte) (key crypto. // GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes. func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) { - keyDER, _ := pem.Decode(in) + // Ignore any EC PARAMETERS blocks when looking for a key (openssl includes + // them by default). + var keyDER *pem.Block + for { + keyDER, in = pem.Decode(in) + if keyDER == nil || keyDER.Type != "EC PARAMETERS" { + break + } + } if keyDER != nil { if procType, ok := keyDER.Headers["Proc-Type"]; ok { if strings.Contains(procType, "ENCRYPTED") { @@ -460,7 +489,7 @@ func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, e if certFile != "" && keyFile != "" { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { - log.Critical("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile) + log.Criticalf("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile) return nil, err } log.Debug("Client certificate loaded ") @@ -560,13 +589,13 @@ func SCTListFromOCSPResponse(response *ocsp.Response) ([]ct.SignedCertificateTim func ReadBytes(valFile string) ([]byte, error) { switch splitVal := strings.SplitN(valFile, ":", 2); len(splitVal) { case 1: - return ioutil.ReadFile(valFile) + return os.ReadFile(valFile) case 2: switch splitVal[0] { case "env": return []byte(os.Getenv(splitVal[1])), nil case "file": - return ioutil.ReadFile(splitVal[1]) + return os.ReadFile(splitVal[1]) default: return nil, fmt.Errorf("unknown prefix: %s", splitVal[0]) } diff --git a/vendor/github.com/cloudflare/cfssl/initca/initca.go b/vendor/github.com/cloudflare/cfssl/initca/initca.go index 2cdc0925f1..40a608502a 100644 --- a/vendor/github.com/cloudflare/cfssl/initca/initca.go +++ b/vendor/github.com/cloudflare/cfssl/initca/initca.go @@ -69,6 +69,10 @@ func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) { } } + if req.CRL != "" { + policy.Default.CRL = req.CRL + } + g := &csr.Generator{Validator: validator} csrPEM, key, err = g.ProcessRequest(req) if err != nil { diff --git a/vendor/github.com/cloudflare/cfssl/signer/local/local.go b/vendor/github.com/cloudflare/cfssl/signer/local/local.go index a92b8f5917..091ce79ce0 100644 --- a/vendor/github.com/cloudflare/cfssl/signer/local/local.go +++ b/vendor/github.com/cloudflare/cfssl/signer/local/local.go @@ -3,20 +3,27 @@ package local import ( "bytes" + "context" "crypto" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" + "database/sql" "encoding/asn1" "encoding/hex" "encoding/pem" "errors" + "fmt" "io" "math/big" "net" "net/http" "net/mail" + "net/url" "os" + "time" "github.com/cloudflare/cfssl/certdb" "github.com/cloudflare/cfssl/config" @@ -25,17 +32,23 @@ import ( "github.com/cloudflare/cfssl/info" "github.com/cloudflare/cfssl/log" "github.com/cloudflare/cfssl/signer" - "github.com/google/certificate-transparency-go" + ct "github.com/google/certificate-transparency-go" "github.com/google/certificate-transparency-go/client" "github.com/google/certificate-transparency-go/jsonclient" - "golang.org/x/net/context" + + zx509 "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3" + "github.com/zmap/zlint/v3/lint" ) // Signer contains a signer that uses the standard library to // support both ECDSA and RSA CA keys. type Signer struct { - ca *x509.Certificate - priv crypto.Signer + ca *x509.Certificate + priv crypto.Signer + // lintPriv is generated randomly when pre-issuance linting is configured and + // used to sign TBSCertificates for linting. + lintPriv crypto.Signer policy *config.Signing sigAlgo x509.SignatureAlgorithm dbAccessor certdb.Accessor @@ -54,11 +67,30 @@ func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.Signatur return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) } + var lintPriv crypto.Signer + // If there is at least one profile (including the default) that configures + // pre-issuance linting then generate the one-off lintPriv key. + for _, profile := range policy.Profiles { + if profile.LintErrLevel > 0 || policy.Default.LintErrLevel > 0 { + // In the future there may be demand for specifying the type of signer used + // for pre-issuance linting in configuration. For now we assume that signing + // with a randomly generated P-256 ECDSA private key is acceptable for all cases + // where linting is requested. + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, cferr.New(cferr.PrivateKeyError, cferr.GenerationFailed) + } + lintPriv = k + break + } + } + return &Signer{ - ca: cert, - priv: priv, - sigAlgo: sigAlgo, - policy: policy, + ca: cert, + priv: priv, + lintPriv: lintPriv, + sigAlgo: sigAlgo, + policy: policy, }, nil } @@ -89,14 +121,75 @@ func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signe priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password) if err != nil { - log.Debug("Malformed private key %v", err) + log.Debugf("Malformed private key %v", err) return nil, err } return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy) } -func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) { +// LintError is an error type returned when pre-issuance linting is configured +// in a signing profile and a TBS Certificate fails linting. It wraps the +// concrete zlint LintResults so that callers can further inspect the cause of +// the failing lints. +type LintError struct { + ErrorResults map[string]lint.LintResult +} + +func (e *LintError) Error() string { + return fmt.Sprintf("pre-issuance linting found %d error results", + len(e.ErrorResults)) +} + +// lint performs pre-issuance linting of a given TBS certificate template when +// the provided errLevel is > 0. Note that the template is provided by-value and +// not by-reference. This is important as the lint function needs to mutate the +// template's signature algorithm to match the lintPriv. +func (s *Signer) lint(template x509.Certificate, errLevel lint.LintStatus, lintRegistry lint.Registry) error { + // Always return nil when linting is disabled (lint.Reserved == 0). + if errLevel == lint.Reserved { + return nil + } + // without a lintPriv key to use to sign the tbsCertificate we can't lint it. + if s.lintPriv == nil { + return cferr.New(cferr.PrivateKeyError, cferr.Unavailable) + } + + // The template's SignatureAlgorithm must be mutated to match the lintPriv or + // x509.CreateCertificate will error because of the mismatch. At the time of + // writing s.lintPriv is always an ECDSA private key. This switch will need to + // be expanded if the lint key type is made configurable. + switch s.lintPriv.(type) { + case *ecdsa.PrivateKey: + template.SignatureAlgorithm = x509.ECDSAWithSHA256 + default: + return cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) + } + + prelintBytes, err := x509.CreateCertificate(rand.Reader, &template, s.ca, template.PublicKey, s.lintPriv) + if err != nil { + return cferr.Wrap(cferr.CertificateError, cferr.Unknown, err) + } + prelintCert, err := zx509.ParseCertificate(prelintBytes) + if err != nil { + return cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err) + } + errorResults := map[string]lint.LintResult{} + results := zlint.LintCertificateEx(prelintCert, lintRegistry) + for name, res := range results.Results { + if res.Status > errLevel { + errorResults[name] = *res + } + } + if len(errorResults) > 0 { + return &LintError{ + ErrorResults: errorResults, + } + } + return nil +} + +func (s *Signer) sign(template *x509.Certificate, lintErrLevel lint.LintStatus, lintRegistry lint.Registry) (cert []byte, err error) { var initRoot bool if s.ca == nil { if !template.IsCA { @@ -105,10 +198,15 @@ func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) { } template.DNSNames = nil template.EmailAddresses = nil + template.URIs = nil s.ca = template initRoot = true } + if err := s.lint(*template, lintErrLevel, lintRegistry); err != nil { + return nil, err + } + derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv) if err != nil { return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err) @@ -159,13 +257,14 @@ func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name { return name } -// OverrideHosts fills template's IPAddresses, EmailAddresses, and DNSNames with the +// OverrideHosts fills template's IPAddresses, EmailAddresses, DNSNames, and URIs with the // content of hosts, if it is not nil. func OverrideHosts(template *x509.Certificate, hosts []string) { if hosts != nil { template.IPAddresses = []net.IP{} template.EmailAddresses = []string{} template.DNSNames = []string{} + template.URIs = []*url.URL{} } for i := range hosts { @@ -173,6 +272,8 @@ func OverrideHosts(template *x509.Certificate, hosts []string) { template.IPAddresses = append(template.IPAddresses, ip) } else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil { template.EmailAddresses = append(template.EmailAddresses, email.Address) + } else if uri, err := url.ParseRequestURI(hosts[i]); err == nil && uri != nil { + template.URIs = append(template.URIs, uri) } else { template.DNSNames = append(template.DNSNames, hosts[i]) } @@ -199,7 +300,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { cferr.BadRequest, errors.New("not a csr")) } - csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes) + csrTemplate, err := signer.ParseCertificateRequest(s, profile, block.Bytes) if err != nil { return nil, err } @@ -232,6 +333,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { if profile.CSRWhitelist.EmailAddresses { safeTemplate.EmailAddresses = csrTemplate.EmailAddresses } + if profile.CSRWhitelist.URIs { + safeTemplate.URIs = csrTemplate.URIs + } } if req.CRLOverride != "" { @@ -277,6 +381,11 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist) } } + for _, name := range safeTemplate.URIs { + if profile.NameWhitelist.Find([]byte(name.String())) == nil { + return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist) + } + } } if profile.ClientProvidesSerialNumbers { @@ -342,7 +451,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}} var poisonedPreCert = certTBS poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension) - cert, err = s.sign(&poisonedPreCert) + cert, err = s.sign(&poisonedPreCert, profile.LintErrLevel, profile.LintRegistry) if err != nil { return } @@ -385,8 +494,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { var SCTListExtension = pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedSCTList} certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension) } + var signedCert []byte - signedCert, err = s.sign(&certTBS) + signedCert, err = s.sign(&certTBS, profile.LintErrLevel, profile.LintRegistry) if err != nil { return nil, err } @@ -397,19 +507,29 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { parsedCert, _ := helpers.ParseCertificatePEM(signedCert) if s.dbAccessor != nil { + now := time.Now() var certRecord = certdb.CertificateRecord{ Serial: certTBS.SerialNumber.String(), // this relies on the specific behavior of x509.CreateCertificate // which sets the AuthorityKeyId from the signer's SubjectKeyId - AKI: hex.EncodeToString(parsedCert.AuthorityKeyId), - CALabel: req.Label, - Status: "good", - Expiry: certTBS.NotAfter, - PEM: string(signedCert), + AKI: hex.EncodeToString(parsedCert.AuthorityKeyId), + CALabel: req.Label, + Status: "good", + Expiry: certTBS.NotAfter, + PEM: string(signedCert), + IssuedAt: &now, + NotBefore: &certTBS.NotBefore, + CommonName: sql.NullString{String: certTBS.Subject.CommonName, Valid: true}, } - err = s.dbAccessor.InsertCertificate(certRecord) - if err != nil { + if err := certRecord.SetMetadata(req.Metadata); err != nil { + return nil, err + } + if err := certRecord.SetSANs(certTBS.DNSNames); err != nil { + return nil, err + } + + if err := s.dbAccessor.InsertCertificate(certRecord); err != nil { return nil, err } log.Debug("saved certificate with serial number ", certTBS.SerialNumber) @@ -424,7 +544,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { // except for the removal of the poison extension and the addition of the SCT list // extension. SignFromPrecert does not verify that the contents of the certificate // still match the signing profile of the signer, it only requires that the precert -// was previously signed by the Signers CA. +// was previously signed by the Signers CA. Similarly, any linting configured +// by the profile used to sign the precert will not be re-applied to the final +// cert and must be done separately by the caller. func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCertificateTimestamp) ([]byte, error) { // Verify certificate was signed by s.ca if err := precert.CheckSignatureFrom(s.ca); err != nil { @@ -467,17 +589,17 @@ func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCert // Create the new tbsCert from precert. Do explicit copies of any slices so that we don't // use memory that may be altered by us or the caller at a later stage. tbsCert := x509.Certificate{ - SignatureAlgorithm: precert.SignatureAlgorithm, - PublicKeyAlgorithm: precert.PublicKeyAlgorithm, - PublicKey: precert.PublicKey, - Version: precert.Version, - SerialNumber: precert.SerialNumber, - Issuer: precert.Issuer, - Subject: precert.Subject, - NotBefore: precert.NotBefore, - NotAfter: precert.NotAfter, - KeyUsage: precert.KeyUsage, - BasicConstraintsValid: precert.BasicConstraintsValid, + SignatureAlgorithm: precert.SignatureAlgorithm, + PublicKeyAlgorithm: precert.PublicKeyAlgorithm, + PublicKey: precert.PublicKey, + Version: precert.Version, + SerialNumber: precert.SerialNumber, + Issuer: precert.Issuer, + Subject: precert.Subject, + NotBefore: precert.NotBefore, + NotAfter: precert.NotAfter, + KeyUsage: precert.KeyUsage, + BasicConstraintsValid: precert.BasicConstraintsValid, IsCA: precert.IsCA, MaxPathLen: precert.MaxPathLen, MaxPathLenZero: precert.MaxPathLenZero, @@ -493,8 +615,10 @@ func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCert // Insert the SCT list extension tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions, sctExt) - // Sign the tbsCert - return s.sign(&tbsCert) + // Sign the tbsCert. Linting is always disabled because there is no way for + // this API to know the correct lint settings to use because there is no + // reference to the signing profile of the precert available. + return s.sign(&tbsCert, 0, nil) } // Info return a populated info.Resp struct or an error. diff --git a/vendor/github.com/cloudflare/cfssl/signer/signer.go b/vendor/github.com/cloudflare/cfssl/signer/signer.go index 97d123673f..ea650bd6df 100644 --- a/vendor/github.com/cloudflare/cfssl/signer/signer.go +++ b/vendor/github.com/cloudflare/cfssl/signer/signer.go @@ -20,6 +20,7 @@ import ( "github.com/cloudflare/cfssl/config" "github.com/cloudflare/cfssl/csr" cferr "github.com/cloudflare/cfssl/errors" + "github.com/cloudflare/cfssl/helpers" "github.com/cloudflare/cfssl/info" ) @@ -45,7 +46,7 @@ type Extension struct { // Extensions provided in the signRequest are copied into the certificate, as // long as they are in the ExtensionWhitelist for the signer's policy. // Extensions requested in the CSR are ignored, except for those processed by -// ParseCertificateRequest (mainly subjectAltName). +// ParseCertificateRequest (mainly subjectAltName) and DelegationUsage. type SignRequest struct { Hosts []string `json:"hosts"` Request string `json:"certificate_request"` @@ -70,6 +71,9 @@ type SignRequest struct { // be passed to SignFromPrecert with the SCTs in order to create a // valid certificate. ReturnPrecert bool + + // Arbitrary metadata to be stored in certdb. + Metadata map[string]interface{} `json:"metadata"` } // appendIf appends to a if s is not an empty string. @@ -169,15 +173,38 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm { } } +func isCommonAttr(t []int) bool { + return (len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 && (t[3] == 3 || (t[3] >= 5 && t[3] <= 11) || t[3] == 17)) +} + // ParseCertificateRequest takes an incoming certificate request and // builds a certificate template from it. -func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certificate, err error) { +func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte) (template *x509.Certificate, err error) { csrv, err := x509.ParseCertificateRequest(csrBytes) if err != nil { err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err) return } + var r pkix.RDNSequence + _, err = asn1.Unmarshal(csrv.RawSubject, &r) + + if err != nil { + err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err) + return + } + + var subject pkix.Name + subject.FillFromRDNSequence(&r) + + for _, v := range r { + for _, vv := range v { + if !isCommonAttr(vv.Type) { + subject.ExtraNames = append(subject.ExtraNames, vv) + } + } + } + err = csrv.CheckSignature() if err != nil { err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err) @@ -185,13 +212,16 @@ func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certific } template = &x509.Certificate{ - Subject: csrv.Subject, + Subject: subject, PublicKeyAlgorithm: csrv.PublicKeyAlgorithm, PublicKey: csrv.PublicKey, SignatureAlgorithm: s.SigAlgo(), DNSNames: csrv.DNSNames, IPAddresses: csrv.IPAddresses, EmailAddresses: csrv.EmailAddresses, + URIs: csrv.URIs, + Extensions: csrv.Extensions, + ExtraExtensions: []pkix.Extension{}, } for _, val := range csrv.Extensions { @@ -211,6 +241,13 @@ func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certific template.IsCA = constraints.IsCA template.MaxPathLen = constraints.MaxPathLen template.MaxPathLenZero = template.MaxPathLen == 0 + } else if val.Id.Equal(helpers.DelegationUsage) { + template.ExtraExtensions = append(template.ExtraExtensions, val) + } else { + // If the profile has 'copy_extensions' to true then lets add it + if p.CopyExtensions { + template.ExtraExtensions = append(template.ExtraExtensions, val) + } } } @@ -320,6 +357,7 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si } template.DNSNames = nil template.EmailAddresses = nil + template.URIs = nil } template.SubjectKeyId = ski diff --git a/vendor/github.com/jmoiron/sqlx/LICENSE b/vendor/github.com/jmoiron/sqlx/LICENSE new file mode 100644 index 0000000000..0d31edfa73 --- /dev/null +++ b/vendor/github.com/jmoiron/sqlx/LICENSE @@ -0,0 +1,23 @@ + Copyright (c) 2013, Jason Moiron + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/github.com/jmoiron/sqlx/types/README.md b/vendor/github.com/jmoiron/sqlx/types/README.md new file mode 100644 index 0000000000..713abe50d1 --- /dev/null +++ b/vendor/github.com/jmoiron/sqlx/types/README.md @@ -0,0 +1,5 @@ +# types + +The types package provides some useful types which implement the `sql.Scanner` +and `driver.Valuer` interfaces, suitable for use as scan and value targets with +database/sql. diff --git a/vendor/github.com/jmoiron/sqlx/types/types.go b/vendor/github.com/jmoiron/sqlx/types/types.go new file mode 100644 index 0000000000..808f583463 --- /dev/null +++ b/vendor/github.com/jmoiron/sqlx/types/types.go @@ -0,0 +1,172 @@ +package types + +import ( + "bytes" + "compress/gzip" + "database/sql/driver" + "encoding/json" + "errors" + + "io/ioutil" +) + +// GzippedText is a []byte which transparently gzips data being submitted to +// a database and ungzips data being Scanned from a database. +type GzippedText []byte + +// Value implements the driver.Valuer interface, gzipping the raw value of +// this GzippedText. +func (g GzippedText) Value() (driver.Value, error) { + b := make([]byte, 0, len(g)) + buf := bytes.NewBuffer(b) + w := gzip.NewWriter(buf) + w.Write(g) + w.Close() + return buf.Bytes(), nil + +} + +// Scan implements the sql.Scanner interface, ungzipping the value coming off +// the wire and storing the raw result in the GzippedText. +func (g *GzippedText) Scan(src interface{}) error { + var source []byte + switch src := src.(type) { + case string: + source = []byte(src) + case []byte: + source = src + default: + return errors.New("Incompatible type for GzippedText") + } + reader, err := gzip.NewReader(bytes.NewReader(source)) + if err != nil { + return err + } + defer reader.Close() + b, err := ioutil.ReadAll(reader) + if err != nil { + return err + } + *g = GzippedText(b) + return nil +} + +// JSONText is a json.RawMessage, which is a []byte underneath. +// Value() validates the json format in the source, and returns an error if +// the json is not valid. Scan does no validation. JSONText additionally +// implements `Unmarshal`, which unmarshals the json within to an interface{} +type JSONText json.RawMessage + +var emptyJSON = JSONText("{}") + +// MarshalJSON returns the *j as the JSON encoding of j. +func (j JSONText) MarshalJSON() ([]byte, error) { + if len(j) == 0 { + return emptyJSON, nil + } + return j, nil +} + +// UnmarshalJSON sets *j to a copy of data +func (j *JSONText) UnmarshalJSON(data []byte) error { + if j == nil { + return errors.New("JSONText: UnmarshalJSON on nil pointer") + } + *j = append((*j)[0:0], data...) + return nil +} + +// Value returns j as a value. This does a validating unmarshal into another +// RawMessage. If j is invalid json, it returns an error. +func (j JSONText) Value() (driver.Value, error) { + var m json.RawMessage + var err = j.Unmarshal(&m) + if err != nil { + return []byte{}, err + } + return []byte(j), nil +} + +// Scan stores the src in *j. No validation is done. +func (j *JSONText) Scan(src interface{}) error { + var source []byte + switch t := src.(type) { + case string: + source = []byte(t) + case []byte: + if len(t) == 0 { + source = emptyJSON + } else { + source = t + } + case nil: + *j = emptyJSON + default: + return errors.New("Incompatible type for JSONText") + } + *j = append((*j)[0:0], source...) + return nil +} + +// Unmarshal unmarshal's the json in j to v, as in json.Unmarshal. +func (j *JSONText) Unmarshal(v interface{}) error { + if len(*j) == 0 { + *j = emptyJSON + } + return json.Unmarshal([]byte(*j), v) +} + +// String supports pretty printing for JSONText types. +func (j JSONText) String() string { + return string(j) +} + +// NullJSONText represents a JSONText that may be null. +// NullJSONText implements the scanner interface so +// it can be used as a scan destination, similar to NullString. +type NullJSONText struct { + JSONText + Valid bool // Valid is true if JSONText is not NULL +} + +// Scan implements the Scanner interface. +func (n *NullJSONText) Scan(value interface{}) error { + if value == nil { + n.JSONText, n.Valid = emptyJSON, false + return nil + } + n.Valid = true + return n.JSONText.Scan(value) +} + +// Value implements the driver Valuer interface. +func (n NullJSONText) Value() (driver.Value, error) { + if !n.Valid { + return nil, nil + } + return n.JSONText.Value() +} + +// BitBool is an implementation of a bool for the MySQL type BIT(1). +// This type allows you to avoid wasting an entire byte for MySQL's boolean type TINYINT. +type BitBool bool + +// Value implements the driver.Valuer interface, +// and turns the BitBool into a bitfield (BIT(1)) for MySQL storage. +func (b BitBool) Value() (driver.Value, error) { + if b { + return []byte{1}, nil + } + return []byte{0}, nil +} + +// Scan implements the sql.Scanner interface, +// and turns the bitfield incoming from MySQL into a BitBool +func (b *BitBool) Scan(src interface{}) error { + v, ok := src.([]byte) + if !ok { + return errors.New("bad []byte type assertion") + } + *b = v[0] == 1 + return nil +} diff --git a/vendor/github.com/weppos/publicsuffix-go/LICENSE.txt b/vendor/github.com/weppos/publicsuffix-go/LICENSE.txt new file mode 100644 index 0000000000..079a934f9d --- /dev/null +++ b/vendor/github.com/weppos/publicsuffix-go/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2020 Simone Carletti + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/weppos/publicsuffix-go/publicsuffix/publicsuffix.go b/vendor/github.com/weppos/publicsuffix-go/publicsuffix/publicsuffix.go new file mode 100644 index 0000000000..689a89f269 --- /dev/null +++ b/vendor/github.com/weppos/publicsuffix-go/publicsuffix/publicsuffix.go @@ -0,0 +1,544 @@ +//go:generate go run ../cmd/gen/gen.go + +// Package publicsuffix provides a domain name parser +// based on data from the public suffix list http://publicsuffix.org/. +// A public suffix is one under which Internet users can directly register names. +package publicsuffix + +import ( + "bufio" + "fmt" + "io" + "net/http/cookiejar" + "os" + "strings" + + "golang.org/x/net/idna" +) + +const ( + // Version identifies the current library version. + // This is a pro forma convention given that Go dependencies + // tends to be fetched directly from the repo. + Version = "0.15.0" + + // NormalType represents a normal rule such as "com" + NormalType = 1 + // WildcardType represents a wildcard rule such as "*.com" + WildcardType = 2 + // ExceptionType represents an exception to a wildard rule + ExceptionType = 3 + + listTokenPrivateDomains = "===BEGIN PRIVATE DOMAINS===" + listTokenComment = "//" +) + +// DefaultList is the default List and it is used by Parse and Domain. +var DefaultList = NewList() + +// DefaultRule is the default Rule that represents "*". +var DefaultRule = MustNewRule("*") + +// DefaultParserOptions are the default options used to parse a Public Suffix list. +var DefaultParserOptions = &ParserOption{PrivateDomains: true, ASCIIEncoded: false} + +// DefaultFindOptions are the default options used to perform the lookup of rules in the list. +var DefaultFindOptions = &FindOptions{IgnorePrivate: false, DefaultRule: DefaultRule} + +// Rule represents a single rule in a Public Suffix List. +type Rule struct { + Type int + Value string + Length int + Private bool +} + +// ParserOption are the options you can use to customize the way a List +// is parsed from a file or a string. +type ParserOption struct { + // Set to false to skip the private domains when parsing. + // Default to true, which means the private domains are included. + PrivateDomains bool + + // Set to false if the input is encoded in U-labels (Unicode) + // as opposite to A-labels. + // Default to false, which means the list is containing Unicode domains. + // This is the default because the original PSL currently contains Unicode. + ASCIIEncoded bool +} + +// FindOptions are the options you can use to customize the way a Rule +// is searched within the list. +type FindOptions struct { + // Set to true to ignore the rules within the "Private" section of the Public Suffix List. + IgnorePrivate bool + + // The default rule to use when no rule matches the input. + // The format Public Suffix algorithm states that the rule "*" should be used when no other rule matches, + // but some consumers may have different needs. + DefaultRule *Rule +} + +// List represents a Public Suffix List. +type List struct { + // rules is kept private because you should not access rules directly + rules map[string]*Rule +} + +// NewList creates a new empty list. +func NewList() *List { + return &List{ + rules: map[string]*Rule{}, + } +} + +// NewListFromString parses a string that represents a Public Suffix source +// and returns a List initialized with the rules in the source. +func NewListFromString(src string, options *ParserOption) (*List, error) { + l := NewList() + _, err := l.LoadString(src, options) + return l, err +} + +// NewListFromFile parses a string that represents a Public Suffix source +// and returns a List initialized with the rules in the source. +func NewListFromFile(path string, options *ParserOption) (*List, error) { + l := NewList() + _, err := l.LoadFile(path, options) + return l, err +} + +// Load parses and loads a set of rules from an io.Reader into the current list. +func (l *List) Load(r io.Reader, options *ParserOption) ([]Rule, error) { + return l.parse(r, options) +} + +// LoadString parses and loads a set of rules from a String into the current list. +func (l *List) LoadString(src string, options *ParserOption) ([]Rule, error) { + r := strings.NewReader(src) + return l.parse(r, options) +} + +// LoadFile parses and loads a set of rules from a File into the current list. +func (l *List) LoadFile(path string, options *ParserOption) ([]Rule, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + return l.parse(f, options) +} + +// AddRule adds a new rule to the list. +// +// The exact position of the rule into the list is unpredictable. +// The list may be optimized internally for lookups, therefore the algorithm +// will decide the best position for the new rule. +func (l *List) AddRule(r *Rule) error { + l.rules[r.Value] = r + return nil +} + +// Size returns the size of the list, which is the number of rules. +func (l *List) Size() int { + return len(l.rules) +} + +func (l *List) parse(r io.Reader, options *ParserOption) ([]Rule, error) { + if options == nil { + options = DefaultParserOptions + } + var rules []Rule + + scanner := bufio.NewScanner(r) + var section int // 1 == ICANN, 2 == PRIVATE + +Scanning: + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + switch { + + // skip blank lines + case line == "": + break + + // include private domains or stop scanner + case strings.Contains(line, listTokenPrivateDomains): + if !options.PrivateDomains { + break Scanning + } + section = 2 + + // skip comments + case strings.HasPrefix(line, listTokenComment): + break + + default: + var rule *Rule + var err error + + if options.ASCIIEncoded { + rule, err = NewRule(line) + } else { + rule, err = NewRuleUnicode(line) + } + if err != nil { + return []Rule{}, err + } + + rule.Private = (section == 2) + l.AddRule(rule) + rules = append(rules, *rule) + } + + } + + return rules, scanner.Err() +} + +// Find and returns the most appropriate rule for the domain name. +func (l *List) Find(name string, options *FindOptions) *Rule { + if options == nil { + options = DefaultFindOptions + } + + part := name + for { + rule, ok := l.rules[part] + + if ok && rule.Match(name) && !(options.IgnorePrivate && rule.Private) { + return rule + } + + i := strings.IndexRune(part, '.') + if i < 0 { + return options.DefaultRule + } + + part = part[i+1:] + } + +} + +// NewRule parses the rule content, creates and returns a Rule. +// +// The content of the rule MUST be encoded in ASCII (A-labels). +func NewRule(content string) (*Rule, error) { + var rule *Rule + var value string + + switch content[0] { + case '*': // wildcard + if content == "*" { + value = "" + } else { + value = content[2:] + } + rule = &Rule{Type: WildcardType, Value: value, Length: len(Labels(value)) + 1} + case '!': // exception + value = content[1:] + rule = &Rule{Type: ExceptionType, Value: value, Length: len(Labels(value))} + default: // normal + value = content + rule = &Rule{Type: NormalType, Value: value, Length: len(Labels(value))} + } + + return rule, nil +} + +// NewRuleUnicode is like NewRule, but expects the content to be encoded in Unicode (U-labels). +func NewRuleUnicode(content string) (*Rule, error) { + var err error + + content, err = ToASCII(content) + if err != nil { + return nil, err + } + + return NewRule(content) +} + +// MustNewRule is like NewRule, but panics if the content cannot be parsed. +func MustNewRule(content string) *Rule { + rule, err := NewRule(content) + if err != nil { + panic(err) + } + return rule +} + +// Match checks if the rule matches the name. +// +// A domain name is said to match a rule if and only if all of the following conditions are met: +// - When the domain and rule are split into corresponding labels, +// that the domain contains as many or more labels than the rule. +// - Beginning with the right-most labels of both the domain and the rule, +// and continuing for all labels in the rule, one finds that for every pair, +// either they are identical, or that the label from the rule is "*". +// +// See https://publicsuffix.org/list/ +func (r *Rule) Match(name string) bool { + left := strings.TrimSuffix(name, r.Value) + + // the name contains as many labels than the rule + // this is a match, unless it's a wildcard + // because the wildcard requires one more label + if left == "" { + return r.Type != WildcardType + } + + // if there is one more label, the rule match + // because either the rule is shorter than the domain + // or the rule is a wildcard and there is one more label + return left[len(left)-1:] == "." +} + +// Decompose takes a name as input and decomposes it into a tuple of , +// according to the rule definition and type. +func (r *Rule) Decompose(name string) (result [2]string) { + if r == DefaultRule { + i := strings.LastIndexByte(name, '.') + if i < 0 { + return + } + result[0], result[1] = name[:i], name[i+1:] + return + } + switch r.Type { + case NormalType: + name = strings.TrimSuffix(name, r.Value) + if len(name) == 0 { + return + } + result[0], result[1] = name[:len(name)-1], r.Value + case WildcardType: + name := strings.TrimSuffix(name, r.Value) + if len(name) == 0 { + return + } + name = name[:len(name)-1] + i := strings.LastIndexByte(name, '.') + if i < 0 { + return + } + result[0], result[1] = name[:i], name[i+1:]+"."+r.Value + case ExceptionType: + i := strings.IndexRune(r.Value, '.') + if i < 0 { + return + } + suffix := r.Value[i+1:] + name = strings.TrimSuffix(name, suffix) + if len(name) == 0 { + return + } + result[0], result[1] = name[:len(name)-1], suffix + } + return +} + +// Labels decomposes given domain name into labels, +// corresponding to the dot-separated tokens. +func Labels(name string) []string { + return strings.Split(name, ".") +} + +// DomainName represents a domain name. +type DomainName struct { + TLD string + SLD string + TRD string + Rule *Rule +} + +// String joins the components of the domain name into a single string. +// Empty labels are skipped. +// +// Examples: +// +// DomainName{"com", "example"}.String() +// // example.com +// DomainName{"com", "example", "www"}.String() +// // www.example.com +// +func (d *DomainName) String() string { + switch { + case d.TLD == "": + return "" + case d.SLD == "": + return d.TLD + case d.TRD == "": + return d.SLD + "." + d.TLD + default: + return d.TRD + "." + d.SLD + "." + d.TLD + } +} + +// Domain extract and return the domain name from the input +// using the default (Public Suffix) List. +// +// Examples: +// +// publicsuffix.Domain("example.com") +// // example.com +// publicsuffix.Domain("www.example.com") +// // example.com +// publicsuffix.Domain("www.example.co.uk") +// // example.co.uk +// +func Domain(name string) (string, error) { + return DomainFromListWithOptions(DefaultList, name, DefaultFindOptions) +} + +// Parse decomposes the name into TLD, SLD, TRD +// using the default (Public Suffix) List, +// and returns the result as a DomainName +// +// Examples: +// +// list := NewList() +// +// publicsuffix.Parse("example.com") +// // &DomainName{"com", "example"} +// publicsuffix.Parse("www.example.com") +// // &DomainName{"com", "example", "www"} +// publicsuffix.Parse("www.example.co.uk") +// // &DomainName{"co.uk", "example"} +// +func Parse(name string) (*DomainName, error) { + return ParseFromListWithOptions(DefaultList, name, DefaultFindOptions) +} + +// DomainFromListWithOptions extract and return the domain name from the input +// using the (Public Suffix) list passed as argument. +// +// Examples: +// +// list := NewList() +// +// publicsuffix.DomainFromListWithOptions(list, "example.com") +// // example.com +// publicsuffix.DomainFromListWithOptions(list, "www.example.com") +// // example.com +// publicsuffix.DomainFromListWithOptions(list, "www.example.co.uk") +// // example.co.uk +// +func DomainFromListWithOptions(l *List, name string, options *FindOptions) (string, error) { + dn, err := ParseFromListWithOptions(l, name, options) + if err != nil { + return "", err + } + return dn.SLD + "." + dn.TLD, nil +} + +// ParseFromListWithOptions decomposes the name into TLD, SLD, TRD +// using the (Public Suffix) list passed as argument, +// and returns the result as a DomainName +// +// Examples: +// +// list := NewList() +// +// publicsuffix.ParseFromListWithOptions(list, "example.com") +// // &DomainName{"com", "example"} +// publicsuffix.ParseFromListWithOptions(list, "www.example.com") +// // &DomainName{"com", "example", "www"} +// publicsuffix.ParseFromListWithOptions(list, "www.example.co.uk") +// // &DomainName{"co.uk", "example"} +// +func ParseFromListWithOptions(l *List, name string, options *FindOptions) (*DomainName, error) { + n, err := normalize(name) + if err != nil { + return nil, err + } + + r := l.Find(n, options) + if r == nil { + return nil, fmt.Errorf("no rule matching name %s", name) + } + + parts := r.Decompose(n) + left, tld := parts[0], parts[1] + if tld == "" { + return nil, fmt.Errorf("%s is a suffix", n) + } + + dn := &DomainName{ + Rule: r, + TLD: tld, + } + if i := strings.LastIndexByte(left, '.'); i < 0 { + dn.SLD = left + } else { + dn.TRD = left[:i] + dn.SLD = left[i+1:] + } + return dn, nil +} + +func normalize(name string) (string, error) { + ret := strings.ToLower(name) + + if ret == "" { + return "", fmt.Errorf("name is blank") + } + if ret[0] == '.' { + return "", fmt.Errorf("name %s starts with a dot", ret) + } + + return ret, nil +} + +// ToASCII is a wrapper for idna.ToASCII. +// +// This wrapper exists because idna.ToASCII backward-compatibility was broken twice in few months +// and I can't call this package directly anymore. The wrapper performs some terrible-but-necessary +// before-after replacements to make sure an already ASCII input always results in the same output +// even if passed through ToASCII. +// +// See golang/net@67957fd0b1, golang/net@f2499483f9, golang/net@78ebe5c8b6, +// and weppos/publicsuffix-go#66. +func ToASCII(s string) (string, error) { + // .example.com should be .example.com + // ..example.com should be ..example.com + if strings.HasPrefix(s, ".") { + dotIndex := 0 + for i := 0; i < len(s); i++ { + if s[i] == '.' { + dotIndex = i + } else { + break + } + } + out, err := idna.ToASCII(s[dotIndex+1:]) + out = s[:dotIndex+1] + out + return out, err + } + + return idna.ToASCII(s) +} + +// ToUnicode is a wrapper for idna.ToUnicode. +// +// See ToASCII for more details about why this wrapper exists. +func ToUnicode(s string) (string, error) { + return idna.ToUnicode(s) +} + +// CookieJarList implements the cookiejar.PublicSuffixList interface. +var CookieJarList cookiejar.PublicSuffixList = cookiejarList{DefaultList} + +type cookiejarList struct { + List *List +} + +// PublicSuffix implements cookiejar.PublicSuffixList. +func (l cookiejarList) PublicSuffix(domain string) string { + rule := l.List.Find(domain, nil) + return rule.Decompose(domain)[1] +} + +// PublicSuffix implements cookiejar.String. +func (cookiejarList) String() string { + return defaultListVersion +} diff --git a/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go b/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go new file mode 100644 index 0000000000..1514f9c5f7 --- /dev/null +++ b/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go @@ -0,0 +1,9188 @@ +// This file is automatically generated +// Run "go run cmd/gen/gen.go" to update the list. + +package publicsuffix + +const defaultListVersion = "PSL version 598c63 (Thu May 6 04:03:10 2021)" + +func DefaultRules() [9169]Rule { + return r +} + +var r = [9169]Rule{ + {1, "ac", 1, false}, + {1, "com.ac", 2, false}, + {1, "edu.ac", 2, false}, + {1, "gov.ac", 2, false}, + {1, "net.ac", 2, false}, + {1, "mil.ac", 2, false}, + {1, "org.ac", 2, false}, + {1, "ad", 1, false}, + {1, "nom.ad", 2, false}, + {1, "ae", 1, false}, + {1, "co.ae", 2, false}, + {1, "net.ae", 2, false}, + {1, "org.ae", 2, false}, + {1, "sch.ae", 2, false}, + {1, "ac.ae", 2, false}, + {1, "gov.ae", 2, false}, + {1, "mil.ae", 2, false}, + {1, "aero", 1, false}, + {1, "accident-investigation.aero", 2, false}, + {1, "accident-prevention.aero", 2, false}, + {1, "aerobatic.aero", 2, false}, + {1, "aeroclub.aero", 2, false}, + {1, "aerodrome.aero", 2, false}, + {1, "agents.aero", 2, false}, + {1, "aircraft.aero", 2, false}, + {1, "airline.aero", 2, false}, + {1, "airport.aero", 2, false}, + {1, "air-surveillance.aero", 2, false}, + {1, "airtraffic.aero", 2, false}, + {1, "air-traffic-control.aero", 2, false}, + {1, "ambulance.aero", 2, false}, + {1, "amusement.aero", 2, false}, + {1, "association.aero", 2, false}, + {1, "author.aero", 2, false}, + {1, "ballooning.aero", 2, false}, + {1, "broker.aero", 2, false}, + {1, "caa.aero", 2, false}, + {1, "cargo.aero", 2, false}, + {1, "catering.aero", 2, false}, + {1, "certification.aero", 2, false}, + {1, "championship.aero", 2, false}, + {1, "charter.aero", 2, false}, + {1, "civilaviation.aero", 2, false}, + {1, "club.aero", 2, false}, + {1, "conference.aero", 2, false}, + {1, "consultant.aero", 2, false}, + {1, "consulting.aero", 2, false}, + {1, "control.aero", 2, false}, + {1, "council.aero", 2, false}, + {1, "crew.aero", 2, false}, + {1, "design.aero", 2, false}, + {1, "dgca.aero", 2, false}, + {1, "educator.aero", 2, false}, + {1, "emergency.aero", 2, false}, + {1, "engine.aero", 2, false}, + {1, "engineer.aero", 2, false}, + {1, "entertainment.aero", 2, false}, + {1, "equipment.aero", 2, false}, + {1, "exchange.aero", 2, false}, + {1, "express.aero", 2, false}, + {1, "federation.aero", 2, false}, + {1, "flight.aero", 2, false}, + {1, "fuel.aero", 2, false}, + {1, "gliding.aero", 2, false}, + {1, "government.aero", 2, false}, + {1, "groundhandling.aero", 2, false}, + {1, "group.aero", 2, false}, + {1, "hanggliding.aero", 2, false}, + {1, "homebuilt.aero", 2, false}, + {1, "insurance.aero", 2, false}, + {1, "journal.aero", 2, false}, + {1, "journalist.aero", 2, false}, + {1, "leasing.aero", 2, false}, + {1, "logistics.aero", 2, false}, + {1, "magazine.aero", 2, false}, + {1, "maintenance.aero", 2, false}, + {1, "media.aero", 2, false}, + {1, "microlight.aero", 2, false}, + {1, "modelling.aero", 2, false}, + {1, "navigation.aero", 2, false}, + {1, "parachuting.aero", 2, false}, + {1, "paragliding.aero", 2, false}, + {1, "passenger-association.aero", 2, false}, + {1, "pilot.aero", 2, false}, + {1, "press.aero", 2, false}, + {1, "production.aero", 2, false}, + {1, "recreation.aero", 2, false}, + {1, "repbody.aero", 2, false}, + {1, "res.aero", 2, false}, + {1, "research.aero", 2, false}, + {1, "rotorcraft.aero", 2, false}, + {1, "safety.aero", 2, false}, + {1, "scientist.aero", 2, false}, + {1, "services.aero", 2, false}, + {1, "show.aero", 2, false}, + {1, "skydiving.aero", 2, false}, + {1, "software.aero", 2, false}, + {1, "student.aero", 2, false}, + {1, "trader.aero", 2, false}, + {1, "trading.aero", 2, false}, + {1, "trainer.aero", 2, false}, + {1, "union.aero", 2, false}, + {1, "workinggroup.aero", 2, false}, + {1, "works.aero", 2, false}, + {1, "af", 1, false}, + {1, "gov.af", 2, false}, + {1, "com.af", 2, false}, + {1, "org.af", 2, false}, + {1, "net.af", 2, false}, + {1, "edu.af", 2, false}, + {1, "ag", 1, false}, + {1, "com.ag", 2, false}, + {1, "org.ag", 2, false}, + {1, "net.ag", 2, false}, + {1, "co.ag", 2, false}, + {1, "nom.ag", 2, false}, + {1, "ai", 1, false}, + {1, "off.ai", 2, false}, + {1, "com.ai", 2, false}, + {1, "net.ai", 2, false}, + {1, "org.ai", 2, false}, + {1, "al", 1, false}, + {1, "com.al", 2, false}, + {1, "edu.al", 2, false}, + {1, "gov.al", 2, false}, + {1, "mil.al", 2, false}, + {1, "net.al", 2, false}, + {1, "org.al", 2, false}, + {1, "am", 1, false}, + {1, "co.am", 2, false}, + {1, "com.am", 2, false}, + {1, "commune.am", 2, false}, + {1, "net.am", 2, false}, + {1, "org.am", 2, false}, + {1, "ao", 1, false}, + {1, "ed.ao", 2, false}, + {1, "gv.ao", 2, false}, + {1, "og.ao", 2, false}, + {1, "co.ao", 2, false}, + {1, "pb.ao", 2, false}, + {1, "it.ao", 2, false}, + {1, "aq", 1, false}, + {1, "ar", 1, false}, + {1, "com.ar", 2, false}, + {1, "edu.ar", 2, false}, + {1, "gob.ar", 2, false}, + {1, "gov.ar", 2, false}, + {1, "int.ar", 2, false}, + {1, "mil.ar", 2, false}, + {1, "musica.ar", 2, false}, + {1, "net.ar", 2, false}, + {1, "org.ar", 2, false}, + {1, "tur.ar", 2, false}, + {1, "arpa", 1, false}, + {1, "e164.arpa", 2, false}, + {1, "in-addr.arpa", 2, false}, + {1, "ip6.arpa", 2, false}, + {1, "iris.arpa", 2, false}, + {1, "uri.arpa", 2, false}, + {1, "urn.arpa", 2, false}, + {1, "as", 1, false}, + {1, "gov.as", 2, false}, + {1, "asia", 1, false}, + {1, "at", 1, false}, + {1, "ac.at", 2, false}, + {1, "co.at", 2, false}, + {1, "gv.at", 2, false}, + {1, "or.at", 2, false}, + {1, "sth.ac.at", 3, false}, + {1, "au", 1, false}, + {1, "com.au", 2, false}, + {1, "net.au", 2, false}, + {1, "org.au", 2, false}, + {1, "edu.au", 2, false}, + {1, "gov.au", 2, false}, + {1, "asn.au", 2, false}, + {1, "id.au", 2, false}, + {1, "info.au", 2, false}, + {1, "conf.au", 2, false}, + {1, "oz.au", 2, false}, + {1, "act.au", 2, false}, + {1, "nsw.au", 2, false}, + {1, "nt.au", 2, false}, + {1, "qld.au", 2, false}, + {1, "sa.au", 2, false}, + {1, "tas.au", 2, false}, + {1, "vic.au", 2, false}, + {1, "wa.au", 2, false}, + {1, "act.edu.au", 3, false}, + {1, "catholic.edu.au", 3, false}, + {1, "nsw.edu.au", 3, false}, + {1, "nt.edu.au", 3, false}, + {1, "qld.edu.au", 3, false}, + {1, "sa.edu.au", 3, false}, + {1, "tas.edu.au", 3, false}, + {1, "vic.edu.au", 3, false}, + {1, "wa.edu.au", 3, false}, + {1, "qld.gov.au", 3, false}, + {1, "sa.gov.au", 3, false}, + {1, "tas.gov.au", 3, false}, + {1, "vic.gov.au", 3, false}, + {1, "wa.gov.au", 3, false}, + {1, "schools.nsw.edu.au", 4, false}, + {1, "aw", 1, false}, + {1, "com.aw", 2, false}, + {1, "ax", 1, false}, + {1, "az", 1, false}, + {1, "com.az", 2, false}, + {1, "net.az", 2, false}, + {1, "int.az", 2, false}, + {1, "gov.az", 2, false}, + {1, "org.az", 2, false}, + {1, "edu.az", 2, false}, + {1, "info.az", 2, false}, + {1, "pp.az", 2, false}, + {1, "mil.az", 2, false}, + {1, "name.az", 2, false}, + {1, "pro.az", 2, false}, + {1, "biz.az", 2, false}, + {1, "ba", 1, false}, + {1, "com.ba", 2, false}, + {1, "edu.ba", 2, false}, + {1, "gov.ba", 2, false}, + {1, "mil.ba", 2, false}, + {1, "net.ba", 2, false}, + {1, "org.ba", 2, false}, + {1, "bb", 1, false}, + {1, "biz.bb", 2, false}, + {1, "co.bb", 2, false}, + {1, "com.bb", 2, false}, + {1, "edu.bb", 2, false}, + {1, "gov.bb", 2, false}, + {1, "info.bb", 2, false}, + {1, "net.bb", 2, false}, + {1, "org.bb", 2, false}, + {1, "store.bb", 2, false}, + {1, "tv.bb", 2, false}, + {2, "bd", 2, false}, + {1, "be", 1, false}, + {1, "ac.be", 2, false}, + {1, "bf", 1, false}, + {1, "gov.bf", 2, false}, + {1, "bg", 1, false}, + {1, "a.bg", 2, false}, + {1, "b.bg", 2, false}, + {1, "c.bg", 2, false}, + {1, "d.bg", 2, false}, + {1, "e.bg", 2, false}, + {1, "f.bg", 2, false}, + {1, "g.bg", 2, false}, + {1, "h.bg", 2, false}, + {1, "i.bg", 2, false}, + {1, "j.bg", 2, false}, + {1, "k.bg", 2, false}, + {1, "l.bg", 2, false}, + {1, "m.bg", 2, false}, + {1, "n.bg", 2, false}, + {1, "o.bg", 2, false}, + {1, "p.bg", 2, false}, + {1, "q.bg", 2, false}, + {1, "r.bg", 2, false}, + {1, "s.bg", 2, false}, + {1, "t.bg", 2, false}, + {1, "u.bg", 2, false}, + {1, "v.bg", 2, false}, + {1, "w.bg", 2, false}, + {1, "x.bg", 2, false}, + {1, "y.bg", 2, false}, + {1, "z.bg", 2, false}, + {1, "0.bg", 2, false}, + {1, "1.bg", 2, false}, + {1, "2.bg", 2, false}, + {1, "3.bg", 2, false}, + {1, "4.bg", 2, false}, + {1, "5.bg", 2, false}, + {1, "6.bg", 2, false}, + {1, "7.bg", 2, false}, + {1, "8.bg", 2, false}, + {1, "9.bg", 2, false}, + {1, "bh", 1, false}, + {1, "com.bh", 2, false}, + {1, "edu.bh", 2, false}, + {1, "net.bh", 2, false}, + {1, "org.bh", 2, false}, + {1, "gov.bh", 2, false}, + {1, "bi", 1, false}, + {1, "co.bi", 2, false}, + {1, "com.bi", 2, false}, + {1, "edu.bi", 2, false}, + {1, "or.bi", 2, false}, + {1, "org.bi", 2, false}, + {1, "biz", 1, false}, + {1, "bj", 1, false}, + {1, "asso.bj", 2, false}, + {1, "barreau.bj", 2, false}, + {1, "gouv.bj", 2, false}, + {1, "bm", 1, false}, + {1, "com.bm", 2, false}, + {1, "edu.bm", 2, false}, + {1, "gov.bm", 2, false}, + {1, "net.bm", 2, false}, + {1, "org.bm", 2, false}, + {1, "bn", 1, false}, + {1, "com.bn", 2, false}, + {1, "edu.bn", 2, false}, + {1, "gov.bn", 2, false}, + {1, "net.bn", 2, false}, + {1, "org.bn", 2, false}, + {1, "bo", 1, false}, + {1, "com.bo", 2, false}, + {1, "edu.bo", 2, false}, + {1, "gob.bo", 2, false}, + {1, "int.bo", 2, false}, + {1, "org.bo", 2, false}, + {1, "net.bo", 2, false}, + {1, "mil.bo", 2, false}, + {1, "tv.bo", 2, false}, + {1, "web.bo", 2, false}, + {1, "academia.bo", 2, false}, + {1, "agro.bo", 2, false}, + {1, "arte.bo", 2, false}, + {1, "blog.bo", 2, false}, + {1, "bolivia.bo", 2, false}, + {1, "ciencia.bo", 2, false}, + {1, "cooperativa.bo", 2, false}, + {1, "democracia.bo", 2, false}, + {1, "deporte.bo", 2, false}, + {1, "ecologia.bo", 2, false}, + {1, "economia.bo", 2, false}, + {1, "empresa.bo", 2, false}, + {1, "indigena.bo", 2, false}, + {1, "industria.bo", 2, false}, + {1, "info.bo", 2, false}, + {1, "medicina.bo", 2, false}, + {1, "movimiento.bo", 2, false}, + {1, "musica.bo", 2, false}, + {1, "natural.bo", 2, false}, + {1, "nombre.bo", 2, false}, + {1, "noticias.bo", 2, false}, + {1, "patria.bo", 2, false}, + {1, "politica.bo", 2, false}, + {1, "profesional.bo", 2, false}, + {1, "plurinacional.bo", 2, false}, + {1, "pueblo.bo", 2, false}, + {1, "revista.bo", 2, false}, + {1, "salud.bo", 2, false}, + {1, "tecnologia.bo", 2, false}, + {1, "tksat.bo", 2, false}, + {1, "transporte.bo", 2, false}, + {1, "wiki.bo", 2, false}, + {1, "br", 1, false}, + {1, "9guacu.br", 2, false}, + {1, "abc.br", 2, false}, + {1, "adm.br", 2, false}, + {1, "adv.br", 2, false}, + {1, "agr.br", 2, false}, + {1, "aju.br", 2, false}, + {1, "am.br", 2, false}, + {1, "anani.br", 2, false}, + {1, "aparecida.br", 2, false}, + {1, "app.br", 2, false}, + {1, "arq.br", 2, false}, + {1, "art.br", 2, false}, + {1, "ato.br", 2, false}, + {1, "b.br", 2, false}, + {1, "barueri.br", 2, false}, + {1, "belem.br", 2, false}, + {1, "bhz.br", 2, false}, + {1, "bib.br", 2, false}, + {1, "bio.br", 2, false}, + {1, "blog.br", 2, false}, + {1, "bmd.br", 2, false}, + {1, "boavista.br", 2, false}, + {1, "bsb.br", 2, false}, + {1, "campinagrande.br", 2, false}, + {1, "campinas.br", 2, false}, + {1, "caxias.br", 2, false}, + {1, "cim.br", 2, false}, + {1, "cng.br", 2, false}, + {1, "cnt.br", 2, false}, + {1, "com.br", 2, false}, + {1, "contagem.br", 2, false}, + {1, "coop.br", 2, false}, + {1, "coz.br", 2, false}, + {1, "cri.br", 2, false}, + {1, "cuiaba.br", 2, false}, + {1, "curitiba.br", 2, false}, + {1, "def.br", 2, false}, + {1, "des.br", 2, false}, + {1, "det.br", 2, false}, + {1, "dev.br", 2, false}, + {1, "ecn.br", 2, false}, + {1, "eco.br", 2, false}, + {1, "edu.br", 2, false}, + {1, "emp.br", 2, false}, + {1, "enf.br", 2, false}, + {1, "eng.br", 2, false}, + {1, "esp.br", 2, false}, + {1, "etc.br", 2, false}, + {1, "eti.br", 2, false}, + {1, "far.br", 2, false}, + {1, "feira.br", 2, false}, + {1, "flog.br", 2, false}, + {1, "floripa.br", 2, false}, + {1, "fm.br", 2, false}, + {1, "fnd.br", 2, false}, + {1, "fortal.br", 2, false}, + {1, "fot.br", 2, false}, + {1, "foz.br", 2, false}, + {1, "fst.br", 2, false}, + {1, "g12.br", 2, false}, + {1, "geo.br", 2, false}, + {1, "ggf.br", 2, false}, + {1, "goiania.br", 2, false}, + {1, "gov.br", 2, false}, + {1, "ac.gov.br", 3, false}, + {1, "al.gov.br", 3, false}, + {1, "am.gov.br", 3, false}, + {1, "ap.gov.br", 3, false}, + {1, "ba.gov.br", 3, false}, + {1, "ce.gov.br", 3, false}, + {1, "df.gov.br", 3, false}, + {1, "es.gov.br", 3, false}, + {1, "go.gov.br", 3, false}, + {1, "ma.gov.br", 3, false}, + {1, "mg.gov.br", 3, false}, + {1, "ms.gov.br", 3, false}, + {1, "mt.gov.br", 3, false}, + {1, "pa.gov.br", 3, false}, + {1, "pb.gov.br", 3, false}, + {1, "pe.gov.br", 3, false}, + {1, "pi.gov.br", 3, false}, + {1, "pr.gov.br", 3, false}, + {1, "rj.gov.br", 3, false}, + {1, "rn.gov.br", 3, false}, + {1, "ro.gov.br", 3, false}, + {1, "rr.gov.br", 3, false}, + {1, "rs.gov.br", 3, false}, + {1, "sc.gov.br", 3, false}, + {1, "se.gov.br", 3, false}, + {1, "sp.gov.br", 3, false}, + {1, "to.gov.br", 3, false}, + {1, "gru.br", 2, false}, + {1, "imb.br", 2, false}, + {1, "ind.br", 2, false}, + {1, "inf.br", 2, false}, + {1, "jab.br", 2, false}, + {1, "jampa.br", 2, false}, + {1, "jdf.br", 2, false}, + {1, "joinville.br", 2, false}, + {1, "jor.br", 2, false}, + {1, "jus.br", 2, false}, + {1, "leg.br", 2, false}, + {1, "lel.br", 2, false}, + {1, "log.br", 2, false}, + {1, "londrina.br", 2, false}, + {1, "macapa.br", 2, false}, + {1, "maceio.br", 2, false}, + {1, "manaus.br", 2, false}, + {1, "maringa.br", 2, false}, + {1, "mat.br", 2, false}, + {1, "med.br", 2, false}, + {1, "mil.br", 2, false}, + {1, "morena.br", 2, false}, + {1, "mp.br", 2, false}, + {1, "mus.br", 2, false}, + {1, "natal.br", 2, false}, + {1, "net.br", 2, false}, + {1, "niteroi.br", 2, false}, + {2, "nom.br", 3, false}, + {1, "not.br", 2, false}, + {1, "ntr.br", 2, false}, + {1, "odo.br", 2, false}, + {1, "ong.br", 2, false}, + {1, "org.br", 2, false}, + {1, "osasco.br", 2, false}, + {1, "palmas.br", 2, false}, + {1, "poa.br", 2, false}, + {1, "ppg.br", 2, false}, + {1, "pro.br", 2, false}, + {1, "psc.br", 2, false}, + {1, "psi.br", 2, false}, + {1, "pvh.br", 2, false}, + {1, "qsl.br", 2, false}, + {1, "radio.br", 2, false}, + {1, "rec.br", 2, false}, + {1, "recife.br", 2, false}, + {1, "rep.br", 2, false}, + {1, "ribeirao.br", 2, false}, + {1, "rio.br", 2, false}, + {1, "riobranco.br", 2, false}, + {1, "riopreto.br", 2, false}, + {1, "salvador.br", 2, false}, + {1, "sampa.br", 2, false}, + {1, "santamaria.br", 2, false}, + {1, "santoandre.br", 2, false}, + {1, "saobernardo.br", 2, false}, + {1, "saogonca.br", 2, false}, + {1, "seg.br", 2, false}, + {1, "sjc.br", 2, false}, + {1, "slg.br", 2, false}, + {1, "slz.br", 2, false}, + {1, "sorocaba.br", 2, false}, + {1, "srv.br", 2, false}, + {1, "taxi.br", 2, false}, + {1, "tc.br", 2, false}, + {1, "tec.br", 2, false}, + {1, "teo.br", 2, false}, + {1, "the.br", 2, false}, + {1, "tmp.br", 2, false}, + {1, "trd.br", 2, false}, + {1, "tur.br", 2, false}, + {1, "tv.br", 2, false}, + {1, "udi.br", 2, false}, + {1, "vet.br", 2, false}, + {1, "vix.br", 2, false}, + {1, "vlog.br", 2, false}, + {1, "wiki.br", 2, false}, + {1, "zlg.br", 2, false}, + {1, "bs", 1, false}, + {1, "com.bs", 2, false}, + {1, "net.bs", 2, false}, + {1, "org.bs", 2, false}, + {1, "edu.bs", 2, false}, + {1, "gov.bs", 2, false}, + {1, "bt", 1, false}, + {1, "com.bt", 2, false}, + {1, "edu.bt", 2, false}, + {1, "gov.bt", 2, false}, + {1, "net.bt", 2, false}, + {1, "org.bt", 2, false}, + {1, "bv", 1, false}, + {1, "bw", 1, false}, + {1, "co.bw", 2, false}, + {1, "org.bw", 2, false}, + {1, "by", 1, false}, + {1, "gov.by", 2, false}, + {1, "mil.by", 2, false}, + {1, "com.by", 2, false}, + {1, "of.by", 2, false}, + {1, "bz", 1, false}, + {1, "com.bz", 2, false}, + {1, "net.bz", 2, false}, + {1, "org.bz", 2, false}, + {1, "edu.bz", 2, false}, + {1, "gov.bz", 2, false}, + {1, "ca", 1, false}, + {1, "ab.ca", 2, false}, + {1, "bc.ca", 2, false}, + {1, "mb.ca", 2, false}, + {1, "nb.ca", 2, false}, + {1, "nf.ca", 2, false}, + {1, "nl.ca", 2, false}, + {1, "ns.ca", 2, false}, + {1, "nt.ca", 2, false}, + {1, "nu.ca", 2, false}, + {1, "on.ca", 2, false}, + {1, "pe.ca", 2, false}, + {1, "qc.ca", 2, false}, + {1, "sk.ca", 2, false}, + {1, "yk.ca", 2, false}, + {1, "gc.ca", 2, false}, + {1, "cat", 1, false}, + {1, "cc", 1, false}, + {1, "cd", 1, false}, + {1, "gov.cd", 2, false}, + {1, "cf", 1, false}, + {1, "cg", 1, false}, + {1, "ch", 1, false}, + {1, "ci", 1, false}, + {1, "org.ci", 2, false}, + {1, "or.ci", 2, false}, + {1, "com.ci", 2, false}, + {1, "co.ci", 2, false}, + {1, "edu.ci", 2, false}, + {1, "ed.ci", 2, false}, + {1, "ac.ci", 2, false}, + {1, "net.ci", 2, false}, + {1, "go.ci", 2, false}, + {1, "asso.ci", 2, false}, + {1, "xn--aroport-bya.ci", 2, false}, + {1, "int.ci", 2, false}, + {1, "presse.ci", 2, false}, + {1, "md.ci", 2, false}, + {1, "gouv.ci", 2, false}, + {2, "ck", 2, false}, + {3, "www.ck", 2, false}, + {1, "cl", 1, false}, + {1, "aprendemas.cl", 2, false}, + {1, "co.cl", 2, false}, + {1, "gob.cl", 2, false}, + {1, "gov.cl", 2, false}, + {1, "mil.cl", 2, false}, + {1, "cm", 1, false}, + {1, "co.cm", 2, false}, + {1, "com.cm", 2, false}, + {1, "gov.cm", 2, false}, + {1, "net.cm", 2, false}, + {1, "cn", 1, false}, + {1, "ac.cn", 2, false}, + {1, "com.cn", 2, false}, + {1, "edu.cn", 2, false}, + {1, "gov.cn", 2, false}, + {1, "net.cn", 2, false}, + {1, "org.cn", 2, false}, + {1, "mil.cn", 2, false}, + {1, "xn--55qx5d.cn", 2, false}, + {1, "xn--io0a7i.cn", 2, false}, + {1, "xn--od0alg.cn", 2, false}, + {1, "ah.cn", 2, false}, + {1, "bj.cn", 2, false}, + {1, "cq.cn", 2, false}, + {1, "fj.cn", 2, false}, + {1, "gd.cn", 2, false}, + {1, "gs.cn", 2, false}, + {1, "gz.cn", 2, false}, + {1, "gx.cn", 2, false}, + {1, "ha.cn", 2, false}, + {1, "hb.cn", 2, false}, + {1, "he.cn", 2, false}, + {1, "hi.cn", 2, false}, + {1, "hl.cn", 2, false}, + {1, "hn.cn", 2, false}, + {1, "jl.cn", 2, false}, + {1, "js.cn", 2, false}, + {1, "jx.cn", 2, false}, + {1, "ln.cn", 2, false}, + {1, "nm.cn", 2, false}, + {1, "nx.cn", 2, false}, + {1, "qh.cn", 2, false}, + {1, "sc.cn", 2, false}, + {1, "sd.cn", 2, false}, + {1, "sh.cn", 2, false}, + {1, "sn.cn", 2, false}, + {1, "sx.cn", 2, false}, + {1, "tj.cn", 2, false}, + {1, "xj.cn", 2, false}, + {1, "xz.cn", 2, false}, + {1, "yn.cn", 2, false}, + {1, "zj.cn", 2, false}, + {1, "hk.cn", 2, false}, + {1, "mo.cn", 2, false}, + {1, "tw.cn", 2, false}, + {1, "co", 1, false}, + {1, "arts.co", 2, false}, + {1, "com.co", 2, false}, + {1, "edu.co", 2, false}, + {1, "firm.co", 2, false}, + {1, "gov.co", 2, false}, + {1, "info.co", 2, false}, + {1, "int.co", 2, false}, + {1, "mil.co", 2, false}, + {1, "net.co", 2, false}, + {1, "nom.co", 2, false}, + {1, "org.co", 2, false}, + {1, "rec.co", 2, false}, + {1, "web.co", 2, false}, + {1, "com", 1, false}, + {1, "coop", 1, false}, + {1, "cr", 1, false}, + {1, "ac.cr", 2, false}, + {1, "co.cr", 2, false}, + {1, "ed.cr", 2, false}, + {1, "fi.cr", 2, false}, + {1, "go.cr", 2, false}, + {1, "or.cr", 2, false}, + {1, "sa.cr", 2, false}, + {1, "cu", 1, false}, + {1, "com.cu", 2, false}, + {1, "edu.cu", 2, false}, + {1, "org.cu", 2, false}, + {1, "net.cu", 2, false}, + {1, "gov.cu", 2, false}, + {1, "inf.cu", 2, false}, + {1, "cv", 1, false}, + {1, "cw", 1, false}, + {1, "com.cw", 2, false}, + {1, "edu.cw", 2, false}, + {1, "net.cw", 2, false}, + {1, "org.cw", 2, false}, + {1, "cx", 1, false}, + {1, "gov.cx", 2, false}, + {1, "cy", 1, false}, + {1, "ac.cy", 2, false}, + {1, "biz.cy", 2, false}, + {1, "com.cy", 2, false}, + {1, "ekloges.cy", 2, false}, + {1, "gov.cy", 2, false}, + {1, "ltd.cy", 2, false}, + {1, "name.cy", 2, false}, + {1, "net.cy", 2, false}, + {1, "org.cy", 2, false}, + {1, "parliament.cy", 2, false}, + {1, "press.cy", 2, false}, + {1, "pro.cy", 2, false}, + {1, "tm.cy", 2, false}, + {1, "cz", 1, false}, + {1, "de", 1, false}, + {1, "dj", 1, false}, + {1, "dk", 1, false}, + {1, "dm", 1, false}, + {1, "com.dm", 2, false}, + {1, "net.dm", 2, false}, + {1, "org.dm", 2, false}, + {1, "edu.dm", 2, false}, + {1, "gov.dm", 2, false}, + {1, "do", 1, false}, + {1, "art.do", 2, false}, + {1, "com.do", 2, false}, + {1, "edu.do", 2, false}, + {1, "gob.do", 2, false}, + {1, "gov.do", 2, false}, + {1, "mil.do", 2, false}, + {1, "net.do", 2, false}, + {1, "org.do", 2, false}, + {1, "sld.do", 2, false}, + {1, "web.do", 2, false}, + {1, "dz", 1, false}, + {1, "art.dz", 2, false}, + {1, "asso.dz", 2, false}, + {1, "com.dz", 2, false}, + {1, "edu.dz", 2, false}, + {1, "gov.dz", 2, false}, + {1, "org.dz", 2, false}, + {1, "net.dz", 2, false}, + {1, "pol.dz", 2, false}, + {1, "soc.dz", 2, false}, + {1, "tm.dz", 2, false}, + {1, "ec", 1, false}, + {1, "com.ec", 2, false}, + {1, "info.ec", 2, false}, + {1, "net.ec", 2, false}, + {1, "fin.ec", 2, false}, + {1, "k12.ec", 2, false}, + {1, "med.ec", 2, false}, + {1, "pro.ec", 2, false}, + {1, "org.ec", 2, false}, + {1, "edu.ec", 2, false}, + {1, "gov.ec", 2, false}, + {1, "gob.ec", 2, false}, + {1, "mil.ec", 2, false}, + {1, "edu", 1, false}, + {1, "ee", 1, false}, + {1, "edu.ee", 2, false}, + {1, "gov.ee", 2, false}, + {1, "riik.ee", 2, false}, + {1, "lib.ee", 2, false}, + {1, "med.ee", 2, false}, + {1, "com.ee", 2, false}, + {1, "pri.ee", 2, false}, + {1, "aip.ee", 2, false}, + {1, "org.ee", 2, false}, + {1, "fie.ee", 2, false}, + {1, "eg", 1, false}, + {1, "com.eg", 2, false}, + {1, "edu.eg", 2, false}, + {1, "eun.eg", 2, false}, + {1, "gov.eg", 2, false}, + {1, "mil.eg", 2, false}, + {1, "name.eg", 2, false}, + {1, "net.eg", 2, false}, + {1, "org.eg", 2, false}, + {1, "sci.eg", 2, false}, + {2, "er", 2, false}, + {1, "es", 1, false}, + {1, "com.es", 2, false}, + {1, "nom.es", 2, false}, + {1, "org.es", 2, false}, + {1, "gob.es", 2, false}, + {1, "edu.es", 2, false}, + {1, "et", 1, false}, + {1, "com.et", 2, false}, + {1, "gov.et", 2, false}, + {1, "org.et", 2, false}, + {1, "edu.et", 2, false}, + {1, "biz.et", 2, false}, + {1, "name.et", 2, false}, + {1, "info.et", 2, false}, + {1, "net.et", 2, false}, + {1, "eu", 1, false}, + {1, "fi", 1, false}, + {1, "aland.fi", 2, false}, + {1, "fj", 1, false}, + {1, "ac.fj", 2, false}, + {1, "biz.fj", 2, false}, + {1, "com.fj", 2, false}, + {1, "gov.fj", 2, false}, + {1, "info.fj", 2, false}, + {1, "mil.fj", 2, false}, + {1, "name.fj", 2, false}, + {1, "net.fj", 2, false}, + {1, "org.fj", 2, false}, + {1, "pro.fj", 2, false}, + {2, "fk", 2, false}, + {1, "com.fm", 2, false}, + {1, "edu.fm", 2, false}, + {1, "net.fm", 2, false}, + {1, "org.fm", 2, false}, + {1, "fm", 1, false}, + {1, "fo", 1, false}, + {1, "fr", 1, false}, + {1, "asso.fr", 2, false}, + {1, "com.fr", 2, false}, + {1, "gouv.fr", 2, false}, + {1, "nom.fr", 2, false}, + {1, "prd.fr", 2, false}, + {1, "tm.fr", 2, false}, + {1, "aeroport.fr", 2, false}, + {1, "avocat.fr", 2, false}, + {1, "avoues.fr", 2, false}, + {1, "cci.fr", 2, false}, + {1, "chambagri.fr", 2, false}, + {1, "chirurgiens-dentistes.fr", 2, false}, + {1, "experts-comptables.fr", 2, false}, + {1, "geometre-expert.fr", 2, false}, + {1, "greta.fr", 2, false}, + {1, "huissier-justice.fr", 2, false}, + {1, "medecin.fr", 2, false}, + {1, "notaires.fr", 2, false}, + {1, "pharmacien.fr", 2, false}, + {1, "port.fr", 2, false}, + {1, "veterinaire.fr", 2, false}, + {1, "ga", 1, false}, + {1, "gb", 1, false}, + {1, "edu.gd", 2, false}, + {1, "gov.gd", 2, false}, + {1, "gd", 1, false}, + {1, "ge", 1, false}, + {1, "com.ge", 2, false}, + {1, "edu.ge", 2, false}, + {1, "gov.ge", 2, false}, + {1, "org.ge", 2, false}, + {1, "mil.ge", 2, false}, + {1, "net.ge", 2, false}, + {1, "pvt.ge", 2, false}, + {1, "gf", 1, false}, + {1, "gg", 1, false}, + {1, "co.gg", 2, false}, + {1, "net.gg", 2, false}, + {1, "org.gg", 2, false}, + {1, "gh", 1, false}, + {1, "com.gh", 2, false}, + {1, "edu.gh", 2, false}, + {1, "gov.gh", 2, false}, + {1, "org.gh", 2, false}, + {1, "mil.gh", 2, false}, + {1, "gi", 1, false}, + {1, "com.gi", 2, false}, + {1, "ltd.gi", 2, false}, + {1, "gov.gi", 2, false}, + {1, "mod.gi", 2, false}, + {1, "edu.gi", 2, false}, + {1, "org.gi", 2, false}, + {1, "gl", 1, false}, + {1, "co.gl", 2, false}, + {1, "com.gl", 2, false}, + {1, "edu.gl", 2, false}, + {1, "net.gl", 2, false}, + {1, "org.gl", 2, false}, + {1, "gm", 1, false}, + {1, "gn", 1, false}, + {1, "ac.gn", 2, false}, + {1, "com.gn", 2, false}, + {1, "edu.gn", 2, false}, + {1, "gov.gn", 2, false}, + {1, "org.gn", 2, false}, + {1, "net.gn", 2, false}, + {1, "gov", 1, false}, + {1, "gp", 1, false}, + {1, "com.gp", 2, false}, + {1, "net.gp", 2, false}, + {1, "mobi.gp", 2, false}, + {1, "edu.gp", 2, false}, + {1, "org.gp", 2, false}, + {1, "asso.gp", 2, false}, + {1, "gq", 1, false}, + {1, "gr", 1, false}, + {1, "com.gr", 2, false}, + {1, "edu.gr", 2, false}, + {1, "net.gr", 2, false}, + {1, "org.gr", 2, false}, + {1, "gov.gr", 2, false}, + {1, "gs", 1, false}, + {1, "gt", 1, false}, + {1, "com.gt", 2, false}, + {1, "edu.gt", 2, false}, + {1, "gob.gt", 2, false}, + {1, "ind.gt", 2, false}, + {1, "mil.gt", 2, false}, + {1, "net.gt", 2, false}, + {1, "org.gt", 2, false}, + {1, "gu", 1, false}, + {1, "com.gu", 2, false}, + {1, "edu.gu", 2, false}, + {1, "gov.gu", 2, false}, + {1, "guam.gu", 2, false}, + {1, "info.gu", 2, false}, + {1, "net.gu", 2, false}, + {1, "org.gu", 2, false}, + {1, "web.gu", 2, false}, + {1, "gw", 1, false}, + {1, "gy", 1, false}, + {1, "co.gy", 2, false}, + {1, "com.gy", 2, false}, + {1, "edu.gy", 2, false}, + {1, "gov.gy", 2, false}, + {1, "net.gy", 2, false}, + {1, "org.gy", 2, false}, + {1, "hk", 1, false}, + {1, "com.hk", 2, false}, + {1, "edu.hk", 2, false}, + {1, "gov.hk", 2, false}, + {1, "idv.hk", 2, false}, + {1, "net.hk", 2, false}, + {1, "org.hk", 2, false}, + {1, "xn--55qx5d.hk", 2, false}, + {1, "xn--wcvs22d.hk", 2, false}, + {1, "xn--lcvr32d.hk", 2, false}, + {1, "xn--mxtq1m.hk", 2, false}, + {1, "xn--gmqw5a.hk", 2, false}, + {1, "xn--ciqpn.hk", 2, false}, + {1, "xn--gmq050i.hk", 2, false}, + {1, "xn--zf0avx.hk", 2, false}, + {1, "xn--io0a7i.hk", 2, false}, + {1, "xn--mk0axi.hk", 2, false}, + {1, "xn--od0alg.hk", 2, false}, + {1, "xn--od0aq3b.hk", 2, false}, + {1, "xn--tn0ag.hk", 2, false}, + {1, "xn--uc0atv.hk", 2, false}, + {1, "xn--uc0ay4a.hk", 2, false}, + {1, "hm", 1, false}, + {1, "hn", 1, false}, + {1, "com.hn", 2, false}, + {1, "edu.hn", 2, false}, + {1, "org.hn", 2, false}, + {1, "net.hn", 2, false}, + {1, "mil.hn", 2, false}, + {1, "gob.hn", 2, false}, + {1, "hr", 1, false}, + {1, "iz.hr", 2, false}, + {1, "from.hr", 2, false}, + {1, "name.hr", 2, false}, + {1, "com.hr", 2, false}, + {1, "ht", 1, false}, + {1, "com.ht", 2, false}, + {1, "shop.ht", 2, false}, + {1, "firm.ht", 2, false}, + {1, "info.ht", 2, false}, + {1, "adult.ht", 2, false}, + {1, "net.ht", 2, false}, + {1, "pro.ht", 2, false}, + {1, "org.ht", 2, false}, + {1, "med.ht", 2, false}, + {1, "art.ht", 2, false}, + {1, "coop.ht", 2, false}, + {1, "pol.ht", 2, false}, + {1, "asso.ht", 2, false}, + {1, "edu.ht", 2, false}, + {1, "rel.ht", 2, false}, + {1, "gouv.ht", 2, false}, + {1, "perso.ht", 2, false}, + {1, "hu", 1, false}, + {1, "co.hu", 2, false}, + {1, "info.hu", 2, false}, + {1, "org.hu", 2, false}, + {1, "priv.hu", 2, false}, + {1, "sport.hu", 2, false}, + {1, "tm.hu", 2, false}, + {1, "2000.hu", 2, false}, + {1, "agrar.hu", 2, false}, + {1, "bolt.hu", 2, false}, + {1, "casino.hu", 2, false}, + {1, "city.hu", 2, false}, + {1, "erotica.hu", 2, false}, + {1, "erotika.hu", 2, false}, + {1, "film.hu", 2, false}, + {1, "forum.hu", 2, false}, + {1, "games.hu", 2, false}, + {1, "hotel.hu", 2, false}, + {1, "ingatlan.hu", 2, false}, + {1, "jogasz.hu", 2, false}, + {1, "konyvelo.hu", 2, false}, + {1, "lakas.hu", 2, false}, + {1, "media.hu", 2, false}, + {1, "news.hu", 2, false}, + {1, "reklam.hu", 2, false}, + {1, "sex.hu", 2, false}, + {1, "shop.hu", 2, false}, + {1, "suli.hu", 2, false}, + {1, "szex.hu", 2, false}, + {1, "tozsde.hu", 2, false}, + {1, "utazas.hu", 2, false}, + {1, "video.hu", 2, false}, + {1, "id", 1, false}, + {1, "ac.id", 2, false}, + {1, "biz.id", 2, false}, + {1, "co.id", 2, false}, + {1, "desa.id", 2, false}, + {1, "go.id", 2, false}, + {1, "mil.id", 2, false}, + {1, "my.id", 2, false}, + {1, "net.id", 2, false}, + {1, "or.id", 2, false}, + {1, "ponpes.id", 2, false}, + {1, "sch.id", 2, false}, + {1, "web.id", 2, false}, + {1, "ie", 1, false}, + {1, "gov.ie", 2, false}, + {1, "il", 1, false}, + {1, "ac.il", 2, false}, + {1, "co.il", 2, false}, + {1, "gov.il", 2, false}, + {1, "idf.il", 2, false}, + {1, "k12.il", 2, false}, + {1, "muni.il", 2, false}, + {1, "net.il", 2, false}, + {1, "org.il", 2, false}, + {1, "im", 1, false}, + {1, "ac.im", 2, false}, + {1, "co.im", 2, false}, + {1, "com.im", 2, false}, + {1, "ltd.co.im", 3, false}, + {1, "net.im", 2, false}, + {1, "org.im", 2, false}, + {1, "plc.co.im", 3, false}, + {1, "tt.im", 2, false}, + {1, "tv.im", 2, false}, + {1, "in", 1, false}, + {1, "co.in", 2, false}, + {1, "firm.in", 2, false}, + {1, "net.in", 2, false}, + {1, "org.in", 2, false}, + {1, "gen.in", 2, false}, + {1, "ind.in", 2, false}, + {1, "nic.in", 2, false}, + {1, "ac.in", 2, false}, + {1, "edu.in", 2, false}, + {1, "res.in", 2, false}, + {1, "gov.in", 2, false}, + {1, "mil.in", 2, false}, + {1, "info", 1, false}, + {1, "int", 1, false}, + {1, "eu.int", 2, false}, + {1, "io", 1, false}, + {1, "com.io", 2, false}, + {1, "iq", 1, false}, + {1, "gov.iq", 2, false}, + {1, "edu.iq", 2, false}, + {1, "mil.iq", 2, false}, + {1, "com.iq", 2, false}, + {1, "org.iq", 2, false}, + {1, "net.iq", 2, false}, + {1, "ir", 1, false}, + {1, "ac.ir", 2, false}, + {1, "co.ir", 2, false}, + {1, "gov.ir", 2, false}, + {1, "id.ir", 2, false}, + {1, "net.ir", 2, false}, + {1, "org.ir", 2, false}, + {1, "sch.ir", 2, false}, + {1, "xn--mgba3a4f16a.ir", 2, false}, + {1, "xn--mgba3a4fra.ir", 2, false}, + {1, "is", 1, false}, + {1, "net.is", 2, false}, + {1, "com.is", 2, false}, + {1, "edu.is", 2, false}, + {1, "gov.is", 2, false}, + {1, "org.is", 2, false}, + {1, "int.is", 2, false}, + {1, "it", 1, false}, + {1, "gov.it", 2, false}, + {1, "edu.it", 2, false}, + {1, "abr.it", 2, false}, + {1, "abruzzo.it", 2, false}, + {1, "aosta-valley.it", 2, false}, + {1, "aostavalley.it", 2, false}, + {1, "bas.it", 2, false}, + {1, "basilicata.it", 2, false}, + {1, "cal.it", 2, false}, + {1, "calabria.it", 2, false}, + {1, "cam.it", 2, false}, + {1, "campania.it", 2, false}, + {1, "emilia-romagna.it", 2, false}, + {1, "emiliaromagna.it", 2, false}, + {1, "emr.it", 2, false}, + {1, "friuli-v-giulia.it", 2, false}, + {1, "friuli-ve-giulia.it", 2, false}, + {1, "friuli-vegiulia.it", 2, false}, + {1, "friuli-venezia-giulia.it", 2, false}, + {1, "friuli-veneziagiulia.it", 2, false}, + {1, "friuli-vgiulia.it", 2, false}, + {1, "friuliv-giulia.it", 2, false}, + {1, "friulive-giulia.it", 2, false}, + {1, "friulivegiulia.it", 2, false}, + {1, "friulivenezia-giulia.it", 2, false}, + {1, "friuliveneziagiulia.it", 2, false}, + {1, "friulivgiulia.it", 2, false}, + {1, "fvg.it", 2, false}, + {1, "laz.it", 2, false}, + {1, "lazio.it", 2, false}, + {1, "lig.it", 2, false}, + {1, "liguria.it", 2, false}, + {1, "lom.it", 2, false}, + {1, "lombardia.it", 2, false}, + {1, "lombardy.it", 2, false}, + {1, "lucania.it", 2, false}, + {1, "mar.it", 2, false}, + {1, "marche.it", 2, false}, + {1, "mol.it", 2, false}, + {1, "molise.it", 2, false}, + {1, "piedmont.it", 2, false}, + {1, "piemonte.it", 2, false}, + {1, "pmn.it", 2, false}, + {1, "pug.it", 2, false}, + {1, "puglia.it", 2, false}, + {1, "sar.it", 2, false}, + {1, "sardegna.it", 2, false}, + {1, "sardinia.it", 2, false}, + {1, "sic.it", 2, false}, + {1, "sicilia.it", 2, false}, + {1, "sicily.it", 2, false}, + {1, "taa.it", 2, false}, + {1, "tos.it", 2, false}, + {1, "toscana.it", 2, false}, + {1, "trentin-sud-tirol.it", 2, false}, + {1, "xn--trentin-sd-tirol-rzb.it", 2, false}, + {1, "trentin-sudtirol.it", 2, false}, + {1, "xn--trentin-sdtirol-7vb.it", 2, false}, + {1, "trentin-sued-tirol.it", 2, false}, + {1, "trentin-suedtirol.it", 2, false}, + {1, "trentino-a-adige.it", 2, false}, + {1, "trentino-aadige.it", 2, false}, + {1, "trentino-alto-adige.it", 2, false}, + {1, "trentino-altoadige.it", 2, false}, + {1, "trentino-s-tirol.it", 2, false}, + {1, "trentino-stirol.it", 2, false}, + {1, "trentino-sud-tirol.it", 2, false}, + {1, "xn--trentino-sd-tirol-c3b.it", 2, false}, + {1, "trentino-sudtirol.it", 2, false}, + {1, "xn--trentino-sdtirol-szb.it", 2, false}, + {1, "trentino-sued-tirol.it", 2, false}, + {1, "trentino-suedtirol.it", 2, false}, + {1, "trentino.it", 2, false}, + {1, "trentinoa-adige.it", 2, false}, + {1, "trentinoaadige.it", 2, false}, + {1, "trentinoalto-adige.it", 2, false}, + {1, "trentinoaltoadige.it", 2, false}, + {1, "trentinos-tirol.it", 2, false}, + {1, "trentinostirol.it", 2, false}, + {1, "trentinosud-tirol.it", 2, false}, + {1, "xn--trentinosd-tirol-rzb.it", 2, false}, + {1, "trentinosudtirol.it", 2, false}, + {1, "xn--trentinosdtirol-7vb.it", 2, false}, + {1, "trentinosued-tirol.it", 2, false}, + {1, "trentinosuedtirol.it", 2, false}, + {1, "trentinsud-tirol.it", 2, false}, + {1, "xn--trentinsd-tirol-6vb.it", 2, false}, + {1, "trentinsudtirol.it", 2, false}, + {1, "xn--trentinsdtirol-nsb.it", 2, false}, + {1, "trentinsued-tirol.it", 2, false}, + {1, "trentinsuedtirol.it", 2, false}, + {1, "tuscany.it", 2, false}, + {1, "umb.it", 2, false}, + {1, "umbria.it", 2, false}, + {1, "val-d-aosta.it", 2, false}, + {1, "val-daosta.it", 2, false}, + {1, "vald-aosta.it", 2, false}, + {1, "valdaosta.it", 2, false}, + {1, "valle-aosta.it", 2, false}, + {1, "valle-d-aosta.it", 2, false}, + {1, "valle-daosta.it", 2, false}, + {1, "valleaosta.it", 2, false}, + {1, "valled-aosta.it", 2, false}, + {1, "valledaosta.it", 2, false}, + {1, "vallee-aoste.it", 2, false}, + {1, "xn--valle-aoste-ebb.it", 2, false}, + {1, "vallee-d-aoste.it", 2, false}, + {1, "xn--valle-d-aoste-ehb.it", 2, false}, + {1, "valleeaoste.it", 2, false}, + {1, "xn--valleaoste-e7a.it", 2, false}, + {1, "valleedaoste.it", 2, false}, + {1, "xn--valledaoste-ebb.it", 2, false}, + {1, "vao.it", 2, false}, + {1, "vda.it", 2, false}, + {1, "ven.it", 2, false}, + {1, "veneto.it", 2, false}, + {1, "ag.it", 2, false}, + {1, "agrigento.it", 2, false}, + {1, "al.it", 2, false}, + {1, "alessandria.it", 2, false}, + {1, "alto-adige.it", 2, false}, + {1, "altoadige.it", 2, false}, + {1, "an.it", 2, false}, + {1, "ancona.it", 2, false}, + {1, "andria-barletta-trani.it", 2, false}, + {1, "andria-trani-barletta.it", 2, false}, + {1, "andriabarlettatrani.it", 2, false}, + {1, "andriatranibarletta.it", 2, false}, + {1, "ao.it", 2, false}, + {1, "aosta.it", 2, false}, + {1, "aoste.it", 2, false}, + {1, "ap.it", 2, false}, + {1, "aq.it", 2, false}, + {1, "aquila.it", 2, false}, + {1, "ar.it", 2, false}, + {1, "arezzo.it", 2, false}, + {1, "ascoli-piceno.it", 2, false}, + {1, "ascolipiceno.it", 2, false}, + {1, "asti.it", 2, false}, + {1, "at.it", 2, false}, + {1, "av.it", 2, false}, + {1, "avellino.it", 2, false}, + {1, "ba.it", 2, false}, + {1, "balsan-sudtirol.it", 2, false}, + {1, "xn--balsan-sdtirol-nsb.it", 2, false}, + {1, "balsan-suedtirol.it", 2, false}, + {1, "balsan.it", 2, false}, + {1, "bari.it", 2, false}, + {1, "barletta-trani-andria.it", 2, false}, + {1, "barlettatraniandria.it", 2, false}, + {1, "belluno.it", 2, false}, + {1, "benevento.it", 2, false}, + {1, "bergamo.it", 2, false}, + {1, "bg.it", 2, false}, + {1, "bi.it", 2, false}, + {1, "biella.it", 2, false}, + {1, "bl.it", 2, false}, + {1, "bn.it", 2, false}, + {1, "bo.it", 2, false}, + {1, "bologna.it", 2, false}, + {1, "bolzano-altoadige.it", 2, false}, + {1, "bolzano.it", 2, false}, + {1, "bozen-sudtirol.it", 2, false}, + {1, "xn--bozen-sdtirol-2ob.it", 2, false}, + {1, "bozen-suedtirol.it", 2, false}, + {1, "bozen.it", 2, false}, + {1, "br.it", 2, false}, + {1, "brescia.it", 2, false}, + {1, "brindisi.it", 2, false}, + {1, "bs.it", 2, false}, + {1, "bt.it", 2, false}, + {1, "bulsan-sudtirol.it", 2, false}, + {1, "xn--bulsan-sdtirol-nsb.it", 2, false}, + {1, "bulsan-suedtirol.it", 2, false}, + {1, "bulsan.it", 2, false}, + {1, "bz.it", 2, false}, + {1, "ca.it", 2, false}, + {1, "cagliari.it", 2, false}, + {1, "caltanissetta.it", 2, false}, + {1, "campidano-medio.it", 2, false}, + {1, "campidanomedio.it", 2, false}, + {1, "campobasso.it", 2, false}, + {1, "carbonia-iglesias.it", 2, false}, + {1, "carboniaiglesias.it", 2, false}, + {1, "carrara-massa.it", 2, false}, + {1, "carraramassa.it", 2, false}, + {1, "caserta.it", 2, false}, + {1, "catania.it", 2, false}, + {1, "catanzaro.it", 2, false}, + {1, "cb.it", 2, false}, + {1, "ce.it", 2, false}, + {1, "cesena-forli.it", 2, false}, + {1, "xn--cesena-forl-mcb.it", 2, false}, + {1, "cesenaforli.it", 2, false}, + {1, "xn--cesenaforl-i8a.it", 2, false}, + {1, "ch.it", 2, false}, + {1, "chieti.it", 2, false}, + {1, "ci.it", 2, false}, + {1, "cl.it", 2, false}, + {1, "cn.it", 2, false}, + {1, "co.it", 2, false}, + {1, "como.it", 2, false}, + {1, "cosenza.it", 2, false}, + {1, "cr.it", 2, false}, + {1, "cremona.it", 2, false}, + {1, "crotone.it", 2, false}, + {1, "cs.it", 2, false}, + {1, "ct.it", 2, false}, + {1, "cuneo.it", 2, false}, + {1, "cz.it", 2, false}, + {1, "dell-ogliastra.it", 2, false}, + {1, "dellogliastra.it", 2, false}, + {1, "en.it", 2, false}, + {1, "enna.it", 2, false}, + {1, "fc.it", 2, false}, + {1, "fe.it", 2, false}, + {1, "fermo.it", 2, false}, + {1, "ferrara.it", 2, false}, + {1, "fg.it", 2, false}, + {1, "fi.it", 2, false}, + {1, "firenze.it", 2, false}, + {1, "florence.it", 2, false}, + {1, "fm.it", 2, false}, + {1, "foggia.it", 2, false}, + {1, "forli-cesena.it", 2, false}, + {1, "xn--forl-cesena-fcb.it", 2, false}, + {1, "forlicesena.it", 2, false}, + {1, "xn--forlcesena-c8a.it", 2, false}, + {1, "fr.it", 2, false}, + {1, "frosinone.it", 2, false}, + {1, "ge.it", 2, false}, + {1, "genoa.it", 2, false}, + {1, "genova.it", 2, false}, + {1, "go.it", 2, false}, + {1, "gorizia.it", 2, false}, + {1, "gr.it", 2, false}, + {1, "grosseto.it", 2, false}, + {1, "iglesias-carbonia.it", 2, false}, + {1, "iglesiascarbonia.it", 2, false}, + {1, "im.it", 2, false}, + {1, "imperia.it", 2, false}, + {1, "is.it", 2, false}, + {1, "isernia.it", 2, false}, + {1, "kr.it", 2, false}, + {1, "la-spezia.it", 2, false}, + {1, "laquila.it", 2, false}, + {1, "laspezia.it", 2, false}, + {1, "latina.it", 2, false}, + {1, "lc.it", 2, false}, + {1, "le.it", 2, false}, + {1, "lecce.it", 2, false}, + {1, "lecco.it", 2, false}, + {1, "li.it", 2, false}, + {1, "livorno.it", 2, false}, + {1, "lo.it", 2, false}, + {1, "lodi.it", 2, false}, + {1, "lt.it", 2, false}, + {1, "lu.it", 2, false}, + {1, "lucca.it", 2, false}, + {1, "macerata.it", 2, false}, + {1, "mantova.it", 2, false}, + {1, "massa-carrara.it", 2, false}, + {1, "massacarrara.it", 2, false}, + {1, "matera.it", 2, false}, + {1, "mb.it", 2, false}, + {1, "mc.it", 2, false}, + {1, "me.it", 2, false}, + {1, "medio-campidano.it", 2, false}, + {1, "mediocampidano.it", 2, false}, + {1, "messina.it", 2, false}, + {1, "mi.it", 2, false}, + {1, "milan.it", 2, false}, + {1, "milano.it", 2, false}, + {1, "mn.it", 2, false}, + {1, "mo.it", 2, false}, + {1, "modena.it", 2, false}, + {1, "monza-brianza.it", 2, false}, + {1, "monza-e-della-brianza.it", 2, false}, + {1, "monza.it", 2, false}, + {1, "monzabrianza.it", 2, false}, + {1, "monzaebrianza.it", 2, false}, + {1, "monzaedellabrianza.it", 2, false}, + {1, "ms.it", 2, false}, + {1, "mt.it", 2, false}, + {1, "na.it", 2, false}, + {1, "naples.it", 2, false}, + {1, "napoli.it", 2, false}, + {1, "no.it", 2, false}, + {1, "novara.it", 2, false}, + {1, "nu.it", 2, false}, + {1, "nuoro.it", 2, false}, + {1, "og.it", 2, false}, + {1, "ogliastra.it", 2, false}, + {1, "olbia-tempio.it", 2, false}, + {1, "olbiatempio.it", 2, false}, + {1, "or.it", 2, false}, + {1, "oristano.it", 2, false}, + {1, "ot.it", 2, false}, + {1, "pa.it", 2, false}, + {1, "padova.it", 2, false}, + {1, "padua.it", 2, false}, + {1, "palermo.it", 2, false}, + {1, "parma.it", 2, false}, + {1, "pavia.it", 2, false}, + {1, "pc.it", 2, false}, + {1, "pd.it", 2, false}, + {1, "pe.it", 2, false}, + {1, "perugia.it", 2, false}, + {1, "pesaro-urbino.it", 2, false}, + {1, "pesarourbino.it", 2, false}, + {1, "pescara.it", 2, false}, + {1, "pg.it", 2, false}, + {1, "pi.it", 2, false}, + {1, "piacenza.it", 2, false}, + {1, "pisa.it", 2, false}, + {1, "pistoia.it", 2, false}, + {1, "pn.it", 2, false}, + {1, "po.it", 2, false}, + {1, "pordenone.it", 2, false}, + {1, "potenza.it", 2, false}, + {1, "pr.it", 2, false}, + {1, "prato.it", 2, false}, + {1, "pt.it", 2, false}, + {1, "pu.it", 2, false}, + {1, "pv.it", 2, false}, + {1, "pz.it", 2, false}, + {1, "ra.it", 2, false}, + {1, "ragusa.it", 2, false}, + {1, "ravenna.it", 2, false}, + {1, "rc.it", 2, false}, + {1, "re.it", 2, false}, + {1, "reggio-calabria.it", 2, false}, + {1, "reggio-emilia.it", 2, false}, + {1, "reggiocalabria.it", 2, false}, + {1, "reggioemilia.it", 2, false}, + {1, "rg.it", 2, false}, + {1, "ri.it", 2, false}, + {1, "rieti.it", 2, false}, + {1, "rimini.it", 2, false}, + {1, "rm.it", 2, false}, + {1, "rn.it", 2, false}, + {1, "ro.it", 2, false}, + {1, "roma.it", 2, false}, + {1, "rome.it", 2, false}, + {1, "rovigo.it", 2, false}, + {1, "sa.it", 2, false}, + {1, "salerno.it", 2, false}, + {1, "sassari.it", 2, false}, + {1, "savona.it", 2, false}, + {1, "si.it", 2, false}, + {1, "siena.it", 2, false}, + {1, "siracusa.it", 2, false}, + {1, "so.it", 2, false}, + {1, "sondrio.it", 2, false}, + {1, "sp.it", 2, false}, + {1, "sr.it", 2, false}, + {1, "ss.it", 2, false}, + {1, "suedtirol.it", 2, false}, + {1, "xn--sdtirol-n2a.it", 2, false}, + {1, "sv.it", 2, false}, + {1, "ta.it", 2, false}, + {1, "taranto.it", 2, false}, + {1, "te.it", 2, false}, + {1, "tempio-olbia.it", 2, false}, + {1, "tempioolbia.it", 2, false}, + {1, "teramo.it", 2, false}, + {1, "terni.it", 2, false}, + {1, "tn.it", 2, false}, + {1, "to.it", 2, false}, + {1, "torino.it", 2, false}, + {1, "tp.it", 2, false}, + {1, "tr.it", 2, false}, + {1, "trani-andria-barletta.it", 2, false}, + {1, "trani-barletta-andria.it", 2, false}, + {1, "traniandriabarletta.it", 2, false}, + {1, "tranibarlettaandria.it", 2, false}, + {1, "trapani.it", 2, false}, + {1, "trento.it", 2, false}, + {1, "treviso.it", 2, false}, + {1, "trieste.it", 2, false}, + {1, "ts.it", 2, false}, + {1, "turin.it", 2, false}, + {1, "tv.it", 2, false}, + {1, "ud.it", 2, false}, + {1, "udine.it", 2, false}, + {1, "urbino-pesaro.it", 2, false}, + {1, "urbinopesaro.it", 2, false}, + {1, "va.it", 2, false}, + {1, "varese.it", 2, false}, + {1, "vb.it", 2, false}, + {1, "vc.it", 2, false}, + {1, "ve.it", 2, false}, + {1, "venezia.it", 2, false}, + {1, "venice.it", 2, false}, + {1, "verbania.it", 2, false}, + {1, "vercelli.it", 2, false}, + {1, "verona.it", 2, false}, + {1, "vi.it", 2, false}, + {1, "vibo-valentia.it", 2, false}, + {1, "vibovalentia.it", 2, false}, + {1, "vicenza.it", 2, false}, + {1, "viterbo.it", 2, false}, + {1, "vr.it", 2, false}, + {1, "vs.it", 2, false}, + {1, "vt.it", 2, false}, + {1, "vv.it", 2, false}, + {1, "je", 1, false}, + {1, "co.je", 2, false}, + {1, "net.je", 2, false}, + {1, "org.je", 2, false}, + {2, "jm", 2, false}, + {1, "jo", 1, false}, + {1, "com.jo", 2, false}, + {1, "org.jo", 2, false}, + {1, "net.jo", 2, false}, + {1, "edu.jo", 2, false}, + {1, "sch.jo", 2, false}, + {1, "gov.jo", 2, false}, + {1, "mil.jo", 2, false}, + {1, "name.jo", 2, false}, + {1, "jobs", 1, false}, + {1, "jp", 1, false}, + {1, "ac.jp", 2, false}, + {1, "ad.jp", 2, false}, + {1, "co.jp", 2, false}, + {1, "ed.jp", 2, false}, + {1, "go.jp", 2, false}, + {1, "gr.jp", 2, false}, + {1, "lg.jp", 2, false}, + {1, "ne.jp", 2, false}, + {1, "or.jp", 2, false}, + {1, "aichi.jp", 2, false}, + {1, "akita.jp", 2, false}, + {1, "aomori.jp", 2, false}, + {1, "chiba.jp", 2, false}, + {1, "ehime.jp", 2, false}, + {1, "fukui.jp", 2, false}, + {1, "fukuoka.jp", 2, false}, + {1, "fukushima.jp", 2, false}, + {1, "gifu.jp", 2, false}, + {1, "gunma.jp", 2, false}, + {1, "hiroshima.jp", 2, false}, + {1, "hokkaido.jp", 2, false}, + {1, "hyogo.jp", 2, false}, + {1, "ibaraki.jp", 2, false}, + {1, "ishikawa.jp", 2, false}, + {1, "iwate.jp", 2, false}, + {1, "kagawa.jp", 2, false}, + {1, "kagoshima.jp", 2, false}, + {1, "kanagawa.jp", 2, false}, + {1, "kochi.jp", 2, false}, + {1, "kumamoto.jp", 2, false}, + {1, "kyoto.jp", 2, false}, + {1, "mie.jp", 2, false}, + {1, "miyagi.jp", 2, false}, + {1, "miyazaki.jp", 2, false}, + {1, "nagano.jp", 2, false}, + {1, "nagasaki.jp", 2, false}, + {1, "nara.jp", 2, false}, + {1, "niigata.jp", 2, false}, + {1, "oita.jp", 2, false}, + {1, "okayama.jp", 2, false}, + {1, "okinawa.jp", 2, false}, + {1, "osaka.jp", 2, false}, + {1, "saga.jp", 2, false}, + {1, "saitama.jp", 2, false}, + {1, "shiga.jp", 2, false}, + {1, "shimane.jp", 2, false}, + {1, "shizuoka.jp", 2, false}, + {1, "tochigi.jp", 2, false}, + {1, "tokushima.jp", 2, false}, + {1, "tokyo.jp", 2, false}, + {1, "tottori.jp", 2, false}, + {1, "toyama.jp", 2, false}, + {1, "wakayama.jp", 2, false}, + {1, "yamagata.jp", 2, false}, + {1, "yamaguchi.jp", 2, false}, + {1, "yamanashi.jp", 2, false}, + {1, "xn--4pvxs.jp", 2, false}, + {1, "xn--vgu402c.jp", 2, false}, + {1, "xn--c3s14m.jp", 2, false}, + {1, "xn--f6qx53a.jp", 2, false}, + {1, "xn--8pvr4u.jp", 2, false}, + {1, "xn--uist22h.jp", 2, false}, + {1, "xn--djrs72d6uy.jp", 2, false}, + {1, "xn--mkru45i.jp", 2, false}, + {1, "xn--0trq7p7nn.jp", 2, false}, + {1, "xn--8ltr62k.jp", 2, false}, + {1, "xn--2m4a15e.jp", 2, false}, + {1, "xn--efvn9s.jp", 2, false}, + {1, "xn--32vp30h.jp", 2, false}, + {1, "xn--4it797k.jp", 2, false}, + {1, "xn--1lqs71d.jp", 2, false}, + {1, "xn--5rtp49c.jp", 2, false}, + {1, "xn--5js045d.jp", 2, false}, + {1, "xn--ehqz56n.jp", 2, false}, + {1, "xn--1lqs03n.jp", 2, false}, + {1, "xn--qqqt11m.jp", 2, false}, + {1, "xn--kbrq7o.jp", 2, false}, + {1, "xn--pssu33l.jp", 2, false}, + {1, "xn--ntsq17g.jp", 2, false}, + {1, "xn--uisz3g.jp", 2, false}, + {1, "xn--6btw5a.jp", 2, false}, + {1, "xn--1ctwo.jp", 2, false}, + {1, "xn--6orx2r.jp", 2, false}, + {1, "xn--rht61e.jp", 2, false}, + {1, "xn--rht27z.jp", 2, false}, + {1, "xn--djty4k.jp", 2, false}, + {1, "xn--nit225k.jp", 2, false}, + {1, "xn--rht3d.jp", 2, false}, + {1, "xn--klty5x.jp", 2, false}, + {1, "xn--kltx9a.jp", 2, false}, + {1, "xn--kltp7d.jp", 2, false}, + {1, "xn--uuwu58a.jp", 2, false}, + {1, "xn--zbx025d.jp", 2, false}, + {1, "xn--ntso0iqx3a.jp", 2, false}, + {1, "xn--elqq16h.jp", 2, false}, + {1, "xn--4it168d.jp", 2, false}, + {1, "xn--klt787d.jp", 2, false}, + {1, "xn--rny31h.jp", 2, false}, + {1, "xn--7t0a264c.jp", 2, false}, + {1, "xn--5rtq34k.jp", 2, false}, + {1, "xn--k7yn95e.jp", 2, false}, + {1, "xn--tor131o.jp", 2, false}, + {1, "xn--d5qv7z876c.jp", 2, false}, + {2, "kawasaki.jp", 3, false}, + {2, "kitakyushu.jp", 3, false}, + {2, "kobe.jp", 3, false}, + {2, "nagoya.jp", 3, false}, + {2, "sapporo.jp", 3, false}, + {2, "sendai.jp", 3, false}, + {2, "yokohama.jp", 3, false}, + {3, "city.kawasaki.jp", 3, false}, + {3, "city.kitakyushu.jp", 3, false}, + {3, "city.kobe.jp", 3, false}, + {3, "city.nagoya.jp", 3, false}, + {3, "city.sapporo.jp", 3, false}, + {3, "city.sendai.jp", 3, false}, + {3, "city.yokohama.jp", 3, false}, + {1, "aisai.aichi.jp", 3, false}, + {1, "ama.aichi.jp", 3, false}, + {1, "anjo.aichi.jp", 3, false}, + {1, "asuke.aichi.jp", 3, false}, + {1, "chiryu.aichi.jp", 3, false}, + {1, "chita.aichi.jp", 3, false}, + {1, "fuso.aichi.jp", 3, false}, + {1, "gamagori.aichi.jp", 3, false}, + {1, "handa.aichi.jp", 3, false}, + {1, "hazu.aichi.jp", 3, false}, + {1, "hekinan.aichi.jp", 3, false}, + {1, "higashiura.aichi.jp", 3, false}, + {1, "ichinomiya.aichi.jp", 3, false}, + {1, "inazawa.aichi.jp", 3, false}, + {1, "inuyama.aichi.jp", 3, false}, + {1, "isshiki.aichi.jp", 3, false}, + {1, "iwakura.aichi.jp", 3, false}, + {1, "kanie.aichi.jp", 3, false}, + {1, "kariya.aichi.jp", 3, false}, + {1, "kasugai.aichi.jp", 3, false}, + {1, "kira.aichi.jp", 3, false}, + {1, "kiyosu.aichi.jp", 3, false}, + {1, "komaki.aichi.jp", 3, false}, + {1, "konan.aichi.jp", 3, false}, + {1, "kota.aichi.jp", 3, false}, + {1, "mihama.aichi.jp", 3, false}, + {1, "miyoshi.aichi.jp", 3, false}, + {1, "nishio.aichi.jp", 3, false}, + {1, "nisshin.aichi.jp", 3, false}, + {1, "obu.aichi.jp", 3, false}, + {1, "oguchi.aichi.jp", 3, false}, + {1, "oharu.aichi.jp", 3, false}, + {1, "okazaki.aichi.jp", 3, false}, + {1, "owariasahi.aichi.jp", 3, false}, + {1, "seto.aichi.jp", 3, false}, + {1, "shikatsu.aichi.jp", 3, false}, + {1, "shinshiro.aichi.jp", 3, false}, + {1, "shitara.aichi.jp", 3, false}, + {1, "tahara.aichi.jp", 3, false}, + {1, "takahama.aichi.jp", 3, false}, + {1, "tobishima.aichi.jp", 3, false}, + {1, "toei.aichi.jp", 3, false}, + {1, "togo.aichi.jp", 3, false}, + {1, "tokai.aichi.jp", 3, false}, + {1, "tokoname.aichi.jp", 3, false}, + {1, "toyoake.aichi.jp", 3, false}, + {1, "toyohashi.aichi.jp", 3, false}, + {1, "toyokawa.aichi.jp", 3, false}, + {1, "toyone.aichi.jp", 3, false}, + {1, "toyota.aichi.jp", 3, false}, + {1, "tsushima.aichi.jp", 3, false}, + {1, "yatomi.aichi.jp", 3, false}, + {1, "akita.akita.jp", 3, false}, + {1, "daisen.akita.jp", 3, false}, + {1, "fujisato.akita.jp", 3, false}, + {1, "gojome.akita.jp", 3, false}, + {1, "hachirogata.akita.jp", 3, false}, + {1, "happou.akita.jp", 3, false}, + {1, "higashinaruse.akita.jp", 3, false}, + {1, "honjo.akita.jp", 3, false}, + {1, "honjyo.akita.jp", 3, false}, + {1, "ikawa.akita.jp", 3, false}, + {1, "kamikoani.akita.jp", 3, false}, + {1, "kamioka.akita.jp", 3, false}, + {1, "katagami.akita.jp", 3, false}, + {1, "kazuno.akita.jp", 3, false}, + {1, "kitaakita.akita.jp", 3, false}, + {1, "kosaka.akita.jp", 3, false}, + {1, "kyowa.akita.jp", 3, false}, + {1, "misato.akita.jp", 3, false}, + {1, "mitane.akita.jp", 3, false}, + {1, "moriyoshi.akita.jp", 3, false}, + {1, "nikaho.akita.jp", 3, false}, + {1, "noshiro.akita.jp", 3, false}, + {1, "odate.akita.jp", 3, false}, + {1, "oga.akita.jp", 3, false}, + {1, "ogata.akita.jp", 3, false}, + {1, "semboku.akita.jp", 3, false}, + {1, "yokote.akita.jp", 3, false}, + {1, "yurihonjo.akita.jp", 3, false}, + {1, "aomori.aomori.jp", 3, false}, + {1, "gonohe.aomori.jp", 3, false}, + {1, "hachinohe.aomori.jp", 3, false}, + {1, "hashikami.aomori.jp", 3, false}, + {1, "hiranai.aomori.jp", 3, false}, + {1, "hirosaki.aomori.jp", 3, false}, + {1, "itayanagi.aomori.jp", 3, false}, + {1, "kuroishi.aomori.jp", 3, false}, + {1, "misawa.aomori.jp", 3, false}, + {1, "mutsu.aomori.jp", 3, false}, + {1, "nakadomari.aomori.jp", 3, false}, + {1, "noheji.aomori.jp", 3, false}, + {1, "oirase.aomori.jp", 3, false}, + {1, "owani.aomori.jp", 3, false}, + {1, "rokunohe.aomori.jp", 3, false}, + {1, "sannohe.aomori.jp", 3, false}, + {1, "shichinohe.aomori.jp", 3, false}, + {1, "shingo.aomori.jp", 3, false}, + {1, "takko.aomori.jp", 3, false}, + {1, "towada.aomori.jp", 3, false}, + {1, "tsugaru.aomori.jp", 3, false}, + {1, "tsuruta.aomori.jp", 3, false}, + {1, "abiko.chiba.jp", 3, false}, + {1, "asahi.chiba.jp", 3, false}, + {1, "chonan.chiba.jp", 3, false}, + {1, "chosei.chiba.jp", 3, false}, + {1, "choshi.chiba.jp", 3, false}, + {1, "chuo.chiba.jp", 3, false}, + {1, "funabashi.chiba.jp", 3, false}, + {1, "futtsu.chiba.jp", 3, false}, + {1, "hanamigawa.chiba.jp", 3, false}, + {1, "ichihara.chiba.jp", 3, false}, + {1, "ichikawa.chiba.jp", 3, false}, + {1, "ichinomiya.chiba.jp", 3, false}, + {1, "inzai.chiba.jp", 3, false}, + {1, "isumi.chiba.jp", 3, false}, + {1, "kamagaya.chiba.jp", 3, false}, + {1, "kamogawa.chiba.jp", 3, false}, + {1, "kashiwa.chiba.jp", 3, false}, + {1, "katori.chiba.jp", 3, false}, + {1, "katsuura.chiba.jp", 3, false}, + {1, "kimitsu.chiba.jp", 3, false}, + {1, "kisarazu.chiba.jp", 3, false}, + {1, "kozaki.chiba.jp", 3, false}, + {1, "kujukuri.chiba.jp", 3, false}, + {1, "kyonan.chiba.jp", 3, false}, + {1, "matsudo.chiba.jp", 3, false}, + {1, "midori.chiba.jp", 3, false}, + {1, "mihama.chiba.jp", 3, false}, + {1, "minamiboso.chiba.jp", 3, false}, + {1, "mobara.chiba.jp", 3, false}, + {1, "mutsuzawa.chiba.jp", 3, false}, + {1, "nagara.chiba.jp", 3, false}, + {1, "nagareyama.chiba.jp", 3, false}, + {1, "narashino.chiba.jp", 3, false}, + {1, "narita.chiba.jp", 3, false}, + {1, "noda.chiba.jp", 3, false}, + {1, "oamishirasato.chiba.jp", 3, false}, + {1, "omigawa.chiba.jp", 3, false}, + {1, "onjuku.chiba.jp", 3, false}, + {1, "otaki.chiba.jp", 3, false}, + {1, "sakae.chiba.jp", 3, false}, + {1, "sakura.chiba.jp", 3, false}, + {1, "shimofusa.chiba.jp", 3, false}, + {1, "shirako.chiba.jp", 3, false}, + {1, "shiroi.chiba.jp", 3, false}, + {1, "shisui.chiba.jp", 3, false}, + {1, "sodegaura.chiba.jp", 3, false}, + {1, "sosa.chiba.jp", 3, false}, + {1, "tako.chiba.jp", 3, false}, + {1, "tateyama.chiba.jp", 3, false}, + {1, "togane.chiba.jp", 3, false}, + {1, "tohnosho.chiba.jp", 3, false}, + {1, "tomisato.chiba.jp", 3, false}, + {1, "urayasu.chiba.jp", 3, false}, + {1, "yachimata.chiba.jp", 3, false}, + {1, "yachiyo.chiba.jp", 3, false}, + {1, "yokaichiba.chiba.jp", 3, false}, + {1, "yokoshibahikari.chiba.jp", 3, false}, + {1, "yotsukaido.chiba.jp", 3, false}, + {1, "ainan.ehime.jp", 3, false}, + {1, "honai.ehime.jp", 3, false}, + {1, "ikata.ehime.jp", 3, false}, + {1, "imabari.ehime.jp", 3, false}, + {1, "iyo.ehime.jp", 3, false}, + {1, "kamijima.ehime.jp", 3, false}, + {1, "kihoku.ehime.jp", 3, false}, + {1, "kumakogen.ehime.jp", 3, false}, + {1, "masaki.ehime.jp", 3, false}, + {1, "matsuno.ehime.jp", 3, false}, + {1, "matsuyama.ehime.jp", 3, false}, + {1, "namikata.ehime.jp", 3, false}, + {1, "niihama.ehime.jp", 3, false}, + {1, "ozu.ehime.jp", 3, false}, + {1, "saijo.ehime.jp", 3, false}, + {1, "seiyo.ehime.jp", 3, false}, + {1, "shikokuchuo.ehime.jp", 3, false}, + {1, "tobe.ehime.jp", 3, false}, + {1, "toon.ehime.jp", 3, false}, + {1, "uchiko.ehime.jp", 3, false}, + {1, "uwajima.ehime.jp", 3, false}, + {1, "yawatahama.ehime.jp", 3, false}, + {1, "echizen.fukui.jp", 3, false}, + {1, "eiheiji.fukui.jp", 3, false}, + {1, "fukui.fukui.jp", 3, false}, + {1, "ikeda.fukui.jp", 3, false}, + {1, "katsuyama.fukui.jp", 3, false}, + {1, "mihama.fukui.jp", 3, false}, + {1, "minamiechizen.fukui.jp", 3, false}, + {1, "obama.fukui.jp", 3, false}, + {1, "ohi.fukui.jp", 3, false}, + {1, "ono.fukui.jp", 3, false}, + {1, "sabae.fukui.jp", 3, false}, + {1, "sakai.fukui.jp", 3, false}, + {1, "takahama.fukui.jp", 3, false}, + {1, "tsuruga.fukui.jp", 3, false}, + {1, "wakasa.fukui.jp", 3, false}, + {1, "ashiya.fukuoka.jp", 3, false}, + {1, "buzen.fukuoka.jp", 3, false}, + {1, "chikugo.fukuoka.jp", 3, false}, + {1, "chikuho.fukuoka.jp", 3, false}, + {1, "chikujo.fukuoka.jp", 3, false}, + {1, "chikushino.fukuoka.jp", 3, false}, + {1, "chikuzen.fukuoka.jp", 3, false}, + {1, "chuo.fukuoka.jp", 3, false}, + {1, "dazaifu.fukuoka.jp", 3, false}, + {1, "fukuchi.fukuoka.jp", 3, false}, + {1, "hakata.fukuoka.jp", 3, false}, + {1, "higashi.fukuoka.jp", 3, false}, + {1, "hirokawa.fukuoka.jp", 3, false}, + {1, "hisayama.fukuoka.jp", 3, false}, + {1, "iizuka.fukuoka.jp", 3, false}, + {1, "inatsuki.fukuoka.jp", 3, false}, + {1, "kaho.fukuoka.jp", 3, false}, + {1, "kasuga.fukuoka.jp", 3, false}, + {1, "kasuya.fukuoka.jp", 3, false}, + {1, "kawara.fukuoka.jp", 3, false}, + {1, "keisen.fukuoka.jp", 3, false}, + {1, "koga.fukuoka.jp", 3, false}, + {1, "kurate.fukuoka.jp", 3, false}, + {1, "kurogi.fukuoka.jp", 3, false}, + {1, "kurume.fukuoka.jp", 3, false}, + {1, "minami.fukuoka.jp", 3, false}, + {1, "miyako.fukuoka.jp", 3, false}, + {1, "miyama.fukuoka.jp", 3, false}, + {1, "miyawaka.fukuoka.jp", 3, false}, + {1, "mizumaki.fukuoka.jp", 3, false}, + {1, "munakata.fukuoka.jp", 3, false}, + {1, "nakagawa.fukuoka.jp", 3, false}, + {1, "nakama.fukuoka.jp", 3, false}, + {1, "nishi.fukuoka.jp", 3, false}, + {1, "nogata.fukuoka.jp", 3, false}, + {1, "ogori.fukuoka.jp", 3, false}, + {1, "okagaki.fukuoka.jp", 3, false}, + {1, "okawa.fukuoka.jp", 3, false}, + {1, "oki.fukuoka.jp", 3, false}, + {1, "omuta.fukuoka.jp", 3, false}, + {1, "onga.fukuoka.jp", 3, false}, + {1, "onojo.fukuoka.jp", 3, false}, + {1, "oto.fukuoka.jp", 3, false}, + {1, "saigawa.fukuoka.jp", 3, false}, + {1, "sasaguri.fukuoka.jp", 3, false}, + {1, "shingu.fukuoka.jp", 3, false}, + {1, "shinyoshitomi.fukuoka.jp", 3, false}, + {1, "shonai.fukuoka.jp", 3, false}, + {1, "soeda.fukuoka.jp", 3, false}, + {1, "sue.fukuoka.jp", 3, false}, + {1, "tachiarai.fukuoka.jp", 3, false}, + {1, "tagawa.fukuoka.jp", 3, false}, + {1, "takata.fukuoka.jp", 3, false}, + {1, "toho.fukuoka.jp", 3, false}, + {1, "toyotsu.fukuoka.jp", 3, false}, + {1, "tsuiki.fukuoka.jp", 3, false}, + {1, "ukiha.fukuoka.jp", 3, false}, + {1, "umi.fukuoka.jp", 3, false}, + {1, "usui.fukuoka.jp", 3, false}, + {1, "yamada.fukuoka.jp", 3, false}, + {1, "yame.fukuoka.jp", 3, false}, + {1, "yanagawa.fukuoka.jp", 3, false}, + {1, "yukuhashi.fukuoka.jp", 3, false}, + {1, "aizubange.fukushima.jp", 3, false}, + {1, "aizumisato.fukushima.jp", 3, false}, + {1, "aizuwakamatsu.fukushima.jp", 3, false}, + {1, "asakawa.fukushima.jp", 3, false}, + {1, "bandai.fukushima.jp", 3, false}, + {1, "date.fukushima.jp", 3, false}, + {1, "fukushima.fukushima.jp", 3, false}, + {1, "furudono.fukushima.jp", 3, false}, + {1, "futaba.fukushima.jp", 3, false}, + {1, "hanawa.fukushima.jp", 3, false}, + {1, "higashi.fukushima.jp", 3, false}, + {1, "hirata.fukushima.jp", 3, false}, + {1, "hirono.fukushima.jp", 3, false}, + {1, "iitate.fukushima.jp", 3, false}, + {1, "inawashiro.fukushima.jp", 3, false}, + {1, "ishikawa.fukushima.jp", 3, false}, + {1, "iwaki.fukushima.jp", 3, false}, + {1, "izumizaki.fukushima.jp", 3, false}, + {1, "kagamiishi.fukushima.jp", 3, false}, + {1, "kaneyama.fukushima.jp", 3, false}, + {1, "kawamata.fukushima.jp", 3, false}, + {1, "kitakata.fukushima.jp", 3, false}, + {1, "kitashiobara.fukushima.jp", 3, false}, + {1, "koori.fukushima.jp", 3, false}, + {1, "koriyama.fukushima.jp", 3, false}, + {1, "kunimi.fukushima.jp", 3, false}, + {1, "miharu.fukushima.jp", 3, false}, + {1, "mishima.fukushima.jp", 3, false}, + {1, "namie.fukushima.jp", 3, false}, + {1, "nango.fukushima.jp", 3, false}, + {1, "nishiaizu.fukushima.jp", 3, false}, + {1, "nishigo.fukushima.jp", 3, false}, + {1, "okuma.fukushima.jp", 3, false}, + {1, "omotego.fukushima.jp", 3, false}, + {1, "ono.fukushima.jp", 3, false}, + {1, "otama.fukushima.jp", 3, false}, + {1, "samegawa.fukushima.jp", 3, false}, + {1, "shimogo.fukushima.jp", 3, false}, + {1, "shirakawa.fukushima.jp", 3, false}, + {1, "showa.fukushima.jp", 3, false}, + {1, "soma.fukushima.jp", 3, false}, + {1, "sukagawa.fukushima.jp", 3, false}, + {1, "taishin.fukushima.jp", 3, false}, + {1, "tamakawa.fukushima.jp", 3, false}, + {1, "tanagura.fukushima.jp", 3, false}, + {1, "tenei.fukushima.jp", 3, false}, + {1, "yabuki.fukushima.jp", 3, false}, + {1, "yamato.fukushima.jp", 3, false}, + {1, "yamatsuri.fukushima.jp", 3, false}, + {1, "yanaizu.fukushima.jp", 3, false}, + {1, "yugawa.fukushima.jp", 3, false}, + {1, "anpachi.gifu.jp", 3, false}, + {1, "ena.gifu.jp", 3, false}, + {1, "gifu.gifu.jp", 3, false}, + {1, "ginan.gifu.jp", 3, false}, + {1, "godo.gifu.jp", 3, false}, + {1, "gujo.gifu.jp", 3, false}, + {1, "hashima.gifu.jp", 3, false}, + {1, "hichiso.gifu.jp", 3, false}, + {1, "hida.gifu.jp", 3, false}, + {1, "higashishirakawa.gifu.jp", 3, false}, + {1, "ibigawa.gifu.jp", 3, false}, + {1, "ikeda.gifu.jp", 3, false}, + {1, "kakamigahara.gifu.jp", 3, false}, + {1, "kani.gifu.jp", 3, false}, + {1, "kasahara.gifu.jp", 3, false}, + {1, "kasamatsu.gifu.jp", 3, false}, + {1, "kawaue.gifu.jp", 3, false}, + {1, "kitagata.gifu.jp", 3, false}, + {1, "mino.gifu.jp", 3, false}, + {1, "minokamo.gifu.jp", 3, false}, + {1, "mitake.gifu.jp", 3, false}, + {1, "mizunami.gifu.jp", 3, false}, + {1, "motosu.gifu.jp", 3, false}, + {1, "nakatsugawa.gifu.jp", 3, false}, + {1, "ogaki.gifu.jp", 3, false}, + {1, "sakahogi.gifu.jp", 3, false}, + {1, "seki.gifu.jp", 3, false}, + {1, "sekigahara.gifu.jp", 3, false}, + {1, "shirakawa.gifu.jp", 3, false}, + {1, "tajimi.gifu.jp", 3, false}, + {1, "takayama.gifu.jp", 3, false}, + {1, "tarui.gifu.jp", 3, false}, + {1, "toki.gifu.jp", 3, false}, + {1, "tomika.gifu.jp", 3, false}, + {1, "wanouchi.gifu.jp", 3, false}, + {1, "yamagata.gifu.jp", 3, false}, + {1, "yaotsu.gifu.jp", 3, false}, + {1, "yoro.gifu.jp", 3, false}, + {1, "annaka.gunma.jp", 3, false}, + {1, "chiyoda.gunma.jp", 3, false}, + {1, "fujioka.gunma.jp", 3, false}, + {1, "higashiagatsuma.gunma.jp", 3, false}, + {1, "isesaki.gunma.jp", 3, false}, + {1, "itakura.gunma.jp", 3, false}, + {1, "kanna.gunma.jp", 3, false}, + {1, "kanra.gunma.jp", 3, false}, + {1, "katashina.gunma.jp", 3, false}, + {1, "kawaba.gunma.jp", 3, false}, + {1, "kiryu.gunma.jp", 3, false}, + {1, "kusatsu.gunma.jp", 3, false}, + {1, "maebashi.gunma.jp", 3, false}, + {1, "meiwa.gunma.jp", 3, false}, + {1, "midori.gunma.jp", 3, false}, + {1, "minakami.gunma.jp", 3, false}, + {1, "naganohara.gunma.jp", 3, false}, + {1, "nakanojo.gunma.jp", 3, false}, + {1, "nanmoku.gunma.jp", 3, false}, + {1, "numata.gunma.jp", 3, false}, + {1, "oizumi.gunma.jp", 3, false}, + {1, "ora.gunma.jp", 3, false}, + {1, "ota.gunma.jp", 3, false}, + {1, "shibukawa.gunma.jp", 3, false}, + {1, "shimonita.gunma.jp", 3, false}, + {1, "shinto.gunma.jp", 3, false}, + {1, "showa.gunma.jp", 3, false}, + {1, "takasaki.gunma.jp", 3, false}, + {1, "takayama.gunma.jp", 3, false}, + {1, "tamamura.gunma.jp", 3, false}, + {1, "tatebayashi.gunma.jp", 3, false}, + {1, "tomioka.gunma.jp", 3, false}, + {1, "tsukiyono.gunma.jp", 3, false}, + {1, "tsumagoi.gunma.jp", 3, false}, + {1, "ueno.gunma.jp", 3, false}, + {1, "yoshioka.gunma.jp", 3, false}, + {1, "asaminami.hiroshima.jp", 3, false}, + {1, "daiwa.hiroshima.jp", 3, false}, + {1, "etajima.hiroshima.jp", 3, false}, + {1, "fuchu.hiroshima.jp", 3, false}, + {1, "fukuyama.hiroshima.jp", 3, false}, + {1, "hatsukaichi.hiroshima.jp", 3, false}, + {1, "higashihiroshima.hiroshima.jp", 3, false}, + {1, "hongo.hiroshima.jp", 3, false}, + {1, "jinsekikogen.hiroshima.jp", 3, false}, + {1, "kaita.hiroshima.jp", 3, false}, + {1, "kui.hiroshima.jp", 3, false}, + {1, "kumano.hiroshima.jp", 3, false}, + {1, "kure.hiroshima.jp", 3, false}, + {1, "mihara.hiroshima.jp", 3, false}, + {1, "miyoshi.hiroshima.jp", 3, false}, + {1, "naka.hiroshima.jp", 3, false}, + {1, "onomichi.hiroshima.jp", 3, false}, + {1, "osakikamijima.hiroshima.jp", 3, false}, + {1, "otake.hiroshima.jp", 3, false}, + {1, "saka.hiroshima.jp", 3, false}, + {1, "sera.hiroshima.jp", 3, false}, + {1, "seranishi.hiroshima.jp", 3, false}, + {1, "shinichi.hiroshima.jp", 3, false}, + {1, "shobara.hiroshima.jp", 3, false}, + {1, "takehara.hiroshima.jp", 3, false}, + {1, "abashiri.hokkaido.jp", 3, false}, + {1, "abira.hokkaido.jp", 3, false}, + {1, "aibetsu.hokkaido.jp", 3, false}, + {1, "akabira.hokkaido.jp", 3, false}, + {1, "akkeshi.hokkaido.jp", 3, false}, + {1, "asahikawa.hokkaido.jp", 3, false}, + {1, "ashibetsu.hokkaido.jp", 3, false}, + {1, "ashoro.hokkaido.jp", 3, false}, + {1, "assabu.hokkaido.jp", 3, false}, + {1, "atsuma.hokkaido.jp", 3, false}, + {1, "bibai.hokkaido.jp", 3, false}, + {1, "biei.hokkaido.jp", 3, false}, + {1, "bifuka.hokkaido.jp", 3, false}, + {1, "bihoro.hokkaido.jp", 3, false}, + {1, "biratori.hokkaido.jp", 3, false}, + {1, "chippubetsu.hokkaido.jp", 3, false}, + {1, "chitose.hokkaido.jp", 3, false}, + {1, "date.hokkaido.jp", 3, false}, + {1, "ebetsu.hokkaido.jp", 3, false}, + {1, "embetsu.hokkaido.jp", 3, false}, + {1, "eniwa.hokkaido.jp", 3, false}, + {1, "erimo.hokkaido.jp", 3, false}, + {1, "esan.hokkaido.jp", 3, false}, + {1, "esashi.hokkaido.jp", 3, false}, + {1, "fukagawa.hokkaido.jp", 3, false}, + {1, "fukushima.hokkaido.jp", 3, false}, + {1, "furano.hokkaido.jp", 3, false}, + {1, "furubira.hokkaido.jp", 3, false}, + {1, "haboro.hokkaido.jp", 3, false}, + {1, "hakodate.hokkaido.jp", 3, false}, + {1, "hamatonbetsu.hokkaido.jp", 3, false}, + {1, "hidaka.hokkaido.jp", 3, false}, + {1, "higashikagura.hokkaido.jp", 3, false}, + {1, "higashikawa.hokkaido.jp", 3, false}, + {1, "hiroo.hokkaido.jp", 3, false}, + {1, "hokuryu.hokkaido.jp", 3, false}, + {1, "hokuto.hokkaido.jp", 3, false}, + {1, "honbetsu.hokkaido.jp", 3, false}, + {1, "horokanai.hokkaido.jp", 3, false}, + {1, "horonobe.hokkaido.jp", 3, false}, + {1, "ikeda.hokkaido.jp", 3, false}, + {1, "imakane.hokkaido.jp", 3, false}, + {1, "ishikari.hokkaido.jp", 3, false}, + {1, "iwamizawa.hokkaido.jp", 3, false}, + {1, "iwanai.hokkaido.jp", 3, false}, + {1, "kamifurano.hokkaido.jp", 3, false}, + {1, "kamikawa.hokkaido.jp", 3, false}, + {1, "kamishihoro.hokkaido.jp", 3, false}, + {1, "kamisunagawa.hokkaido.jp", 3, false}, + {1, "kamoenai.hokkaido.jp", 3, false}, + {1, "kayabe.hokkaido.jp", 3, false}, + {1, "kembuchi.hokkaido.jp", 3, false}, + {1, "kikonai.hokkaido.jp", 3, false}, + {1, "kimobetsu.hokkaido.jp", 3, false}, + {1, "kitahiroshima.hokkaido.jp", 3, false}, + {1, "kitami.hokkaido.jp", 3, false}, + {1, "kiyosato.hokkaido.jp", 3, false}, + {1, "koshimizu.hokkaido.jp", 3, false}, + {1, "kunneppu.hokkaido.jp", 3, false}, + {1, "kuriyama.hokkaido.jp", 3, false}, + {1, "kuromatsunai.hokkaido.jp", 3, false}, + {1, "kushiro.hokkaido.jp", 3, false}, + {1, "kutchan.hokkaido.jp", 3, false}, + {1, "kyowa.hokkaido.jp", 3, false}, + {1, "mashike.hokkaido.jp", 3, false}, + {1, "matsumae.hokkaido.jp", 3, false}, + {1, "mikasa.hokkaido.jp", 3, false}, + {1, "minamifurano.hokkaido.jp", 3, false}, + {1, "mombetsu.hokkaido.jp", 3, false}, + {1, "moseushi.hokkaido.jp", 3, false}, + {1, "mukawa.hokkaido.jp", 3, false}, + {1, "muroran.hokkaido.jp", 3, false}, + {1, "naie.hokkaido.jp", 3, false}, + {1, "nakagawa.hokkaido.jp", 3, false}, + {1, "nakasatsunai.hokkaido.jp", 3, false}, + {1, "nakatombetsu.hokkaido.jp", 3, false}, + {1, "nanae.hokkaido.jp", 3, false}, + {1, "nanporo.hokkaido.jp", 3, false}, + {1, "nayoro.hokkaido.jp", 3, false}, + {1, "nemuro.hokkaido.jp", 3, false}, + {1, "niikappu.hokkaido.jp", 3, false}, + {1, "niki.hokkaido.jp", 3, false}, + {1, "nishiokoppe.hokkaido.jp", 3, false}, + {1, "noboribetsu.hokkaido.jp", 3, false}, + {1, "numata.hokkaido.jp", 3, false}, + {1, "obihiro.hokkaido.jp", 3, false}, + {1, "obira.hokkaido.jp", 3, false}, + {1, "oketo.hokkaido.jp", 3, false}, + {1, "okoppe.hokkaido.jp", 3, false}, + {1, "otaru.hokkaido.jp", 3, false}, + {1, "otobe.hokkaido.jp", 3, false}, + {1, "otofuke.hokkaido.jp", 3, false}, + {1, "otoineppu.hokkaido.jp", 3, false}, + {1, "oumu.hokkaido.jp", 3, false}, + {1, "ozora.hokkaido.jp", 3, false}, + {1, "pippu.hokkaido.jp", 3, false}, + {1, "rankoshi.hokkaido.jp", 3, false}, + {1, "rebun.hokkaido.jp", 3, false}, + {1, "rikubetsu.hokkaido.jp", 3, false}, + {1, "rishiri.hokkaido.jp", 3, false}, + {1, "rishirifuji.hokkaido.jp", 3, false}, + {1, "saroma.hokkaido.jp", 3, false}, + {1, "sarufutsu.hokkaido.jp", 3, false}, + {1, "shakotan.hokkaido.jp", 3, false}, + {1, "shari.hokkaido.jp", 3, false}, + {1, "shibecha.hokkaido.jp", 3, false}, + {1, "shibetsu.hokkaido.jp", 3, false}, + {1, "shikabe.hokkaido.jp", 3, false}, + {1, "shikaoi.hokkaido.jp", 3, false}, + {1, "shimamaki.hokkaido.jp", 3, false}, + {1, "shimizu.hokkaido.jp", 3, false}, + {1, "shimokawa.hokkaido.jp", 3, false}, + {1, "shinshinotsu.hokkaido.jp", 3, false}, + {1, "shintoku.hokkaido.jp", 3, false}, + {1, "shiranuka.hokkaido.jp", 3, false}, + {1, "shiraoi.hokkaido.jp", 3, false}, + {1, "shiriuchi.hokkaido.jp", 3, false}, + {1, "sobetsu.hokkaido.jp", 3, false}, + {1, "sunagawa.hokkaido.jp", 3, false}, + {1, "taiki.hokkaido.jp", 3, false}, + {1, "takasu.hokkaido.jp", 3, false}, + {1, "takikawa.hokkaido.jp", 3, false}, + {1, "takinoue.hokkaido.jp", 3, false}, + {1, "teshikaga.hokkaido.jp", 3, false}, + {1, "tobetsu.hokkaido.jp", 3, false}, + {1, "tohma.hokkaido.jp", 3, false}, + {1, "tomakomai.hokkaido.jp", 3, false}, + {1, "tomari.hokkaido.jp", 3, false}, + {1, "toya.hokkaido.jp", 3, false}, + {1, "toyako.hokkaido.jp", 3, false}, + {1, "toyotomi.hokkaido.jp", 3, false}, + {1, "toyoura.hokkaido.jp", 3, false}, + {1, "tsubetsu.hokkaido.jp", 3, false}, + {1, "tsukigata.hokkaido.jp", 3, false}, + {1, "urakawa.hokkaido.jp", 3, false}, + {1, "urausu.hokkaido.jp", 3, false}, + {1, "uryu.hokkaido.jp", 3, false}, + {1, "utashinai.hokkaido.jp", 3, false}, + {1, "wakkanai.hokkaido.jp", 3, false}, + {1, "wassamu.hokkaido.jp", 3, false}, + {1, "yakumo.hokkaido.jp", 3, false}, + {1, "yoichi.hokkaido.jp", 3, false}, + {1, "aioi.hyogo.jp", 3, false}, + {1, "akashi.hyogo.jp", 3, false}, + {1, "ako.hyogo.jp", 3, false}, + {1, "amagasaki.hyogo.jp", 3, false}, + {1, "aogaki.hyogo.jp", 3, false}, + {1, "asago.hyogo.jp", 3, false}, + {1, "ashiya.hyogo.jp", 3, false}, + {1, "awaji.hyogo.jp", 3, false}, + {1, "fukusaki.hyogo.jp", 3, false}, + {1, "goshiki.hyogo.jp", 3, false}, + {1, "harima.hyogo.jp", 3, false}, + {1, "himeji.hyogo.jp", 3, false}, + {1, "ichikawa.hyogo.jp", 3, false}, + {1, "inagawa.hyogo.jp", 3, false}, + {1, "itami.hyogo.jp", 3, false}, + {1, "kakogawa.hyogo.jp", 3, false}, + {1, "kamigori.hyogo.jp", 3, false}, + {1, "kamikawa.hyogo.jp", 3, false}, + {1, "kasai.hyogo.jp", 3, false}, + {1, "kasuga.hyogo.jp", 3, false}, + {1, "kawanishi.hyogo.jp", 3, false}, + {1, "miki.hyogo.jp", 3, false}, + {1, "minamiawaji.hyogo.jp", 3, false}, + {1, "nishinomiya.hyogo.jp", 3, false}, + {1, "nishiwaki.hyogo.jp", 3, false}, + {1, "ono.hyogo.jp", 3, false}, + {1, "sanda.hyogo.jp", 3, false}, + {1, "sannan.hyogo.jp", 3, false}, + {1, "sasayama.hyogo.jp", 3, false}, + {1, "sayo.hyogo.jp", 3, false}, + {1, "shingu.hyogo.jp", 3, false}, + {1, "shinonsen.hyogo.jp", 3, false}, + {1, "shiso.hyogo.jp", 3, false}, + {1, "sumoto.hyogo.jp", 3, false}, + {1, "taishi.hyogo.jp", 3, false}, + {1, "taka.hyogo.jp", 3, false}, + {1, "takarazuka.hyogo.jp", 3, false}, + {1, "takasago.hyogo.jp", 3, false}, + {1, "takino.hyogo.jp", 3, false}, + {1, "tamba.hyogo.jp", 3, false}, + {1, "tatsuno.hyogo.jp", 3, false}, + {1, "toyooka.hyogo.jp", 3, false}, + {1, "yabu.hyogo.jp", 3, false}, + {1, "yashiro.hyogo.jp", 3, false}, + {1, "yoka.hyogo.jp", 3, false}, + {1, "yokawa.hyogo.jp", 3, false}, + {1, "ami.ibaraki.jp", 3, false}, + {1, "asahi.ibaraki.jp", 3, false}, + {1, "bando.ibaraki.jp", 3, false}, + {1, "chikusei.ibaraki.jp", 3, false}, + {1, "daigo.ibaraki.jp", 3, false}, + {1, "fujishiro.ibaraki.jp", 3, false}, + {1, "hitachi.ibaraki.jp", 3, false}, + {1, "hitachinaka.ibaraki.jp", 3, false}, + {1, "hitachiomiya.ibaraki.jp", 3, false}, + {1, "hitachiota.ibaraki.jp", 3, false}, + {1, "ibaraki.ibaraki.jp", 3, false}, + {1, "ina.ibaraki.jp", 3, false}, + {1, "inashiki.ibaraki.jp", 3, false}, + {1, "itako.ibaraki.jp", 3, false}, + {1, "iwama.ibaraki.jp", 3, false}, + {1, "joso.ibaraki.jp", 3, false}, + {1, "kamisu.ibaraki.jp", 3, false}, + {1, "kasama.ibaraki.jp", 3, false}, + {1, "kashima.ibaraki.jp", 3, false}, + {1, "kasumigaura.ibaraki.jp", 3, false}, + {1, "koga.ibaraki.jp", 3, false}, + {1, "miho.ibaraki.jp", 3, false}, + {1, "mito.ibaraki.jp", 3, false}, + {1, "moriya.ibaraki.jp", 3, false}, + {1, "naka.ibaraki.jp", 3, false}, + {1, "namegata.ibaraki.jp", 3, false}, + {1, "oarai.ibaraki.jp", 3, false}, + {1, "ogawa.ibaraki.jp", 3, false}, + {1, "omitama.ibaraki.jp", 3, false}, + {1, "ryugasaki.ibaraki.jp", 3, false}, + {1, "sakai.ibaraki.jp", 3, false}, + {1, "sakuragawa.ibaraki.jp", 3, false}, + {1, "shimodate.ibaraki.jp", 3, false}, + {1, "shimotsuma.ibaraki.jp", 3, false}, + {1, "shirosato.ibaraki.jp", 3, false}, + {1, "sowa.ibaraki.jp", 3, false}, + {1, "suifu.ibaraki.jp", 3, false}, + {1, "takahagi.ibaraki.jp", 3, false}, + {1, "tamatsukuri.ibaraki.jp", 3, false}, + {1, "tokai.ibaraki.jp", 3, false}, + {1, "tomobe.ibaraki.jp", 3, false}, + {1, "tone.ibaraki.jp", 3, false}, + {1, "toride.ibaraki.jp", 3, false}, + {1, "tsuchiura.ibaraki.jp", 3, false}, + {1, "tsukuba.ibaraki.jp", 3, false}, + {1, "uchihara.ibaraki.jp", 3, false}, + {1, "ushiku.ibaraki.jp", 3, false}, + {1, "yachiyo.ibaraki.jp", 3, false}, + {1, "yamagata.ibaraki.jp", 3, false}, + {1, "yawara.ibaraki.jp", 3, false}, + {1, "yuki.ibaraki.jp", 3, false}, + {1, "anamizu.ishikawa.jp", 3, false}, + {1, "hakui.ishikawa.jp", 3, false}, + {1, "hakusan.ishikawa.jp", 3, false}, + {1, "kaga.ishikawa.jp", 3, false}, + {1, "kahoku.ishikawa.jp", 3, false}, + {1, "kanazawa.ishikawa.jp", 3, false}, + {1, "kawakita.ishikawa.jp", 3, false}, + {1, "komatsu.ishikawa.jp", 3, false}, + {1, "nakanoto.ishikawa.jp", 3, false}, + {1, "nanao.ishikawa.jp", 3, false}, + {1, "nomi.ishikawa.jp", 3, false}, + {1, "nonoichi.ishikawa.jp", 3, false}, + {1, "noto.ishikawa.jp", 3, false}, + {1, "shika.ishikawa.jp", 3, false}, + {1, "suzu.ishikawa.jp", 3, false}, + {1, "tsubata.ishikawa.jp", 3, false}, + {1, "tsurugi.ishikawa.jp", 3, false}, + {1, "uchinada.ishikawa.jp", 3, false}, + {1, "wajima.ishikawa.jp", 3, false}, + {1, "fudai.iwate.jp", 3, false}, + {1, "fujisawa.iwate.jp", 3, false}, + {1, "hanamaki.iwate.jp", 3, false}, + {1, "hiraizumi.iwate.jp", 3, false}, + {1, "hirono.iwate.jp", 3, false}, + {1, "ichinohe.iwate.jp", 3, false}, + {1, "ichinoseki.iwate.jp", 3, false}, + {1, "iwaizumi.iwate.jp", 3, false}, + {1, "iwate.iwate.jp", 3, false}, + {1, "joboji.iwate.jp", 3, false}, + {1, "kamaishi.iwate.jp", 3, false}, + {1, "kanegasaki.iwate.jp", 3, false}, + {1, "karumai.iwate.jp", 3, false}, + {1, "kawai.iwate.jp", 3, false}, + {1, "kitakami.iwate.jp", 3, false}, + {1, "kuji.iwate.jp", 3, false}, + {1, "kunohe.iwate.jp", 3, false}, + {1, "kuzumaki.iwate.jp", 3, false}, + {1, "miyako.iwate.jp", 3, false}, + {1, "mizusawa.iwate.jp", 3, false}, + {1, "morioka.iwate.jp", 3, false}, + {1, "ninohe.iwate.jp", 3, false}, + {1, "noda.iwate.jp", 3, false}, + {1, "ofunato.iwate.jp", 3, false}, + {1, "oshu.iwate.jp", 3, false}, + {1, "otsuchi.iwate.jp", 3, false}, + {1, "rikuzentakata.iwate.jp", 3, false}, + {1, "shiwa.iwate.jp", 3, false}, + {1, "shizukuishi.iwate.jp", 3, false}, + {1, "sumita.iwate.jp", 3, false}, + {1, "tanohata.iwate.jp", 3, false}, + {1, "tono.iwate.jp", 3, false}, + {1, "yahaba.iwate.jp", 3, false}, + {1, "yamada.iwate.jp", 3, false}, + {1, "ayagawa.kagawa.jp", 3, false}, + {1, "higashikagawa.kagawa.jp", 3, false}, + {1, "kanonji.kagawa.jp", 3, false}, + {1, "kotohira.kagawa.jp", 3, false}, + {1, "manno.kagawa.jp", 3, false}, + {1, "marugame.kagawa.jp", 3, false}, + {1, "mitoyo.kagawa.jp", 3, false}, + {1, "naoshima.kagawa.jp", 3, false}, + {1, "sanuki.kagawa.jp", 3, false}, + {1, "tadotsu.kagawa.jp", 3, false}, + {1, "takamatsu.kagawa.jp", 3, false}, + {1, "tonosho.kagawa.jp", 3, false}, + {1, "uchinomi.kagawa.jp", 3, false}, + {1, "utazu.kagawa.jp", 3, false}, + {1, "zentsuji.kagawa.jp", 3, false}, + {1, "akune.kagoshima.jp", 3, false}, + {1, "amami.kagoshima.jp", 3, false}, + {1, "hioki.kagoshima.jp", 3, false}, + {1, "isa.kagoshima.jp", 3, false}, + {1, "isen.kagoshima.jp", 3, false}, + {1, "izumi.kagoshima.jp", 3, false}, + {1, "kagoshima.kagoshima.jp", 3, false}, + {1, "kanoya.kagoshima.jp", 3, false}, + {1, "kawanabe.kagoshima.jp", 3, false}, + {1, "kinko.kagoshima.jp", 3, false}, + {1, "kouyama.kagoshima.jp", 3, false}, + {1, "makurazaki.kagoshima.jp", 3, false}, + {1, "matsumoto.kagoshima.jp", 3, false}, + {1, "minamitane.kagoshima.jp", 3, false}, + {1, "nakatane.kagoshima.jp", 3, false}, + {1, "nishinoomote.kagoshima.jp", 3, false}, + {1, "satsumasendai.kagoshima.jp", 3, false}, + {1, "soo.kagoshima.jp", 3, false}, + {1, "tarumizu.kagoshima.jp", 3, false}, + {1, "yusui.kagoshima.jp", 3, false}, + {1, "aikawa.kanagawa.jp", 3, false}, + {1, "atsugi.kanagawa.jp", 3, false}, + {1, "ayase.kanagawa.jp", 3, false}, + {1, "chigasaki.kanagawa.jp", 3, false}, + {1, "ebina.kanagawa.jp", 3, false}, + {1, "fujisawa.kanagawa.jp", 3, false}, + {1, "hadano.kanagawa.jp", 3, false}, + {1, "hakone.kanagawa.jp", 3, false}, + {1, "hiratsuka.kanagawa.jp", 3, false}, + {1, "isehara.kanagawa.jp", 3, false}, + {1, "kaisei.kanagawa.jp", 3, false}, + {1, "kamakura.kanagawa.jp", 3, false}, + {1, "kiyokawa.kanagawa.jp", 3, false}, + {1, "matsuda.kanagawa.jp", 3, false}, + {1, "minamiashigara.kanagawa.jp", 3, false}, + {1, "miura.kanagawa.jp", 3, false}, + {1, "nakai.kanagawa.jp", 3, false}, + {1, "ninomiya.kanagawa.jp", 3, false}, + {1, "odawara.kanagawa.jp", 3, false}, + {1, "oi.kanagawa.jp", 3, false}, + {1, "oiso.kanagawa.jp", 3, false}, + {1, "sagamihara.kanagawa.jp", 3, false}, + {1, "samukawa.kanagawa.jp", 3, false}, + {1, "tsukui.kanagawa.jp", 3, false}, + {1, "yamakita.kanagawa.jp", 3, false}, + {1, "yamato.kanagawa.jp", 3, false}, + {1, "yokosuka.kanagawa.jp", 3, false}, + {1, "yugawara.kanagawa.jp", 3, false}, + {1, "zama.kanagawa.jp", 3, false}, + {1, "zushi.kanagawa.jp", 3, false}, + {1, "aki.kochi.jp", 3, false}, + {1, "geisei.kochi.jp", 3, false}, + {1, "hidaka.kochi.jp", 3, false}, + {1, "higashitsuno.kochi.jp", 3, false}, + {1, "ino.kochi.jp", 3, false}, + {1, "kagami.kochi.jp", 3, false}, + {1, "kami.kochi.jp", 3, false}, + {1, "kitagawa.kochi.jp", 3, false}, + {1, "kochi.kochi.jp", 3, false}, + {1, "mihara.kochi.jp", 3, false}, + {1, "motoyama.kochi.jp", 3, false}, + {1, "muroto.kochi.jp", 3, false}, + {1, "nahari.kochi.jp", 3, false}, + {1, "nakamura.kochi.jp", 3, false}, + {1, "nankoku.kochi.jp", 3, false}, + {1, "nishitosa.kochi.jp", 3, false}, + {1, "niyodogawa.kochi.jp", 3, false}, + {1, "ochi.kochi.jp", 3, false}, + {1, "okawa.kochi.jp", 3, false}, + {1, "otoyo.kochi.jp", 3, false}, + {1, "otsuki.kochi.jp", 3, false}, + {1, "sakawa.kochi.jp", 3, false}, + {1, "sukumo.kochi.jp", 3, false}, + {1, "susaki.kochi.jp", 3, false}, + {1, "tosa.kochi.jp", 3, false}, + {1, "tosashimizu.kochi.jp", 3, false}, + {1, "toyo.kochi.jp", 3, false}, + {1, "tsuno.kochi.jp", 3, false}, + {1, "umaji.kochi.jp", 3, false}, + {1, "yasuda.kochi.jp", 3, false}, + {1, "yusuhara.kochi.jp", 3, false}, + {1, "amakusa.kumamoto.jp", 3, false}, + {1, "arao.kumamoto.jp", 3, false}, + {1, "aso.kumamoto.jp", 3, false}, + {1, "choyo.kumamoto.jp", 3, false}, + {1, "gyokuto.kumamoto.jp", 3, false}, + {1, "kamiamakusa.kumamoto.jp", 3, false}, + {1, "kikuchi.kumamoto.jp", 3, false}, + {1, "kumamoto.kumamoto.jp", 3, false}, + {1, "mashiki.kumamoto.jp", 3, false}, + {1, "mifune.kumamoto.jp", 3, false}, + {1, "minamata.kumamoto.jp", 3, false}, + {1, "minamioguni.kumamoto.jp", 3, false}, + {1, "nagasu.kumamoto.jp", 3, false}, + {1, "nishihara.kumamoto.jp", 3, false}, + {1, "oguni.kumamoto.jp", 3, false}, + {1, "ozu.kumamoto.jp", 3, false}, + {1, "sumoto.kumamoto.jp", 3, false}, + {1, "takamori.kumamoto.jp", 3, false}, + {1, "uki.kumamoto.jp", 3, false}, + {1, "uto.kumamoto.jp", 3, false}, + {1, "yamaga.kumamoto.jp", 3, false}, + {1, "yamato.kumamoto.jp", 3, false}, + {1, "yatsushiro.kumamoto.jp", 3, false}, + {1, "ayabe.kyoto.jp", 3, false}, + {1, "fukuchiyama.kyoto.jp", 3, false}, + {1, "higashiyama.kyoto.jp", 3, false}, + {1, "ide.kyoto.jp", 3, false}, + {1, "ine.kyoto.jp", 3, false}, + {1, "joyo.kyoto.jp", 3, false}, + {1, "kameoka.kyoto.jp", 3, false}, + {1, "kamo.kyoto.jp", 3, false}, + {1, "kita.kyoto.jp", 3, false}, + {1, "kizu.kyoto.jp", 3, false}, + {1, "kumiyama.kyoto.jp", 3, false}, + {1, "kyotamba.kyoto.jp", 3, false}, + {1, "kyotanabe.kyoto.jp", 3, false}, + {1, "kyotango.kyoto.jp", 3, false}, + {1, "maizuru.kyoto.jp", 3, false}, + {1, "minami.kyoto.jp", 3, false}, + {1, "minamiyamashiro.kyoto.jp", 3, false}, + {1, "miyazu.kyoto.jp", 3, false}, + {1, "muko.kyoto.jp", 3, false}, + {1, "nagaokakyo.kyoto.jp", 3, false}, + {1, "nakagyo.kyoto.jp", 3, false}, + {1, "nantan.kyoto.jp", 3, false}, + {1, "oyamazaki.kyoto.jp", 3, false}, + {1, "sakyo.kyoto.jp", 3, false}, + {1, "seika.kyoto.jp", 3, false}, + {1, "tanabe.kyoto.jp", 3, false}, + {1, "uji.kyoto.jp", 3, false}, + {1, "ujitawara.kyoto.jp", 3, false}, + {1, "wazuka.kyoto.jp", 3, false}, + {1, "yamashina.kyoto.jp", 3, false}, + {1, "yawata.kyoto.jp", 3, false}, + {1, "asahi.mie.jp", 3, false}, + {1, "inabe.mie.jp", 3, false}, + {1, "ise.mie.jp", 3, false}, + {1, "kameyama.mie.jp", 3, false}, + {1, "kawagoe.mie.jp", 3, false}, + {1, "kiho.mie.jp", 3, false}, + {1, "kisosaki.mie.jp", 3, false}, + {1, "kiwa.mie.jp", 3, false}, + {1, "komono.mie.jp", 3, false}, + {1, "kumano.mie.jp", 3, false}, + {1, "kuwana.mie.jp", 3, false}, + {1, "matsusaka.mie.jp", 3, false}, + {1, "meiwa.mie.jp", 3, false}, + {1, "mihama.mie.jp", 3, false}, + {1, "minamiise.mie.jp", 3, false}, + {1, "misugi.mie.jp", 3, false}, + {1, "miyama.mie.jp", 3, false}, + {1, "nabari.mie.jp", 3, false}, + {1, "shima.mie.jp", 3, false}, + {1, "suzuka.mie.jp", 3, false}, + {1, "tado.mie.jp", 3, false}, + {1, "taiki.mie.jp", 3, false}, + {1, "taki.mie.jp", 3, false}, + {1, "tamaki.mie.jp", 3, false}, + {1, "toba.mie.jp", 3, false}, + {1, "tsu.mie.jp", 3, false}, + {1, "udono.mie.jp", 3, false}, + {1, "ureshino.mie.jp", 3, false}, + {1, "watarai.mie.jp", 3, false}, + {1, "yokkaichi.mie.jp", 3, false}, + {1, "furukawa.miyagi.jp", 3, false}, + {1, "higashimatsushima.miyagi.jp", 3, false}, + {1, "ishinomaki.miyagi.jp", 3, false}, + {1, "iwanuma.miyagi.jp", 3, false}, + {1, "kakuda.miyagi.jp", 3, false}, + {1, "kami.miyagi.jp", 3, false}, + {1, "kawasaki.miyagi.jp", 3, false}, + {1, "marumori.miyagi.jp", 3, false}, + {1, "matsushima.miyagi.jp", 3, false}, + {1, "minamisanriku.miyagi.jp", 3, false}, + {1, "misato.miyagi.jp", 3, false}, + {1, "murata.miyagi.jp", 3, false}, + {1, "natori.miyagi.jp", 3, false}, + {1, "ogawara.miyagi.jp", 3, false}, + {1, "ohira.miyagi.jp", 3, false}, + {1, "onagawa.miyagi.jp", 3, false}, + {1, "osaki.miyagi.jp", 3, false}, + {1, "rifu.miyagi.jp", 3, false}, + {1, "semine.miyagi.jp", 3, false}, + {1, "shibata.miyagi.jp", 3, false}, + {1, "shichikashuku.miyagi.jp", 3, false}, + {1, "shikama.miyagi.jp", 3, false}, + {1, "shiogama.miyagi.jp", 3, false}, + {1, "shiroishi.miyagi.jp", 3, false}, + {1, "tagajo.miyagi.jp", 3, false}, + {1, "taiwa.miyagi.jp", 3, false}, + {1, "tome.miyagi.jp", 3, false}, + {1, "tomiya.miyagi.jp", 3, false}, + {1, "wakuya.miyagi.jp", 3, false}, + {1, "watari.miyagi.jp", 3, false}, + {1, "yamamoto.miyagi.jp", 3, false}, + {1, "zao.miyagi.jp", 3, false}, + {1, "aya.miyazaki.jp", 3, false}, + {1, "ebino.miyazaki.jp", 3, false}, + {1, "gokase.miyazaki.jp", 3, false}, + {1, "hyuga.miyazaki.jp", 3, false}, + {1, "kadogawa.miyazaki.jp", 3, false}, + {1, "kawaminami.miyazaki.jp", 3, false}, + {1, "kijo.miyazaki.jp", 3, false}, + {1, "kitagawa.miyazaki.jp", 3, false}, + {1, "kitakata.miyazaki.jp", 3, false}, + {1, "kitaura.miyazaki.jp", 3, false}, + {1, "kobayashi.miyazaki.jp", 3, false}, + {1, "kunitomi.miyazaki.jp", 3, false}, + {1, "kushima.miyazaki.jp", 3, false}, + {1, "mimata.miyazaki.jp", 3, false}, + {1, "miyakonojo.miyazaki.jp", 3, false}, + {1, "miyazaki.miyazaki.jp", 3, false}, + {1, "morotsuka.miyazaki.jp", 3, false}, + {1, "nichinan.miyazaki.jp", 3, false}, + {1, "nishimera.miyazaki.jp", 3, false}, + {1, "nobeoka.miyazaki.jp", 3, false}, + {1, "saito.miyazaki.jp", 3, false}, + {1, "shiiba.miyazaki.jp", 3, false}, + {1, "shintomi.miyazaki.jp", 3, false}, + {1, "takaharu.miyazaki.jp", 3, false}, + {1, "takanabe.miyazaki.jp", 3, false}, + {1, "takazaki.miyazaki.jp", 3, false}, + {1, "tsuno.miyazaki.jp", 3, false}, + {1, "achi.nagano.jp", 3, false}, + {1, "agematsu.nagano.jp", 3, false}, + {1, "anan.nagano.jp", 3, false}, + {1, "aoki.nagano.jp", 3, false}, + {1, "asahi.nagano.jp", 3, false}, + {1, "azumino.nagano.jp", 3, false}, + {1, "chikuhoku.nagano.jp", 3, false}, + {1, "chikuma.nagano.jp", 3, false}, + {1, "chino.nagano.jp", 3, false}, + {1, "fujimi.nagano.jp", 3, false}, + {1, "hakuba.nagano.jp", 3, false}, + {1, "hara.nagano.jp", 3, false}, + {1, "hiraya.nagano.jp", 3, false}, + {1, "iida.nagano.jp", 3, false}, + {1, "iijima.nagano.jp", 3, false}, + {1, "iiyama.nagano.jp", 3, false}, + {1, "iizuna.nagano.jp", 3, false}, + {1, "ikeda.nagano.jp", 3, false}, + {1, "ikusaka.nagano.jp", 3, false}, + {1, "ina.nagano.jp", 3, false}, + {1, "karuizawa.nagano.jp", 3, false}, + {1, "kawakami.nagano.jp", 3, false}, + {1, "kiso.nagano.jp", 3, false}, + {1, "kisofukushima.nagano.jp", 3, false}, + {1, "kitaaiki.nagano.jp", 3, false}, + {1, "komagane.nagano.jp", 3, false}, + {1, "komoro.nagano.jp", 3, false}, + {1, "matsukawa.nagano.jp", 3, false}, + {1, "matsumoto.nagano.jp", 3, false}, + {1, "miasa.nagano.jp", 3, false}, + {1, "minamiaiki.nagano.jp", 3, false}, + {1, "minamimaki.nagano.jp", 3, false}, + {1, "minamiminowa.nagano.jp", 3, false}, + {1, "minowa.nagano.jp", 3, false}, + {1, "miyada.nagano.jp", 3, false}, + {1, "miyota.nagano.jp", 3, false}, + {1, "mochizuki.nagano.jp", 3, false}, + {1, "nagano.nagano.jp", 3, false}, + {1, "nagawa.nagano.jp", 3, false}, + {1, "nagiso.nagano.jp", 3, false}, + {1, "nakagawa.nagano.jp", 3, false}, + {1, "nakano.nagano.jp", 3, false}, + {1, "nozawaonsen.nagano.jp", 3, false}, + {1, "obuse.nagano.jp", 3, false}, + {1, "ogawa.nagano.jp", 3, false}, + {1, "okaya.nagano.jp", 3, false}, + {1, "omachi.nagano.jp", 3, false}, + {1, "omi.nagano.jp", 3, false}, + {1, "ookuwa.nagano.jp", 3, false}, + {1, "ooshika.nagano.jp", 3, false}, + {1, "otaki.nagano.jp", 3, false}, + {1, "otari.nagano.jp", 3, false}, + {1, "sakae.nagano.jp", 3, false}, + {1, "sakaki.nagano.jp", 3, false}, + {1, "saku.nagano.jp", 3, false}, + {1, "sakuho.nagano.jp", 3, false}, + {1, "shimosuwa.nagano.jp", 3, false}, + {1, "shinanomachi.nagano.jp", 3, false}, + {1, "shiojiri.nagano.jp", 3, false}, + {1, "suwa.nagano.jp", 3, false}, + {1, "suzaka.nagano.jp", 3, false}, + {1, "takagi.nagano.jp", 3, false}, + {1, "takamori.nagano.jp", 3, false}, + {1, "takayama.nagano.jp", 3, false}, + {1, "tateshina.nagano.jp", 3, false}, + {1, "tatsuno.nagano.jp", 3, false}, + {1, "togakushi.nagano.jp", 3, false}, + {1, "togura.nagano.jp", 3, false}, + {1, "tomi.nagano.jp", 3, false}, + {1, "ueda.nagano.jp", 3, false}, + {1, "wada.nagano.jp", 3, false}, + {1, "yamagata.nagano.jp", 3, false}, + {1, "yamanouchi.nagano.jp", 3, false}, + {1, "yasaka.nagano.jp", 3, false}, + {1, "yasuoka.nagano.jp", 3, false}, + {1, "chijiwa.nagasaki.jp", 3, false}, + {1, "futsu.nagasaki.jp", 3, false}, + {1, "goto.nagasaki.jp", 3, false}, + {1, "hasami.nagasaki.jp", 3, false}, + {1, "hirado.nagasaki.jp", 3, false}, + {1, "iki.nagasaki.jp", 3, false}, + {1, "isahaya.nagasaki.jp", 3, false}, + {1, "kawatana.nagasaki.jp", 3, false}, + {1, "kuchinotsu.nagasaki.jp", 3, false}, + {1, "matsuura.nagasaki.jp", 3, false}, + {1, "nagasaki.nagasaki.jp", 3, false}, + {1, "obama.nagasaki.jp", 3, false}, + {1, "omura.nagasaki.jp", 3, false}, + {1, "oseto.nagasaki.jp", 3, false}, + {1, "saikai.nagasaki.jp", 3, false}, + {1, "sasebo.nagasaki.jp", 3, false}, + {1, "seihi.nagasaki.jp", 3, false}, + {1, "shimabara.nagasaki.jp", 3, false}, + {1, "shinkamigoto.nagasaki.jp", 3, false}, + {1, "togitsu.nagasaki.jp", 3, false}, + {1, "tsushima.nagasaki.jp", 3, false}, + {1, "unzen.nagasaki.jp", 3, false}, + {1, "ando.nara.jp", 3, false}, + {1, "gose.nara.jp", 3, false}, + {1, "heguri.nara.jp", 3, false}, + {1, "higashiyoshino.nara.jp", 3, false}, + {1, "ikaruga.nara.jp", 3, false}, + {1, "ikoma.nara.jp", 3, false}, + {1, "kamikitayama.nara.jp", 3, false}, + {1, "kanmaki.nara.jp", 3, false}, + {1, "kashiba.nara.jp", 3, false}, + {1, "kashihara.nara.jp", 3, false}, + {1, "katsuragi.nara.jp", 3, false}, + {1, "kawai.nara.jp", 3, false}, + {1, "kawakami.nara.jp", 3, false}, + {1, "kawanishi.nara.jp", 3, false}, + {1, "koryo.nara.jp", 3, false}, + {1, "kurotaki.nara.jp", 3, false}, + {1, "mitsue.nara.jp", 3, false}, + {1, "miyake.nara.jp", 3, false}, + {1, "nara.nara.jp", 3, false}, + {1, "nosegawa.nara.jp", 3, false}, + {1, "oji.nara.jp", 3, false}, + {1, "ouda.nara.jp", 3, false}, + {1, "oyodo.nara.jp", 3, false}, + {1, "sakurai.nara.jp", 3, false}, + {1, "sango.nara.jp", 3, false}, + {1, "shimoichi.nara.jp", 3, false}, + {1, "shimokitayama.nara.jp", 3, false}, + {1, "shinjo.nara.jp", 3, false}, + {1, "soni.nara.jp", 3, false}, + {1, "takatori.nara.jp", 3, false}, + {1, "tawaramoto.nara.jp", 3, false}, + {1, "tenkawa.nara.jp", 3, false}, + {1, "tenri.nara.jp", 3, false}, + {1, "uda.nara.jp", 3, false}, + {1, "yamatokoriyama.nara.jp", 3, false}, + {1, "yamatotakada.nara.jp", 3, false}, + {1, "yamazoe.nara.jp", 3, false}, + {1, "yoshino.nara.jp", 3, false}, + {1, "aga.niigata.jp", 3, false}, + {1, "agano.niigata.jp", 3, false}, + {1, "gosen.niigata.jp", 3, false}, + {1, "itoigawa.niigata.jp", 3, false}, + {1, "izumozaki.niigata.jp", 3, false}, + {1, "joetsu.niigata.jp", 3, false}, + {1, "kamo.niigata.jp", 3, false}, + {1, "kariwa.niigata.jp", 3, false}, + {1, "kashiwazaki.niigata.jp", 3, false}, + {1, "minamiuonuma.niigata.jp", 3, false}, + {1, "mitsuke.niigata.jp", 3, false}, + {1, "muika.niigata.jp", 3, false}, + {1, "murakami.niigata.jp", 3, false}, + {1, "myoko.niigata.jp", 3, false}, + {1, "nagaoka.niigata.jp", 3, false}, + {1, "niigata.niigata.jp", 3, false}, + {1, "ojiya.niigata.jp", 3, false}, + {1, "omi.niigata.jp", 3, false}, + {1, "sado.niigata.jp", 3, false}, + {1, "sanjo.niigata.jp", 3, false}, + {1, "seiro.niigata.jp", 3, false}, + {1, "seirou.niigata.jp", 3, false}, + {1, "sekikawa.niigata.jp", 3, false}, + {1, "shibata.niigata.jp", 3, false}, + {1, "tagami.niigata.jp", 3, false}, + {1, "tainai.niigata.jp", 3, false}, + {1, "tochio.niigata.jp", 3, false}, + {1, "tokamachi.niigata.jp", 3, false}, + {1, "tsubame.niigata.jp", 3, false}, + {1, "tsunan.niigata.jp", 3, false}, + {1, "uonuma.niigata.jp", 3, false}, + {1, "yahiko.niigata.jp", 3, false}, + {1, "yoita.niigata.jp", 3, false}, + {1, "yuzawa.niigata.jp", 3, false}, + {1, "beppu.oita.jp", 3, false}, + {1, "bungoono.oita.jp", 3, false}, + {1, "bungotakada.oita.jp", 3, false}, + {1, "hasama.oita.jp", 3, false}, + {1, "hiji.oita.jp", 3, false}, + {1, "himeshima.oita.jp", 3, false}, + {1, "hita.oita.jp", 3, false}, + {1, "kamitsue.oita.jp", 3, false}, + {1, "kokonoe.oita.jp", 3, false}, + {1, "kuju.oita.jp", 3, false}, + {1, "kunisaki.oita.jp", 3, false}, + {1, "kusu.oita.jp", 3, false}, + {1, "oita.oita.jp", 3, false}, + {1, "saiki.oita.jp", 3, false}, + {1, "taketa.oita.jp", 3, false}, + {1, "tsukumi.oita.jp", 3, false}, + {1, "usa.oita.jp", 3, false}, + {1, "usuki.oita.jp", 3, false}, + {1, "yufu.oita.jp", 3, false}, + {1, "akaiwa.okayama.jp", 3, false}, + {1, "asakuchi.okayama.jp", 3, false}, + {1, "bizen.okayama.jp", 3, false}, + {1, "hayashima.okayama.jp", 3, false}, + {1, "ibara.okayama.jp", 3, false}, + {1, "kagamino.okayama.jp", 3, false}, + {1, "kasaoka.okayama.jp", 3, false}, + {1, "kibichuo.okayama.jp", 3, false}, + {1, "kumenan.okayama.jp", 3, false}, + {1, "kurashiki.okayama.jp", 3, false}, + {1, "maniwa.okayama.jp", 3, false}, + {1, "misaki.okayama.jp", 3, false}, + {1, "nagi.okayama.jp", 3, false}, + {1, "niimi.okayama.jp", 3, false}, + {1, "nishiawakura.okayama.jp", 3, false}, + {1, "okayama.okayama.jp", 3, false}, + {1, "satosho.okayama.jp", 3, false}, + {1, "setouchi.okayama.jp", 3, false}, + {1, "shinjo.okayama.jp", 3, false}, + {1, "shoo.okayama.jp", 3, false}, + {1, "soja.okayama.jp", 3, false}, + {1, "takahashi.okayama.jp", 3, false}, + {1, "tamano.okayama.jp", 3, false}, + {1, "tsuyama.okayama.jp", 3, false}, + {1, "wake.okayama.jp", 3, false}, + {1, "yakage.okayama.jp", 3, false}, + {1, "aguni.okinawa.jp", 3, false}, + {1, "ginowan.okinawa.jp", 3, false}, + {1, "ginoza.okinawa.jp", 3, false}, + {1, "gushikami.okinawa.jp", 3, false}, + {1, "haebaru.okinawa.jp", 3, false}, + {1, "higashi.okinawa.jp", 3, false}, + {1, "hirara.okinawa.jp", 3, false}, + {1, "iheya.okinawa.jp", 3, false}, + {1, "ishigaki.okinawa.jp", 3, false}, + {1, "ishikawa.okinawa.jp", 3, false}, + {1, "itoman.okinawa.jp", 3, false}, + {1, "izena.okinawa.jp", 3, false}, + {1, "kadena.okinawa.jp", 3, false}, + {1, "kin.okinawa.jp", 3, false}, + {1, "kitadaito.okinawa.jp", 3, false}, + {1, "kitanakagusuku.okinawa.jp", 3, false}, + {1, "kumejima.okinawa.jp", 3, false}, + {1, "kunigami.okinawa.jp", 3, false}, + {1, "minamidaito.okinawa.jp", 3, false}, + {1, "motobu.okinawa.jp", 3, false}, + {1, "nago.okinawa.jp", 3, false}, + {1, "naha.okinawa.jp", 3, false}, + {1, "nakagusuku.okinawa.jp", 3, false}, + {1, "nakijin.okinawa.jp", 3, false}, + {1, "nanjo.okinawa.jp", 3, false}, + {1, "nishihara.okinawa.jp", 3, false}, + {1, "ogimi.okinawa.jp", 3, false}, + {1, "okinawa.okinawa.jp", 3, false}, + {1, "onna.okinawa.jp", 3, false}, + {1, "shimoji.okinawa.jp", 3, false}, + {1, "taketomi.okinawa.jp", 3, false}, + {1, "tarama.okinawa.jp", 3, false}, + {1, "tokashiki.okinawa.jp", 3, false}, + {1, "tomigusuku.okinawa.jp", 3, false}, + {1, "tonaki.okinawa.jp", 3, false}, + {1, "urasoe.okinawa.jp", 3, false}, + {1, "uruma.okinawa.jp", 3, false}, + {1, "yaese.okinawa.jp", 3, false}, + {1, "yomitan.okinawa.jp", 3, false}, + {1, "yonabaru.okinawa.jp", 3, false}, + {1, "yonaguni.okinawa.jp", 3, false}, + {1, "zamami.okinawa.jp", 3, false}, + {1, "abeno.osaka.jp", 3, false}, + {1, "chihayaakasaka.osaka.jp", 3, false}, + {1, "chuo.osaka.jp", 3, false}, + {1, "daito.osaka.jp", 3, false}, + {1, "fujiidera.osaka.jp", 3, false}, + {1, "habikino.osaka.jp", 3, false}, + {1, "hannan.osaka.jp", 3, false}, + {1, "higashiosaka.osaka.jp", 3, false}, + {1, "higashisumiyoshi.osaka.jp", 3, false}, + {1, "higashiyodogawa.osaka.jp", 3, false}, + {1, "hirakata.osaka.jp", 3, false}, + {1, "ibaraki.osaka.jp", 3, false}, + {1, "ikeda.osaka.jp", 3, false}, + {1, "izumi.osaka.jp", 3, false}, + {1, "izumiotsu.osaka.jp", 3, false}, + {1, "izumisano.osaka.jp", 3, false}, + {1, "kadoma.osaka.jp", 3, false}, + {1, "kaizuka.osaka.jp", 3, false}, + {1, "kanan.osaka.jp", 3, false}, + {1, "kashiwara.osaka.jp", 3, false}, + {1, "katano.osaka.jp", 3, false}, + {1, "kawachinagano.osaka.jp", 3, false}, + {1, "kishiwada.osaka.jp", 3, false}, + {1, "kita.osaka.jp", 3, false}, + {1, "kumatori.osaka.jp", 3, false}, + {1, "matsubara.osaka.jp", 3, false}, + {1, "minato.osaka.jp", 3, false}, + {1, "minoh.osaka.jp", 3, false}, + {1, "misaki.osaka.jp", 3, false}, + {1, "moriguchi.osaka.jp", 3, false}, + {1, "neyagawa.osaka.jp", 3, false}, + {1, "nishi.osaka.jp", 3, false}, + {1, "nose.osaka.jp", 3, false}, + {1, "osakasayama.osaka.jp", 3, false}, + {1, "sakai.osaka.jp", 3, false}, + {1, "sayama.osaka.jp", 3, false}, + {1, "sennan.osaka.jp", 3, false}, + {1, "settsu.osaka.jp", 3, false}, + {1, "shijonawate.osaka.jp", 3, false}, + {1, "shimamoto.osaka.jp", 3, false}, + {1, "suita.osaka.jp", 3, false}, + {1, "tadaoka.osaka.jp", 3, false}, + {1, "taishi.osaka.jp", 3, false}, + {1, "tajiri.osaka.jp", 3, false}, + {1, "takaishi.osaka.jp", 3, false}, + {1, "takatsuki.osaka.jp", 3, false}, + {1, "tondabayashi.osaka.jp", 3, false}, + {1, "toyonaka.osaka.jp", 3, false}, + {1, "toyono.osaka.jp", 3, false}, + {1, "yao.osaka.jp", 3, false}, + {1, "ariake.saga.jp", 3, false}, + {1, "arita.saga.jp", 3, false}, + {1, "fukudomi.saga.jp", 3, false}, + {1, "genkai.saga.jp", 3, false}, + {1, "hamatama.saga.jp", 3, false}, + {1, "hizen.saga.jp", 3, false}, + {1, "imari.saga.jp", 3, false}, + {1, "kamimine.saga.jp", 3, false}, + {1, "kanzaki.saga.jp", 3, false}, + {1, "karatsu.saga.jp", 3, false}, + {1, "kashima.saga.jp", 3, false}, + {1, "kitagata.saga.jp", 3, false}, + {1, "kitahata.saga.jp", 3, false}, + {1, "kiyama.saga.jp", 3, false}, + {1, "kouhoku.saga.jp", 3, false}, + {1, "kyuragi.saga.jp", 3, false}, + {1, "nishiarita.saga.jp", 3, false}, + {1, "ogi.saga.jp", 3, false}, + {1, "omachi.saga.jp", 3, false}, + {1, "ouchi.saga.jp", 3, false}, + {1, "saga.saga.jp", 3, false}, + {1, "shiroishi.saga.jp", 3, false}, + {1, "taku.saga.jp", 3, false}, + {1, "tara.saga.jp", 3, false}, + {1, "tosu.saga.jp", 3, false}, + {1, "yoshinogari.saga.jp", 3, false}, + {1, "arakawa.saitama.jp", 3, false}, + {1, "asaka.saitama.jp", 3, false}, + {1, "chichibu.saitama.jp", 3, false}, + {1, "fujimi.saitama.jp", 3, false}, + {1, "fujimino.saitama.jp", 3, false}, + {1, "fukaya.saitama.jp", 3, false}, + {1, "hanno.saitama.jp", 3, false}, + {1, "hanyu.saitama.jp", 3, false}, + {1, "hasuda.saitama.jp", 3, false}, + {1, "hatogaya.saitama.jp", 3, false}, + {1, "hatoyama.saitama.jp", 3, false}, + {1, "hidaka.saitama.jp", 3, false}, + {1, "higashichichibu.saitama.jp", 3, false}, + {1, "higashimatsuyama.saitama.jp", 3, false}, + {1, "honjo.saitama.jp", 3, false}, + {1, "ina.saitama.jp", 3, false}, + {1, "iruma.saitama.jp", 3, false}, + {1, "iwatsuki.saitama.jp", 3, false}, + {1, "kamiizumi.saitama.jp", 3, false}, + {1, "kamikawa.saitama.jp", 3, false}, + {1, "kamisato.saitama.jp", 3, false}, + {1, "kasukabe.saitama.jp", 3, false}, + {1, "kawagoe.saitama.jp", 3, false}, + {1, "kawaguchi.saitama.jp", 3, false}, + {1, "kawajima.saitama.jp", 3, false}, + {1, "kazo.saitama.jp", 3, false}, + {1, "kitamoto.saitama.jp", 3, false}, + {1, "koshigaya.saitama.jp", 3, false}, + {1, "kounosu.saitama.jp", 3, false}, + {1, "kuki.saitama.jp", 3, false}, + {1, "kumagaya.saitama.jp", 3, false}, + {1, "matsubushi.saitama.jp", 3, false}, + {1, "minano.saitama.jp", 3, false}, + {1, "misato.saitama.jp", 3, false}, + {1, "miyashiro.saitama.jp", 3, false}, + {1, "miyoshi.saitama.jp", 3, false}, + {1, "moroyama.saitama.jp", 3, false}, + {1, "nagatoro.saitama.jp", 3, false}, + {1, "namegawa.saitama.jp", 3, false}, + {1, "niiza.saitama.jp", 3, false}, + {1, "ogano.saitama.jp", 3, false}, + {1, "ogawa.saitama.jp", 3, false}, + {1, "ogose.saitama.jp", 3, false}, + {1, "okegawa.saitama.jp", 3, false}, + {1, "omiya.saitama.jp", 3, false}, + {1, "otaki.saitama.jp", 3, false}, + {1, "ranzan.saitama.jp", 3, false}, + {1, "ryokami.saitama.jp", 3, false}, + {1, "saitama.saitama.jp", 3, false}, + {1, "sakado.saitama.jp", 3, false}, + {1, "satte.saitama.jp", 3, false}, + {1, "sayama.saitama.jp", 3, false}, + {1, "shiki.saitama.jp", 3, false}, + {1, "shiraoka.saitama.jp", 3, false}, + {1, "soka.saitama.jp", 3, false}, + {1, "sugito.saitama.jp", 3, false}, + {1, "toda.saitama.jp", 3, false}, + {1, "tokigawa.saitama.jp", 3, false}, + {1, "tokorozawa.saitama.jp", 3, false}, + {1, "tsurugashima.saitama.jp", 3, false}, + {1, "urawa.saitama.jp", 3, false}, + {1, "warabi.saitama.jp", 3, false}, + {1, "yashio.saitama.jp", 3, false}, + {1, "yokoze.saitama.jp", 3, false}, + {1, "yono.saitama.jp", 3, false}, + {1, "yorii.saitama.jp", 3, false}, + {1, "yoshida.saitama.jp", 3, false}, + {1, "yoshikawa.saitama.jp", 3, false}, + {1, "yoshimi.saitama.jp", 3, false}, + {1, "aisho.shiga.jp", 3, false}, + {1, "gamo.shiga.jp", 3, false}, + {1, "higashiomi.shiga.jp", 3, false}, + {1, "hikone.shiga.jp", 3, false}, + {1, "koka.shiga.jp", 3, false}, + {1, "konan.shiga.jp", 3, false}, + {1, "kosei.shiga.jp", 3, false}, + {1, "koto.shiga.jp", 3, false}, + {1, "kusatsu.shiga.jp", 3, false}, + {1, "maibara.shiga.jp", 3, false}, + {1, "moriyama.shiga.jp", 3, false}, + {1, "nagahama.shiga.jp", 3, false}, + {1, "nishiazai.shiga.jp", 3, false}, + {1, "notogawa.shiga.jp", 3, false}, + {1, "omihachiman.shiga.jp", 3, false}, + {1, "otsu.shiga.jp", 3, false}, + {1, "ritto.shiga.jp", 3, false}, + {1, "ryuoh.shiga.jp", 3, false}, + {1, "takashima.shiga.jp", 3, false}, + {1, "takatsuki.shiga.jp", 3, false}, + {1, "torahime.shiga.jp", 3, false}, + {1, "toyosato.shiga.jp", 3, false}, + {1, "yasu.shiga.jp", 3, false}, + {1, "akagi.shimane.jp", 3, false}, + {1, "ama.shimane.jp", 3, false}, + {1, "gotsu.shimane.jp", 3, false}, + {1, "hamada.shimane.jp", 3, false}, + {1, "higashiizumo.shimane.jp", 3, false}, + {1, "hikawa.shimane.jp", 3, false}, + {1, "hikimi.shimane.jp", 3, false}, + {1, "izumo.shimane.jp", 3, false}, + {1, "kakinoki.shimane.jp", 3, false}, + {1, "masuda.shimane.jp", 3, false}, + {1, "matsue.shimane.jp", 3, false}, + {1, "misato.shimane.jp", 3, false}, + {1, "nishinoshima.shimane.jp", 3, false}, + {1, "ohda.shimane.jp", 3, false}, + {1, "okinoshima.shimane.jp", 3, false}, + {1, "okuizumo.shimane.jp", 3, false}, + {1, "shimane.shimane.jp", 3, false}, + {1, "tamayu.shimane.jp", 3, false}, + {1, "tsuwano.shimane.jp", 3, false}, + {1, "unnan.shimane.jp", 3, false}, + {1, "yakumo.shimane.jp", 3, false}, + {1, "yasugi.shimane.jp", 3, false}, + {1, "yatsuka.shimane.jp", 3, false}, + {1, "arai.shizuoka.jp", 3, false}, + {1, "atami.shizuoka.jp", 3, false}, + {1, "fuji.shizuoka.jp", 3, false}, + {1, "fujieda.shizuoka.jp", 3, false}, + {1, "fujikawa.shizuoka.jp", 3, false}, + {1, "fujinomiya.shizuoka.jp", 3, false}, + {1, "fukuroi.shizuoka.jp", 3, false}, + {1, "gotemba.shizuoka.jp", 3, false}, + {1, "haibara.shizuoka.jp", 3, false}, + {1, "hamamatsu.shizuoka.jp", 3, false}, + {1, "higashiizu.shizuoka.jp", 3, false}, + {1, "ito.shizuoka.jp", 3, false}, + {1, "iwata.shizuoka.jp", 3, false}, + {1, "izu.shizuoka.jp", 3, false}, + {1, "izunokuni.shizuoka.jp", 3, false}, + {1, "kakegawa.shizuoka.jp", 3, false}, + {1, "kannami.shizuoka.jp", 3, false}, + {1, "kawanehon.shizuoka.jp", 3, false}, + {1, "kawazu.shizuoka.jp", 3, false}, + {1, "kikugawa.shizuoka.jp", 3, false}, + {1, "kosai.shizuoka.jp", 3, false}, + {1, "makinohara.shizuoka.jp", 3, false}, + {1, "matsuzaki.shizuoka.jp", 3, false}, + {1, "minamiizu.shizuoka.jp", 3, false}, + {1, "mishima.shizuoka.jp", 3, false}, + {1, "morimachi.shizuoka.jp", 3, false}, + {1, "nishiizu.shizuoka.jp", 3, false}, + {1, "numazu.shizuoka.jp", 3, false}, + {1, "omaezaki.shizuoka.jp", 3, false}, + {1, "shimada.shizuoka.jp", 3, false}, + {1, "shimizu.shizuoka.jp", 3, false}, + {1, "shimoda.shizuoka.jp", 3, false}, + {1, "shizuoka.shizuoka.jp", 3, false}, + {1, "susono.shizuoka.jp", 3, false}, + {1, "yaizu.shizuoka.jp", 3, false}, + {1, "yoshida.shizuoka.jp", 3, false}, + {1, "ashikaga.tochigi.jp", 3, false}, + {1, "bato.tochigi.jp", 3, false}, + {1, "haga.tochigi.jp", 3, false}, + {1, "ichikai.tochigi.jp", 3, false}, + {1, "iwafune.tochigi.jp", 3, false}, + {1, "kaminokawa.tochigi.jp", 3, false}, + {1, "kanuma.tochigi.jp", 3, false}, + {1, "karasuyama.tochigi.jp", 3, false}, + {1, "kuroiso.tochigi.jp", 3, false}, + {1, "mashiko.tochigi.jp", 3, false}, + {1, "mibu.tochigi.jp", 3, false}, + {1, "moka.tochigi.jp", 3, false}, + {1, "motegi.tochigi.jp", 3, false}, + {1, "nasu.tochigi.jp", 3, false}, + {1, "nasushiobara.tochigi.jp", 3, false}, + {1, "nikko.tochigi.jp", 3, false}, + {1, "nishikata.tochigi.jp", 3, false}, + {1, "nogi.tochigi.jp", 3, false}, + {1, "ohira.tochigi.jp", 3, false}, + {1, "ohtawara.tochigi.jp", 3, false}, + {1, "oyama.tochigi.jp", 3, false}, + {1, "sakura.tochigi.jp", 3, false}, + {1, "sano.tochigi.jp", 3, false}, + {1, "shimotsuke.tochigi.jp", 3, false}, + {1, "shioya.tochigi.jp", 3, false}, + {1, "takanezawa.tochigi.jp", 3, false}, + {1, "tochigi.tochigi.jp", 3, false}, + {1, "tsuga.tochigi.jp", 3, false}, + {1, "ujiie.tochigi.jp", 3, false}, + {1, "utsunomiya.tochigi.jp", 3, false}, + {1, "yaita.tochigi.jp", 3, false}, + {1, "aizumi.tokushima.jp", 3, false}, + {1, "anan.tokushima.jp", 3, false}, + {1, "ichiba.tokushima.jp", 3, false}, + {1, "itano.tokushima.jp", 3, false}, + {1, "kainan.tokushima.jp", 3, false}, + {1, "komatsushima.tokushima.jp", 3, false}, + {1, "matsushige.tokushima.jp", 3, false}, + {1, "mima.tokushima.jp", 3, false}, + {1, "minami.tokushima.jp", 3, false}, + {1, "miyoshi.tokushima.jp", 3, false}, + {1, "mugi.tokushima.jp", 3, false}, + {1, "nakagawa.tokushima.jp", 3, false}, + {1, "naruto.tokushima.jp", 3, false}, + {1, "sanagochi.tokushima.jp", 3, false}, + {1, "shishikui.tokushima.jp", 3, false}, + {1, "tokushima.tokushima.jp", 3, false}, + {1, "wajiki.tokushima.jp", 3, false}, + {1, "adachi.tokyo.jp", 3, false}, + {1, "akiruno.tokyo.jp", 3, false}, + {1, "akishima.tokyo.jp", 3, false}, + {1, "aogashima.tokyo.jp", 3, false}, + {1, "arakawa.tokyo.jp", 3, false}, + {1, "bunkyo.tokyo.jp", 3, false}, + {1, "chiyoda.tokyo.jp", 3, false}, + {1, "chofu.tokyo.jp", 3, false}, + {1, "chuo.tokyo.jp", 3, false}, + {1, "edogawa.tokyo.jp", 3, false}, + {1, "fuchu.tokyo.jp", 3, false}, + {1, "fussa.tokyo.jp", 3, false}, + {1, "hachijo.tokyo.jp", 3, false}, + {1, "hachioji.tokyo.jp", 3, false}, + {1, "hamura.tokyo.jp", 3, false}, + {1, "higashikurume.tokyo.jp", 3, false}, + {1, "higashimurayama.tokyo.jp", 3, false}, + {1, "higashiyamato.tokyo.jp", 3, false}, + {1, "hino.tokyo.jp", 3, false}, + {1, "hinode.tokyo.jp", 3, false}, + {1, "hinohara.tokyo.jp", 3, false}, + {1, "inagi.tokyo.jp", 3, false}, + {1, "itabashi.tokyo.jp", 3, false}, + {1, "katsushika.tokyo.jp", 3, false}, + {1, "kita.tokyo.jp", 3, false}, + {1, "kiyose.tokyo.jp", 3, false}, + {1, "kodaira.tokyo.jp", 3, false}, + {1, "koganei.tokyo.jp", 3, false}, + {1, "kokubunji.tokyo.jp", 3, false}, + {1, "komae.tokyo.jp", 3, false}, + {1, "koto.tokyo.jp", 3, false}, + {1, "kouzushima.tokyo.jp", 3, false}, + {1, "kunitachi.tokyo.jp", 3, false}, + {1, "machida.tokyo.jp", 3, false}, + {1, "meguro.tokyo.jp", 3, false}, + {1, "minato.tokyo.jp", 3, false}, + {1, "mitaka.tokyo.jp", 3, false}, + {1, "mizuho.tokyo.jp", 3, false}, + {1, "musashimurayama.tokyo.jp", 3, false}, + {1, "musashino.tokyo.jp", 3, false}, + {1, "nakano.tokyo.jp", 3, false}, + {1, "nerima.tokyo.jp", 3, false}, + {1, "ogasawara.tokyo.jp", 3, false}, + {1, "okutama.tokyo.jp", 3, false}, + {1, "ome.tokyo.jp", 3, false}, + {1, "oshima.tokyo.jp", 3, false}, + {1, "ota.tokyo.jp", 3, false}, + {1, "setagaya.tokyo.jp", 3, false}, + {1, "shibuya.tokyo.jp", 3, false}, + {1, "shinagawa.tokyo.jp", 3, false}, + {1, "shinjuku.tokyo.jp", 3, false}, + {1, "suginami.tokyo.jp", 3, false}, + {1, "sumida.tokyo.jp", 3, false}, + {1, "tachikawa.tokyo.jp", 3, false}, + {1, "taito.tokyo.jp", 3, false}, + {1, "tama.tokyo.jp", 3, false}, + {1, "toshima.tokyo.jp", 3, false}, + {1, "chizu.tottori.jp", 3, false}, + {1, "hino.tottori.jp", 3, false}, + {1, "kawahara.tottori.jp", 3, false}, + {1, "koge.tottori.jp", 3, false}, + {1, "kotoura.tottori.jp", 3, false}, + {1, "misasa.tottori.jp", 3, false}, + {1, "nanbu.tottori.jp", 3, false}, + {1, "nichinan.tottori.jp", 3, false}, + {1, "sakaiminato.tottori.jp", 3, false}, + {1, "tottori.tottori.jp", 3, false}, + {1, "wakasa.tottori.jp", 3, false}, + {1, "yazu.tottori.jp", 3, false}, + {1, "yonago.tottori.jp", 3, false}, + {1, "asahi.toyama.jp", 3, false}, + {1, "fuchu.toyama.jp", 3, false}, + {1, "fukumitsu.toyama.jp", 3, false}, + {1, "funahashi.toyama.jp", 3, false}, + {1, "himi.toyama.jp", 3, false}, + {1, "imizu.toyama.jp", 3, false}, + {1, "inami.toyama.jp", 3, false}, + {1, "johana.toyama.jp", 3, false}, + {1, "kamiichi.toyama.jp", 3, false}, + {1, "kurobe.toyama.jp", 3, false}, + {1, "nakaniikawa.toyama.jp", 3, false}, + {1, "namerikawa.toyama.jp", 3, false}, + {1, "nanto.toyama.jp", 3, false}, + {1, "nyuzen.toyama.jp", 3, false}, + {1, "oyabe.toyama.jp", 3, false}, + {1, "taira.toyama.jp", 3, false}, + {1, "takaoka.toyama.jp", 3, false}, + {1, "tateyama.toyama.jp", 3, false}, + {1, "toga.toyama.jp", 3, false}, + {1, "tonami.toyama.jp", 3, false}, + {1, "toyama.toyama.jp", 3, false}, + {1, "unazuki.toyama.jp", 3, false}, + {1, "uozu.toyama.jp", 3, false}, + {1, "yamada.toyama.jp", 3, false}, + {1, "arida.wakayama.jp", 3, false}, + {1, "aridagawa.wakayama.jp", 3, false}, + {1, "gobo.wakayama.jp", 3, false}, + {1, "hashimoto.wakayama.jp", 3, false}, + {1, "hidaka.wakayama.jp", 3, false}, + {1, "hirogawa.wakayama.jp", 3, false}, + {1, "inami.wakayama.jp", 3, false}, + {1, "iwade.wakayama.jp", 3, false}, + {1, "kainan.wakayama.jp", 3, false}, + {1, "kamitonda.wakayama.jp", 3, false}, + {1, "katsuragi.wakayama.jp", 3, false}, + {1, "kimino.wakayama.jp", 3, false}, + {1, "kinokawa.wakayama.jp", 3, false}, + {1, "kitayama.wakayama.jp", 3, false}, + {1, "koya.wakayama.jp", 3, false}, + {1, "koza.wakayama.jp", 3, false}, + {1, "kozagawa.wakayama.jp", 3, false}, + {1, "kudoyama.wakayama.jp", 3, false}, + {1, "kushimoto.wakayama.jp", 3, false}, + {1, "mihama.wakayama.jp", 3, false}, + {1, "misato.wakayama.jp", 3, false}, + {1, "nachikatsuura.wakayama.jp", 3, false}, + {1, "shingu.wakayama.jp", 3, false}, + {1, "shirahama.wakayama.jp", 3, false}, + {1, "taiji.wakayama.jp", 3, false}, + {1, "tanabe.wakayama.jp", 3, false}, + {1, "wakayama.wakayama.jp", 3, false}, + {1, "yuasa.wakayama.jp", 3, false}, + {1, "yura.wakayama.jp", 3, false}, + {1, "asahi.yamagata.jp", 3, false}, + {1, "funagata.yamagata.jp", 3, false}, + {1, "higashine.yamagata.jp", 3, false}, + {1, "iide.yamagata.jp", 3, false}, + {1, "kahoku.yamagata.jp", 3, false}, + {1, "kaminoyama.yamagata.jp", 3, false}, + {1, "kaneyama.yamagata.jp", 3, false}, + {1, "kawanishi.yamagata.jp", 3, false}, + {1, "mamurogawa.yamagata.jp", 3, false}, + {1, "mikawa.yamagata.jp", 3, false}, + {1, "murayama.yamagata.jp", 3, false}, + {1, "nagai.yamagata.jp", 3, false}, + {1, "nakayama.yamagata.jp", 3, false}, + {1, "nanyo.yamagata.jp", 3, false}, + {1, "nishikawa.yamagata.jp", 3, false}, + {1, "obanazawa.yamagata.jp", 3, false}, + {1, "oe.yamagata.jp", 3, false}, + {1, "oguni.yamagata.jp", 3, false}, + {1, "ohkura.yamagata.jp", 3, false}, + {1, "oishida.yamagata.jp", 3, false}, + {1, "sagae.yamagata.jp", 3, false}, + {1, "sakata.yamagata.jp", 3, false}, + {1, "sakegawa.yamagata.jp", 3, false}, + {1, "shinjo.yamagata.jp", 3, false}, + {1, "shirataka.yamagata.jp", 3, false}, + {1, "shonai.yamagata.jp", 3, false}, + {1, "takahata.yamagata.jp", 3, false}, + {1, "tendo.yamagata.jp", 3, false}, + {1, "tozawa.yamagata.jp", 3, false}, + {1, "tsuruoka.yamagata.jp", 3, false}, + {1, "yamagata.yamagata.jp", 3, false}, + {1, "yamanobe.yamagata.jp", 3, false}, + {1, "yonezawa.yamagata.jp", 3, false}, + {1, "yuza.yamagata.jp", 3, false}, + {1, "abu.yamaguchi.jp", 3, false}, + {1, "hagi.yamaguchi.jp", 3, false}, + {1, "hikari.yamaguchi.jp", 3, false}, + {1, "hofu.yamaguchi.jp", 3, false}, + {1, "iwakuni.yamaguchi.jp", 3, false}, + {1, "kudamatsu.yamaguchi.jp", 3, false}, + {1, "mitou.yamaguchi.jp", 3, false}, + {1, "nagato.yamaguchi.jp", 3, false}, + {1, "oshima.yamaguchi.jp", 3, false}, + {1, "shimonoseki.yamaguchi.jp", 3, false}, + {1, "shunan.yamaguchi.jp", 3, false}, + {1, "tabuse.yamaguchi.jp", 3, false}, + {1, "tokuyama.yamaguchi.jp", 3, false}, + {1, "toyota.yamaguchi.jp", 3, false}, + {1, "ube.yamaguchi.jp", 3, false}, + {1, "yuu.yamaguchi.jp", 3, false}, + {1, "chuo.yamanashi.jp", 3, false}, + {1, "doshi.yamanashi.jp", 3, false}, + {1, "fuefuki.yamanashi.jp", 3, false}, + {1, "fujikawa.yamanashi.jp", 3, false}, + {1, "fujikawaguchiko.yamanashi.jp", 3, false}, + {1, "fujiyoshida.yamanashi.jp", 3, false}, + {1, "hayakawa.yamanashi.jp", 3, false}, + {1, "hokuto.yamanashi.jp", 3, false}, + {1, "ichikawamisato.yamanashi.jp", 3, false}, + {1, "kai.yamanashi.jp", 3, false}, + {1, "kofu.yamanashi.jp", 3, false}, + {1, "koshu.yamanashi.jp", 3, false}, + {1, "kosuge.yamanashi.jp", 3, false}, + {1, "minami-alps.yamanashi.jp", 3, false}, + {1, "minobu.yamanashi.jp", 3, false}, + {1, "nakamichi.yamanashi.jp", 3, false}, + {1, "nanbu.yamanashi.jp", 3, false}, + {1, "narusawa.yamanashi.jp", 3, false}, + {1, "nirasaki.yamanashi.jp", 3, false}, + {1, "nishikatsura.yamanashi.jp", 3, false}, + {1, "oshino.yamanashi.jp", 3, false}, + {1, "otsuki.yamanashi.jp", 3, false}, + {1, "showa.yamanashi.jp", 3, false}, + {1, "tabayama.yamanashi.jp", 3, false}, + {1, "tsuru.yamanashi.jp", 3, false}, + {1, "uenohara.yamanashi.jp", 3, false}, + {1, "yamanakako.yamanashi.jp", 3, false}, + {1, "yamanashi.yamanashi.jp", 3, false}, + {1, "ke", 1, false}, + {1, "ac.ke", 2, false}, + {1, "co.ke", 2, false}, + {1, "go.ke", 2, false}, + {1, "info.ke", 2, false}, + {1, "me.ke", 2, false}, + {1, "mobi.ke", 2, false}, + {1, "ne.ke", 2, false}, + {1, "or.ke", 2, false}, + {1, "sc.ke", 2, false}, + {1, "kg", 1, false}, + {1, "org.kg", 2, false}, + {1, "net.kg", 2, false}, + {1, "com.kg", 2, false}, + {1, "edu.kg", 2, false}, + {1, "gov.kg", 2, false}, + {1, "mil.kg", 2, false}, + {2, "kh", 2, false}, + {1, "ki", 1, false}, + {1, "edu.ki", 2, false}, + {1, "biz.ki", 2, false}, + {1, "net.ki", 2, false}, + {1, "org.ki", 2, false}, + {1, "gov.ki", 2, false}, + {1, "info.ki", 2, false}, + {1, "com.ki", 2, false}, + {1, "km", 1, false}, + {1, "org.km", 2, false}, + {1, "nom.km", 2, false}, + {1, "gov.km", 2, false}, + {1, "prd.km", 2, false}, + {1, "tm.km", 2, false}, + {1, "edu.km", 2, false}, + {1, "mil.km", 2, false}, + {1, "ass.km", 2, false}, + {1, "com.km", 2, false}, + {1, "coop.km", 2, false}, + {1, "asso.km", 2, false}, + {1, "presse.km", 2, false}, + {1, "medecin.km", 2, false}, + {1, "notaires.km", 2, false}, + {1, "pharmaciens.km", 2, false}, + {1, "veterinaire.km", 2, false}, + {1, "gouv.km", 2, false}, + {1, "kn", 1, false}, + {1, "net.kn", 2, false}, + {1, "org.kn", 2, false}, + {1, "edu.kn", 2, false}, + {1, "gov.kn", 2, false}, + {1, "kp", 1, false}, + {1, "com.kp", 2, false}, + {1, "edu.kp", 2, false}, + {1, "gov.kp", 2, false}, + {1, "org.kp", 2, false}, + {1, "rep.kp", 2, false}, + {1, "tra.kp", 2, false}, + {1, "kr", 1, false}, + {1, "ac.kr", 2, false}, + {1, "co.kr", 2, false}, + {1, "es.kr", 2, false}, + {1, "go.kr", 2, false}, + {1, "hs.kr", 2, false}, + {1, "kg.kr", 2, false}, + {1, "mil.kr", 2, false}, + {1, "ms.kr", 2, false}, + {1, "ne.kr", 2, false}, + {1, "or.kr", 2, false}, + {1, "pe.kr", 2, false}, + {1, "re.kr", 2, false}, + {1, "sc.kr", 2, false}, + {1, "busan.kr", 2, false}, + {1, "chungbuk.kr", 2, false}, + {1, "chungnam.kr", 2, false}, + {1, "daegu.kr", 2, false}, + {1, "daejeon.kr", 2, false}, + {1, "gangwon.kr", 2, false}, + {1, "gwangju.kr", 2, false}, + {1, "gyeongbuk.kr", 2, false}, + {1, "gyeonggi.kr", 2, false}, + {1, "gyeongnam.kr", 2, false}, + {1, "incheon.kr", 2, false}, + {1, "jeju.kr", 2, false}, + {1, "jeonbuk.kr", 2, false}, + {1, "jeonnam.kr", 2, false}, + {1, "seoul.kr", 2, false}, + {1, "ulsan.kr", 2, false}, + {1, "kw", 1, false}, + {1, "com.kw", 2, false}, + {1, "edu.kw", 2, false}, + {1, "emb.kw", 2, false}, + {1, "gov.kw", 2, false}, + {1, "ind.kw", 2, false}, + {1, "net.kw", 2, false}, + {1, "org.kw", 2, false}, + {1, "ky", 1, false}, + {1, "edu.ky", 2, false}, + {1, "gov.ky", 2, false}, + {1, "com.ky", 2, false}, + {1, "org.ky", 2, false}, + {1, "net.ky", 2, false}, + {1, "kz", 1, false}, + {1, "org.kz", 2, false}, + {1, "edu.kz", 2, false}, + {1, "net.kz", 2, false}, + {1, "gov.kz", 2, false}, + {1, "mil.kz", 2, false}, + {1, "com.kz", 2, false}, + {1, "la", 1, false}, + {1, "int.la", 2, false}, + {1, "net.la", 2, false}, + {1, "info.la", 2, false}, + {1, "edu.la", 2, false}, + {1, "gov.la", 2, false}, + {1, "per.la", 2, false}, + {1, "com.la", 2, false}, + {1, "org.la", 2, false}, + {1, "lb", 1, false}, + {1, "com.lb", 2, false}, + {1, "edu.lb", 2, false}, + {1, "gov.lb", 2, false}, + {1, "net.lb", 2, false}, + {1, "org.lb", 2, false}, + {1, "lc", 1, false}, + {1, "com.lc", 2, false}, + {1, "net.lc", 2, false}, + {1, "co.lc", 2, false}, + {1, "org.lc", 2, false}, + {1, "edu.lc", 2, false}, + {1, "gov.lc", 2, false}, + {1, "li", 1, false}, + {1, "lk", 1, false}, + {1, "gov.lk", 2, false}, + {1, "sch.lk", 2, false}, + {1, "net.lk", 2, false}, + {1, "int.lk", 2, false}, + {1, "com.lk", 2, false}, + {1, "org.lk", 2, false}, + {1, "edu.lk", 2, false}, + {1, "ngo.lk", 2, false}, + {1, "soc.lk", 2, false}, + {1, "web.lk", 2, false}, + {1, "ltd.lk", 2, false}, + {1, "assn.lk", 2, false}, + {1, "grp.lk", 2, false}, + {1, "hotel.lk", 2, false}, + {1, "ac.lk", 2, false}, + {1, "lr", 1, false}, + {1, "com.lr", 2, false}, + {1, "edu.lr", 2, false}, + {1, "gov.lr", 2, false}, + {1, "org.lr", 2, false}, + {1, "net.lr", 2, false}, + {1, "ls", 1, false}, + {1, "ac.ls", 2, false}, + {1, "biz.ls", 2, false}, + {1, "co.ls", 2, false}, + {1, "edu.ls", 2, false}, + {1, "gov.ls", 2, false}, + {1, "info.ls", 2, false}, + {1, "net.ls", 2, false}, + {1, "org.ls", 2, false}, + {1, "sc.ls", 2, false}, + {1, "lt", 1, false}, + {1, "gov.lt", 2, false}, + {1, "lu", 1, false}, + {1, "lv", 1, false}, + {1, "com.lv", 2, false}, + {1, "edu.lv", 2, false}, + {1, "gov.lv", 2, false}, + {1, "org.lv", 2, false}, + {1, "mil.lv", 2, false}, + {1, "id.lv", 2, false}, + {1, "net.lv", 2, false}, + {1, "asn.lv", 2, false}, + {1, "conf.lv", 2, false}, + {1, "ly", 1, false}, + {1, "com.ly", 2, false}, + {1, "net.ly", 2, false}, + {1, "gov.ly", 2, false}, + {1, "plc.ly", 2, false}, + {1, "edu.ly", 2, false}, + {1, "sch.ly", 2, false}, + {1, "med.ly", 2, false}, + {1, "org.ly", 2, false}, + {1, "id.ly", 2, false}, + {1, "ma", 1, false}, + {1, "co.ma", 2, false}, + {1, "net.ma", 2, false}, + {1, "gov.ma", 2, false}, + {1, "org.ma", 2, false}, + {1, "ac.ma", 2, false}, + {1, "press.ma", 2, false}, + {1, "mc", 1, false}, + {1, "tm.mc", 2, false}, + {1, "asso.mc", 2, false}, + {1, "md", 1, false}, + {1, "me", 1, false}, + {1, "co.me", 2, false}, + {1, "net.me", 2, false}, + {1, "org.me", 2, false}, + {1, "edu.me", 2, false}, + {1, "ac.me", 2, false}, + {1, "gov.me", 2, false}, + {1, "its.me", 2, false}, + {1, "priv.me", 2, false}, + {1, "mg", 1, false}, + {1, "org.mg", 2, false}, + {1, "nom.mg", 2, false}, + {1, "gov.mg", 2, false}, + {1, "prd.mg", 2, false}, + {1, "tm.mg", 2, false}, + {1, "edu.mg", 2, false}, + {1, "mil.mg", 2, false}, + {1, "com.mg", 2, false}, + {1, "co.mg", 2, false}, + {1, "mh", 1, false}, + {1, "mil", 1, false}, + {1, "mk", 1, false}, + {1, "com.mk", 2, false}, + {1, "org.mk", 2, false}, + {1, "net.mk", 2, false}, + {1, "edu.mk", 2, false}, + {1, "gov.mk", 2, false}, + {1, "inf.mk", 2, false}, + {1, "name.mk", 2, false}, + {1, "ml", 1, false}, + {1, "com.ml", 2, false}, + {1, "edu.ml", 2, false}, + {1, "gouv.ml", 2, false}, + {1, "gov.ml", 2, false}, + {1, "net.ml", 2, false}, + {1, "org.ml", 2, false}, + {1, "presse.ml", 2, false}, + {2, "mm", 2, false}, + {1, "mn", 1, false}, + {1, "gov.mn", 2, false}, + {1, "edu.mn", 2, false}, + {1, "org.mn", 2, false}, + {1, "mo", 1, false}, + {1, "com.mo", 2, false}, + {1, "net.mo", 2, false}, + {1, "org.mo", 2, false}, + {1, "edu.mo", 2, false}, + {1, "gov.mo", 2, false}, + {1, "mobi", 1, false}, + {1, "mp", 1, false}, + {1, "mq", 1, false}, + {1, "mr", 1, false}, + {1, "gov.mr", 2, false}, + {1, "ms", 1, false}, + {1, "com.ms", 2, false}, + {1, "edu.ms", 2, false}, + {1, "gov.ms", 2, false}, + {1, "net.ms", 2, false}, + {1, "org.ms", 2, false}, + {1, "mt", 1, false}, + {1, "com.mt", 2, false}, + {1, "edu.mt", 2, false}, + {1, "net.mt", 2, false}, + {1, "org.mt", 2, false}, + {1, "mu", 1, false}, + {1, "com.mu", 2, false}, + {1, "net.mu", 2, false}, + {1, "org.mu", 2, false}, + {1, "gov.mu", 2, false}, + {1, "ac.mu", 2, false}, + {1, "co.mu", 2, false}, + {1, "or.mu", 2, false}, + {1, "museum", 1, false}, + {1, "academy.museum", 2, false}, + {1, "agriculture.museum", 2, false}, + {1, "air.museum", 2, false}, + {1, "airguard.museum", 2, false}, + {1, "alabama.museum", 2, false}, + {1, "alaska.museum", 2, false}, + {1, "amber.museum", 2, false}, + {1, "ambulance.museum", 2, false}, + {1, "american.museum", 2, false}, + {1, "americana.museum", 2, false}, + {1, "americanantiques.museum", 2, false}, + {1, "americanart.museum", 2, false}, + {1, "amsterdam.museum", 2, false}, + {1, "and.museum", 2, false}, + {1, "annefrank.museum", 2, false}, + {1, "anthro.museum", 2, false}, + {1, "anthropology.museum", 2, false}, + {1, "antiques.museum", 2, false}, + {1, "aquarium.museum", 2, false}, + {1, "arboretum.museum", 2, false}, + {1, "archaeological.museum", 2, false}, + {1, "archaeology.museum", 2, false}, + {1, "architecture.museum", 2, false}, + {1, "art.museum", 2, false}, + {1, "artanddesign.museum", 2, false}, + {1, "artcenter.museum", 2, false}, + {1, "artdeco.museum", 2, false}, + {1, "arteducation.museum", 2, false}, + {1, "artgallery.museum", 2, false}, + {1, "arts.museum", 2, false}, + {1, "artsandcrafts.museum", 2, false}, + {1, "asmatart.museum", 2, false}, + {1, "assassination.museum", 2, false}, + {1, "assisi.museum", 2, false}, + {1, "association.museum", 2, false}, + {1, "astronomy.museum", 2, false}, + {1, "atlanta.museum", 2, false}, + {1, "austin.museum", 2, false}, + {1, "australia.museum", 2, false}, + {1, "automotive.museum", 2, false}, + {1, "aviation.museum", 2, false}, + {1, "axis.museum", 2, false}, + {1, "badajoz.museum", 2, false}, + {1, "baghdad.museum", 2, false}, + {1, "bahn.museum", 2, false}, + {1, "bale.museum", 2, false}, + {1, "baltimore.museum", 2, false}, + {1, "barcelona.museum", 2, false}, + {1, "baseball.museum", 2, false}, + {1, "basel.museum", 2, false}, + {1, "baths.museum", 2, false}, + {1, "bauern.museum", 2, false}, + {1, "beauxarts.museum", 2, false}, + {1, "beeldengeluid.museum", 2, false}, + {1, "bellevue.museum", 2, false}, + {1, "bergbau.museum", 2, false}, + {1, "berkeley.museum", 2, false}, + {1, "berlin.museum", 2, false}, + {1, "bern.museum", 2, false}, + {1, "bible.museum", 2, false}, + {1, "bilbao.museum", 2, false}, + {1, "bill.museum", 2, false}, + {1, "birdart.museum", 2, false}, + {1, "birthplace.museum", 2, false}, + {1, "bonn.museum", 2, false}, + {1, "boston.museum", 2, false}, + {1, "botanical.museum", 2, false}, + {1, "botanicalgarden.museum", 2, false}, + {1, "botanicgarden.museum", 2, false}, + {1, "botany.museum", 2, false}, + {1, "brandywinevalley.museum", 2, false}, + {1, "brasil.museum", 2, false}, + {1, "bristol.museum", 2, false}, + {1, "british.museum", 2, false}, + {1, "britishcolumbia.museum", 2, false}, + {1, "broadcast.museum", 2, false}, + {1, "brunel.museum", 2, false}, + {1, "brussel.museum", 2, false}, + {1, "brussels.museum", 2, false}, + {1, "bruxelles.museum", 2, false}, + {1, "building.museum", 2, false}, + {1, "burghof.museum", 2, false}, + {1, "bus.museum", 2, false}, + {1, "bushey.museum", 2, false}, + {1, "cadaques.museum", 2, false}, + {1, "california.museum", 2, false}, + {1, "cambridge.museum", 2, false}, + {1, "can.museum", 2, false}, + {1, "canada.museum", 2, false}, + {1, "capebreton.museum", 2, false}, + {1, "carrier.museum", 2, false}, + {1, "cartoonart.museum", 2, false}, + {1, "casadelamoneda.museum", 2, false}, + {1, "castle.museum", 2, false}, + {1, "castres.museum", 2, false}, + {1, "celtic.museum", 2, false}, + {1, "center.museum", 2, false}, + {1, "chattanooga.museum", 2, false}, + {1, "cheltenham.museum", 2, false}, + {1, "chesapeakebay.museum", 2, false}, + {1, "chicago.museum", 2, false}, + {1, "children.museum", 2, false}, + {1, "childrens.museum", 2, false}, + {1, "childrensgarden.museum", 2, false}, + {1, "chiropractic.museum", 2, false}, + {1, "chocolate.museum", 2, false}, + {1, "christiansburg.museum", 2, false}, + {1, "cincinnati.museum", 2, false}, + {1, "cinema.museum", 2, false}, + {1, "circus.museum", 2, false}, + {1, "civilisation.museum", 2, false}, + {1, "civilization.museum", 2, false}, + {1, "civilwar.museum", 2, false}, + {1, "clinton.museum", 2, false}, + {1, "clock.museum", 2, false}, + {1, "coal.museum", 2, false}, + {1, "coastaldefence.museum", 2, false}, + {1, "cody.museum", 2, false}, + {1, "coldwar.museum", 2, false}, + {1, "collection.museum", 2, false}, + {1, "colonialwilliamsburg.museum", 2, false}, + {1, "coloradoplateau.museum", 2, false}, + {1, "columbia.museum", 2, false}, + {1, "columbus.museum", 2, false}, + {1, "communication.museum", 2, false}, + {1, "communications.museum", 2, false}, + {1, "community.museum", 2, false}, + {1, "computer.museum", 2, false}, + {1, "computerhistory.museum", 2, false}, + {1, "xn--comunicaes-v6a2o.museum", 2, false}, + {1, "contemporary.museum", 2, false}, + {1, "contemporaryart.museum", 2, false}, + {1, "convent.museum", 2, false}, + {1, "copenhagen.museum", 2, false}, + {1, "corporation.museum", 2, false}, + {1, "xn--correios-e-telecomunicaes-ghc29a.museum", 2, false}, + {1, "corvette.museum", 2, false}, + {1, "costume.museum", 2, false}, + {1, "countryestate.museum", 2, false}, + {1, "county.museum", 2, false}, + {1, "crafts.museum", 2, false}, + {1, "cranbrook.museum", 2, false}, + {1, "creation.museum", 2, false}, + {1, "cultural.museum", 2, false}, + {1, "culturalcenter.museum", 2, false}, + {1, "culture.museum", 2, false}, + {1, "cyber.museum", 2, false}, + {1, "cymru.museum", 2, false}, + {1, "dali.museum", 2, false}, + {1, "dallas.museum", 2, false}, + {1, "database.museum", 2, false}, + {1, "ddr.museum", 2, false}, + {1, "decorativearts.museum", 2, false}, + {1, "delaware.museum", 2, false}, + {1, "delmenhorst.museum", 2, false}, + {1, "denmark.museum", 2, false}, + {1, "depot.museum", 2, false}, + {1, "design.museum", 2, false}, + {1, "detroit.museum", 2, false}, + {1, "dinosaur.museum", 2, false}, + {1, "discovery.museum", 2, false}, + {1, "dolls.museum", 2, false}, + {1, "donostia.museum", 2, false}, + {1, "durham.museum", 2, false}, + {1, "eastafrica.museum", 2, false}, + {1, "eastcoast.museum", 2, false}, + {1, "education.museum", 2, false}, + {1, "educational.museum", 2, false}, + {1, "egyptian.museum", 2, false}, + {1, "eisenbahn.museum", 2, false}, + {1, "elburg.museum", 2, false}, + {1, "elvendrell.museum", 2, false}, + {1, "embroidery.museum", 2, false}, + {1, "encyclopedic.museum", 2, false}, + {1, "england.museum", 2, false}, + {1, "entomology.museum", 2, false}, + {1, "environment.museum", 2, false}, + {1, "environmentalconservation.museum", 2, false}, + {1, "epilepsy.museum", 2, false}, + {1, "essex.museum", 2, false}, + {1, "estate.museum", 2, false}, + {1, "ethnology.museum", 2, false}, + {1, "exeter.museum", 2, false}, + {1, "exhibition.museum", 2, false}, + {1, "family.museum", 2, false}, + {1, "farm.museum", 2, false}, + {1, "farmequipment.museum", 2, false}, + {1, "farmers.museum", 2, false}, + {1, "farmstead.museum", 2, false}, + {1, "field.museum", 2, false}, + {1, "figueres.museum", 2, false}, + {1, "filatelia.museum", 2, false}, + {1, "film.museum", 2, false}, + {1, "fineart.museum", 2, false}, + {1, "finearts.museum", 2, false}, + {1, "finland.museum", 2, false}, + {1, "flanders.museum", 2, false}, + {1, "florida.museum", 2, false}, + {1, "force.museum", 2, false}, + {1, "fortmissoula.museum", 2, false}, + {1, "fortworth.museum", 2, false}, + {1, "foundation.museum", 2, false}, + {1, "francaise.museum", 2, false}, + {1, "frankfurt.museum", 2, false}, + {1, "franziskaner.museum", 2, false}, + {1, "freemasonry.museum", 2, false}, + {1, "freiburg.museum", 2, false}, + {1, "fribourg.museum", 2, false}, + {1, "frog.museum", 2, false}, + {1, "fundacio.museum", 2, false}, + {1, "furniture.museum", 2, false}, + {1, "gallery.museum", 2, false}, + {1, "garden.museum", 2, false}, + {1, "gateway.museum", 2, false}, + {1, "geelvinck.museum", 2, false}, + {1, "gemological.museum", 2, false}, + {1, "geology.museum", 2, false}, + {1, "georgia.museum", 2, false}, + {1, "giessen.museum", 2, false}, + {1, "glas.museum", 2, false}, + {1, "glass.museum", 2, false}, + {1, "gorge.museum", 2, false}, + {1, "grandrapids.museum", 2, false}, + {1, "graz.museum", 2, false}, + {1, "guernsey.museum", 2, false}, + {1, "halloffame.museum", 2, false}, + {1, "hamburg.museum", 2, false}, + {1, "handson.museum", 2, false}, + {1, "harvestcelebration.museum", 2, false}, + {1, "hawaii.museum", 2, false}, + {1, "health.museum", 2, false}, + {1, "heimatunduhren.museum", 2, false}, + {1, "hellas.museum", 2, false}, + {1, "helsinki.museum", 2, false}, + {1, "hembygdsforbund.museum", 2, false}, + {1, "heritage.museum", 2, false}, + {1, "histoire.museum", 2, false}, + {1, "historical.museum", 2, false}, + {1, "historicalsociety.museum", 2, false}, + {1, "historichouses.museum", 2, false}, + {1, "historisch.museum", 2, false}, + {1, "historisches.museum", 2, false}, + {1, "history.museum", 2, false}, + {1, "historyofscience.museum", 2, false}, + {1, "horology.museum", 2, false}, + {1, "house.museum", 2, false}, + {1, "humanities.museum", 2, false}, + {1, "illustration.museum", 2, false}, + {1, "imageandsound.museum", 2, false}, + {1, "indian.museum", 2, false}, + {1, "indiana.museum", 2, false}, + {1, "indianapolis.museum", 2, false}, + {1, "indianmarket.museum", 2, false}, + {1, "intelligence.museum", 2, false}, + {1, "interactive.museum", 2, false}, + {1, "iraq.museum", 2, false}, + {1, "iron.museum", 2, false}, + {1, "isleofman.museum", 2, false}, + {1, "jamison.museum", 2, false}, + {1, "jefferson.museum", 2, false}, + {1, "jerusalem.museum", 2, false}, + {1, "jewelry.museum", 2, false}, + {1, "jewish.museum", 2, false}, + {1, "jewishart.museum", 2, false}, + {1, "jfk.museum", 2, false}, + {1, "journalism.museum", 2, false}, + {1, "judaica.museum", 2, false}, + {1, "judygarland.museum", 2, false}, + {1, "juedisches.museum", 2, false}, + {1, "juif.museum", 2, false}, + {1, "karate.museum", 2, false}, + {1, "karikatur.museum", 2, false}, + {1, "kids.museum", 2, false}, + {1, "koebenhavn.museum", 2, false}, + {1, "koeln.museum", 2, false}, + {1, "kunst.museum", 2, false}, + {1, "kunstsammlung.museum", 2, false}, + {1, "kunstunddesign.museum", 2, false}, + {1, "labor.museum", 2, false}, + {1, "labour.museum", 2, false}, + {1, "lajolla.museum", 2, false}, + {1, "lancashire.museum", 2, false}, + {1, "landes.museum", 2, false}, + {1, "lans.museum", 2, false}, + {1, "xn--lns-qla.museum", 2, false}, + {1, "larsson.museum", 2, false}, + {1, "lewismiller.museum", 2, false}, + {1, "lincoln.museum", 2, false}, + {1, "linz.museum", 2, false}, + {1, "living.museum", 2, false}, + {1, "livinghistory.museum", 2, false}, + {1, "localhistory.museum", 2, false}, + {1, "london.museum", 2, false}, + {1, "losangeles.museum", 2, false}, + {1, "louvre.museum", 2, false}, + {1, "loyalist.museum", 2, false}, + {1, "lucerne.museum", 2, false}, + {1, "luxembourg.museum", 2, false}, + {1, "luzern.museum", 2, false}, + {1, "mad.museum", 2, false}, + {1, "madrid.museum", 2, false}, + {1, "mallorca.museum", 2, false}, + {1, "manchester.museum", 2, false}, + {1, "mansion.museum", 2, false}, + {1, "mansions.museum", 2, false}, + {1, "manx.museum", 2, false}, + {1, "marburg.museum", 2, false}, + {1, "maritime.museum", 2, false}, + {1, "maritimo.museum", 2, false}, + {1, "maryland.museum", 2, false}, + {1, "marylhurst.museum", 2, false}, + {1, "media.museum", 2, false}, + {1, "medical.museum", 2, false}, + {1, "medizinhistorisches.museum", 2, false}, + {1, "meeres.museum", 2, false}, + {1, "memorial.museum", 2, false}, + {1, "mesaverde.museum", 2, false}, + {1, "michigan.museum", 2, false}, + {1, "midatlantic.museum", 2, false}, + {1, "military.museum", 2, false}, + {1, "mill.museum", 2, false}, + {1, "miners.museum", 2, false}, + {1, "mining.museum", 2, false}, + {1, "minnesota.museum", 2, false}, + {1, "missile.museum", 2, false}, + {1, "missoula.museum", 2, false}, + {1, "modern.museum", 2, false}, + {1, "moma.museum", 2, false}, + {1, "money.museum", 2, false}, + {1, "monmouth.museum", 2, false}, + {1, "monticello.museum", 2, false}, + {1, "montreal.museum", 2, false}, + {1, "moscow.museum", 2, false}, + {1, "motorcycle.museum", 2, false}, + {1, "muenchen.museum", 2, false}, + {1, "muenster.museum", 2, false}, + {1, "mulhouse.museum", 2, false}, + {1, "muncie.museum", 2, false}, + {1, "museet.museum", 2, false}, + {1, "museumcenter.museum", 2, false}, + {1, "museumvereniging.museum", 2, false}, + {1, "music.museum", 2, false}, + {1, "national.museum", 2, false}, + {1, "nationalfirearms.museum", 2, false}, + {1, "nationalheritage.museum", 2, false}, + {1, "nativeamerican.museum", 2, false}, + {1, "naturalhistory.museum", 2, false}, + {1, "naturalhistorymuseum.museum", 2, false}, + {1, "naturalsciences.museum", 2, false}, + {1, "nature.museum", 2, false}, + {1, "naturhistorisches.museum", 2, false}, + {1, "natuurwetenschappen.museum", 2, false}, + {1, "naumburg.museum", 2, false}, + {1, "naval.museum", 2, false}, + {1, "nebraska.museum", 2, false}, + {1, "neues.museum", 2, false}, + {1, "newhampshire.museum", 2, false}, + {1, "newjersey.museum", 2, false}, + {1, "newmexico.museum", 2, false}, + {1, "newport.museum", 2, false}, + {1, "newspaper.museum", 2, false}, + {1, "newyork.museum", 2, false}, + {1, "niepce.museum", 2, false}, + {1, "norfolk.museum", 2, false}, + {1, "north.museum", 2, false}, + {1, "nrw.museum", 2, false}, + {1, "nyc.museum", 2, false}, + {1, "nyny.museum", 2, false}, + {1, "oceanographic.museum", 2, false}, + {1, "oceanographique.museum", 2, false}, + {1, "omaha.museum", 2, false}, + {1, "online.museum", 2, false}, + {1, "ontario.museum", 2, false}, + {1, "openair.museum", 2, false}, + {1, "oregon.museum", 2, false}, + {1, "oregontrail.museum", 2, false}, + {1, "otago.museum", 2, false}, + {1, "oxford.museum", 2, false}, + {1, "pacific.museum", 2, false}, + {1, "paderborn.museum", 2, false}, + {1, "palace.museum", 2, false}, + {1, "paleo.museum", 2, false}, + {1, "palmsprings.museum", 2, false}, + {1, "panama.museum", 2, false}, + {1, "paris.museum", 2, false}, + {1, "pasadena.museum", 2, false}, + {1, "pharmacy.museum", 2, false}, + {1, "philadelphia.museum", 2, false}, + {1, "philadelphiaarea.museum", 2, false}, + {1, "philately.museum", 2, false}, + {1, "phoenix.museum", 2, false}, + {1, "photography.museum", 2, false}, + {1, "pilots.museum", 2, false}, + {1, "pittsburgh.museum", 2, false}, + {1, "planetarium.museum", 2, false}, + {1, "plantation.museum", 2, false}, + {1, "plants.museum", 2, false}, + {1, "plaza.museum", 2, false}, + {1, "portal.museum", 2, false}, + {1, "portland.museum", 2, false}, + {1, "portlligat.museum", 2, false}, + {1, "posts-and-telecommunications.museum", 2, false}, + {1, "preservation.museum", 2, false}, + {1, "presidio.museum", 2, false}, + {1, "press.museum", 2, false}, + {1, "project.museum", 2, false}, + {1, "public.museum", 2, false}, + {1, "pubol.museum", 2, false}, + {1, "quebec.museum", 2, false}, + {1, "railroad.museum", 2, false}, + {1, "railway.museum", 2, false}, + {1, "research.museum", 2, false}, + {1, "resistance.museum", 2, false}, + {1, "riodejaneiro.museum", 2, false}, + {1, "rochester.museum", 2, false}, + {1, "rockart.museum", 2, false}, + {1, "roma.museum", 2, false}, + {1, "russia.museum", 2, false}, + {1, "saintlouis.museum", 2, false}, + {1, "salem.museum", 2, false}, + {1, "salvadordali.museum", 2, false}, + {1, "salzburg.museum", 2, false}, + {1, "sandiego.museum", 2, false}, + {1, "sanfrancisco.museum", 2, false}, + {1, "santabarbara.museum", 2, false}, + {1, "santacruz.museum", 2, false}, + {1, "santafe.museum", 2, false}, + {1, "saskatchewan.museum", 2, false}, + {1, "satx.museum", 2, false}, + {1, "savannahga.museum", 2, false}, + {1, "schlesisches.museum", 2, false}, + {1, "schoenbrunn.museum", 2, false}, + {1, "schokoladen.museum", 2, false}, + {1, "school.museum", 2, false}, + {1, "schweiz.museum", 2, false}, + {1, "science.museum", 2, false}, + {1, "scienceandhistory.museum", 2, false}, + {1, "scienceandindustry.museum", 2, false}, + {1, "sciencecenter.museum", 2, false}, + {1, "sciencecenters.museum", 2, false}, + {1, "science-fiction.museum", 2, false}, + {1, "sciencehistory.museum", 2, false}, + {1, "sciences.museum", 2, false}, + {1, "sciencesnaturelles.museum", 2, false}, + {1, "scotland.museum", 2, false}, + {1, "seaport.museum", 2, false}, + {1, "settlement.museum", 2, false}, + {1, "settlers.museum", 2, false}, + {1, "shell.museum", 2, false}, + {1, "sherbrooke.museum", 2, false}, + {1, "sibenik.museum", 2, false}, + {1, "silk.museum", 2, false}, + {1, "ski.museum", 2, false}, + {1, "skole.museum", 2, false}, + {1, "society.museum", 2, false}, + {1, "sologne.museum", 2, false}, + {1, "soundandvision.museum", 2, false}, + {1, "southcarolina.museum", 2, false}, + {1, "southwest.museum", 2, false}, + {1, "space.museum", 2, false}, + {1, "spy.museum", 2, false}, + {1, "square.museum", 2, false}, + {1, "stadt.museum", 2, false}, + {1, "stalbans.museum", 2, false}, + {1, "starnberg.museum", 2, false}, + {1, "state.museum", 2, false}, + {1, "stateofdelaware.museum", 2, false}, + {1, "station.museum", 2, false}, + {1, "steam.museum", 2, false}, + {1, "steiermark.museum", 2, false}, + {1, "stjohn.museum", 2, false}, + {1, "stockholm.museum", 2, false}, + {1, "stpetersburg.museum", 2, false}, + {1, "stuttgart.museum", 2, false}, + {1, "suisse.museum", 2, false}, + {1, "surgeonshall.museum", 2, false}, + {1, "surrey.museum", 2, false}, + {1, "svizzera.museum", 2, false}, + {1, "sweden.museum", 2, false}, + {1, "sydney.museum", 2, false}, + {1, "tank.museum", 2, false}, + {1, "tcm.museum", 2, false}, + {1, "technology.museum", 2, false}, + {1, "telekommunikation.museum", 2, false}, + {1, "television.museum", 2, false}, + {1, "texas.museum", 2, false}, + {1, "textile.museum", 2, false}, + {1, "theater.museum", 2, false}, + {1, "time.museum", 2, false}, + {1, "timekeeping.museum", 2, false}, + {1, "topology.museum", 2, false}, + {1, "torino.museum", 2, false}, + {1, "touch.museum", 2, false}, + {1, "town.museum", 2, false}, + {1, "transport.museum", 2, false}, + {1, "tree.museum", 2, false}, + {1, "trolley.museum", 2, false}, + {1, "trust.museum", 2, false}, + {1, "trustee.museum", 2, false}, + {1, "uhren.museum", 2, false}, + {1, "ulm.museum", 2, false}, + {1, "undersea.museum", 2, false}, + {1, "university.museum", 2, false}, + {1, "usa.museum", 2, false}, + {1, "usantiques.museum", 2, false}, + {1, "usarts.museum", 2, false}, + {1, "uscountryestate.museum", 2, false}, + {1, "usculture.museum", 2, false}, + {1, "usdecorativearts.museum", 2, false}, + {1, "usgarden.museum", 2, false}, + {1, "ushistory.museum", 2, false}, + {1, "ushuaia.museum", 2, false}, + {1, "uslivinghistory.museum", 2, false}, + {1, "utah.museum", 2, false}, + {1, "uvic.museum", 2, false}, + {1, "valley.museum", 2, false}, + {1, "vantaa.museum", 2, false}, + {1, "versailles.museum", 2, false}, + {1, "viking.museum", 2, false}, + {1, "village.museum", 2, false}, + {1, "virginia.museum", 2, false}, + {1, "virtual.museum", 2, false}, + {1, "virtuel.museum", 2, false}, + {1, "vlaanderen.museum", 2, false}, + {1, "volkenkunde.museum", 2, false}, + {1, "wales.museum", 2, false}, + {1, "wallonie.museum", 2, false}, + {1, "war.museum", 2, false}, + {1, "washingtondc.museum", 2, false}, + {1, "watchandclock.museum", 2, false}, + {1, "watch-and-clock.museum", 2, false}, + {1, "western.museum", 2, false}, + {1, "westfalen.museum", 2, false}, + {1, "whaling.museum", 2, false}, + {1, "wildlife.museum", 2, false}, + {1, "williamsburg.museum", 2, false}, + {1, "windmill.museum", 2, false}, + {1, "workshop.museum", 2, false}, + {1, "york.museum", 2, false}, + {1, "yorkshire.museum", 2, false}, + {1, "yosemite.museum", 2, false}, + {1, "youth.museum", 2, false}, + {1, "zoological.museum", 2, false}, + {1, "zoology.museum", 2, false}, + {1, "xn--9dbhblg6di.museum", 2, false}, + {1, "xn--h1aegh.museum", 2, false}, + {1, "mv", 1, false}, + {1, "aero.mv", 2, false}, + {1, "biz.mv", 2, false}, + {1, "com.mv", 2, false}, + {1, "coop.mv", 2, false}, + {1, "edu.mv", 2, false}, + {1, "gov.mv", 2, false}, + {1, "info.mv", 2, false}, + {1, "int.mv", 2, false}, + {1, "mil.mv", 2, false}, + {1, "museum.mv", 2, false}, + {1, "name.mv", 2, false}, + {1, "net.mv", 2, false}, + {1, "org.mv", 2, false}, + {1, "pro.mv", 2, false}, + {1, "mw", 1, false}, + {1, "ac.mw", 2, false}, + {1, "biz.mw", 2, false}, + {1, "co.mw", 2, false}, + {1, "com.mw", 2, false}, + {1, "coop.mw", 2, false}, + {1, "edu.mw", 2, false}, + {1, "gov.mw", 2, false}, + {1, "int.mw", 2, false}, + {1, "museum.mw", 2, false}, + {1, "net.mw", 2, false}, + {1, "org.mw", 2, false}, + {1, "mx", 1, false}, + {1, "com.mx", 2, false}, + {1, "org.mx", 2, false}, + {1, "gob.mx", 2, false}, + {1, "edu.mx", 2, false}, + {1, "net.mx", 2, false}, + {1, "my", 1, false}, + {1, "biz.my", 2, false}, + {1, "com.my", 2, false}, + {1, "edu.my", 2, false}, + {1, "gov.my", 2, false}, + {1, "mil.my", 2, false}, + {1, "name.my", 2, false}, + {1, "net.my", 2, false}, + {1, "org.my", 2, false}, + {1, "mz", 1, false}, + {1, "ac.mz", 2, false}, + {1, "adv.mz", 2, false}, + {1, "co.mz", 2, false}, + {1, "edu.mz", 2, false}, + {1, "gov.mz", 2, false}, + {1, "mil.mz", 2, false}, + {1, "net.mz", 2, false}, + {1, "org.mz", 2, false}, + {1, "na", 1, false}, + {1, "info.na", 2, false}, + {1, "pro.na", 2, false}, + {1, "name.na", 2, false}, + {1, "school.na", 2, false}, + {1, "or.na", 2, false}, + {1, "dr.na", 2, false}, + {1, "us.na", 2, false}, + {1, "mx.na", 2, false}, + {1, "ca.na", 2, false}, + {1, "in.na", 2, false}, + {1, "cc.na", 2, false}, + {1, "tv.na", 2, false}, + {1, "ws.na", 2, false}, + {1, "mobi.na", 2, false}, + {1, "co.na", 2, false}, + {1, "com.na", 2, false}, + {1, "org.na", 2, false}, + {1, "name", 1, false}, + {1, "nc", 1, false}, + {1, "asso.nc", 2, false}, + {1, "nom.nc", 2, false}, + {1, "ne", 1, false}, + {1, "net", 1, false}, + {1, "nf", 1, false}, + {1, "com.nf", 2, false}, + {1, "net.nf", 2, false}, + {1, "per.nf", 2, false}, + {1, "rec.nf", 2, false}, + {1, "web.nf", 2, false}, + {1, "arts.nf", 2, false}, + {1, "firm.nf", 2, false}, + {1, "info.nf", 2, false}, + {1, "other.nf", 2, false}, + {1, "store.nf", 2, false}, + {1, "ng", 1, false}, + {1, "com.ng", 2, false}, + {1, "edu.ng", 2, false}, + {1, "gov.ng", 2, false}, + {1, "i.ng", 2, false}, + {1, "mil.ng", 2, false}, + {1, "mobi.ng", 2, false}, + {1, "name.ng", 2, false}, + {1, "net.ng", 2, false}, + {1, "org.ng", 2, false}, + {1, "sch.ng", 2, false}, + {1, "ni", 1, false}, + {1, "ac.ni", 2, false}, + {1, "biz.ni", 2, false}, + {1, "co.ni", 2, false}, + {1, "com.ni", 2, false}, + {1, "edu.ni", 2, false}, + {1, "gob.ni", 2, false}, + {1, "in.ni", 2, false}, + {1, "info.ni", 2, false}, + {1, "int.ni", 2, false}, + {1, "mil.ni", 2, false}, + {1, "net.ni", 2, false}, + {1, "nom.ni", 2, false}, + {1, "org.ni", 2, false}, + {1, "web.ni", 2, false}, + {1, "nl", 1, false}, + {1, "no", 1, false}, + {1, "fhs.no", 2, false}, + {1, "vgs.no", 2, false}, + {1, "fylkesbibl.no", 2, false}, + {1, "folkebibl.no", 2, false}, + {1, "museum.no", 2, false}, + {1, "idrett.no", 2, false}, + {1, "priv.no", 2, false}, + {1, "mil.no", 2, false}, + {1, "stat.no", 2, false}, + {1, "dep.no", 2, false}, + {1, "kommune.no", 2, false}, + {1, "herad.no", 2, false}, + {1, "aa.no", 2, false}, + {1, "ah.no", 2, false}, + {1, "bu.no", 2, false}, + {1, "fm.no", 2, false}, + {1, "hl.no", 2, false}, + {1, "hm.no", 2, false}, + {1, "jan-mayen.no", 2, false}, + {1, "mr.no", 2, false}, + {1, "nl.no", 2, false}, + {1, "nt.no", 2, false}, + {1, "of.no", 2, false}, + {1, "ol.no", 2, false}, + {1, "oslo.no", 2, false}, + {1, "rl.no", 2, false}, + {1, "sf.no", 2, false}, + {1, "st.no", 2, false}, + {1, "svalbard.no", 2, false}, + {1, "tm.no", 2, false}, + {1, "tr.no", 2, false}, + {1, "va.no", 2, false}, + {1, "vf.no", 2, false}, + {1, "gs.aa.no", 3, false}, + {1, "gs.ah.no", 3, false}, + {1, "gs.bu.no", 3, false}, + {1, "gs.fm.no", 3, false}, + {1, "gs.hl.no", 3, false}, + {1, "gs.hm.no", 3, false}, + {1, "gs.jan-mayen.no", 3, false}, + {1, "gs.mr.no", 3, false}, + {1, "gs.nl.no", 3, false}, + {1, "gs.nt.no", 3, false}, + {1, "gs.of.no", 3, false}, + {1, "gs.ol.no", 3, false}, + {1, "gs.oslo.no", 3, false}, + {1, "gs.rl.no", 3, false}, + {1, "gs.sf.no", 3, false}, + {1, "gs.st.no", 3, false}, + {1, "gs.svalbard.no", 3, false}, + {1, "gs.tm.no", 3, false}, + {1, "gs.tr.no", 3, false}, + {1, "gs.va.no", 3, false}, + {1, "gs.vf.no", 3, false}, + {1, "akrehamn.no", 2, false}, + {1, "xn--krehamn-dxa.no", 2, false}, + {1, "algard.no", 2, false}, + {1, "xn--lgrd-poac.no", 2, false}, + {1, "arna.no", 2, false}, + {1, "brumunddal.no", 2, false}, + {1, "bryne.no", 2, false}, + {1, "bronnoysund.no", 2, false}, + {1, "xn--brnnysund-m8ac.no", 2, false}, + {1, "drobak.no", 2, false}, + {1, "xn--drbak-wua.no", 2, false}, + {1, "egersund.no", 2, false}, + {1, "fetsund.no", 2, false}, + {1, "floro.no", 2, false}, + {1, "xn--flor-jra.no", 2, false}, + {1, "fredrikstad.no", 2, false}, + {1, "hokksund.no", 2, false}, + {1, "honefoss.no", 2, false}, + {1, "xn--hnefoss-q1a.no", 2, false}, + {1, "jessheim.no", 2, false}, + {1, "jorpeland.no", 2, false}, + {1, "xn--jrpeland-54a.no", 2, false}, + {1, "kirkenes.no", 2, false}, + {1, "kopervik.no", 2, false}, + {1, "krokstadelva.no", 2, false}, + {1, "langevag.no", 2, false}, + {1, "xn--langevg-jxa.no", 2, false}, + {1, "leirvik.no", 2, false}, + {1, "mjondalen.no", 2, false}, + {1, "xn--mjndalen-64a.no", 2, false}, + {1, "mo-i-rana.no", 2, false}, + {1, "mosjoen.no", 2, false}, + {1, "xn--mosjen-eya.no", 2, false}, + {1, "nesoddtangen.no", 2, false}, + {1, "orkanger.no", 2, false}, + {1, "osoyro.no", 2, false}, + {1, "xn--osyro-wua.no", 2, false}, + {1, "raholt.no", 2, false}, + {1, "xn--rholt-mra.no", 2, false}, + {1, "sandnessjoen.no", 2, false}, + {1, "xn--sandnessjen-ogb.no", 2, false}, + {1, "skedsmokorset.no", 2, false}, + {1, "slattum.no", 2, false}, + {1, "spjelkavik.no", 2, false}, + {1, "stathelle.no", 2, false}, + {1, "stavern.no", 2, false}, + {1, "stjordalshalsen.no", 2, false}, + {1, "xn--stjrdalshalsen-sqb.no", 2, false}, + {1, "tananger.no", 2, false}, + {1, "tranby.no", 2, false}, + {1, "vossevangen.no", 2, false}, + {1, "afjord.no", 2, false}, + {1, "xn--fjord-lra.no", 2, false}, + {1, "agdenes.no", 2, false}, + {1, "al.no", 2, false}, + {1, "xn--l-1fa.no", 2, false}, + {1, "alesund.no", 2, false}, + {1, "xn--lesund-hua.no", 2, false}, + {1, "alstahaug.no", 2, false}, + {1, "alta.no", 2, false}, + {1, "xn--lt-liac.no", 2, false}, + {1, "alaheadju.no", 2, false}, + {1, "xn--laheadju-7ya.no", 2, false}, + {1, "alvdal.no", 2, false}, + {1, "amli.no", 2, false}, + {1, "xn--mli-tla.no", 2, false}, + {1, "amot.no", 2, false}, + {1, "xn--mot-tla.no", 2, false}, + {1, "andebu.no", 2, false}, + {1, "andoy.no", 2, false}, + {1, "xn--andy-ira.no", 2, false}, + {1, "andasuolo.no", 2, false}, + {1, "ardal.no", 2, false}, + {1, "xn--rdal-poa.no", 2, false}, + {1, "aremark.no", 2, false}, + {1, "arendal.no", 2, false}, + {1, "xn--s-1fa.no", 2, false}, + {1, "aseral.no", 2, false}, + {1, "xn--seral-lra.no", 2, false}, + {1, "asker.no", 2, false}, + {1, "askim.no", 2, false}, + {1, "askvoll.no", 2, false}, + {1, "askoy.no", 2, false}, + {1, "xn--asky-ira.no", 2, false}, + {1, "asnes.no", 2, false}, + {1, "xn--snes-poa.no", 2, false}, + {1, "audnedaln.no", 2, false}, + {1, "aukra.no", 2, false}, + {1, "aure.no", 2, false}, + {1, "aurland.no", 2, false}, + {1, "aurskog-holand.no", 2, false}, + {1, "xn--aurskog-hland-jnb.no", 2, false}, + {1, "austevoll.no", 2, false}, + {1, "austrheim.no", 2, false}, + {1, "averoy.no", 2, false}, + {1, "xn--avery-yua.no", 2, false}, + {1, "balestrand.no", 2, false}, + {1, "ballangen.no", 2, false}, + {1, "balat.no", 2, false}, + {1, "xn--blt-elab.no", 2, false}, + {1, "balsfjord.no", 2, false}, + {1, "bahccavuotna.no", 2, false}, + {1, "xn--bhccavuotna-k7a.no", 2, false}, + {1, "bamble.no", 2, false}, + {1, "bardu.no", 2, false}, + {1, "beardu.no", 2, false}, + {1, "beiarn.no", 2, false}, + {1, "bajddar.no", 2, false}, + {1, "xn--bjddar-pta.no", 2, false}, + {1, "baidar.no", 2, false}, + {1, "xn--bidr-5nac.no", 2, false}, + {1, "berg.no", 2, false}, + {1, "bergen.no", 2, false}, + {1, "berlevag.no", 2, false}, + {1, "xn--berlevg-jxa.no", 2, false}, + {1, "bearalvahki.no", 2, false}, + {1, "xn--bearalvhki-y4a.no", 2, false}, + {1, "bindal.no", 2, false}, + {1, "birkenes.no", 2, false}, + {1, "bjarkoy.no", 2, false}, + {1, "xn--bjarky-fya.no", 2, false}, + {1, "bjerkreim.no", 2, false}, + {1, "bjugn.no", 2, false}, + {1, "bodo.no", 2, false}, + {1, "xn--bod-2na.no", 2, false}, + {1, "badaddja.no", 2, false}, + {1, "xn--bdddj-mrabd.no", 2, false}, + {1, "budejju.no", 2, false}, + {1, "bokn.no", 2, false}, + {1, "bremanger.no", 2, false}, + {1, "bronnoy.no", 2, false}, + {1, "xn--brnny-wuac.no", 2, false}, + {1, "bygland.no", 2, false}, + {1, "bykle.no", 2, false}, + {1, "barum.no", 2, false}, + {1, "xn--brum-voa.no", 2, false}, + {1, "bo.telemark.no", 3, false}, + {1, "xn--b-5ga.telemark.no", 3, false}, + {1, "bo.nordland.no", 3, false}, + {1, "xn--b-5ga.nordland.no", 3, false}, + {1, "bievat.no", 2, false}, + {1, "xn--bievt-0qa.no", 2, false}, + {1, "bomlo.no", 2, false}, + {1, "xn--bmlo-gra.no", 2, false}, + {1, "batsfjord.no", 2, false}, + {1, "xn--btsfjord-9za.no", 2, false}, + {1, "bahcavuotna.no", 2, false}, + {1, "xn--bhcavuotna-s4a.no", 2, false}, + {1, "dovre.no", 2, false}, + {1, "drammen.no", 2, false}, + {1, "drangedal.no", 2, false}, + {1, "dyroy.no", 2, false}, + {1, "xn--dyry-ira.no", 2, false}, + {1, "donna.no", 2, false}, + {1, "xn--dnna-gra.no", 2, false}, + {1, "eid.no", 2, false}, + {1, "eidfjord.no", 2, false}, + {1, "eidsberg.no", 2, false}, + {1, "eidskog.no", 2, false}, + {1, "eidsvoll.no", 2, false}, + {1, "eigersund.no", 2, false}, + {1, "elverum.no", 2, false}, + {1, "enebakk.no", 2, false}, + {1, "engerdal.no", 2, false}, + {1, "etne.no", 2, false}, + {1, "etnedal.no", 2, false}, + {1, "evenes.no", 2, false}, + {1, "evenassi.no", 2, false}, + {1, "xn--eveni-0qa01ga.no", 2, false}, + {1, "evje-og-hornnes.no", 2, false}, + {1, "farsund.no", 2, false}, + {1, "fauske.no", 2, false}, + {1, "fuossko.no", 2, false}, + {1, "fuoisku.no", 2, false}, + {1, "fedje.no", 2, false}, + {1, "fet.no", 2, false}, + {1, "finnoy.no", 2, false}, + {1, "xn--finny-yua.no", 2, false}, + {1, "fitjar.no", 2, false}, + {1, "fjaler.no", 2, false}, + {1, "fjell.no", 2, false}, + {1, "flakstad.no", 2, false}, + {1, "flatanger.no", 2, false}, + {1, "flekkefjord.no", 2, false}, + {1, "flesberg.no", 2, false}, + {1, "flora.no", 2, false}, + {1, "fla.no", 2, false}, + {1, "xn--fl-zia.no", 2, false}, + {1, "folldal.no", 2, false}, + {1, "forsand.no", 2, false}, + {1, "fosnes.no", 2, false}, + {1, "frei.no", 2, false}, + {1, "frogn.no", 2, false}, + {1, "froland.no", 2, false}, + {1, "frosta.no", 2, false}, + {1, "frana.no", 2, false}, + {1, "xn--frna-woa.no", 2, false}, + {1, "froya.no", 2, false}, + {1, "xn--frya-hra.no", 2, false}, + {1, "fusa.no", 2, false}, + {1, "fyresdal.no", 2, false}, + {1, "forde.no", 2, false}, + {1, "xn--frde-gra.no", 2, false}, + {1, "gamvik.no", 2, false}, + {1, "gangaviika.no", 2, false}, + {1, "xn--ggaviika-8ya47h.no", 2, false}, + {1, "gaular.no", 2, false}, + {1, "gausdal.no", 2, false}, + {1, "gildeskal.no", 2, false}, + {1, "xn--gildeskl-g0a.no", 2, false}, + {1, "giske.no", 2, false}, + {1, "gjemnes.no", 2, false}, + {1, "gjerdrum.no", 2, false}, + {1, "gjerstad.no", 2, false}, + {1, "gjesdal.no", 2, false}, + {1, "gjovik.no", 2, false}, + {1, "xn--gjvik-wua.no", 2, false}, + {1, "gloppen.no", 2, false}, + {1, "gol.no", 2, false}, + {1, "gran.no", 2, false}, + {1, "grane.no", 2, false}, + {1, "granvin.no", 2, false}, + {1, "gratangen.no", 2, false}, + {1, "grimstad.no", 2, false}, + {1, "grong.no", 2, false}, + {1, "kraanghke.no", 2, false}, + {1, "xn--kranghke-b0a.no", 2, false}, + {1, "grue.no", 2, false}, + {1, "gulen.no", 2, false}, + {1, "hadsel.no", 2, false}, + {1, "halden.no", 2, false}, + {1, "halsa.no", 2, false}, + {1, "hamar.no", 2, false}, + {1, "hamaroy.no", 2, false}, + {1, "habmer.no", 2, false}, + {1, "xn--hbmer-xqa.no", 2, false}, + {1, "hapmir.no", 2, false}, + {1, "xn--hpmir-xqa.no", 2, false}, + {1, "hammerfest.no", 2, false}, + {1, "hammarfeasta.no", 2, false}, + {1, "xn--hmmrfeasta-s4ac.no", 2, false}, + {1, "haram.no", 2, false}, + {1, "hareid.no", 2, false}, + {1, "harstad.no", 2, false}, + {1, "hasvik.no", 2, false}, + {1, "aknoluokta.no", 2, false}, + {1, "xn--koluokta-7ya57h.no", 2, false}, + {1, "hattfjelldal.no", 2, false}, + {1, "aarborte.no", 2, false}, + {1, "haugesund.no", 2, false}, + {1, "hemne.no", 2, false}, + {1, "hemnes.no", 2, false}, + {1, "hemsedal.no", 2, false}, + {1, "heroy.more-og-romsdal.no", 3, false}, + {1, "xn--hery-ira.xn--mre-og-romsdal-qqb.no", 3, false}, + {1, "heroy.nordland.no", 3, false}, + {1, "xn--hery-ira.nordland.no", 3, false}, + {1, "hitra.no", 2, false}, + {1, "hjartdal.no", 2, false}, + {1, "hjelmeland.no", 2, false}, + {1, "hobol.no", 2, false}, + {1, "xn--hobl-ira.no", 2, false}, + {1, "hof.no", 2, false}, + {1, "hol.no", 2, false}, + {1, "hole.no", 2, false}, + {1, "holmestrand.no", 2, false}, + {1, "holtalen.no", 2, false}, + {1, "xn--holtlen-hxa.no", 2, false}, + {1, "hornindal.no", 2, false}, + {1, "horten.no", 2, false}, + {1, "hurdal.no", 2, false}, + {1, "hurum.no", 2, false}, + {1, "hvaler.no", 2, false}, + {1, "hyllestad.no", 2, false}, + {1, "hagebostad.no", 2, false}, + {1, "xn--hgebostad-g3a.no", 2, false}, + {1, "hoyanger.no", 2, false}, + {1, "xn--hyanger-q1a.no", 2, false}, + {1, "hoylandet.no", 2, false}, + {1, "xn--hylandet-54a.no", 2, false}, + {1, "ha.no", 2, false}, + {1, "xn--h-2fa.no", 2, false}, + {1, "ibestad.no", 2, false}, + {1, "inderoy.no", 2, false}, + {1, "xn--indery-fya.no", 2, false}, + {1, "iveland.no", 2, false}, + {1, "jevnaker.no", 2, false}, + {1, "jondal.no", 2, false}, + {1, "jolster.no", 2, false}, + {1, "xn--jlster-bya.no", 2, false}, + {1, "karasjok.no", 2, false}, + {1, "karasjohka.no", 2, false}, + {1, "xn--krjohka-hwab49j.no", 2, false}, + {1, "karlsoy.no", 2, false}, + {1, "galsa.no", 2, false}, + {1, "xn--gls-elac.no", 2, false}, + {1, "karmoy.no", 2, false}, + {1, "xn--karmy-yua.no", 2, false}, + {1, "kautokeino.no", 2, false}, + {1, "guovdageaidnu.no", 2, false}, + {1, "klepp.no", 2, false}, + {1, "klabu.no", 2, false}, + {1, "xn--klbu-woa.no", 2, false}, + {1, "kongsberg.no", 2, false}, + {1, "kongsvinger.no", 2, false}, + {1, "kragero.no", 2, false}, + {1, "xn--krager-gya.no", 2, false}, + {1, "kristiansand.no", 2, false}, + {1, "kristiansund.no", 2, false}, + {1, "krodsherad.no", 2, false}, + {1, "xn--krdsherad-m8a.no", 2, false}, + {1, "kvalsund.no", 2, false}, + {1, "rahkkeravju.no", 2, false}, + {1, "xn--rhkkervju-01af.no", 2, false}, + {1, "kvam.no", 2, false}, + {1, "kvinesdal.no", 2, false}, + {1, "kvinnherad.no", 2, false}, + {1, "kviteseid.no", 2, false}, + {1, "kvitsoy.no", 2, false}, + {1, "xn--kvitsy-fya.no", 2, false}, + {1, "kvafjord.no", 2, false}, + {1, "xn--kvfjord-nxa.no", 2, false}, + {1, "giehtavuoatna.no", 2, false}, + {1, "kvanangen.no", 2, false}, + {1, "xn--kvnangen-k0a.no", 2, false}, + {1, "navuotna.no", 2, false}, + {1, "xn--nvuotna-hwa.no", 2, false}, + {1, "kafjord.no", 2, false}, + {1, "xn--kfjord-iua.no", 2, false}, + {1, "gaivuotna.no", 2, false}, + {1, "xn--givuotna-8ya.no", 2, false}, + {1, "larvik.no", 2, false}, + {1, "lavangen.no", 2, false}, + {1, "lavagis.no", 2, false}, + {1, "loabat.no", 2, false}, + {1, "xn--loabt-0qa.no", 2, false}, + {1, "lebesby.no", 2, false}, + {1, "davvesiida.no", 2, false}, + {1, "leikanger.no", 2, false}, + {1, "leirfjord.no", 2, false}, + {1, "leka.no", 2, false}, + {1, "leksvik.no", 2, false}, + {1, "lenvik.no", 2, false}, + {1, "leangaviika.no", 2, false}, + {1, "xn--leagaviika-52b.no", 2, false}, + {1, "lesja.no", 2, false}, + {1, "levanger.no", 2, false}, + {1, "lier.no", 2, false}, + {1, "lierne.no", 2, false}, + {1, "lillehammer.no", 2, false}, + {1, "lillesand.no", 2, false}, + {1, "lindesnes.no", 2, false}, + {1, "lindas.no", 2, false}, + {1, "xn--linds-pra.no", 2, false}, + {1, "lom.no", 2, false}, + {1, "loppa.no", 2, false}, + {1, "lahppi.no", 2, false}, + {1, "xn--lhppi-xqa.no", 2, false}, + {1, "lund.no", 2, false}, + {1, "lunner.no", 2, false}, + {1, "luroy.no", 2, false}, + {1, "xn--lury-ira.no", 2, false}, + {1, "luster.no", 2, false}, + {1, "lyngdal.no", 2, false}, + {1, "lyngen.no", 2, false}, + {1, "ivgu.no", 2, false}, + {1, "lardal.no", 2, false}, + {1, "lerdal.no", 2, false}, + {1, "xn--lrdal-sra.no", 2, false}, + {1, "lodingen.no", 2, false}, + {1, "xn--ldingen-q1a.no", 2, false}, + {1, "lorenskog.no", 2, false}, + {1, "xn--lrenskog-54a.no", 2, false}, + {1, "loten.no", 2, false}, + {1, "xn--lten-gra.no", 2, false}, + {1, "malvik.no", 2, false}, + {1, "masoy.no", 2, false}, + {1, "xn--msy-ula0h.no", 2, false}, + {1, "muosat.no", 2, false}, + {1, "xn--muost-0qa.no", 2, false}, + {1, "mandal.no", 2, false}, + {1, "marker.no", 2, false}, + {1, "marnardal.no", 2, false}, + {1, "masfjorden.no", 2, false}, + {1, "meland.no", 2, false}, + {1, "meldal.no", 2, false}, + {1, "melhus.no", 2, false}, + {1, "meloy.no", 2, false}, + {1, "xn--mely-ira.no", 2, false}, + {1, "meraker.no", 2, false}, + {1, "xn--merker-kua.no", 2, false}, + {1, "moareke.no", 2, false}, + {1, "xn--moreke-jua.no", 2, false}, + {1, "midsund.no", 2, false}, + {1, "midtre-gauldal.no", 2, false}, + {1, "modalen.no", 2, false}, + {1, "modum.no", 2, false}, + {1, "molde.no", 2, false}, + {1, "moskenes.no", 2, false}, + {1, "moss.no", 2, false}, + {1, "mosvik.no", 2, false}, + {1, "malselv.no", 2, false}, + {1, "xn--mlselv-iua.no", 2, false}, + {1, "malatvuopmi.no", 2, false}, + {1, "xn--mlatvuopmi-s4a.no", 2, false}, + {1, "namdalseid.no", 2, false}, + {1, "aejrie.no", 2, false}, + {1, "namsos.no", 2, false}, + {1, "namsskogan.no", 2, false}, + {1, "naamesjevuemie.no", 2, false}, + {1, "xn--nmesjevuemie-tcba.no", 2, false}, + {1, "laakesvuemie.no", 2, false}, + {1, "nannestad.no", 2, false}, + {1, "narvik.no", 2, false}, + {1, "narviika.no", 2, false}, + {1, "naustdal.no", 2, false}, + {1, "nedre-eiker.no", 2, false}, + {1, "nes.akershus.no", 3, false}, + {1, "nes.buskerud.no", 3, false}, + {1, "nesna.no", 2, false}, + {1, "nesodden.no", 2, false}, + {1, "nesseby.no", 2, false}, + {1, "unjarga.no", 2, false}, + {1, "xn--unjrga-rta.no", 2, false}, + {1, "nesset.no", 2, false}, + {1, "nissedal.no", 2, false}, + {1, "nittedal.no", 2, false}, + {1, "nord-aurdal.no", 2, false}, + {1, "nord-fron.no", 2, false}, + {1, "nord-odal.no", 2, false}, + {1, "norddal.no", 2, false}, + {1, "nordkapp.no", 2, false}, + {1, "davvenjarga.no", 2, false}, + {1, "xn--davvenjrga-y4a.no", 2, false}, + {1, "nordre-land.no", 2, false}, + {1, "nordreisa.no", 2, false}, + {1, "raisa.no", 2, false}, + {1, "xn--risa-5na.no", 2, false}, + {1, "nore-og-uvdal.no", 2, false}, + {1, "notodden.no", 2, false}, + {1, "naroy.no", 2, false}, + {1, "xn--nry-yla5g.no", 2, false}, + {1, "notteroy.no", 2, false}, + {1, "xn--nttery-byae.no", 2, false}, + {1, "odda.no", 2, false}, + {1, "oksnes.no", 2, false}, + {1, "xn--ksnes-uua.no", 2, false}, + {1, "oppdal.no", 2, false}, + {1, "oppegard.no", 2, false}, + {1, "xn--oppegrd-ixa.no", 2, false}, + {1, "orkdal.no", 2, false}, + {1, "orland.no", 2, false}, + {1, "xn--rland-uua.no", 2, false}, + {1, "orskog.no", 2, false}, + {1, "xn--rskog-uua.no", 2, false}, + {1, "orsta.no", 2, false}, + {1, "xn--rsta-fra.no", 2, false}, + {1, "os.hedmark.no", 3, false}, + {1, "os.hordaland.no", 3, false}, + {1, "osen.no", 2, false}, + {1, "osteroy.no", 2, false}, + {1, "xn--ostery-fya.no", 2, false}, + {1, "ostre-toten.no", 2, false}, + {1, "xn--stre-toten-zcb.no", 2, false}, + {1, "overhalla.no", 2, false}, + {1, "ovre-eiker.no", 2, false}, + {1, "xn--vre-eiker-k8a.no", 2, false}, + {1, "oyer.no", 2, false}, + {1, "xn--yer-zna.no", 2, false}, + {1, "oygarden.no", 2, false}, + {1, "xn--ygarden-p1a.no", 2, false}, + {1, "oystre-slidre.no", 2, false}, + {1, "xn--ystre-slidre-ujb.no", 2, false}, + {1, "porsanger.no", 2, false}, + {1, "porsangu.no", 2, false}, + {1, "xn--porsgu-sta26f.no", 2, false}, + {1, "porsgrunn.no", 2, false}, + {1, "radoy.no", 2, false}, + {1, "xn--rady-ira.no", 2, false}, + {1, "rakkestad.no", 2, false}, + {1, "rana.no", 2, false}, + {1, "ruovat.no", 2, false}, + {1, "randaberg.no", 2, false}, + {1, "rauma.no", 2, false}, + {1, "rendalen.no", 2, false}, + {1, "rennebu.no", 2, false}, + {1, "rennesoy.no", 2, false}, + {1, "xn--rennesy-v1a.no", 2, false}, + {1, "rindal.no", 2, false}, + {1, "ringebu.no", 2, false}, + {1, "ringerike.no", 2, false}, + {1, "ringsaker.no", 2, false}, + {1, "rissa.no", 2, false}, + {1, "risor.no", 2, false}, + {1, "xn--risr-ira.no", 2, false}, + {1, "roan.no", 2, false}, + {1, "rollag.no", 2, false}, + {1, "rygge.no", 2, false}, + {1, "ralingen.no", 2, false}, + {1, "xn--rlingen-mxa.no", 2, false}, + {1, "rodoy.no", 2, false}, + {1, "xn--rdy-0nab.no", 2, false}, + {1, "romskog.no", 2, false}, + {1, "xn--rmskog-bya.no", 2, false}, + {1, "roros.no", 2, false}, + {1, "xn--rros-gra.no", 2, false}, + {1, "rost.no", 2, false}, + {1, "xn--rst-0na.no", 2, false}, + {1, "royken.no", 2, false}, + {1, "xn--ryken-vua.no", 2, false}, + {1, "royrvik.no", 2, false}, + {1, "xn--ryrvik-bya.no", 2, false}, + {1, "rade.no", 2, false}, + {1, "xn--rde-ula.no", 2, false}, + {1, "salangen.no", 2, false}, + {1, "siellak.no", 2, false}, + {1, "saltdal.no", 2, false}, + {1, "salat.no", 2, false}, + {1, "xn--slt-elab.no", 2, false}, + {1, "xn--slat-5na.no", 2, false}, + {1, "samnanger.no", 2, false}, + {1, "sande.more-og-romsdal.no", 3, false}, + {1, "sande.xn--mre-og-romsdal-qqb.no", 3, false}, + {1, "sande.vestfold.no", 3, false}, + {1, "sandefjord.no", 2, false}, + {1, "sandnes.no", 2, false}, + {1, "sandoy.no", 2, false}, + {1, "xn--sandy-yua.no", 2, false}, + {1, "sarpsborg.no", 2, false}, + {1, "sauda.no", 2, false}, + {1, "sauherad.no", 2, false}, + {1, "sel.no", 2, false}, + {1, "selbu.no", 2, false}, + {1, "selje.no", 2, false}, + {1, "seljord.no", 2, false}, + {1, "sigdal.no", 2, false}, + {1, "siljan.no", 2, false}, + {1, "sirdal.no", 2, false}, + {1, "skaun.no", 2, false}, + {1, "skedsmo.no", 2, false}, + {1, "ski.no", 2, false}, + {1, "skien.no", 2, false}, + {1, "skiptvet.no", 2, false}, + {1, "skjervoy.no", 2, false}, + {1, "xn--skjervy-v1a.no", 2, false}, + {1, "skierva.no", 2, false}, + {1, "xn--skierv-uta.no", 2, false}, + {1, "skjak.no", 2, false}, + {1, "xn--skjk-soa.no", 2, false}, + {1, "skodje.no", 2, false}, + {1, "skanland.no", 2, false}, + {1, "xn--sknland-fxa.no", 2, false}, + {1, "skanit.no", 2, false}, + {1, "xn--sknit-yqa.no", 2, false}, + {1, "smola.no", 2, false}, + {1, "xn--smla-hra.no", 2, false}, + {1, "snillfjord.no", 2, false}, + {1, "snasa.no", 2, false}, + {1, "xn--snsa-roa.no", 2, false}, + {1, "snoasa.no", 2, false}, + {1, "snaase.no", 2, false}, + {1, "xn--snase-nra.no", 2, false}, + {1, "sogndal.no", 2, false}, + {1, "sokndal.no", 2, false}, + {1, "sola.no", 2, false}, + {1, "solund.no", 2, false}, + {1, "songdalen.no", 2, false}, + {1, "sortland.no", 2, false}, + {1, "spydeberg.no", 2, false}, + {1, "stange.no", 2, false}, + {1, "stavanger.no", 2, false}, + {1, "steigen.no", 2, false}, + {1, "steinkjer.no", 2, false}, + {1, "stjordal.no", 2, false}, + {1, "xn--stjrdal-s1a.no", 2, false}, + {1, "stokke.no", 2, false}, + {1, "stor-elvdal.no", 2, false}, + {1, "stord.no", 2, false}, + {1, "stordal.no", 2, false}, + {1, "storfjord.no", 2, false}, + {1, "omasvuotna.no", 2, false}, + {1, "strand.no", 2, false}, + {1, "stranda.no", 2, false}, + {1, "stryn.no", 2, false}, + {1, "sula.no", 2, false}, + {1, "suldal.no", 2, false}, + {1, "sund.no", 2, false}, + {1, "sunndal.no", 2, false}, + {1, "surnadal.no", 2, false}, + {1, "sveio.no", 2, false}, + {1, "svelvik.no", 2, false}, + {1, "sykkylven.no", 2, false}, + {1, "sogne.no", 2, false}, + {1, "xn--sgne-gra.no", 2, false}, + {1, "somna.no", 2, false}, + {1, "xn--smna-gra.no", 2, false}, + {1, "sondre-land.no", 2, false}, + {1, "xn--sndre-land-0cb.no", 2, false}, + {1, "sor-aurdal.no", 2, false}, + {1, "xn--sr-aurdal-l8a.no", 2, false}, + {1, "sor-fron.no", 2, false}, + {1, "xn--sr-fron-q1a.no", 2, false}, + {1, "sor-odal.no", 2, false}, + {1, "xn--sr-odal-q1a.no", 2, false}, + {1, "sor-varanger.no", 2, false}, + {1, "xn--sr-varanger-ggb.no", 2, false}, + {1, "matta-varjjat.no", 2, false}, + {1, "xn--mtta-vrjjat-k7af.no", 2, false}, + {1, "sorfold.no", 2, false}, + {1, "xn--srfold-bya.no", 2, false}, + {1, "sorreisa.no", 2, false}, + {1, "xn--srreisa-q1a.no", 2, false}, + {1, "sorum.no", 2, false}, + {1, "xn--srum-gra.no", 2, false}, + {1, "tana.no", 2, false}, + {1, "deatnu.no", 2, false}, + {1, "time.no", 2, false}, + {1, "tingvoll.no", 2, false}, + {1, "tinn.no", 2, false}, + {1, "tjeldsund.no", 2, false}, + {1, "dielddanuorri.no", 2, false}, + {1, "tjome.no", 2, false}, + {1, "xn--tjme-hra.no", 2, false}, + {1, "tokke.no", 2, false}, + {1, "tolga.no", 2, false}, + {1, "torsken.no", 2, false}, + {1, "tranoy.no", 2, false}, + {1, "xn--trany-yua.no", 2, false}, + {1, "tromso.no", 2, false}, + {1, "xn--troms-zua.no", 2, false}, + {1, "tromsa.no", 2, false}, + {1, "romsa.no", 2, false}, + {1, "trondheim.no", 2, false}, + {1, "troandin.no", 2, false}, + {1, "trysil.no", 2, false}, + {1, "trana.no", 2, false}, + {1, "xn--trna-woa.no", 2, false}, + {1, "trogstad.no", 2, false}, + {1, "xn--trgstad-r1a.no", 2, false}, + {1, "tvedestrand.no", 2, false}, + {1, "tydal.no", 2, false}, + {1, "tynset.no", 2, false}, + {1, "tysfjord.no", 2, false}, + {1, "divtasvuodna.no", 2, false}, + {1, "divttasvuotna.no", 2, false}, + {1, "tysnes.no", 2, false}, + {1, "tysvar.no", 2, false}, + {1, "xn--tysvr-vra.no", 2, false}, + {1, "tonsberg.no", 2, false}, + {1, "xn--tnsberg-q1a.no", 2, false}, + {1, "ullensaker.no", 2, false}, + {1, "ullensvang.no", 2, false}, + {1, "ulvik.no", 2, false}, + {1, "utsira.no", 2, false}, + {1, "vadso.no", 2, false}, + {1, "xn--vads-jra.no", 2, false}, + {1, "cahcesuolo.no", 2, false}, + {1, "xn--hcesuolo-7ya35b.no", 2, false}, + {1, "vaksdal.no", 2, false}, + {1, "valle.no", 2, false}, + {1, "vang.no", 2, false}, + {1, "vanylven.no", 2, false}, + {1, "vardo.no", 2, false}, + {1, "xn--vard-jra.no", 2, false}, + {1, "varggat.no", 2, false}, + {1, "xn--vrggt-xqad.no", 2, false}, + {1, "vefsn.no", 2, false}, + {1, "vaapste.no", 2, false}, + {1, "vega.no", 2, false}, + {1, "vegarshei.no", 2, false}, + {1, "xn--vegrshei-c0a.no", 2, false}, + {1, "vennesla.no", 2, false}, + {1, "verdal.no", 2, false}, + {1, "verran.no", 2, false}, + {1, "vestby.no", 2, false}, + {1, "vestnes.no", 2, false}, + {1, "vestre-slidre.no", 2, false}, + {1, "vestre-toten.no", 2, false}, + {1, "vestvagoy.no", 2, false}, + {1, "xn--vestvgy-ixa6o.no", 2, false}, + {1, "vevelstad.no", 2, false}, + {1, "vik.no", 2, false}, + {1, "vikna.no", 2, false}, + {1, "vindafjord.no", 2, false}, + {1, "volda.no", 2, false}, + {1, "voss.no", 2, false}, + {1, "varoy.no", 2, false}, + {1, "xn--vry-yla5g.no", 2, false}, + {1, "vagan.no", 2, false}, + {1, "xn--vgan-qoa.no", 2, false}, + {1, "voagat.no", 2, false}, + {1, "vagsoy.no", 2, false}, + {1, "xn--vgsy-qoa0j.no", 2, false}, + {1, "vaga.no", 2, false}, + {1, "xn--vg-yiab.no", 2, false}, + {1, "valer.ostfold.no", 3, false}, + {1, "xn--vler-qoa.xn--stfold-9xa.no", 3, false}, + {1, "valer.hedmark.no", 3, false}, + {1, "xn--vler-qoa.hedmark.no", 3, false}, + {2, "np", 2, false}, + {1, "nr", 1, false}, + {1, "biz.nr", 2, false}, + {1, "info.nr", 2, false}, + {1, "gov.nr", 2, false}, + {1, "edu.nr", 2, false}, + {1, "org.nr", 2, false}, + {1, "net.nr", 2, false}, + {1, "com.nr", 2, false}, + {1, "nu", 1, false}, + {1, "nz", 1, false}, + {1, "ac.nz", 2, false}, + {1, "co.nz", 2, false}, + {1, "cri.nz", 2, false}, + {1, "geek.nz", 2, false}, + {1, "gen.nz", 2, false}, + {1, "govt.nz", 2, false}, + {1, "health.nz", 2, false}, + {1, "iwi.nz", 2, false}, + {1, "kiwi.nz", 2, false}, + {1, "maori.nz", 2, false}, + {1, "mil.nz", 2, false}, + {1, "xn--mori-qsa.nz", 2, false}, + {1, "net.nz", 2, false}, + {1, "org.nz", 2, false}, + {1, "parliament.nz", 2, false}, + {1, "school.nz", 2, false}, + {1, "om", 1, false}, + {1, "co.om", 2, false}, + {1, "com.om", 2, false}, + {1, "edu.om", 2, false}, + {1, "gov.om", 2, false}, + {1, "med.om", 2, false}, + {1, "museum.om", 2, false}, + {1, "net.om", 2, false}, + {1, "org.om", 2, false}, + {1, "pro.om", 2, false}, + {1, "onion", 1, false}, + {1, "org", 1, false}, + {1, "pa", 1, false}, + {1, "ac.pa", 2, false}, + {1, "gob.pa", 2, false}, + {1, "com.pa", 2, false}, + {1, "org.pa", 2, false}, + {1, "sld.pa", 2, false}, + {1, "edu.pa", 2, false}, + {1, "net.pa", 2, false}, + {1, "ing.pa", 2, false}, + {1, "abo.pa", 2, false}, + {1, "med.pa", 2, false}, + {1, "nom.pa", 2, false}, + {1, "pe", 1, false}, + {1, "edu.pe", 2, false}, + {1, "gob.pe", 2, false}, + {1, "nom.pe", 2, false}, + {1, "mil.pe", 2, false}, + {1, "org.pe", 2, false}, + {1, "com.pe", 2, false}, + {1, "net.pe", 2, false}, + {1, "pf", 1, false}, + {1, "com.pf", 2, false}, + {1, "org.pf", 2, false}, + {1, "edu.pf", 2, false}, + {2, "pg", 2, false}, + {1, "ph", 1, false}, + {1, "com.ph", 2, false}, + {1, "net.ph", 2, false}, + {1, "org.ph", 2, false}, + {1, "gov.ph", 2, false}, + {1, "edu.ph", 2, false}, + {1, "ngo.ph", 2, false}, + {1, "mil.ph", 2, false}, + {1, "i.ph", 2, false}, + {1, "pk", 1, false}, + {1, "com.pk", 2, false}, + {1, "net.pk", 2, false}, + {1, "edu.pk", 2, false}, + {1, "org.pk", 2, false}, + {1, "fam.pk", 2, false}, + {1, "biz.pk", 2, false}, + {1, "web.pk", 2, false}, + {1, "gov.pk", 2, false}, + {1, "gob.pk", 2, false}, + {1, "gok.pk", 2, false}, + {1, "gon.pk", 2, false}, + {1, "gop.pk", 2, false}, + {1, "gos.pk", 2, false}, + {1, "info.pk", 2, false}, + {1, "pl", 1, false}, + {1, "com.pl", 2, false}, + {1, "net.pl", 2, false}, + {1, "org.pl", 2, false}, + {1, "aid.pl", 2, false}, + {1, "agro.pl", 2, false}, + {1, "atm.pl", 2, false}, + {1, "auto.pl", 2, false}, + {1, "biz.pl", 2, false}, + {1, "edu.pl", 2, false}, + {1, "gmina.pl", 2, false}, + {1, "gsm.pl", 2, false}, + {1, "info.pl", 2, false}, + {1, "mail.pl", 2, false}, + {1, "miasta.pl", 2, false}, + {1, "media.pl", 2, false}, + {1, "mil.pl", 2, false}, + {1, "nieruchomosci.pl", 2, false}, + {1, "nom.pl", 2, false}, + {1, "pc.pl", 2, false}, + {1, "powiat.pl", 2, false}, + {1, "priv.pl", 2, false}, + {1, "realestate.pl", 2, false}, + {1, "rel.pl", 2, false}, + {1, "sex.pl", 2, false}, + {1, "shop.pl", 2, false}, + {1, "sklep.pl", 2, false}, + {1, "sos.pl", 2, false}, + {1, "szkola.pl", 2, false}, + {1, "targi.pl", 2, false}, + {1, "tm.pl", 2, false}, + {1, "tourism.pl", 2, false}, + {1, "travel.pl", 2, false}, + {1, "turystyka.pl", 2, false}, + {1, "gov.pl", 2, false}, + {1, "ap.gov.pl", 3, false}, + {1, "ic.gov.pl", 3, false}, + {1, "is.gov.pl", 3, false}, + {1, "us.gov.pl", 3, false}, + {1, "kmpsp.gov.pl", 3, false}, + {1, "kppsp.gov.pl", 3, false}, + {1, "kwpsp.gov.pl", 3, false}, + {1, "psp.gov.pl", 3, false}, + {1, "wskr.gov.pl", 3, false}, + {1, "kwp.gov.pl", 3, false}, + {1, "mw.gov.pl", 3, false}, + {1, "ug.gov.pl", 3, false}, + {1, "um.gov.pl", 3, false}, + {1, "umig.gov.pl", 3, false}, + {1, "ugim.gov.pl", 3, false}, + {1, "upow.gov.pl", 3, false}, + {1, "uw.gov.pl", 3, false}, + {1, "starostwo.gov.pl", 3, false}, + {1, "pa.gov.pl", 3, false}, + {1, "po.gov.pl", 3, false}, + {1, "psse.gov.pl", 3, false}, + {1, "pup.gov.pl", 3, false}, + {1, "rzgw.gov.pl", 3, false}, + {1, "sa.gov.pl", 3, false}, + {1, "so.gov.pl", 3, false}, + {1, "sr.gov.pl", 3, false}, + {1, "wsa.gov.pl", 3, false}, + {1, "sko.gov.pl", 3, false}, + {1, "uzs.gov.pl", 3, false}, + {1, "wiih.gov.pl", 3, false}, + {1, "winb.gov.pl", 3, false}, + {1, "pinb.gov.pl", 3, false}, + {1, "wios.gov.pl", 3, false}, + {1, "witd.gov.pl", 3, false}, + {1, "wzmiuw.gov.pl", 3, false}, + {1, "piw.gov.pl", 3, false}, + {1, "wiw.gov.pl", 3, false}, + {1, "griw.gov.pl", 3, false}, + {1, "wif.gov.pl", 3, false}, + {1, "oum.gov.pl", 3, false}, + {1, "sdn.gov.pl", 3, false}, + {1, "zp.gov.pl", 3, false}, + {1, "uppo.gov.pl", 3, false}, + {1, "mup.gov.pl", 3, false}, + {1, "wuoz.gov.pl", 3, false}, + {1, "konsulat.gov.pl", 3, false}, + {1, "oirm.gov.pl", 3, false}, + {1, "augustow.pl", 2, false}, + {1, "babia-gora.pl", 2, false}, + {1, "bedzin.pl", 2, false}, + {1, "beskidy.pl", 2, false}, + {1, "bialowieza.pl", 2, false}, + {1, "bialystok.pl", 2, false}, + {1, "bielawa.pl", 2, false}, + {1, "bieszczady.pl", 2, false}, + {1, "boleslawiec.pl", 2, false}, + {1, "bydgoszcz.pl", 2, false}, + {1, "bytom.pl", 2, false}, + {1, "cieszyn.pl", 2, false}, + {1, "czeladz.pl", 2, false}, + {1, "czest.pl", 2, false}, + {1, "dlugoleka.pl", 2, false}, + {1, "elblag.pl", 2, false}, + {1, "elk.pl", 2, false}, + {1, "glogow.pl", 2, false}, + {1, "gniezno.pl", 2, false}, + {1, "gorlice.pl", 2, false}, + {1, "grajewo.pl", 2, false}, + {1, "ilawa.pl", 2, false}, + {1, "jaworzno.pl", 2, false}, + {1, "jelenia-gora.pl", 2, false}, + {1, "jgora.pl", 2, false}, + {1, "kalisz.pl", 2, false}, + {1, "kazimierz-dolny.pl", 2, false}, + {1, "karpacz.pl", 2, false}, + {1, "kartuzy.pl", 2, false}, + {1, "kaszuby.pl", 2, false}, + {1, "katowice.pl", 2, false}, + {1, "kepno.pl", 2, false}, + {1, "ketrzyn.pl", 2, false}, + {1, "klodzko.pl", 2, false}, + {1, "kobierzyce.pl", 2, false}, + {1, "kolobrzeg.pl", 2, false}, + {1, "konin.pl", 2, false}, + {1, "konskowola.pl", 2, false}, + {1, "kutno.pl", 2, false}, + {1, "lapy.pl", 2, false}, + {1, "lebork.pl", 2, false}, + {1, "legnica.pl", 2, false}, + {1, "lezajsk.pl", 2, false}, + {1, "limanowa.pl", 2, false}, + {1, "lomza.pl", 2, false}, + {1, "lowicz.pl", 2, false}, + {1, "lubin.pl", 2, false}, + {1, "lukow.pl", 2, false}, + {1, "malbork.pl", 2, false}, + {1, "malopolska.pl", 2, false}, + {1, "mazowsze.pl", 2, false}, + {1, "mazury.pl", 2, false}, + {1, "mielec.pl", 2, false}, + {1, "mielno.pl", 2, false}, + {1, "mragowo.pl", 2, false}, + {1, "naklo.pl", 2, false}, + {1, "nowaruda.pl", 2, false}, + {1, "nysa.pl", 2, false}, + {1, "olawa.pl", 2, false}, + {1, "olecko.pl", 2, false}, + {1, "olkusz.pl", 2, false}, + {1, "olsztyn.pl", 2, false}, + {1, "opoczno.pl", 2, false}, + {1, "opole.pl", 2, false}, + {1, "ostroda.pl", 2, false}, + {1, "ostroleka.pl", 2, false}, + {1, "ostrowiec.pl", 2, false}, + {1, "ostrowwlkp.pl", 2, false}, + {1, "pila.pl", 2, false}, + {1, "pisz.pl", 2, false}, + {1, "podhale.pl", 2, false}, + {1, "podlasie.pl", 2, false}, + {1, "polkowice.pl", 2, false}, + {1, "pomorze.pl", 2, false}, + {1, "pomorskie.pl", 2, false}, + {1, "prochowice.pl", 2, false}, + {1, "pruszkow.pl", 2, false}, + {1, "przeworsk.pl", 2, false}, + {1, "pulawy.pl", 2, false}, + {1, "radom.pl", 2, false}, + {1, "rawa-maz.pl", 2, false}, + {1, "rybnik.pl", 2, false}, + {1, "rzeszow.pl", 2, false}, + {1, "sanok.pl", 2, false}, + {1, "sejny.pl", 2, false}, + {1, "slask.pl", 2, false}, + {1, "slupsk.pl", 2, false}, + {1, "sosnowiec.pl", 2, false}, + {1, "stalowa-wola.pl", 2, false}, + {1, "skoczow.pl", 2, false}, + {1, "starachowice.pl", 2, false}, + {1, "stargard.pl", 2, false}, + {1, "suwalki.pl", 2, false}, + {1, "swidnica.pl", 2, false}, + {1, "swiebodzin.pl", 2, false}, + {1, "swinoujscie.pl", 2, false}, + {1, "szczecin.pl", 2, false}, + {1, "szczytno.pl", 2, false}, + {1, "tarnobrzeg.pl", 2, false}, + {1, "tgory.pl", 2, false}, + {1, "turek.pl", 2, false}, + {1, "tychy.pl", 2, false}, + {1, "ustka.pl", 2, false}, + {1, "walbrzych.pl", 2, false}, + {1, "warmia.pl", 2, false}, + {1, "warszawa.pl", 2, false}, + {1, "waw.pl", 2, false}, + {1, "wegrow.pl", 2, false}, + {1, "wielun.pl", 2, false}, + {1, "wlocl.pl", 2, false}, + {1, "wloclawek.pl", 2, false}, + {1, "wodzislaw.pl", 2, false}, + {1, "wolomin.pl", 2, false}, + {1, "wroclaw.pl", 2, false}, + {1, "zachpomor.pl", 2, false}, + {1, "zagan.pl", 2, false}, + {1, "zarow.pl", 2, false}, + {1, "zgora.pl", 2, false}, + {1, "zgorzelec.pl", 2, false}, + {1, "pm", 1, false}, + {1, "pn", 1, false}, + {1, "gov.pn", 2, false}, + {1, "co.pn", 2, false}, + {1, "org.pn", 2, false}, + {1, "edu.pn", 2, false}, + {1, "net.pn", 2, false}, + {1, "post", 1, false}, + {1, "pr", 1, false}, + {1, "com.pr", 2, false}, + {1, "net.pr", 2, false}, + {1, "org.pr", 2, false}, + {1, "gov.pr", 2, false}, + {1, "edu.pr", 2, false}, + {1, "isla.pr", 2, false}, + {1, "pro.pr", 2, false}, + {1, "biz.pr", 2, false}, + {1, "info.pr", 2, false}, + {1, "name.pr", 2, false}, + {1, "est.pr", 2, false}, + {1, "prof.pr", 2, false}, + {1, "ac.pr", 2, false}, + {1, "pro", 1, false}, + {1, "aaa.pro", 2, false}, + {1, "aca.pro", 2, false}, + {1, "acct.pro", 2, false}, + {1, "avocat.pro", 2, false}, + {1, "bar.pro", 2, false}, + {1, "cpa.pro", 2, false}, + {1, "eng.pro", 2, false}, + {1, "jur.pro", 2, false}, + {1, "law.pro", 2, false}, + {1, "med.pro", 2, false}, + {1, "recht.pro", 2, false}, + {1, "ps", 1, false}, + {1, "edu.ps", 2, false}, + {1, "gov.ps", 2, false}, + {1, "sec.ps", 2, false}, + {1, "plo.ps", 2, false}, + {1, "com.ps", 2, false}, + {1, "org.ps", 2, false}, + {1, "net.ps", 2, false}, + {1, "pt", 1, false}, + {1, "net.pt", 2, false}, + {1, "gov.pt", 2, false}, + {1, "org.pt", 2, false}, + {1, "edu.pt", 2, false}, + {1, "int.pt", 2, false}, + {1, "publ.pt", 2, false}, + {1, "com.pt", 2, false}, + {1, "nome.pt", 2, false}, + {1, "pw", 1, false}, + {1, "co.pw", 2, false}, + {1, "ne.pw", 2, false}, + {1, "or.pw", 2, false}, + {1, "ed.pw", 2, false}, + {1, "go.pw", 2, false}, + {1, "belau.pw", 2, false}, + {1, "py", 1, false}, + {1, "com.py", 2, false}, + {1, "coop.py", 2, false}, + {1, "edu.py", 2, false}, + {1, "gov.py", 2, false}, + {1, "mil.py", 2, false}, + {1, "net.py", 2, false}, + {1, "org.py", 2, false}, + {1, "qa", 1, false}, + {1, "com.qa", 2, false}, + {1, "edu.qa", 2, false}, + {1, "gov.qa", 2, false}, + {1, "mil.qa", 2, false}, + {1, "name.qa", 2, false}, + {1, "net.qa", 2, false}, + {1, "org.qa", 2, false}, + {1, "sch.qa", 2, false}, + {1, "re", 1, false}, + {1, "asso.re", 2, false}, + {1, "com.re", 2, false}, + {1, "nom.re", 2, false}, + {1, "ro", 1, false}, + {1, "arts.ro", 2, false}, + {1, "com.ro", 2, false}, + {1, "firm.ro", 2, false}, + {1, "info.ro", 2, false}, + {1, "nom.ro", 2, false}, + {1, "nt.ro", 2, false}, + {1, "org.ro", 2, false}, + {1, "rec.ro", 2, false}, + {1, "store.ro", 2, false}, + {1, "tm.ro", 2, false}, + {1, "www.ro", 2, false}, + {1, "rs", 1, false}, + {1, "ac.rs", 2, false}, + {1, "co.rs", 2, false}, + {1, "edu.rs", 2, false}, + {1, "gov.rs", 2, false}, + {1, "in.rs", 2, false}, + {1, "org.rs", 2, false}, + {1, "ru", 1, false}, + {1, "rw", 1, false}, + {1, "ac.rw", 2, false}, + {1, "co.rw", 2, false}, + {1, "coop.rw", 2, false}, + {1, "gov.rw", 2, false}, + {1, "mil.rw", 2, false}, + {1, "net.rw", 2, false}, + {1, "org.rw", 2, false}, + {1, "sa", 1, false}, + {1, "com.sa", 2, false}, + {1, "net.sa", 2, false}, + {1, "org.sa", 2, false}, + {1, "gov.sa", 2, false}, + {1, "med.sa", 2, false}, + {1, "pub.sa", 2, false}, + {1, "edu.sa", 2, false}, + {1, "sch.sa", 2, false}, + {1, "sb", 1, false}, + {1, "com.sb", 2, false}, + {1, "edu.sb", 2, false}, + {1, "gov.sb", 2, false}, + {1, "net.sb", 2, false}, + {1, "org.sb", 2, false}, + {1, "sc", 1, false}, + {1, "com.sc", 2, false}, + {1, "gov.sc", 2, false}, + {1, "net.sc", 2, false}, + {1, "org.sc", 2, false}, + {1, "edu.sc", 2, false}, + {1, "sd", 1, false}, + {1, "com.sd", 2, false}, + {1, "net.sd", 2, false}, + {1, "org.sd", 2, false}, + {1, "edu.sd", 2, false}, + {1, "med.sd", 2, false}, + {1, "tv.sd", 2, false}, + {1, "gov.sd", 2, false}, + {1, "info.sd", 2, false}, + {1, "se", 1, false}, + {1, "a.se", 2, false}, + {1, "ac.se", 2, false}, + {1, "b.se", 2, false}, + {1, "bd.se", 2, false}, + {1, "brand.se", 2, false}, + {1, "c.se", 2, false}, + {1, "d.se", 2, false}, + {1, "e.se", 2, false}, + {1, "f.se", 2, false}, + {1, "fh.se", 2, false}, + {1, "fhsk.se", 2, false}, + {1, "fhv.se", 2, false}, + {1, "g.se", 2, false}, + {1, "h.se", 2, false}, + {1, "i.se", 2, false}, + {1, "k.se", 2, false}, + {1, "komforb.se", 2, false}, + {1, "kommunalforbund.se", 2, false}, + {1, "komvux.se", 2, false}, + {1, "l.se", 2, false}, + {1, "lanbib.se", 2, false}, + {1, "m.se", 2, false}, + {1, "n.se", 2, false}, + {1, "naturbruksgymn.se", 2, false}, + {1, "o.se", 2, false}, + {1, "org.se", 2, false}, + {1, "p.se", 2, false}, + {1, "parti.se", 2, false}, + {1, "pp.se", 2, false}, + {1, "press.se", 2, false}, + {1, "r.se", 2, false}, + {1, "s.se", 2, false}, + {1, "t.se", 2, false}, + {1, "tm.se", 2, false}, + {1, "u.se", 2, false}, + {1, "w.se", 2, false}, + {1, "x.se", 2, false}, + {1, "y.se", 2, false}, + {1, "z.se", 2, false}, + {1, "sg", 1, false}, + {1, "com.sg", 2, false}, + {1, "net.sg", 2, false}, + {1, "org.sg", 2, false}, + {1, "gov.sg", 2, false}, + {1, "edu.sg", 2, false}, + {1, "per.sg", 2, false}, + {1, "sh", 1, false}, + {1, "com.sh", 2, false}, + {1, "net.sh", 2, false}, + {1, "gov.sh", 2, false}, + {1, "org.sh", 2, false}, + {1, "mil.sh", 2, false}, + {1, "si", 1, false}, + {1, "sj", 1, false}, + {1, "sk", 1, false}, + {1, "sl", 1, false}, + {1, "com.sl", 2, false}, + {1, "net.sl", 2, false}, + {1, "edu.sl", 2, false}, + {1, "gov.sl", 2, false}, + {1, "org.sl", 2, false}, + {1, "sm", 1, false}, + {1, "sn", 1, false}, + {1, "art.sn", 2, false}, + {1, "com.sn", 2, false}, + {1, "edu.sn", 2, false}, + {1, "gouv.sn", 2, false}, + {1, "org.sn", 2, false}, + {1, "perso.sn", 2, false}, + {1, "univ.sn", 2, false}, + {1, "so", 1, false}, + {1, "com.so", 2, false}, + {1, "edu.so", 2, false}, + {1, "gov.so", 2, false}, + {1, "me.so", 2, false}, + {1, "net.so", 2, false}, + {1, "org.so", 2, false}, + {1, "sr", 1, false}, + {1, "ss", 1, false}, + {1, "biz.ss", 2, false}, + {1, "com.ss", 2, false}, + {1, "edu.ss", 2, false}, + {1, "gov.ss", 2, false}, + {1, "me.ss", 2, false}, + {1, "net.ss", 2, false}, + {1, "org.ss", 2, false}, + {1, "sch.ss", 2, false}, + {1, "st", 1, false}, + {1, "co.st", 2, false}, + {1, "com.st", 2, false}, + {1, "consulado.st", 2, false}, + {1, "edu.st", 2, false}, + {1, "embaixada.st", 2, false}, + {1, "mil.st", 2, false}, + {1, "net.st", 2, false}, + {1, "org.st", 2, false}, + {1, "principe.st", 2, false}, + {1, "saotome.st", 2, false}, + {1, "store.st", 2, false}, + {1, "su", 1, false}, + {1, "sv", 1, false}, + {1, "com.sv", 2, false}, + {1, "edu.sv", 2, false}, + {1, "gob.sv", 2, false}, + {1, "org.sv", 2, false}, + {1, "red.sv", 2, false}, + {1, "sx", 1, false}, + {1, "gov.sx", 2, false}, + {1, "sy", 1, false}, + {1, "edu.sy", 2, false}, + {1, "gov.sy", 2, false}, + {1, "net.sy", 2, false}, + {1, "mil.sy", 2, false}, + {1, "com.sy", 2, false}, + {1, "org.sy", 2, false}, + {1, "sz", 1, false}, + {1, "co.sz", 2, false}, + {1, "ac.sz", 2, false}, + {1, "org.sz", 2, false}, + {1, "tc", 1, false}, + {1, "td", 1, false}, + {1, "tel", 1, false}, + {1, "tf", 1, false}, + {1, "tg", 1, false}, + {1, "th", 1, false}, + {1, "ac.th", 2, false}, + {1, "co.th", 2, false}, + {1, "go.th", 2, false}, + {1, "in.th", 2, false}, + {1, "mi.th", 2, false}, + {1, "net.th", 2, false}, + {1, "or.th", 2, false}, + {1, "tj", 1, false}, + {1, "ac.tj", 2, false}, + {1, "biz.tj", 2, false}, + {1, "co.tj", 2, false}, + {1, "com.tj", 2, false}, + {1, "edu.tj", 2, false}, + {1, "go.tj", 2, false}, + {1, "gov.tj", 2, false}, + {1, "int.tj", 2, false}, + {1, "mil.tj", 2, false}, + {1, "name.tj", 2, false}, + {1, "net.tj", 2, false}, + {1, "nic.tj", 2, false}, + {1, "org.tj", 2, false}, + {1, "test.tj", 2, false}, + {1, "web.tj", 2, false}, + {1, "tk", 1, false}, + {1, "tl", 1, false}, + {1, "gov.tl", 2, false}, + {1, "tm", 1, false}, + {1, "com.tm", 2, false}, + {1, "co.tm", 2, false}, + {1, "org.tm", 2, false}, + {1, "net.tm", 2, false}, + {1, "nom.tm", 2, false}, + {1, "gov.tm", 2, false}, + {1, "mil.tm", 2, false}, + {1, "edu.tm", 2, false}, + {1, "tn", 1, false}, + {1, "com.tn", 2, false}, + {1, "ens.tn", 2, false}, + {1, "fin.tn", 2, false}, + {1, "gov.tn", 2, false}, + {1, "ind.tn", 2, false}, + {1, "intl.tn", 2, false}, + {1, "nat.tn", 2, false}, + {1, "net.tn", 2, false}, + {1, "org.tn", 2, false}, + {1, "info.tn", 2, false}, + {1, "perso.tn", 2, false}, + {1, "tourism.tn", 2, false}, + {1, "edunet.tn", 2, false}, + {1, "rnrt.tn", 2, false}, + {1, "rns.tn", 2, false}, + {1, "rnu.tn", 2, false}, + {1, "mincom.tn", 2, false}, + {1, "agrinet.tn", 2, false}, + {1, "defense.tn", 2, false}, + {1, "turen.tn", 2, false}, + {1, "to", 1, false}, + {1, "com.to", 2, false}, + {1, "gov.to", 2, false}, + {1, "net.to", 2, false}, + {1, "org.to", 2, false}, + {1, "edu.to", 2, false}, + {1, "mil.to", 2, false}, + {1, "tr", 1, false}, + {1, "av.tr", 2, false}, + {1, "bbs.tr", 2, false}, + {1, "bel.tr", 2, false}, + {1, "biz.tr", 2, false}, + {1, "com.tr", 2, false}, + {1, "dr.tr", 2, false}, + {1, "edu.tr", 2, false}, + {1, "gen.tr", 2, false}, + {1, "gov.tr", 2, false}, + {1, "info.tr", 2, false}, + {1, "mil.tr", 2, false}, + {1, "k12.tr", 2, false}, + {1, "kep.tr", 2, false}, + {1, "name.tr", 2, false}, + {1, "net.tr", 2, false}, + {1, "org.tr", 2, false}, + {1, "pol.tr", 2, false}, + {1, "tel.tr", 2, false}, + {1, "tsk.tr", 2, false}, + {1, "tv.tr", 2, false}, + {1, "web.tr", 2, false}, + {1, "nc.tr", 2, false}, + {1, "gov.nc.tr", 3, false}, + {1, "tt", 1, false}, + {1, "co.tt", 2, false}, + {1, "com.tt", 2, false}, + {1, "org.tt", 2, false}, + {1, "net.tt", 2, false}, + {1, "biz.tt", 2, false}, + {1, "info.tt", 2, false}, + {1, "pro.tt", 2, false}, + {1, "int.tt", 2, false}, + {1, "coop.tt", 2, false}, + {1, "jobs.tt", 2, false}, + {1, "mobi.tt", 2, false}, + {1, "travel.tt", 2, false}, + {1, "museum.tt", 2, false}, + {1, "aero.tt", 2, false}, + {1, "name.tt", 2, false}, + {1, "gov.tt", 2, false}, + {1, "edu.tt", 2, false}, + {1, "tv", 1, false}, + {1, "tw", 1, false}, + {1, "edu.tw", 2, false}, + {1, "gov.tw", 2, false}, + {1, "mil.tw", 2, false}, + {1, "com.tw", 2, false}, + {1, "net.tw", 2, false}, + {1, "org.tw", 2, false}, + {1, "idv.tw", 2, false}, + {1, "game.tw", 2, false}, + {1, "ebiz.tw", 2, false}, + {1, "club.tw", 2, false}, + {1, "xn--zf0ao64a.tw", 2, false}, + {1, "xn--uc0atv.tw", 2, false}, + {1, "xn--czrw28b.tw", 2, false}, + {1, "tz", 1, false}, + {1, "ac.tz", 2, false}, + {1, "co.tz", 2, false}, + {1, "go.tz", 2, false}, + {1, "hotel.tz", 2, false}, + {1, "info.tz", 2, false}, + {1, "me.tz", 2, false}, + {1, "mil.tz", 2, false}, + {1, "mobi.tz", 2, false}, + {1, "ne.tz", 2, false}, + {1, "or.tz", 2, false}, + {1, "sc.tz", 2, false}, + {1, "tv.tz", 2, false}, + {1, "ua", 1, false}, + {1, "com.ua", 2, false}, + {1, "edu.ua", 2, false}, + {1, "gov.ua", 2, false}, + {1, "in.ua", 2, false}, + {1, "net.ua", 2, false}, + {1, "org.ua", 2, false}, + {1, "cherkassy.ua", 2, false}, + {1, "cherkasy.ua", 2, false}, + {1, "chernigov.ua", 2, false}, + {1, "chernihiv.ua", 2, false}, + {1, "chernivtsi.ua", 2, false}, + {1, "chernovtsy.ua", 2, false}, + {1, "ck.ua", 2, false}, + {1, "cn.ua", 2, false}, + {1, "cr.ua", 2, false}, + {1, "crimea.ua", 2, false}, + {1, "cv.ua", 2, false}, + {1, "dn.ua", 2, false}, + {1, "dnepropetrovsk.ua", 2, false}, + {1, "dnipropetrovsk.ua", 2, false}, + {1, "donetsk.ua", 2, false}, + {1, "dp.ua", 2, false}, + {1, "if.ua", 2, false}, + {1, "ivano-frankivsk.ua", 2, false}, + {1, "kh.ua", 2, false}, + {1, "kharkiv.ua", 2, false}, + {1, "kharkov.ua", 2, false}, + {1, "kherson.ua", 2, false}, + {1, "khmelnitskiy.ua", 2, false}, + {1, "khmelnytskyi.ua", 2, false}, + {1, "kiev.ua", 2, false}, + {1, "kirovograd.ua", 2, false}, + {1, "km.ua", 2, false}, + {1, "kr.ua", 2, false}, + {1, "krym.ua", 2, false}, + {1, "ks.ua", 2, false}, + {1, "kv.ua", 2, false}, + {1, "kyiv.ua", 2, false}, + {1, "lg.ua", 2, false}, + {1, "lt.ua", 2, false}, + {1, "lugansk.ua", 2, false}, + {1, "lutsk.ua", 2, false}, + {1, "lv.ua", 2, false}, + {1, "lviv.ua", 2, false}, + {1, "mk.ua", 2, false}, + {1, "mykolaiv.ua", 2, false}, + {1, "nikolaev.ua", 2, false}, + {1, "od.ua", 2, false}, + {1, "odesa.ua", 2, false}, + {1, "odessa.ua", 2, false}, + {1, "pl.ua", 2, false}, + {1, "poltava.ua", 2, false}, + {1, "rivne.ua", 2, false}, + {1, "rovno.ua", 2, false}, + {1, "rv.ua", 2, false}, + {1, "sb.ua", 2, false}, + {1, "sebastopol.ua", 2, false}, + {1, "sevastopol.ua", 2, false}, + {1, "sm.ua", 2, false}, + {1, "sumy.ua", 2, false}, + {1, "te.ua", 2, false}, + {1, "ternopil.ua", 2, false}, + {1, "uz.ua", 2, false}, + {1, "uzhgorod.ua", 2, false}, + {1, "vinnica.ua", 2, false}, + {1, "vinnytsia.ua", 2, false}, + {1, "vn.ua", 2, false}, + {1, "volyn.ua", 2, false}, + {1, "yalta.ua", 2, false}, + {1, "zaporizhzhe.ua", 2, false}, + {1, "zaporizhzhia.ua", 2, false}, + {1, "zhitomir.ua", 2, false}, + {1, "zhytomyr.ua", 2, false}, + {1, "zp.ua", 2, false}, + {1, "zt.ua", 2, false}, + {1, "ug", 1, false}, + {1, "co.ug", 2, false}, + {1, "or.ug", 2, false}, + {1, "ac.ug", 2, false}, + {1, "sc.ug", 2, false}, + {1, "go.ug", 2, false}, + {1, "ne.ug", 2, false}, + {1, "com.ug", 2, false}, + {1, "org.ug", 2, false}, + {1, "uk", 1, false}, + {1, "ac.uk", 2, false}, + {1, "co.uk", 2, false}, + {1, "gov.uk", 2, false}, + {1, "ltd.uk", 2, false}, + {1, "me.uk", 2, false}, + {1, "net.uk", 2, false}, + {1, "nhs.uk", 2, false}, + {1, "org.uk", 2, false}, + {1, "plc.uk", 2, false}, + {1, "police.uk", 2, false}, + {2, "sch.uk", 3, false}, + {1, "us", 1, false}, + {1, "dni.us", 2, false}, + {1, "fed.us", 2, false}, + {1, "isa.us", 2, false}, + {1, "kids.us", 2, false}, + {1, "nsn.us", 2, false}, + {1, "ak.us", 2, false}, + {1, "al.us", 2, false}, + {1, "ar.us", 2, false}, + {1, "as.us", 2, false}, + {1, "az.us", 2, false}, + {1, "ca.us", 2, false}, + {1, "co.us", 2, false}, + {1, "ct.us", 2, false}, + {1, "dc.us", 2, false}, + {1, "de.us", 2, false}, + {1, "fl.us", 2, false}, + {1, "ga.us", 2, false}, + {1, "gu.us", 2, false}, + {1, "hi.us", 2, false}, + {1, "ia.us", 2, false}, + {1, "id.us", 2, false}, + {1, "il.us", 2, false}, + {1, "in.us", 2, false}, + {1, "ks.us", 2, false}, + {1, "ky.us", 2, false}, + {1, "la.us", 2, false}, + {1, "ma.us", 2, false}, + {1, "md.us", 2, false}, + {1, "me.us", 2, false}, + {1, "mi.us", 2, false}, + {1, "mn.us", 2, false}, + {1, "mo.us", 2, false}, + {1, "ms.us", 2, false}, + {1, "mt.us", 2, false}, + {1, "nc.us", 2, false}, + {1, "nd.us", 2, false}, + {1, "ne.us", 2, false}, + {1, "nh.us", 2, false}, + {1, "nj.us", 2, false}, + {1, "nm.us", 2, false}, + {1, "nv.us", 2, false}, + {1, "ny.us", 2, false}, + {1, "oh.us", 2, false}, + {1, "ok.us", 2, false}, + {1, "or.us", 2, false}, + {1, "pa.us", 2, false}, + {1, "pr.us", 2, false}, + {1, "ri.us", 2, false}, + {1, "sc.us", 2, false}, + {1, "sd.us", 2, false}, + {1, "tn.us", 2, false}, + {1, "tx.us", 2, false}, + {1, "ut.us", 2, false}, + {1, "vi.us", 2, false}, + {1, "vt.us", 2, false}, + {1, "va.us", 2, false}, + {1, "wa.us", 2, false}, + {1, "wi.us", 2, false}, + {1, "wv.us", 2, false}, + {1, "wy.us", 2, false}, + {1, "k12.ak.us", 3, false}, + {1, "k12.al.us", 3, false}, + {1, "k12.ar.us", 3, false}, + {1, "k12.as.us", 3, false}, + {1, "k12.az.us", 3, false}, + {1, "k12.ca.us", 3, false}, + {1, "k12.co.us", 3, false}, + {1, "k12.ct.us", 3, false}, + {1, "k12.dc.us", 3, false}, + {1, "k12.de.us", 3, false}, + {1, "k12.fl.us", 3, false}, + {1, "k12.ga.us", 3, false}, + {1, "k12.gu.us", 3, false}, + {1, "k12.ia.us", 3, false}, + {1, "k12.id.us", 3, false}, + {1, "k12.il.us", 3, false}, + {1, "k12.in.us", 3, false}, + {1, "k12.ks.us", 3, false}, + {1, "k12.ky.us", 3, false}, + {1, "k12.la.us", 3, false}, + {1, "k12.ma.us", 3, false}, + {1, "k12.md.us", 3, false}, + {1, "k12.me.us", 3, false}, + {1, "k12.mi.us", 3, false}, + {1, "k12.mn.us", 3, false}, + {1, "k12.mo.us", 3, false}, + {1, "k12.ms.us", 3, false}, + {1, "k12.mt.us", 3, false}, + {1, "k12.nc.us", 3, false}, + {1, "k12.ne.us", 3, false}, + {1, "k12.nh.us", 3, false}, + {1, "k12.nj.us", 3, false}, + {1, "k12.nm.us", 3, false}, + {1, "k12.nv.us", 3, false}, + {1, "k12.ny.us", 3, false}, + {1, "k12.oh.us", 3, false}, + {1, "k12.ok.us", 3, false}, + {1, "k12.or.us", 3, false}, + {1, "k12.pa.us", 3, false}, + {1, "k12.pr.us", 3, false}, + {1, "k12.sc.us", 3, false}, + {1, "k12.tn.us", 3, false}, + {1, "k12.tx.us", 3, false}, + {1, "k12.ut.us", 3, false}, + {1, "k12.vi.us", 3, false}, + {1, "k12.vt.us", 3, false}, + {1, "k12.va.us", 3, false}, + {1, "k12.wa.us", 3, false}, + {1, "k12.wi.us", 3, false}, + {1, "k12.wy.us", 3, false}, + {1, "cc.ak.us", 3, false}, + {1, "cc.al.us", 3, false}, + {1, "cc.ar.us", 3, false}, + {1, "cc.as.us", 3, false}, + {1, "cc.az.us", 3, false}, + {1, "cc.ca.us", 3, false}, + {1, "cc.co.us", 3, false}, + {1, "cc.ct.us", 3, false}, + {1, "cc.dc.us", 3, false}, + {1, "cc.de.us", 3, false}, + {1, "cc.fl.us", 3, false}, + {1, "cc.ga.us", 3, false}, + {1, "cc.gu.us", 3, false}, + {1, "cc.hi.us", 3, false}, + {1, "cc.ia.us", 3, false}, + {1, "cc.id.us", 3, false}, + {1, "cc.il.us", 3, false}, + {1, "cc.in.us", 3, false}, + {1, "cc.ks.us", 3, false}, + {1, "cc.ky.us", 3, false}, + {1, "cc.la.us", 3, false}, + {1, "cc.ma.us", 3, false}, + {1, "cc.md.us", 3, false}, + {1, "cc.me.us", 3, false}, + {1, "cc.mi.us", 3, false}, + {1, "cc.mn.us", 3, false}, + {1, "cc.mo.us", 3, false}, + {1, "cc.ms.us", 3, false}, + {1, "cc.mt.us", 3, false}, + {1, "cc.nc.us", 3, false}, + {1, "cc.nd.us", 3, false}, + {1, "cc.ne.us", 3, false}, + {1, "cc.nh.us", 3, false}, + {1, "cc.nj.us", 3, false}, + {1, "cc.nm.us", 3, false}, + {1, "cc.nv.us", 3, false}, + {1, "cc.ny.us", 3, false}, + {1, "cc.oh.us", 3, false}, + {1, "cc.ok.us", 3, false}, + {1, "cc.or.us", 3, false}, + {1, "cc.pa.us", 3, false}, + {1, "cc.pr.us", 3, false}, + {1, "cc.ri.us", 3, false}, + {1, "cc.sc.us", 3, false}, + {1, "cc.sd.us", 3, false}, + {1, "cc.tn.us", 3, false}, + {1, "cc.tx.us", 3, false}, + {1, "cc.ut.us", 3, false}, + {1, "cc.vi.us", 3, false}, + {1, "cc.vt.us", 3, false}, + {1, "cc.va.us", 3, false}, + {1, "cc.wa.us", 3, false}, + {1, "cc.wi.us", 3, false}, + {1, "cc.wv.us", 3, false}, + {1, "cc.wy.us", 3, false}, + {1, "lib.ak.us", 3, false}, + {1, "lib.al.us", 3, false}, + {1, "lib.ar.us", 3, false}, + {1, "lib.as.us", 3, false}, + {1, "lib.az.us", 3, false}, + {1, "lib.ca.us", 3, false}, + {1, "lib.co.us", 3, false}, + {1, "lib.ct.us", 3, false}, + {1, "lib.dc.us", 3, false}, + {1, "lib.fl.us", 3, false}, + {1, "lib.ga.us", 3, false}, + {1, "lib.gu.us", 3, false}, + {1, "lib.hi.us", 3, false}, + {1, "lib.ia.us", 3, false}, + {1, "lib.id.us", 3, false}, + {1, "lib.il.us", 3, false}, + {1, "lib.in.us", 3, false}, + {1, "lib.ks.us", 3, false}, + {1, "lib.ky.us", 3, false}, + {1, "lib.la.us", 3, false}, + {1, "lib.ma.us", 3, false}, + {1, "lib.md.us", 3, false}, + {1, "lib.me.us", 3, false}, + {1, "lib.mi.us", 3, false}, + {1, "lib.mn.us", 3, false}, + {1, "lib.mo.us", 3, false}, + {1, "lib.ms.us", 3, false}, + {1, "lib.mt.us", 3, false}, + {1, "lib.nc.us", 3, false}, + {1, "lib.nd.us", 3, false}, + {1, "lib.ne.us", 3, false}, + {1, "lib.nh.us", 3, false}, + {1, "lib.nj.us", 3, false}, + {1, "lib.nm.us", 3, false}, + {1, "lib.nv.us", 3, false}, + {1, "lib.ny.us", 3, false}, + {1, "lib.oh.us", 3, false}, + {1, "lib.ok.us", 3, false}, + {1, "lib.or.us", 3, false}, + {1, "lib.pa.us", 3, false}, + {1, "lib.pr.us", 3, false}, + {1, "lib.ri.us", 3, false}, + {1, "lib.sc.us", 3, false}, + {1, "lib.sd.us", 3, false}, + {1, "lib.tn.us", 3, false}, + {1, "lib.tx.us", 3, false}, + {1, "lib.ut.us", 3, false}, + {1, "lib.vi.us", 3, false}, + {1, "lib.vt.us", 3, false}, + {1, "lib.va.us", 3, false}, + {1, "lib.wa.us", 3, false}, + {1, "lib.wi.us", 3, false}, + {1, "lib.wy.us", 3, false}, + {1, "pvt.k12.ma.us", 4, false}, + {1, "chtr.k12.ma.us", 4, false}, + {1, "paroch.k12.ma.us", 4, false}, + {1, "ann-arbor.mi.us", 3, false}, + {1, "cog.mi.us", 3, false}, + {1, "dst.mi.us", 3, false}, + {1, "eaton.mi.us", 3, false}, + {1, "gen.mi.us", 3, false}, + {1, "mus.mi.us", 3, false}, + {1, "tec.mi.us", 3, false}, + {1, "washtenaw.mi.us", 3, false}, + {1, "uy", 1, false}, + {1, "com.uy", 2, false}, + {1, "edu.uy", 2, false}, + {1, "gub.uy", 2, false}, + {1, "mil.uy", 2, false}, + {1, "net.uy", 2, false}, + {1, "org.uy", 2, false}, + {1, "uz", 1, false}, + {1, "co.uz", 2, false}, + {1, "com.uz", 2, false}, + {1, "net.uz", 2, false}, + {1, "org.uz", 2, false}, + {1, "va", 1, false}, + {1, "vc", 1, false}, + {1, "com.vc", 2, false}, + {1, "net.vc", 2, false}, + {1, "org.vc", 2, false}, + {1, "gov.vc", 2, false}, + {1, "mil.vc", 2, false}, + {1, "edu.vc", 2, false}, + {1, "ve", 1, false}, + {1, "arts.ve", 2, false}, + {1, "co.ve", 2, false}, + {1, "com.ve", 2, false}, + {1, "e12.ve", 2, false}, + {1, "edu.ve", 2, false}, + {1, "firm.ve", 2, false}, + {1, "gob.ve", 2, false}, + {1, "gov.ve", 2, false}, + {1, "info.ve", 2, false}, + {1, "int.ve", 2, false}, + {1, "mil.ve", 2, false}, + {1, "net.ve", 2, false}, + {1, "org.ve", 2, false}, + {1, "rec.ve", 2, false}, + {1, "store.ve", 2, false}, + {1, "tec.ve", 2, false}, + {1, "web.ve", 2, false}, + {1, "vg", 1, false}, + {1, "vi", 1, false}, + {1, "co.vi", 2, false}, + {1, "com.vi", 2, false}, + {1, "k12.vi", 2, false}, + {1, "net.vi", 2, false}, + {1, "org.vi", 2, false}, + {1, "vn", 1, false}, + {1, "com.vn", 2, false}, + {1, "net.vn", 2, false}, + {1, "org.vn", 2, false}, + {1, "edu.vn", 2, false}, + {1, "gov.vn", 2, false}, + {1, "int.vn", 2, false}, + {1, "ac.vn", 2, false}, + {1, "biz.vn", 2, false}, + {1, "info.vn", 2, false}, + {1, "name.vn", 2, false}, + {1, "pro.vn", 2, false}, + {1, "health.vn", 2, false}, + {1, "vu", 1, false}, + {1, "com.vu", 2, false}, + {1, "edu.vu", 2, false}, + {1, "net.vu", 2, false}, + {1, "org.vu", 2, false}, + {1, "wf", 1, false}, + {1, "ws", 1, false}, + {1, "com.ws", 2, false}, + {1, "net.ws", 2, false}, + {1, "org.ws", 2, false}, + {1, "gov.ws", 2, false}, + {1, "edu.ws", 2, false}, + {1, "yt", 1, false}, + {1, "xn--mgbaam7a8h", 1, false}, + {1, "xn--y9a3aq", 1, false}, + {1, "xn--54b7fta0cc", 1, false}, + {1, "xn--90ae", 1, false}, + {1, "xn--mgbcpq6gpa1a", 1, false}, + {1, "xn--90ais", 1, false}, + {1, "xn--fiqs8s", 1, false}, + {1, "xn--fiqz9s", 1, false}, + {1, "xn--lgbbat1ad8j", 1, false}, + {1, "xn--wgbh1c", 1, false}, + {1, "xn--e1a4c", 1, false}, + {1, "xn--qxa6a", 1, false}, + {1, "xn--mgbah1a3hjkrd", 1, false}, + {1, "xn--node", 1, false}, + {1, "xn--qxam", 1, false}, + {1, "xn--j6w193g", 1, false}, + {1, "xn--55qx5d.xn--j6w193g", 2, false}, + {1, "xn--wcvs22d.xn--j6w193g", 2, false}, + {1, "xn--mxtq1m.xn--j6w193g", 2, false}, + {1, "xn--gmqw5a.xn--j6w193g", 2, false}, + {1, "xn--od0alg.xn--j6w193g", 2, false}, + {1, "xn--uc0atv.xn--j6w193g", 2, false}, + {1, "xn--2scrj9c", 1, false}, + {1, "xn--3hcrj9c", 1, false}, + {1, "xn--45br5cyl", 1, false}, + {1, "xn--h2breg3eve", 1, false}, + {1, "xn--h2brj9c8c", 1, false}, + {1, "xn--mgbgu82a", 1, false}, + {1, "xn--rvc1e0am3e", 1, false}, + {1, "xn--h2brj9c", 1, false}, + {1, "xn--mgbbh1a", 1, false}, + {1, "xn--mgbbh1a71e", 1, false}, + {1, "xn--fpcrj9c3d", 1, false}, + {1, "xn--gecrj9c", 1, false}, + {1, "xn--s9brj9c", 1, false}, + {1, "xn--45brj9c", 1, false}, + {1, "xn--xkc2dl3a5ee0h", 1, false}, + {1, "xn--mgba3a4f16a", 1, false}, + {1, "xn--mgba3a4fra", 1, false}, + {1, "xn--mgbtx2b", 1, false}, + {1, "xn--mgbayh7gpa", 1, false}, + {1, "xn--3e0b707e", 1, false}, + {1, "xn--80ao21a", 1, false}, + {1, "xn--q7ce6a", 1, false}, + {1, "xn--fzc2c9e2c", 1, false}, + {1, "xn--xkc2al3hye2a", 1, false}, + {1, "xn--mgbc0a9azcg", 1, false}, + {1, "xn--d1alf", 1, false}, + {1, "xn--l1acc", 1, false}, + {1, "xn--mix891f", 1, false}, + {1, "xn--mix082f", 1, false}, + {1, "xn--mgbx4cd0ab", 1, false}, + {1, "xn--mgb9awbf", 1, false}, + {1, "xn--mgbai9azgqp6j", 1, false}, + {1, "xn--mgbai9a5eva00b", 1, false}, + {1, "xn--ygbi2ammx", 1, false}, + {1, "xn--90a3ac", 1, false}, + {1, "xn--o1ac.xn--90a3ac", 2, false}, + {1, "xn--c1avg.xn--90a3ac", 2, false}, + {1, "xn--90azh.xn--90a3ac", 2, false}, + {1, "xn--d1at.xn--90a3ac", 2, false}, + {1, "xn--o1ach.xn--90a3ac", 2, false}, + {1, "xn--80au.xn--90a3ac", 2, false}, + {1, "xn--p1ai", 1, false}, + {1, "xn--wgbl6a", 1, false}, + {1, "xn--mgberp4a5d4ar", 1, false}, + {1, "xn--mgberp4a5d4a87g", 1, false}, + {1, "xn--mgbqly7c0a67fbc", 1, false}, + {1, "xn--mgbqly7cvafr", 1, false}, + {1, "xn--mgbpl2fh", 1, false}, + {1, "xn--yfro4i67o", 1, false}, + {1, "xn--clchc0ea0b2g2a9gcd", 1, false}, + {1, "xn--ogbpf8fl", 1, false}, + {1, "xn--mgbtf8fl", 1, false}, + {1, "xn--o3cw4h", 1, false}, + {1, "xn--12c1fe0br.xn--o3cw4h", 2, false}, + {1, "xn--12co0c3b4eva.xn--o3cw4h", 2, false}, + {1, "xn--h3cuzk1di.xn--o3cw4h", 2, false}, + {1, "xn--o3cyx2a.xn--o3cw4h", 2, false}, + {1, "xn--m3ch0j3a.xn--o3cw4h", 2, false}, + {1, "xn--12cfi8ixb8l.xn--o3cw4h", 2, false}, + {1, "xn--pgbs0dh", 1, false}, + {1, "xn--kpry57d", 1, false}, + {1, "xn--kprw13d", 1, false}, + {1, "xn--nnx388a", 1, false}, + {1, "xn--j1amh", 1, false}, + {1, "xn--mgb2ddes", 1, false}, + {1, "xxx", 1, false}, + {1, "ye", 1, false}, + {1, "com.ye", 2, false}, + {1, "edu.ye", 2, false}, + {1, "gov.ye", 2, false}, + {1, "net.ye", 2, false}, + {1, "mil.ye", 2, false}, + {1, "org.ye", 2, false}, + {1, "ac.za", 2, false}, + {1, "agric.za", 2, false}, + {1, "alt.za", 2, false}, + {1, "co.za", 2, false}, + {1, "edu.za", 2, false}, + {1, "gov.za", 2, false}, + {1, "grondar.za", 2, false}, + {1, "law.za", 2, false}, + {1, "mil.za", 2, false}, + {1, "net.za", 2, false}, + {1, "ngo.za", 2, false}, + {1, "nic.za", 2, false}, + {1, "nis.za", 2, false}, + {1, "nom.za", 2, false}, + {1, "org.za", 2, false}, + {1, "school.za", 2, false}, + {1, "tm.za", 2, false}, + {1, "web.za", 2, false}, + {1, "zm", 1, false}, + {1, "ac.zm", 2, false}, + {1, "biz.zm", 2, false}, + {1, "co.zm", 2, false}, + {1, "com.zm", 2, false}, + {1, "edu.zm", 2, false}, + {1, "gov.zm", 2, false}, + {1, "info.zm", 2, false}, + {1, "mil.zm", 2, false}, + {1, "net.zm", 2, false}, + {1, "org.zm", 2, false}, + {1, "sch.zm", 2, false}, + {1, "zw", 1, false}, + {1, "ac.zw", 2, false}, + {1, "co.zw", 2, false}, + {1, "gov.zw", 2, false}, + {1, "mil.zw", 2, false}, + {1, "org.zw", 2, false}, + {1, "aaa", 1, false}, + {1, "aarp", 1, false}, + {1, "abarth", 1, false}, + {1, "abb", 1, false}, + {1, "abbott", 1, false}, + {1, "abbvie", 1, false}, + {1, "abc", 1, false}, + {1, "able", 1, false}, + {1, "abogado", 1, false}, + {1, "abudhabi", 1, false}, + {1, "academy", 1, false}, + {1, "accenture", 1, false}, + {1, "accountant", 1, false}, + {1, "accountants", 1, false}, + {1, "aco", 1, false}, + {1, "actor", 1, false}, + {1, "adac", 1, false}, + {1, "ads", 1, false}, + {1, "adult", 1, false}, + {1, "aeg", 1, false}, + {1, "aetna", 1, false}, + {1, "afamilycompany", 1, false}, + {1, "afl", 1, false}, + {1, "africa", 1, false}, + {1, "agakhan", 1, false}, + {1, "agency", 1, false}, + {1, "aig", 1, false}, + {1, "airbus", 1, false}, + {1, "airforce", 1, false}, + {1, "airtel", 1, false}, + {1, "akdn", 1, false}, + {1, "alfaromeo", 1, false}, + {1, "alibaba", 1, false}, + {1, "alipay", 1, false}, + {1, "allfinanz", 1, false}, + {1, "allstate", 1, false}, + {1, "ally", 1, false}, + {1, "alsace", 1, false}, + {1, "alstom", 1, false}, + {1, "amazon", 1, false}, + {1, "americanexpress", 1, false}, + {1, "americanfamily", 1, false}, + {1, "amex", 1, false}, + {1, "amfam", 1, false}, + {1, "amica", 1, false}, + {1, "amsterdam", 1, false}, + {1, "analytics", 1, false}, + {1, "android", 1, false}, + {1, "anquan", 1, false}, + {1, "anz", 1, false}, + {1, "aol", 1, false}, + {1, "apartments", 1, false}, + {1, "app", 1, false}, + {1, "apple", 1, false}, + {1, "aquarelle", 1, false}, + {1, "arab", 1, false}, + {1, "aramco", 1, false}, + {1, "archi", 1, false}, + {1, "army", 1, false}, + {1, "art", 1, false}, + {1, "arte", 1, false}, + {1, "asda", 1, false}, + {1, "associates", 1, false}, + {1, "athleta", 1, false}, + {1, "attorney", 1, false}, + {1, "auction", 1, false}, + {1, "audi", 1, false}, + {1, "audible", 1, false}, + {1, "audio", 1, false}, + {1, "auspost", 1, false}, + {1, "author", 1, false}, + {1, "auto", 1, false}, + {1, "autos", 1, false}, + {1, "avianca", 1, false}, + {1, "aws", 1, false}, + {1, "axa", 1, false}, + {1, "azure", 1, false}, + {1, "baby", 1, false}, + {1, "baidu", 1, false}, + {1, "banamex", 1, false}, + {1, "bananarepublic", 1, false}, + {1, "band", 1, false}, + {1, "bank", 1, false}, + {1, "bar", 1, false}, + {1, "barcelona", 1, false}, + {1, "barclaycard", 1, false}, + {1, "barclays", 1, false}, + {1, "barefoot", 1, false}, + {1, "bargains", 1, false}, + {1, "baseball", 1, false}, + {1, "basketball", 1, false}, + {1, "bauhaus", 1, false}, + {1, "bayern", 1, false}, + {1, "bbc", 1, false}, + {1, "bbt", 1, false}, + {1, "bbva", 1, false}, + {1, "bcg", 1, false}, + {1, "bcn", 1, false}, + {1, "beats", 1, false}, + {1, "beauty", 1, false}, + {1, "beer", 1, false}, + {1, "bentley", 1, false}, + {1, "berlin", 1, false}, + {1, "best", 1, false}, + {1, "bestbuy", 1, false}, + {1, "bet", 1, false}, + {1, "bharti", 1, false}, + {1, "bible", 1, false}, + {1, "bid", 1, false}, + {1, "bike", 1, false}, + {1, "bing", 1, false}, + {1, "bingo", 1, false}, + {1, "bio", 1, false}, + {1, "black", 1, false}, + {1, "blackfriday", 1, false}, + {1, "blockbuster", 1, false}, + {1, "blog", 1, false}, + {1, "bloomberg", 1, false}, + {1, "blue", 1, false}, + {1, "bms", 1, false}, + {1, "bmw", 1, false}, + {1, "bnpparibas", 1, false}, + {1, "boats", 1, false}, + {1, "boehringer", 1, false}, + {1, "bofa", 1, false}, + {1, "bom", 1, false}, + {1, "bond", 1, false}, + {1, "boo", 1, false}, + {1, "book", 1, false}, + {1, "booking", 1, false}, + {1, "bosch", 1, false}, + {1, "bostik", 1, false}, + {1, "boston", 1, false}, + {1, "bot", 1, false}, + {1, "boutique", 1, false}, + {1, "box", 1, false}, + {1, "bradesco", 1, false}, + {1, "bridgestone", 1, false}, + {1, "broadway", 1, false}, + {1, "broker", 1, false}, + {1, "brother", 1, false}, + {1, "brussels", 1, false}, + {1, "budapest", 1, false}, + {1, "bugatti", 1, false}, + {1, "build", 1, false}, + {1, "builders", 1, false}, + {1, "business", 1, false}, + {1, "buy", 1, false}, + {1, "buzz", 1, false}, + {1, "bzh", 1, false}, + {1, "cab", 1, false}, + {1, "cafe", 1, false}, + {1, "cal", 1, false}, + {1, "call", 1, false}, + {1, "calvinklein", 1, false}, + {1, "cam", 1, false}, + {1, "camera", 1, false}, + {1, "camp", 1, false}, + {1, "cancerresearch", 1, false}, + {1, "canon", 1, false}, + {1, "capetown", 1, false}, + {1, "capital", 1, false}, + {1, "capitalone", 1, false}, + {1, "car", 1, false}, + {1, "caravan", 1, false}, + {1, "cards", 1, false}, + {1, "care", 1, false}, + {1, "career", 1, false}, + {1, "careers", 1, false}, + {1, "cars", 1, false}, + {1, "casa", 1, false}, + {1, "case", 1, false}, + {1, "cash", 1, false}, + {1, "casino", 1, false}, + {1, "catering", 1, false}, + {1, "catholic", 1, false}, + {1, "cba", 1, false}, + {1, "cbn", 1, false}, + {1, "cbre", 1, false}, + {1, "cbs", 1, false}, + {1, "center", 1, false}, + {1, "ceo", 1, false}, + {1, "cern", 1, false}, + {1, "cfa", 1, false}, + {1, "cfd", 1, false}, + {1, "chanel", 1, false}, + {1, "channel", 1, false}, + {1, "charity", 1, false}, + {1, "chase", 1, false}, + {1, "chat", 1, false}, + {1, "cheap", 1, false}, + {1, "chintai", 1, false}, + {1, "christmas", 1, false}, + {1, "chrome", 1, false}, + {1, "church", 1, false}, + {1, "cipriani", 1, false}, + {1, "circle", 1, false}, + {1, "cisco", 1, false}, + {1, "citadel", 1, false}, + {1, "citi", 1, false}, + {1, "citic", 1, false}, + {1, "city", 1, false}, + {1, "cityeats", 1, false}, + {1, "claims", 1, false}, + {1, "cleaning", 1, false}, + {1, "click", 1, false}, + {1, "clinic", 1, false}, + {1, "clinique", 1, false}, + {1, "clothing", 1, false}, + {1, "cloud", 1, false}, + {1, "club", 1, false}, + {1, "clubmed", 1, false}, + {1, "coach", 1, false}, + {1, "codes", 1, false}, + {1, "coffee", 1, false}, + {1, "college", 1, false}, + {1, "cologne", 1, false}, + {1, "comcast", 1, false}, + {1, "commbank", 1, false}, + {1, "community", 1, false}, + {1, "company", 1, false}, + {1, "compare", 1, false}, + {1, "computer", 1, false}, + {1, "comsec", 1, false}, + {1, "condos", 1, false}, + {1, "construction", 1, false}, + {1, "consulting", 1, false}, + {1, "contact", 1, false}, + {1, "contractors", 1, false}, + {1, "cooking", 1, false}, + {1, "cookingchannel", 1, false}, + {1, "cool", 1, false}, + {1, "corsica", 1, false}, + {1, "country", 1, false}, + {1, "coupon", 1, false}, + {1, "coupons", 1, false}, + {1, "courses", 1, false}, + {1, "cpa", 1, false}, + {1, "credit", 1, false}, + {1, "creditcard", 1, false}, + {1, "creditunion", 1, false}, + {1, "cricket", 1, false}, + {1, "crown", 1, false}, + {1, "crs", 1, false}, + {1, "cruise", 1, false}, + {1, "cruises", 1, false}, + {1, "csc", 1, false}, + {1, "cuisinella", 1, false}, + {1, "cymru", 1, false}, + {1, "cyou", 1, false}, + {1, "dabur", 1, false}, + {1, "dad", 1, false}, + {1, "dance", 1, false}, + {1, "data", 1, false}, + {1, "date", 1, false}, + {1, "dating", 1, false}, + {1, "datsun", 1, false}, + {1, "day", 1, false}, + {1, "dclk", 1, false}, + {1, "dds", 1, false}, + {1, "deal", 1, false}, + {1, "dealer", 1, false}, + {1, "deals", 1, false}, + {1, "degree", 1, false}, + {1, "delivery", 1, false}, + {1, "dell", 1, false}, + {1, "deloitte", 1, false}, + {1, "delta", 1, false}, + {1, "democrat", 1, false}, + {1, "dental", 1, false}, + {1, "dentist", 1, false}, + {1, "desi", 1, false}, + {1, "design", 1, false}, + {1, "dev", 1, false}, + {1, "dhl", 1, false}, + {1, "diamonds", 1, false}, + {1, "diet", 1, false}, + {1, "digital", 1, false}, + {1, "direct", 1, false}, + {1, "directory", 1, false}, + {1, "discount", 1, false}, + {1, "discover", 1, false}, + {1, "dish", 1, false}, + {1, "diy", 1, false}, + {1, "dnp", 1, false}, + {1, "docs", 1, false}, + {1, "doctor", 1, false}, + {1, "dog", 1, false}, + {1, "domains", 1, false}, + {1, "dot", 1, false}, + {1, "download", 1, false}, + {1, "drive", 1, false}, + {1, "dtv", 1, false}, + {1, "dubai", 1, false}, + {1, "duck", 1, false}, + {1, "dunlop", 1, false}, + {1, "dupont", 1, false}, + {1, "durban", 1, false}, + {1, "dvag", 1, false}, + {1, "dvr", 1, false}, + {1, "earth", 1, false}, + {1, "eat", 1, false}, + {1, "eco", 1, false}, + {1, "edeka", 1, false}, + {1, "education", 1, false}, + {1, "email", 1, false}, + {1, "emerck", 1, false}, + {1, "energy", 1, false}, + {1, "engineer", 1, false}, + {1, "engineering", 1, false}, + {1, "enterprises", 1, false}, + {1, "epson", 1, false}, + {1, "equipment", 1, false}, + {1, "ericsson", 1, false}, + {1, "erni", 1, false}, + {1, "esq", 1, false}, + {1, "estate", 1, false}, + {1, "etisalat", 1, false}, + {1, "eurovision", 1, false}, + {1, "eus", 1, false}, + {1, "events", 1, false}, + {1, "exchange", 1, false}, + {1, "expert", 1, false}, + {1, "exposed", 1, false}, + {1, "express", 1, false}, + {1, "extraspace", 1, false}, + {1, "fage", 1, false}, + {1, "fail", 1, false}, + {1, "fairwinds", 1, false}, + {1, "faith", 1, false}, + {1, "family", 1, false}, + {1, "fan", 1, false}, + {1, "fans", 1, false}, + {1, "farm", 1, false}, + {1, "farmers", 1, false}, + {1, "fashion", 1, false}, + {1, "fast", 1, false}, + {1, "fedex", 1, false}, + {1, "feedback", 1, false}, + {1, "ferrari", 1, false}, + {1, "ferrero", 1, false}, + {1, "fiat", 1, false}, + {1, "fidelity", 1, false}, + {1, "fido", 1, false}, + {1, "film", 1, false}, + {1, "final", 1, false}, + {1, "finance", 1, false}, + {1, "financial", 1, false}, + {1, "fire", 1, false}, + {1, "firestone", 1, false}, + {1, "firmdale", 1, false}, + {1, "fish", 1, false}, + {1, "fishing", 1, false}, + {1, "fit", 1, false}, + {1, "fitness", 1, false}, + {1, "flickr", 1, false}, + {1, "flights", 1, false}, + {1, "flir", 1, false}, + {1, "florist", 1, false}, + {1, "flowers", 1, false}, + {1, "fly", 1, false}, + {1, "foo", 1, false}, + {1, "food", 1, false}, + {1, "foodnetwork", 1, false}, + {1, "football", 1, false}, + {1, "ford", 1, false}, + {1, "forex", 1, false}, + {1, "forsale", 1, false}, + {1, "forum", 1, false}, + {1, "foundation", 1, false}, + {1, "fox", 1, false}, + {1, "free", 1, false}, + {1, "fresenius", 1, false}, + {1, "frl", 1, false}, + {1, "frogans", 1, false}, + {1, "frontdoor", 1, false}, + {1, "frontier", 1, false}, + {1, "ftr", 1, false}, + {1, "fujitsu", 1, false}, + {1, "fun", 1, false}, + {1, "fund", 1, false}, + {1, "furniture", 1, false}, + {1, "futbol", 1, false}, + {1, "fyi", 1, false}, + {1, "gal", 1, false}, + {1, "gallery", 1, false}, + {1, "gallo", 1, false}, + {1, "gallup", 1, false}, + {1, "game", 1, false}, + {1, "games", 1, false}, + {1, "gap", 1, false}, + {1, "garden", 1, false}, + {1, "gay", 1, false}, + {1, "gbiz", 1, false}, + {1, "gdn", 1, false}, + {1, "gea", 1, false}, + {1, "gent", 1, false}, + {1, "genting", 1, false}, + {1, "george", 1, false}, + {1, "ggee", 1, false}, + {1, "gift", 1, false}, + {1, "gifts", 1, false}, + {1, "gives", 1, false}, + {1, "giving", 1, false}, + {1, "glade", 1, false}, + {1, "glass", 1, false}, + {1, "gle", 1, false}, + {1, "global", 1, false}, + {1, "globo", 1, false}, + {1, "gmail", 1, false}, + {1, "gmbh", 1, false}, + {1, "gmo", 1, false}, + {1, "gmx", 1, false}, + {1, "godaddy", 1, false}, + {1, "gold", 1, false}, + {1, "goldpoint", 1, false}, + {1, "golf", 1, false}, + {1, "goo", 1, false}, + {1, "goodyear", 1, false}, + {1, "goog", 1, false}, + {1, "google", 1, false}, + {1, "gop", 1, false}, + {1, "got", 1, false}, + {1, "grainger", 1, false}, + {1, "graphics", 1, false}, + {1, "gratis", 1, false}, + {1, "green", 1, false}, + {1, "gripe", 1, false}, + {1, "grocery", 1, false}, + {1, "group", 1, false}, + {1, "guardian", 1, false}, + {1, "gucci", 1, false}, + {1, "guge", 1, false}, + {1, "guide", 1, false}, + {1, "guitars", 1, false}, + {1, "guru", 1, false}, + {1, "hair", 1, false}, + {1, "hamburg", 1, false}, + {1, "hangout", 1, false}, + {1, "haus", 1, false}, + {1, "hbo", 1, false}, + {1, "hdfc", 1, false}, + {1, "hdfcbank", 1, false}, + {1, "health", 1, false}, + {1, "healthcare", 1, false}, + {1, "help", 1, false}, + {1, "helsinki", 1, false}, + {1, "here", 1, false}, + {1, "hermes", 1, false}, + {1, "hgtv", 1, false}, + {1, "hiphop", 1, false}, + {1, "hisamitsu", 1, false}, + {1, "hitachi", 1, false}, + {1, "hiv", 1, false}, + {1, "hkt", 1, false}, + {1, "hockey", 1, false}, + {1, "holdings", 1, false}, + {1, "holiday", 1, false}, + {1, "homedepot", 1, false}, + {1, "homegoods", 1, false}, + {1, "homes", 1, false}, + {1, "homesense", 1, false}, + {1, "honda", 1, false}, + {1, "horse", 1, false}, + {1, "hospital", 1, false}, + {1, "host", 1, false}, + {1, "hosting", 1, false}, + {1, "hot", 1, false}, + {1, "hoteles", 1, false}, + {1, "hotels", 1, false}, + {1, "hotmail", 1, false}, + {1, "house", 1, false}, + {1, "how", 1, false}, + {1, "hsbc", 1, false}, + {1, "hughes", 1, false}, + {1, "hyatt", 1, false}, + {1, "hyundai", 1, false}, + {1, "ibm", 1, false}, + {1, "icbc", 1, false}, + {1, "ice", 1, false}, + {1, "icu", 1, false}, + {1, "ieee", 1, false}, + {1, "ifm", 1, false}, + {1, "ikano", 1, false}, + {1, "imamat", 1, false}, + {1, "imdb", 1, false}, + {1, "immo", 1, false}, + {1, "immobilien", 1, false}, + {1, "inc", 1, false}, + {1, "industries", 1, false}, + {1, "infiniti", 1, false}, + {1, "ing", 1, false}, + {1, "ink", 1, false}, + {1, "institute", 1, false}, + {1, "insurance", 1, false}, + {1, "insure", 1, false}, + {1, "international", 1, false}, + {1, "intuit", 1, false}, + {1, "investments", 1, false}, + {1, "ipiranga", 1, false}, + {1, "irish", 1, false}, + {1, "ismaili", 1, false}, + {1, "ist", 1, false}, + {1, "istanbul", 1, false}, + {1, "itau", 1, false}, + {1, "itv", 1, false}, + {1, "jaguar", 1, false}, + {1, "java", 1, false}, + {1, "jcb", 1, false}, + {1, "jeep", 1, false}, + {1, "jetzt", 1, false}, + {1, "jewelry", 1, false}, + {1, "jio", 1, false}, + {1, "jll", 1, false}, + {1, "jmp", 1, false}, + {1, "jnj", 1, false}, + {1, "joburg", 1, false}, + {1, "jot", 1, false}, + {1, "joy", 1, false}, + {1, "jpmorgan", 1, false}, + {1, "jprs", 1, false}, + {1, "juegos", 1, false}, + {1, "juniper", 1, false}, + {1, "kaufen", 1, false}, + {1, "kddi", 1, false}, + {1, "kerryhotels", 1, false}, + {1, "kerrylogistics", 1, false}, + {1, "kerryproperties", 1, false}, + {1, "kfh", 1, false}, + {1, "kia", 1, false}, + {1, "kim", 1, false}, + {1, "kinder", 1, false}, + {1, "kindle", 1, false}, + {1, "kitchen", 1, false}, + {1, "kiwi", 1, false}, + {1, "koeln", 1, false}, + {1, "komatsu", 1, false}, + {1, "kosher", 1, false}, + {1, "kpmg", 1, false}, + {1, "kpn", 1, false}, + {1, "krd", 1, false}, + {1, "kred", 1, false}, + {1, "kuokgroup", 1, false}, + {1, "kyoto", 1, false}, + {1, "lacaixa", 1, false}, + {1, "lamborghini", 1, false}, + {1, "lamer", 1, false}, + {1, "lancaster", 1, false}, + {1, "lancia", 1, false}, + {1, "land", 1, false}, + {1, "landrover", 1, false}, + {1, "lanxess", 1, false}, + {1, "lasalle", 1, false}, + {1, "lat", 1, false}, + {1, "latino", 1, false}, + {1, "latrobe", 1, false}, + {1, "law", 1, false}, + {1, "lawyer", 1, false}, + {1, "lds", 1, false}, + {1, "lease", 1, false}, + {1, "leclerc", 1, false}, + {1, "lefrak", 1, false}, + {1, "legal", 1, false}, + {1, "lego", 1, false}, + {1, "lexus", 1, false}, + {1, "lgbt", 1, false}, + {1, "lidl", 1, false}, + {1, "life", 1, false}, + {1, "lifeinsurance", 1, false}, + {1, "lifestyle", 1, false}, + {1, "lighting", 1, false}, + {1, "like", 1, false}, + {1, "lilly", 1, false}, + {1, "limited", 1, false}, + {1, "limo", 1, false}, + {1, "lincoln", 1, false}, + {1, "linde", 1, false}, + {1, "link", 1, false}, + {1, "lipsy", 1, false}, + {1, "live", 1, false}, + {1, "living", 1, false}, + {1, "lixil", 1, false}, + {1, "llc", 1, false}, + {1, "llp", 1, false}, + {1, "loan", 1, false}, + {1, "loans", 1, false}, + {1, "locker", 1, false}, + {1, "locus", 1, false}, + {1, "loft", 1, false}, + {1, "lol", 1, false}, + {1, "london", 1, false}, + {1, "lotte", 1, false}, + {1, "lotto", 1, false}, + {1, "love", 1, false}, + {1, "lpl", 1, false}, + {1, "lplfinancial", 1, false}, + {1, "ltd", 1, false}, + {1, "ltda", 1, false}, + {1, "lundbeck", 1, false}, + {1, "luxe", 1, false}, + {1, "luxury", 1, false}, + {1, "macys", 1, false}, + {1, "madrid", 1, false}, + {1, "maif", 1, false}, + {1, "maison", 1, false}, + {1, "makeup", 1, false}, + {1, "man", 1, false}, + {1, "management", 1, false}, + {1, "mango", 1, false}, + {1, "map", 1, false}, + {1, "market", 1, false}, + {1, "marketing", 1, false}, + {1, "markets", 1, false}, + {1, "marriott", 1, false}, + {1, "marshalls", 1, false}, + {1, "maserati", 1, false}, + {1, "mattel", 1, false}, + {1, "mba", 1, false}, + {1, "mckinsey", 1, false}, + {1, "med", 1, false}, + {1, "media", 1, false}, + {1, "meet", 1, false}, + {1, "melbourne", 1, false}, + {1, "meme", 1, false}, + {1, "memorial", 1, false}, + {1, "men", 1, false}, + {1, "menu", 1, false}, + {1, "merckmsd", 1, false}, + {1, "miami", 1, false}, + {1, "microsoft", 1, false}, + {1, "mini", 1, false}, + {1, "mint", 1, false}, + {1, "mit", 1, false}, + {1, "mitsubishi", 1, false}, + {1, "mlb", 1, false}, + {1, "mls", 1, false}, + {1, "mma", 1, false}, + {1, "mobile", 1, false}, + {1, "moda", 1, false}, + {1, "moe", 1, false}, + {1, "moi", 1, false}, + {1, "mom", 1, false}, + {1, "monash", 1, false}, + {1, "money", 1, false}, + {1, "monster", 1, false}, + {1, "mormon", 1, false}, + {1, "mortgage", 1, false}, + {1, "moscow", 1, false}, + {1, "moto", 1, false}, + {1, "motorcycles", 1, false}, + {1, "mov", 1, false}, + {1, "movie", 1, false}, + {1, "msd", 1, false}, + {1, "mtn", 1, false}, + {1, "mtr", 1, false}, + {1, "mutual", 1, false}, + {1, "nab", 1, false}, + {1, "nagoya", 1, false}, + {1, "natura", 1, false}, + {1, "navy", 1, false}, + {1, "nba", 1, false}, + {1, "nec", 1, false}, + {1, "netbank", 1, false}, + {1, "netflix", 1, false}, + {1, "network", 1, false}, + {1, "neustar", 1, false}, + {1, "new", 1, false}, + {1, "news", 1, false}, + {1, "next", 1, false}, + {1, "nextdirect", 1, false}, + {1, "nexus", 1, false}, + {1, "nfl", 1, false}, + {1, "ngo", 1, false}, + {1, "nhk", 1, false}, + {1, "nico", 1, false}, + {1, "nike", 1, false}, + {1, "nikon", 1, false}, + {1, "ninja", 1, false}, + {1, "nissan", 1, false}, + {1, "nissay", 1, false}, + {1, "nokia", 1, false}, + {1, "northwesternmutual", 1, false}, + {1, "norton", 1, false}, + {1, "now", 1, false}, + {1, "nowruz", 1, false}, + {1, "nowtv", 1, false}, + {1, "nra", 1, false}, + {1, "nrw", 1, false}, + {1, "ntt", 1, false}, + {1, "nyc", 1, false}, + {1, "obi", 1, false}, + {1, "observer", 1, false}, + {1, "off", 1, false}, + {1, "office", 1, false}, + {1, "okinawa", 1, false}, + {1, "olayan", 1, false}, + {1, "olayangroup", 1, false}, + {1, "oldnavy", 1, false}, + {1, "ollo", 1, false}, + {1, "omega", 1, false}, + {1, "one", 1, false}, + {1, "ong", 1, false}, + {1, "onl", 1, false}, + {1, "online", 1, false}, + {1, "ooo", 1, false}, + {1, "open", 1, false}, + {1, "oracle", 1, false}, + {1, "orange", 1, false}, + {1, "organic", 1, false}, + {1, "origins", 1, false}, + {1, "osaka", 1, false}, + {1, "otsuka", 1, false}, + {1, "ott", 1, false}, + {1, "ovh", 1, false}, + {1, "page", 1, false}, + {1, "panasonic", 1, false}, + {1, "paris", 1, false}, + {1, "pars", 1, false}, + {1, "partners", 1, false}, + {1, "parts", 1, false}, + {1, "party", 1, false}, + {1, "passagens", 1, false}, + {1, "pay", 1, false}, + {1, "pccw", 1, false}, + {1, "pet", 1, false}, + {1, "pfizer", 1, false}, + {1, "pharmacy", 1, false}, + {1, "phd", 1, false}, + {1, "philips", 1, false}, + {1, "phone", 1, false}, + {1, "photo", 1, false}, + {1, "photography", 1, false}, + {1, "photos", 1, false}, + {1, "physio", 1, false}, + {1, "pics", 1, false}, + {1, "pictet", 1, false}, + {1, "pictures", 1, false}, + {1, "pid", 1, false}, + {1, "pin", 1, false}, + {1, "ping", 1, false}, + {1, "pink", 1, false}, + {1, "pioneer", 1, false}, + {1, "pizza", 1, false}, + {1, "place", 1, false}, + {1, "play", 1, false}, + {1, "playstation", 1, false}, + {1, "plumbing", 1, false}, + {1, "plus", 1, false}, + {1, "pnc", 1, false}, + {1, "pohl", 1, false}, + {1, "poker", 1, false}, + {1, "politie", 1, false}, + {1, "porn", 1, false}, + {1, "pramerica", 1, false}, + {1, "praxi", 1, false}, + {1, "press", 1, false}, + {1, "prime", 1, false}, + {1, "prod", 1, false}, + {1, "productions", 1, false}, + {1, "prof", 1, false}, + {1, "progressive", 1, false}, + {1, "promo", 1, false}, + {1, "properties", 1, false}, + {1, "property", 1, false}, + {1, "protection", 1, false}, + {1, "pru", 1, false}, + {1, "prudential", 1, false}, + {1, "pub", 1, false}, + {1, "pwc", 1, false}, + {1, "qpon", 1, false}, + {1, "quebec", 1, false}, + {1, "quest", 1, false}, + {1, "qvc", 1, false}, + {1, "racing", 1, false}, + {1, "radio", 1, false}, + {1, "raid", 1, false}, + {1, "read", 1, false}, + {1, "realestate", 1, false}, + {1, "realtor", 1, false}, + {1, "realty", 1, false}, + {1, "recipes", 1, false}, + {1, "red", 1, false}, + {1, "redstone", 1, false}, + {1, "redumbrella", 1, false}, + {1, "rehab", 1, false}, + {1, "reise", 1, false}, + {1, "reisen", 1, false}, + {1, "reit", 1, false}, + {1, "reliance", 1, false}, + {1, "ren", 1, false}, + {1, "rent", 1, false}, + {1, "rentals", 1, false}, + {1, "repair", 1, false}, + {1, "report", 1, false}, + {1, "republican", 1, false}, + {1, "rest", 1, false}, + {1, "restaurant", 1, false}, + {1, "review", 1, false}, + {1, "reviews", 1, false}, + {1, "rexroth", 1, false}, + {1, "rich", 1, false}, + {1, "richardli", 1, false}, + {1, "ricoh", 1, false}, + {1, "ril", 1, false}, + {1, "rio", 1, false}, + {1, "rip", 1, false}, + {1, "rmit", 1, false}, + {1, "rocher", 1, false}, + {1, "rocks", 1, false}, + {1, "rodeo", 1, false}, + {1, "rogers", 1, false}, + {1, "room", 1, false}, + {1, "rsvp", 1, false}, + {1, "rugby", 1, false}, + {1, "ruhr", 1, false}, + {1, "run", 1, false}, + {1, "rwe", 1, false}, + {1, "ryukyu", 1, false}, + {1, "saarland", 1, false}, + {1, "safe", 1, false}, + {1, "safety", 1, false}, + {1, "sakura", 1, false}, + {1, "sale", 1, false}, + {1, "salon", 1, false}, + {1, "samsclub", 1, false}, + {1, "samsung", 1, false}, + {1, "sandvik", 1, false}, + {1, "sandvikcoromant", 1, false}, + {1, "sanofi", 1, false}, + {1, "sap", 1, false}, + {1, "sarl", 1, false}, + {1, "sas", 1, false}, + {1, "save", 1, false}, + {1, "saxo", 1, false}, + {1, "sbi", 1, false}, + {1, "sbs", 1, false}, + {1, "sca", 1, false}, + {1, "scb", 1, false}, + {1, "schaeffler", 1, false}, + {1, "schmidt", 1, false}, + {1, "scholarships", 1, false}, + {1, "school", 1, false}, + {1, "schule", 1, false}, + {1, "schwarz", 1, false}, + {1, "science", 1, false}, + {1, "scjohnson", 1, false}, + {1, "scot", 1, false}, + {1, "search", 1, false}, + {1, "seat", 1, false}, + {1, "secure", 1, false}, + {1, "security", 1, false}, + {1, "seek", 1, false}, + {1, "select", 1, false}, + {1, "sener", 1, false}, + {1, "services", 1, false}, + {1, "ses", 1, false}, + {1, "seven", 1, false}, + {1, "sew", 1, false}, + {1, "sex", 1, false}, + {1, "sexy", 1, false}, + {1, "sfr", 1, false}, + {1, "shangrila", 1, false}, + {1, "sharp", 1, false}, + {1, "shaw", 1, false}, + {1, "shell", 1, false}, + {1, "shia", 1, false}, + {1, "shiksha", 1, false}, + {1, "shoes", 1, false}, + {1, "shop", 1, false}, + {1, "shopping", 1, false}, + {1, "shouji", 1, false}, + {1, "show", 1, false}, + {1, "showtime", 1, false}, + {1, "silk", 1, false}, + {1, "sina", 1, false}, + {1, "singles", 1, false}, + {1, "site", 1, false}, + {1, "ski", 1, false}, + {1, "skin", 1, false}, + {1, "sky", 1, false}, + {1, "skype", 1, false}, + {1, "sling", 1, false}, + {1, "smart", 1, false}, + {1, "smile", 1, false}, + {1, "sncf", 1, false}, + {1, "soccer", 1, false}, + {1, "social", 1, false}, + {1, "softbank", 1, false}, + {1, "software", 1, false}, + {1, "sohu", 1, false}, + {1, "solar", 1, false}, + {1, "solutions", 1, false}, + {1, "song", 1, false}, + {1, "sony", 1, false}, + {1, "soy", 1, false}, + {1, "spa", 1, false}, + {1, "space", 1, false}, + {1, "sport", 1, false}, + {1, "spot", 1, false}, + {1, "srl", 1, false}, + {1, "stada", 1, false}, + {1, "staples", 1, false}, + {1, "star", 1, false}, + {1, "statebank", 1, false}, + {1, "statefarm", 1, false}, + {1, "stc", 1, false}, + {1, "stcgroup", 1, false}, + {1, "stockholm", 1, false}, + {1, "storage", 1, false}, + {1, "store", 1, false}, + {1, "stream", 1, false}, + {1, "studio", 1, false}, + {1, "study", 1, false}, + {1, "style", 1, false}, + {1, "sucks", 1, false}, + {1, "supplies", 1, false}, + {1, "supply", 1, false}, + {1, "support", 1, false}, + {1, "surf", 1, false}, + {1, "surgery", 1, false}, + {1, "suzuki", 1, false}, + {1, "swatch", 1, false}, + {1, "swiftcover", 1, false}, + {1, "swiss", 1, false}, + {1, "sydney", 1, false}, + {1, "systems", 1, false}, + {1, "tab", 1, false}, + {1, "taipei", 1, false}, + {1, "talk", 1, false}, + {1, "taobao", 1, false}, + {1, "target", 1, false}, + {1, "tatamotors", 1, false}, + {1, "tatar", 1, false}, + {1, "tattoo", 1, false}, + {1, "tax", 1, false}, + {1, "taxi", 1, false}, + {1, "tci", 1, false}, + {1, "tdk", 1, false}, + {1, "team", 1, false}, + {1, "tech", 1, false}, + {1, "technology", 1, false}, + {1, "temasek", 1, false}, + {1, "tennis", 1, false}, + {1, "teva", 1, false}, + {1, "thd", 1, false}, + {1, "theater", 1, false}, + {1, "theatre", 1, false}, + {1, "tiaa", 1, false}, + {1, "tickets", 1, false}, + {1, "tienda", 1, false}, + {1, "tiffany", 1, false}, + {1, "tips", 1, false}, + {1, "tires", 1, false}, + {1, "tirol", 1, false}, + {1, "tjmaxx", 1, false}, + {1, "tjx", 1, false}, + {1, "tkmaxx", 1, false}, + {1, "tmall", 1, false}, + {1, "today", 1, false}, + {1, "tokyo", 1, false}, + {1, "tools", 1, false}, + {1, "top", 1, false}, + {1, "toray", 1, false}, + {1, "toshiba", 1, false}, + {1, "total", 1, false}, + {1, "tours", 1, false}, + {1, "town", 1, false}, + {1, "toyota", 1, false}, + {1, "toys", 1, false}, + {1, "trade", 1, false}, + {1, "trading", 1, false}, + {1, "training", 1, false}, + {1, "travel", 1, false}, + {1, "travelchannel", 1, false}, + {1, "travelers", 1, false}, + {1, "travelersinsurance", 1, false}, + {1, "trust", 1, false}, + {1, "trv", 1, false}, + {1, "tube", 1, false}, + {1, "tui", 1, false}, + {1, "tunes", 1, false}, + {1, "tushu", 1, false}, + {1, "tvs", 1, false}, + {1, "ubank", 1, false}, + {1, "ubs", 1, false}, + {1, "unicom", 1, false}, + {1, "university", 1, false}, + {1, "uno", 1, false}, + {1, "uol", 1, false}, + {1, "ups", 1, false}, + {1, "vacations", 1, false}, + {1, "vana", 1, false}, + {1, "vanguard", 1, false}, + {1, "vegas", 1, false}, + {1, "ventures", 1, false}, + {1, "verisign", 1, false}, + {1, "versicherung", 1, false}, + {1, "vet", 1, false}, + {1, "viajes", 1, false}, + {1, "video", 1, false}, + {1, "vig", 1, false}, + {1, "viking", 1, false}, + {1, "villas", 1, false}, + {1, "vin", 1, false}, + {1, "vip", 1, false}, + {1, "virgin", 1, false}, + {1, "visa", 1, false}, + {1, "vision", 1, false}, + {1, "viva", 1, false}, + {1, "vivo", 1, false}, + {1, "vlaanderen", 1, false}, + {1, "vodka", 1, false}, + {1, "volkswagen", 1, false}, + {1, "volvo", 1, false}, + {1, "vote", 1, false}, + {1, "voting", 1, false}, + {1, "voto", 1, false}, + {1, "voyage", 1, false}, + {1, "vuelos", 1, false}, + {1, "wales", 1, false}, + {1, "walmart", 1, false}, + {1, "walter", 1, false}, + {1, "wang", 1, false}, + {1, "wanggou", 1, false}, + {1, "watch", 1, false}, + {1, "watches", 1, false}, + {1, "weather", 1, false}, + {1, "weatherchannel", 1, false}, + {1, "webcam", 1, false}, + {1, "weber", 1, false}, + {1, "website", 1, false}, + {1, "wedding", 1, false}, + {1, "weibo", 1, false}, + {1, "weir", 1, false}, + {1, "whoswho", 1, false}, + {1, "wien", 1, false}, + {1, "wiki", 1, false}, + {1, "williamhill", 1, false}, + {1, "win", 1, false}, + {1, "windows", 1, false}, + {1, "wine", 1, false}, + {1, "winners", 1, false}, + {1, "wme", 1, false}, + {1, "wolterskluwer", 1, false}, + {1, "woodside", 1, false}, + {1, "work", 1, false}, + {1, "works", 1, false}, + {1, "world", 1, false}, + {1, "wow", 1, false}, + {1, "wtc", 1, false}, + {1, "wtf", 1, false}, + {1, "xbox", 1, false}, + {1, "xerox", 1, false}, + {1, "xfinity", 1, false}, + {1, "xihuan", 1, false}, + {1, "xin", 1, false}, + {1, "xn--11b4c3d", 1, false}, + {1, "xn--1ck2e1b", 1, false}, + {1, "xn--1qqw23a", 1, false}, + {1, "xn--30rr7y", 1, false}, + {1, "xn--3bst00m", 1, false}, + {1, "xn--3ds443g", 1, false}, + {1, "xn--3oq18vl8pn36a", 1, false}, + {1, "xn--3pxu8k", 1, false}, + {1, "xn--42c2d9a", 1, false}, + {1, "xn--45q11c", 1, false}, + {1, "xn--4gbrim", 1, false}, + {1, "xn--55qw42g", 1, false}, + {1, "xn--55qx5d", 1, false}, + {1, "xn--5su34j936bgsg", 1, false}, + {1, "xn--5tzm5g", 1, false}, + {1, "xn--6frz82g", 1, false}, + {1, "xn--6qq986b3xl", 1, false}, + {1, "xn--80adxhks", 1, false}, + {1, "xn--80aqecdr1a", 1, false}, + {1, "xn--80asehdb", 1, false}, + {1, "xn--80aswg", 1, false}, + {1, "xn--8y0a063a", 1, false}, + {1, "xn--9dbq2a", 1, false}, + {1, "xn--9et52u", 1, false}, + {1, "xn--9krt00a", 1, false}, + {1, "xn--b4w605ferd", 1, false}, + {1, "xn--bck1b9a5dre4c", 1, false}, + {1, "xn--c1avg", 1, false}, + {1, "xn--c2br7g", 1, false}, + {1, "xn--cck2b3b", 1, false}, + {1, "xn--cckwcxetd", 1, false}, + {1, "xn--cg4bki", 1, false}, + {1, "xn--czr694b", 1, false}, + {1, "xn--czrs0t", 1, false}, + {1, "xn--czru2d", 1, false}, + {1, "xn--d1acj3b", 1, false}, + {1, "xn--eckvdtc9d", 1, false}, + {1, "xn--efvy88h", 1, false}, + {1, "xn--fct429k", 1, false}, + {1, "xn--fhbei", 1, false}, + {1, "xn--fiq228c5hs", 1, false}, + {1, "xn--fiq64b", 1, false}, + {1, "xn--fjq720a", 1, false}, + {1, "xn--flw351e", 1, false}, + {1, "xn--fzys8d69uvgm", 1, false}, + {1, "xn--g2xx48c", 1, false}, + {1, "xn--gckr3f0f", 1, false}, + {1, "xn--gk3at1e", 1, false}, + {1, "xn--hxt814e", 1, false}, + {1, "xn--i1b6b1a6a2e", 1, false}, + {1, "xn--imr513n", 1, false}, + {1, "xn--io0a7i", 1, false}, + {1, "xn--j1aef", 1, false}, + {1, "xn--jlq480n2rg", 1, false}, + {1, "xn--jlq61u9w7b", 1, false}, + {1, "xn--jvr189m", 1, false}, + {1, "xn--kcrx77d1x4a", 1, false}, + {1, "xn--kput3i", 1, false}, + {1, "xn--mgba3a3ejt", 1, false}, + {1, "xn--mgba7c0bbn0a", 1, false}, + {1, "xn--mgbaakc7dvf", 1, false}, + {1, "xn--mgbab2bd", 1, false}, + {1, "xn--mgbca7dzdo", 1, false}, + {1, "xn--mgbi4ecexp", 1, false}, + {1, "xn--mgbt3dhd", 1, false}, + {1, "xn--mk1bu44c", 1, false}, + {1, "xn--mxtq1m", 1, false}, + {1, "xn--ngbc5azd", 1, false}, + {1, "xn--ngbe9e0a", 1, false}, + {1, "xn--ngbrx", 1, false}, + {1, "xn--nqv7f", 1, false}, + {1, "xn--nqv7fs00ema", 1, false}, + {1, "xn--nyqy26a", 1, false}, + {1, "xn--otu796d", 1, false}, + {1, "xn--p1acf", 1, false}, + {1, "xn--pssy2u", 1, false}, + {1, "xn--q9jyb4c", 1, false}, + {1, "xn--qcka1pmc", 1, false}, + {1, "xn--rhqv96g", 1, false}, + {1, "xn--rovu88b", 1, false}, + {1, "xn--ses554g", 1, false}, + {1, "xn--t60b56a", 1, false}, + {1, "xn--tckwe", 1, false}, + {1, "xn--tiq49xqyj", 1, false}, + {1, "xn--unup4y", 1, false}, + {1, "xn--vermgensberater-ctb", 1, false}, + {1, "xn--vermgensberatung-pwb", 1, false}, + {1, "xn--vhquv", 1, false}, + {1, "xn--vuq861b", 1, false}, + {1, "xn--w4r85el8fhu5dnra", 1, false}, + {1, "xn--w4rs40l", 1, false}, + {1, "xn--xhq521b", 1, false}, + {1, "xn--zfr164b", 1, false}, + {1, "xyz", 1, false}, + {1, "yachts", 1, false}, + {1, "yahoo", 1, false}, + {1, "yamaxun", 1, false}, + {1, "yandex", 1, false}, + {1, "yodobashi", 1, false}, + {1, "yoga", 1, false}, + {1, "yokohama", 1, false}, + {1, "you", 1, false}, + {1, "youtube", 1, false}, + {1, "yun", 1, false}, + {1, "zappos", 1, false}, + {1, "zara", 1, false}, + {1, "zero", 1, false}, + {1, "zip", 1, false}, + {1, "zone", 1, false}, + {1, "zuerich", 1, false}, + {1, "cc.ua", 2, true}, + {1, "inf.ua", 2, true}, + {1, "ltd.ua", 2, true}, + {1, "611.to", 2, true}, + {1, "graphox.us", 2, true}, + {2, "devcdnaccesso.com", 3, true}, + {1, "adobeaemcloud.com", 2, true}, + {1, "adobeaemcloud.net", 2, true}, + {2, "dev.adobeaemcloud.com", 4, true}, + {1, "beep.pl", 2, true}, + {1, "barsy.ca", 2, true}, + {2, "compute.estate", 3, true}, + {2, "alces.network", 3, true}, + {1, "kasserver.com", 2, true}, + {1, "altervista.org", 2, true}, + {1, "alwaysdata.net", 2, true}, + {1, "cloudfront.net", 2, true}, + {2, "compute.amazonaws.com", 4, true}, + {2, "compute-1.amazonaws.com", 4, true}, + {2, "compute.amazonaws.com.cn", 5, true}, + {1, "us-east-1.amazonaws.com", 3, true}, + {1, "cn-north-1.eb.amazonaws.com.cn", 5, true}, + {1, "cn-northwest-1.eb.amazonaws.com.cn", 5, true}, + {1, "elasticbeanstalk.com", 2, true}, + {1, "ap-northeast-1.elasticbeanstalk.com", 3, true}, + {1, "ap-northeast-2.elasticbeanstalk.com", 3, true}, + {1, "ap-northeast-3.elasticbeanstalk.com", 3, true}, + {1, "ap-south-1.elasticbeanstalk.com", 3, true}, + {1, "ap-southeast-1.elasticbeanstalk.com", 3, true}, + {1, "ap-southeast-2.elasticbeanstalk.com", 3, true}, + {1, "ca-central-1.elasticbeanstalk.com", 3, true}, + {1, "eu-central-1.elasticbeanstalk.com", 3, true}, + {1, "eu-west-1.elasticbeanstalk.com", 3, true}, + {1, "eu-west-2.elasticbeanstalk.com", 3, true}, + {1, "eu-west-3.elasticbeanstalk.com", 3, true}, + {1, "sa-east-1.elasticbeanstalk.com", 3, true}, + {1, "us-east-1.elasticbeanstalk.com", 3, true}, + {1, "us-east-2.elasticbeanstalk.com", 3, true}, + {1, "us-gov-west-1.elasticbeanstalk.com", 3, true}, + {1, "us-west-1.elasticbeanstalk.com", 3, true}, + {1, "us-west-2.elasticbeanstalk.com", 3, true}, + {2, "elb.amazonaws.com", 4, true}, + {2, "elb.amazonaws.com.cn", 5, true}, + {1, "awsglobalaccelerator.com", 2, true}, + {1, "s3.amazonaws.com", 3, true}, + {1, "s3-ap-northeast-1.amazonaws.com", 3, true}, + {1, "s3-ap-northeast-2.amazonaws.com", 3, true}, + {1, "s3-ap-south-1.amazonaws.com", 3, true}, + {1, "s3-ap-southeast-1.amazonaws.com", 3, true}, + {1, "s3-ap-southeast-2.amazonaws.com", 3, true}, + {1, "s3-ca-central-1.amazonaws.com", 3, true}, + {1, "s3-eu-central-1.amazonaws.com", 3, true}, + {1, "s3-eu-west-1.amazonaws.com", 3, true}, + {1, "s3-eu-west-2.amazonaws.com", 3, true}, + {1, "s3-eu-west-3.amazonaws.com", 3, true}, + {1, "s3-external-1.amazonaws.com", 3, true}, + {1, "s3-fips-us-gov-west-1.amazonaws.com", 3, true}, + {1, "s3-sa-east-1.amazonaws.com", 3, true}, + {1, "s3-us-gov-west-1.amazonaws.com", 3, true}, + {1, "s3-us-east-2.amazonaws.com", 3, true}, + {1, "s3-us-west-1.amazonaws.com", 3, true}, + {1, "s3-us-west-2.amazonaws.com", 3, true}, + {1, "s3.ap-northeast-2.amazonaws.com", 4, true}, + {1, "s3.ap-south-1.amazonaws.com", 4, true}, + {1, "s3.cn-north-1.amazonaws.com.cn", 5, true}, + {1, "s3.ca-central-1.amazonaws.com", 4, true}, + {1, "s3.eu-central-1.amazonaws.com", 4, true}, + {1, "s3.eu-west-2.amazonaws.com", 4, true}, + {1, "s3.eu-west-3.amazonaws.com", 4, true}, + {1, "s3.us-east-2.amazonaws.com", 4, true}, + {1, "s3.dualstack.ap-northeast-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.ap-northeast-2.amazonaws.com", 5, true}, + {1, "s3.dualstack.ap-south-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.ap-southeast-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.ap-southeast-2.amazonaws.com", 5, true}, + {1, "s3.dualstack.ca-central-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.eu-central-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.eu-west-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.eu-west-2.amazonaws.com", 5, true}, + {1, "s3.dualstack.eu-west-3.amazonaws.com", 5, true}, + {1, "s3.dualstack.sa-east-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.us-east-1.amazonaws.com", 5, true}, + {1, "s3.dualstack.us-east-2.amazonaws.com", 5, true}, + {1, "s3-website-us-east-1.amazonaws.com", 3, true}, + {1, "s3-website-us-west-1.amazonaws.com", 3, true}, + {1, "s3-website-us-west-2.amazonaws.com", 3, true}, + {1, "s3-website-ap-northeast-1.amazonaws.com", 3, true}, + {1, "s3-website-ap-southeast-1.amazonaws.com", 3, true}, + {1, "s3-website-ap-southeast-2.amazonaws.com", 3, true}, + {1, "s3-website-eu-west-1.amazonaws.com", 3, true}, + {1, "s3-website-sa-east-1.amazonaws.com", 3, true}, + {1, "s3-website.ap-northeast-2.amazonaws.com", 4, true}, + {1, "s3-website.ap-south-1.amazonaws.com", 4, true}, + {1, "s3-website.ca-central-1.amazonaws.com", 4, true}, + {1, "s3-website.eu-central-1.amazonaws.com", 4, true}, + {1, "s3-website.eu-west-2.amazonaws.com", 4, true}, + {1, "s3-website.eu-west-3.amazonaws.com", 4, true}, + {1, "s3-website.us-east-2.amazonaws.com", 4, true}, + {1, "amsw.nl", 2, true}, + {1, "t3l3p0rt.net", 2, true}, + {1, "tele.amune.org", 3, true}, + {1, "apigee.io", 2, true}, + {1, "appspacehosted.com", 2, true}, + {1, "appspaceusercontent.com", 2, true}, + {1, "on-aptible.com", 2, true}, + {1, "user.aseinet.ne.jp", 4, true}, + {1, "gv.vc", 2, true}, + {1, "d.gv.vc", 3, true}, + {1, "user.party.eus", 3, true}, + {1, "pimienta.org", 2, true}, + {1, "poivron.org", 2, true}, + {1, "potager.org", 2, true}, + {1, "sweetpepper.org", 2, true}, + {1, "myasustor.com", 2, true}, + {1, "myfritz.net", 2, true}, + {2, "awdev.ca", 3, true}, + {2, "advisor.ws", 3, true}, + {1, "b-data.io", 2, true}, + {1, "backplaneapp.io", 2, true}, + {1, "balena-devices.com", 2, true}, + {2, "banzai.cloud", 3, true}, + {1, "app.banzaicloud.io", 3, true}, + {2, "backyards.banzaicloud.io", 4, true}, + {1, "betainabox.com", 2, true}, + {1, "bnr.la", 2, true}, + {1, "blackbaudcdn.net", 2, true}, + {1, "of.je", 2, true}, + {1, "boomla.net", 2, true}, + {1, "boutir.com", 2, true}, + {1, "boxfuse.io", 2, true}, + {1, "square7.ch", 2, true}, + {1, "bplaced.com", 2, true}, + {1, "bplaced.de", 2, true}, + {1, "square7.de", 2, true}, + {1, "bplaced.net", 2, true}, + {1, "square7.net", 2, true}, + {1, "browsersafetymark.io", 2, true}, + {1, "uk0.bigv.io", 3, true}, + {1, "dh.bytemark.co.uk", 4, true}, + {1, "vm.bytemark.co.uk", 4, true}, + {1, "cafjs.com", 2, true}, + {1, "mycd.eu", 2, true}, + {1, "carrd.co", 2, true}, + {1, "crd.co", 2, true}, + {1, "uwu.ai", 2, true}, + {1, "ae.org", 2, true}, + {1, "br.com", 2, true}, + {1, "cn.com", 2, true}, + {1, "com.de", 2, true}, + {1, "com.se", 2, true}, + {1, "de.com", 2, true}, + {1, "eu.com", 2, true}, + {1, "gb.net", 2, true}, + {1, "hu.net", 2, true}, + {1, "jp.net", 2, true}, + {1, "jpn.com", 2, true}, + {1, "mex.com", 2, true}, + {1, "ru.com", 2, true}, + {1, "sa.com", 2, true}, + {1, "se.net", 2, true}, + {1, "uk.com", 2, true}, + {1, "uk.net", 2, true}, + {1, "us.com", 2, true}, + {1, "za.bz", 2, true}, + {1, "za.com", 2, true}, + {1, "ar.com", 2, true}, + {1, "gb.com", 2, true}, + {1, "hu.com", 2, true}, + {1, "kr.com", 2, true}, + {1, "no.com", 2, true}, + {1, "qc.com", 2, true}, + {1, "uy.com", 2, true}, + {1, "africa.com", 2, true}, + {1, "gr.com", 2, true}, + {1, "in.net", 2, true}, + {1, "web.in", 2, true}, + {1, "us.org", 2, true}, + {1, "co.com", 2, true}, + {1, "aus.basketball", 2, true}, + {1, "nz.basketball", 2, true}, + {1, "radio.am", 2, true}, + {1, "radio.fm", 2, true}, + {1, "c.la", 2, true}, + {1, "certmgr.org", 2, true}, + {1, "cx.ua", 2, true}, + {1, "discourse.group", 2, true}, + {1, "discourse.team", 2, true}, + {1, "virtueeldomein.nl", 2, true}, + {1, "cleverapps.io", 2, true}, + {2, "lcl.dev", 3, true}, + {2, "lclstage.dev", 3, true}, + {2, "stg.dev", 3, true}, + {2, "stgstage.dev", 3, true}, + {1, "clic2000.net", 2, true}, + {1, "clickrising.net", 2, true}, + {1, "c66.me", 2, true}, + {1, "cloud66.ws", 2, true}, + {1, "cloud66.zone", 2, true}, + {1, "jdevcloud.com", 2, true}, + {1, "wpdevcloud.com", 2, true}, + {1, "cloudaccess.host", 2, true}, + {1, "freesite.host", 2, true}, + {1, "cloudaccess.net", 2, true}, + {1, "cloudcontrolled.com", 2, true}, + {1, "cloudcontrolapp.com", 2, true}, + {1, "cloudera.site", 2, true}, + {1, "pages.dev", 2, true}, + {1, "trycloudflare.com", 2, true}, + {1, "workers.dev", 2, true}, + {1, "wnext.app", 2, true}, + {1, "co.ca", 2, true}, + {2, "otap.co", 3, true}, + {1, "co.cz", 2, true}, + {1, "c.cdn77.org", 3, true}, + {1, "cdn77-ssl.net", 2, true}, + {1, "r.cdn77.net", 3, true}, + {1, "rsc.cdn77.org", 3, true}, + {1, "ssl.origin.cdn77-secure.org", 4, true}, + {1, "cloudns.asia", 2, true}, + {1, "cloudns.biz", 2, true}, + {1, "cloudns.club", 2, true}, + {1, "cloudns.cc", 2, true}, + {1, "cloudns.eu", 2, true}, + {1, "cloudns.in", 2, true}, + {1, "cloudns.info", 2, true}, + {1, "cloudns.org", 2, true}, + {1, "cloudns.pro", 2, true}, + {1, "cloudns.pw", 2, true}, + {1, "cloudns.us", 2, true}, + {1, "cnpy.gdn", 2, true}, + {1, "co.nl", 2, true}, + {1, "co.no", 2, true}, + {1, "webhosting.be", 2, true}, + {1, "hosting-cluster.nl", 2, true}, + {1, "ac.ru", 2, true}, + {1, "edu.ru", 2, true}, + {1, "gov.ru", 2, true}, + {1, "int.ru", 2, true}, + {1, "mil.ru", 2, true}, + {1, "test.ru", 2, true}, + {1, "dyn.cosidns.de", 3, true}, + {1, "dynamisches-dns.de", 2, true}, + {1, "dnsupdater.de", 2, true}, + {1, "internet-dns.de", 2, true}, + {1, "l-o-g-i-n.de", 2, true}, + {1, "dynamic-dns.info", 2, true}, + {1, "feste-ip.net", 2, true}, + {1, "knx-server.net", 2, true}, + {1, "static-access.net", 2, true}, + {1, "realm.cz", 2, true}, + {2, "cryptonomic.net", 3, true}, + {1, "cupcake.is", 2, true}, + {1, "curv.dev", 2, true}, + {1, "multibaas.app", 2, true}, + {1, "multibaas.com", 2, true}, + {2, "customer-oci.com", 3, true}, + {2, "oci.customer-oci.com", 4, true}, + {2, "ocp.customer-oci.com", 4, true}, + {2, "ocs.customer-oci.com", 4, true}, + {1, "cyon.link", 2, true}, + {1, "cyon.site", 2, true}, + {1, "fnwk.site", 2, true}, + {1, "folionetwork.site", 2, true}, + {1, "platform0.app", 2, true}, + {1, "daplie.me", 2, true}, + {1, "localhost.daplie.me", 3, true}, + {1, "dattolocal.com", 2, true}, + {1, "dattorelay.com", 2, true}, + {1, "dattoweb.com", 2, true}, + {1, "mydatto.com", 2, true}, + {1, "dattolocal.net", 2, true}, + {1, "mydatto.net", 2, true}, + {1, "biz.dk", 2, true}, + {1, "co.dk", 2, true}, + {1, "firm.dk", 2, true}, + {1, "reg.dk", 2, true}, + {1, "store.dk", 2, true}, + {1, "dyndns.dappnode.io", 3, true}, + {2, "dapps.earth", 3, true}, + {2, "bzz.dapps.earth", 4, true}, + {1, "builtwithdark.com", 2, true}, + {1, "edgestack.me", 2, true}, + {1, "debian.net", 2, true}, + {1, "deno.dev", 2, true}, + {1, "deno-staging.dev", 2, true}, + {1, "dedyn.io", 2, true}, + {1, "jozi.biz", 2, true}, + {1, "dnshome.de", 2, true}, + {1, "online.th", 2, true}, + {1, "shop.th", 2, true}, + {1, "drayddns.com", 2, true}, + {1, "shoparena.pl", 2, true}, + {1, "dreamhosters.com", 2, true}, + {1, "mydrobo.com", 2, true}, + {1, "drud.io", 2, true}, + {1, "drud.us", 2, true}, + {1, "duckdns.org", 2, true}, + {1, "bip.sh", 2, true}, + {1, "bitbridge.net", 2, true}, + {1, "dy.fi", 2, true}, + {1, "tunk.org", 2, true}, + {1, "dyndns-at-home.com", 2, true}, + {1, "dyndns-at-work.com", 2, true}, + {1, "dyndns-blog.com", 2, true}, + {1, "dyndns-free.com", 2, true}, + {1, "dyndns-home.com", 2, true}, + {1, "dyndns-ip.com", 2, true}, + {1, "dyndns-mail.com", 2, true}, + {1, "dyndns-office.com", 2, true}, + {1, "dyndns-pics.com", 2, true}, + {1, "dyndns-remote.com", 2, true}, + {1, "dyndns-server.com", 2, true}, + {1, "dyndns-web.com", 2, true}, + {1, "dyndns-wiki.com", 2, true}, + {1, "dyndns-work.com", 2, true}, + {1, "dyndns.biz", 2, true}, + {1, "dyndns.info", 2, true}, + {1, "dyndns.org", 2, true}, + {1, "dyndns.tv", 2, true}, + {1, "at-band-camp.net", 2, true}, + {1, "ath.cx", 2, true}, + {1, "barrel-of-knowledge.info", 2, true}, + {1, "barrell-of-knowledge.info", 2, true}, + {1, "better-than.tv", 2, true}, + {1, "blogdns.com", 2, true}, + {1, "blogdns.net", 2, true}, + {1, "blogdns.org", 2, true}, + {1, "blogsite.org", 2, true}, + {1, "boldlygoingnowhere.org", 2, true}, + {1, "broke-it.net", 2, true}, + {1, "buyshouses.net", 2, true}, + {1, "cechire.com", 2, true}, + {1, "dnsalias.com", 2, true}, + {1, "dnsalias.net", 2, true}, + {1, "dnsalias.org", 2, true}, + {1, "dnsdojo.com", 2, true}, + {1, "dnsdojo.net", 2, true}, + {1, "dnsdojo.org", 2, true}, + {1, "does-it.net", 2, true}, + {1, "doesntexist.com", 2, true}, + {1, "doesntexist.org", 2, true}, + {1, "dontexist.com", 2, true}, + {1, "dontexist.net", 2, true}, + {1, "dontexist.org", 2, true}, + {1, "doomdns.com", 2, true}, + {1, "doomdns.org", 2, true}, + {1, "dvrdns.org", 2, true}, + {1, "dyn-o-saur.com", 2, true}, + {1, "dynalias.com", 2, true}, + {1, "dynalias.net", 2, true}, + {1, "dynalias.org", 2, true}, + {1, "dynathome.net", 2, true}, + {1, "dyndns.ws", 2, true}, + {1, "endofinternet.net", 2, true}, + {1, "endofinternet.org", 2, true}, + {1, "endoftheinternet.org", 2, true}, + {1, "est-a-la-maison.com", 2, true}, + {1, "est-a-la-masion.com", 2, true}, + {1, "est-le-patron.com", 2, true}, + {1, "est-mon-blogueur.com", 2, true}, + {1, "for-better.biz", 2, true}, + {1, "for-more.biz", 2, true}, + {1, "for-our.info", 2, true}, + {1, "for-some.biz", 2, true}, + {1, "for-the.biz", 2, true}, + {1, "forgot.her.name", 3, true}, + {1, "forgot.his.name", 3, true}, + {1, "from-ak.com", 2, true}, + {1, "from-al.com", 2, true}, + {1, "from-ar.com", 2, true}, + {1, "from-az.net", 2, true}, + {1, "from-ca.com", 2, true}, + {1, "from-co.net", 2, true}, + {1, "from-ct.com", 2, true}, + {1, "from-dc.com", 2, true}, + {1, "from-de.com", 2, true}, + {1, "from-fl.com", 2, true}, + {1, "from-ga.com", 2, true}, + {1, "from-hi.com", 2, true}, + {1, "from-ia.com", 2, true}, + {1, "from-id.com", 2, true}, + {1, "from-il.com", 2, true}, + {1, "from-in.com", 2, true}, + {1, "from-ks.com", 2, true}, + {1, "from-ky.com", 2, true}, + {1, "from-la.net", 2, true}, + {1, "from-ma.com", 2, true}, + {1, "from-md.com", 2, true}, + {1, "from-me.org", 2, true}, + {1, "from-mi.com", 2, true}, + {1, "from-mn.com", 2, true}, + {1, "from-mo.com", 2, true}, + {1, "from-ms.com", 2, true}, + {1, "from-mt.com", 2, true}, + {1, "from-nc.com", 2, true}, + {1, "from-nd.com", 2, true}, + {1, "from-ne.com", 2, true}, + {1, "from-nh.com", 2, true}, + {1, "from-nj.com", 2, true}, + {1, "from-nm.com", 2, true}, + {1, "from-nv.com", 2, true}, + {1, "from-ny.net", 2, true}, + {1, "from-oh.com", 2, true}, + {1, "from-ok.com", 2, true}, + {1, "from-or.com", 2, true}, + {1, "from-pa.com", 2, true}, + {1, "from-pr.com", 2, true}, + {1, "from-ri.com", 2, true}, + {1, "from-sc.com", 2, true}, + {1, "from-sd.com", 2, true}, + {1, "from-tn.com", 2, true}, + {1, "from-tx.com", 2, true}, + {1, "from-ut.com", 2, true}, + {1, "from-va.com", 2, true}, + {1, "from-vt.com", 2, true}, + {1, "from-wa.com", 2, true}, + {1, "from-wi.com", 2, true}, + {1, "from-wv.com", 2, true}, + {1, "from-wy.com", 2, true}, + {1, "ftpaccess.cc", 2, true}, + {1, "fuettertdasnetz.de", 2, true}, + {1, "game-host.org", 2, true}, + {1, "game-server.cc", 2, true}, + {1, "getmyip.com", 2, true}, + {1, "gets-it.net", 2, true}, + {1, "go.dyndns.org", 3, true}, + {1, "gotdns.com", 2, true}, + {1, "gotdns.org", 2, true}, + {1, "groks-the.info", 2, true}, + {1, "groks-this.info", 2, true}, + {1, "ham-radio-op.net", 2, true}, + {1, "here-for-more.info", 2, true}, + {1, "hobby-site.com", 2, true}, + {1, "hobby-site.org", 2, true}, + {1, "home.dyndns.org", 3, true}, + {1, "homedns.org", 2, true}, + {1, "homeftp.net", 2, true}, + {1, "homeftp.org", 2, true}, + {1, "homeip.net", 2, true}, + {1, "homelinux.com", 2, true}, + {1, "homelinux.net", 2, true}, + {1, "homelinux.org", 2, true}, + {1, "homeunix.com", 2, true}, + {1, "homeunix.net", 2, true}, + {1, "homeunix.org", 2, true}, + {1, "iamallama.com", 2, true}, + {1, "in-the-band.net", 2, true}, + {1, "is-a-anarchist.com", 2, true}, + {1, "is-a-blogger.com", 2, true}, + {1, "is-a-bookkeeper.com", 2, true}, + {1, "is-a-bruinsfan.org", 2, true}, + {1, "is-a-bulls-fan.com", 2, true}, + {1, "is-a-candidate.org", 2, true}, + {1, "is-a-caterer.com", 2, true}, + {1, "is-a-celticsfan.org", 2, true}, + {1, "is-a-chef.com", 2, true}, + {1, "is-a-chef.net", 2, true}, + {1, "is-a-chef.org", 2, true}, + {1, "is-a-conservative.com", 2, true}, + {1, "is-a-cpa.com", 2, true}, + {1, "is-a-cubicle-slave.com", 2, true}, + {1, "is-a-democrat.com", 2, true}, + {1, "is-a-designer.com", 2, true}, + {1, "is-a-doctor.com", 2, true}, + {1, "is-a-financialadvisor.com", 2, true}, + {1, "is-a-geek.com", 2, true}, + {1, "is-a-geek.net", 2, true}, + {1, "is-a-geek.org", 2, true}, + {1, "is-a-green.com", 2, true}, + {1, "is-a-guru.com", 2, true}, + {1, "is-a-hard-worker.com", 2, true}, + {1, "is-a-hunter.com", 2, true}, + {1, "is-a-knight.org", 2, true}, + {1, "is-a-landscaper.com", 2, true}, + {1, "is-a-lawyer.com", 2, true}, + {1, "is-a-liberal.com", 2, true}, + {1, "is-a-libertarian.com", 2, true}, + {1, "is-a-linux-user.org", 2, true}, + {1, "is-a-llama.com", 2, true}, + {1, "is-a-musician.com", 2, true}, + {1, "is-a-nascarfan.com", 2, true}, + {1, "is-a-nurse.com", 2, true}, + {1, "is-a-painter.com", 2, true}, + {1, "is-a-patsfan.org", 2, true}, + {1, "is-a-personaltrainer.com", 2, true}, + {1, "is-a-photographer.com", 2, true}, + {1, "is-a-player.com", 2, true}, + {1, "is-a-republican.com", 2, true}, + {1, "is-a-rockstar.com", 2, true}, + {1, "is-a-socialist.com", 2, true}, + {1, "is-a-soxfan.org", 2, true}, + {1, "is-a-student.com", 2, true}, + {1, "is-a-teacher.com", 2, true}, + {1, "is-a-techie.com", 2, true}, + {1, "is-a-therapist.com", 2, true}, + {1, "is-an-accountant.com", 2, true}, + {1, "is-an-actor.com", 2, true}, + {1, "is-an-actress.com", 2, true}, + {1, "is-an-anarchist.com", 2, true}, + {1, "is-an-artist.com", 2, true}, + {1, "is-an-engineer.com", 2, true}, + {1, "is-an-entertainer.com", 2, true}, + {1, "is-by.us", 2, true}, + {1, "is-certified.com", 2, true}, + {1, "is-found.org", 2, true}, + {1, "is-gone.com", 2, true}, + {1, "is-into-anime.com", 2, true}, + {1, "is-into-cars.com", 2, true}, + {1, "is-into-cartoons.com", 2, true}, + {1, "is-into-games.com", 2, true}, + {1, "is-leet.com", 2, true}, + {1, "is-lost.org", 2, true}, + {1, "is-not-certified.com", 2, true}, + {1, "is-saved.org", 2, true}, + {1, "is-slick.com", 2, true}, + {1, "is-uberleet.com", 2, true}, + {1, "is-very-bad.org", 2, true}, + {1, "is-very-evil.org", 2, true}, + {1, "is-very-good.org", 2, true}, + {1, "is-very-nice.org", 2, true}, + {1, "is-very-sweet.org", 2, true}, + {1, "is-with-theband.com", 2, true}, + {1, "isa-geek.com", 2, true}, + {1, "isa-geek.net", 2, true}, + {1, "isa-geek.org", 2, true}, + {1, "isa-hockeynut.com", 2, true}, + {1, "issmarterthanyou.com", 2, true}, + {1, "isteingeek.de", 2, true}, + {1, "istmein.de", 2, true}, + {1, "kicks-ass.net", 2, true}, + {1, "kicks-ass.org", 2, true}, + {1, "knowsitall.info", 2, true}, + {1, "land-4-sale.us", 2, true}, + {1, "lebtimnetz.de", 2, true}, + {1, "leitungsen.de", 2, true}, + {1, "likes-pie.com", 2, true}, + {1, "likescandy.com", 2, true}, + {1, "merseine.nu", 2, true}, + {1, "mine.nu", 2, true}, + {1, "misconfused.org", 2, true}, + {1, "mypets.ws", 2, true}, + {1, "myphotos.cc", 2, true}, + {1, "neat-url.com", 2, true}, + {1, "office-on-the.net", 2, true}, + {1, "on-the-web.tv", 2, true}, + {1, "podzone.net", 2, true}, + {1, "podzone.org", 2, true}, + {1, "readmyblog.org", 2, true}, + {1, "saves-the-whales.com", 2, true}, + {1, "scrapper-site.net", 2, true}, + {1, "scrapping.cc", 2, true}, + {1, "selfip.biz", 2, true}, + {1, "selfip.com", 2, true}, + {1, "selfip.info", 2, true}, + {1, "selfip.net", 2, true}, + {1, "selfip.org", 2, true}, + {1, "sells-for-less.com", 2, true}, + {1, "sells-for-u.com", 2, true}, + {1, "sells-it.net", 2, true}, + {1, "sellsyourhome.org", 2, true}, + {1, "servebbs.com", 2, true}, + {1, "servebbs.net", 2, true}, + {1, "servebbs.org", 2, true}, + {1, "serveftp.net", 2, true}, + {1, "serveftp.org", 2, true}, + {1, "servegame.org", 2, true}, + {1, "shacknet.nu", 2, true}, + {1, "simple-url.com", 2, true}, + {1, "space-to-rent.com", 2, true}, + {1, "stuff-4-sale.org", 2, true}, + {1, "stuff-4-sale.us", 2, true}, + {1, "teaches-yoga.com", 2, true}, + {1, "thruhere.net", 2, true}, + {1, "traeumtgerade.de", 2, true}, + {1, "webhop.biz", 2, true}, + {1, "webhop.info", 2, true}, + {1, "webhop.net", 2, true}, + {1, "webhop.org", 2, true}, + {1, "worse-than.tv", 2, true}, + {1, "writesthisblog.com", 2, true}, + {1, "ddnss.de", 2, true}, + {1, "dyn.ddnss.de", 3, true}, + {1, "dyndns.ddnss.de", 3, true}, + {1, "dyndns1.de", 2, true}, + {1, "dyn-ip24.de", 2, true}, + {1, "home-webserver.de", 2, true}, + {1, "dyn.home-webserver.de", 3, true}, + {1, "myhome-server.de", 2, true}, + {1, "ddnss.org", 2, true}, + {1, "definima.net", 2, true}, + {1, "definima.io", 2, true}, + {1, "ondigitalocean.app", 2, true}, + {1, "bci.dnstrace.pro", 3, true}, + {1, "ddnsfree.com", 2, true}, + {1, "ddnsgeek.com", 2, true}, + {1, "giize.com", 2, true}, + {1, "gleeze.com", 2, true}, + {1, "kozow.com", 2, true}, + {1, "loseyourip.com", 2, true}, + {1, "ooguy.com", 2, true}, + {1, "theworkpc.com", 2, true}, + {1, "casacam.net", 2, true}, + {1, "dynu.net", 2, true}, + {1, "accesscam.org", 2, true}, + {1, "camdvr.org", 2, true}, + {1, "freeddns.org", 2, true}, + {1, "mywire.org", 2, true}, + {1, "webredirect.org", 2, true}, + {1, "myddns.rocks", 2, true}, + {1, "blogsite.xyz", 2, true}, + {1, "dynv6.net", 2, true}, + {1, "e4.cz", 2, true}, + {1, "en-root.fr", 2, true}, + {1, "mytuleap.com", 2, true}, + {1, "onred.one", 2, true}, + {1, "staging.onred.one", 3, true}, + {1, "service.one", 2, true}, + {1, "enonic.io", 2, true}, + {1, "customer.enonic.io", 3, true}, + {1, "eu.org", 2, true}, + {1, "al.eu.org", 3, true}, + {1, "asso.eu.org", 3, true}, + {1, "at.eu.org", 3, true}, + {1, "au.eu.org", 3, true}, + {1, "be.eu.org", 3, true}, + {1, "bg.eu.org", 3, true}, + {1, "ca.eu.org", 3, true}, + {1, "cd.eu.org", 3, true}, + {1, "ch.eu.org", 3, true}, + {1, "cn.eu.org", 3, true}, + {1, "cy.eu.org", 3, true}, + {1, "cz.eu.org", 3, true}, + {1, "de.eu.org", 3, true}, + {1, "dk.eu.org", 3, true}, + {1, "edu.eu.org", 3, true}, + {1, "ee.eu.org", 3, true}, + {1, "es.eu.org", 3, true}, + {1, "fi.eu.org", 3, true}, + {1, "fr.eu.org", 3, true}, + {1, "gr.eu.org", 3, true}, + {1, "hr.eu.org", 3, true}, + {1, "hu.eu.org", 3, true}, + {1, "ie.eu.org", 3, true}, + {1, "il.eu.org", 3, true}, + {1, "in.eu.org", 3, true}, + {1, "int.eu.org", 3, true}, + {1, "is.eu.org", 3, true}, + {1, "it.eu.org", 3, true}, + {1, "jp.eu.org", 3, true}, + {1, "kr.eu.org", 3, true}, + {1, "lt.eu.org", 3, true}, + {1, "lu.eu.org", 3, true}, + {1, "lv.eu.org", 3, true}, + {1, "mc.eu.org", 3, true}, + {1, "me.eu.org", 3, true}, + {1, "mk.eu.org", 3, true}, + {1, "mt.eu.org", 3, true}, + {1, "my.eu.org", 3, true}, + {1, "net.eu.org", 3, true}, + {1, "ng.eu.org", 3, true}, + {1, "nl.eu.org", 3, true}, + {1, "no.eu.org", 3, true}, + {1, "nz.eu.org", 3, true}, + {1, "paris.eu.org", 3, true}, + {1, "pl.eu.org", 3, true}, + {1, "pt.eu.org", 3, true}, + {1, "q-a.eu.org", 3, true}, + {1, "ro.eu.org", 3, true}, + {1, "ru.eu.org", 3, true}, + {1, "se.eu.org", 3, true}, + {1, "si.eu.org", 3, true}, + {1, "sk.eu.org", 3, true}, + {1, "tr.eu.org", 3, true}, + {1, "uk.eu.org", 3, true}, + {1, "us.eu.org", 3, true}, + {1, "eurodir.ru", 2, true}, + {1, "eu-1.evennode.com", 3, true}, + {1, "eu-2.evennode.com", 3, true}, + {1, "eu-3.evennode.com", 3, true}, + {1, "eu-4.evennode.com", 3, true}, + {1, "us-1.evennode.com", 3, true}, + {1, "us-2.evennode.com", 3, true}, + {1, "us-3.evennode.com", 3, true}, + {1, "us-4.evennode.com", 3, true}, + {1, "twmail.cc", 2, true}, + {1, "twmail.net", 2, true}, + {1, "twmail.org", 2, true}, + {1, "mymailer.com.tw", 3, true}, + {1, "url.tw", 2, true}, + {1, "onfabrica.com", 2, true}, + {1, "apps.fbsbx.com", 3, true}, + {1, "ru.net", 2, true}, + {1, "adygeya.ru", 2, true}, + {1, "bashkiria.ru", 2, true}, + {1, "bir.ru", 2, true}, + {1, "cbg.ru", 2, true}, + {1, "com.ru", 2, true}, + {1, "dagestan.ru", 2, true}, + {1, "grozny.ru", 2, true}, + {1, "kalmykia.ru", 2, true}, + {1, "kustanai.ru", 2, true}, + {1, "marine.ru", 2, true}, + {1, "mordovia.ru", 2, true}, + {1, "msk.ru", 2, true}, + {1, "mytis.ru", 2, true}, + {1, "nalchik.ru", 2, true}, + {1, "nov.ru", 2, true}, + {1, "pyatigorsk.ru", 2, true}, + {1, "spb.ru", 2, true}, + {1, "vladikavkaz.ru", 2, true}, + {1, "vladimir.ru", 2, true}, + {1, "abkhazia.su", 2, true}, + {1, "adygeya.su", 2, true}, + {1, "aktyubinsk.su", 2, true}, + {1, "arkhangelsk.su", 2, true}, + {1, "armenia.su", 2, true}, + {1, "ashgabad.su", 2, true}, + {1, "azerbaijan.su", 2, true}, + {1, "balashov.su", 2, true}, + {1, "bashkiria.su", 2, true}, + {1, "bryansk.su", 2, true}, + {1, "bukhara.su", 2, true}, + {1, "chimkent.su", 2, true}, + {1, "dagestan.su", 2, true}, + {1, "east-kazakhstan.su", 2, true}, + {1, "exnet.su", 2, true}, + {1, "georgia.su", 2, true}, + {1, "grozny.su", 2, true}, + {1, "ivanovo.su", 2, true}, + {1, "jambyl.su", 2, true}, + {1, "kalmykia.su", 2, true}, + {1, "kaluga.su", 2, true}, + {1, "karacol.su", 2, true}, + {1, "karaganda.su", 2, true}, + {1, "karelia.su", 2, true}, + {1, "khakassia.su", 2, true}, + {1, "krasnodar.su", 2, true}, + {1, "kurgan.su", 2, true}, + {1, "kustanai.su", 2, true}, + {1, "lenug.su", 2, true}, + {1, "mangyshlak.su", 2, true}, + {1, "mordovia.su", 2, true}, + {1, "msk.su", 2, true}, + {1, "murmansk.su", 2, true}, + {1, "nalchik.su", 2, true}, + {1, "navoi.su", 2, true}, + {1, "north-kazakhstan.su", 2, true}, + {1, "nov.su", 2, true}, + {1, "obninsk.su", 2, true}, + {1, "penza.su", 2, true}, + {1, "pokrovsk.su", 2, true}, + {1, "sochi.su", 2, true}, + {1, "spb.su", 2, true}, + {1, "tashkent.su", 2, true}, + {1, "termez.su", 2, true}, + {1, "togliatti.su", 2, true}, + {1, "troitsk.su", 2, true}, + {1, "tselinograd.su", 2, true}, + {1, "tula.su", 2, true}, + {1, "tuva.su", 2, true}, + {1, "vladikavkaz.su", 2, true}, + {1, "vladimir.su", 2, true}, + {1, "vologda.su", 2, true}, + {1, "channelsdvr.net", 2, true}, + {1, "u.channelsdvr.net", 3, true}, + {1, "edgecompute.app", 2, true}, + {1, "fastly-terrarium.com", 2, true}, + {1, "fastlylb.net", 2, true}, + {1, "map.fastlylb.net", 3, true}, + {1, "freetls.fastly.net", 3, true}, + {1, "map.fastly.net", 3, true}, + {1, "a.prod.fastly.net", 4, true}, + {1, "global.prod.fastly.net", 4, true}, + {1, "a.ssl.fastly.net", 4, true}, + {1, "b.ssl.fastly.net", 4, true}, + {1, "global.ssl.fastly.net", 4, true}, + {1, "fastvps-server.com", 2, true}, + {1, "fastvps.host", 2, true}, + {1, "myfast.host", 2, true}, + {1, "fastvps.site", 2, true}, + {1, "myfast.space", 2, true}, + {1, "fedorainfracloud.org", 2, true}, + {1, "fedorapeople.org", 2, true}, + {1, "cloud.fedoraproject.org", 3, true}, + {1, "app.os.fedoraproject.org", 4, true}, + {1, "app.os.stg.fedoraproject.org", 5, true}, + {1, "couk.me", 2, true}, + {1, "ukco.me", 2, true}, + {1, "conn.uk", 2, true}, + {1, "copro.uk", 2, true}, + {1, "hosp.uk", 2, true}, + {1, "mydobiss.com", 2, true}, + {1, "fh-muenster.io", 2, true}, + {1, "filegear.me", 2, true}, + {1, "filegear-au.me", 2, true}, + {1, "filegear-de.me", 2, true}, + {1, "filegear-gb.me", 2, true}, + {1, "filegear-ie.me", 2, true}, + {1, "filegear-jp.me", 2, true}, + {1, "filegear-sg.me", 2, true}, + {1, "firebaseapp.com", 2, true}, + {1, "fireweb.app", 2, true}, + {1, "flap.id", 2, true}, + {1, "fly.dev", 2, true}, + {1, "edgeapp.net", 2, true}, + {1, "shw.io", 2, true}, + {1, "flynnhosting.net", 2, true}, + {1, "forgeblocks.com", 2, true}, + {2, "id.forgerock.io", 4, true}, + {1, "framer.app", 2, true}, + {1, "framercanvas.com", 2, true}, + {1, "ravpage.co.il", 3, true}, + {1, "0e.vc", 2, true}, + {1, "freebox-os.com", 2, true}, + {1, "freeboxos.com", 2, true}, + {1, "fbx-os.fr", 2, true}, + {1, "fbxos.fr", 2, true}, + {1, "freebox-os.fr", 2, true}, + {1, "freeboxos.fr", 2, true}, + {1, "freedesktop.org", 2, true}, + {1, "freemyip.com", 2, true}, + {1, "wien.funkfeuer.at", 3, true}, + {2, "futurecms.at", 3, true}, + {2, "ex.futurecms.at", 4, true}, + {2, "in.futurecms.at", 4, true}, + {1, "futurehosting.at", 2, true}, + {1, "futuremailing.at", 2, true}, + {2, "ex.ortsinfo.at", 4, true}, + {2, "kunden.ortsinfo.at", 4, true}, + {2, "statics.cloud", 3, true}, + {1, "service.gov.uk", 3, true}, + {1, "gehirn.ne.jp", 3, true}, + {1, "usercontent.jp", 2, true}, + {1, "gentapps.com", 2, true}, + {1, "gentlentapis.com", 2, true}, + {1, "lab.ms", 2, true}, + {1, "cdn-edges.net", 2, true}, + {1, "ghost.io", 2, true}, + {1, "gsj.bz", 2, true}, + {1, "githubusercontent.com", 2, true}, + {1, "github.dev", 2, true}, + {1, "githubpreview.dev", 2, true}, + {1, "github.io", 2, true}, + {1, "gitlab.io", 2, true}, + {1, "gitapp.si", 2, true}, + {1, "gitpage.si", 2, true}, + {1, "glitch.me", 2, true}, + {1, "co.ro", 2, true}, + {1, "shop.ro", 2, true}, + {1, "lolipop.io", 2, true}, + {1, "cloudapps.digital", 2, true}, + {1, "london.cloudapps.digital", 3, true}, + {1, "pymnt.uk", 2, true}, + {1, "homeoffice.gov.uk", 3, true}, + {1, "ro.im", 2, true}, + {1, "goip.de", 2, true}, + {1, "run.app", 2, true}, + {1, "a.run.app", 3, true}, + {1, "web.app", 2, true}, + {2, "0emm.com", 3, true}, + {1, "appspot.com", 2, true}, + {2, "r.appspot.com", 4, true}, + {1, "codespot.com", 2, true}, + {1, "googleapis.com", 2, true}, + {1, "googlecode.com", 2, true}, + {1, "pagespeedmobilizer.com", 2, true}, + {1, "publishproxy.com", 2, true}, + {1, "withgoogle.com", 2, true}, + {1, "withyoutube.com", 2, true}, + {2, "gateway.dev", 3, true}, + {1, "cloud.goog", 2, true}, + {1, "translate.goog", 2, true}, + {1, "cloudfunctions.net", 2, true}, + {1, "blogspot.ae", 2, true}, + {1, "blogspot.al", 2, true}, + {1, "blogspot.am", 2, true}, + {1, "blogspot.ba", 2, true}, + {1, "blogspot.be", 2, true}, + {1, "blogspot.bg", 2, true}, + {1, "blogspot.bj", 2, true}, + {1, "blogspot.ca", 2, true}, + {1, "blogspot.cf", 2, true}, + {1, "blogspot.ch", 2, true}, + {1, "blogspot.cl", 2, true}, + {1, "blogspot.co.at", 3, true}, + {1, "blogspot.co.id", 3, true}, + {1, "blogspot.co.il", 3, true}, + {1, "blogspot.co.ke", 3, true}, + {1, "blogspot.co.nz", 3, true}, + {1, "blogspot.co.uk", 3, true}, + {1, "blogspot.co.za", 3, true}, + {1, "blogspot.com", 2, true}, + {1, "blogspot.com.ar", 3, true}, + {1, "blogspot.com.au", 3, true}, + {1, "blogspot.com.br", 3, true}, + {1, "blogspot.com.by", 3, true}, + {1, "blogspot.com.co", 3, true}, + {1, "blogspot.com.cy", 3, true}, + {1, "blogspot.com.ee", 3, true}, + {1, "blogspot.com.eg", 3, true}, + {1, "blogspot.com.es", 3, true}, + {1, "blogspot.com.mt", 3, true}, + {1, "blogspot.com.ng", 3, true}, + {1, "blogspot.com.tr", 3, true}, + {1, "blogspot.com.uy", 3, true}, + {1, "blogspot.cv", 2, true}, + {1, "blogspot.cz", 2, true}, + {1, "blogspot.de", 2, true}, + {1, "blogspot.dk", 2, true}, + {1, "blogspot.fi", 2, true}, + {1, "blogspot.fr", 2, true}, + {1, "blogspot.gr", 2, true}, + {1, "blogspot.hk", 2, true}, + {1, "blogspot.hr", 2, true}, + {1, "blogspot.hu", 2, true}, + {1, "blogspot.ie", 2, true}, + {1, "blogspot.in", 2, true}, + {1, "blogspot.is", 2, true}, + {1, "blogspot.it", 2, true}, + {1, "blogspot.jp", 2, true}, + {1, "blogspot.kr", 2, true}, + {1, "blogspot.li", 2, true}, + {1, "blogspot.lt", 2, true}, + {1, "blogspot.lu", 2, true}, + {1, "blogspot.md", 2, true}, + {1, "blogspot.mk", 2, true}, + {1, "blogspot.mr", 2, true}, + {1, "blogspot.mx", 2, true}, + {1, "blogspot.my", 2, true}, + {1, "blogspot.nl", 2, true}, + {1, "blogspot.no", 2, true}, + {1, "blogspot.pe", 2, true}, + {1, "blogspot.pt", 2, true}, + {1, "blogspot.qa", 2, true}, + {1, "blogspot.re", 2, true}, + {1, "blogspot.ro", 2, true}, + {1, "blogspot.rs", 2, true}, + {1, "blogspot.ru", 2, true}, + {1, "blogspot.se", 2, true}, + {1, "blogspot.sg", 2, true}, + {1, "blogspot.si", 2, true}, + {1, "blogspot.sk", 2, true}, + {1, "blogspot.sn", 2, true}, + {1, "blogspot.td", 2, true}, + {1, "blogspot.tw", 2, true}, + {1, "blogspot.ug", 2, true}, + {1, "blogspot.vn", 2, true}, + {1, "goupile.fr", 2, true}, + {1, "awsmppl.com", 2, true}, + {1, "xn--gnstigbestellen-zvb.de", 2, true}, + {1, "xn--gnstigliefern-wob.de", 2, true}, + {1, "fin.ci", 2, true}, + {1, "free.hr", 2, true}, + {1, "caa.li", 2, true}, + {1, "ua.rs", 2, true}, + {1, "conf.se", 2, true}, + {1, "hs.zone", 2, true}, + {1, "hs.run", 2, true}, + {1, "hashbang.sh", 2, true}, + {1, "hasura.app", 2, true}, + {1, "hasura-app.io", 2, true}, + {1, "hepforge.org", 2, true}, + {1, "herokuapp.com", 2, true}, + {1, "herokussl.com", 2, true}, + {1, "myravendb.com", 2, true}, + {1, "ravendb.community", 2, true}, + {1, "ravendb.me", 2, true}, + {1, "development.run", 2, true}, + {1, "ravendb.run", 2, true}, + {1, "secaas.hk", 2, true}, + {1, "orx.biz", 2, true}, + {1, "biz.gl", 2, true}, + {1, "col.ng", 2, true}, + {1, "firm.ng", 2, true}, + {1, "gen.ng", 2, true}, + {1, "ltd.ng", 2, true}, + {1, "ngo.ng", 2, true}, + {1, "edu.scot", 2, true}, + {1, "sch.so", 2, true}, + {1, "org.yt", 2, true}, + {1, "hostyhosting.io", 2, true}, + {1, "xn--hkkinen-5wa.fi", 2, true}, + {2, "moonscale.io", 3, true}, + {1, "moonscale.net", 2, true}, + {1, "iki.fi", 2, true}, + {1, "impertrixcdn.com", 2, true}, + {1, "impertrix.com", 2, true}, + {1, "smushcdn.com", 2, true}, + {1, "wphostedmail.com", 2, true}, + {1, "wpmucdn.com", 2, true}, + {1, "tempurl.host", 2, true}, + {1, "wpmudev.host", 2, true}, + {1, "dyn-berlin.de", 2, true}, + {1, "in-berlin.de", 2, true}, + {1, "in-brb.de", 2, true}, + {1, "in-butter.de", 2, true}, + {1, "in-dsl.de", 2, true}, + {1, "in-dsl.net", 2, true}, + {1, "in-dsl.org", 2, true}, + {1, "in-vpn.de", 2, true}, + {1, "in-vpn.net", 2, true}, + {1, "in-vpn.org", 2, true}, + {1, "biz.at", 2, true}, + {1, "info.at", 2, true}, + {1, "info.cx", 2, true}, + {1, "ac.leg.br", 3, true}, + {1, "al.leg.br", 3, true}, + {1, "am.leg.br", 3, true}, + {1, "ap.leg.br", 3, true}, + {1, "ba.leg.br", 3, true}, + {1, "ce.leg.br", 3, true}, + {1, "df.leg.br", 3, true}, + {1, "es.leg.br", 3, true}, + {1, "go.leg.br", 3, true}, + {1, "ma.leg.br", 3, true}, + {1, "mg.leg.br", 3, true}, + {1, "ms.leg.br", 3, true}, + {1, "mt.leg.br", 3, true}, + {1, "pa.leg.br", 3, true}, + {1, "pb.leg.br", 3, true}, + {1, "pe.leg.br", 3, true}, + {1, "pi.leg.br", 3, true}, + {1, "pr.leg.br", 3, true}, + {1, "rj.leg.br", 3, true}, + {1, "rn.leg.br", 3, true}, + {1, "ro.leg.br", 3, true}, + {1, "rr.leg.br", 3, true}, + {1, "rs.leg.br", 3, true}, + {1, "sc.leg.br", 3, true}, + {1, "se.leg.br", 3, true}, + {1, "sp.leg.br", 3, true}, + {1, "to.leg.br", 3, true}, + {1, "pixolino.com", 2, true}, + {1, "na4u.ru", 2, true}, + {1, "iopsys.se", 2, true}, + {1, "ipifony.net", 2, true}, + {1, "mein-iserv.de", 2, true}, + {1, "schulserver.de", 2, true}, + {1, "test-iserv.de", 2, true}, + {1, "iserv.dev", 2, true}, + {1, "iobb.net", 2, true}, + {1, "mel.cloudlets.com.au", 4, true}, + {1, "cloud.interhostsolutions.be", 3, true}, + {1, "users.scale.virtualcloud.com.br", 5, true}, + {1, "mycloud.by", 2, true}, + {1, "alp1.ae.flow.ch", 4, true}, + {1, "appengine.flow.ch", 3, true}, + {1, "es-1.axarnet.cloud", 3, true}, + {1, "diadem.cloud", 2, true}, + {1, "vip.jelastic.cloud", 3, true}, + {1, "jele.cloud", 2, true}, + {1, "it1.eur.aruba.jenv-aruba.cloud", 5, true}, + {1, "it1.jenv-aruba.cloud", 3, true}, + {1, "keliweb.cloud", 2, true}, + {1, "cs.keliweb.cloud", 3, true}, + {1, "oxa.cloud", 2, true}, + {1, "tn.oxa.cloud", 3, true}, + {1, "uk.oxa.cloud", 3, true}, + {1, "primetel.cloud", 2, true}, + {1, "uk.primetel.cloud", 3, true}, + {1, "ca.reclaim.cloud", 3, true}, + {1, "uk.reclaim.cloud", 3, true}, + {1, "us.reclaim.cloud", 3, true}, + {1, "ch.trendhosting.cloud", 3, true}, + {1, "de.trendhosting.cloud", 3, true}, + {1, "jele.club", 2, true}, + {1, "amscompute.com", 2, true}, + {1, "clicketcloud.com", 2, true}, + {1, "dopaas.com", 2, true}, + {1, "hidora.com", 2, true}, + {1, "paas.hosted-by-previder.com", 3, true}, + {1, "rag-cloud.hosteur.com", 3, true}, + {1, "rag-cloud-ch.hosteur.com", 3, true}, + {1, "jcloud.ik-server.com", 3, true}, + {1, "jcloud-ver-jpc.ik-server.com", 3, true}, + {1, "demo.jelastic.com", 3, true}, + {1, "kilatiron.com", 2, true}, + {1, "paas.massivegrid.com", 3, true}, + {1, "jed.wafaicloud.com", 3, true}, + {1, "lon.wafaicloud.com", 3, true}, + {1, "ryd.wafaicloud.com", 3, true}, + {1, "j.scaleforce.com.cy", 4, true}, + {1, "jelastic.dogado.eu", 3, true}, + {1, "fi.cloudplatform.fi", 3, true}, + {1, "demo.datacenter.fi", 3, true}, + {1, "paas.datacenter.fi", 3, true}, + {1, "jele.host", 2, true}, + {1, "mircloud.host", 2, true}, + {1, "paas.beebyte.io", 3, true}, + {1, "sekd1.beebyteapp.io", 3, true}, + {1, "jele.io", 2, true}, + {1, "cloud-fr1.unispace.io", 3, true}, + {1, "jc.neen.it", 3, true}, + {1, "cloud.jelastic.open.tim.it", 5, true}, + {1, "jcloud.kz", 2, true}, + {1, "upaas.kazteleport.kz", 3, true}, + {1, "cloudjiffy.net", 2, true}, + {1, "fra1-de.cloudjiffy.net", 3, true}, + {1, "west1-us.cloudjiffy.net", 3, true}, + {1, "jls-sto1.elastx.net", 3, true}, + {1, "jls-sto2.elastx.net", 3, true}, + {1, "jls-sto3.elastx.net", 3, true}, + {1, "faststacks.net", 2, true}, + {1, "fr-1.paas.massivegrid.net", 4, true}, + {1, "lon-1.paas.massivegrid.net", 4, true}, + {1, "lon-2.paas.massivegrid.net", 4, true}, + {1, "ny-1.paas.massivegrid.net", 4, true}, + {1, "ny-2.paas.massivegrid.net", 4, true}, + {1, "sg-1.paas.massivegrid.net", 4, true}, + {1, "jelastic.saveincloud.net", 3, true}, + {1, "nordeste-idc.saveincloud.net", 3, true}, + {1, "j.scaleforce.net", 3, true}, + {1, "jelastic.tsukaeru.net", 3, true}, + {1, "sdscloud.pl", 2, true}, + {1, "unicloud.pl", 2, true}, + {1, "mircloud.ru", 2, true}, + {1, "jelastic.regruhosting.ru", 3, true}, + {1, "enscaled.sg", 2, true}, + {1, "jele.site", 2, true}, + {1, "jelastic.team", 2, true}, + {1, "orangecloud.tn", 2, true}, + {1, "j.layershift.co.uk", 4, true}, + {1, "phx.enscaled.us", 3, true}, + {1, "mircloud.us", 2, true}, + {1, "myjino.ru", 2, true}, + {2, "hosting.myjino.ru", 4, true}, + {2, "landing.myjino.ru", 4, true}, + {2, "spectrum.myjino.ru", 4, true}, + {2, "vps.myjino.ru", 4, true}, + {2, "triton.zone", 3, true}, + {2, "cns.joyent.com", 4, true}, + {1, "js.org", 2, true}, + {1, "kaas.gg", 2, true}, + {1, "khplay.nl", 2, true}, + {1, "keymachine.de", 2, true}, + {1, "kinghost.net", 2, true}, + {1, "uni5.net", 2, true}, + {1, "knightpoint.systems", 2, true}, + {1, "oya.to", 2, true}, + {1, "kuleuven.cloud", 2, true}, + {1, "ezproxy.kuleuven.be", 3, true}, + {1, "co.krd", 2, true}, + {1, "edu.krd", 2, true}, + {1, "krellian.net", 2, true}, + {1, "webthings.io", 2, true}, + {1, "git-repos.de", 2, true}, + {1, "lcube-server.de", 2, true}, + {1, "svn-repos.de", 2, true}, + {1, "leadpages.co", 2, true}, + {1, "lpages.co", 2, true}, + {1, "lpusercontent.com", 2, true}, + {1, "lelux.site", 2, true}, + {1, "co.business", 2, true}, + {1, "co.education", 2, true}, + {1, "co.events", 2, true}, + {1, "co.financial", 2, true}, + {1, "co.network", 2, true}, + {1, "co.place", 2, true}, + {1, "co.technology", 2, true}, + {1, "app.lmpm.com", 3, true}, + {1, "linkyard.cloud", 2, true}, + {1, "linkyard-cloud.ch", 2, true}, + {1, "members.linode.com", 3, true}, + {2, "nodebalancer.linode.com", 4, true}, + {2, "linodeobjects.com", 3, true}, + {1, "we.bs", 2, true}, + {1, "localzone.xyz", 2, true}, + {1, "loginline.app", 2, true}, + {1, "loginline.dev", 2, true}, + {1, "loginline.io", 2, true}, + {1, "loginline.services", 2, true}, + {1, "loginline.site", 2, true}, + {1, "lohmus.me", 2, true}, + {1, "krasnik.pl", 2, true}, + {1, "leczna.pl", 2, true}, + {1, "lubartow.pl", 2, true}, + {1, "lublin.pl", 2, true}, + {1, "poniatowa.pl", 2, true}, + {1, "swidnik.pl", 2, true}, + {1, "glug.org.uk", 3, true}, + {1, "lug.org.uk", 3, true}, + {1, "lugs.org.uk", 3, true}, + {1, "barsy.bg", 2, true}, + {1, "barsy.co.uk", 3, true}, + {1, "barsyonline.co.uk", 3, true}, + {1, "barsycenter.com", 2, true}, + {1, "barsyonline.com", 2, true}, + {1, "barsy.club", 2, true}, + {1, "barsy.de", 2, true}, + {1, "barsy.eu", 2, true}, + {1, "barsy.in", 2, true}, + {1, "barsy.info", 2, true}, + {1, "barsy.io", 2, true}, + {1, "barsy.me", 2, true}, + {1, "barsy.menu", 2, true}, + {1, "barsy.mobi", 2, true}, + {1, "barsy.net", 2, true}, + {1, "barsy.online", 2, true}, + {1, "barsy.org", 2, true}, + {1, "barsy.pro", 2, true}, + {1, "barsy.pub", 2, true}, + {1, "barsy.shop", 2, true}, + {1, "barsy.site", 2, true}, + {1, "barsy.support", 2, true}, + {1, "barsy.uk", 2, true}, + {2, "magentosite.cloud", 3, true}, + {1, "mayfirst.info", 2, true}, + {1, "mayfirst.org", 2, true}, + {1, "hb.cldmail.ru", 3, true}, + {1, "cn.vu", 2, true}, + {1, "mazeplay.com", 2, true}, + {1, "mcpe.me", 2, true}, + {1, "mcdir.me", 2, true}, + {1, "mcdir.ru", 2, true}, + {1, "mcpre.ru", 2, true}, + {1, "vps.mcdir.ru", 3, true}, + {1, "hra.health", 2, true}, + {1, "miniserver.com", 2, true}, + {1, "memset.net", 2, true}, + {2, "cloud.metacentrum.cz", 4, true}, + {1, "custom.metacentrum.cz", 3, true}, + {1, "flt.cloud.muni.cz", 4, true}, + {1, "usr.cloud.muni.cz", 4, true}, + {1, "meteorapp.com", 2, true}, + {1, "eu.meteorapp.com", 3, true}, + {1, "co.pl", 2, true}, + {2, "azurecontainer.io", 3, true}, + {1, "azurewebsites.net", 2, true}, + {1, "azure-mobile.net", 2, true}, + {1, "cloudapp.net", 2, true}, + {1, "azurestaticapps.net", 2, true}, + {1, "centralus.azurestaticapps.net", 3, true}, + {1, "eastasia.azurestaticapps.net", 3, true}, + {1, "eastus2.azurestaticapps.net", 3, true}, + {1, "westeurope.azurestaticapps.net", 3, true}, + {1, "westus2.azurestaticapps.net", 3, true}, + {1, "csx.cc", 2, true}, + {1, "mintere.site", 2, true}, + {1, "forte.id", 2, true}, + {1, "mozilla-iot.org", 2, true}, + {1, "bmoattachments.org", 2, true}, + {1, "net.ru", 2, true}, + {1, "org.ru", 2, true}, + {1, "pp.ru", 2, true}, + {1, "hostedpi.com", 2, true}, + {1, "customer.mythic-beasts.com", 3, true}, + {1, "caracal.mythic-beasts.com", 3, true}, + {1, "fentiger.mythic-beasts.com", 3, true}, + {1, "lynx.mythic-beasts.com", 3, true}, + {1, "ocelot.mythic-beasts.com", 3, true}, + {1, "oncilla.mythic-beasts.com", 3, true}, + {1, "onza.mythic-beasts.com", 3, true}, + {1, "sphinx.mythic-beasts.com", 3, true}, + {1, "vs.mythic-beasts.com", 3, true}, + {1, "x.mythic-beasts.com", 3, true}, + {1, "yali.mythic-beasts.com", 3, true}, + {1, "cust.retrosnub.co.uk", 4, true}, + {1, "ui.nabu.casa", 3, true}, + {1, "pony.club", 2, true}, + {1, "of.fashion", 2, true}, + {1, "in.london", 2, true}, + {1, "of.london", 2, true}, + {1, "from.marketing", 2, true}, + {1, "with.marketing", 2, true}, + {1, "for.men", 2, true}, + {1, "repair.men", 2, true}, + {1, "and.mom", 2, true}, + {1, "for.mom", 2, true}, + {1, "for.one", 2, true}, + {1, "under.one", 2, true}, + {1, "for.sale", 2, true}, + {1, "that.win", 2, true}, + {1, "from.work", 2, true}, + {1, "to.work", 2, true}, + {1, "nctu.me", 2, true}, + {1, "netlify.app", 2, true}, + {1, "4u.com", 2, true}, + {1, "ngrok.io", 2, true}, + {1, "nh-serv.co.uk", 3, true}, + {1, "nfshost.com", 2, true}, + {2, "developer.app", 3, true}, + {1, "noop.app", 2, true}, + {2, "northflank.app", 3, true}, + {2, "code.run", 3, true}, + {1, "noticeable.news", 2, true}, + {1, "dnsking.ch", 2, true}, + {1, "mypi.co", 2, true}, + {1, "n4t.co", 2, true}, + {1, "001www.com", 2, true}, + {1, "ddnslive.com", 2, true}, + {1, "myiphost.com", 2, true}, + {1, "forumz.info", 2, true}, + {1, "16-b.it", 2, true}, + {1, "32-b.it", 2, true}, + {1, "64-b.it", 2, true}, + {1, "soundcast.me", 2, true}, + {1, "tcp4.me", 2, true}, + {1, "dnsup.net", 2, true}, + {1, "hicam.net", 2, true}, + {1, "now-dns.net", 2, true}, + {1, "ownip.net", 2, true}, + {1, "vpndns.net", 2, true}, + {1, "dynserv.org", 2, true}, + {1, "now-dns.org", 2, true}, + {1, "x443.pw", 2, true}, + {1, "now-dns.top", 2, true}, + {1, "ntdll.top", 2, true}, + {1, "freeddns.us", 2, true}, + {1, "crafting.xyz", 2, true}, + {1, "zapto.xyz", 2, true}, + {1, "nsupdate.info", 2, true}, + {1, "nerdpol.ovh", 2, true}, + {1, "blogsyte.com", 2, true}, + {1, "brasilia.me", 2, true}, + {1, "cable-modem.org", 2, true}, + {1, "ciscofreak.com", 2, true}, + {1, "collegefan.org", 2, true}, + {1, "couchpotatofries.org", 2, true}, + {1, "damnserver.com", 2, true}, + {1, "ddns.me", 2, true}, + {1, "ditchyourip.com", 2, true}, + {1, "dnsfor.me", 2, true}, + {1, "dnsiskinky.com", 2, true}, + {1, "dvrcam.info", 2, true}, + {1, "dynns.com", 2, true}, + {1, "eating-organic.net", 2, true}, + {1, "fantasyleague.cc", 2, true}, + {1, "geekgalaxy.com", 2, true}, + {1, "golffan.us", 2, true}, + {1, "health-carereform.com", 2, true}, + {1, "homesecuritymac.com", 2, true}, + {1, "homesecuritypc.com", 2, true}, + {1, "hopto.me", 2, true}, + {1, "ilovecollege.info", 2, true}, + {1, "loginto.me", 2, true}, + {1, "mlbfan.org", 2, true}, + {1, "mmafan.biz", 2, true}, + {1, "myactivedirectory.com", 2, true}, + {1, "mydissent.net", 2, true}, + {1, "myeffect.net", 2, true}, + {1, "mymediapc.net", 2, true}, + {1, "mypsx.net", 2, true}, + {1, "mysecuritycamera.com", 2, true}, + {1, "mysecuritycamera.net", 2, true}, + {1, "mysecuritycamera.org", 2, true}, + {1, "net-freaks.com", 2, true}, + {1, "nflfan.org", 2, true}, + {1, "nhlfan.net", 2, true}, + {1, "no-ip.ca", 2, true}, + {1, "no-ip.co.uk", 3, true}, + {1, "no-ip.net", 2, true}, + {1, "noip.us", 2, true}, + {1, "onthewifi.com", 2, true}, + {1, "pgafan.net", 2, true}, + {1, "point2this.com", 2, true}, + {1, "pointto.us", 2, true}, + {1, "privatizehealthinsurance.net", 2, true}, + {1, "quicksytes.com", 2, true}, + {1, "read-books.org", 2, true}, + {1, "securitytactics.com", 2, true}, + {1, "serveexchange.com", 2, true}, + {1, "servehumour.com", 2, true}, + {1, "servep2p.com", 2, true}, + {1, "servesarcasm.com", 2, true}, + {1, "stufftoread.com", 2, true}, + {1, "ufcfan.org", 2, true}, + {1, "unusualperson.com", 2, true}, + {1, "workisboring.com", 2, true}, + {1, "3utilities.com", 2, true}, + {1, "bounceme.net", 2, true}, + {1, "ddns.net", 2, true}, + {1, "ddnsking.com", 2, true}, + {1, "gotdns.ch", 2, true}, + {1, "hopto.org", 2, true}, + {1, "myftp.biz", 2, true}, + {1, "myftp.org", 2, true}, + {1, "myvnc.com", 2, true}, + {1, "no-ip.biz", 2, true}, + {1, "no-ip.info", 2, true}, + {1, "no-ip.org", 2, true}, + {1, "noip.me", 2, true}, + {1, "redirectme.net", 2, true}, + {1, "servebeer.com", 2, true}, + {1, "serveblog.net", 2, true}, + {1, "servecounterstrike.com", 2, true}, + {1, "serveftp.com", 2, true}, + {1, "servegame.com", 2, true}, + {1, "servehalflife.com", 2, true}, + {1, "servehttp.com", 2, true}, + {1, "serveirc.com", 2, true}, + {1, "serveminecraft.net", 2, true}, + {1, "servemp3.com", 2, true}, + {1, "servepics.com", 2, true}, + {1, "servequake.com", 2, true}, + {1, "sytes.net", 2, true}, + {1, "webhop.me", 2, true}, + {1, "zapto.org", 2, true}, + {1, "stage.nodeart.io", 3, true}, + {1, "nodum.co", 2, true}, + {1, "nodum.io", 2, true}, + {1, "pcloud.host", 2, true}, + {1, "nyc.mn", 2, true}, + {1, "nom.ae", 2, true}, + {1, "nom.af", 2, true}, + {1, "nom.ai", 2, true}, + {1, "nom.al", 2, true}, + {1, "nym.by", 2, true}, + {1, "nom.bz", 2, true}, + {1, "nym.bz", 2, true}, + {1, "nom.cl", 2, true}, + {1, "nym.ec", 2, true}, + {1, "nom.gd", 2, true}, + {1, "nom.ge", 2, true}, + {1, "nom.gl", 2, true}, + {1, "nym.gr", 2, true}, + {1, "nom.gt", 2, true}, + {1, "nym.gy", 2, true}, + {1, "nym.hk", 2, true}, + {1, "nom.hn", 2, true}, + {1, "nym.ie", 2, true}, + {1, "nom.im", 2, true}, + {1, "nom.ke", 2, true}, + {1, "nym.kz", 2, true}, + {1, "nym.la", 2, true}, + {1, "nym.lc", 2, true}, + {1, "nom.li", 2, true}, + {1, "nym.li", 2, true}, + {1, "nym.lt", 2, true}, + {1, "nym.lu", 2, true}, + {1, "nom.lv", 2, true}, + {1, "nym.me", 2, true}, + {1, "nom.mk", 2, true}, + {1, "nym.mn", 2, true}, + {1, "nym.mx", 2, true}, + {1, "nom.nu", 2, true}, + {1, "nym.nz", 2, true}, + {1, "nym.pe", 2, true}, + {1, "nym.pt", 2, true}, + {1, "nom.pw", 2, true}, + {1, "nom.qa", 2, true}, + {1, "nym.ro", 2, true}, + {1, "nom.rs", 2, true}, + {1, "nom.si", 2, true}, + {1, "nym.sk", 2, true}, + {1, "nom.st", 2, true}, + {1, "nym.su", 2, true}, + {1, "nym.sx", 2, true}, + {1, "nom.tj", 2, true}, + {1, "nym.tw", 2, true}, + {1, "nom.ug", 2, true}, + {1, "nom.uy", 2, true}, + {1, "nom.vc", 2, true}, + {1, "nom.vg", 2, true}, + {1, "static.observableusercontent.com", 3, true}, + {1, "cya.gg", 2, true}, + {1, "omg.lol", 2, true}, + {1, "cloudycluster.net", 2, true}, + {1, "omniwe.site", 2, true}, + {1, "nid.io", 2, true}, + {1, "opensocial.site", 2, true}, + {1, "opencraft.hosting", 2, true}, + {1, "orsites.com", 2, true}, + {1, "operaunite.com", 2, true}, + {1, "authgear-staging.com", 2, true}, + {1, "authgearapps.com", 2, true}, + {1, "skygearapp.com", 2, true}, + {1, "outsystemscloud.com", 2, true}, + {2, "webpaas.ovh.net", 4, true}, + {2, "hosting.ovh.net", 4, true}, + {1, "ownprovider.com", 2, true}, + {1, "own.pm", 2, true}, + {2, "owo.codes", 3, true}, + {1, "ox.rs", 2, true}, + {1, "oy.lc", 2, true}, + {1, "pgfog.com", 2, true}, + {1, "pagefrontapp.com", 2, true}, + {1, "pagexl.com", 2, true}, + {2, "paywhirl.com", 3, true}, + {1, "bar0.net", 2, true}, + {1, "bar1.net", 2, true}, + {1, "bar2.net", 2, true}, + {1, "rdv.to", 2, true}, + {1, "art.pl", 2, true}, + {1, "gliwice.pl", 2, true}, + {1, "krakow.pl", 2, true}, + {1, "poznan.pl", 2, true}, + {1, "wroc.pl", 2, true}, + {1, "zakopane.pl", 2, true}, + {1, "pantheonsite.io", 2, true}, + {1, "gotpantheon.com", 2, true}, + {1, "mypep.link", 2, true}, + {1, "perspecta.cloud", 2, true}, + {1, "lk3.ru", 2, true}, + {1, "ra-ru.ru", 2, true}, + {1, "zsew.ru", 2, true}, + {1, "on-web.fr", 2, true}, + {1, "bc.platform.sh", 3, true}, + {1, "ent.platform.sh", 3, true}, + {1, "eu.platform.sh", 3, true}, + {1, "us.platform.sh", 3, true}, + {2, "platformsh.site", 3, true}, + {2, "tst.site", 3, true}, + {1, "platter-app.com", 2, true}, + {1, "platter-app.dev", 2, true}, + {1, "platterp.us", 2, true}, + {1, "pdns.page", 2, true}, + {1, "plesk.page", 2, true}, + {1, "pleskns.com", 2, true}, + {1, "dyn53.io", 2, true}, + {1, "co.bn", 2, true}, + {1, "xen.prgmr.com", 3, true}, + {1, "priv.at", 2, true}, + {1, "prvcy.page", 2, true}, + {2, "dweb.link", 3, true}, + {1, "protonet.io", 2, true}, + {1, "chirurgiens-dentistes-en-france.fr", 2, true}, + {1, "byen.site", 2, true}, + {1, "pubtls.org", 2, true}, + {1, "pythonanywhere.com", 2, true}, + {1, "eu.pythonanywhere.com", 3, true}, + {1, "qoto.io", 2, true}, + {1, "qualifioapp.com", 2, true}, + {1, "qbuser.com", 2, true}, + {1, "cloudsite.builders", 2, true}, + {1, "instantcloud.cn", 2, true}, + {1, "ras.ru", 2, true}, + {1, "qa2.com", 2, true}, + {1, "qcx.io", 2, true}, + {2, "sys.qcx.io", 4, true}, + {1, "dev-myqnapcloud.com", 2, true}, + {1, "alpha-myqnapcloud.com", 2, true}, + {1, "myqnapcloud.com", 2, true}, + {2, "quipelements.com", 3, true}, + {1, "vapor.cloud", 2, true}, + {1, "vaporcloud.io", 2, true}, + {1, "rackmaze.com", 2, true}, + {1, "rackmaze.net", 2, true}, + {1, "g.vbrplsbx.io", 3, true}, + {2, "on-k3s.io", 3, true}, + {2, "on-rancher.cloud", 3, true}, + {2, "on-rio.io", 3, true}, + {1, "readthedocs.io", 2, true}, + {1, "rhcloud.com", 2, true}, + {1, "app.render.com", 3, true}, + {1, "onrender.com", 2, true}, + {1, "repl.co", 2, true}, + {1, "id.repl.co", 3, true}, + {1, "repl.run", 2, true}, + {1, "resindevice.io", 2, true}, + {1, "devices.resinstaging.io", 3, true}, + {1, "hzc.io", 2, true}, + {1, "wellbeingzone.eu", 2, true}, + {1, "wellbeingzone.co.uk", 3, true}, + {1, "git-pages.rit.edu", 3, true}, + {1, "xn--90amc.xn--p1acf", 2, true}, + {1, "xn--j1aef.xn--p1acf", 2, true}, + {1, "xn--j1ael8b.xn--p1acf", 2, true}, + {1, "xn--h1ahn.xn--p1acf", 2, true}, + {1, "xn--j1adp.xn--p1acf", 2, true}, + {1, "xn--c1avg.xn--p1acf", 2, true}, + {1, "xn--80aaa0cvac.xn--p1acf", 2, true}, + {1, "xn--h1aliz.xn--p1acf", 2, true}, + {1, "xn--90a1af.xn--p1acf", 2, true}, + {1, "xn--41a.xn--p1acf", 2, true}, + {1, "sandcats.io", 2, true}, + {1, "logoip.de", 2, true}, + {1, "logoip.com", 2, true}, + {1, "schokokeks.net", 2, true}, + {1, "gov.scot", 2, true}, + {1, "service.gov.scot", 3, true}, + {1, "scrysec.com", 2, true}, + {1, "firewall-gateway.com", 2, true}, + {1, "firewall-gateway.de", 2, true}, + {1, "my-gateway.de", 2, true}, + {1, "my-router.de", 2, true}, + {1, "spdns.de", 2, true}, + {1, "spdns.eu", 2, true}, + {1, "firewall-gateway.net", 2, true}, + {1, "my-firewall.org", 2, true}, + {1, "myfirewall.org", 2, true}, + {1, "spdns.org", 2, true}, + {1, "seidat.net", 2, true}, + {1, "senseering.net", 2, true}, + {1, "magnet.page", 2, true}, + {1, "biz.ua", 2, true}, + {1, "co.ua", 2, true}, + {1, "pp.ua", 2, true}, + {1, "shiftcrypto.dev", 2, true}, + {1, "shiftcrypto.io", 2, true}, + {1, "shiftedit.io", 2, true}, + {1, "myshopblocks.com", 2, true}, + {1, "myshopify.com", 2, true}, + {1, "shopitsite.com", 2, true}, + {1, "shopware.store", 2, true}, + {1, "mo-siemens.io", 2, true}, + {1, "1kapp.com", 2, true}, + {1, "appchizi.com", 2, true}, + {1, "applinzi.com", 2, true}, + {1, "sinaapp.com", 2, true}, + {1, "vipsinaapp.com", 2, true}, + {1, "siteleaf.net", 2, true}, + {1, "bounty-full.com", 2, true}, + {1, "alpha.bounty-full.com", 3, true}, + {1, "beta.bounty-full.com", 3, true}, + {1, "small-web.org", 2, true}, + {1, "try-snowplow.com", 2, true}, + {1, "srht.site", 2, true}, + {1, "stackhero-network.com", 2, true}, + {1, "static.land", 2, true}, + {1, "dev.static.land", 3, true}, + {1, "sites.static.land", 3, true}, + {1, "storebase.store", 2, true}, + {1, "vps-host.net", 2, true}, + {1, "atl.jelastic.vps-host.net", 4, true}, + {1, "njs.jelastic.vps-host.net", 4, true}, + {1, "ric.jelastic.vps-host.net", 4, true}, + {1, "playstation-cloud.com", 2, true}, + {1, "apps.lair.io", 3, true}, + {2, "stolos.io", 3, true}, + {1, "spacekit.io", 2, true}, + {1, "customer.speedpartner.de", 3, true}, + {1, "api.stdlib.com", 3, true}, + {1, "storj.farm", 2, true}, + {1, "utwente.io", 2, true}, + {1, "soc.srcf.net", 3, true}, + {1, "user.srcf.net", 3, true}, + {1, "temp-dns.com", 2, true}, + {2, "s5y.io", 3, true}, + {2, "sensiosite.cloud", 3, true}, + {1, "syncloud.it", 2, true}, + {1, "diskstation.me", 2, true}, + {1, "dscloud.biz", 2, true}, + {1, "dscloud.me", 2, true}, + {1, "dscloud.mobi", 2, true}, + {1, "dsmynas.com", 2, true}, + {1, "dsmynas.net", 2, true}, + {1, "dsmynas.org", 2, true}, + {1, "familyds.com", 2, true}, + {1, "familyds.net", 2, true}, + {1, "familyds.org", 2, true}, + {1, "i234.me", 2, true}, + {1, "myds.me", 2, true}, + {1, "synology.me", 2, true}, + {1, "vpnplus.to", 2, true}, + {1, "direct.quickconnect.to", 3, true}, + {1, "taifun-dns.de", 2, true}, + {1, "gda.pl", 2, true}, + {1, "gdansk.pl", 2, true}, + {1, "gdynia.pl", 2, true}, + {1, "med.pl", 2, true}, + {1, "sopot.pl", 2, true}, + {1, "edugit.org", 2, true}, + {1, "telebit.app", 2, true}, + {1, "telebit.io", 2, true}, + {2, "telebit.xyz", 3, true}, + {1, "gwiddle.co.uk", 3, true}, + {1, "thingdustdata.com", 2, true}, + {1, "cust.dev.thingdust.io", 4, true}, + {1, "cust.disrec.thingdust.io", 4, true}, + {1, "cust.prod.thingdust.io", 4, true}, + {1, "cust.testing.thingdust.io", 4, true}, + {2, "firenet.ch", 3, true}, + {2, "svc.firenet.ch", 4, true}, + {1, "arvo.network", 2, true}, + {1, "azimuth.network", 2, true}, + {1, "tlon.network", 2, true}, + {1, "torproject.net", 2, true}, + {1, "pages.torproject.net", 3, true}, + {1, "bloxcms.com", 2, true}, + {1, "townnews-staging.com", 2, true}, + {1, "tbits.me", 2, true}, + {1, "12hp.at", 2, true}, + {1, "2ix.at", 2, true}, + {1, "4lima.at", 2, true}, + {1, "lima-city.at", 2, true}, + {1, "12hp.ch", 2, true}, + {1, "2ix.ch", 2, true}, + {1, "4lima.ch", 2, true}, + {1, "lima-city.ch", 2, true}, + {1, "trafficplex.cloud", 2, true}, + {1, "de.cool", 2, true}, + {1, "12hp.de", 2, true}, + {1, "2ix.de", 2, true}, + {1, "4lima.de", 2, true}, + {1, "lima-city.de", 2, true}, + {1, "1337.pictures", 2, true}, + {1, "clan.rip", 2, true}, + {1, "lima-city.rocks", 2, true}, + {1, "webspace.rocks", 2, true}, + {1, "lima.zone", 2, true}, + {2, "transurl.be", 3, true}, + {2, "transurl.eu", 3, true}, + {2, "transurl.nl", 3, true}, + {1, "tuxfamily.org", 2, true}, + {1, "dd-dns.de", 2, true}, + {1, "diskstation.eu", 2, true}, + {1, "diskstation.org", 2, true}, + {1, "dray-dns.de", 2, true}, + {1, "draydns.de", 2, true}, + {1, "dyn-vpn.de", 2, true}, + {1, "dynvpn.de", 2, true}, + {1, "mein-vigor.de", 2, true}, + {1, "my-vigor.de", 2, true}, + {1, "my-wan.de", 2, true}, + {1, "syno-ds.de", 2, true}, + {1, "synology-diskstation.de", 2, true}, + {1, "synology-ds.de", 2, true}, + {1, "uber.space", 2, true}, + {2, "uberspace.de", 3, true}, + {1, "hk.com", 2, true}, + {1, "hk.org", 2, true}, + {1, "ltd.hk", 2, true}, + {1, "inc.hk", 2, true}, + {1, "virtualuser.de", 2, true}, + {1, "virtual-user.de", 2, true}, + {1, "urown.cloud", 2, true}, + {1, "dnsupdate.info", 2, true}, + {1, "lib.de.us", 3, true}, + {1, "2038.io", 2, true}, + {1, "vercel.app", 2, true}, + {1, "vercel.dev", 2, true}, + {1, "now.sh", 2, true}, + {1, "router.management", 2, true}, + {1, "v-info.info", 2, true}, + {1, "voorloper.cloud", 2, true}, + {1, "neko.am", 2, true}, + {1, "nyaa.am", 2, true}, + {1, "be.ax", 2, true}, + {1, "cat.ax", 2, true}, + {1, "es.ax", 2, true}, + {1, "eu.ax", 2, true}, + {1, "gg.ax", 2, true}, + {1, "mc.ax", 2, true}, + {1, "us.ax", 2, true}, + {1, "xy.ax", 2, true}, + {1, "nl.ci", 2, true}, + {1, "xx.gl", 2, true}, + {1, "app.gp", 2, true}, + {1, "blog.gt", 2, true}, + {1, "de.gt", 2, true}, + {1, "to.gt", 2, true}, + {1, "be.gy", 2, true}, + {1, "cc.hn", 2, true}, + {1, "blog.kg", 2, true}, + {1, "io.kg", 2, true}, + {1, "jp.kg", 2, true}, + {1, "tv.kg", 2, true}, + {1, "uk.kg", 2, true}, + {1, "us.kg", 2, true}, + {1, "de.ls", 2, true}, + {1, "at.md", 2, true}, + {1, "de.md", 2, true}, + {1, "jp.md", 2, true}, + {1, "to.md", 2, true}, + {1, "uwu.nu", 2, true}, + {1, "indie.porn", 2, true}, + {1, "vxl.sh", 2, true}, + {1, "ch.tc", 2, true}, + {1, "me.tc", 2, true}, + {1, "we.tc", 2, true}, + {1, "nyan.to", 2, true}, + {1, "at.vg", 2, true}, + {1, "blog.vu", 2, true}, + {1, "dev.vu", 2, true}, + {1, "me.vu", 2, true}, + {1, "v.ua", 2, true}, + {1, "wafflecell.com", 2, true}, + {1, "idnblogger.com", 2, true}, + {1, "indowapblog.com", 2, true}, + {1, "bloger.id", 2, true}, + {1, "wblog.id", 2, true}, + {1, "wbq.me", 2, true}, + {1, "fastblog.net", 2, true}, + {2, "webhare.dev", 3, true}, + {1, "reserve-online.net", 2, true}, + {1, "reserve-online.com", 2, true}, + {1, "bookonline.app", 2, true}, + {1, "hotelwithflight.com", 2, true}, + {1, "wedeploy.io", 2, true}, + {1, "wedeploy.me", 2, true}, + {1, "wedeploy.sh", 2, true}, + {1, "remotewd.com", 2, true}, + {1, "pages.wiardweb.com", 3, true}, + {1, "wmflabs.org", 2, true}, + {1, "toolforge.org", 2, true}, + {1, "wmcloud.org", 2, true}, + {1, "panel.gg", 2, true}, + {1, "daemon.panel.gg", 3, true}, + {1, "woltlab-demo.com", 2, true}, + {1, "myforum.community", 2, true}, + {1, "community-pro.de", 2, true}, + {1, "diskussionsbereich.de", 2, true}, + {1, "community-pro.net", 2, true}, + {1, "meinforum.net", 2, true}, + {1, "wpenginepowered.com", 2, true}, + {1, "js.wpenginepowered.com", 3, true}, + {1, "wixsite.com", 2, true}, + {1, "editorx.io", 2, true}, + {1, "half.host", 2, true}, + {1, "xnbay.com", 2, true}, + {1, "u2.xnbay.com", 3, true}, + {1, "u2-local.xnbay.com", 3, true}, + {1, "cistron.nl", 2, true}, + {1, "demon.nl", 2, true}, + {1, "xs4all.space", 2, true}, + {1, "yandexcloud.net", 2, true}, + {1, "storage.yandexcloud.net", 3, true}, + {1, "website.yandexcloud.net", 3, true}, + {1, "official.academy", 2, true}, + {1, "yolasite.com", 2, true}, + {1, "ybo.faith", 2, true}, + {1, "yombo.me", 2, true}, + {1, "homelink.one", 2, true}, + {1, "ybo.party", 2, true}, + {1, "ybo.review", 2, true}, + {1, "ybo.science", 2, true}, + {1, "ybo.trade", 2, true}, + {1, "nohost.me", 2, true}, + {1, "noho.st", 2, true}, + {1, "za.net", 2, true}, + {1, "za.org", 2, true}, + {1, "bss.design", 2, true}, + {1, "basicserver.io", 2, true}, + {1, "virtualserver.io", 2, true}, + {1, "enterprisecloud.nu", 2, true}, +} + +func init() { + for i := range r { + DefaultList.AddRule(&r[i]) + } +} diff --git a/vendor/github.com/zmap/zcrypto/LICENSE b/vendor/github.com/zmap/zcrypto/LICENSE new file mode 100644 index 0000000000..830522ba23 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/LICENSE @@ -0,0 +1,257 @@ +ZCrypto is an original work created at the University of Michigan, and is +licensed under the Apache 2.0 license. However, ZCrypto contains a fork of +several packages from Golang standard library, as well as code from the +BoringSSL test runner. Files that were created by Google, and new files in +forks of packages maintained by Google have a Google copyright and fall under +the ISC license. In addition ZCrypto includes a `util/isURL.go` file created by +Alex Saskevich and licensed under the MIT license. All other files are copyright +Regents of the University of Michigan, and fall under the Apache 2.0 license. +All three licenses are reproduced at the bottom of this file. + +-------- + +ISC License used for Google code + +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +-------- + +MIT License used for util/isURL.go adopted from https://github.com/asaskevich/govalidator + + The MIT License (MIT) + + Copyright (c) 2014 Alex Saskevich + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +-------- + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + ZCrypto Copyright 2015 Regents of the University of Michigan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/zmap/zcrypto/dsa/dsa.go b/vendor/github.com/zmap/zcrypto/dsa/dsa.go new file mode 100644 index 0000000000..16bd1f5f55 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/dsa/dsa.go @@ -0,0 +1,309 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3. +// +// The DSA operations in this package are not implemented using constant-time algorithms. +// +// Warning: DSA is a legacy algorithm, and modern alternatives such as +// Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys +// with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while +// bigger keys are not widely supported. Note that FIPS 186-5 no longer approves +// DSA for signature generation. +package dsa + +import ( + "errors" + "io" + "math/big" + + "github.com/zmap/zcrypto/internal/randutil" +) + +// Parameters represents the domain parameters for a key. These parameters can +// be shared across many keys. The bit length of Q must be a multiple of 8. +type Parameters struct { + P, Q, G *big.Int +} + +// PublicKey represents a DSA public key. +type PublicKey struct { + Parameters + Y *big.Int +} + +// PrivateKey represents a DSA private key. +type PrivateKey struct { + PublicKey + X *big.Int +} + +// ErrInvalidPublicKey results when a public key is not usable by this code. +// FIPS is quite strict about the format of DSA keys, but other code may be +// less so. Thus, when using keys which may have been generated by other code, +// this error must be handled. +var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key") + +// ParameterSizes is an enumeration of the acceptable bit lengths of the primes +// in a set of DSA parameters. See FIPS 186-3, section 4.2. +type ParameterSizes int + +const ( + L1024N160 ParameterSizes = iota + L2048N224 + L2048N256 + L3072N256 +) + +// numMRTests is the number of Miller-Rabin primality tests that we perform. We +// pick the largest recommended number from table C.1 of FIPS 186-3. +const numMRTests = 64 + +// GenerateParameters puts a random, valid set of DSA parameters into params. +// This function can take many seconds, even on fast machines. +func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error { + // This function doesn't follow FIPS 186-3 exactly in that it doesn't + // use a verification seed to generate the primes. The verification + // seed doesn't appear to be exported or used by other code and + // omitting it makes the code cleaner. + + var L, N int + switch sizes { + case L1024N160: + L = 1024 + N = 160 + case L2048N224: + L = 2048 + N = 224 + case L2048N256: + L = 2048 + N = 256 + case L3072N256: + L = 3072 + N = 256 + default: + return errors.New("crypto/dsa: invalid ParameterSizes") + } + + qBytes := make([]byte, N/8) + pBytes := make([]byte, L/8) + + q := new(big.Int) + p := new(big.Int) + rem := new(big.Int) + one := new(big.Int) + one.SetInt64(1) + +GeneratePrimes: + for { + if _, err := io.ReadFull(rand, qBytes); err != nil { + return err + } + + qBytes[len(qBytes)-1] |= 1 + qBytes[0] |= 0x80 + q.SetBytes(qBytes) + + if !q.ProbablyPrime(numMRTests) { + continue + } + + for i := 0; i < 4*L; i++ { + if _, err := io.ReadFull(rand, pBytes); err != nil { + return err + } + + pBytes[len(pBytes)-1] |= 1 + pBytes[0] |= 0x80 + + p.SetBytes(pBytes) + rem.Mod(p, q) + rem.Sub(rem, one) + p.Sub(p, rem) + if p.BitLen() < L { + continue + } + + if !p.ProbablyPrime(numMRTests) { + continue + } + + params.P = p + params.Q = q + break GeneratePrimes + } + } + + h := new(big.Int) + h.SetInt64(2) + g := new(big.Int) + + pm1 := new(big.Int).Sub(p, one) + e := new(big.Int).Div(pm1, q) + + for { + g.Exp(h, e, p) + if g.Cmp(one) == 0 { + h.Add(h, one) + continue + } + + params.G = g + return nil + } +} + +// GenerateKey generates a public&private key pair. The Parameters of the +// PrivateKey must already be valid (see GenerateParameters). +func GenerateKey(priv *PrivateKey, rand io.Reader) error { + if priv.P == nil || priv.Q == nil || priv.G == nil { + return errors.New("crypto/dsa: parameters not set up before generating key") + } + + x := new(big.Int) + xBytes := make([]byte, priv.Q.BitLen()/8) + + for { + _, err := io.ReadFull(rand, xBytes) + if err != nil { + return err + } + x.SetBytes(xBytes) + if x.Sign() != 0 && x.Cmp(priv.Q) < 0 { + break + } + } + + priv.X = x + priv.Y = new(big.Int) + priv.Y.Exp(priv.G, x, priv.P) + return nil +} + +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. +// This has better constant-time properties than Euclid's method (implemented +// in math/big.Int.ModInverse) although math/big itself isn't strictly +// constant-time so it's not perfect. +func fermatInverse(k, P *big.Int) *big.Int { + two := big.NewInt(2) + pMinus2 := new(big.Int).Sub(P, two) + return new(big.Int).Exp(k, pMinus2, P) +} + +// Sign signs an arbitrary length hash (which should be the result of hashing a +// larger message) using the private key, priv. It returns the signature as a +// pair of integers. The security of the private key depends on the entropy of +// rand. +// +// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated +// to the byte-length of the subgroup. This function does not perform that +// truncation itself. +// +// Be aware that calling Sign with an attacker-controlled PrivateKey may +// require an arbitrary amount of CPU. +func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { + randutil.MaybeReadByte(rand) + + // FIPS 186-3, section 4.6 + + n := priv.Q.BitLen() + if priv.Q.Sign() <= 0 || priv.P.Sign() <= 0 || priv.G.Sign() <= 0 || priv.X.Sign() <= 0 || n%8 != 0 { + err = ErrInvalidPublicKey + return + } + n >>= 3 + + var attempts int + for attempts = 10; attempts > 0; attempts-- { + k := new(big.Int) + buf := make([]byte, n) + for { + _, err = io.ReadFull(rand, buf) + if err != nil { + return + } + k.SetBytes(buf) + // priv.Q must be >= 128 because the test above + // requires it to be > 0 and that + // ceil(log_2(Q)) mod 8 = 0 + // Thus this loop will quickly terminate. + if k.Sign() > 0 && k.Cmp(priv.Q) < 0 { + break + } + } + + kInv := fermatInverse(k, priv.Q) + + r = new(big.Int).Exp(priv.G, k, priv.P) + r.Mod(r, priv.Q) + + if r.Sign() == 0 { + continue + } + + z := k.SetBytes(hash) + + s = new(big.Int).Mul(priv.X, r) + s.Add(s, z) + s.Mod(s, priv.Q) + s.Mul(s, kInv) + s.Mod(s, priv.Q) + + if s.Sign() != 0 { + break + } + } + + // Only degenerate private keys will require more than a handful of + // attempts. + if attempts == 0 { + return nil, nil, ErrInvalidPublicKey + } + + return +} + +// Verify verifies the signature in r, s of hash using the public key, pub. It +// reports whether the signature is valid. +// +// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated +// to the byte-length of the subgroup. This function does not perform that +// truncation itself. +func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { + // FIPS 186-3, section 4.7 + + if pub.P.Sign() == 0 { + return false + } + + if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 { + return false + } + if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 { + return false + } + + w := new(big.Int).ModInverse(s, pub.Q) + if w == nil { + return false + } + + n := pub.Q.BitLen() + if n%8 != 0 { + return false + } + z := new(big.Int).SetBytes(hash) + + u1 := new(big.Int).Mul(z, w) + u1.Mod(u1, pub.Q) + u2 := w.Mul(r, w) + u2.Mod(u2, pub.Q) + v := u1.Exp(pub.G, u1, pub.P) + u2.Exp(pub.Y, u2, pub.P) + v.Mul(v, u2) + v.Mod(v, pub.P) + v.Mod(v, pub.Q) + + return v.Cmp(r) == 0 +} diff --git a/vendor/github.com/zmap/zcrypto/internal/randutil/randutil.go b/vendor/github.com/zmap/zcrypto/internal/randutil/randutil.go new file mode 100644 index 0000000000..84b1295a87 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/internal/randutil/randutil.go @@ -0,0 +1,38 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package randutil contains internal randomness utilities for various +// crypto packages. +package randutil + +import ( + "io" + "sync" +) + +var ( + closedChanOnce sync.Once + closedChan chan struct{} +) + +// MaybeReadByte reads a single byte from r with ~50% probability. This is used +// to ensure that callers do not depend on non-guaranteed behaviour, e.g. +// assuming that rsa.GenerateKey is deterministic w.r.t. a given random stream. +// +// This does not affect tests that pass a stream of fixed bytes as the random +// source (e.g. a zeroReader). +func MaybeReadByte(r io.Reader) { + closedChanOnce.Do(func() { + closedChan = make(chan struct{}) + close(closedChan) + }) + + select { + case <-closedChan: + return + case <-closedChan: + var buf [1]byte + r.Read(buf[:]) + } +} diff --git a/vendor/github.com/zmap/zcrypto/json/dhe.go b/vendor/github.com/zmap/zcrypto/json/dhe.go new file mode 100644 index 0000000000..0d4770bca3 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/json/dhe.go @@ -0,0 +1,130 @@ +/* + * ZGrab Copyright 2015 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package json + +import ( + "encoding/json" + "math/big" +) + +// DHParams can be used to store finite-field Diffie-Hellman parameters. At any +// point in time, it is unlikely that both OurPrivate and TheirPrivate will be +// non-nil. +type DHParams struct { + Prime *big.Int + Generator *big.Int + ServerPublic *big.Int + ServerPrivate *big.Int + ClientPublic *big.Int + ClientPrivate *big.Int + SessionKey *big.Int +} + +type auxDHParams struct { + Prime *cryptoParameter `json:"prime"` + Generator *cryptoParameter `json:"generator"` + ServerPublic *cryptoParameter `json:"server_public,omitempty"` + ServerPrivate *cryptoParameter `json:"server_private,omitempty"` + ClientPublic *cryptoParameter `json:"client_public,omitempty"` + ClientPrivate *cryptoParameter `json:"client_private,omitempty"` + SessionKey *cryptoParameter `json:"session_key,omitempty"` +} + +// MarshalJSON implements the json.Marshal interface +func (p *DHParams) MarshalJSON() ([]byte, error) { + aux := auxDHParams{ + Prime: &cryptoParameter{Int: p.Prime}, + Generator: &cryptoParameter{Int: p.Generator}, + } + if p.ServerPublic != nil { + aux.ServerPublic = &cryptoParameter{Int: p.ServerPublic} + } + if p.ServerPrivate != nil { + aux.ServerPrivate = &cryptoParameter{Int: p.ServerPrivate} + } + if p.ClientPublic != nil { + aux.ClientPublic = &cryptoParameter{Int: p.ClientPublic} + } + if p.ClientPrivate != nil { + aux.ClientPrivate = &cryptoParameter{Int: p.ClientPrivate} + } + if p.SessionKey != nil { + aux.SessionKey = &cryptoParameter{Int: p.SessionKey} + } + return json.Marshal(aux) +} + +// UnmarshalJSON implement the json.Unmarshaler interface +func (p *DHParams) UnmarshalJSON(b []byte) error { + var aux auxDHParams + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + if aux.Prime != nil { + p.Prime = aux.Prime.Int + } + if aux.Generator != nil { + p.Generator = aux.Generator.Int + } + if aux.ServerPublic != nil { + p.ServerPublic = aux.ServerPublic.Int + } + if aux.ServerPrivate != nil { + p.ServerPrivate = aux.ServerPrivate.Int + } + if aux.ClientPublic != nil { + p.ClientPublic = aux.ClientPublic.Int + } + if aux.ClientPrivate != nil { + p.ClientPrivate = aux.ClientPrivate.Int + } + if aux.SessionKey != nil { + p.SessionKey = aux.SessionKey.Int + } + return nil +} + +// CryptoParameter represents a big.Int used a parameter in some cryptography. +// It serializes to json as a tupe of a base64-encoded number and a length in +// bits. +type cryptoParameter struct { + *big.Int +} + +type auxCryptoParameter struct { + Raw []byte `json:"value"` + Length int `json:"length"` +} + +// MarshalJSON implements the json.Marshaler interface +func (p *cryptoParameter) MarshalJSON() ([]byte, error) { + var aux auxCryptoParameter + if p.Int != nil { + aux.Raw = p.Bytes() + aux.Length = 8 * len(aux.Raw) + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshal interface +func (p *cryptoParameter) UnmarshalJSON(b []byte) error { + var aux auxCryptoParameter + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + p.Int = new(big.Int) + p.SetBytes(aux.Raw) + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/json/ecdhe.go b/vendor/github.com/zmap/zcrypto/json/ecdhe.go new file mode 100644 index 0000000000..5d3d19179c --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/json/ecdhe.go @@ -0,0 +1,107 @@ +/* + * ZGrab Copyright 2015 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package json + +import ( + "crypto/elliptic" + "encoding/json" + "math/big" +) + +// TLSCurveID is the type of a TLS identifier for an elliptic curve. See +// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 +type TLSCurveID uint16 + +// ECDHPrivateParams are the TLS key exchange parameters for ECDH keys. +type ECDHPrivateParams struct { + Value []byte `json:"value,omitempty"` + Length int `json:"length,omitempty"` +} + +// ECDHParams stores elliptic-curve Diffie-Hellman paramters.At any point in +// time, it is unlikely that both ServerPrivate and ClientPrivate will be non-nil. +type ECDHParams struct { + TLSCurveID TLSCurveID `json:"curve_id,omitempty"` + Curve elliptic.Curve `json:"-"` + ServerPublic *ECPoint `json:"server_public,omitempty"` + ServerPrivate *ECDHPrivateParams `json:"server_private,omitempty"` + ClientPublic *ECPoint `json:"client_public,omitempty"` + ClientPrivate *ECDHPrivateParams `json:"client_private,omitempty"` +} + +// ECPoint represents an elliptic curve point and serializes nicely to JSON +type ECPoint struct { + X *big.Int + Y *big.Int +} + +// MarshalJSON implements the json.Marshler interface +func (p *ECPoint) MarshalJSON() ([]byte, error) { + aux := struct { + X *cryptoParameter `json:"x"` + Y *cryptoParameter `json:"y"` + }{ + X: &cryptoParameter{Int: p.X}, + Y: &cryptoParameter{Int: p.Y}, + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshler interface +func (p *ECPoint) UnmarshalJSON(b []byte) error { + aux := struct { + X *cryptoParameter `json:"x"` + Y *cryptoParameter `json:"y"` + }{} + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + p.X = aux.X.Int + p.Y = aux.Y.Int + return nil +} + +// Description returns the description field for the given ID. See +// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 +func (c *TLSCurveID) Description() string { + if desc, ok := ecIDToName[*c]; ok { + return desc + } + return "unknown" +} + +// MarshalJSON implements the json.Marshaler interface +func (c *TLSCurveID) MarshalJSON() ([]byte, error) { + aux := struct { + Name string `json:"name"` + ID uint16 `json:"id"` + }{ + Name: c.Description(), + ID: uint16(*c), + } + return json.Marshal(&aux) +} + +//UnmarshalJSON implements the json.Unmarshaler interface +func (c *TLSCurveID) UnmarshalJSON(b []byte) error { + aux := struct { + ID uint16 `json:"id"` + }{} + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + *c = TLSCurveID(aux.ID) + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/json/names.go b/vendor/github.com/zmap/zcrypto/json/names.go new file mode 100644 index 0000000000..3882824867 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/json/names.go @@ -0,0 +1,113 @@ +/* + * ZGrab Copyright 2015 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package json + +// IANA-assigned curve ID values, see +// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 +const ( + Sect163k1 TLSCurveID = 1 + Sect163r1 TLSCurveID = 2 + Sect163r2 TLSCurveID = 3 + Sect193r1 TLSCurveID = 4 + Sect193r2 TLSCurveID = 5 + Sect233k1 TLSCurveID = 6 + Sect233r1 TLSCurveID = 7 + Sect239k1 TLSCurveID = 8 + Sect283k1 TLSCurveID = 9 + Sect283r1 TLSCurveID = 10 + Sect409k1 TLSCurveID = 11 + Sect409r1 TLSCurveID = 12 + Sect571k1 TLSCurveID = 13 + Sect571r1 TLSCurveID = 14 + Secp160k1 TLSCurveID = 15 + Secp160r1 TLSCurveID = 16 + Secp160r2 TLSCurveID = 17 + Secp192k1 TLSCurveID = 18 + Secp192r1 TLSCurveID = 19 + Secp224k1 TLSCurveID = 20 + Secp224r1 TLSCurveID = 21 + Secp256k1 TLSCurveID = 22 + Secp256r1 TLSCurveID = 23 + Secp384r1 TLSCurveID = 24 + Secp521r1 TLSCurveID = 25 + BrainpoolP256r1 TLSCurveID = 26 + BrainpoolP384r1 TLSCurveID = 27 + BrainpoolP512r1 TLSCurveID = 28 +) + +var ecIDToName map[TLSCurveID]string +var ecNameToID map[string]TLSCurveID + +func init() { + ecIDToName = make(map[TLSCurveID]string, 64) + ecIDToName[Sect163k1] = "sect163k1" + ecIDToName[Sect163r1] = "sect163r1" + ecIDToName[Sect163r2] = "sect163r2" + ecIDToName[Sect193r1] = "sect193r1" + ecIDToName[Sect193r2] = "sect193r2" + ecIDToName[Sect233k1] = "sect233k1" + ecIDToName[Sect233r1] = "sect233r1" + ecIDToName[Sect239k1] = "sect239k1" + ecIDToName[Sect283k1] = "sect283k1" + ecIDToName[Sect283r1] = "sect283r1" + ecIDToName[Sect409k1] = "sect409k1" + ecIDToName[Sect409r1] = "sect409r1" + ecIDToName[Sect571k1] = "sect571k1" + ecIDToName[Sect571r1] = "sect571r1" + ecIDToName[Secp160k1] = "secp160k1" + ecIDToName[Secp160r1] = "secp160r1" + ecIDToName[Secp160r2] = "secp160r2" + ecIDToName[Secp192k1] = "secp192k1" + ecIDToName[Secp192r1] = "secp192r1" + ecIDToName[Secp224k1] = "secp224k1" + ecIDToName[Secp224r1] = "secp224r1" + ecIDToName[Secp256k1] = "secp256k1" + ecIDToName[Secp256r1] = "secp256r1" + ecIDToName[Secp384r1] = "secp384r1" + ecIDToName[Secp521r1] = "secp521r1" + ecIDToName[BrainpoolP256r1] = "brainpoolp256r1" + ecIDToName[BrainpoolP384r1] = "brainpoolp384r1" + ecIDToName[BrainpoolP512r1] = "brainpoolp512r1" + + ecNameToID = make(map[string]TLSCurveID, 64) + ecNameToID["sect163k1"] = Sect163k1 + ecNameToID["sect163r1"] = Sect163r1 + ecNameToID["sect163r2"] = Sect163r2 + ecNameToID["sect193r1"] = Sect193r1 + ecNameToID["sect193r2"] = Sect193r2 + ecNameToID["sect233k1"] = Sect233k1 + ecNameToID["sect233r1"] = Sect233r1 + ecNameToID["sect239k1"] = Sect239k1 + ecNameToID["sect283k1"] = Sect283k1 + ecNameToID["sect283r1"] = Sect283r1 + ecNameToID["sect409k1"] = Sect409k1 + ecNameToID["sect409r1"] = Sect409r1 + ecNameToID["sect571k1"] = Sect571k1 + ecNameToID["sect571r1"] = Sect571r1 + ecNameToID["secp160k1"] = Secp160k1 + ecNameToID["secp160r1"] = Secp160r1 + ecNameToID["secp160r2"] = Secp160r2 + ecNameToID["secp192k1"] = Secp192k1 + ecNameToID["secp192r1"] = Secp192r1 + ecNameToID["secp224k1"] = Secp224k1 + ecNameToID["secp224r1"] = Secp224r1 + ecNameToID["secp256k1"] = Secp256k1 + ecNameToID["secp256r1"] = Secp256r1 + ecNameToID["secp384r1"] = Secp384r1 + ecNameToID["secp521r1"] = Secp521r1 + ecNameToID["brainpoolp256r1"] = BrainpoolP256r1 + ecNameToID["brainpoolp384r1"] = BrainpoolP384r1 + ecNameToID["brainpoolp512r1"] = BrainpoolP512r1 +} diff --git a/vendor/github.com/zmap/zcrypto/json/rsa.go b/vendor/github.com/zmap/zcrypto/json/rsa.go new file mode 100644 index 0000000000..270256973b --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/json/rsa.go @@ -0,0 +1,67 @@ +/* + * ZGrab Copyright 2015 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package json + +import ( + "crypto/rsa" + "encoding/json" + "fmt" + "math/big" +) + +// RSAPublicKey provides JSON methods for the standard rsa.PublicKey. +type RSAPublicKey struct { + *rsa.PublicKey +} + +type auxRSAPublicKey struct { + Exponent int `json:"exponent"` + Modulus []byte `json:"modulus"` + Length int `json:"length"` +} + +// RSAClientParams are the TLS key exchange parameters for RSA keys. +type RSAClientParams struct { + Length uint16 `json:"length,omitempty"` + EncryptedPMS []byte `json:"encrypted_pre_master_secret,omitempty"` +} + +// MarshalJSON implements the json.Marshal interface +func (rp *RSAPublicKey) MarshalJSON() ([]byte, error) { + var aux auxRSAPublicKey + if rp.PublicKey != nil { + aux.Exponent = rp.E + aux.Modulus = rp.N.Bytes() + aux.Length = len(aux.Modulus) * 8 + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshal interface +func (rp *RSAPublicKey) UnmarshalJSON(b []byte) error { + var aux auxRSAPublicKey + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + if rp.PublicKey == nil { + rp.PublicKey = new(rsa.PublicKey) + } + rp.E = aux.Exponent + rp.N = big.NewInt(0).SetBytes(aux.Modulus) + if len(aux.Modulus)*8 != aux.Length { + return fmt.Errorf("mismatched length (got %d, field specified %d)", len(aux.Modulus), aux.Length) + } + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/util/isURL.go b/vendor/github.com/zmap/zcrypto/util/isURL.go new file mode 100644 index 0000000000..6a09a471a0 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/util/isURL.go @@ -0,0 +1,77 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Alex Saskevich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +package util + +import ( + "net/url" + "regexp" + "strings" + "unicode/utf8" +) + +const ( + maxURLRuneCount = 2083 + minURLRuneCount = 3 + + IP = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))` + URLSchema = `((ftp|tcp|udp|wss?|https?):\/\/)` + URLUsername = `(\S+(:\S*)?@)` + URLPath = `((\/|\?|#)[^\s]*)` + URLPort = `(:(\d{1,5}))` + URLIP = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))` + URLSubdomain = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))` +) + +var ( + URL = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$` + rxURL = regexp.MustCompile(URL) +) + +// IsURL check if the string is an URL. +// This function is (graciously) adopted from +// https://github.com/asaskevich/govalidator to avoid needing a full dependency on +// `govalidator` for the one `IsURL` function. +func IsURL(str string) bool { + if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") { + return false + } + strTemp := str + if strings.Contains(str, ":") && !strings.Contains(str, "://") { + // support no indicated urlscheme but with colon for port number + // http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString + strTemp = "http://" + str + } + u, err := url.Parse(strTemp) + if err != nil { + return false + } + if strings.HasPrefix(u.Host, ".") { + return false + } + if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) { + return false + } + return rxURL.MatchString(str) +} diff --git a/vendor/github.com/zmap/zcrypto/x509/README.md b/vendor/github.com/zmap/zcrypto/x509/README.md new file mode 100644 index 0000000000..e2a2883508 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/README.md @@ -0,0 +1,8 @@ +Originally based on the go/crypto/x509 standard library, +this package has now diverged enough that it is no longer +updated with direct correspondence to new go releases. + +Approximately supports all the features of +github.com/golang/go/crypto/x509 package at: +branch: release-branch.go1.10 +revision: dea961ebd9f871b39b3bdaab32f952037f28cd71 diff --git a/vendor/github.com/zmap/zcrypto/x509/cert_pool.go b/vendor/github.com/zmap/zcrypto/x509/cert_pool.go new file mode 100644 index 0000000000..a6c6d2b036 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/cert_pool.go @@ -0,0 +1,171 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "encoding/pem" +) + +// CertPool is a set of certificates. +type CertPool struct { + bySubjectKeyId map[string][]int + byName map[string][]int + bySHA256 map[string]int + certs []*Certificate +} + +// NewCertPool returns a new, empty CertPool. +func NewCertPool() *CertPool { + return &CertPool{ + bySubjectKeyId: make(map[string][]int), + byName: make(map[string][]int), + bySHA256: make(map[string]int), + } +} + +// findVerifiedParents attempts to find certificates in s which have signed the +// given certificate. If any candidates were rejected then errCert will be set +// to one of them, arbitrarily, and err will contain the reason that it was +// rejected. +func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) { + if s == nil { + return + } + var candidates []int + + if len(cert.AuthorityKeyId) > 0 { + candidates, _ = s.bySubjectKeyId[string(cert.AuthorityKeyId)] + } + if len(candidates) == 0 { + candidates, _ = s.byName[string(cert.RawIssuer)] + } + + for _, c := range candidates { + if err = cert.CheckSignatureFrom(s.certs[c]); err == nil { + cert.validSignature = true + parents = append(parents, c) + } else { + errCert = s.certs[c] + } + } + + return +} + +// Contains returns true if c is in s. +func (s *CertPool) Contains(c *Certificate) bool { + if s == nil { + return false + } + _, ok := s.bySHA256[string(c.FingerprintSHA256)] + return ok +} + +// Covers returns true if all certs in pool are in s. +func (s *CertPool) Covers(pool *CertPool) bool { + if pool == nil { + return true + } + for _, c := range pool.certs { + if !s.Contains(c) { + return false + } + } + return true +} + +// Certificates returns a list of parsed certificates in the pool. +func (s *CertPool) Certificates() []*Certificate { + out := make([]*Certificate, 0, len(s.certs)) + out = append(out, s.certs...) + return out +} + +// Size returns the number of unique certificates in the CertPool. +func (s *CertPool) Size() int { + if s == nil { + return 0 + } + return len(s.certs) +} + +// Sum returns the union of two certificate pools as a new certificate pool. +func (s *CertPool) Sum(other *CertPool) (sum *CertPool) { + sum = NewCertPool() + if s != nil { + for _, c := range s.certs { + sum.AddCert(c) + } + } + if other != nil { + for _, c := range other.certs { + sum.AddCert(c) + } + } + return +} + +// AddCert adds a certificate to a pool. +func (s *CertPool) AddCert(cert *Certificate) { + if cert == nil { + panic("adding nil Certificate to CertPool") + } + + // Check that the certificate isn't being added twice. + sha256fp := string(cert.FingerprintSHA256) + if _, ok := s.bySHA256[sha256fp]; ok { + return + } + + n := len(s.certs) + s.certs = append(s.certs, cert) + + if len(cert.SubjectKeyId) > 0 { + keyId := string(cert.SubjectKeyId) + s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n) + } + name := string(cert.RawSubject) + s.byName[name] = append(s.byName[name], n) + s.bySHA256[sha256fp] = n +} + +// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. +// It appends any certificates found to s and reports whether any certificates +// were successfully parsed. +// +// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set +// of root CAs in a format suitable for this function. +func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { + for len(pemCerts) > 0 { + var block *pem.Block + block, pemCerts = pem.Decode(pemCerts) + if block == nil { + break + } + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + + cert, err := ParseCertificate(block.Bytes) + if err != nil { + continue + } + + s.AddCert(cert) + ok = true + } + + return +} + +// Subjects returns a list of the DER-encoded subjects of +// all of the certificates in the pool. +func (s *CertPool) Subjects() [][]byte { + res := make([][]byte, len(s.certs)) + for i, c := range s.certs { + res[i] = c.RawSubject + } + return res +} diff --git a/vendor/github.com/zmap/zcrypto/x509/certificate_type.go b/vendor/github.com/zmap/zcrypto/x509/certificate_type.go new file mode 100644 index 0000000000..7bb7f32476 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/certificate_type.go @@ -0,0 +1,64 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import "encoding/json" + +// TODO: Automatically generate this file from a CSV + +// CertificateType represents whether a certificate is a root, intermediate, or +// leaf. +type CertificateType int + +// CertificateType constants. Values should not be considered significant aside +// from CertificateTypeUnknown is the zero value. +const ( + CertificateTypeUnknown CertificateType = 0 + CertificateTypeLeaf CertificateType = 1 + CertificateTypeIntermediate CertificateType = 2 + CertificateTypeRoot CertificateType = 3 +) + +const ( + certificateTypeStringLeaf = "leaf" + certificateTypeStringIntermediate = "intermediate" + certificateTypeStringRoot = "root" + certificateTypeStringUnknown = "unknown" +) + +// MarshalJSON implements the json.Marshaler interface. Any unknown integer +// value is considered the same as CertificateTypeUnknown. +func (t CertificateType) MarshalJSON() ([]byte, error) { + switch t { + case CertificateTypeLeaf: + return json.Marshal(certificateTypeStringLeaf) + case CertificateTypeIntermediate: + return json.Marshal(certificateTypeStringIntermediate) + case CertificateTypeRoot: + return json.Marshal(certificateTypeStringRoot) + default: + return json.Marshal(certificateTypeStringUnknown) + } +} + +// UnmarshalJSON implements the json.Unmarshaler interface. Any unknown string +// is considered the same CertificateTypeUnknown. +func (t *CertificateType) UnmarshalJSON(b []byte) error { + var certificateTypeString string + if err := json.Unmarshal(b, &certificateTypeString); err != nil { + return err + } + switch certificateTypeString { + case certificateTypeStringLeaf: + *t = CertificateTypeLeaf + case certificateTypeStringIntermediate: + *t = CertificateTypeIntermediate + case certificateTypeStringRoot: + *t = CertificateTypeRoot + default: + *t = CertificateTypeUnknown + } + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/chain.go b/vendor/github.com/zmap/zcrypto/x509/chain.go new file mode 100644 index 0000000000..bca0f278ce --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/chain.go @@ -0,0 +1,70 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "strings" +) + +// CertificateChain is a slice of certificates. The 0'th element is the leaf, +// and the last element is a root. Successive elements have a child-parent +// relationship. +type CertificateChain []*Certificate + +// Range runs a function on each element of chain. It can modify each +// certificate in place. +func (chain CertificateChain) Range(f func(int, *Certificate)) { + for i, c := range chain { + f(i, c) + } +} + +// SubjectAndKeyInChain returns true if the given SubjectAndKey is found in any +// certificate in the chain. +func (chain CertificateChain) SubjectAndKeyInChain(sk *SubjectAndKey) bool { + for _, cert := range chain { + if bytes.Equal(sk.RawSubject, cert.RawSubject) && bytes.Equal(sk.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) { + return true + } + } + return false +} + +// CertificateSubjectAndKeyInChain returns true if the SubjectAndKey from c is +// found in any certificate in the chain. +func (chain CertificateChain) CertificateSubjectAndKeyInChain(c *Certificate) bool { + for _, cert := range chain { + if bytes.Equal(c.RawSubject, cert.RawSubject) && bytes.Equal(c.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) { + return true + } + } + return false +} + +// CertificateInChain returns true if c is in the chain. +func (chain CertificateChain) CertificateInChain(c *Certificate) bool { + for _, cert := range chain { + if bytes.Equal(c.Raw, cert.Raw) { + return true + } + } + return false +} + +func (chain CertificateChain) AppendToFreshChain(c *Certificate) CertificateChain { + n := make([]*Certificate, len(chain)+1) + copy(n, chain) + n[len(chain)] = c + return n +} + +func (chain CertificateChain) chainID() string { + var parts []string + for _, c := range chain { + parts = append(parts, string(c.FingerprintSHA256)) + } + return strings.Join(parts, "") +} diff --git a/vendor/github.com/zmap/zcrypto/x509/ct/serialization.go b/vendor/github.com/zmap/zcrypto/x509/ct/serialization.go new file mode 100644 index 0000000000..aac17dc2c7 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/ct/serialization.go @@ -0,0 +1,168 @@ +package ct + +// This file contains selectively chosen snippets of +// github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80 +// +// These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct +// which contains yet another version of x509,asn1 and tls + +import ( + "encoding/binary" + "errors" + "fmt" + "io" +) + +// Variable size structure prefix-header byte lengths +const ( + CertificateLengthBytes = 3 + PreCertificateLengthBytes = 3 + ExtensionsLengthBytes = 2 + CertificateChainLengthBytes = 3 + SignatureLengthBytes = 2 +) + +func writeUint(w io.Writer, value uint64, numBytes int) error { + buf := make([]uint8, numBytes) + for i := 0; i < numBytes; i++ { + buf[numBytes-i-1] = uint8(value & 0xff) + value >>= 8 + } + if value != 0 { + return errors.New("numBytes was insufficiently large to represent value") + } + if _, err := w.Write(buf); err != nil { + return err + } + return nil +} + +func writeVarBytes(w io.Writer, value []byte, numLenBytes int) error { + if err := writeUint(w, uint64(len(value)), numLenBytes); err != nil { + return err + } + if _, err := w.Write(value); err != nil { + return err + } + return nil +} + +func readUint(r io.Reader, numBytes int) (uint64, error) { + var l uint64 + for i := 0; i < numBytes; i++ { + l <<= 8 + var t uint8 + if err := binary.Read(r, binary.BigEndian, &t); err != nil { + return 0, err + } + l |= uint64(t) + } + return l, nil +} + +// Reads a variable length array of bytes from |r|. |numLenBytes| specifies the +// number of (BigEndian) prefix-bytes which contain the length of the actual +// array data bytes that follow. +// Allocates an array to hold the contents and returns a slice view into it if +// the read was successful, or an error otherwise. +func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) { + switch { + case numLenBytes > 8: + return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes) + case numLenBytes == 0: + return nil, errors.New("numLenBytes should be > 0") + } + l, err := readUint(r, numLenBytes) + if err != nil { + return nil, err + } + data := make([]byte, l) + if n, err := io.ReadFull(r, data); err != nil { + if err == io.EOF || err == io.ErrUnexpectedEOF { + return nil, fmt.Errorf("short read: expected %d but got %d", l, n) + } + return nil, err + } + return data, nil +} + +// UnmarshalDigitallySigned reconstructs a DigitallySigned structure from a Reader +func UnmarshalDigitallySigned(r io.Reader) (*DigitallySigned, error) { + var h byte + if err := binary.Read(r, binary.BigEndian, &h); err != nil { + return nil, fmt.Errorf("failed to read HashAlgorithm: %v", err) + } + + var s byte + if err := binary.Read(r, binary.BigEndian, &s); err != nil { + return nil, fmt.Errorf("failed to read SignatureAlgorithm: %v", err) + } + + sig, err := readVarBytes(r, SignatureLengthBytes) + if err != nil { + return nil, fmt.Errorf("failed to read Signature bytes: %v", err) + } + + return &DigitallySigned{ + HashAlgorithm: HashAlgorithm(h), + SignatureAlgorithm: SignatureAlgorithm(s), + Signature: sig, + }, nil +} + +func marshalDigitallySignedHere(ds DigitallySigned, here []byte) ([]byte, error) { + sigLen := len(ds.Signature) + dsOutLen := 2 + SignatureLengthBytes + sigLen + if here == nil { + here = make([]byte, dsOutLen) + } + if len(here) < dsOutLen { + return nil, ErrNotEnoughBuffer + } + here = here[0:dsOutLen] + + here[0] = byte(ds.HashAlgorithm) + here[1] = byte(ds.SignatureAlgorithm) + binary.BigEndian.PutUint16(here[2:4], uint16(sigLen)) + copy(here[4:], ds.Signature) + + return here, nil +} + +// MarshalDigitallySigned marshalls a DigitallySigned structure into a byte array +func MarshalDigitallySigned(ds DigitallySigned) ([]byte, error) { + return marshalDigitallySignedHere(ds, nil) +} + +func deserializeSCTV1(r io.Reader, sct *SignedCertificateTimestamp) error { + if err := binary.Read(r, binary.BigEndian, &sct.LogID); err != nil { + return err + } + if err := binary.Read(r, binary.BigEndian, &sct.Timestamp); err != nil { + return err + } + ext, err := readVarBytes(r, ExtensionsLengthBytes) + if err != nil { + return err + } + sct.Extensions = ext + ds, err := UnmarshalDigitallySigned(r) + if err != nil { + return err + } + sct.Signature = *ds + return nil +} + +func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) { + var sct SignedCertificateTimestamp + if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil { + return nil, err + } + switch sct.SCTVersion { + case V1: + return &sct, deserializeSCTV1(r, &sct) + default: + return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion) + } +} diff --git a/vendor/github.com/zmap/zcrypto/x509/ct/types.go b/vendor/github.com/zmap/zcrypto/x509/ct/types.go new file mode 100644 index 0000000000..8d894d3344 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/ct/types.go @@ -0,0 +1,229 @@ +package ct + +// This file contains selectively chosen snippets of +// github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80 +// +// These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct +// which contains yet another version of x509,asn1 and tls + +import ( + "bytes" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" +) + +// CTExtensions is a representation of the raw bytes of any CtExtension +// structure (see section 3.2) +type CTExtensions []byte + +// SHA256Hash represents the output from the SHA256 hash function. +type SHA256Hash [sha256.Size]byte + +// FromBase64String populates the SHA256 struct with the contents of the base64 data passed in. +func (s *SHA256Hash) FromBase64String(b64 string) error { + bs, err := base64.StdEncoding.DecodeString(b64) + if err != nil { + return fmt.Errorf("failed to unbase64 LogID: %v", err) + } + if len(bs) != sha256.Size { + return fmt.Errorf("invalid SHA256 length, expected 32 but got %d", len(bs)) + } + copy(s[:], bs) + return nil +} + +// Base64String returns the base64 representation of this SHA256Hash. +func (s SHA256Hash) Base64String() string { + return base64.StdEncoding.EncodeToString(s[:]) +} + +// MarshalJSON implements the json.Marshaller interface for SHA256Hash. +func (s SHA256Hash) MarshalJSON() ([]byte, error) { + return []byte(`"` + s.Base64String() + `"`), nil +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (s *SHA256Hash) UnmarshalJSON(b []byte) error { + var content string + if err := json.Unmarshal(b, &content); err != nil { + return fmt.Errorf("failed to unmarshal SHA256Hash: %v", err) + } + return s.FromBase64String(content) +} + +// HashAlgorithm from the DigitallySigned struct +type HashAlgorithm byte + +// HashAlgorithm constants +const ( + None HashAlgorithm = 0 + MD5 HashAlgorithm = 1 + SHA1 HashAlgorithm = 2 + SHA224 HashAlgorithm = 3 + SHA256 HashAlgorithm = 4 + SHA384 HashAlgorithm = 5 + SHA512 HashAlgorithm = 6 +) + +func (h HashAlgorithm) String() string { + switch h { + case None: + return "None" + case MD5: + return "MD5" + case SHA1: + return "SHA1" + case SHA224: + return "SHA224" + case SHA256: + return "SHA256" + case SHA384: + return "SHA384" + case SHA512: + return "SHA512" + default: + return fmt.Sprintf("UNKNOWN(%d)", h) + } +} + +// SignatureAlgorithm from the the DigitallySigned struct +type SignatureAlgorithm byte + +// SignatureAlgorithm constants +const ( + Anonymous SignatureAlgorithm = 0 + RSA SignatureAlgorithm = 1 + DSA SignatureAlgorithm = 2 + ECDSA SignatureAlgorithm = 3 +) + +func (s SignatureAlgorithm) String() string { + switch s { + case Anonymous: + return "Anonymous" + case RSA: + return "RSA" + case DSA: + return "DSA" + case ECDSA: + return "ECDSA" + default: + return fmt.Sprintf("UNKNOWN(%d)", s) + } +} + +// DigitallySigned represents an RFC5246 DigitallySigned structure +type DigitallySigned struct { + HashAlgorithm HashAlgorithm + SignatureAlgorithm SignatureAlgorithm + Signature []byte +} + +// FromBase64String populates the DigitallySigned structure from the base64 data passed in. +// Returns an error if the base64 data is invalid. +func (d *DigitallySigned) FromBase64String(b64 string) error { + raw, err := base64.StdEncoding.DecodeString(b64) + if err != nil { + return fmt.Errorf("failed to unbase64 DigitallySigned: %v", err) + } + ds, err := UnmarshalDigitallySigned(bytes.NewReader(raw)) + if err != nil { + return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err) + } + *d = *ds + return nil +} + +// Base64String returns the base64 representation of the DigitallySigned struct. +func (d DigitallySigned) Base64String() (string, error) { + b, err := MarshalDigitallySigned(d) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(b), nil +} + +// MarshalJSON implements the json.Marshaller interface. +func (d DigitallySigned) MarshalJSON() ([]byte, error) { + b64, err := d.Base64String() + if err != nil { + return []byte{}, err + } + return []byte(`"` + b64 + `"`), nil +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (d *DigitallySigned) UnmarshalJSON(b []byte) error { + var content string + if err := json.Unmarshal(b, &content); err != nil { + return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err) + } + return d.FromBase64String(content) +} + +// Version represents the Version enum from section 3.2 of the RFC: +// enum { v1(0), (255) } Version; +type Version uint8 + +func (v Version) String() string { + switch v { + case V1: + return "V1" + default: + return fmt.Sprintf("UnknownVersion(%d)", v) + } +} + +// CT Version constants, see section 3.2 of the RFC. +const ( + V1 Version = 0 +) + +// SignedCertificateTimestamp represents the structure returned by the +// add-chain and add-pre-chain methods after base64 decoding. (see RFC sections +// 3.2 ,4.1 and 4.2) +type SignedCertificateTimestamp struct { + SCTVersion Version `json:"version"` // The version of the protocol to which the SCT conforms + LogID SHA256Hash `json:"log_id"` // the SHA-256 hash of the log's public key, calculated over + // the DER encoding of the key represented as SubjectPublicKeyInfo. + Timestamp uint64 `json:"timestamp,omitempty"` // Timestamp (in ms since unix epoc) at which the SCT was issued. NOTE: When this is serialized, the output is in seconds, not milliseconds. + Extensions CTExtensions `json:"extensions,omitempty"` // For future extensions to the protocol + Signature DigitallySigned `json:"signature"` // The Log's signature for this SCT +} + +// Copied from ct/types.go 2018/06/15 to deal with BQ timestamp overflow; output +// is expected to be seconds, not milliseconds. +type auxSignedCertificateTimestamp SignedCertificateTimestamp + +const kMaxTimestamp = 253402300799 + +// MarshalJSON implements the JSON.Marshaller interface. +func (sct *SignedCertificateTimestamp) MarshalJSON() ([]byte, error) { + aux := auxSignedCertificateTimestamp(*sct) + aux.Timestamp = sct.Timestamp / 1000 // convert ms to sec + if aux.Timestamp > kMaxTimestamp { + aux.Timestamp = 0 + } + return json.Marshal(&aux) +} + +type sctError int + +// Preallocate errors for performance +var ( + ErrInvalidVersion error = sctError(1) + ErrNotEnoughBuffer error = sctError(2) +) + +func (e sctError) Error() string { + switch e { + case ErrInvalidVersion: + return "invalid SCT version detected" + case ErrNotEnoughBuffer: + return "provided buffer was too small" + default: + return "unknown error" + } +} diff --git a/vendor/github.com/zmap/zcrypto/x509/example.json b/vendor/github.com/zmap/zcrypto/x509/example.json new file mode 100644 index 0000000000..dd225da71d --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/example.json @@ -0,0 +1,65 @@ +{ + "domain": null, + "certificate": { + "version": 3, + "serial_number": 123893, + "signature_algorithm": { + "id": 123, + "name": "SHA1" + }, + "issuer": { + "common_name": "Starfield CA", + "attributes": [ + { "organization": "Startfield" }, + { "location": "Scottsdale" }, + { "state": "Arizona" }, + { "country": "US" } + ] + }, + "validity": { + "start": "20140102", + "end": "20150102", + "length" :8760 + }, + "subject": { + "common_name": "*.tools.ieft.org", + "attributes": [ + { "organization_unit": "Domain Control Validated" } + ] + }, + "subject_key_info": { + "algorithm": { + "id": 234, + "name": "RSA" + }, + "key": { + "modulus": "base64encodedmodulus", + "exponent": 65537 + } + }, + "extensions": [ + { + "id": 345, + "name": "Certificate Basic Constraints", + "is_ca": false + }, + { + "id": 456, + "name": "Alt Names", + "alt_names": [ + "*.tools.ietf.org", + "tools.ietf.org" + ] + } + ] + }, + "signature_algorithm": { + "id": 123, + "name": "SHA1" + }, + "signature": { + "value": "base64encodedsignature", + "is_valid": true, + "matches_domain": null + } +} diff --git a/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go b/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go new file mode 100644 index 0000000000..4b66fc522b --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go @@ -0,0 +1,679 @@ +// Created by extended_key_usage_gen; DO NOT EDIT + +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "encoding/asn1" +) + +const ( + OID_EKU_APPLE_CODE_SIGNING = "1.2.840.113635.100.4.1" + OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT = "1.2.840.113635.100.4.1.1" + OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING = "1.2.840.113635.100.4.1.2" + OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY = "1.2.840.113635.100.4.1.3" + OID_EKU_APPLE_RESOURCE_SIGNING = "1.2.840.113635.100.4.1.4" + OID_EKU_APPLE_ICHAT_SIGNING = "1.2.840.113635.100.4.2" + OID_EKU_APPLE_ICHAT_ENCRYPTION = "1.2.840.113635.100.4.3" + OID_EKU_APPLE_SYSTEM_IDENTITY = "1.2.840.113635.100.4.4" + OID_EKU_APPLE_CRYPTO_ENV = "1.2.840.113635.100.4.5" + OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV = "1.2.840.113635.100.4.5.1" + OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV = "1.2.840.113635.100.4.5.2" + OID_EKU_APPLE_CRYPTO_TEST_ENV = "1.2.840.113635.100.4.5.3" + OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV = "1.2.840.113635.100.4.5.4" + OID_EKU_APPLE_CRYPTO_QOS = "1.2.840.113635.100.4.6" + OID_EKU_APPLE_CRYPTO_TIER0_QOS = "1.2.840.113635.100.4.6.1" + OID_EKU_APPLE_CRYPTO_TIER1_QOS = "1.2.840.113635.100.4.6.2" + OID_EKU_APPLE_CRYPTO_TIER2_QOS = "1.2.840.113635.100.4.6.3" + OID_EKU_APPLE_CRYPTO_TIER3_QOS = "1.2.840.113635.100.4.6.4" + OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING = "1.3.6.1.4.1.311.10.3.1" + OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE = "1.3.6.1.4.1.311.10.3.10" + OID_EKU_MICROSOFT_KEY_RECOVERY_3 = "1.3.6.1.4.1.311.10.3.11" + OID_EKU_MICROSOFT_DOCUMENT_SIGNING = "1.3.6.1.4.1.311.10.3.12" + OID_EKU_MICROSOFT_LIFETIME_SIGNING = "1.3.6.1.4.1.311.10.3.13" + OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE = "1.3.6.1.4.1.311.10.3.14" + OID_EKU_MICROSOFT_SMART_DISPLAY = "1.3.6.1.4.1.311.10.3.15" + OID_EKU_MICROSOFT_CSP_SIGNATURE = "1.3.6.1.4.1.311.10.3.16" + OID_EKU_MICROSOFT_TIMESTAMP_SIGNING = "1.3.6.1.4.1.311.10.3.2" + OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO = "1.3.6.1.4.1.311.10.3.3" + OID_EKU_MICROSOFT_SGC_SERIALIZED = "1.3.6.1.4.1.311.10.3.3.1" + OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM = "1.3.6.1.4.1.311.10.3.4" + OID_EKU_MICROSOFT_EFS_RECOVERY = "1.3.6.1.4.1.311.10.3.4.1" + OID_EKU_MICROSOFT_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.5" + OID_EKU_MICROSOFT_NT5_CRYPTO = "1.3.6.1.4.1.311.10.3.6" + OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.7" + OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO = "1.3.6.1.4.1.311.10.3.8" + OID_EKU_MICROSOFT_ROOT_LIST_SIGNER = "1.3.6.1.4.1.311.10.3.9" + OID_EKU_MICROSOFT_DRM = "1.3.6.1.4.1.311.10.5.1" + OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION = "1.3.6.1.4.1.311.10.5.2" + OID_EKU_MICROSOFT_LICENSES = "1.3.6.1.4.1.311.10.5.3" + OID_EKU_MICROSOFT_LICENSE_SERVER = "1.3.6.1.4.1.311.10.5.4" + OID_EKU_MICROSOFT_ENROLLMENT_AGENT = "1.3.6.1.4.1.311.20.2.1" + OID_EKU_MICROSOFT_SMARTCARD_LOGON = "1.3.6.1.4.1.311.20.2.2" + OID_EKU_MICROSOFT_CA_EXCHANGE = "1.3.6.1.4.1.311.21.5" + OID_EKU_MICROSOFT_KEY_RECOVERY_21 = "1.3.6.1.4.1.311.21.6" + OID_EKU_MICROSOFT_SYSTEM_HEALTH = "1.3.6.1.4.1.311.47.1.1" + OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE = "1.3.6.1.4.1.311.47.1.3" + OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING = "1.3.6.1.4.1.311.61.1.1" + OID_EKU_SERVER_AUTH = "1.3.6.1.5.5.7.3.1" + OID_EKU_DVCS = "1.3.6.1.5.5.7.3.10" + OID_EKU_SBGP_CERT_AA_SERVICE_AUTH = "1.3.6.1.5.5.7.3.11" + OID_EKU_EAP_OVER_PPP = "1.3.6.1.5.5.7.3.13" + OID_EKU_EAP_OVER_LAN = "1.3.6.1.5.5.7.3.14" + OID_EKU_CLIENT_AUTH = "1.3.6.1.5.5.7.3.2" + OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3" + OID_EKU_EMAIL_PROTECTION = "1.3.6.1.5.5.7.3.4" + OID_EKU_IPSEC_END_SYSTEM = "1.3.6.1.5.5.7.3.5" + OID_EKU_IPSEC_TUNNEL = "1.3.6.1.5.5.7.3.6" + OID_EKU_IPSEC_USER = "1.3.6.1.5.5.7.3.7" + OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8" + OID_EKU_OCSP_SIGNING = "1.3.6.1.5.5.7.3.9" + OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE = "1.3.6.1.5.5.8.2.2" + OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO = "2.16.840.1.113730.4.1" + OID_EKU_ANY = "2.5.29.37.0" +) + +var ( + oidExtKeyUsageAppleCodeSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1} + oidExtKeyUsageAppleCodeSigningDevelopment = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 1} + oidExtKeyUsageAppleSoftwareUpdateSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 2} + oidExtKeyUsageAppleCodeSigningThirdParty = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 3} + oidExtKeyUsageAppleResourceSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 4} + oidExtKeyUsageAppleIchatSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 2} + oidExtKeyUsageAppleIchatEncryption = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 3} + oidExtKeyUsageAppleSystemIdentity = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 4} + oidExtKeyUsageAppleCryptoEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5} + oidExtKeyUsageAppleCryptoProductionEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 1} + oidExtKeyUsageAppleCryptoMaintenanceEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 2} + oidExtKeyUsageAppleCryptoTestEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 3} + oidExtKeyUsageAppleCryptoDevelopmentEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 4} + oidExtKeyUsageAppleCryptoQos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6} + oidExtKeyUsageAppleCryptoTier0Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 1} + oidExtKeyUsageAppleCryptoTier1Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 2} + oidExtKeyUsageAppleCryptoTier2Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 3} + oidExtKeyUsageAppleCryptoTier3Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 4} + oidExtKeyUsageMicrosoftCertTrustListSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 1} + oidExtKeyUsageMicrosoftQualifiedSubordinate = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 10} + oidExtKeyUsageMicrosoftKeyRecovery3 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 11} + oidExtKeyUsageMicrosoftDocumentSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 12} + oidExtKeyUsageMicrosoftLifetimeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 13} + oidExtKeyUsageMicrosoftMobileDeviceSoftware = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 14} + oidExtKeyUsageMicrosoftSmartDisplay = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 15} + oidExtKeyUsageMicrosoftCspSignature = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 16} + oidExtKeyUsageMicrosoftTimestampSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 2} + oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3} + oidExtKeyUsageMicrosoftSgcSerialized = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3, 1} + oidExtKeyUsageMicrosoftEncryptedFileSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 4} + oidExtKeyUsageMicrosoftEfsRecovery = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 4, 1} + oidExtKeyUsageMicrosoftWhqlCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 5} + oidExtKeyUsageMicrosoftNt5Crypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 6} + oidExtKeyUsageMicrosoftOemWhqlCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 7} + oidExtKeyUsageMicrosoftEmbeddedNtCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 8} + oidExtKeyUsageMicrosoftRootListSigner = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 9} + oidExtKeyUsageMicrosoftDrm = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 1} + oidExtKeyUsageMicrosoftDrmIndividualization = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 2} + oidExtKeyUsageMicrosoftLicenses = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 3} + oidExtKeyUsageMicrosoftLicenseServer = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 4} + oidExtKeyUsageMicrosoftEnrollmentAgent = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 1} + oidExtKeyUsageMicrosoftSmartcardLogon = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 2} + oidExtKeyUsageMicrosoftCaExchange = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 5} + oidExtKeyUsageMicrosoftKeyRecovery21 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 6} + oidExtKeyUsageMicrosoftSystemHealth = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 47, 1, 1} + oidExtKeyUsageMicrosoftSystemHealthLoophole = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 47, 1, 3} + oidExtKeyUsageMicrosoftKernelModeCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1} + oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} + oidExtKeyUsageDvcs = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 10} + oidExtKeyUsageSbgpCertAaServiceAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 11} + oidExtKeyUsageEapOverPpp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 13} + oidExtKeyUsageEapOverLan = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 14} + oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} + oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3} + oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4} + oidExtKeyUsageIpsecEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5} + oidExtKeyUsageIpsecTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6} + oidExtKeyUsageIpsecUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7} + oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} + oidExtKeyUsageOcspSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9} + oidExtKeyUsageIpsecIntermediateSystemUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 8, 2, 2} + oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1} + oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0} +) + +const ( + ExtKeyUsageAppleCodeSigning ExtKeyUsage = iota + ExtKeyUsageAppleCodeSigningDevelopment + ExtKeyUsageAppleSoftwareUpdateSigning + ExtKeyUsageAppleCodeSigningThirdParty + ExtKeyUsageAppleResourceSigning + ExtKeyUsageAppleIchatSigning + ExtKeyUsageAppleIchatEncryption + ExtKeyUsageAppleSystemIdentity + ExtKeyUsageAppleCryptoEnv + ExtKeyUsageAppleCryptoProductionEnv + ExtKeyUsageAppleCryptoMaintenanceEnv + ExtKeyUsageAppleCryptoTestEnv + ExtKeyUsageAppleCryptoDevelopmentEnv + ExtKeyUsageAppleCryptoQos + ExtKeyUsageAppleCryptoTier0Qos + ExtKeyUsageAppleCryptoTier1Qos + ExtKeyUsageAppleCryptoTier2Qos + ExtKeyUsageAppleCryptoTier3Qos + ExtKeyUsageMicrosoftCertTrustListSigning + ExtKeyUsageMicrosoftQualifiedSubordinate + ExtKeyUsageMicrosoftKeyRecovery3 + ExtKeyUsageMicrosoftDocumentSigning + ExtKeyUsageMicrosoftLifetimeSigning + ExtKeyUsageMicrosoftMobileDeviceSoftware + ExtKeyUsageMicrosoftSmartDisplay + ExtKeyUsageMicrosoftCspSignature + ExtKeyUsageMicrosoftTimestampSigning + ExtKeyUsageMicrosoftServerGatedCrypto + ExtKeyUsageMicrosoftSgcSerialized + ExtKeyUsageMicrosoftEncryptedFileSystem + ExtKeyUsageMicrosoftEfsRecovery + ExtKeyUsageMicrosoftWhqlCrypto + ExtKeyUsageMicrosoftNt5Crypto + ExtKeyUsageMicrosoftOemWhqlCrypto + ExtKeyUsageMicrosoftEmbeddedNtCrypto + ExtKeyUsageMicrosoftRootListSigner + ExtKeyUsageMicrosoftDrm + ExtKeyUsageMicrosoftDrmIndividualization + ExtKeyUsageMicrosoftLicenses + ExtKeyUsageMicrosoftLicenseServer + ExtKeyUsageMicrosoftEnrollmentAgent + ExtKeyUsageMicrosoftSmartcardLogon + ExtKeyUsageMicrosoftCaExchange + ExtKeyUsageMicrosoftKeyRecovery21 + ExtKeyUsageMicrosoftSystemHealth + ExtKeyUsageMicrosoftSystemHealthLoophole + ExtKeyUsageMicrosoftKernelModeCodeSigning + ExtKeyUsageServerAuth + ExtKeyUsageDvcs + ExtKeyUsageSbgpCertAaServiceAuth + ExtKeyUsageEapOverPpp + ExtKeyUsageEapOverLan + ExtKeyUsageClientAuth + ExtKeyUsageCodeSigning + ExtKeyUsageEmailProtection + ExtKeyUsageIpsecEndSystem + ExtKeyUsageIpsecTunnel + ExtKeyUsageIpsecUser + ExtKeyUsageTimeStamping + ExtKeyUsageOcspSigning + ExtKeyUsageIpsecIntermediateSystemUsage + ExtKeyUsageNetscapeServerGatedCrypto + ExtKeyUsageAny +) + +type auxExtendedKeyUsage struct { + AppleCodeSigning bool `json:"apple_code_signing,omitempty" oid:"1.2.840.113635.100.4.1"` + AppleCodeSigningDevelopment bool `json:"apple_code_signing_development,omitempty" oid:"1.2.840.113635.100.4.1.1"` + AppleSoftwareUpdateSigning bool `json:"apple_software_update_signing,omitempty" oid:"1.2.840.113635.100.4.1.2"` + AppleCodeSigningThirdParty bool `json:"apple_code_signing_third_party,omitempty" oid:"1.2.840.113635.100.4.1.3"` + AppleResourceSigning bool `json:"apple_resource_signing,omitempty" oid:"1.2.840.113635.100.4.1.4"` + AppleIchatSigning bool `json:"apple_ichat_signing,omitempty" oid:"1.2.840.113635.100.4.2"` + AppleIchatEncryption bool `json:"apple_ichat_encryption,omitempty" oid:"1.2.840.113635.100.4.3"` + AppleSystemIdentity bool `json:"apple_system_identity,omitempty" oid:"1.2.840.113635.100.4.4"` + AppleCryptoEnv bool `json:"apple_crypto_env,omitempty" oid:"1.2.840.113635.100.4.5"` + AppleCryptoProductionEnv bool `json:"apple_crypto_production_env,omitempty" oid:"1.2.840.113635.100.4.5.1"` + AppleCryptoMaintenanceEnv bool `json:"apple_crypto_maintenance_env,omitempty" oid:"1.2.840.113635.100.4.5.2"` + AppleCryptoTestEnv bool `json:"apple_crypto_test_env,omitempty" oid:"1.2.840.113635.100.4.5.3"` + AppleCryptoDevelopmentEnv bool `json:"apple_crypto_development_env,omitempty" oid:"1.2.840.113635.100.4.5.4"` + AppleCryptoQos bool `json:"apple_crypto_qos,omitempty" oid:"1.2.840.113635.100.4.6"` + AppleCryptoTier0Qos bool `json:"apple_crypto_tier0_qos,omitempty" oid:"1.2.840.113635.100.4.6.1"` + AppleCryptoTier1Qos bool `json:"apple_crypto_tier1_qos,omitempty" oid:"1.2.840.113635.100.4.6.2"` + AppleCryptoTier2Qos bool `json:"apple_crypto_tier2_qos,omitempty" oid:"1.2.840.113635.100.4.6.3"` + AppleCryptoTier3Qos bool `json:"apple_crypto_tier3_qos,omitempty" oid:"1.2.840.113635.100.4.6.4"` + MicrosoftCertTrustListSigning bool `json:"microsoft_cert_trust_list_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.1"` + MicrosoftQualifiedSubordinate bool `json:"microsoft_qualified_subordinate,omitempty" oid:"1.3.6.1.4.1.311.10.3.10"` + MicrosoftKeyRecovery3 bool `json:"microsoft_key_recovery_3,omitempty" oid:"1.3.6.1.4.1.311.10.3.11"` + MicrosoftDocumentSigning bool `json:"microsoft_document_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.12"` + MicrosoftLifetimeSigning bool `json:"microsoft_lifetime_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.13"` + MicrosoftMobileDeviceSoftware bool `json:"microsoft_mobile_device_software,omitempty" oid:"1.3.6.1.4.1.311.10.3.14"` + MicrosoftSmartDisplay bool `json:"microsoft_smart_display,omitempty" oid:"1.3.6.1.4.1.311.10.3.15"` + MicrosoftCspSignature bool `json:"microsoft_csp_signature,omitempty" oid:"1.3.6.1.4.1.311.10.3.16"` + MicrosoftTimestampSigning bool `json:"microsoft_timestamp_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.2"` + MicrosoftServerGatedCrypto bool `json:"microsoft_server_gated_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.3"` + MicrosoftSgcSerialized bool `json:"microsoft_sgc_serialized,omitempty" oid:"1.3.6.1.4.1.311.10.3.3.1"` + MicrosoftEncryptedFileSystem bool `json:"microsoft_encrypted_file_system,omitempty" oid:"1.3.6.1.4.1.311.10.3.4"` + MicrosoftEfsRecovery bool `json:"microsoft_efs_recovery,omitempty" oid:"1.3.6.1.4.1.311.10.3.4.1"` + MicrosoftWhqlCrypto bool `json:"microsoft_whql_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.5"` + MicrosoftNt5Crypto bool `json:"microsoft_nt5_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.6"` + MicrosoftOemWhqlCrypto bool `json:"microsoft_oem_whql_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.7"` + MicrosoftEmbeddedNtCrypto bool `json:"microsoft_embedded_nt_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.8"` + MicrosoftRootListSigner bool `json:"microsoft_root_list_signer,omitempty" oid:"1.3.6.1.4.1.311.10.3.9"` + MicrosoftDrm bool `json:"microsoft_drm,omitempty" oid:"1.3.6.1.4.1.311.10.5.1"` + MicrosoftDrmIndividualization bool `json:"microsoft_drm_individualization,omitempty" oid:"1.3.6.1.4.1.311.10.5.2"` + MicrosoftLicenses bool `json:"microsoft_licenses,omitempty" oid:"1.3.6.1.4.1.311.10.5.3"` + MicrosoftLicenseServer bool `json:"microsoft_license_server,omitempty" oid:"1.3.6.1.4.1.311.10.5.4"` + MicrosoftEnrollmentAgent bool `json:"microsoft_enrollment_agent,omitempty" oid:"1.3.6.1.4.1.311.20.2.1"` + MicrosoftSmartcardLogon bool `json:"microsoft_smartcard_logon,omitempty" oid:"1.3.6.1.4.1.311.20.2.2"` + MicrosoftCaExchange bool `json:"microsoft_ca_exchange,omitempty" oid:"1.3.6.1.4.1.311.21.5"` + MicrosoftKeyRecovery21 bool `json:"microsoft_key_recovery_21,omitempty" oid:"1.3.6.1.4.1.311.21.6"` + MicrosoftSystemHealth bool `json:"microsoft_system_health,omitempty" oid:"1.3.6.1.4.1.311.47.1.1"` + MicrosoftSystemHealthLoophole bool `json:"microsoft_system_health_loophole,omitempty" oid:"1.3.6.1.4.1.311.47.1.3"` + MicrosoftKernelModeCodeSigning bool `json:"microsoft_kernel_mode_code_signing,omitempty" oid:"1.3.6.1.4.1.311.61.1.1"` + ServerAuth bool `json:"server_auth,omitempty" oid:"1.3.6.1.5.5.7.3.1"` + Dvcs bool `json:"dvcs,omitempty" oid:"1.3.6.1.5.5.7.3.10"` + SbgpCertAaServiceAuth bool `json:"sbgp_cert_aa_service_auth,omitempty" oid:"1.3.6.1.5.5.7.3.11"` + EapOverPpp bool `json:"eap_over_ppp,omitempty" oid:"1.3.6.1.5.5.7.3.13"` + EapOverLan bool `json:"eap_over_lan,omitempty" oid:"1.3.6.1.5.5.7.3.14"` + ClientAuth bool `json:"client_auth,omitempty" oid:"1.3.6.1.5.5.7.3.2"` + CodeSigning bool `json:"code_signing,omitempty" oid:"1.3.6.1.5.5.7.3.3"` + EmailProtection bool `json:"email_protection,omitempty" oid:"1.3.6.1.5.5.7.3.4"` + IpsecEndSystem bool `json:"ipsec_end_system,omitempty" oid:"1.3.6.1.5.5.7.3.5"` + IpsecTunnel bool `json:"ipsec_tunnel,omitempty" oid:"1.3.6.1.5.5.7.3.6"` + IpsecUser bool `json:"ipsec_user,omitempty" oid:"1.3.6.1.5.5.7.3.7"` + TimeStamping bool `json:"time_stamping,omitempty" oid:"1.3.6.1.5.5.7.3.8"` + OcspSigning bool `json:"ocsp_signing,omitempty" oid:"1.3.6.1.5.5.7.3.9"` + IpsecIntermediateSystemUsage bool `json:"ipsec_intermediate_system_usage,omitempty" oid:"1.3.6.1.5.5.8.2.2"` + NetscapeServerGatedCrypto bool `json:"netscape_server_gated_crypto,omitempty" oid:"2.16.840.1.113730.4.1"` + Any bool `json:"any,omitempty" oid:"2.5.29.37.0"` + Unknown []string `json:"unknown,omitempty"` +} + +func (aux *auxExtendedKeyUsage) populateFromASN1(oid asn1.ObjectIdentifier) { + s := oid.String() + switch s { + case OID_EKU_APPLE_CODE_SIGNING: + aux.AppleCodeSigning = true + case OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT: + aux.AppleCodeSigningDevelopment = true + case OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING: + aux.AppleSoftwareUpdateSigning = true + case OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY: + aux.AppleCodeSigningThirdParty = true + case OID_EKU_APPLE_RESOURCE_SIGNING: + aux.AppleResourceSigning = true + case OID_EKU_APPLE_ICHAT_SIGNING: + aux.AppleIchatSigning = true + case OID_EKU_APPLE_ICHAT_ENCRYPTION: + aux.AppleIchatEncryption = true + case OID_EKU_APPLE_SYSTEM_IDENTITY: + aux.AppleSystemIdentity = true + case OID_EKU_APPLE_CRYPTO_ENV: + aux.AppleCryptoEnv = true + case OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV: + aux.AppleCryptoProductionEnv = true + case OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV: + aux.AppleCryptoMaintenanceEnv = true + case OID_EKU_APPLE_CRYPTO_TEST_ENV: + aux.AppleCryptoTestEnv = true + case OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV: + aux.AppleCryptoDevelopmentEnv = true + case OID_EKU_APPLE_CRYPTO_QOS: + aux.AppleCryptoQos = true + case OID_EKU_APPLE_CRYPTO_TIER0_QOS: + aux.AppleCryptoTier0Qos = true + case OID_EKU_APPLE_CRYPTO_TIER1_QOS: + aux.AppleCryptoTier1Qos = true + case OID_EKU_APPLE_CRYPTO_TIER2_QOS: + aux.AppleCryptoTier2Qos = true + case OID_EKU_APPLE_CRYPTO_TIER3_QOS: + aux.AppleCryptoTier3Qos = true + case OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING: + aux.MicrosoftCertTrustListSigning = true + case OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE: + aux.MicrosoftQualifiedSubordinate = true + case OID_EKU_MICROSOFT_KEY_RECOVERY_3: + aux.MicrosoftKeyRecovery3 = true + case OID_EKU_MICROSOFT_DOCUMENT_SIGNING: + aux.MicrosoftDocumentSigning = true + case OID_EKU_MICROSOFT_LIFETIME_SIGNING: + aux.MicrosoftLifetimeSigning = true + case OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE: + aux.MicrosoftMobileDeviceSoftware = true + case OID_EKU_MICROSOFT_SMART_DISPLAY: + aux.MicrosoftSmartDisplay = true + case OID_EKU_MICROSOFT_CSP_SIGNATURE: + aux.MicrosoftCspSignature = true + case OID_EKU_MICROSOFT_TIMESTAMP_SIGNING: + aux.MicrosoftTimestampSigning = true + case OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO: + aux.MicrosoftServerGatedCrypto = true + case OID_EKU_MICROSOFT_SGC_SERIALIZED: + aux.MicrosoftSgcSerialized = true + case OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM: + aux.MicrosoftEncryptedFileSystem = true + case OID_EKU_MICROSOFT_EFS_RECOVERY: + aux.MicrosoftEfsRecovery = true + case OID_EKU_MICROSOFT_WHQL_CRYPTO: + aux.MicrosoftWhqlCrypto = true + case OID_EKU_MICROSOFT_NT5_CRYPTO: + aux.MicrosoftNt5Crypto = true + case OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO: + aux.MicrosoftOemWhqlCrypto = true + case OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO: + aux.MicrosoftEmbeddedNtCrypto = true + case OID_EKU_MICROSOFT_ROOT_LIST_SIGNER: + aux.MicrosoftRootListSigner = true + case OID_EKU_MICROSOFT_DRM: + aux.MicrosoftDrm = true + case OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION: + aux.MicrosoftDrmIndividualization = true + case OID_EKU_MICROSOFT_LICENSES: + aux.MicrosoftLicenses = true + case OID_EKU_MICROSOFT_LICENSE_SERVER: + aux.MicrosoftLicenseServer = true + case OID_EKU_MICROSOFT_ENROLLMENT_AGENT: + aux.MicrosoftEnrollmentAgent = true + case OID_EKU_MICROSOFT_SMARTCARD_LOGON: + aux.MicrosoftSmartcardLogon = true + case OID_EKU_MICROSOFT_CA_EXCHANGE: + aux.MicrosoftCaExchange = true + case OID_EKU_MICROSOFT_KEY_RECOVERY_21: + aux.MicrosoftKeyRecovery21 = true + case OID_EKU_MICROSOFT_SYSTEM_HEALTH: + aux.MicrosoftSystemHealth = true + case OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE: + aux.MicrosoftSystemHealthLoophole = true + case OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING: + aux.MicrosoftKernelModeCodeSigning = true + case OID_EKU_SERVER_AUTH: + aux.ServerAuth = true + case OID_EKU_DVCS: + aux.Dvcs = true + case OID_EKU_SBGP_CERT_AA_SERVICE_AUTH: + aux.SbgpCertAaServiceAuth = true + case OID_EKU_EAP_OVER_PPP: + aux.EapOverPpp = true + case OID_EKU_EAP_OVER_LAN: + aux.EapOverLan = true + case OID_EKU_CLIENT_AUTH: + aux.ClientAuth = true + case OID_EKU_CODE_SIGNING: + aux.CodeSigning = true + case OID_EKU_EMAIL_PROTECTION: + aux.EmailProtection = true + case OID_EKU_IPSEC_END_SYSTEM: + aux.IpsecEndSystem = true + case OID_EKU_IPSEC_TUNNEL: + aux.IpsecTunnel = true + case OID_EKU_IPSEC_USER: + aux.IpsecUser = true + case OID_EKU_TIME_STAMPING: + aux.TimeStamping = true + case OID_EKU_OCSP_SIGNING: + aux.OcspSigning = true + case OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE: + aux.IpsecIntermediateSystemUsage = true + case OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO: + aux.NetscapeServerGatedCrypto = true + case OID_EKU_ANY: + aux.Any = true + default: + } + return +} + +func (aux *auxExtendedKeyUsage) populateFromExtKeyUsage(eku ExtKeyUsage) { + switch eku { + case ExtKeyUsageAppleCodeSigning: + aux.AppleCodeSigning = true + case ExtKeyUsageAppleCodeSigningDevelopment: + aux.AppleCodeSigningDevelopment = true + case ExtKeyUsageAppleSoftwareUpdateSigning: + aux.AppleSoftwareUpdateSigning = true + case ExtKeyUsageAppleCodeSigningThirdParty: + aux.AppleCodeSigningThirdParty = true + case ExtKeyUsageAppleResourceSigning: + aux.AppleResourceSigning = true + case ExtKeyUsageAppleIchatSigning: + aux.AppleIchatSigning = true + case ExtKeyUsageAppleIchatEncryption: + aux.AppleIchatEncryption = true + case ExtKeyUsageAppleSystemIdentity: + aux.AppleSystemIdentity = true + case ExtKeyUsageAppleCryptoEnv: + aux.AppleCryptoEnv = true + case ExtKeyUsageAppleCryptoProductionEnv: + aux.AppleCryptoProductionEnv = true + case ExtKeyUsageAppleCryptoMaintenanceEnv: + aux.AppleCryptoMaintenanceEnv = true + case ExtKeyUsageAppleCryptoTestEnv: + aux.AppleCryptoTestEnv = true + case ExtKeyUsageAppleCryptoDevelopmentEnv: + aux.AppleCryptoDevelopmentEnv = true + case ExtKeyUsageAppleCryptoQos: + aux.AppleCryptoQos = true + case ExtKeyUsageAppleCryptoTier0Qos: + aux.AppleCryptoTier0Qos = true + case ExtKeyUsageAppleCryptoTier1Qos: + aux.AppleCryptoTier1Qos = true + case ExtKeyUsageAppleCryptoTier2Qos: + aux.AppleCryptoTier2Qos = true + case ExtKeyUsageAppleCryptoTier3Qos: + aux.AppleCryptoTier3Qos = true + case ExtKeyUsageMicrosoftCertTrustListSigning: + aux.MicrosoftCertTrustListSigning = true + case ExtKeyUsageMicrosoftQualifiedSubordinate: + aux.MicrosoftQualifiedSubordinate = true + case ExtKeyUsageMicrosoftKeyRecovery3: + aux.MicrosoftKeyRecovery3 = true + case ExtKeyUsageMicrosoftDocumentSigning: + aux.MicrosoftDocumentSigning = true + case ExtKeyUsageMicrosoftLifetimeSigning: + aux.MicrosoftLifetimeSigning = true + case ExtKeyUsageMicrosoftMobileDeviceSoftware: + aux.MicrosoftMobileDeviceSoftware = true + case ExtKeyUsageMicrosoftSmartDisplay: + aux.MicrosoftSmartDisplay = true + case ExtKeyUsageMicrosoftCspSignature: + aux.MicrosoftCspSignature = true + case ExtKeyUsageMicrosoftTimestampSigning: + aux.MicrosoftTimestampSigning = true + case ExtKeyUsageMicrosoftServerGatedCrypto: + aux.MicrosoftServerGatedCrypto = true + case ExtKeyUsageMicrosoftSgcSerialized: + aux.MicrosoftSgcSerialized = true + case ExtKeyUsageMicrosoftEncryptedFileSystem: + aux.MicrosoftEncryptedFileSystem = true + case ExtKeyUsageMicrosoftEfsRecovery: + aux.MicrosoftEfsRecovery = true + case ExtKeyUsageMicrosoftWhqlCrypto: + aux.MicrosoftWhqlCrypto = true + case ExtKeyUsageMicrosoftNt5Crypto: + aux.MicrosoftNt5Crypto = true + case ExtKeyUsageMicrosoftOemWhqlCrypto: + aux.MicrosoftOemWhqlCrypto = true + case ExtKeyUsageMicrosoftEmbeddedNtCrypto: + aux.MicrosoftEmbeddedNtCrypto = true + case ExtKeyUsageMicrosoftRootListSigner: + aux.MicrosoftRootListSigner = true + case ExtKeyUsageMicrosoftDrm: + aux.MicrosoftDrm = true + case ExtKeyUsageMicrosoftDrmIndividualization: + aux.MicrosoftDrmIndividualization = true + case ExtKeyUsageMicrosoftLicenses: + aux.MicrosoftLicenses = true + case ExtKeyUsageMicrosoftLicenseServer: + aux.MicrosoftLicenseServer = true + case ExtKeyUsageMicrosoftEnrollmentAgent: + aux.MicrosoftEnrollmentAgent = true + case ExtKeyUsageMicrosoftSmartcardLogon: + aux.MicrosoftSmartcardLogon = true + case ExtKeyUsageMicrosoftCaExchange: + aux.MicrosoftCaExchange = true + case ExtKeyUsageMicrosoftKeyRecovery21: + aux.MicrosoftKeyRecovery21 = true + case ExtKeyUsageMicrosoftSystemHealth: + aux.MicrosoftSystemHealth = true + case ExtKeyUsageMicrosoftSystemHealthLoophole: + aux.MicrosoftSystemHealthLoophole = true + case ExtKeyUsageMicrosoftKernelModeCodeSigning: + aux.MicrosoftKernelModeCodeSigning = true + case ExtKeyUsageServerAuth: + aux.ServerAuth = true + case ExtKeyUsageDvcs: + aux.Dvcs = true + case ExtKeyUsageSbgpCertAaServiceAuth: + aux.SbgpCertAaServiceAuth = true + case ExtKeyUsageEapOverPpp: + aux.EapOverPpp = true + case ExtKeyUsageEapOverLan: + aux.EapOverLan = true + case ExtKeyUsageClientAuth: + aux.ClientAuth = true + case ExtKeyUsageCodeSigning: + aux.CodeSigning = true + case ExtKeyUsageEmailProtection: + aux.EmailProtection = true + case ExtKeyUsageIpsecEndSystem: + aux.IpsecEndSystem = true + case ExtKeyUsageIpsecTunnel: + aux.IpsecTunnel = true + case ExtKeyUsageIpsecUser: + aux.IpsecUser = true + case ExtKeyUsageTimeStamping: + aux.TimeStamping = true + case ExtKeyUsageOcspSigning: + aux.OcspSigning = true + case ExtKeyUsageIpsecIntermediateSystemUsage: + aux.IpsecIntermediateSystemUsage = true + case ExtKeyUsageNetscapeServerGatedCrypto: + aux.NetscapeServerGatedCrypto = true + case ExtKeyUsageAny: + aux.Any = true + default: + } + return +} + +var ekuOIDs map[string]asn1.ObjectIdentifier + +var ekuConstants map[string]ExtKeyUsage + +func init() { + ekuOIDs = make(map[string]asn1.ObjectIdentifier) + ekuOIDs[OID_EKU_APPLE_CODE_SIGNING] = oidExtKeyUsageAppleCodeSigning + ekuOIDs[OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT] = oidExtKeyUsageAppleCodeSigningDevelopment + ekuOIDs[OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING] = oidExtKeyUsageAppleSoftwareUpdateSigning + ekuOIDs[OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY] = oidExtKeyUsageAppleCodeSigningThirdParty + ekuOIDs[OID_EKU_APPLE_RESOURCE_SIGNING] = oidExtKeyUsageAppleResourceSigning + ekuOIDs[OID_EKU_APPLE_ICHAT_SIGNING] = oidExtKeyUsageAppleIchatSigning + ekuOIDs[OID_EKU_APPLE_ICHAT_ENCRYPTION] = oidExtKeyUsageAppleIchatEncryption + ekuOIDs[OID_EKU_APPLE_SYSTEM_IDENTITY] = oidExtKeyUsageAppleSystemIdentity + ekuOIDs[OID_EKU_APPLE_CRYPTO_ENV] = oidExtKeyUsageAppleCryptoEnv + ekuOIDs[OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV] = oidExtKeyUsageAppleCryptoProductionEnv + ekuOIDs[OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV] = oidExtKeyUsageAppleCryptoMaintenanceEnv + ekuOIDs[OID_EKU_APPLE_CRYPTO_TEST_ENV] = oidExtKeyUsageAppleCryptoTestEnv + ekuOIDs[OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV] = oidExtKeyUsageAppleCryptoDevelopmentEnv + ekuOIDs[OID_EKU_APPLE_CRYPTO_QOS] = oidExtKeyUsageAppleCryptoQos + ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER0_QOS] = oidExtKeyUsageAppleCryptoTier0Qos + ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER1_QOS] = oidExtKeyUsageAppleCryptoTier1Qos + ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER2_QOS] = oidExtKeyUsageAppleCryptoTier2Qos + ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER3_QOS] = oidExtKeyUsageAppleCryptoTier3Qos + ekuOIDs[OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING] = oidExtKeyUsageMicrosoftCertTrustListSigning + ekuOIDs[OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE] = oidExtKeyUsageMicrosoftQualifiedSubordinate + ekuOIDs[OID_EKU_MICROSOFT_KEY_RECOVERY_3] = oidExtKeyUsageMicrosoftKeyRecovery3 + ekuOIDs[OID_EKU_MICROSOFT_DOCUMENT_SIGNING] = oidExtKeyUsageMicrosoftDocumentSigning + ekuOIDs[OID_EKU_MICROSOFT_LIFETIME_SIGNING] = oidExtKeyUsageMicrosoftLifetimeSigning + ekuOIDs[OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE] = oidExtKeyUsageMicrosoftMobileDeviceSoftware + ekuOIDs[OID_EKU_MICROSOFT_SMART_DISPLAY] = oidExtKeyUsageMicrosoftSmartDisplay + ekuOIDs[OID_EKU_MICROSOFT_CSP_SIGNATURE] = oidExtKeyUsageMicrosoftCspSignature + ekuOIDs[OID_EKU_MICROSOFT_TIMESTAMP_SIGNING] = oidExtKeyUsageMicrosoftTimestampSigning + ekuOIDs[OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO] = oidExtKeyUsageMicrosoftServerGatedCrypto + ekuOIDs[OID_EKU_MICROSOFT_SGC_SERIALIZED] = oidExtKeyUsageMicrosoftSgcSerialized + ekuOIDs[OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM] = oidExtKeyUsageMicrosoftEncryptedFileSystem + ekuOIDs[OID_EKU_MICROSOFT_EFS_RECOVERY] = oidExtKeyUsageMicrosoftEfsRecovery + ekuOIDs[OID_EKU_MICROSOFT_WHQL_CRYPTO] = oidExtKeyUsageMicrosoftWhqlCrypto + ekuOIDs[OID_EKU_MICROSOFT_NT5_CRYPTO] = oidExtKeyUsageMicrosoftNt5Crypto + ekuOIDs[OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO] = oidExtKeyUsageMicrosoftOemWhqlCrypto + ekuOIDs[OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO] = oidExtKeyUsageMicrosoftEmbeddedNtCrypto + ekuOIDs[OID_EKU_MICROSOFT_ROOT_LIST_SIGNER] = oidExtKeyUsageMicrosoftRootListSigner + ekuOIDs[OID_EKU_MICROSOFT_DRM] = oidExtKeyUsageMicrosoftDrm + ekuOIDs[OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION] = oidExtKeyUsageMicrosoftDrmIndividualization + ekuOIDs[OID_EKU_MICROSOFT_LICENSES] = oidExtKeyUsageMicrosoftLicenses + ekuOIDs[OID_EKU_MICROSOFT_LICENSE_SERVER] = oidExtKeyUsageMicrosoftLicenseServer + ekuOIDs[OID_EKU_MICROSOFT_ENROLLMENT_AGENT] = oidExtKeyUsageMicrosoftEnrollmentAgent + ekuOIDs[OID_EKU_MICROSOFT_SMARTCARD_LOGON] = oidExtKeyUsageMicrosoftSmartcardLogon + ekuOIDs[OID_EKU_MICROSOFT_CA_EXCHANGE] = oidExtKeyUsageMicrosoftCaExchange + ekuOIDs[OID_EKU_MICROSOFT_KEY_RECOVERY_21] = oidExtKeyUsageMicrosoftKeyRecovery21 + ekuOIDs[OID_EKU_MICROSOFT_SYSTEM_HEALTH] = oidExtKeyUsageMicrosoftSystemHealth + ekuOIDs[OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE] = oidExtKeyUsageMicrosoftSystemHealthLoophole + ekuOIDs[OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING] = oidExtKeyUsageMicrosoftKernelModeCodeSigning + ekuOIDs[OID_EKU_SERVER_AUTH] = oidExtKeyUsageServerAuth + ekuOIDs[OID_EKU_DVCS] = oidExtKeyUsageDvcs + ekuOIDs[OID_EKU_SBGP_CERT_AA_SERVICE_AUTH] = oidExtKeyUsageSbgpCertAaServiceAuth + ekuOIDs[OID_EKU_EAP_OVER_PPP] = oidExtKeyUsageEapOverPpp + ekuOIDs[OID_EKU_EAP_OVER_LAN] = oidExtKeyUsageEapOverLan + ekuOIDs[OID_EKU_CLIENT_AUTH] = oidExtKeyUsageClientAuth + ekuOIDs[OID_EKU_CODE_SIGNING] = oidExtKeyUsageCodeSigning + ekuOIDs[OID_EKU_EMAIL_PROTECTION] = oidExtKeyUsageEmailProtection + ekuOIDs[OID_EKU_IPSEC_END_SYSTEM] = oidExtKeyUsageIpsecEndSystem + ekuOIDs[OID_EKU_IPSEC_TUNNEL] = oidExtKeyUsageIpsecTunnel + ekuOIDs[OID_EKU_IPSEC_USER] = oidExtKeyUsageIpsecUser + ekuOIDs[OID_EKU_TIME_STAMPING] = oidExtKeyUsageTimeStamping + ekuOIDs[OID_EKU_OCSP_SIGNING] = oidExtKeyUsageOcspSigning + ekuOIDs[OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE] = oidExtKeyUsageIpsecIntermediateSystemUsage + ekuOIDs[OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO] = oidExtKeyUsageNetscapeServerGatedCrypto + ekuOIDs[OID_EKU_ANY] = oidExtKeyUsageAny + + ekuConstants = make(map[string]ExtKeyUsage) + ekuConstants[OID_EKU_APPLE_CODE_SIGNING] = ExtKeyUsageAppleCodeSigning + ekuConstants[OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT] = ExtKeyUsageAppleCodeSigningDevelopment + ekuConstants[OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING] = ExtKeyUsageAppleSoftwareUpdateSigning + ekuConstants[OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY] = ExtKeyUsageAppleCodeSigningThirdParty + ekuConstants[OID_EKU_APPLE_RESOURCE_SIGNING] = ExtKeyUsageAppleResourceSigning + ekuConstants[OID_EKU_APPLE_ICHAT_SIGNING] = ExtKeyUsageAppleIchatSigning + ekuConstants[OID_EKU_APPLE_ICHAT_ENCRYPTION] = ExtKeyUsageAppleIchatEncryption + ekuConstants[OID_EKU_APPLE_SYSTEM_IDENTITY] = ExtKeyUsageAppleSystemIdentity + ekuConstants[OID_EKU_APPLE_CRYPTO_ENV] = ExtKeyUsageAppleCryptoEnv + ekuConstants[OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV] = ExtKeyUsageAppleCryptoProductionEnv + ekuConstants[OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV] = ExtKeyUsageAppleCryptoMaintenanceEnv + ekuConstants[OID_EKU_APPLE_CRYPTO_TEST_ENV] = ExtKeyUsageAppleCryptoTestEnv + ekuConstants[OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV] = ExtKeyUsageAppleCryptoDevelopmentEnv + ekuConstants[OID_EKU_APPLE_CRYPTO_QOS] = ExtKeyUsageAppleCryptoQos + ekuConstants[OID_EKU_APPLE_CRYPTO_TIER0_QOS] = ExtKeyUsageAppleCryptoTier0Qos + ekuConstants[OID_EKU_APPLE_CRYPTO_TIER1_QOS] = ExtKeyUsageAppleCryptoTier1Qos + ekuConstants[OID_EKU_APPLE_CRYPTO_TIER2_QOS] = ExtKeyUsageAppleCryptoTier2Qos + ekuConstants[OID_EKU_APPLE_CRYPTO_TIER3_QOS] = ExtKeyUsageAppleCryptoTier3Qos + ekuConstants[OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING] = ExtKeyUsageMicrosoftCertTrustListSigning + ekuConstants[OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE] = ExtKeyUsageMicrosoftQualifiedSubordinate + ekuConstants[OID_EKU_MICROSOFT_KEY_RECOVERY_3] = ExtKeyUsageMicrosoftKeyRecovery3 + ekuConstants[OID_EKU_MICROSOFT_DOCUMENT_SIGNING] = ExtKeyUsageMicrosoftDocumentSigning + ekuConstants[OID_EKU_MICROSOFT_LIFETIME_SIGNING] = ExtKeyUsageMicrosoftLifetimeSigning + ekuConstants[OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE] = ExtKeyUsageMicrosoftMobileDeviceSoftware + ekuConstants[OID_EKU_MICROSOFT_SMART_DISPLAY] = ExtKeyUsageMicrosoftSmartDisplay + ekuConstants[OID_EKU_MICROSOFT_CSP_SIGNATURE] = ExtKeyUsageMicrosoftCspSignature + ekuConstants[OID_EKU_MICROSOFT_TIMESTAMP_SIGNING] = ExtKeyUsageMicrosoftTimestampSigning + ekuConstants[OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO] = ExtKeyUsageMicrosoftServerGatedCrypto + ekuConstants[OID_EKU_MICROSOFT_SGC_SERIALIZED] = ExtKeyUsageMicrosoftSgcSerialized + ekuConstants[OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM] = ExtKeyUsageMicrosoftEncryptedFileSystem + ekuConstants[OID_EKU_MICROSOFT_EFS_RECOVERY] = ExtKeyUsageMicrosoftEfsRecovery + ekuConstants[OID_EKU_MICROSOFT_WHQL_CRYPTO] = ExtKeyUsageMicrosoftWhqlCrypto + ekuConstants[OID_EKU_MICROSOFT_NT5_CRYPTO] = ExtKeyUsageMicrosoftNt5Crypto + ekuConstants[OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO] = ExtKeyUsageMicrosoftOemWhqlCrypto + ekuConstants[OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO] = ExtKeyUsageMicrosoftEmbeddedNtCrypto + ekuConstants[OID_EKU_MICROSOFT_ROOT_LIST_SIGNER] = ExtKeyUsageMicrosoftRootListSigner + ekuConstants[OID_EKU_MICROSOFT_DRM] = ExtKeyUsageMicrosoftDrm + ekuConstants[OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION] = ExtKeyUsageMicrosoftDrmIndividualization + ekuConstants[OID_EKU_MICROSOFT_LICENSES] = ExtKeyUsageMicrosoftLicenses + ekuConstants[OID_EKU_MICROSOFT_LICENSE_SERVER] = ExtKeyUsageMicrosoftLicenseServer + ekuConstants[OID_EKU_MICROSOFT_ENROLLMENT_AGENT] = ExtKeyUsageMicrosoftEnrollmentAgent + ekuConstants[OID_EKU_MICROSOFT_SMARTCARD_LOGON] = ExtKeyUsageMicrosoftSmartcardLogon + ekuConstants[OID_EKU_MICROSOFT_CA_EXCHANGE] = ExtKeyUsageMicrosoftCaExchange + ekuConstants[OID_EKU_MICROSOFT_KEY_RECOVERY_21] = ExtKeyUsageMicrosoftKeyRecovery21 + ekuConstants[OID_EKU_MICROSOFT_SYSTEM_HEALTH] = ExtKeyUsageMicrosoftSystemHealth + ekuConstants[OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE] = ExtKeyUsageMicrosoftSystemHealthLoophole + ekuConstants[OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING] = ExtKeyUsageMicrosoftKernelModeCodeSigning + ekuConstants[OID_EKU_SERVER_AUTH] = ExtKeyUsageServerAuth + ekuConstants[OID_EKU_DVCS] = ExtKeyUsageDvcs + ekuConstants[OID_EKU_SBGP_CERT_AA_SERVICE_AUTH] = ExtKeyUsageSbgpCertAaServiceAuth + ekuConstants[OID_EKU_EAP_OVER_PPP] = ExtKeyUsageEapOverPpp + ekuConstants[OID_EKU_EAP_OVER_LAN] = ExtKeyUsageEapOverLan + ekuConstants[OID_EKU_CLIENT_AUTH] = ExtKeyUsageClientAuth + ekuConstants[OID_EKU_CODE_SIGNING] = ExtKeyUsageCodeSigning + ekuConstants[OID_EKU_EMAIL_PROTECTION] = ExtKeyUsageEmailProtection + ekuConstants[OID_EKU_IPSEC_END_SYSTEM] = ExtKeyUsageIpsecEndSystem + ekuConstants[OID_EKU_IPSEC_TUNNEL] = ExtKeyUsageIpsecTunnel + ekuConstants[OID_EKU_IPSEC_USER] = ExtKeyUsageIpsecUser + ekuConstants[OID_EKU_TIME_STAMPING] = ExtKeyUsageTimeStamping + ekuConstants[OID_EKU_OCSP_SIGNING] = ExtKeyUsageOcspSigning + ekuConstants[OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE] = ExtKeyUsageIpsecIntermediateSystemUsage + ekuConstants[OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO] = ExtKeyUsageNetscapeServerGatedCrypto + ekuConstants[OID_EKU_ANY] = ExtKeyUsageAny +} diff --git a/vendor/github.com/zmap/zcrypto/x509/extended_key_usage_schema.sh b/vendor/github.com/zmap/zcrypto/x509/extended_key_usage_schema.sh new file mode 100644 index 0000000000..b8811911e0 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/extended_key_usage_schema.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +# TODO: This should really be generated by Go code as a subrecord, but +# importing in Python is hard. This is quick and dirty. + +FIELDS=$(\ + cat extended_key_usage.go |\ + grep json |\ + cut -d ':' -f 2 |\ + sed 's|,omitempty||g' |\ + tr -d '`') +echo "extended_key_usage = SubRecord({" +for f in $FIELDS; do + if [ $f == "\"unknown\"" ]; then + echo " $f: ListOf(OID())" + else + echo " $f: Boolean()," + fi +done +echo "})" diff --git a/vendor/github.com/zmap/zcrypto/x509/extensions.go b/vendor/github.com/zmap/zcrypto/x509/extensions.go new file mode 100644 index 0000000000..3c15216e3f --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/extensions.go @@ -0,0 +1,818 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "encoding/asn1" + "encoding/hex" + "encoding/json" + "net" + "strconv" + "strings" + + "github.com/zmap/zcrypto/x509/ct" + "github.com/zmap/zcrypto/x509/pkix" +) + +var ( + oidExtKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15} + oidExtBasicConstraints = asn1.ObjectIdentifier{2, 5, 29, 19} + oidExtSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17} + oidExtIssuerAltName = asn1.ObjectIdentifier{2, 5, 29, 18} + oidExtNameConstraints = asn1.ObjectIdentifier{2, 5, 29, 30} + oidCRLDistributionPoints = asn1.ObjectIdentifier{2, 5, 29, 31} + oidExtAuthKeyId = asn1.ObjectIdentifier{2, 5, 29, 35} + oidExtSubjectKeyId = asn1.ObjectIdentifier{2, 5, 29, 14} + oidExtExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37} + oidExtCertificatePolicy = asn1.ObjectIdentifier{2, 5, 29, 32} + + oidExtAuthorityInfoAccess = oidExtensionAuthorityInfoAccess + oidExtensionCTPrecertificatePoison = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3} + oidExtSignedCertificateTimestampList = oidExtensionSignedCertificateTimestampList + + oidExtCABFOrganizationID = asn1.ObjectIdentifier{2, 23, 140, 3, 1} + oidExtQCStatements = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3} +) + +type CertificateExtensions struct { + KeyUsage KeyUsage `json:"key_usage,omitempty"` + BasicConstraints *BasicConstraints `json:"basic_constraints,omitempty"` + SubjectAltName *GeneralNames `json:"subject_alt_name,omitempty"` + IssuerAltName *GeneralNames `json:"issuer_alt_name,omitempty"` + NameConstraints *NameConstraints `json:"name_constraints,omitempty"` + CRLDistributionPoints CRLDistributionPoints `json:"crl_distribution_points,omitempty"` + AuthKeyID SubjAuthKeyId `json:"authority_key_id,omitempty"` + SubjectKeyID SubjAuthKeyId `json:"subject_key_id,omitempty"` + ExtendedKeyUsage *ExtendedKeyUsageExtension `json:"extended_key_usage,omitempty"` + CertificatePolicies *CertificatePoliciesData `json:"certificate_policies,omitempty"` + AuthorityInfoAccess *AuthorityInfoAccess `json:"authority_info_access,omitempty"` + IsPrecert IsPrecert `json:"ct_poison,omitempty"` + SignedCertificateTimestampList []*ct.SignedCertificateTimestamp `json:"signed_certificate_timestamps,omitempty"` + TorServiceDescriptors []*TorServiceDescriptorHash `json:"tor_service_descriptors,omitempty"` + CABFOrganizationIdentifier *CABFOrganizationIdentifier `json:"cabf_organization_id,omitempty"` + QCStatements *QCStatements `json:"qc_statements,omitempty"` +} + +type UnknownCertificateExtensions []pkix.Extension + +type IsPrecert bool + +type BasicConstraints struct { + IsCA bool `json:"is_ca"` + MaxPathLen *int `json:"max_path_len,omitempty"` +} + +type NoticeReference struct { + Organization string `json:"organization,omitempty"` + NoticeNumbers NoticeNumber `json:"notice_numbers,omitempty"` +} + +type UserNoticeData struct { + ExplicitText string `json:"explicit_text,omitempty"` + NoticeReference []NoticeReference `json:"notice_reference,omitempty"` +} + +type CertificatePoliciesJSON struct { + PolicyIdentifier string `json:"id,omitempty"` + CPSUri []string `json:"cps,omitempty"` + UserNotice []UserNoticeData `json:"user_notice,omitempty"` +} + +type CertificatePolicies []CertificatePoliciesJSON + +type CertificatePoliciesData struct { + PolicyIdentifiers []asn1.ObjectIdentifier + QualifierId [][]asn1.ObjectIdentifier + CPSUri [][]string + ExplicitTexts [][]string + NoticeRefOrganization [][]string + NoticeRefNumbers [][]NoticeNumber +} + +func (cp *CertificatePoliciesData) MarshalJSON() ([]byte, error) { + policies := CertificatePolicies{} + for idx, oid := range cp.PolicyIdentifiers { + cpsJSON := CertificatePoliciesJSON{} + cpsJSON.PolicyIdentifier = oid.String() + for _, uri := range cp.CPSUri[idx] { + cpsJSON.CPSUri = append(cpsJSON.CPSUri, uri) + } + + for idx2, explicit_text := range cp.ExplicitTexts[idx] { + uNoticeData := UserNoticeData{} + uNoticeData.ExplicitText = explicit_text + noticeRef := NoticeReference{} + if len(cp.NoticeRefOrganization[idx]) > 0 { + organization := cp.NoticeRefOrganization[idx][idx2] + noticeRef.Organization = organization + noticeRef.NoticeNumbers = cp.NoticeRefNumbers[idx][idx2] + uNoticeData.NoticeReference = append(uNoticeData.NoticeReference, noticeRef) + } + cpsJSON.UserNotice = append(cpsJSON.UserNotice, uNoticeData) + } + + policies = append(policies, cpsJSON) + } + return json.Marshal(policies) +} + +// GeneralNames corresponds an X.509 GeneralName defined in +// Section 4.2.1.6 of RFC 5280. +// +// GeneralName ::= CHOICE { +// otherName [0] AnotherName, +// rfc822Name [1] IA5String, +// dNSName [2] IA5String, +// x400Address [3] ORAddress, +// directoryName [4] Name, +// ediPartyName [5] EDIPartyName, +// uniformResourceIdentifier [6] IA5String, +// iPAddress [7] OCTET STRING, +// registeredID [8] OBJECT IDENTIFIER } +type GeneralNames struct { + DirectoryNames []pkix.Name + DNSNames []string + EDIPartyNames []pkix.EDIPartyName + EmailAddresses []string + IPAddresses []net.IP + OtherNames []pkix.OtherName + RegisteredIDs []asn1.ObjectIdentifier + URIs []string +} + +type jsonGeneralNames struct { + DirectoryNames []pkix.Name `json:"directory_names,omitempty"` + DNSNames []string `json:"dns_names,omitempty"` + EDIPartyNames []pkix.EDIPartyName `json:"edi_party_names,omitempty"` + EmailAddresses []string `json:"email_addresses,omitempty"` + IPAddresses []net.IP `json:"ip_addresses,omitempty"` + OtherNames []pkix.OtherName `json:"other_names,omitempty"` + RegisteredIDs []string `json:"registered_ids,omitempty"` + URIs []string `json:"uniform_resource_identifiers,omitempty"` +} + +func (gn *GeneralNames) MarshalJSON() ([]byte, error) { + jsan := jsonGeneralNames{ + DirectoryNames: gn.DirectoryNames, + DNSNames: gn.DNSNames, + EDIPartyNames: gn.EDIPartyNames, + EmailAddresses: gn.EmailAddresses, + IPAddresses: gn.IPAddresses, + OtherNames: gn.OtherNames, + RegisteredIDs: make([]string, 0, len(gn.RegisteredIDs)), + URIs: gn.URIs, + } + for _, id := range gn.RegisteredIDs { + jsan.RegisteredIDs = append(jsan.RegisteredIDs, id.String()) + } + return json.Marshal(jsan) +} + +func (gn *GeneralNames) UnmarshalJSON(b []byte) error { + var jsan jsonGeneralNames + err := json.Unmarshal(b, &jsan) + if err != nil { + return err + } + + gn.DirectoryNames = jsan.DirectoryNames + gn.DNSNames = jsan.DNSNames + gn.EDIPartyNames = jsan.EDIPartyNames + gn.EmailAddresses = jsan.EmailAddresses + gn.IPAddresses = jsan.IPAddresses + gn.OtherNames = jsan.OtherNames + gn.RegisteredIDs = make([]asn1.ObjectIdentifier, len(jsan.RegisteredIDs)) + gn.URIs = jsan.URIs + + for i, rID := range jsan.RegisteredIDs { + arcs := strings.Split(rID, ".") + oid := make(asn1.ObjectIdentifier, len(arcs)) + + for j, s := range arcs { + tmp, err := strconv.ParseInt(s, 10, 32) + if err != nil { + return err + } + oid[j] = int(tmp) + } + gn.RegisteredIDs[i] = oid + } + return nil +} + +// TODO: Handle excluded names + +type NameConstraints struct { + Critical bool `json:"critical"` + + PermittedDNSNames []GeneralSubtreeString + PermittedEmailAddresses []GeneralSubtreeString + PermittedURIs []GeneralSubtreeString + PermittedIPAddresses []GeneralSubtreeIP + PermittedDirectoryNames []GeneralSubtreeName + PermittedEdiPartyNames []GeneralSubtreeEdi + PermittedRegisteredIDs []GeneralSubtreeOid + + ExcludedEmailAddresses []GeneralSubtreeString + ExcludedDNSNames []GeneralSubtreeString + ExcludedURIs []GeneralSubtreeString + ExcludedIPAddresses []GeneralSubtreeIP + ExcludedDirectoryNames []GeneralSubtreeName + ExcludedEdiPartyNames []GeneralSubtreeEdi + ExcludedRegisteredIDs []GeneralSubtreeOid +} + +type NameConstraintsJSON struct { + Critical bool `json:"critical"` + + PermittedDNSNames []string `json:"permitted_names,omitempty"` + PermittedEmailAddresses []string `json:"permitted_email_addresses,omitempty"` + PermittedURIs []string `json:"permitted_uris,omitempty"` + PermittedIPAddresses []GeneralSubtreeIP `json:"permitted_ip_addresses,omitempty"` + PermittedDirectoryNames []pkix.Name `json:"permitted_directory_names,omitempty"` + PermittedEdiPartyNames []pkix.EDIPartyName `json:"permitted_edi_party_names,omitempty"` + PermittedRegisteredIDs []string `json:"permitted_registred_id,omitempty"` + + ExcludedDNSNames []string `json:"excluded_names,omitempty"` + ExcludedEmailAddresses []string `json:"excluded_email_addresses,omitempty"` + ExcludedURIs []string `json:"excluded_uris,omitempty"` + ExcludedIPAddresses []GeneralSubtreeIP `json:"excluded_ip_addresses,omitempty"` + ExcludedDirectoryNames []pkix.Name `json:"excluded_directory_names,omitempty"` + ExcludedEdiPartyNames []pkix.EDIPartyName `json:"excluded_edi_party_names,omitempty"` + ExcludedRegisteredIDs []string `json:"excluded_registred_id,omitempty"` +} + +func (nc *NameConstraints) UnmarshalJSON(b []byte) error { + var ncJson NameConstraintsJSON + err := json.Unmarshal(b, &ncJson) + if err != nil { + return err + } + for _, dns := range ncJson.PermittedDNSNames { + nc.PermittedDNSNames = append(nc.PermittedDNSNames, GeneralSubtreeString{Data: dns}) + } + for _, email := range ncJson.PermittedEmailAddresses { + nc.PermittedEmailAddresses = append(nc.PermittedEmailAddresses, GeneralSubtreeString{Data: email}) + } + for _, uri := range ncJson.PermittedURIs { + nc.PermittedURIs = append(nc.PermittedURIs, GeneralSubtreeString{Data: uri}) + } + for _, constraint := range ncJson.PermittedIPAddresses { + nc.PermittedIPAddresses = append(nc.PermittedIPAddresses, constraint) + } + for _, directory := range ncJson.PermittedDirectoryNames { + nc.PermittedDirectoryNames = append(nc.PermittedDirectoryNames, GeneralSubtreeName{Data: directory}) + } + for _, edi := range ncJson.PermittedEdiPartyNames { + nc.PermittedEdiPartyNames = append(nc.PermittedEdiPartyNames, GeneralSubtreeEdi{Data: edi}) + } + for _, id := range ncJson.PermittedRegisteredIDs { + arcs := strings.Split(id, ".") + oid := make(asn1.ObjectIdentifier, len(arcs)) + + for j, s := range arcs { + tmp, err := strconv.ParseInt(s, 10, 32) + if err != nil { + return err + } + oid[j] = int(tmp) + } + nc.PermittedRegisteredIDs = append(nc.PermittedRegisteredIDs, GeneralSubtreeOid{Data: oid}) + } + + for _, dns := range ncJson.ExcludedDNSNames { + nc.ExcludedDNSNames = append(nc.ExcludedDNSNames, GeneralSubtreeString{Data: dns}) + } + for _, email := range ncJson.ExcludedEmailAddresses { + nc.ExcludedEmailAddresses = append(nc.ExcludedEmailAddresses, GeneralSubtreeString{Data: email}) + } + for _, uri := range ncJson.ExcludedURIs { + nc.ExcludedURIs = append(nc.ExcludedURIs, GeneralSubtreeString{Data: uri}) + } + for _, constraint := range ncJson.ExcludedIPAddresses { + nc.ExcludedIPAddresses = append(nc.ExcludedIPAddresses, constraint) + } + for _, directory := range ncJson.ExcludedDirectoryNames { + nc.ExcludedDirectoryNames = append(nc.ExcludedDirectoryNames, GeneralSubtreeName{Data: directory}) + } + for _, edi := range ncJson.ExcludedEdiPartyNames { + nc.ExcludedEdiPartyNames = append(nc.ExcludedEdiPartyNames, GeneralSubtreeEdi{Data: edi}) + } + for _, id := range ncJson.ExcludedRegisteredIDs { + arcs := strings.Split(id, ".") + oid := make(asn1.ObjectIdentifier, len(arcs)) + + for j, s := range arcs { + tmp, err := strconv.ParseInt(s, 10, 32) + if err != nil { + return err + } + oid[j] = int(tmp) + } + nc.ExcludedRegisteredIDs = append(nc.ExcludedRegisteredIDs, GeneralSubtreeOid{Data: oid}) + } + return nil +} + +func (nc NameConstraints) MarshalJSON() ([]byte, error) { + var out NameConstraintsJSON + for _, dns := range nc.PermittedDNSNames { + out.PermittedDNSNames = append(out.PermittedDNSNames, dns.Data) + } + for _, email := range nc.PermittedEmailAddresses { + out.PermittedEmailAddresses = append(out.PermittedEmailAddresses, email.Data) + } + for _, uri := range nc.PermittedURIs { + out.PermittedURIs = append(out.PermittedURIs, uri.Data) + } + out.PermittedIPAddresses = nc.PermittedIPAddresses + for _, directory := range nc.PermittedDirectoryNames { + out.PermittedDirectoryNames = append(out.PermittedDirectoryNames, directory.Data) + } + for _, edi := range nc.PermittedEdiPartyNames { + out.PermittedEdiPartyNames = append(out.PermittedEdiPartyNames, edi.Data) + } + for _, id := range nc.PermittedRegisteredIDs { + out.PermittedRegisteredIDs = append(out.PermittedRegisteredIDs, id.Data.String()) + } + + for _, dns := range nc.ExcludedDNSNames { + out.ExcludedDNSNames = append(out.ExcludedDNSNames, dns.Data) + } + for _, email := range nc.ExcludedEmailAddresses { + out.ExcludedEmailAddresses = append(out.ExcludedEmailAddresses, email.Data) + } + for _, uri := range nc.ExcludedURIs { + out.ExcludedURIs = append(out.ExcludedURIs, uri.Data) + } + for _, ip := range nc.ExcludedIPAddresses { + out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, ip) + } + for _, directory := range nc.ExcludedDirectoryNames { + out.ExcludedDirectoryNames = append(out.ExcludedDirectoryNames, directory.Data) + } + for _, edi := range nc.ExcludedEdiPartyNames { + out.ExcludedEdiPartyNames = append(out.ExcludedEdiPartyNames, edi.Data) + } + for _, id := range nc.ExcludedRegisteredIDs { + out.ExcludedRegisteredIDs = append(out.ExcludedRegisteredIDs, id.Data.String()) + } + return json.Marshal(out) +} + +type CRLDistributionPoints []string + +type SubjAuthKeyId []byte + +func (kid SubjAuthKeyId) MarshalJSON() ([]byte, error) { + enc := hex.EncodeToString(kid) + return json.Marshal(enc) +} + +type ExtendedKeyUsage []ExtKeyUsage + +type ExtendedKeyUsageExtension struct { + Known ExtendedKeyUsage + Unknown []asn1.ObjectIdentifier +} + +// MarshalJSON implements the json.Marshal interface. The output is a struct of +// bools, with an additional `Value` field containing the actual OIDs. +func (e *ExtendedKeyUsageExtension) MarshalJSON() ([]byte, error) { + aux := new(auxExtendedKeyUsage) + for _, e := range e.Known { + aux.populateFromExtKeyUsage(e) + } + for _, oid := range e.Unknown { + aux.Unknown = append(aux.Unknown, oid.String()) + } + return json.Marshal(aux) +} + +func (e *ExtendedKeyUsageExtension) UnmarshalJSON(b []byte) error { + aux := new(auxExtendedKeyUsage) + if err := json.Unmarshal(b, aux); err != nil { + return err + } + // TODO: Generate the reverse functions. + return nil +} + +//go:generate go run extended_key_usage_gen.go + +// The string functions for CertValidationLevel are auto-generated via +// `go generate ` or running `go generate` in the package directory +//go:generate stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go +type CertValidationLevel int + +const ( + UnknownValidationLevel CertValidationLevel = 0 + DV CertValidationLevel = 1 + OV CertValidationLevel = 2 + EV CertValidationLevel = 3 +) + +func (c *CertValidationLevel) MarshalJSON() ([]byte, error) { + if *c == UnknownValidationLevel || *c < 0 || *c > EV { + return json.Marshal("unknown") + } + return json.Marshal(c.String()) +} + +// TODO: All of validation-level maps should be auto-generated from +// https://github.com/zmap/constants. + +// ExtendedValidationOIDs contains the UNION of Chromium +// (https://chromium.googlesource.com/chromium/src/net/+/master/cert/ev_root_ca_metadata.cc) +// and Firefox +// (http://hg.mozilla.org/mozilla-central/file/tip/security/certverifier/ExtendedValidation.cpp) +// EV OID lists +var ExtendedValidationOIDs = map[string]interface{}{ + // CA/Browser Forum EV OID standard + // https://cabforum.org/object-registry/ + "2.23.140.1.1": nil, + // CA/Browser Forum EV Code Signing + "2.23.140.1.3": nil, + // CA/Browser Forum .onion EV Certs + "2.23.140.1.31": nil, + // AC Camerfirma S.A. Chambers of Commerce Root - 2008 + // https://www.camerfirma.com + // AC Camerfirma uses the last two arcs to track how the private key + // is managed - the effective verification policy is the same. + "1.3.6.1.4.1.17326.10.14.2.1.2": nil, + "1.3.6.1.4.1.17326.10.14.2.2.2": nil, + // AC Camerfirma S.A. Global Chambersign Root - 2008 + // https://server2.camerfirma.com:8082 + // AC Camerfirma uses the last two arcs to track how the private key + // is managed - the effective verification policy is the same. + "1.3.6.1.4.1.17326.10.8.12.1.2": nil, + "1.3.6.1.4.1.17326.10.8.12.2.2": nil, + // Actalis Authentication Root CA + // https://ssltest-a.actalis.it:8443 + "1.3.159.1.17.1": nil, + // AffirmTrust Commercial + // https://commercial.affirmtrust.com/ + "1.3.6.1.4.1.34697.2.1": nil, + // AffirmTrust Networking + // https://networking.affirmtrust.com:4431 + "1.3.6.1.4.1.34697.2.2": nil, + // AffirmTrust Premium + // https://premium.affirmtrust.com:4432/ + "1.3.6.1.4.1.34697.2.3": nil, + // AffirmTrust Premium ECC + // https://premiumecc.affirmtrust.com:4433/ + "1.3.6.1.4.1.34697.2.4": nil, + // Autoridad de Certificacion Firmaprofesional CIF A62634068 + // https://publifirma.firmaprofesional.com/ + "1.3.6.1.4.1.13177.10.1.3.10": nil, + // Buypass Class 3 CA 1 + // https://valid.evident.ca13.ssl.buypass.no/ + "2.16.578.1.26.1.3.3": nil, + // Certification Authority of WoSign + // CA 沃通根证书 + // https://root2evtest.wosign.com/ + "1.3.6.1.4.1.36305.2": nil, + // CertPlus Class 2 Primary CA (KEYNECTIS) + // https://www.keynectis.com/ + "1.3.6.1.4.1.22234.2.5.2.3.1": nil, + // Certum Trusted Network CA + // https://juice.certum.pl/ + "1.2.616.1.113527.2.5.1.1": nil, + // China Internet Network Information Center EV Certificates Root + // https://evdemo.cnnic.cn/ + "1.3.6.1.4.1.29836.1.10": nil, + // COMODO Certification Authority & USERTrust RSA Certification Authority & UTN-USERFirst-Hardware & AddTrust External CA Root + // https://secure.comodo.com/ + // https://usertrustrsacertificationauthority-ev.comodoca.com/ + // https://addtrustexternalcaroot-ev.comodoca.com + "1.3.6.1.4.1.6449.1.2.1.5.1": nil, + // Cybertrust Global Root & GTE CyberTrust Global Root & Baltimore CyberTrust Root + // https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif + // https://www.cybertrust.ne.jp/ + // https://secure.omniroot.com/repository/ + "1.3.6.1.4.1.6334.1.100.1": nil, + // DigiCert High Assurance EV Root CA + // https://www.digicert.com + "2.16.840.1.114412.2.1": nil, + // D-TRUST Root Class 3 CA 2 EV 2009 + // https://certdemo-ev-valid.ssl.d-trust.net/ + "1.3.6.1.4.1.4788.2.202.1": nil, + // Entrust.net Secure Server Certification Authority + // https://www.entrust.net/ + "2.16.840.1.114028.10.1.2": nil, + // E-Tugra Certification Authority + // https://sslev.e-tugra.com.tr + "2.16.792.3.0.4.1.1.4": nil, + // GeoTrust Primary Certification Authority + // https://www.geotrust.com/ + "1.3.6.1.4.1.14370.1.6": nil, + // GlobalSign Root CA - R2 + // https://www.globalsign.com/ + "1.3.6.1.4.1.4146.1.1": nil, + // Go Daddy Class 2 Certification Authority & Go Daddy Root Certificate Authority - G2 + // https://www.godaddy.com/ + // https://valid.gdig2.catest.godaddy.com/ + "2.16.840.1.114413.1.7.23.3": nil, + // Izenpe.com - SHA256 root + // The first OID is for businesses and the second for government entities. + // These are the test sites, respectively: + // https://servicios.izenpe.com + // https://servicios1.izenpe.com + // Windows XP finds this, SHA1, root instead. The policy OIDs are the same + // as for the SHA256 root, above. + "1.3.6.1.4.1.14777.6.1.1": nil, + "1.3.6.1.4.1.14777.6.1.2": nil, + // Network Solutions Certificate Authority + // https://www.networksolutions.com/website-packages/index.jsp + "1.3.6.1.4.1.782.1.2.1.8.1": nil, + // QuoVadis Root CA 2 + // https://www.quovadis.bm/ + "1.3.6.1.4.1.8024.0.2.100.1.2": nil, + // SecureTrust CA, SecureTrust Corporation + // https://www.securetrust.com + // https://www.trustwave.com/ + "2.16.840.1.114404.1.1.2.4.1": nil, + // Security Communication RootCA1 + // https://www.secomtrust.net/contact/form.html + "1.2.392.200091.100.721.1": nil, + // Staat der Nederlanden EV Root CA + // https://pkioevssl-v.quovadisglobal.com/ + "2.16.528.1.1003.1.2.7": nil, + // StartCom Certification Authority + // https://www.startssl.com/ + "1.3.6.1.4.1.23223.1.1.1": nil, + // Starfield Class 2 Certification Authority + // https://www.starfieldtech.com/ + "2.16.840.1.114414.1.7.23.3": nil, + // Starfield Services Root Certificate Authority - G2 + // https://valid.sfsg2.catest.starfieldtech.com/ + "2.16.840.1.114414.1.7.24.3": nil, + // SwissSign Gold CA - G2 + // https://testevg2.swisssign.net/ + "2.16.756.1.89.1.2.1.1": nil, + // Swisscom Root EV CA 2 + // https://test-quarz-ev-ca-2.pre.swissdigicert.ch + "2.16.756.1.83.21.0": nil, + // thawte Primary Root CA + // https://www.thawte.com/ + "2.16.840.1.113733.1.7.48.1": nil, + // TWCA Global Root CA + // https://evssldemo3.twca.com.tw/index.html + "1.3.6.1.4.1.40869.1.1.22.3": nil, + // T-TeleSec GlobalRoot Class 3 + // http://www.telesec.de/ / https://root-class3.test.telesec.de/ + "1.3.6.1.4.1.7879.13.24.1": nil, + // VeriSign Class 3 Public Primary Certification Authority - G5 + // https://www.verisign.com/ + "2.16.840.1.113733.1.7.23.6": nil, + // Wells Fargo WellsSecure Public Root Certificate Authority + // https://nerys.wellsfargo.com/test.html + "2.16.840.1.114171.500.9": nil, + // CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN + // https://www.cfca.com.cn/ + "2.16.156.112554.3": nil, + // CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH + // https://www.wisekey.com/repository/cacertificates/ + "2.16.756.5.14.7.4.8": nil, + // CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6,O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A...,L=Ankara,C=TR + // https://www.turktrust.com.tr/ + "2.16.792.3.0.3.1.1.5": nil, +} + +// OrganizationValidationOIDs contains CA specific OV OIDs from +// https://cabforum.org/object-registry/ +var OrganizationValidationOIDs = map[string]interface{}{ + // CA/Browser Forum OV OID standard + // https://cabforum.org/object-registry/ + "2.23.140.1.2.2": nil, + // CA/Browser Forum individually validated + "2.23.140.1.2.3": nil, + // Digicert + "2.16.840.1.114412.1.1": nil, + // D-Trust + "1.3.6.1.4.1.4788.2.200.1": nil, + // GoDaddy + "2.16.840.1.114413.1.7.23.2": nil, + // Logius + "2.16.528.1.1003.1.2.5.6": nil, + // QuoVadis + "1.3.6.1.4.1.8024.0.2.100.1.1": nil, + // Starfield + "2.16.840.1.114414.1.7.23.2": nil, + // TurkTrust + "2.16.792.3.0.3.1.1.2": nil, +} + +// DomainValidationOIDs contain OIDs that identify DV certs. +var DomainValidationOIDs = map[string]interface{}{ + // Globalsign + "1.3.6.1.4.1.4146.1.10.10": nil, + // Let's Encrypt + "1.3.6.1.4.1.44947.1.1.1": nil, + // Comodo (eNom) + "1.3.6.1.4.1.6449.1.2.2.10": nil, + // Comodo (WoTrust) + "1.3.6.1.4.1.6449.1.2.2.15": nil, + // Comodo (RBC SOFT) + "1.3.6.1.4.1.6449.1.2.2.16": nil, + // Comodo (RegisterFly) + "1.3.6.1.4.1.6449.1.2.2.17": nil, + // Comodo (Central Security Patrols) + "1.3.6.1.4.1.6449.1.2.2.18": nil, + // Comodo (eBiz Networks) + "1.3.6.1.4.1.6449.1.2.2.19": nil, + // Comodo (OptimumSSL) + "1.3.6.1.4.1.6449.1.2.2.21": nil, + // Comodo (WoSign) + "1.3.6.1.4.1.6449.1.2.2.22": nil, + // Comodo (Register.com) + "1.3.6.1.4.1.6449.1.2.2.24": nil, + // Comodo (The Code Project) + "1.3.6.1.4.1.6449.1.2.2.25": nil, + // Comodo (Gandi) + "1.3.6.1.4.1.6449.1.2.2.26": nil, + // Comodo (GlobeSSL) + "1.3.6.1.4.1.6449.1.2.2.27": nil, + // Comodo (DreamHost) + "1.3.6.1.4.1.6449.1.2.2.28": nil, + // Comodo (TERENA) + "1.3.6.1.4.1.6449.1.2.2.29": nil, + // Comodo (GlobalSSL) + "1.3.6.1.4.1.6449.1.2.2.31": nil, + // Comodo (IceWarp) + "1.3.6.1.4.1.6449.1.2.2.35": nil, + // Comodo (Dotname Korea) + "1.3.6.1.4.1.6449.1.2.2.37": nil, + // Comodo (TrustSign) + "1.3.6.1.4.1.6449.1.2.2.38": nil, + // Comodo (Formidable) + "1.3.6.1.4.1.6449.1.2.2.39": nil, + // Comodo (SSL Blindado) + "1.3.6.1.4.1.6449.1.2.2.40": nil, + // Comodo (Dreamscape Networks) + "1.3.6.1.4.1.6449.1.2.2.41": nil, + // Comodo (K Software) + "1.3.6.1.4.1.6449.1.2.2.42": nil, + // Comodo (FBS) + "1.3.6.1.4.1.6449.1.2.2.44": nil, + // Comodo (ReliaSite) + "1.3.6.1.4.1.6449.1.2.2.45": nil, + // Comodo (CertAssure) + "1.3.6.1.4.1.6449.1.2.2.47": nil, + // Comodo (TrustAsia) + "1.3.6.1.4.1.6449.1.2.2.49": nil, + // Comodo (SecureCore) + "1.3.6.1.4.1.6449.1.2.2.50": nil, + // Comodo (Western Digital) + "1.3.6.1.4.1.6449.1.2.2.51": nil, + // Comodo (cPanel) + "1.3.6.1.4.1.6449.1.2.2.52": nil, + // Comodo (BlackCert) + "1.3.6.1.4.1.6449.1.2.2.53": nil, + // Comodo (KeyNet Systems) + "1.3.6.1.4.1.6449.1.2.2.54": nil, + // Comodo + "1.3.6.1.4.1.6449.1.2.2.7": nil, + // Comodo (CSC) + "1.3.6.1.4.1.6449.1.2.2.8": nil, + // Digicert + "2.16.840.1.114412.1.2": nil, + // GoDaddy + "2.16.840.1.114413.1.7.23.1": nil, + // Starfield + "2.16.840.1.114414.1.7.23.1": nil, + // CA/B Forum + "2.23.140.1.2.1": nil, +} + +// TODO pull out other types +type AuthorityInfoAccess struct { + OCSPServer []string `json:"ocsp_urls,omitempty"` + IssuingCertificateURL []string `json:"issuer_urls,omitempty"` +} + +/* + id-CABFOrganizationIdentifier OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) international-organizations(23) ca-browser-forum(140) certificate-extensions(3) cabf-organization-identifier(1) } + + ext-CABFOrganizationIdentifier EXTENSION ::= { SYNTAX CABFOrganizationIdentifier IDENTIFIED BY id-CABFOrganizationIdentifier } + + CABFOrganizationIdentifier ::= SEQUENCE { + + registrationSchemeIdentifier PrintableString (SIZE(3)), + + registrationCountry PrintableString (SIZE(2)), + + registrationStateOrProvince [0] IMPLICIT PrintableString OPTIONAL (SIZE(0..128)), + + registrationReference UTF8String + + } +*/ +type CABFOrganizationIDASN struct { + RegistrationSchemeIdentifier string `asn1:"printable"` + RegistrationCountry string `asn1:"printable"` + RegistrationStateOrProvince string `asn1:"printable,optional,tag:0"` + RegistrationReference string `asn1:"utf8"` +} + +type CABFOrganizationIdentifier struct { + Scheme string `json:"scheme,omitempty"` + Country string `json:"country,omitempty"` + State string `json:"state,omitempty"` + Reference string `json:"reference,omitempty"` +} + +func (c *Certificate) jsonifyExtensions() (*CertificateExtensions, UnknownCertificateExtensions) { + exts := new(CertificateExtensions) + unk := make([]pkix.Extension, 0, 2) + for _, e := range c.Extensions { + if e.Id.Equal(oidExtKeyUsage) { + exts.KeyUsage = c.KeyUsage + } else if e.Id.Equal(oidExtBasicConstraints) { + exts.BasicConstraints = new(BasicConstraints) + exts.BasicConstraints.IsCA = c.IsCA + if c.MaxPathLen > 0 || c.MaxPathLenZero { + exts.BasicConstraints.MaxPathLen = new(int) + *exts.BasicConstraints.MaxPathLen = c.MaxPathLen + } + } else if e.Id.Equal(oidExtSubjectAltName) { + exts.SubjectAltName = new(GeneralNames) + exts.SubjectAltName.DirectoryNames = c.DirectoryNames + exts.SubjectAltName.DNSNames = c.DNSNames + exts.SubjectAltName.EDIPartyNames = c.EDIPartyNames + exts.SubjectAltName.EmailAddresses = c.EmailAddresses + exts.SubjectAltName.IPAddresses = c.IPAddresses + exts.SubjectAltName.OtherNames = c.OtherNames + exts.SubjectAltName.RegisteredIDs = c.RegisteredIDs + exts.SubjectAltName.URIs = c.URIs + } else if e.Id.Equal(oidExtIssuerAltName) { + exts.IssuerAltName = new(GeneralNames) + exts.IssuerAltName.DirectoryNames = c.IANDirectoryNames + exts.IssuerAltName.DNSNames = c.IANDNSNames + exts.IssuerAltName.EDIPartyNames = c.IANEDIPartyNames + exts.IssuerAltName.EmailAddresses = c.IANEmailAddresses + exts.IssuerAltName.IPAddresses = c.IANIPAddresses + exts.IssuerAltName.OtherNames = c.IANOtherNames + exts.IssuerAltName.RegisteredIDs = c.IANRegisteredIDs + exts.IssuerAltName.URIs = c.IANURIs + } else if e.Id.Equal(oidExtNameConstraints) { + exts.NameConstraints = new(NameConstraints) + exts.NameConstraints.Critical = c.NameConstraintsCritical + + exts.NameConstraints.PermittedDNSNames = c.PermittedDNSNames + exts.NameConstraints.PermittedEmailAddresses = c.PermittedEmailAddresses + exts.NameConstraints.PermittedURIs = c.PermittedURIs + exts.NameConstraints.PermittedIPAddresses = c.PermittedIPAddresses + exts.NameConstraints.PermittedDirectoryNames = c.PermittedDirectoryNames + exts.NameConstraints.PermittedEdiPartyNames = c.PermittedEdiPartyNames + exts.NameConstraints.PermittedRegisteredIDs = c.PermittedRegisteredIDs + + exts.NameConstraints.ExcludedEmailAddresses = c.ExcludedEmailAddresses + exts.NameConstraints.ExcludedDNSNames = c.ExcludedDNSNames + exts.NameConstraints.ExcludedURIs = c.ExcludedURIs + exts.NameConstraints.ExcludedIPAddresses = c.ExcludedIPAddresses + exts.NameConstraints.ExcludedDirectoryNames = c.ExcludedDirectoryNames + exts.NameConstraints.ExcludedEdiPartyNames = c.ExcludedEdiPartyNames + exts.NameConstraints.ExcludedRegisteredIDs = c.ExcludedRegisteredIDs + } else if e.Id.Equal(oidCRLDistributionPoints) { + exts.CRLDistributionPoints = c.CRLDistributionPoints + } else if e.Id.Equal(oidExtAuthKeyId) { + exts.AuthKeyID = c.AuthorityKeyId + } else if e.Id.Equal(oidExtExtendedKeyUsage) { + exts.ExtendedKeyUsage = new(ExtendedKeyUsageExtension) + exts.ExtendedKeyUsage.Known = c.ExtKeyUsage + exts.ExtendedKeyUsage.Unknown = c.UnknownExtKeyUsage + } else if e.Id.Equal(oidExtCertificatePolicy) { + exts.CertificatePolicies = new(CertificatePoliciesData) + exts.CertificatePolicies.PolicyIdentifiers = c.PolicyIdentifiers + exts.CertificatePolicies.NoticeRefNumbers = c.NoticeRefNumbers + exts.CertificatePolicies.NoticeRefOrganization = c.ParsedNoticeRefOrganization + exts.CertificatePolicies.ExplicitTexts = c.ParsedExplicitTexts + exts.CertificatePolicies.QualifierId = c.QualifierId + exts.CertificatePolicies.CPSUri = c.CPSuri + + } else if e.Id.Equal(oidExtAuthorityInfoAccess) { + exts.AuthorityInfoAccess = new(AuthorityInfoAccess) + exts.AuthorityInfoAccess.OCSPServer = c.OCSPServer + exts.AuthorityInfoAccess.IssuingCertificateURL = c.IssuingCertificateURL + } else if e.Id.Equal(oidExtSubjectKeyId) { + exts.SubjectKeyID = c.SubjectKeyId + } else if e.Id.Equal(oidExtSignedCertificateTimestampList) { + exts.SignedCertificateTimestampList = c.SignedCertificateTimestampList + } else if e.Id.Equal(oidExtensionCTPrecertificatePoison) { + exts.IsPrecert = true + } else if e.Id.Equal(oidBRTorServiceDescriptor) { + exts.TorServiceDescriptors = c.TorServiceDescriptors + } else if e.Id.Equal(oidExtCABFOrganizationID) { + exts.CABFOrganizationIdentifier = c.CABFOrganizationIdentifier + } else if e.Id.Equal(oidExtQCStatements) { + exts.QCStatements = c.QCStatements + } else { + // Unknown extension + unk = append(unk, e) + } + } + return exts, unk +} diff --git a/vendor/github.com/zmap/zcrypto/x509/fingerprint.go b/vendor/github.com/zmap/zcrypto/x509/fingerprint.go new file mode 100644 index 0000000000..e62a701562 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/fingerprint.go @@ -0,0 +1,61 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "encoding/json" +) + +// CertificateFingerprint represents a digest/fingerprint of some data. It can +// easily be encoded to hex and JSON (as a hex string). +type CertificateFingerprint []byte + +// MD5Fingerprint creates a fingerprint of data using the MD5 hash algorithm. +func MD5Fingerprint(data []byte) CertificateFingerprint { + sum := md5.Sum(data) + return sum[:] +} + +// SHA1Fingerprint creates a fingerprint of data using the SHA1 hash algorithm. +func SHA1Fingerprint(data []byte) CertificateFingerprint { + sum := sha1.Sum(data) + return sum[:] +} + +// SHA256Fingerprint creates a fingerprint of data using the SHA256 hash +// algorithm. +func SHA256Fingerprint(data []byte) CertificateFingerprint { + sum := sha256.Sum256(data) + return sum[:] +} + +// SHA512Fingerprint creates a fingerprint of data using the SHA256 hash +// algorithm. +func SHA512Fingerprint(data []byte) CertificateFingerprint { + sum := sha512.Sum512(data) + return sum[:] +} + +// Equal returns true if the fingerprints are bytewise-equal. +func (f CertificateFingerprint) Equal(other CertificateFingerprint) bool { + return bytes.Equal(f, other) +} + +// Hex returns the given fingerprint encoded as a hex string. +func (f CertificateFingerprint) Hex() string { + return hex.EncodeToString(f) +} + +// MarshalJSON implements the json.Marshaler interface, and marshals the +// fingerprint as a hex string. +func (f *CertificateFingerprint) MarshalJSON() ([]byte, error) { + return json.Marshal(f.Hex()) +} diff --git a/vendor/github.com/zmap/zcrypto/x509/generated_certvalidationlevel_string.go b/vendor/github.com/zmap/zcrypto/x509/generated_certvalidationlevel_string.go new file mode 100644 index 0000000000..23cd32a1ed --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/generated_certvalidationlevel_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go"; DO NOT EDIT. + +package x509 + +import "strconv" + +const _CertValidationLevel_name = "UnknownValidationLevelDVOVEV" + +var _CertValidationLevel_index = [...]uint8{0, 22, 24, 26, 28} + +func (i CertValidationLevel) String() string { + if i < 0 || i >= CertValidationLevel(len(_CertValidationLevel_index)-1) { + return "CertValidationLevel(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _CertValidationLevel_name[_CertValidationLevel_index[i]:_CertValidationLevel_index[i+1]] +} diff --git a/vendor/github.com/zmap/zcrypto/x509/json.go b/vendor/github.com/zmap/zcrypto/x509/json.go new file mode 100644 index 0000000000..936f28f3f2 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/json.go @@ -0,0 +1,652 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto/ecdsa" + "crypto/rsa" + "encoding/asn1" + "encoding/json" + "errors" + "net" + "sort" + + "github.com/zmap/zcrypto/dsa" + + "strings" + "time" + + jsonKeys "github.com/zmap/zcrypto/json" + "github.com/zmap/zcrypto/util" + "github.com/zmap/zcrypto/x509/pkix" +) + +var kMinTime, kMaxTime time.Time + +func init() { + var err error + kMinTime, err = time.Parse(time.RFC3339, "1970-01-01T00:00:00Z") + if err != nil { + panic(err) + } + kMaxTime, err = time.Parse(time.RFC3339, "9999-12-31T23:59:59Z") + if err != nil { + panic(err) + } +} + +type auxKeyUsage struct { + DigitalSignature bool `json:"digital_signature,omitempty"` + ContentCommitment bool `json:"content_commitment,omitempty"` + KeyEncipherment bool `json:"key_encipherment,omitempty"` + DataEncipherment bool `json:"data_encipherment,omitempty"` + KeyAgreement bool `json:"key_agreement,omitempty"` + CertificateSign bool `json:"certificate_sign,omitempty"` + CRLSign bool `json:"crl_sign,omitempty"` + EncipherOnly bool `json:"encipher_only,omitempty"` + DecipherOnly bool `json:"decipher_only,omitempty"` + Value uint32 `json:"value"` +} + +// MarshalJSON implements the json.Marshaler interface +func (k KeyUsage) MarshalJSON() ([]byte, error) { + var enc auxKeyUsage + enc.Value = uint32(k) + if k&KeyUsageDigitalSignature > 0 { + enc.DigitalSignature = true + } + if k&KeyUsageContentCommitment > 0 { + enc.ContentCommitment = true + } + if k&KeyUsageKeyEncipherment > 0 { + enc.KeyEncipherment = true + } + if k&KeyUsageDataEncipherment > 0 { + enc.DataEncipherment = true + } + if k&KeyUsageKeyAgreement > 0 { + enc.KeyAgreement = true + } + if k&KeyUsageCertSign > 0 { + enc.CertificateSign = true + } + if k&KeyUsageCRLSign > 0 { + enc.CRLSign = true + } + if k&KeyUsageEncipherOnly > 0 { + enc.EncipherOnly = true + } + if k&KeyUsageDecipherOnly > 0 { + enc.DecipherOnly = true + } + return json.Marshal(&enc) +} + +// UnmarshalJSON implements the json.Unmarshler interface +func (k *KeyUsage) UnmarshalJSON(b []byte) error { + var aux auxKeyUsage + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + // TODO: validate the flags match + v := int(aux.Value) + *k = KeyUsage(v) + return nil +} + +// JSONSignatureAlgorithm is the intermediate type +// used when marshaling a PublicKeyAlgorithm out to JSON. +type JSONSignatureAlgorithm struct { + Name string `json:"name,omitempty"` + OID pkix.AuxOID `json:"oid"` +} + +// MarshalJSON implements the json.Marshaler interface +// MAY NOT PRESERVE ORIGINAL OID FROM CERTIFICATE - +// CONSIDER USING jsonifySignatureAlgorithm INSTEAD! +func (s *SignatureAlgorithm) MarshalJSON() ([]byte, error) { + aux := JSONSignatureAlgorithm{ + Name: s.String(), + } + for _, val := range signatureAlgorithmDetails { + if val.algo == *s { + aux.OID = make([]int, len(val.oid)) + for idx := range val.oid { + aux.OID[idx] = val.oid[idx] + } + } + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshler interface +func (s *SignatureAlgorithm) UnmarshalJSON(b []byte) error { + var aux JSONSignatureAlgorithm + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + *s = UnknownSignatureAlgorithm + oid := asn1.ObjectIdentifier(aux.OID.AsSlice()) + if oid.Equal(oidSignatureRSAPSS) { + pssAlgs := []SignatureAlgorithm{SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS} + for _, alg := range pssAlgs { + if strings.Compare(alg.String(), aux.Name) == 0 { + *s = alg + break + } + } + } else { + for _, val := range signatureAlgorithmDetails { + if val.oid.Equal(oid) { + *s = val.algo + break + } + } + } + return nil +} + +// jsonifySignatureAlgorithm gathers the necessary fields in a Certificate +// into a JSONSignatureAlgorithm, which can then use the default +// JSON marhsalers and unmarshalers. THIS FUNCTION IS PREFERED OVER +// THE CUSTOM JSON MARSHALER PRESENTED ABOVE FOR SIGNATUREALGORITHM +// BECAUSE THIS METHOD PRESERVES THE OID ORIGINALLY IN THE CERTIFICATE! +// This reason also explains why we need this function - +// the OID is unfortunately stored outside the scope of a +// SignatureAlgorithm struct and cannot be recovered without access to the +// entire Certificate if we do not know the signature algorithm. +func (c *Certificate) jsonifySignatureAlgorithm() JSONSignatureAlgorithm { + aux := JSONSignatureAlgorithm{} + if c.SignatureAlgorithm == 0 { + aux.Name = "unknown_algorithm" + } else { + aux.Name = c.SignatureAlgorithm.String() + } + aux.OID = make([]int, len(c.SignatureAlgorithmOID)) + for idx := range c.SignatureAlgorithmOID { + aux.OID[idx] = c.SignatureAlgorithmOID[idx] + } + return aux +} + +type auxPublicKeyAlgorithm struct { + Name string `json:"name,omitempty"` + OID *pkix.AuxOID `json:"oid,omitempty"` +} + +var publicKeyNameToAlgorithm = map[string]PublicKeyAlgorithm{ + "RSA": RSA, + "DSA": DSA, + "ECDSA": ECDSA, +} + +// MarshalJSON implements the json.Marshaler interface +func (p *PublicKeyAlgorithm) MarshalJSON() ([]byte, error) { + aux := auxPublicKeyAlgorithm{ + Name: p.String(), + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (p *PublicKeyAlgorithm) UnmarshalJSON(b []byte) error { + var aux auxPublicKeyAlgorithm + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + *p = publicKeyNameToAlgorithm[aux.Name] + return nil +} + +func clampTime(t time.Time) time.Time { + if t.Before(kMinTime) { + return kMinTime + } + if t.After(kMaxTime) { + return kMaxTime + } + return t +} + +type auxValidity struct { + Start string `json:"start"` + End string `json:"end"` + ValidityPeriod int `json:"length"` +} + +func (v *validity) MarshalJSON() ([]byte, error) { + aux := auxValidity{ + Start: clampTime(v.NotBefore.UTC()).Format(time.RFC3339), + End: clampTime(v.NotAfter.UTC()).Format(time.RFC3339), + ValidityPeriod: int(v.NotAfter.Sub(v.NotBefore).Seconds()), + } + return json.Marshal(&aux) +} + +func (v *validity) UnmarshalJSON(b []byte) error { + var aux auxValidity + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + var err error + if v.NotBefore, err = time.Parse(time.RFC3339, aux.Start); err != nil { + return err + } + if v.NotAfter, err = time.Parse(time.RFC3339, aux.End); err != nil { + return err + } + + return nil +} + +// ECDSAPublicKeyJSON - used to condense several fields from a +// ECDSA public key into one field for use in JSONCertificate. +// Uses default JSON marshal and unmarshal methods +type ECDSAPublicKeyJSON struct { + B []byte `json:"b"` + Curve string `json:"curve"` + Gx []byte `json:"gx"` + Gy []byte `json:"gy"` + Length int `json:"length"` + N []byte `json:"n"` + P []byte `json:"p"` + Pub []byte `json:"pub,omitempty"` + X []byte `json:"x"` + Y []byte `json:"y"` +} + +// DSAPublicKeyJSON - used to condense several fields from a +// DSA public key into one field for use in JSONCertificate. +// Uses default JSON marshal and unmarshal methods +type DSAPublicKeyJSON struct { + G []byte `json:"g"` + P []byte `json:"p"` + Q []byte `json:"q"` + Y []byte `json:"y"` +} + +// GetDSAPublicKeyJSON - get the DSAPublicKeyJSON for the given standard DSA PublicKey. +func GetDSAPublicKeyJSON(key *dsa.PublicKey) *DSAPublicKeyJSON { + return &DSAPublicKeyJSON{ + P: key.P.Bytes(), + Q: key.Q.Bytes(), + G: key.G.Bytes(), + Y: key.Y.Bytes(), + } +} + +// GetRSAPublicKeyJSON - get the jsonKeys.RSAPublicKey for the given standard RSA PublicKey. +func GetRSAPublicKeyJSON(key *rsa.PublicKey) *jsonKeys.RSAPublicKey { + rsaKey := new(jsonKeys.RSAPublicKey) + rsaKey.PublicKey = key + return rsaKey +} + +// GetECDSAPublicKeyJSON - get the GetECDSAPublicKeyJSON for the given standard ECDSA PublicKey. +func GetECDSAPublicKeyJSON(key *ecdsa.PublicKey) *ECDSAPublicKeyJSON { + params := key.Params() + return &ECDSAPublicKeyJSON{ + P: params.P.Bytes(), + N: params.N.Bytes(), + B: params.B.Bytes(), + Gx: params.Gx.Bytes(), + Gy: params.Gy.Bytes(), + X: key.X.Bytes(), + Y: key.Y.Bytes(), + Curve: key.Curve.Params().Name, + Length: key.Curve.Params().BitSize, + } +} + +// GetAugmentedECDSAPublicKeyJSON - get the GetECDSAPublicKeyJSON for the given "augmented" +// ECDSA PublicKey. +func GetAugmentedECDSAPublicKeyJSON(key *AugmentedECDSA) *ECDSAPublicKeyJSON { + params := key.Pub.Params() + return &ECDSAPublicKeyJSON{ + P: params.P.Bytes(), + N: params.N.Bytes(), + B: params.B.Bytes(), + Gx: params.Gx.Bytes(), + Gy: params.Gy.Bytes(), + X: key.Pub.X.Bytes(), + Y: key.Pub.Y.Bytes(), + Curve: key.Pub.Curve.Params().Name, + Length: key.Pub.Curve.Params().BitSize, + Pub: key.Raw.Bytes, + } +} + +// jsonifySubjectKey - Convert public key data in a Certificate +// into json output format for JSONCertificate +func (c *Certificate) jsonifySubjectKey() JSONSubjectKeyInfo { + j := JSONSubjectKeyInfo{ + KeyAlgorithm: c.PublicKeyAlgorithm, + SPKIFingerprint: c.SPKIFingerprint, + } + + switch key := c.PublicKey.(type) { + case *rsa.PublicKey: + rsaKey := new(jsonKeys.RSAPublicKey) + rsaKey.PublicKey = key + j.RSAPublicKey = rsaKey + case *dsa.PublicKey: + j.DSAPublicKey = &DSAPublicKeyJSON{ + P: key.P.Bytes(), + Q: key.Q.Bytes(), + G: key.G.Bytes(), + Y: key.Y.Bytes(), + } + case *ecdsa.PublicKey: + params := key.Params() + j.ECDSAPublicKey = &ECDSAPublicKeyJSON{ + P: params.P.Bytes(), + N: params.N.Bytes(), + B: params.B.Bytes(), + Gx: params.Gx.Bytes(), + Gy: params.Gy.Bytes(), + X: key.X.Bytes(), + Y: key.Y.Bytes(), + Curve: key.Curve.Params().Name, + Length: key.Curve.Params().BitSize, + } + case *AugmentedECDSA: + params := key.Pub.Params() + j.ECDSAPublicKey = &ECDSAPublicKeyJSON{ + P: params.P.Bytes(), + N: params.N.Bytes(), + B: params.B.Bytes(), + Gx: params.Gx.Bytes(), + Gy: params.Gy.Bytes(), + X: key.Pub.X.Bytes(), + Y: key.Pub.Y.Bytes(), + Curve: key.Pub.Curve.Params().Name, + Length: key.Pub.Curve.Params().BitSize, + Pub: key.Raw.Bytes, + } + } + return j +} + +// JSONSubjectKeyInfo - used to condense several fields from x509.Certificate +// related to the subject public key into one field within JSONCertificate +// Unfortunately, this struct cannot have its own Marshal method since it +// needs information from multiple fields in x509.Certificate +type JSONSubjectKeyInfo struct { + KeyAlgorithm PublicKeyAlgorithm `json:"key_algorithm"` + RSAPublicKey *jsonKeys.RSAPublicKey `json:"rsa_public_key,omitempty"` + DSAPublicKey *DSAPublicKeyJSON `json:"dsa_public_key,omitempty"` + ECDSAPublicKey *ECDSAPublicKeyJSON `json:"ecdsa_public_key,omitempty"` + SPKIFingerprint CertificateFingerprint `json:"fingerprint_sha256"` +} + +// JSONSignature - used to condense several fields from x509.Certificate +// related to the signature into one field within JSONCertificate +// Unfortunately, this struct cannot have its own Marshal method since it +// needs information from multiple fields in x509.Certificate +type JSONSignature struct { + SignatureAlgorithm JSONSignatureAlgorithm `json:"signature_algorithm"` + Value []byte `json:"value"` + Valid bool `json:"valid"` + SelfSigned bool `json:"self_signed"` +} + +// JSONValidity - used to condense several fields related +// to validity in x509.Certificate into one field within JSONCertificate +// Unfortunately, this struct cannot have its own Marshal method since it +// needs information from multiple fields in x509.Certificate +type JSONValidity struct { + validity + ValidityPeriod int +} + +// JSONCertificate - used to condense data from x509.Certificate when marhsaling +// into JSON. This struct has a distinct and independent layout from +// x509.Certificate, mostly for condensing data across repetitive +// fields and making it more presentable. +type JSONCertificate struct { + Version int `json:"version"` + SerialNumber string `json:"serial_number"` + SignatureAlgorithm JSONSignatureAlgorithm `json:"signature_algorithm"` + Issuer pkix.Name `json:"issuer"` + IssuerDN string `json:"issuer_dn,omitempty"` + Validity JSONValidity `json:"validity"` + Subject pkix.Name `json:"subject"` + SubjectDN string `json:"subject_dn,omitempty"` + SubjectKeyInfo JSONSubjectKeyInfo `json:"subject_key_info"` + Extensions *CertificateExtensions `json:"extensions,omitempty"` + UnknownExtensions UnknownCertificateExtensions `json:"unknown_extensions,omitempty"` + Signature JSONSignature `json:"signature"` + FingerprintMD5 CertificateFingerprint `json:"fingerprint_md5"` + FingerprintSHA1 CertificateFingerprint `json:"fingerprint_sha1"` + FingerprintSHA256 CertificateFingerprint `json:"fingerprint_sha256"` + FingerprintNoCT CertificateFingerprint `json:"tbs_noct_fingerprint"` + SPKISubjectFingerprint CertificateFingerprint `json:"spki_subject_fingerprint"` + TBSCertificateFingerprint CertificateFingerprint `json:"tbs_fingerprint"` + ValidationLevel CertValidationLevel `json:"validation_level"` + Names []string `json:"names,omitempty"` + Redacted bool `json:"redacted"` +} + +// CollectAllNames - Collect and validate all DNS / URI / IP Address names for a given certificate +func (c *Certificate) CollectAllNames() []string { + var names []string + + if isValidName(c.Subject.CommonName) { + names = append(names, c.Subject.CommonName) + } + + for _, name := range c.DNSNames { + if isValidName(name) { + names = append(names, name) + } else if !strings.Contains(name, ".") { //just a TLD + names = append(names, name) + } + + } + + for _, name := range c.URIs { + if util.IsURL(name) { + names = append(names, name) + } + } + + for _, name := range c.IPAddresses { + str := name.String() + if util.IsURL(str) { + names = append(names, str) + } + } + + return purgeNameDuplicates(names) +} + +func (c *Certificate) MarshalJSON() ([]byte, error) { + // Fill out the certificate + jc := new(JSONCertificate) + jc.Version = c.Version + jc.SerialNumber = c.SerialNumber.String() + jc.Issuer = c.Issuer + jc.IssuerDN = c.Issuer.String() + + jc.Validity.NotBefore = c.NotBefore + jc.Validity.NotAfter = c.NotAfter + jc.Validity.ValidityPeriod = c.ValidityPeriod + jc.Subject = c.Subject + jc.SubjectDN = c.Subject.String() + jc.Names = c.CollectAllNames() + jc.Redacted = false + for _, name := range jc.Names { + if strings.HasPrefix(name, "?") { + jc.Redacted = true + } + } + + jc.SubjectKeyInfo = c.jsonifySubjectKey() + jc.Extensions, jc.UnknownExtensions = c.jsonifyExtensions() + + // TODO: Handle the fact this might not match + jc.SignatureAlgorithm = c.jsonifySignatureAlgorithm() + jc.Signature.SignatureAlgorithm = jc.SignatureAlgorithm + jc.Signature.Value = c.Signature + jc.Signature.Valid = c.validSignature + jc.Signature.SelfSigned = c.SelfSigned + if c.SelfSigned { + jc.Signature.Valid = true + } + jc.FingerprintMD5 = c.FingerprintMD5 + jc.FingerprintSHA1 = c.FingerprintSHA1 + jc.FingerprintSHA256 = c.FingerprintSHA256 + jc.FingerprintNoCT = c.FingerprintNoCT + jc.SPKISubjectFingerprint = c.SPKISubjectFingerprint + jc.TBSCertificateFingerprint = c.TBSCertificateFingerprint + jc.ValidationLevel = c.ValidationLevel + + return json.Marshal(jc) +} + +// UnmarshalJSON - intentionally implimented to always error, +// as this method should not be used. The MarshalJSON method +// on Certificate condenses data in a way that is not recoverable. +// Use the x509.ParseCertificate function instead or +// JSONCertificateWithRaw Marshal method +func (jc *JSONCertificate) UnmarshalJSON(b []byte) error { + return errors.New("Do not unmarshal cert JSON directly, use JSONCertificateWithRaw or x509.ParseCertificate function") +} + +// UnmarshalJSON - intentionally implimented to always error, +// as this method should not be used. The MarshalJSON method +// on Certificate condenses data in a way that is not recoverable. +// Use the x509.ParseCertificate function instead or +// JSONCertificateWithRaw Marshal method +func (c *Certificate) UnmarshalJSON(b []byte) error { + return errors.New("Do not unmarshal cert JSON directly, use JSONCertificateWithRaw or x509.ParseCertificate function") +} + +// JSONCertificateWithRaw - intermediate struct for unmarshaling json +// of a certificate - the raw is require since the +// MarshalJSON method on Certificate condenses data in a way that +// makes extraction to the original in Unmarshal impossible. +// The JSON output of Marshal is not even used to construct +// a certificate, all we need is raw +type JSONCertificateWithRaw struct { + Raw []byte `json:"raw,omitempty"` +} + +// ParseRaw - for converting the intermediate object +// JSONCertificateWithRaw into a parsed Certificate +// see description of JSONCertificateWithRaw for +// why this is used instead of UnmarshalJSON methods +func (c *JSONCertificateWithRaw) ParseRaw() (*Certificate, error) { + return ParseCertificate(c.Raw) +} + +func purgeNameDuplicates(names []string) (out []string) { + hashset := make(map[string]bool, len(names)) + for _, name := range names { + if _, inc := hashset[name]; !inc { + hashset[name] = true + } + } + + out = make([]string, 0, len(hashset)) + for key := range hashset { + out = append(out, key) + } + + sort.Strings(out) // must sort to ensure output is deterministic! + return +} + +func isValidName(name string) (ret bool) { + + // Check for wildcards and redacts, ignore malformed urls + if strings.HasPrefix(name, "?.") || strings.HasPrefix(name, "*.") { + ret = isValidName(name[2:]) + } else { + ret = util.IsURL(name) + } + return +} + +func orMask(ip net.IP, mask net.IPMask) net.IP { + if len(ip) == 0 || len(mask) == 0 { + return nil + } + if len(ip) != net.IPv4len && len(ip) != net.IPv6len { + return nil + } + if len(ip) != len(mask) { + return nil + } + out := make([]byte, len(ip)) + for idx := range ip { + out[idx] = ip[idx] | mask[idx] + } + return out +} + +func invertMask(mask net.IPMask) net.IPMask { + if mask == nil { + return nil + } + out := make([]byte, len(mask)) + for idx := range mask { + out[idx] = ^mask[idx] + } + return out +} + +type auxGeneralSubtreeIP struct { + CIDR string `json:"cidr,omitempty"` + Begin string `json:"begin,omitempty"` + End string `json:"end,omitempty"` + Mask string `json:"mask,omitempty"` +} + +func (g *GeneralSubtreeIP) MarshalJSON() ([]byte, error) { + aux := auxGeneralSubtreeIP{} + aux.CIDR = g.Data.String() + // Check to see if the subnet is valid. An invalid subnet will return 0,0 + // from Size(). If the subnet is invalid, only output the CIDR. + ones, bits := g.Data.Mask.Size() + if ones == 0 && bits == 0 { + return json.Marshal(&aux) + } + // The first IP in the range should be `ip & mask`. + begin := g.Data.IP.Mask(g.Data.Mask) + if begin != nil { + aux.Begin = begin.String() + } + // The last IP (inclusive) is `ip & (^mask)`. + inverseMask := invertMask(g.Data.Mask) + end := orMask(g.Data.IP, inverseMask) + if end != nil { + aux.End = end.String() + } + // Output the mask as an IP, but enforce it can be formatted correctly. + // net.IP.String() only works on byte arrays of the correct length. + maskLen := len(g.Data.Mask) + if maskLen == net.IPv4len || maskLen == net.IPv6len { + maskAsIP := net.IP(g.Data.Mask) + aux.Mask = maskAsIP.String() + } + return json.Marshal(&aux) +} + +func (g *GeneralSubtreeIP) UnmarshalJSON(b []byte) error { + aux := auxGeneralSubtreeIP{} + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + ip, ipNet, err := net.ParseCIDR(aux.CIDR) + if err != nil { + return err + } + g.Data.IP = ip + g.Data.Mask = ipNet.Mask + g.Min = 0 + g.Max = 0 + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/names.go b/vendor/github.com/zmap/zcrypto/x509/names.go new file mode 100644 index 0000000000..012f919210 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/names.go @@ -0,0 +1,30 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +func (p PublicKeyAlgorithm) String() string { + if p >= total_key_algorithms || p < 0 { + p = UnknownPublicKeyAlgorithm + } + return keyAlgorithmNames[p] +} + +func (c *Certificate) SignatureAlgorithmName() string { + switch c.SignatureAlgorithm { + case UnknownSignatureAlgorithm: + return c.SignatureAlgorithmOID.String() + default: + return c.SignatureAlgorithm.String() + } +} + +func (c *Certificate) PublicKeyAlgorithmName() string { + switch c.PublicKeyAlgorithm { + case UnknownPublicKeyAlgorithm: + return c.PublicKeyAlgorithmOID.String() + default: + return c.PublicKeyAlgorithm.String() + } +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pem_decrypt.go b/vendor/github.com/zmap/zcrypto/x509/pem_decrypt.go new file mode 100644 index 0000000000..0388d63e14 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pem_decrypt.go @@ -0,0 +1,240 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// RFC 1423 describes the encryption of PEM blocks. The algorithm used to +// generate a key from the password was derived by looking at the OpenSSL +// implementation. + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/md5" + "encoding/hex" + "encoding/pem" + "errors" + "io" + "strings" +) + +type PEMCipher int + +// Possible values for the EncryptPEMBlock encryption algorithm. +const ( + _ PEMCipher = iota + PEMCipherDES + PEMCipher3DES + PEMCipherAES128 + PEMCipherAES192 + PEMCipherAES256 +) + +// rfc1423Algo holds a method for enciphering a PEM block. +type rfc1423Algo struct { + cipher PEMCipher + name string + cipherFunc func(key []byte) (cipher.Block, error) + keySize int + blockSize int +} + +// rfc1423Algos holds a slice of the possible ways to encrypt a PEM +// block. The ivSize numbers were taken from the OpenSSL source. +var rfc1423Algos = []rfc1423Algo{{ + cipher: PEMCipherDES, + name: "DES-CBC", + cipherFunc: des.NewCipher, + keySize: 8, + blockSize: des.BlockSize, +}, { + cipher: PEMCipher3DES, + name: "DES-EDE3-CBC", + cipherFunc: des.NewTripleDESCipher, + keySize: 24, + blockSize: des.BlockSize, +}, { + cipher: PEMCipherAES128, + name: "AES-128-CBC", + cipherFunc: aes.NewCipher, + keySize: 16, + blockSize: aes.BlockSize, +}, { + cipher: PEMCipherAES192, + name: "AES-192-CBC", + cipherFunc: aes.NewCipher, + keySize: 24, + blockSize: aes.BlockSize, +}, { + cipher: PEMCipherAES256, + name: "AES-256-CBC", + cipherFunc: aes.NewCipher, + keySize: 32, + blockSize: aes.BlockSize, +}, +} + +// deriveKey uses a key derivation function to stretch the password into a key +// with the number of bits our cipher requires. This algorithm was derived from +// the OpenSSL source. +func (c rfc1423Algo) deriveKey(password, salt []byte) []byte { + hash := md5.New() + out := make([]byte, c.keySize) + var digest []byte + + for i := 0; i < len(out); i += len(digest) { + hash.Reset() + hash.Write(digest) + hash.Write(password) + hash.Write(salt) + digest = hash.Sum(digest[:0]) + copy(out[i:], digest) + } + return out +} + +// IsEncryptedPEMBlock returns if the PEM block is password encrypted. +func IsEncryptedPEMBlock(b *pem.Block) bool { + _, ok := b.Headers["DEK-Info"] + return ok +} + +// IncorrectPasswordError is returned when an incorrect password is detected. +var IncorrectPasswordError = errors.New("x509: decryption password incorrect") + +// DecryptPEMBlock takes a password encrypted PEM block and the password used to +// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects +// the DEK-Info header to determine the algorithm used for decryption. If no +// DEK-Info header is present, an error is returned. If an incorrect password +// is detected an IncorrectPasswordError is returned. Because of deficiencies +// in the encrypted-PEM format, it's not always possible to detect an incorrect +// password. In these cases no error will be returned but the decrypted DER +// bytes will be random noise. +func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { + dek, ok := b.Headers["DEK-Info"] + if !ok { + return nil, errors.New("x509: no DEK-Info header in block") + } + + idx := strings.Index(dek, ",") + if idx == -1 { + return nil, errors.New("x509: malformed DEK-Info header") + } + + mode, hexIV := dek[:idx], dek[idx+1:] + ciph := cipherByName(mode) + if ciph == nil { + return nil, errors.New("x509: unknown encryption mode") + } + iv, err := hex.DecodeString(hexIV) + if err != nil { + return nil, err + } + if len(iv) != ciph.blockSize { + return nil, errors.New("x509: incorrect IV size") + } + + // Based on the OpenSSL implementation. The salt is the first 8 bytes + // of the initialization vector. + key := ciph.deriveKey(password, iv[:8]) + block, err := ciph.cipherFunc(key) + if err != nil { + return nil, err + } + + if len(b.Bytes)%block.BlockSize() != 0 { + return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size") + } + + data := make([]byte, len(b.Bytes)) + dec := cipher.NewCBCDecrypter(block, iv) + dec.CryptBlocks(data, b.Bytes) + + // Blocks are padded using a scheme where the last n bytes of padding are all + // equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423. + // For example: + // [x y z 2 2] + // [x y 7 7 7 7 7 7 7] + // If we detect a bad padding, we assume it is an invalid password. + dlen := len(data) + if dlen == 0 || dlen%ciph.blockSize != 0 { + return nil, errors.New("x509: invalid padding") + } + last := int(data[dlen-1]) + if dlen < last { + return nil, IncorrectPasswordError + } + if last == 0 || last > ciph.blockSize { + return nil, IncorrectPasswordError + } + for _, val := range data[dlen-last:] { + if int(val) != last { + return nil, IncorrectPasswordError + } + } + return data[:dlen-last], nil +} + +// EncryptPEMBlock returns a PEM block of the specified type holding the +// given DER-encoded data encrypted with the specified algorithm and +// password. +func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) { + ciph := cipherByKey(alg) + if ciph == nil { + return nil, errors.New("x509: unknown encryption mode") + } + iv := make([]byte, ciph.blockSize) + if _, err := io.ReadFull(rand, iv); err != nil { + return nil, errors.New("x509: cannot generate IV: " + err.Error()) + } + // The salt is the first 8 bytes of the initialization vector, + // matching the key derivation in DecryptPEMBlock. + key := ciph.deriveKey(password, iv[:8]) + block, err := ciph.cipherFunc(key) + if err != nil { + return nil, err + } + enc := cipher.NewCBCEncrypter(block, iv) + pad := ciph.blockSize - len(data)%ciph.blockSize + encrypted := make([]byte, len(data), len(data)+pad) + // We could save this copy by encrypting all the whole blocks in + // the data separately, but it doesn't seem worth the additional + // code. + copy(encrypted, data) + // See RFC 1423, section 1.1 + for i := 0; i < pad; i++ { + encrypted = append(encrypted, byte(pad)) + } + enc.CryptBlocks(encrypted, encrypted) + + return &pem.Block{ + Type: blockType, + Headers: map[string]string{ + "Proc-Type": "4,ENCRYPTED", + "DEK-Info": ciph.name + "," + hex.EncodeToString(iv), + }, + Bytes: encrypted, + }, nil +} + +func cipherByName(name string) *rfc1423Algo { + for i := range rfc1423Algos { + alg := &rfc1423Algos[i] + if alg.name == name { + return alg + } + } + return nil +} + +func cipherByKey(key PEMCipher) *rfc1423Algo { + for i := range rfc1423Algos { + alg := &rfc1423Algos[i] + if alg.cipher == key { + return alg + } + } + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pkcs1.go b/vendor/github.com/zmap/zcrypto/x509/pkcs1.go new file mode 100644 index 0000000000..73bc7623a5 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pkcs1.go @@ -0,0 +1,121 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto/rsa" + "encoding/asn1" + "errors" + "math/big" +) + +// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key. +type pkcs1PrivateKey struct { + Version int + N *big.Int + E int + D *big.Int + P *big.Int + Q *big.Int + // We ignore these values, if present, because rsa will calculate them. + Dp *big.Int `asn1:"optional"` + Dq *big.Int `asn1:"optional"` + Qinv *big.Int `asn1:"optional"` + + AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"` +} + +type pkcs1AdditionalRSAPrime struct { + Prime *big.Int + + // We ignore these values because rsa will calculate them. + Exp *big.Int + Coeff *big.Int +} + +// pkcs1PublicKey reflects the ASN.1 structure of a PKCS#1 public key. +type pkcs1PublicKey struct { + N *big.Int + E int +} + +// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. +func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { + var priv pkcs1PrivateKey + rest, err := asn1.Unmarshal(der, &priv) + if len(rest) > 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + if err != nil { + return nil, err + } + + if priv.Version > 1 { + return nil, errors.New("x509: unsupported private key version") + } + + if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 { + return nil, errors.New("x509: private key contains zero or negative value") + } + + key := new(rsa.PrivateKey) + key.PublicKey = rsa.PublicKey{ + E: priv.E, + N: priv.N, + } + + key.D = priv.D + key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) + key.Primes[0] = priv.P + key.Primes[1] = priv.Q + for i, a := range priv.AdditionalPrimes { + if a.Prime.Sign() <= 0 { + return nil, errors.New("x509: private key contains zero or negative prime") + } + key.Primes[i+2] = a.Prime + // We ignore the other two values because rsa will calculate + // them as needed. + } + + err = key.Validate() + if err != nil { + return nil, err + } + key.Precompute() + + return key, nil +} + +// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form. +func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte { + key.Precompute() + + version := 0 + if len(key.Primes) > 2 { + version = 1 + } + + priv := pkcs1PrivateKey{ + Version: version, + N: key.N, + E: key.PublicKey.E, + D: key.D, + P: key.Primes[0], + Q: key.Primes[1], + Dp: key.Precomputed.Dp, + Dq: key.Precomputed.Dq, + Qinv: key.Precomputed.Qinv, + } + + priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues)) + for i, values := range key.Precomputed.CRTValues { + priv.AdditionalPrimes[i].Prime = key.Primes[2+i] + priv.AdditionalPrimes[i].Exp = values.Exp + priv.AdditionalPrimes[i].Coeff = values.Coeff + } + + b, _ := asn1.Marshal(priv) + return b +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pkcs8.go b/vendor/github.com/zmap/zcrypto/x509/pkcs8.go new file mode 100644 index 0000000000..d69049fae5 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pkcs8.go @@ -0,0 +1,54 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "encoding/asn1" + "errors" + "fmt" + "github.com/zmap/zcrypto/x509/pkix" +) + +// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See +// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn +// and RFC 5208. +type pkcs8 struct { + Version int + Algo pkix.AlgorithmIdentifier + PrivateKey []byte + // optional attributes omitted. +} + +// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. +// See RFC 5208. +func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { + var privKey pkcs8 + if _, err := asn1.Unmarshal(der, &privKey); err != nil { + return nil, err + } + switch { + case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): + key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) + if err != nil { + return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error()) + } + return key, nil + + case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): + bytes := privKey.Algo.Parameters.FullBytes + namedCurveOID := new(asn1.ObjectIdentifier) + if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { + namedCurveOID = nil + } + key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) + if err != nil { + return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) + } + return key, nil + + default: + return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) + } +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/json.go b/vendor/github.com/zmap/zcrypto/x509/pkix/json.go new file mode 100644 index 0000000000..3000f977e2 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/json.go @@ -0,0 +1,279 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pkix + +import ( + "encoding/asn1" + "encoding/json" + "errors" + "strconv" + "strings" +) + +type auxAttributeTypeAndValue struct { + Type string `json:"type,omitempty"` + Value string `json:"value,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +func (a *AttributeTypeAndValue) MarshalJSON() ([]byte, error) { + aux := auxAttributeTypeAndValue{} + aux.Type = a.Type.String() + if s, ok := a.Value.(string); ok { + aux.Value = s + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (a *AttributeTypeAndValue) UnmarshalJSON(b []byte) error { + aux := auxAttributeTypeAndValue{} + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + a.Type = nil + if len(aux.Type) > 0 { + parts := strings.Split(aux.Type, ".") + for _, part := range parts { + i, err := strconv.Atoi(part) + if err != nil { + return err + } + a.Type = append(a.Type, i) + } + } + a.Value = aux.Value + return nil +} + +type auxOtherName struct { + ID string `json:"id,omitempty"` + Value []byte `json:"value,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +func (o *OtherName) MarshalJSON() ([]byte, error) { + aux := auxOtherName{ + ID: o.TypeID.String(), + Value: o.Value.Bytes, + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (o *OtherName) UnmarshalJSON(b []byte) (err error) { + aux := auxOtherName{} + if err = json.Unmarshal(b, &aux); err != nil { + return + } + + // Turn dot-notation back into an OID + if len(aux.ID) == 0 { + return errors.New("empty type ID") + } + parts := strings.Split(aux.ID, ".") + o.TypeID = nil + for _, part := range parts { + i, err := strconv.Atoi(part) + if err != nil { + return err + } + o.TypeID = append(o.TypeID, i) + } + + // Build the ASN.1 value + o.Value = asn1.RawValue{ + Tag: 0, + Class: asn1.ClassContextSpecific, + IsCompound: true, + Bytes: aux.Value, + } + o.Value.FullBytes, err = asn1.Marshal(o.Value) + return +} + +type auxExtension struct { + ID string `json:"id,omitempty"` + Critical bool `json:"critical"` + Value []byte `json:"value,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +func (ext *Extension) MarshalJSON() ([]byte, error) { + aux := auxExtension{ + ID: ext.Id.String(), + Critical: ext.Critical, + Value: ext.Value, + } + return json.Marshal(&aux) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (ext *Extension) UnmarshalJSON(b []byte) (err error) { + aux := auxExtension{} + if err = json.Unmarshal(b, &aux); err != nil { + return + } + + parts := strings.Split(aux.ID, ".") + for _, part := range parts { + i, err := strconv.Atoi(part) + if err != nil { + return err + } + ext.Id = append(ext.Id, i) + } + ext.Critical = aux.Critical + ext.Value = aux.Value + return +} + +type auxName struct { + CommonName []string `json:"common_name,omitempty"` + SerialNumber []string `json:"serial_number,omitempty"` + Country []string `json:"country,omitempty"` + Locality []string `json:"locality,omitempty"` + Province []string `json:"province,omitempty"` + StreetAddress []string `json:"street_address,omitempty"` + Organization []string `json:"organization,omitempty"` + OrganizationalUnit []string `json:"organizational_unit,omitempty"` + PostalCode []string `json:"postal_code,omitempty"` + DomainComponent []string `json:"domain_component,omitempty"` + EmailAddress []string `json:"email_address,omitempty"` + GivenName []string `json:"given_name,omitempty"` + Surname []string `json:"surname,omitempty"` + // EV + JurisdictionCountry []string `json:"jurisdiction_country,omitempty"` + JurisdictionLocality []string `json:"jurisdiction_locality,omitempty"` + JurisdictionProvince []string `json:"jurisdiction_province,omitempty"` + + // QWACS + OrganizationID []string `json:"organization_id,omitempty"` + + UnknownAttributes []AttributeTypeAndValue `json:"-"` +} + +// MarshalJSON implements the json.Marshaler interface. +func (n *Name) MarshalJSON() ([]byte, error) { + aux := auxName{} + attrs := n.ToRDNSequence() + for _, attrSet := range attrs { + for _, a := range attrSet { + s, ok := a.Value.(string) + if !ok { + continue + } + if a.Type.Equal(oidCommonName) { + aux.CommonName = append(aux.CommonName, s) + } else if a.Type.Equal(oidSurname) { + aux.Surname = append(aux.Surname, s) + } else if a.Type.Equal(oidSerialNumber) { + aux.SerialNumber = append(aux.SerialNumber, s) + } else if a.Type.Equal(oidCountry) { + aux.Country = append(aux.Country, s) + } else if a.Type.Equal(oidLocality) { + aux.Locality = append(aux.Locality, s) + } else if a.Type.Equal(oidProvince) { + aux.Province = append(aux.Province, s) + } else if a.Type.Equal(oidStreetAddress) { + aux.StreetAddress = append(aux.StreetAddress, s) + } else if a.Type.Equal(oidOrganization) { + aux.Organization = append(aux.Organization, s) + } else if a.Type.Equal(oidGivenName) { + aux.GivenName = append(aux.GivenName, s) + } else if a.Type.Equal(oidOrganizationalUnit) { + aux.OrganizationalUnit = append(aux.OrganizationalUnit, s) + } else if a.Type.Equal(oidPostalCode) { + aux.PostalCode = append(aux.PostalCode, s) + } else if a.Type.Equal(oidDomainComponent) { + aux.DomainComponent = append(aux.DomainComponent, s) + } else if a.Type.Equal(oidDNEmailAddress) { + aux.EmailAddress = append(aux.EmailAddress, s) + // EV + } else if a.Type.Equal(oidJurisdictionCountry) { + aux.JurisdictionCountry = append(aux.JurisdictionCountry, s) + } else if a.Type.Equal(oidJurisdictionLocality) { + aux.JurisdictionLocality = append(aux.JurisdictionLocality, s) + } else if a.Type.Equal(oidJurisdictionProvince) { + aux.JurisdictionProvince = append(aux.JurisdictionProvince, s) + } else if a.Type.Equal(oidOrganizationID) { + aux.OrganizationID = append(aux.OrganizationID, s) + } else { + aux.UnknownAttributes = append(aux.UnknownAttributes, a) + } + } + } + return json.Marshal(&aux) +} + +func appendATV(names []AttributeTypeAndValue, fieldVals []string, asn1Id asn1.ObjectIdentifier) []AttributeTypeAndValue { + if len(fieldVals) == 0 { + return names + } + + for _, val := range fieldVals { + names = append(names, AttributeTypeAndValue{Type: asn1Id, Value: val}) + } + + return names +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (n *Name) UnmarshalJSON(b []byte) error { + aux := auxName{} + if err := json.Unmarshal(b, &aux); err != nil { + return err + } + + // Populate Names as []AttributeTypeAndValue + n.Names = appendATV(n.Names, aux.Country, oidCountry) + n.Names = appendATV(n.Names, aux.Organization, oidOrganization) + n.Names = appendATV(n.Names, aux.OrganizationalUnit, oidOrganizationalUnit) + n.Names = appendATV(n.Names, aux.Locality, oidLocality) + n.Names = appendATV(n.Names, aux.Province, oidProvince) + n.Names = appendATV(n.Names, aux.StreetAddress, oidStreetAddress) + n.Names = appendATV(n.Names, aux.PostalCode, oidPostalCode) + n.Names = appendATV(n.Names, aux.DomainComponent, oidDomainComponent) + n.Names = appendATV(n.Names, aux.EmailAddress, oidDNEmailAddress) + // EV + n.Names = appendATV(n.Names, aux.JurisdictionCountry, oidJurisdictionCountry) + n.Names = appendATV(n.Names, aux.JurisdictionLocality, oidJurisdictionLocality) + n.Names = appendATV(n.Names, aux.JurisdictionProvince, oidJurisdictionProvince) + + n.Names = appendATV(n.Names, aux.CommonName, oidCommonName) + n.Names = appendATV(n.Names, aux.SerialNumber, oidSerialNumber) + + // Populate specific fields as []string + n.Country = aux.Country + n.Organization = aux.Organization + n.OrganizationalUnit = aux.OrganizationalUnit + n.Locality = aux.Locality + n.Province = aux.Province + n.StreetAddress = aux.StreetAddress + n.PostalCode = aux.PostalCode + n.DomainComponent = aux.DomainComponent + // EV + n.JurisdictionCountry = aux.JurisdictionCountry + n.JurisdictionLocality = aux.JurisdictionLocality + n.JurisdictionProvince = aux.JurisdictionProvince + + // CommonName and SerialNumber are not arrays. + if len(aux.CommonName) > 0 { + n.CommonName = aux.CommonName[0] + } + if len(aux.SerialNumber) > 0 { + n.SerialNumber = aux.SerialNumber[0] + } + + // Add "extra" commonNames and serialNumbers to ExtraNames. + if len(aux.CommonName) > 1 { + n.ExtraNames = appendATV(n.ExtraNames, aux.CommonName[1:], oidCommonName) + } + if len(aux.SerialNumber) > 1 { + n.ExtraNames = appendATV(n.ExtraNames, aux.SerialNumber[1:], oidSerialNumber) + } + + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go b/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go new file mode 100644 index 0000000000..314ab7b587 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go @@ -0,0 +1,74 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pkix + +import ( + "encoding/asn1" + "encoding/json" + "fmt" + "strconv" + "strings" +) + +// AuxOID behaves similar to asn1.ObjectIdentifier, except encodes to JSON as a +// string in dot notation. It is a type synonym for []int, and can be converted +// to an asn1.ObjectIdentifier by going through []int and back. +type AuxOID []int + +// AsSlice returns a slice over the inner-representation +func (aux *AuxOID) AsSlice() []int { + return *aux +} + +// CopyAsSlice returns a copy of the inter-representation as a slice +func (aux *AuxOID) CopyAsSlice() []int { + out := make([]int, len(*aux)) + copy(out, *aux) + return out +} + +// Equal tests (deep) equality of two AuxOIDs +func (aux *AuxOID) Equal(other *AuxOID) bool { + var a []int = *aux + var b []int = *other + if len(a) != len(b) { + return false + } + for idx := range a { + if a[idx] != b[idx] { + return false + } + } + return true +} + +// MarshalJSON implements the json.Marshaler interface +func (aux *AuxOID) MarshalJSON() ([]byte, error) { + var oid asn1.ObjectIdentifier + oid = []int(*aux) + return json.Marshal(oid.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (aux *AuxOID) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + parts := strings.Split(s, ".") + if len(parts) < 1 { + return fmt.Errorf("Invalid OID string %s", s) + } + slice := make([]int, len(parts)) + for idx := range parts { + n, err := strconv.Atoi(parts[idx]) + if err != nil || n < 0 { + return fmt.Errorf("Invalid OID integer %s", parts[idx]) + } + slice[idx] = n + } + *aux = slice + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/oid_names.go b/vendor/github.com/zmap/zcrypto/x509/pkix/oid_names.go new file mode 100644 index 0000000000..1f396560f6 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/oid_names.go @@ -0,0 +1,1014 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pkix + +// OIDName stores the short and long version of the name of an IANA-assigned OID +type OIDName struct { + ShortName string `json:"short_name"` + LongName string `json:"long_name"` +} + +var oidDotNotationToNames map[string]OIDName + +func init() { + oidDotNotationToNames = make(map[string]OIDName, 1024) + + oidDotNotationToNames["0.0"] = OIDName{ShortName: "UNDEF", LongName: "undefined"} + oidDotNotationToNames["1.2.840.113549"] = OIDName{ShortName: "rsadsi", LongName: "RSA Data Security"} + oidDotNotationToNames["1.2.840.113549.1"] = OIDName{ShortName: "pkcs", LongName: "RSA Data Security"} + oidDotNotationToNames["1.2.840.113549.2.2"] = OIDName{ShortName: "MD2", LongName: "md2"} + oidDotNotationToNames["1.2.840.113549.2.5"] = OIDName{ShortName: "MD5", LongName: "md5"} + oidDotNotationToNames["1.2.840.113549.3.4"] = OIDName{ShortName: "RC4", LongName: "rc4"} + oidDotNotationToNames["1.2.840.113549.1.1.1"] = OIDName{ShortName: "rsaEncryption", LongName: "rsaEncryption"} + oidDotNotationToNames["1.2.840.113549.1.1.2"] = OIDName{ShortName: "RSA-MD2", LongName: "md2WithRSAEncryption"} + oidDotNotationToNames["1.2.840.113549.1.1.4"] = OIDName{ShortName: "RSA-MD5", LongName: "md5WithRSAEncryption"} + oidDotNotationToNames["1.2.840.113549.1.5.1"] = OIDName{ShortName: "PBE-MD2-DES", LongName: "pbeWithMD2AndDES-CBC"} + oidDotNotationToNames["1.2.840.113549.1.5.3"] = OIDName{ShortName: "PBE-MD5-DES", LongName: "pbeWithMD5AndDES-CBC"} + oidDotNotationToNames["2.5"] = OIDName{ShortName: "X500", LongName: "directory services (X.500)"} + oidDotNotationToNames["2.5.4"] = OIDName{ShortName: "X509", LongName: "X509"} + oidDotNotationToNames["2.5.4.3"] = OIDName{ShortName: "CN", LongName: "commonName"} + oidDotNotationToNames["2.5.4.6"] = OIDName{ShortName: "C", LongName: "countryName"} + oidDotNotationToNames["2.5.4.7"] = OIDName{ShortName: "L", LongName: "localityName"} + oidDotNotationToNames["2.5.4.8"] = OIDName{ShortName: "ST", LongName: "stateOrProvinceName"} + oidDotNotationToNames["2.5.4.10"] = OIDName{ShortName: "O", LongName: "organizationName"} + oidDotNotationToNames["2.5.4.11"] = OIDName{ShortName: "OU", LongName: "organizationalUnitName"} + oidDotNotationToNames["2.5.4.97"] = OIDName{ShortName: "organizationIdentifier", LongName: "organizationIdentifier"} + oidDotNotationToNames["2.5.8.1.1"] = OIDName{ShortName: "RSA", LongName: "rsa"} + oidDotNotationToNames["1.2.840.113549.1.7"] = OIDName{ShortName: "pkcs7", LongName: "pkcs7"} + oidDotNotationToNames["1.2.840.113549.1.7.1"] = OIDName{ShortName: "pkcs7-data", LongName: "pkcs7-data"} + oidDotNotationToNames["1.2.840.113549.1.7.2"] = OIDName{ShortName: "pkcs7-signedData", LongName: "pkcs7-signedData"} + oidDotNotationToNames["1.2.840.113549.1.7.3"] = OIDName{ShortName: "pkcs7-envelopedData", LongName: "pkcs7-envelopedData"} + oidDotNotationToNames["1.2.840.113549.1.7.4"] = OIDName{ShortName: "pkcs7-signedAndEnvelopedData", LongName: "pkcs7-signedAndEnvelopedData"} + oidDotNotationToNames["1.2.840.113549.1.7.5"] = OIDName{ShortName: "pkcs7-digestData", LongName: "pkcs7-digestData"} + oidDotNotationToNames["1.2.840.113549.1.7.6"] = OIDName{ShortName: "pkcs7-encryptedData", LongName: "pkcs7-encryptedData"} + oidDotNotationToNames["1.2.840.113549.1.3"] = OIDName{ShortName: "pkcs3", LongName: "pkcs3"} + oidDotNotationToNames["1.2.840.113549.1.3.1"] = OIDName{ShortName: "dhKeyAgreement", LongName: "dhKeyAgreement"} + oidDotNotationToNames["1.3.14.3.2.6"] = OIDName{ShortName: "DES-ECB", LongName: "des-ecb"} + oidDotNotationToNames["1.3.14.3.2.9"] = OIDName{ShortName: "DES-CFB", LongName: "des-cfb"} + oidDotNotationToNames["1.3.14.3.2.7"] = OIDName{ShortName: "DES-CBC", LongName: "des-cbc"} + oidDotNotationToNames["1.3.14.3.2.17"] = OIDName{ShortName: "DES-EDE", LongName: "des-ede"} + oidDotNotationToNames["1.3.6.1.4.1.188.7.1.1.2"] = OIDName{ShortName: "IDEA-CBC", LongName: "idea-cbc"} + oidDotNotationToNames["1.2.840.113549.3.2"] = OIDName{ShortName: "RC2-CBC", LongName: "rc2-cbc"} + oidDotNotationToNames["1.3.14.3.2.18"] = OIDName{ShortName: "SHA", LongName: "sha"} + oidDotNotationToNames["1.3.14.3.2.15"] = OIDName{ShortName: "RSA-SHA", LongName: "shaWithRSAEncryption"} + oidDotNotationToNames["1.2.840.113549.3.7"] = OIDName{ShortName: "DES-EDE3-CBC", LongName: "des-ede3-cbc"} + oidDotNotationToNames["1.3.14.3.2.8"] = OIDName{ShortName: "DES-OFB", LongName: "des-ofb"} + oidDotNotationToNames["1.2.840.113549.1.9"] = OIDName{ShortName: "pkcs9", LongName: "pkcs9"} + oidDotNotationToNames["1.2.840.113549.1.9.1"] = OIDName{ShortName: "emailAddress", LongName: "emailAddress"} + oidDotNotationToNames["1.2.840.113549.1.9.2"] = OIDName{ShortName: "unstructuredName", LongName: "unstructuredName"} + oidDotNotationToNames["1.2.840.113549.1.9.3"] = OIDName{ShortName: "contentType", LongName: "contentType"} + oidDotNotationToNames["1.2.840.113549.1.9.4"] = OIDName{ShortName: "messageDigest", LongName: "messageDigest"} + oidDotNotationToNames["1.2.840.113549.1.9.5"] = OIDName{ShortName: "signingTime", LongName: "signingTime"} + oidDotNotationToNames["1.2.840.113549.1.9.6"] = OIDName{ShortName: "countersignature", LongName: "countersignature"} + oidDotNotationToNames["1.2.840.113549.1.9.7"] = OIDName{ShortName: "challengePassword", LongName: "challengePassword"} + oidDotNotationToNames["1.2.840.113549.1.9.8"] = OIDName{ShortName: "unstructuredAddress", LongName: "unstructuredAddress"} + oidDotNotationToNames["1.2.840.113549.1.9.9"] = OIDName{ShortName: "extendedCertificateAttributes", LongName: "extendedCertificateAttributes"} + oidDotNotationToNames["2.16.840.1.113730"] = OIDName{ShortName: "Netscape", LongName: "Netscape Communications Corp."} + oidDotNotationToNames["2.16.840.1.113730.1"] = OIDName{ShortName: "nsCertExt", LongName: "Netscape Certificate Extension"} + oidDotNotationToNames["2.16.840.1.113730.2"] = OIDName{ShortName: "nsDataType", LongName: "Netscape Data Type"} + oidDotNotationToNames["1.3.14.3.2.26"] = OIDName{ShortName: "SHA1", LongName: "sha1"} + oidDotNotationToNames["1.2.840.113549.1.1.5"] = OIDName{ShortName: "RSA-SHA1", LongName: "sha1WithRSAEncryption"} + oidDotNotationToNames["1.3.14.3.2.13"] = OIDName{ShortName: "DSA-SHA", LongName: "dsaWithSHA"} + oidDotNotationToNames["1.3.14.3.2.12"] = OIDName{ShortName: "DSA-old", LongName: "dsaEncryption-old"} + oidDotNotationToNames["1.2.840.113549.1.5.11"] = OIDName{ShortName: "PBE-SHA1-RC2-64", LongName: "pbeWithSHA1AndRC2-CBC"} + oidDotNotationToNames["1.2.840.113549.1.5.12"] = OIDName{ShortName: "PBKDF2", LongName: "PBKDF2"} + oidDotNotationToNames["1.3.14.3.2.27"] = OIDName{ShortName: "DSA-SHA1-old", LongName: "dsaWithSHA1-old"} + oidDotNotationToNames["2.16.840.1.113730.1.1"] = OIDName{ShortName: "nsCertType", LongName: "Netscape Cert Type"} + oidDotNotationToNames["2.16.840.1.113730.1.2"] = OIDName{ShortName: "nsBaseUrl", LongName: "Netscape Base Url"} + oidDotNotationToNames["2.16.840.1.113730.1.3"] = OIDName{ShortName: "nsRevocationUrl", LongName: "Netscape Revocation Url"} + oidDotNotationToNames["2.16.840.1.113730.1.4"] = OIDName{ShortName: "nsCaRevocationUrl", LongName: "Netscape CA Revocation Url"} + oidDotNotationToNames["2.16.840.1.113730.1.7"] = OIDName{ShortName: "nsRenewalUrl", LongName: "Netscape Renewal Url"} + oidDotNotationToNames["2.16.840.1.113730.1.8"] = OIDName{ShortName: "nsCaPolicyUrl", LongName: "Netscape CA Policy Url"} + oidDotNotationToNames["2.16.840.1.113730.1.12"] = OIDName{ShortName: "nsSslServerName", LongName: "Netscape SSL Server Name"} + oidDotNotationToNames["2.16.840.1.113730.1.13"] = OIDName{ShortName: "nsComment", LongName: "Netscape Comment"} + oidDotNotationToNames["2.16.840.1.113730.2.5"] = OIDName{ShortName: "nsCertSequence", LongName: "Netscape Certificate Sequence"} + oidDotNotationToNames["2.5.29"] = OIDName{ShortName: "id-ce", LongName: "id-ce"} + oidDotNotationToNames["2.5.29.14"] = OIDName{ShortName: "subjectKeyIdentifier", LongName: "X509v3 Subject Key Identifier"} + oidDotNotationToNames["2.5.29.15"] = OIDName{ShortName: "keyUsage", LongName: "X509v3 Key Usage"} + oidDotNotationToNames["2.5.29.16"] = OIDName{ShortName: "privateKeyUsagePeriod", LongName: "X509v3 Private Key Usage Period"} + oidDotNotationToNames["2.5.29.17"] = OIDName{ShortName: "subjectAltName", LongName: "X509v3 Subject Alternative Name"} + oidDotNotationToNames["2.5.29.18"] = OIDName{ShortName: "issuerAltName", LongName: "X509v3 Issuer Alternative Name"} + oidDotNotationToNames["2.5.29.19"] = OIDName{ShortName: "basicConstraints", LongName: "X509v3 Basic Constraints"} + oidDotNotationToNames["2.5.29.20"] = OIDName{ShortName: "crlNumber", LongName: "X509v3 CRL Number"} + oidDotNotationToNames["2.5.29.32"] = OIDName{ShortName: "certificatePolicies", LongName: "X509v3 Certificate Policies"} + oidDotNotationToNames["2.5.29.35"] = OIDName{ShortName: "authorityKeyIdentifier", LongName: "X509v3 Authority Key Identifier"} + oidDotNotationToNames["1.3.6.1.4.1.3029.1.2"] = OIDName{ShortName: "BF-CBC", LongName: "bf-cbc"} + oidDotNotationToNames["2.5.8.3.101"] = OIDName{ShortName: "MDC2", LongName: "mdc2"} + oidDotNotationToNames["2.5.8.3.100"] = OIDName{ShortName: "RSA-MDC2", LongName: "mdc2WithRSA"} + oidDotNotationToNames["2.5.4.42"] = OIDName{ShortName: "GN", LongName: "givenName"} + oidDotNotationToNames["2.5.4.4"] = OIDName{ShortName: "SN", LongName: "surname"} + oidDotNotationToNames["2.5.4.43"] = OIDName{ShortName: "initials", LongName: "initials"} + oidDotNotationToNames["2.5.29.31"] = OIDName{ShortName: "crlDistributionPoints", LongName: "X509v3 CRL Distribution Points"} + oidDotNotationToNames["1.3.14.3.2.3"] = OIDName{ShortName: "RSA-NP-MD5", LongName: "md5WithRSA"} + oidDotNotationToNames["2.5.4.5"] = OIDName{ShortName: "serialNumber", LongName: "serialNumber"} + oidDotNotationToNames["2.5.4.12"] = OIDName{ShortName: "title", LongName: "title"} + oidDotNotationToNames["2.5.4.13"] = OIDName{ShortName: "description", LongName: "description"} + oidDotNotationToNames["1.2.840.113533.7.66.10"] = OIDName{ShortName: "CAST5-CBC", LongName: "cast5-cbc"} + oidDotNotationToNames["1.2.840.113533.7.66.12"] = OIDName{ShortName: "pbeWithMD5AndCast5CBC", LongName: "pbeWithMD5AndCast5CBC"} + oidDotNotationToNames["1.2.840.10040.4.3"] = OIDName{ShortName: "DSA-SHA1", LongName: "dsaWithSHA1"} + oidDotNotationToNames["1.3.14.3.2.29"] = OIDName{ShortName: "RSA-SHA1-2", LongName: "sha1WithRSA"} + oidDotNotationToNames["1.2.840.10040.4.1"] = OIDName{ShortName: "DSA", LongName: "dsaEncryption"} + oidDotNotationToNames["1.3.36.3.2.1"] = OIDName{ShortName: "RIPEMD160", LongName: "ripemd160"} + oidDotNotationToNames["1.3.36.3.3.1.2"] = OIDName{ShortName: "RSA-RIPEMD160", LongName: "ripemd160WithRSA"} + oidDotNotationToNames["1.2.840.113549.3.8"] = OIDName{ShortName: "RC5-CBC", LongName: "rc5-cbc"} + oidDotNotationToNames["1.1.1.1.666.1"] = OIDName{ShortName: "RLE", LongName: "run length compression"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.8"] = OIDName{ShortName: "ZLIB", LongName: "zlib compression"} + oidDotNotationToNames["2.5.29.37"] = OIDName{ShortName: "extendedKeyUsage", LongName: "X509v3 Extended Key Usage"} + oidDotNotationToNames["1.3.6.1.5.5.7"] = OIDName{ShortName: "PKIX", LongName: "PKIX"} + oidDotNotationToNames["1.3.6.1.5.5.7.3"] = OIDName{ShortName: "id-kp", LongName: "id-kp"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.1"] = OIDName{ShortName: "serverAuth", LongName: "TLS Web Server Authentication"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.2"] = OIDName{ShortName: "clientAuth", LongName: "TLS Web Client Authentication"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.3"] = OIDName{ShortName: "codeSigning", LongName: "Code Signing"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.4"] = OIDName{ShortName: "emailProtection", LongName: "E-mail Protection"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.8"] = OIDName{ShortName: "timeStamping", LongName: "Time Stamping"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.21"] = OIDName{ShortName: "msCodeInd", LongName: "Microsoft Individual Code Signing"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.22"] = OIDName{ShortName: "msCodeCom", LongName: "Microsoft Commercial Code Signing"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.1"] = OIDName{ShortName: "msCTLSign", LongName: "Microsoft Trust List Signing"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.3"] = OIDName{ShortName: "msSGC", LongName: "Microsoft Server Gated Crypto"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.4"] = OIDName{ShortName: "msEFS", LongName: "Microsoft Encrypted File System"} + oidDotNotationToNames["2.16.840.1.113730.4.1"] = OIDName{ShortName: "nsSGC", LongName: "Netscape Server Gated Crypto"} + oidDotNotationToNames["2.5.29.27"] = OIDName{ShortName: "deltaCRL", LongName: "X509v3 Delta CRL Indicator"} + oidDotNotationToNames["2.5.29.21"] = OIDName{ShortName: "CRLReason", LongName: "X509v3 CRL Reason Code"} + oidDotNotationToNames["2.5.29.24"] = OIDName{ShortName: "invalidityDate", LongName: "Invalidity Date"} + oidDotNotationToNames["1.3.101.1.4.1"] = OIDName{ShortName: "SXNetID", LongName: "Strong Extranet ID"} + oidDotNotationToNames["1.2.840.113549.1.12.1.1"] = OIDName{ShortName: "PBE-SHA1-RC4-128", LongName: "pbeWithSHA1And128BitRC4"} + oidDotNotationToNames["1.2.840.113549.1.12.1.2"] = OIDName{ShortName: "PBE-SHA1-RC4-40", LongName: "pbeWithSHA1And40BitRC4"} + oidDotNotationToNames["1.2.840.113549.1.12.1.3"] = OIDName{ShortName: "PBE-SHA1-3DES", LongName: "pbeWithSHA1And3-KeyTripleDES-CBC"} + oidDotNotationToNames["1.2.840.113549.1.12.1.4"] = OIDName{ShortName: "PBE-SHA1-2DES", LongName: "pbeWithSHA1And2-KeyTripleDES-CBC"} + oidDotNotationToNames["1.2.840.113549.1.12.1.5"] = OIDName{ShortName: "PBE-SHA1-RC2-128", LongName: "pbeWithSHA1And128BitRC2-CBC"} + oidDotNotationToNames["1.2.840.113549.1.12.1.6"] = OIDName{ShortName: "PBE-SHA1-RC2-40", LongName: "pbeWithSHA1And40BitRC2-CBC"} + oidDotNotationToNames["1.2.840.113549.1.12.10.1.1"] = OIDName{ShortName: "keyBag", LongName: "keyBag"} + oidDotNotationToNames["1.2.840.113549.1.12.10.1.2"] = OIDName{ShortName: "pkcs8ShroudedKeyBag", LongName: "pkcs8ShroudedKeyBag"} + oidDotNotationToNames["1.2.840.113549.1.12.10.1.3"] = OIDName{ShortName: "certBag", LongName: "certBag"} + oidDotNotationToNames["1.2.840.113549.1.12.10.1.4"] = OIDName{ShortName: "crlBag", LongName: "crlBag"} + oidDotNotationToNames["1.2.840.113549.1.12.10.1.5"] = OIDName{ShortName: "secretBag", LongName: "secretBag"} + oidDotNotationToNames["1.2.840.113549.1.12.10.1.6"] = OIDName{ShortName: "safeContentsBag", LongName: "safeContentsBag"} + oidDotNotationToNames["1.2.840.113549.1.9.20"] = OIDName{ShortName: "friendlyName", LongName: "friendlyName"} + oidDotNotationToNames["1.2.840.113549.1.9.21"] = OIDName{ShortName: "localKeyID", LongName: "localKeyID"} + oidDotNotationToNames["1.2.840.113549.1.9.22.1"] = OIDName{ShortName: "x509Certificate", LongName: "x509Certificate"} + oidDotNotationToNames["1.2.840.113549.1.9.22.2"] = OIDName{ShortName: "sdsiCertificate", LongName: "sdsiCertificate"} + oidDotNotationToNames["1.2.840.113549.1.9.23.1"] = OIDName{ShortName: "x509Crl", LongName: "x509Crl"} + oidDotNotationToNames["1.2.840.113549.1.5.13"] = OIDName{ShortName: "PBES2", LongName: "PBES2"} + oidDotNotationToNames["1.2.840.113549.1.5.14"] = OIDName{ShortName: "PBMAC1", LongName: "PBMAC1"} + oidDotNotationToNames["1.2.840.113549.2.7"] = OIDName{ShortName: "hmacWithSHA1", LongName: "hmacWithSHA1"} + oidDotNotationToNames["1.3.6.1.5.5.7.2.1"] = OIDName{ShortName: "id-qt-cps", LongName: "Policy Qualifier CPS"} + oidDotNotationToNames["1.3.6.1.5.5.7.2.2"] = OIDName{ShortName: "id-qt-unotice", LongName: "Policy Qualifier User Notice"} + oidDotNotationToNames["1.2.840.113549.1.9.15"] = OIDName{ShortName: "SMIME-CAPS", LongName: "S/MIME Capabilities"} + oidDotNotationToNames["1.2.840.113549.1.5.4"] = OIDName{ShortName: "PBE-MD2-RC2-64", LongName: "pbeWithMD2AndRC2-CBC"} + oidDotNotationToNames["1.2.840.113549.1.5.6"] = OIDName{ShortName: "PBE-MD5-RC2-64", LongName: "pbeWithMD5AndRC2-CBC"} + oidDotNotationToNames["1.2.840.113549.1.5.10"] = OIDName{ShortName: "PBE-SHA1-DES", LongName: "pbeWithSHA1AndDES-CBC"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.14"] = OIDName{ShortName: "msExtReq", LongName: "Microsoft Extension Request"} + oidDotNotationToNames["1.2.840.113549.1.9.14"] = OIDName{ShortName: "extReq", LongName: "Extension Request"} + oidDotNotationToNames["2.5.4.41"] = OIDName{ShortName: "name", LongName: "name"} + oidDotNotationToNames["2.5.4.46"] = OIDName{ShortName: "dnQualifier", LongName: "dnQualifier"} + oidDotNotationToNames["1.3.6.1.5.5.7.1"] = OIDName{ShortName: "id-pe", LongName: "id-pe"} + oidDotNotationToNames["1.3.6.1.5.5.7.48"] = OIDName{ShortName: "id-ad", LongName: "id-ad"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.1"] = OIDName{ShortName: "authorityInfoAccess", LongName: "Authority Information Access"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1"] = OIDName{ShortName: "OCSP", LongName: "OCSP"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.2"] = OIDName{ShortName: "caIssuers", LongName: "CA Issuers"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.9"] = OIDName{ShortName: "OCSPSigning", LongName: "OCSP Signing"} + oidDotNotationToNames["1.0"] = OIDName{ShortName: "ISO", LongName: "iso"} + oidDotNotationToNames["1.2"] = OIDName{ShortName: "member-body", LongName: "ISO Member Body"} + oidDotNotationToNames["1.2.840"] = OIDName{ShortName: "ISO-US", LongName: "ISO US Member Body"} + oidDotNotationToNames["1.2.840.10040"] = OIDName{ShortName: "X9-57", LongName: "X9.57"} + oidDotNotationToNames["1.2.840.10040.4"] = OIDName{ShortName: "X9cm", LongName: "X9.57 CM ?"} + oidDotNotationToNames["1.2.840.113549.1.1"] = OIDName{ShortName: "pkcs1", LongName: "pkcs1"} + oidDotNotationToNames["1.2.840.113549.1.5"] = OIDName{ShortName: "pkcs5", LongName: "pkcs5"} + oidDotNotationToNames["1.2.840.113549.1.9.16"] = OIDName{ShortName: "SMIME", LongName: "S/MIME"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0"] = OIDName{ShortName: "id-smime-mod", LongName: "id-smime-mod"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1"] = OIDName{ShortName: "id-smime-ct", LongName: "id-smime-ct"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2"] = OIDName{ShortName: "id-smime-aa", LongName: "id-smime-aa"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3"] = OIDName{ShortName: "id-smime-alg", LongName: "id-smime-alg"} + oidDotNotationToNames["1.2.840.113549.1.9.16.4"] = OIDName{ShortName: "id-smime-cd", LongName: "id-smime-cd"} + oidDotNotationToNames["1.2.840.113549.1.9.16.5"] = OIDName{ShortName: "id-smime-spq", LongName: "id-smime-spq"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6"] = OIDName{ShortName: "id-smime-cti", LongName: "id-smime-cti"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.1"] = OIDName{ShortName: "id-smime-mod-cms", LongName: "id-smime-mod-cms"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.2"] = OIDName{ShortName: "id-smime-mod-ess", LongName: "id-smime-mod-ess"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.3"] = OIDName{ShortName: "id-smime-mod-oid", LongName: "id-smime-mod-oid"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.4"] = OIDName{ShortName: "id-smime-mod-msg-v3", LongName: "id-smime-mod-msg-v3"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.5"] = OIDName{ShortName: "id-smime-mod-ets-eSignature-88", LongName: "id-smime-mod-ets-eSignature-88"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.6"] = OIDName{ShortName: "id-smime-mod-ets-eSignature-97", LongName: "id-smime-mod-ets-eSignature-97"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.7"] = OIDName{ShortName: "id-smime-mod-ets-eSigPolicy-88", LongName: "id-smime-mod-ets-eSigPolicy-88"} + oidDotNotationToNames["1.2.840.113549.1.9.16.0.8"] = OIDName{ShortName: "id-smime-mod-ets-eSigPolicy-97", LongName: "id-smime-mod-ets-eSigPolicy-97"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.1"] = OIDName{ShortName: "id-smime-ct-receipt", LongName: "id-smime-ct-receipt"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.2"] = OIDName{ShortName: "id-smime-ct-authData", LongName: "id-smime-ct-authData"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.3"] = OIDName{ShortName: "id-smime-ct-publishCert", LongName: "id-smime-ct-publishCert"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.4"] = OIDName{ShortName: "id-smime-ct-TSTInfo", LongName: "id-smime-ct-TSTInfo"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.5"] = OIDName{ShortName: "id-smime-ct-TDTInfo", LongName: "id-smime-ct-TDTInfo"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.6"] = OIDName{ShortName: "id-smime-ct-contentInfo", LongName: "id-smime-ct-contentInfo"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.7"] = OIDName{ShortName: "id-smime-ct-DVCSRequestData", LongName: "id-smime-ct-DVCSRequestData"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.8"] = OIDName{ShortName: "id-smime-ct-DVCSResponseData", LongName: "id-smime-ct-DVCSResponseData"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.1"] = OIDName{ShortName: "id-smime-aa-receiptRequest", LongName: "id-smime-aa-receiptRequest"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.2"] = OIDName{ShortName: "id-smime-aa-securityLabel", LongName: "id-smime-aa-securityLabel"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.3"] = OIDName{ShortName: "id-smime-aa-mlExpandHistory", LongName: "id-smime-aa-mlExpandHistory"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.4"] = OIDName{ShortName: "id-smime-aa-contentHint", LongName: "id-smime-aa-contentHint"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.5"] = OIDName{ShortName: "id-smime-aa-msgSigDigest", LongName: "id-smime-aa-msgSigDigest"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.6"] = OIDName{ShortName: "id-smime-aa-encapContentType", LongName: "id-smime-aa-encapContentType"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.7"] = OIDName{ShortName: "id-smime-aa-contentIdentifier", LongName: "id-smime-aa-contentIdentifier"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.8"] = OIDName{ShortName: "id-smime-aa-macValue", LongName: "id-smime-aa-macValue"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.9"] = OIDName{ShortName: "id-smime-aa-equivalentLabels", LongName: "id-smime-aa-equivalentLabels"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.10"] = OIDName{ShortName: "id-smime-aa-contentReference", LongName: "id-smime-aa-contentReference"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.11"] = OIDName{ShortName: "id-smime-aa-encrypKeyPref", LongName: "id-smime-aa-encrypKeyPref"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.12"] = OIDName{ShortName: "id-smime-aa-signingCertificate", LongName: "id-smime-aa-signingCertificate"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.13"] = OIDName{ShortName: "id-smime-aa-smimeEncryptCerts", LongName: "id-smime-aa-smimeEncryptCerts"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.14"] = OIDName{ShortName: "id-smime-aa-timeStampToken", LongName: "id-smime-aa-timeStampToken"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.15"] = OIDName{ShortName: "id-smime-aa-ets-sigPolicyId", LongName: "id-smime-aa-ets-sigPolicyId"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.16"] = OIDName{ShortName: "id-smime-aa-ets-commitmentType", LongName: "id-smime-aa-ets-commitmentType"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.17"] = OIDName{ShortName: "id-smime-aa-ets-signerLocation", LongName: "id-smime-aa-ets-signerLocation"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.18"] = OIDName{ShortName: "id-smime-aa-ets-signerAttr", LongName: "id-smime-aa-ets-signerAttr"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.19"] = OIDName{ShortName: "id-smime-aa-ets-otherSigCert", LongName: "id-smime-aa-ets-otherSigCert"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.20"] = OIDName{ShortName: "id-smime-aa-ets-contentTimestamp", LongName: "id-smime-aa-ets-contentTimestamp"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.21"] = OIDName{ShortName: "id-smime-aa-ets-CertificateRefs", LongName: "id-smime-aa-ets-CertificateRefs"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.22"] = OIDName{ShortName: "id-smime-aa-ets-RevocationRefs", LongName: "id-smime-aa-ets-RevocationRefs"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.23"] = OIDName{ShortName: "id-smime-aa-ets-certValues", LongName: "id-smime-aa-ets-certValues"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.24"] = OIDName{ShortName: "id-smime-aa-ets-revocationValues", LongName: "id-smime-aa-ets-revocationValues"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.25"] = OIDName{ShortName: "id-smime-aa-ets-escTimeStamp", LongName: "id-smime-aa-ets-escTimeStamp"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.26"] = OIDName{ShortName: "id-smime-aa-ets-certCRLTimestamp", LongName: "id-smime-aa-ets-certCRLTimestamp"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.27"] = OIDName{ShortName: "id-smime-aa-ets-archiveTimeStamp", LongName: "id-smime-aa-ets-archiveTimeStamp"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.28"] = OIDName{ShortName: "id-smime-aa-signatureType", LongName: "id-smime-aa-signatureType"} + oidDotNotationToNames["1.2.840.113549.1.9.16.2.29"] = OIDName{ShortName: "id-smime-aa-dvcs-dvc", LongName: "id-smime-aa-dvcs-dvc"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.1"] = OIDName{ShortName: "id-smime-alg-ESDHwith3DES", LongName: "id-smime-alg-ESDHwith3DES"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.2"] = OIDName{ShortName: "id-smime-alg-ESDHwithRC2", LongName: "id-smime-alg-ESDHwithRC2"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.3"] = OIDName{ShortName: "id-smime-alg-3DESwrap", LongName: "id-smime-alg-3DESwrap"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.4"] = OIDName{ShortName: "id-smime-alg-RC2wrap", LongName: "id-smime-alg-RC2wrap"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.5"] = OIDName{ShortName: "id-smime-alg-ESDH", LongName: "id-smime-alg-ESDH"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.6"] = OIDName{ShortName: "id-smime-alg-CMS3DESwrap", LongName: "id-smime-alg-CMS3DESwrap"} + oidDotNotationToNames["1.2.840.113549.1.9.16.3.7"] = OIDName{ShortName: "id-smime-alg-CMSRC2wrap", LongName: "id-smime-alg-CMSRC2wrap"} + oidDotNotationToNames["1.2.840.113549.1.9.16.4.1"] = OIDName{ShortName: "id-smime-cd-ldap", LongName: "id-smime-cd-ldap"} + oidDotNotationToNames["1.2.840.113549.1.9.16.5.1"] = OIDName{ShortName: "id-smime-spq-ets-sqt-uri", LongName: "id-smime-spq-ets-sqt-uri"} + oidDotNotationToNames["1.2.840.113549.1.9.16.5.2"] = OIDName{ShortName: "id-smime-spq-ets-sqt-unotice", LongName: "id-smime-spq-ets-sqt-unotice"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6.1"] = OIDName{ShortName: "id-smime-cti-ets-proofOfOrigin", LongName: "id-smime-cti-ets-proofOfOrigin"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6.2"] = OIDName{ShortName: "id-smime-cti-ets-proofOfReceipt", LongName: "id-smime-cti-ets-proofOfReceipt"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6.3"] = OIDName{ShortName: "id-smime-cti-ets-proofOfDelivery", LongName: "id-smime-cti-ets-proofOfDelivery"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6.4"] = OIDName{ShortName: "id-smime-cti-ets-proofOfSender", LongName: "id-smime-cti-ets-proofOfSender"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6.5"] = OIDName{ShortName: "id-smime-cti-ets-proofOfApproval", LongName: "id-smime-cti-ets-proofOfApproval"} + oidDotNotationToNames["1.2.840.113549.1.9.16.6.6"] = OIDName{ShortName: "id-smime-cti-ets-proofOfCreation", LongName: "id-smime-cti-ets-proofOfCreation"} + oidDotNotationToNames["1.2.840.113549.2.4"] = OIDName{ShortName: "MD4", LongName: "md4"} + oidDotNotationToNames["1.3.6.1.5.5.7.0"] = OIDName{ShortName: "id-pkix-mod", LongName: "id-pkix-mod"} + oidDotNotationToNames["1.3.6.1.5.5.7.2"] = OIDName{ShortName: "id-qt", LongName: "id-qt"} + oidDotNotationToNames["1.3.6.1.5.5.7.4"] = OIDName{ShortName: "id-it", LongName: "id-it"} + oidDotNotationToNames["1.3.6.1.5.5.7.5"] = OIDName{ShortName: "id-pkip", LongName: "id-pkip"} + oidDotNotationToNames["1.3.6.1.5.5.7.6"] = OIDName{ShortName: "id-alg", LongName: "id-alg"} + oidDotNotationToNames["1.3.6.1.5.5.7.7"] = OIDName{ShortName: "id-cmc", LongName: "id-cmc"} + oidDotNotationToNames["1.3.6.1.5.5.7.8"] = OIDName{ShortName: "id-on", LongName: "id-on"} + oidDotNotationToNames["1.3.6.1.5.5.7.9"] = OIDName{ShortName: "id-pda", LongName: "id-pda"} + oidDotNotationToNames["1.3.6.1.5.5.7.10"] = OIDName{ShortName: "id-aca", LongName: "id-aca"} + oidDotNotationToNames["1.3.6.1.5.5.7.11"] = OIDName{ShortName: "id-qcs", LongName: "id-qcs"} + oidDotNotationToNames["1.3.6.1.5.5.7.12"] = OIDName{ShortName: "id-cct", LongName: "id-cct"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.1"] = OIDName{ShortName: "id-pkix1-explicit-88", LongName: "id-pkix1-explicit-88"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.2"] = OIDName{ShortName: "id-pkix1-implicit-88", LongName: "id-pkix1-implicit-88"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.3"] = OIDName{ShortName: "id-pkix1-explicit-93", LongName: "id-pkix1-explicit-93"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.4"] = OIDName{ShortName: "id-pkix1-implicit-93", LongName: "id-pkix1-implicit-93"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.5"] = OIDName{ShortName: "id-mod-crmf", LongName: "id-mod-crmf"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.6"] = OIDName{ShortName: "id-mod-cmc", LongName: "id-mod-cmc"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.7"] = OIDName{ShortName: "id-mod-kea-profile-88", LongName: "id-mod-kea-profile-88"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.8"] = OIDName{ShortName: "id-mod-kea-profile-93", LongName: "id-mod-kea-profile-93"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.9"] = OIDName{ShortName: "id-mod-cmp", LongName: "id-mod-cmp"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.10"] = OIDName{ShortName: "id-mod-qualified-cert-88", LongName: "id-mod-qualified-cert-88"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.11"] = OIDName{ShortName: "id-mod-qualified-cert-93", LongName: "id-mod-qualified-cert-93"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.12"] = OIDName{ShortName: "id-mod-attribute-cert", LongName: "id-mod-attribute-cert"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.13"] = OIDName{ShortName: "id-mod-timestamp-protocol", LongName: "id-mod-timestamp-protocol"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.14"] = OIDName{ShortName: "id-mod-ocsp", LongName: "id-mod-ocsp"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.15"] = OIDName{ShortName: "id-mod-dvcs", LongName: "id-mod-dvcs"} + oidDotNotationToNames["1.3.6.1.5.5.7.0.16"] = OIDName{ShortName: "id-mod-cmp2000", LongName: "id-mod-cmp2000"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.2"] = OIDName{ShortName: "biometricInfo", LongName: "Biometric Info"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.3"] = OIDName{ShortName: "qcStatements", LongName: "qcStatements"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.4"] = OIDName{ShortName: "ac-auditEntity", LongName: "ac-auditEntity"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.5"] = OIDName{ShortName: "ac-targeting", LongName: "ac-targeting"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.6"] = OIDName{ShortName: "aaControls", LongName: "aaControls"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.7"] = OIDName{ShortName: "sbgp-ipAddrBlock", LongName: "sbgp-ipAddrBlock"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.8"] = OIDName{ShortName: "sbgp-autonomousSysNum", LongName: "sbgp-autonomousSysNum"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.9"] = OIDName{ShortName: "sbgp-routerIdentifier", LongName: "sbgp-routerIdentifier"} + oidDotNotationToNames["1.3.6.1.5.5.7.2.3"] = OIDName{ShortName: "textNotice", LongName: "textNotice"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.5"] = OIDName{ShortName: "ipsecEndSystem", LongName: "IPSec End System"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.6"] = OIDName{ShortName: "ipsecTunnel", LongName: "IPSec Tunnel"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.7"] = OIDName{ShortName: "ipsecUser", LongName: "IPSec User"} + oidDotNotationToNames["1.3.6.1.5.5.7.3.10"] = OIDName{ShortName: "DVCS", LongName: "dvcs"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.1"] = OIDName{ShortName: "id-it-caProtEncCert", LongName: "id-it-caProtEncCert"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.2"] = OIDName{ShortName: "id-it-signKeyPairTypes", LongName: "id-it-signKeyPairTypes"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.3"] = OIDName{ShortName: "id-it-encKeyPairTypes", LongName: "id-it-encKeyPairTypes"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.4"] = OIDName{ShortName: "id-it-preferredSymmAlg", LongName: "id-it-preferredSymmAlg"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.5"] = OIDName{ShortName: "id-it-caKeyUpdateInfo", LongName: "id-it-caKeyUpdateInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.6"] = OIDName{ShortName: "id-it-currentCRL", LongName: "id-it-currentCRL"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.7"] = OIDName{ShortName: "id-it-unsupportedOIDs", LongName: "id-it-unsupportedOIDs"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.8"] = OIDName{ShortName: "id-it-subscriptionRequest", LongName: "id-it-subscriptionRequest"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.9"] = OIDName{ShortName: "id-it-subscriptionResponse", LongName: "id-it-subscriptionResponse"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.10"] = OIDName{ShortName: "id-it-keyPairParamReq", LongName: "id-it-keyPairParamReq"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.11"] = OIDName{ShortName: "id-it-keyPairParamRep", LongName: "id-it-keyPairParamRep"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.12"] = OIDName{ShortName: "id-it-revPassphrase", LongName: "id-it-revPassphrase"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.13"] = OIDName{ShortName: "id-it-implicitConfirm", LongName: "id-it-implicitConfirm"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.14"] = OIDName{ShortName: "id-it-confirmWaitTime", LongName: "id-it-confirmWaitTime"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.15"] = OIDName{ShortName: "id-it-origPKIMessage", LongName: "id-it-origPKIMessage"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1"] = OIDName{ShortName: "id-regCtrl", LongName: "id-regCtrl"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.2"] = OIDName{ShortName: "id-regInfo", LongName: "id-regInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1.1"] = OIDName{ShortName: "id-regCtrl-regToken", LongName: "id-regCtrl-regToken"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1.2"] = OIDName{ShortName: "id-regCtrl-authenticator", LongName: "id-regCtrl-authenticator"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1.3"] = OIDName{ShortName: "id-regCtrl-pkiPublicationInfo", LongName: "id-regCtrl-pkiPublicationInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1.4"] = OIDName{ShortName: "id-regCtrl-pkiArchiveOptions", LongName: "id-regCtrl-pkiArchiveOptions"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1.5"] = OIDName{ShortName: "id-regCtrl-oldCertID", LongName: "id-regCtrl-oldCertID"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.1.6"] = OIDName{ShortName: "id-regCtrl-protocolEncrKey", LongName: "id-regCtrl-protocolEncrKey"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.2.1"] = OIDName{ShortName: "id-regInfo-utf8Pairs", LongName: "id-regInfo-utf8Pairs"} + oidDotNotationToNames["1.3.6.1.5.5.7.5.2.2"] = OIDName{ShortName: "id-regInfo-certReq", LongName: "id-regInfo-certReq"} + oidDotNotationToNames["1.3.6.1.5.5.7.6.1"] = OIDName{ShortName: "id-alg-des40", LongName: "id-alg-des40"} + oidDotNotationToNames["1.3.6.1.5.5.7.6.2"] = OIDName{ShortName: "id-alg-noSignature", LongName: "id-alg-noSignature"} + oidDotNotationToNames["1.3.6.1.5.5.7.6.3"] = OIDName{ShortName: "id-alg-dh-sig-hmac-sha1", LongName: "id-alg-dh-sig-hmac-sha1"} + oidDotNotationToNames["1.3.6.1.5.5.7.6.4"] = OIDName{ShortName: "id-alg-dh-pop", LongName: "id-alg-dh-pop"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.1"] = OIDName{ShortName: "id-cmc-statusInfo", LongName: "id-cmc-statusInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.2"] = OIDName{ShortName: "id-cmc-identification", LongName: "id-cmc-identification"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.3"] = OIDName{ShortName: "id-cmc-identityProof", LongName: "id-cmc-identityProof"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.4"] = OIDName{ShortName: "id-cmc-dataReturn", LongName: "id-cmc-dataReturn"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.5"] = OIDName{ShortName: "id-cmc-transactionId", LongName: "id-cmc-transactionId"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.6"] = OIDName{ShortName: "id-cmc-senderNonce", LongName: "id-cmc-senderNonce"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.7"] = OIDName{ShortName: "id-cmc-recipientNonce", LongName: "id-cmc-recipientNonce"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.8"] = OIDName{ShortName: "id-cmc-addExtensions", LongName: "id-cmc-addExtensions"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.9"] = OIDName{ShortName: "id-cmc-encryptedPOP", LongName: "id-cmc-encryptedPOP"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.10"] = OIDName{ShortName: "id-cmc-decryptedPOP", LongName: "id-cmc-decryptedPOP"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.11"] = OIDName{ShortName: "id-cmc-lraPOPWitness", LongName: "id-cmc-lraPOPWitness"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.15"] = OIDName{ShortName: "id-cmc-getCert", LongName: "id-cmc-getCert"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.16"] = OIDName{ShortName: "id-cmc-getCRL", LongName: "id-cmc-getCRL"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.17"] = OIDName{ShortName: "id-cmc-revokeRequest", LongName: "id-cmc-revokeRequest"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.18"] = OIDName{ShortName: "id-cmc-regInfo", LongName: "id-cmc-regInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.19"] = OIDName{ShortName: "id-cmc-responseInfo", LongName: "id-cmc-responseInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.21"] = OIDName{ShortName: "id-cmc-queryPending", LongName: "id-cmc-queryPending"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.22"] = OIDName{ShortName: "id-cmc-popLinkRandom", LongName: "id-cmc-popLinkRandom"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.23"] = OIDName{ShortName: "id-cmc-popLinkWitness", LongName: "id-cmc-popLinkWitness"} + oidDotNotationToNames["1.3.6.1.5.5.7.7.24"] = OIDName{ShortName: "id-cmc-confirmCertAcceptance", LongName: "id-cmc-confirmCertAcceptance"} + oidDotNotationToNames["1.3.6.1.5.5.7.8.1"] = OIDName{ShortName: "id-on-personalData", LongName: "id-on-personalData"} + oidDotNotationToNames["1.3.6.1.5.5.7.9.1"] = OIDName{ShortName: "id-pda-dateOfBirth", LongName: "id-pda-dateOfBirth"} + oidDotNotationToNames["1.3.6.1.5.5.7.9.2"] = OIDName{ShortName: "id-pda-placeOfBirth", LongName: "id-pda-placeOfBirth"} + oidDotNotationToNames["1.3.6.1.5.5.7.9.3"] = OIDName{ShortName: "id-pda-gender", LongName: "id-pda-gender"} + oidDotNotationToNames["1.3.6.1.5.5.7.9.4"] = OIDName{ShortName: "id-pda-countryOfCitizenship", LongName: "id-pda-countryOfCitizenship"} + oidDotNotationToNames["1.3.6.1.5.5.7.9.5"] = OIDName{ShortName: "id-pda-countryOfResidence", LongName: "id-pda-countryOfResidence"} + oidDotNotationToNames["1.3.6.1.5.5.7.10.1"] = OIDName{ShortName: "id-aca-authenticationInfo", LongName: "id-aca-authenticationInfo"} + oidDotNotationToNames["1.3.6.1.5.5.7.10.2"] = OIDName{ShortName: "id-aca-accessIdentity", LongName: "id-aca-accessIdentity"} + oidDotNotationToNames["1.3.6.1.5.5.7.10.3"] = OIDName{ShortName: "id-aca-chargingIdentity", LongName: "id-aca-chargingIdentity"} + oidDotNotationToNames["1.3.6.1.5.5.7.10.4"] = OIDName{ShortName: "id-aca-group", LongName: "id-aca-group"} + oidDotNotationToNames["1.3.6.1.5.5.7.10.5"] = OIDName{ShortName: "id-aca-role", LongName: "id-aca-role"} + oidDotNotationToNames["1.3.6.1.5.5.7.11.1"] = OIDName{ShortName: "id-qcs-pkixQCSyntax-v1", LongName: "id-qcs-pkixQCSyntax-v1"} + oidDotNotationToNames["1.3.6.1.5.5.7.12.1"] = OIDName{ShortName: "id-cct-crs", LongName: "id-cct-crs"} + oidDotNotationToNames["1.3.6.1.5.5.7.12.2"] = OIDName{ShortName: "id-cct-PKIData", LongName: "id-cct-PKIData"} + oidDotNotationToNames["1.3.6.1.5.5.7.12.3"] = OIDName{ShortName: "id-cct-PKIResponse", LongName: "id-cct-PKIResponse"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.3"] = OIDName{ShortName: "ad_timestamping", LongName: "AD Time Stamping"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.4"] = OIDName{ShortName: "AD_DVCS", LongName: "ad dvcs"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.1"] = OIDName{ShortName: "basicOCSPResponse", LongName: "Basic OCSP Response"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.2"] = OIDName{ShortName: "Nonce", LongName: "OCSP Nonce"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.3"] = OIDName{ShortName: "CrlID", LongName: "OCSP CRL ID"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.4"] = OIDName{ShortName: "acceptableResponses", LongName: "Acceptable OCSP Responses"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.5"] = OIDName{ShortName: "noCheck", LongName: "OCSP No Check"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.6"] = OIDName{ShortName: "archiveCutoff", LongName: "OCSP Archive Cutoff"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.7"] = OIDName{ShortName: "serviceLocator", LongName: "OCSP Service Locator"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.8"] = OIDName{ShortName: "extendedStatus", LongName: "Extended OCSP Status"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.9"] = OIDName{ShortName: "valid", LongName: "valid"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.10"] = OIDName{ShortName: "path", LongName: "path"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.1.11"] = OIDName{ShortName: "trustRoot", LongName: "Trust Root"} + oidDotNotationToNames["1.3.14.3.2"] = OIDName{ShortName: "algorithm", LongName: "algorithm"} + oidDotNotationToNames["1.3.14.3.2.11"] = OIDName{ShortName: "rsaSignature", LongName: "rsaSignature"} + oidDotNotationToNames["2.5.8"] = OIDName{ShortName: "X500algorithms", LongName: "directory services - algorithms"} + oidDotNotationToNames["1.3"] = OIDName{ShortName: "ORG", LongName: "org"} + oidDotNotationToNames["1.3.6"] = OIDName{ShortName: "DOD", LongName: "dod"} + oidDotNotationToNames["1.3.6.1"] = OIDName{ShortName: "IANA", LongName: "iana"} + oidDotNotationToNames["1.3.6.1.1"] = OIDName{ShortName: "directory", LongName: "Directory"} + oidDotNotationToNames["1.3.6.1.2"] = OIDName{ShortName: "mgmt", LongName: "Management"} + oidDotNotationToNames["1.3.6.1.3"] = OIDName{ShortName: "experimental", LongName: "Experimental"} + oidDotNotationToNames["1.3.6.1.4"] = OIDName{ShortName: "private", LongName: "Private"} + oidDotNotationToNames["1.3.6.1.5"] = OIDName{ShortName: "security", LongName: "Security"} + oidDotNotationToNames["1.3.6.1.6"] = OIDName{ShortName: "snmpv2", LongName: "SNMPv2"} + oidDotNotationToNames["1.3.6.1.7"] = OIDName{ShortName: "Mail", LongName: "Mail"} + oidDotNotationToNames["1.3.6.1.4.1"] = OIDName{ShortName: "enterprises", LongName: "Enterprises"} + oidDotNotationToNames["1.3.6.1.4.1.1466.344"] = OIDName{ShortName: "dcobject", LongName: "dcObject"} + oidDotNotationToNames["0.9.2342.19200300.100.1.25"] = OIDName{ShortName: "DC", LongName: "domainComponent"} + oidDotNotationToNames["0.9.2342.19200300.100.4.13"] = OIDName{ShortName: "domain", LongName: "Domain"} + oidDotNotationToNames["0.0"] = OIDName{ShortName: "NULL", LongName: "NULL"} + oidDotNotationToNames["2.5.1.5"] = OIDName{ShortName: "selected-attribute-types", LongName: "Selected Attribute Types"} + oidDotNotationToNames["2.5.1.5.55"] = OIDName{ShortName: "clearance", LongName: "clearance"} + oidDotNotationToNames["1.2.840.113549.1.1.3"] = OIDName{ShortName: "RSA-MD4", LongName: "md4WithRSAEncryption"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.10"] = OIDName{ShortName: "ac-proxying", LongName: "ac-proxying"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.11"] = OIDName{ShortName: "subjectInfoAccess", LongName: "Subject Information Access"} + oidDotNotationToNames["1.3.6.1.5.5.7.10.6"] = OIDName{ShortName: "id-aca-encAttrs", LongName: "id-aca-encAttrs"} + oidDotNotationToNames["2.5.4.72"] = OIDName{ShortName: "role", LongName: "role"} + oidDotNotationToNames["2.5.29.36"] = OIDName{ShortName: "policyConstraints", LongName: "X509v3 Policy Constraints"} + oidDotNotationToNames["2.5.29.55"] = OIDName{ShortName: "targetInformation", LongName: "X509v3 AC Targeting"} + oidDotNotationToNames["2.5.29.56"] = OIDName{ShortName: "noRevAvail", LongName: "X509v3 No Revocation Available"} + oidDotNotationToNames["0.0"] = OIDName{ShortName: "NULL", LongName: "NULL"} + oidDotNotationToNames["1.2.840.10045"] = OIDName{ShortName: "ansi-X9-62", LongName: "ANSI X9.62"} + oidDotNotationToNames["1.2.840.10045.1.1"] = OIDName{ShortName: "prime-field", LongName: "prime-field"} + oidDotNotationToNames["1.2.840.10045.1.2"] = OIDName{ShortName: "characteristic-two-field", LongName: "characteristic-two-field"} + oidDotNotationToNames["1.2.840.10045.2.1"] = OIDName{ShortName: "id-ecPublicKey", LongName: "id-ecPublicKey"} + oidDotNotationToNames["1.2.840.10045.3.1.1"] = OIDName{ShortName: "prime192v1", LongName: "prime192v1"} + oidDotNotationToNames["1.2.840.10045.3.1.2"] = OIDName{ShortName: "prime192v2", LongName: "prime192v2"} + oidDotNotationToNames["1.2.840.10045.3.1.3"] = OIDName{ShortName: "prime192v3", LongName: "prime192v3"} + oidDotNotationToNames["1.2.840.10045.3.1.4"] = OIDName{ShortName: "prime239v1", LongName: "prime239v1"} + oidDotNotationToNames["1.2.840.10045.3.1.5"] = OIDName{ShortName: "prime239v2", LongName: "prime239v2"} + oidDotNotationToNames["1.2.840.10045.3.1.6"] = OIDName{ShortName: "prime239v3", LongName: "prime239v3"} + oidDotNotationToNames["1.2.840.10045.3.1.7"] = OIDName{ShortName: "prime256v1", LongName: "prime256v1"} + oidDotNotationToNames["1.2.840.10045.4.1"] = OIDName{ShortName: "ecdsa-with-SHA1", LongName: "ecdsa-with-SHA1"} + oidDotNotationToNames["1.3.6.1.4.1.311.17.1"] = OIDName{ShortName: "CSPName", LongName: "Microsoft CSP Name"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.1"] = OIDName{ShortName: "AES-128-ECB", LongName: "aes-128-ecb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.2"] = OIDName{ShortName: "AES-128-CBC", LongName: "aes-128-cbc"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.3"] = OIDName{ShortName: "AES-128-OFB", LongName: "aes-128-ofb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.4"] = OIDName{ShortName: "AES-128-CFB", LongName: "aes-128-cfb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.21"] = OIDName{ShortName: "AES-192-ECB", LongName: "aes-192-ecb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.22"] = OIDName{ShortName: "AES-192-CBC", LongName: "aes-192-cbc"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.23"] = OIDName{ShortName: "AES-192-OFB", LongName: "aes-192-ofb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.24"] = OIDName{ShortName: "AES-192-CFB", LongName: "aes-192-cfb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.41"] = OIDName{ShortName: "AES-256-ECB", LongName: "aes-256-ecb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.42"] = OIDName{ShortName: "AES-256-CBC", LongName: "aes-256-cbc"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.43"] = OIDName{ShortName: "AES-256-OFB", LongName: "aes-256-ofb"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.44"] = OIDName{ShortName: "AES-256-CFB", LongName: "aes-256-cfb"} + oidDotNotationToNames["2.5.29.23"] = OIDName{ShortName: "holdInstructionCode", LongName: "Hold Instruction Code"} + oidDotNotationToNames["1.2.840.10040.2.1"] = OIDName{ShortName: "holdInstructionNone", LongName: "Hold Instruction None"} + oidDotNotationToNames["1.2.840.10040.2.2"] = OIDName{ShortName: "holdInstructionCallIssuer", LongName: "Hold Instruction Call Issuer"} + oidDotNotationToNames["1.2.840.10040.2.3"] = OIDName{ShortName: "holdInstructionReject", LongName: "Hold Instruction Reject"} + oidDotNotationToNames["0.9"] = OIDName{ShortName: "data", LongName: "data"} + oidDotNotationToNames["0.9.2342"] = OIDName{ShortName: "pss", LongName: "pss"} + oidDotNotationToNames["0.9.2342.19200300"] = OIDName{ShortName: "ucl", LongName: "ucl"} + oidDotNotationToNames["0.9.2342.19200300.100"] = OIDName{ShortName: "pilot", LongName: "pilot"} + oidDotNotationToNames["0.9.2342.19200300.100.1"] = OIDName{ShortName: "pilotAttributeType", LongName: "pilotAttributeType"} + oidDotNotationToNames["0.9.2342.19200300.100.3"] = OIDName{ShortName: "pilotAttributeSyntax", LongName: "pilotAttributeSyntax"} + oidDotNotationToNames["0.9.2342.19200300.100.4"] = OIDName{ShortName: "pilotObjectClass", LongName: "pilotObjectClass"} + oidDotNotationToNames["0.9.2342.19200300.100.10"] = OIDName{ShortName: "pilotGroups", LongName: "pilotGroups"} + oidDotNotationToNames["0.9.2342.19200300.100.3.4"] = OIDName{ShortName: "iA5StringSyntax", LongName: "iA5StringSyntax"} + oidDotNotationToNames["0.9.2342.19200300.100.3.5"] = OIDName{ShortName: "caseIgnoreIA5StringSyntax", LongName: "caseIgnoreIA5StringSyntax"} + oidDotNotationToNames["0.9.2342.19200300.100.4.3"] = OIDName{ShortName: "pilotObject", LongName: "pilotObject"} + oidDotNotationToNames["0.9.2342.19200300.100.4.4"] = OIDName{ShortName: "pilotPerson", LongName: "pilotPerson"} + oidDotNotationToNames["0.9.2342.19200300.100.4.5"] = OIDName{ShortName: "account", LongName: "account"} + oidDotNotationToNames["0.9.2342.19200300.100.4.6"] = OIDName{ShortName: "document", LongName: "document"} + oidDotNotationToNames["0.9.2342.19200300.100.4.7"] = OIDName{ShortName: "room", LongName: "room"} + oidDotNotationToNames["0.9.2342.19200300.100.4.9"] = OIDName{ShortName: "documentSeries", LongName: "documentSeries"} + oidDotNotationToNames["0.9.2342.19200300.100.4.14"] = OIDName{ShortName: "rFC822localPart", LongName: "rFC822localPart"} + oidDotNotationToNames["0.9.2342.19200300.100.4.15"] = OIDName{ShortName: "dNSDomain", LongName: "dNSDomain"} + oidDotNotationToNames["0.9.2342.19200300.100.4.17"] = OIDName{ShortName: "domainRelatedObject", LongName: "domainRelatedObject"} + oidDotNotationToNames["0.9.2342.19200300.100.4.18"] = OIDName{ShortName: "friendlyCountry", LongName: "friendlyCountry"} + oidDotNotationToNames["0.9.2342.19200300.100.4.19"] = OIDName{ShortName: "simpleSecurityObject", LongName: "simpleSecurityObject"} + oidDotNotationToNames["0.9.2342.19200300.100.4.20"] = OIDName{ShortName: "pilotOrganization", LongName: "pilotOrganization"} + oidDotNotationToNames["0.9.2342.19200300.100.4.21"] = OIDName{ShortName: "pilotDSA", LongName: "pilotDSA"} + oidDotNotationToNames["0.9.2342.19200300.100.4.22"] = OIDName{ShortName: "qualityLabelledData", LongName: "qualityLabelledData"} + oidDotNotationToNames["0.9.2342.19200300.100.1.1"] = OIDName{ShortName: "UID", LongName: "userId"} + oidDotNotationToNames["0.9.2342.19200300.100.1.2"] = OIDName{ShortName: "textEncodedORAddress", LongName: "textEncodedORAddress"} + oidDotNotationToNames["0.9.2342.19200300.100.1.3"] = OIDName{ShortName: "mail", LongName: "rfc822Mailbox"} + oidDotNotationToNames["0.9.2342.19200300.100.1.4"] = OIDName{ShortName: "info", LongName: "info"} + oidDotNotationToNames["0.9.2342.19200300.100.1.5"] = OIDName{ShortName: "favouriteDrink", LongName: "favouriteDrink"} + oidDotNotationToNames["0.9.2342.19200300.100.1.6"] = OIDName{ShortName: "roomNumber", LongName: "roomNumber"} + oidDotNotationToNames["0.9.2342.19200300.100.1.7"] = OIDName{ShortName: "photo", LongName: "photo"} + oidDotNotationToNames["0.9.2342.19200300.100.1.8"] = OIDName{ShortName: "userClass", LongName: "userClass"} + oidDotNotationToNames["0.9.2342.19200300.100.1.9"] = OIDName{ShortName: "host", LongName: "host"} + oidDotNotationToNames["0.9.2342.19200300.100.1.10"] = OIDName{ShortName: "manager", LongName: "manager"} + oidDotNotationToNames["0.9.2342.19200300.100.1.11"] = OIDName{ShortName: "documentIdentifier", LongName: "documentIdentifier"} + oidDotNotationToNames["0.9.2342.19200300.100.1.12"] = OIDName{ShortName: "documentTitle", LongName: "documentTitle"} + oidDotNotationToNames["0.9.2342.19200300.100.1.13"] = OIDName{ShortName: "documentVersion", LongName: "documentVersion"} + oidDotNotationToNames["0.9.2342.19200300.100.1.14"] = OIDName{ShortName: "documentAuthor", LongName: "documentAuthor"} + oidDotNotationToNames["0.9.2342.19200300.100.1.15"] = OIDName{ShortName: "documentLocation", LongName: "documentLocation"} + oidDotNotationToNames["0.9.2342.19200300.100.1.20"] = OIDName{ShortName: "homeTelephoneNumber", LongName: "homeTelephoneNumber"} + oidDotNotationToNames["0.9.2342.19200300.100.1.21"] = OIDName{ShortName: "secretary", LongName: "secretary"} + oidDotNotationToNames["0.9.2342.19200300.100.1.22"] = OIDName{ShortName: "otherMailbox", LongName: "otherMailbox"} + oidDotNotationToNames["0.9.2342.19200300.100.1.23"] = OIDName{ShortName: "lastModifiedTime", LongName: "lastModifiedTime"} + oidDotNotationToNames["0.9.2342.19200300.100.1.24"] = OIDName{ShortName: "lastModifiedBy", LongName: "lastModifiedBy"} + oidDotNotationToNames["0.9.2342.19200300.100.1.26"] = OIDName{ShortName: "aRecord", LongName: "aRecord"} + oidDotNotationToNames["0.9.2342.19200300.100.1.27"] = OIDName{ShortName: "pilotAttributeType27", LongName: "pilotAttributeType27"} + oidDotNotationToNames["0.9.2342.19200300.100.1.28"] = OIDName{ShortName: "mXRecord", LongName: "mXRecord"} + oidDotNotationToNames["0.9.2342.19200300.100.1.29"] = OIDName{ShortName: "nSRecord", LongName: "nSRecord"} + oidDotNotationToNames["0.9.2342.19200300.100.1.30"] = OIDName{ShortName: "sOARecord", LongName: "sOARecord"} + oidDotNotationToNames["0.9.2342.19200300.100.1.31"] = OIDName{ShortName: "cNAMERecord", LongName: "cNAMERecord"} + oidDotNotationToNames["0.9.2342.19200300.100.1.37"] = OIDName{ShortName: "associatedDomain", LongName: "associatedDomain"} + oidDotNotationToNames["0.9.2342.19200300.100.1.38"] = OIDName{ShortName: "associatedName", LongName: "associatedName"} + oidDotNotationToNames["0.9.2342.19200300.100.1.39"] = OIDName{ShortName: "homePostalAddress", LongName: "homePostalAddress"} + oidDotNotationToNames["0.9.2342.19200300.100.1.40"] = OIDName{ShortName: "personalTitle", LongName: "personalTitle"} + oidDotNotationToNames["0.9.2342.19200300.100.1.41"] = OIDName{ShortName: "mobileTelephoneNumber", LongName: "mobileTelephoneNumber"} + oidDotNotationToNames["0.9.2342.19200300.100.1.42"] = OIDName{ShortName: "pagerTelephoneNumber", LongName: "pagerTelephoneNumber"} + oidDotNotationToNames["0.9.2342.19200300.100.1.43"] = OIDName{ShortName: "friendlyCountryName", LongName: "friendlyCountryName"} + oidDotNotationToNames["0.9.2342.19200300.100.1.45"] = OIDName{ShortName: "organizationalStatus", LongName: "organizationalStatus"} + oidDotNotationToNames["0.9.2342.19200300.100.1.46"] = OIDName{ShortName: "janetMailbox", LongName: "janetMailbox"} + oidDotNotationToNames["0.9.2342.19200300.100.1.47"] = OIDName{ShortName: "mailPreferenceOption", LongName: "mailPreferenceOption"} + oidDotNotationToNames["0.9.2342.19200300.100.1.48"] = OIDName{ShortName: "buildingName", LongName: "buildingName"} + oidDotNotationToNames["0.9.2342.19200300.100.1.49"] = OIDName{ShortName: "dSAQuality", LongName: "dSAQuality"} + oidDotNotationToNames["0.9.2342.19200300.100.1.50"] = OIDName{ShortName: "singleLevelQuality", LongName: "singleLevelQuality"} + oidDotNotationToNames["0.9.2342.19200300.100.1.51"] = OIDName{ShortName: "subtreeMinimumQuality", LongName: "subtreeMinimumQuality"} + oidDotNotationToNames["0.9.2342.19200300.100.1.52"] = OIDName{ShortName: "subtreeMaximumQuality", LongName: "subtreeMaximumQuality"} + oidDotNotationToNames["0.9.2342.19200300.100.1.53"] = OIDName{ShortName: "personalSignature", LongName: "personalSignature"} + oidDotNotationToNames["0.9.2342.19200300.100.1.54"] = OIDName{ShortName: "dITRedirect", LongName: "dITRedirect"} + oidDotNotationToNames["0.9.2342.19200300.100.1.55"] = OIDName{ShortName: "audio", LongName: "audio"} + oidDotNotationToNames["0.9.2342.19200300.100.1.56"] = OIDName{ShortName: "documentPublisher", LongName: "documentPublisher"} + oidDotNotationToNames["2.5.4.45"] = OIDName{ShortName: "x500UniqueIdentifier", LongName: "x500UniqueIdentifier"} + oidDotNotationToNames["1.3.6.1.7.1"] = OIDName{ShortName: "mime-mhs", LongName: "MIME MHS"} + oidDotNotationToNames["1.3.6.1.7.1.1"] = OIDName{ShortName: "mime-mhs-headings", LongName: "mime-mhs-headings"} + oidDotNotationToNames["1.3.6.1.7.1.2"] = OIDName{ShortName: "mime-mhs-bodies", LongName: "mime-mhs-bodies"} + oidDotNotationToNames["1.3.6.1.7.1.1.1"] = OIDName{ShortName: "id-hex-partial-message", LongName: "id-hex-partial-message"} + oidDotNotationToNames["1.3.6.1.7.1.1.2"] = OIDName{ShortName: "id-hex-multipart-message", LongName: "id-hex-multipart-message"} + oidDotNotationToNames["2.5.4.44"] = OIDName{ShortName: "generationQualifier", LongName: "generationQualifier"} + oidDotNotationToNames["2.5.4.65"] = OIDName{ShortName: "pseudonym", LongName: "pseudonym"} + oidDotNotationToNames["2.23.42"] = OIDName{ShortName: "id-set", LongName: "Secure Electronic Transactions"} + oidDotNotationToNames["2.23.42.0"] = OIDName{ShortName: "set-ctype", LongName: "content types"} + oidDotNotationToNames["2.23.42.1"] = OIDName{ShortName: "set-msgExt", LongName: "message extensions"} + oidDotNotationToNames["2.23.42.3"] = OIDName{ShortName: "set-attr", LongName: "set-attr"} + oidDotNotationToNames["2.23.42.5"] = OIDName{ShortName: "set-policy", LongName: "set-policy"} + oidDotNotationToNames["2.23.42.7"] = OIDName{ShortName: "set-certExt", LongName: "certificate extensions"} + oidDotNotationToNames["2.23.42.8"] = OIDName{ShortName: "set-brand", LongName: "set-brand"} + oidDotNotationToNames["2.23.42.0.0"] = OIDName{ShortName: "setct-PANData", LongName: "setct-PANData"} + oidDotNotationToNames["2.23.42.0.1"] = OIDName{ShortName: "setct-PANToken", LongName: "setct-PANToken"} + oidDotNotationToNames["2.23.42.0.2"] = OIDName{ShortName: "setct-PANOnly", LongName: "setct-PANOnly"} + oidDotNotationToNames["2.23.42.0.3"] = OIDName{ShortName: "setct-OIData", LongName: "setct-OIData"} + oidDotNotationToNames["2.23.42.0.4"] = OIDName{ShortName: "setct-PI", LongName: "setct-PI"} + oidDotNotationToNames["2.23.42.0.5"] = OIDName{ShortName: "setct-PIData", LongName: "setct-PIData"} + oidDotNotationToNames["2.23.42.0.6"] = OIDName{ShortName: "setct-PIDataUnsigned", LongName: "setct-PIDataUnsigned"} + oidDotNotationToNames["2.23.42.0.7"] = OIDName{ShortName: "setct-HODInput", LongName: "setct-HODInput"} + oidDotNotationToNames["2.23.42.0.8"] = OIDName{ShortName: "setct-AuthResBaggage", LongName: "setct-AuthResBaggage"} + oidDotNotationToNames["2.23.42.0.9"] = OIDName{ShortName: "setct-AuthRevReqBaggage", LongName: "setct-AuthRevReqBaggage"} + oidDotNotationToNames["2.23.42.0.10"] = OIDName{ShortName: "setct-AuthRevResBaggage", LongName: "setct-AuthRevResBaggage"} + oidDotNotationToNames["2.23.42.0.11"] = OIDName{ShortName: "setct-CapTokenSeq", LongName: "setct-CapTokenSeq"} + oidDotNotationToNames["2.23.42.0.12"] = OIDName{ShortName: "setct-PInitResData", LongName: "setct-PInitResData"} + oidDotNotationToNames["2.23.42.0.13"] = OIDName{ShortName: "setct-PI-TBS", LongName: "setct-PI-TBS"} + oidDotNotationToNames["2.23.42.0.14"] = OIDName{ShortName: "setct-PResData", LongName: "setct-PResData"} + oidDotNotationToNames["2.23.42.0.16"] = OIDName{ShortName: "setct-AuthReqTBS", LongName: "setct-AuthReqTBS"} + oidDotNotationToNames["2.23.42.0.17"] = OIDName{ShortName: "setct-AuthResTBS", LongName: "setct-AuthResTBS"} + oidDotNotationToNames["2.23.42.0.18"] = OIDName{ShortName: "setct-AuthResTBSX", LongName: "setct-AuthResTBSX"} + oidDotNotationToNames["2.23.42.0.19"] = OIDName{ShortName: "setct-AuthTokenTBS", LongName: "setct-AuthTokenTBS"} + oidDotNotationToNames["2.23.42.0.20"] = OIDName{ShortName: "setct-CapTokenData", LongName: "setct-CapTokenData"} + oidDotNotationToNames["2.23.42.0.21"] = OIDName{ShortName: "setct-CapTokenTBS", LongName: "setct-CapTokenTBS"} + oidDotNotationToNames["2.23.42.0.22"] = OIDName{ShortName: "setct-AcqCardCodeMsg", LongName: "setct-AcqCardCodeMsg"} + oidDotNotationToNames["2.23.42.0.23"] = OIDName{ShortName: "setct-AuthRevReqTBS", LongName: "setct-AuthRevReqTBS"} + oidDotNotationToNames["2.23.42.0.24"] = OIDName{ShortName: "setct-AuthRevResData", LongName: "setct-AuthRevResData"} + oidDotNotationToNames["2.23.42.0.25"] = OIDName{ShortName: "setct-AuthRevResTBS", LongName: "setct-AuthRevResTBS"} + oidDotNotationToNames["2.23.42.0.26"] = OIDName{ShortName: "setct-CapReqTBS", LongName: "setct-CapReqTBS"} + oidDotNotationToNames["2.23.42.0.27"] = OIDName{ShortName: "setct-CapReqTBSX", LongName: "setct-CapReqTBSX"} + oidDotNotationToNames["2.23.42.0.28"] = OIDName{ShortName: "setct-CapResData", LongName: "setct-CapResData"} + oidDotNotationToNames["2.23.42.0.29"] = OIDName{ShortName: "setct-CapRevReqTBS", LongName: "setct-CapRevReqTBS"} + oidDotNotationToNames["2.23.42.0.30"] = OIDName{ShortName: "setct-CapRevReqTBSX", LongName: "setct-CapRevReqTBSX"} + oidDotNotationToNames["2.23.42.0.31"] = OIDName{ShortName: "setct-CapRevResData", LongName: "setct-CapRevResData"} + oidDotNotationToNames["2.23.42.0.32"] = OIDName{ShortName: "setct-CredReqTBS", LongName: "setct-CredReqTBS"} + oidDotNotationToNames["2.23.42.0.33"] = OIDName{ShortName: "setct-CredReqTBSX", LongName: "setct-CredReqTBSX"} + oidDotNotationToNames["2.23.42.0.34"] = OIDName{ShortName: "setct-CredResData", LongName: "setct-CredResData"} + oidDotNotationToNames["2.23.42.0.35"] = OIDName{ShortName: "setct-CredRevReqTBS", LongName: "setct-CredRevReqTBS"} + oidDotNotationToNames["2.23.42.0.36"] = OIDName{ShortName: "setct-CredRevReqTBSX", LongName: "setct-CredRevReqTBSX"} + oidDotNotationToNames["2.23.42.0.37"] = OIDName{ShortName: "setct-CredRevResData", LongName: "setct-CredRevResData"} + oidDotNotationToNames["2.23.42.0.38"] = OIDName{ShortName: "setct-PCertReqData", LongName: "setct-PCertReqData"} + oidDotNotationToNames["2.23.42.0.39"] = OIDName{ShortName: "setct-PCertResTBS", LongName: "setct-PCertResTBS"} + oidDotNotationToNames["2.23.42.0.40"] = OIDName{ShortName: "setct-BatchAdminReqData", LongName: "setct-BatchAdminReqData"} + oidDotNotationToNames["2.23.42.0.41"] = OIDName{ShortName: "setct-BatchAdminResData", LongName: "setct-BatchAdminResData"} + oidDotNotationToNames["2.23.42.0.42"] = OIDName{ShortName: "setct-CardCInitResTBS", LongName: "setct-CardCInitResTBS"} + oidDotNotationToNames["2.23.42.0.43"] = OIDName{ShortName: "setct-MeAqCInitResTBS", LongName: "setct-MeAqCInitResTBS"} + oidDotNotationToNames["2.23.42.0.44"] = OIDName{ShortName: "setct-RegFormResTBS", LongName: "setct-RegFormResTBS"} + oidDotNotationToNames["2.23.42.0.45"] = OIDName{ShortName: "setct-CertReqData", LongName: "setct-CertReqData"} + oidDotNotationToNames["2.23.42.0.46"] = OIDName{ShortName: "setct-CertReqTBS", LongName: "setct-CertReqTBS"} + oidDotNotationToNames["2.23.42.0.47"] = OIDName{ShortName: "setct-CertResData", LongName: "setct-CertResData"} + oidDotNotationToNames["2.23.42.0.48"] = OIDName{ShortName: "setct-CertInqReqTBS", LongName: "setct-CertInqReqTBS"} + oidDotNotationToNames["2.23.42.0.49"] = OIDName{ShortName: "setct-ErrorTBS", LongName: "setct-ErrorTBS"} + oidDotNotationToNames["2.23.42.0.50"] = OIDName{ShortName: "setct-PIDualSignedTBE", LongName: "setct-PIDualSignedTBE"} + oidDotNotationToNames["2.23.42.0.51"] = OIDName{ShortName: "setct-PIUnsignedTBE", LongName: "setct-PIUnsignedTBE"} + oidDotNotationToNames["2.23.42.0.52"] = OIDName{ShortName: "setct-AuthReqTBE", LongName: "setct-AuthReqTBE"} + oidDotNotationToNames["2.23.42.0.53"] = OIDName{ShortName: "setct-AuthResTBE", LongName: "setct-AuthResTBE"} + oidDotNotationToNames["2.23.42.0.54"] = OIDName{ShortName: "setct-AuthResTBEX", LongName: "setct-AuthResTBEX"} + oidDotNotationToNames["2.23.42.0.55"] = OIDName{ShortName: "setct-AuthTokenTBE", LongName: "setct-AuthTokenTBE"} + oidDotNotationToNames["2.23.42.0.56"] = OIDName{ShortName: "setct-CapTokenTBE", LongName: "setct-CapTokenTBE"} + oidDotNotationToNames["2.23.42.0.57"] = OIDName{ShortName: "setct-CapTokenTBEX", LongName: "setct-CapTokenTBEX"} + oidDotNotationToNames["2.23.42.0.58"] = OIDName{ShortName: "setct-AcqCardCodeMsgTBE", LongName: "setct-AcqCardCodeMsgTBE"} + oidDotNotationToNames["2.23.42.0.59"] = OIDName{ShortName: "setct-AuthRevReqTBE", LongName: "setct-AuthRevReqTBE"} + oidDotNotationToNames["2.23.42.0.60"] = OIDName{ShortName: "setct-AuthRevResTBE", LongName: "setct-AuthRevResTBE"} + oidDotNotationToNames["2.23.42.0.61"] = OIDName{ShortName: "setct-AuthRevResTBEB", LongName: "setct-AuthRevResTBEB"} + oidDotNotationToNames["2.23.42.0.62"] = OIDName{ShortName: "setct-CapReqTBE", LongName: "setct-CapReqTBE"} + oidDotNotationToNames["2.23.42.0.63"] = OIDName{ShortName: "setct-CapReqTBEX", LongName: "setct-CapReqTBEX"} + oidDotNotationToNames["2.23.42.0.64"] = OIDName{ShortName: "setct-CapResTBE", LongName: "setct-CapResTBE"} + oidDotNotationToNames["2.23.42.0.65"] = OIDName{ShortName: "setct-CapRevReqTBE", LongName: "setct-CapRevReqTBE"} + oidDotNotationToNames["2.23.42.0.66"] = OIDName{ShortName: "setct-CapRevReqTBEX", LongName: "setct-CapRevReqTBEX"} + oidDotNotationToNames["2.23.42.0.67"] = OIDName{ShortName: "setct-CapRevResTBE", LongName: "setct-CapRevResTBE"} + oidDotNotationToNames["2.23.42.0.68"] = OIDName{ShortName: "setct-CredReqTBE", LongName: "setct-CredReqTBE"} + oidDotNotationToNames["2.23.42.0.69"] = OIDName{ShortName: "setct-CredReqTBEX", LongName: "setct-CredReqTBEX"} + oidDotNotationToNames["2.23.42.0.70"] = OIDName{ShortName: "setct-CredResTBE", LongName: "setct-CredResTBE"} + oidDotNotationToNames["2.23.42.0.71"] = OIDName{ShortName: "setct-CredRevReqTBE", LongName: "setct-CredRevReqTBE"} + oidDotNotationToNames["2.23.42.0.72"] = OIDName{ShortName: "setct-CredRevReqTBEX", LongName: "setct-CredRevReqTBEX"} + oidDotNotationToNames["2.23.42.0.73"] = OIDName{ShortName: "setct-CredRevResTBE", LongName: "setct-CredRevResTBE"} + oidDotNotationToNames["2.23.42.0.74"] = OIDName{ShortName: "setct-BatchAdminReqTBE", LongName: "setct-BatchAdminReqTBE"} + oidDotNotationToNames["2.23.42.0.75"] = OIDName{ShortName: "setct-BatchAdminResTBE", LongName: "setct-BatchAdminResTBE"} + oidDotNotationToNames["2.23.42.0.76"] = OIDName{ShortName: "setct-RegFormReqTBE", LongName: "setct-RegFormReqTBE"} + oidDotNotationToNames["2.23.42.0.77"] = OIDName{ShortName: "setct-CertReqTBE", LongName: "setct-CertReqTBE"} + oidDotNotationToNames["2.23.42.0.78"] = OIDName{ShortName: "setct-CertReqTBEX", LongName: "setct-CertReqTBEX"} + oidDotNotationToNames["2.23.42.0.79"] = OIDName{ShortName: "setct-CertResTBE", LongName: "setct-CertResTBE"} + oidDotNotationToNames["2.23.42.0.80"] = OIDName{ShortName: "setct-CRLNotificationTBS", LongName: "setct-CRLNotificationTBS"} + oidDotNotationToNames["2.23.42.0.81"] = OIDName{ShortName: "setct-CRLNotificationResTBS", LongName: "setct-CRLNotificationResTBS"} + oidDotNotationToNames["2.23.42.0.82"] = OIDName{ShortName: "setct-BCIDistributionTBS", LongName: "setct-BCIDistributionTBS"} + oidDotNotationToNames["2.23.42.1.1"] = OIDName{ShortName: "setext-genCrypt", LongName: "generic cryptogram"} + oidDotNotationToNames["2.23.42.1.3"] = OIDName{ShortName: "setext-miAuth", LongName: "merchant initiated auth"} + oidDotNotationToNames["2.23.42.1.4"] = OIDName{ShortName: "setext-pinSecure", LongName: "setext-pinSecure"} + oidDotNotationToNames["2.23.42.1.5"] = OIDName{ShortName: "setext-pinAny", LongName: "setext-pinAny"} + oidDotNotationToNames["2.23.42.1.7"] = OIDName{ShortName: "setext-track2", LongName: "setext-track2"} + oidDotNotationToNames["2.23.42.1.8"] = OIDName{ShortName: "setext-cv", LongName: "additional verification"} + oidDotNotationToNames["2.23.42.5.0"] = OIDName{ShortName: "set-policy-root", LongName: "set-policy-root"} + oidDotNotationToNames["2.23.42.7.0"] = OIDName{ShortName: "setCext-hashedRoot", LongName: "setCext-hashedRoot"} + oidDotNotationToNames["2.23.42.7.1"] = OIDName{ShortName: "setCext-certType", LongName: "setCext-certType"} + oidDotNotationToNames["2.23.42.7.2"] = OIDName{ShortName: "setCext-merchData", LongName: "setCext-merchData"} + oidDotNotationToNames["2.23.42.7.3"] = OIDName{ShortName: "setCext-cCertRequired", LongName: "setCext-cCertRequired"} + oidDotNotationToNames["2.23.42.7.4"] = OIDName{ShortName: "setCext-tunneling", LongName: "setCext-tunneling"} + oidDotNotationToNames["2.23.42.7.5"] = OIDName{ShortName: "setCext-setExt", LongName: "setCext-setExt"} + oidDotNotationToNames["2.23.42.7.6"] = OIDName{ShortName: "setCext-setQualf", LongName: "setCext-setQualf"} + oidDotNotationToNames["2.23.42.7.7"] = OIDName{ShortName: "setCext-PGWYcapabilities", LongName: "setCext-PGWYcapabilities"} + oidDotNotationToNames["2.23.42.7.8"] = OIDName{ShortName: "setCext-TokenIdentifier", LongName: "setCext-TokenIdentifier"} + oidDotNotationToNames["2.23.42.7.9"] = OIDName{ShortName: "setCext-Track2Data", LongName: "setCext-Track2Data"} + oidDotNotationToNames["2.23.42.7.10"] = OIDName{ShortName: "setCext-TokenType", LongName: "setCext-TokenType"} + oidDotNotationToNames["2.23.42.7.11"] = OIDName{ShortName: "setCext-IssuerCapabilities", LongName: "setCext-IssuerCapabilities"} + oidDotNotationToNames["2.23.42.3.0"] = OIDName{ShortName: "setAttr-Cert", LongName: "setAttr-Cert"} + oidDotNotationToNames["2.23.42.3.1"] = OIDName{ShortName: "setAttr-PGWYcap", LongName: "payment gateway capabilities"} + oidDotNotationToNames["2.23.42.3.2"] = OIDName{ShortName: "setAttr-TokenType", LongName: "setAttr-TokenType"} + oidDotNotationToNames["2.23.42.3.3"] = OIDName{ShortName: "setAttr-IssCap", LongName: "issuer capabilities"} + oidDotNotationToNames["2.23.42.3.0.0"] = OIDName{ShortName: "set-rootKeyThumb", LongName: "set-rootKeyThumb"} + oidDotNotationToNames["2.23.42.3.0.1"] = OIDName{ShortName: "set-addPolicy", LongName: "set-addPolicy"} + oidDotNotationToNames["2.23.42.3.2.1"] = OIDName{ShortName: "setAttr-Token-EMV", LongName: "setAttr-Token-EMV"} + oidDotNotationToNames["2.23.42.3.2.2"] = OIDName{ShortName: "setAttr-Token-B0Prime", LongName: "setAttr-Token-B0Prime"} + oidDotNotationToNames["2.23.42.3.3.3"] = OIDName{ShortName: "setAttr-IssCap-CVM", LongName: "setAttr-IssCap-CVM"} + oidDotNotationToNames["2.23.42.3.3.4"] = OIDName{ShortName: "setAttr-IssCap-T2", LongName: "setAttr-IssCap-T2"} + oidDotNotationToNames["2.23.42.3.3.5"] = OIDName{ShortName: "setAttr-IssCap-Sig", LongName: "setAttr-IssCap-Sig"} + oidDotNotationToNames["2.23.42.3.3.3.1"] = OIDName{ShortName: "setAttr-GenCryptgrm", LongName: "generate cryptogram"} + oidDotNotationToNames["2.23.42.3.3.4.1"] = OIDName{ShortName: "setAttr-T2Enc", LongName: "encrypted track 2"} + oidDotNotationToNames["2.23.42.3.3.4.2"] = OIDName{ShortName: "setAttr-T2cleartxt", LongName: "cleartext track 2"} + oidDotNotationToNames["2.23.42.3.3.5.1"] = OIDName{ShortName: "setAttr-TokICCsig", LongName: "ICC or token signature"} + oidDotNotationToNames["2.23.42.3.3.5.2"] = OIDName{ShortName: "setAttr-SecDevSig", LongName: "secure device signature"} + oidDotNotationToNames["2.23.42.8.1"] = OIDName{ShortName: "set-brand-IATA-ATA", LongName: "set-brand-IATA-ATA"} + oidDotNotationToNames["2.23.42.8.30"] = OIDName{ShortName: "set-brand-Diners", LongName: "set-brand-Diners"} + oidDotNotationToNames["2.23.42.8.34"] = OIDName{ShortName: "set-brand-AmericanExpress", LongName: "set-brand-AmericanExpress"} + oidDotNotationToNames["2.23.42.8.35"] = OIDName{ShortName: "set-brand-JCB", LongName: "set-brand-JCB"} + oidDotNotationToNames["2.23.42.8.4"] = OIDName{ShortName: "set-brand-Visa", LongName: "set-brand-Visa"} + oidDotNotationToNames["2.23.42.8.5"] = OIDName{ShortName: "set-brand-MasterCard", LongName: "set-brand-MasterCard"} + oidDotNotationToNames["2.23.42.8.6011"] = OIDName{ShortName: "set-brand-Novus", LongName: "set-brand-Novus"} + oidDotNotationToNames["1.2.840.113549.3.10"] = OIDName{ShortName: "DES-CDMF", LongName: "des-cdmf"} + oidDotNotationToNames["1.2.840.113549.1.1.6"] = OIDName{ShortName: "rsaOAEPEncryptionSET", LongName: "rsaOAEPEncryptionSET"} + oidDotNotationToNames["0.0"] = OIDName{ShortName: "ITU-T", LongName: "itu-t"} + oidDotNotationToNames["2.0"] = OIDName{ShortName: "JOINT-ISO-ITU-T", LongName: "joint-iso-itu-t"} + oidDotNotationToNames["2.23"] = OIDName{ShortName: "international-organizations", LongName: "International Organizations"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.2.2"] = OIDName{ShortName: "msSmartcardLogin", LongName: "Microsoft Smartcardlogin"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.2.3"] = OIDName{ShortName: "msUPN", LongName: "Microsoft Universal Principal Name"} + oidDotNotationToNames["2.5.4.9"] = OIDName{ShortName: "street", LongName: "streetAddress"} + oidDotNotationToNames["2.5.4.17"] = OIDName{ShortName: "postalCode", LongName: "postalCode"} + oidDotNotationToNames["1.3.6.1.5.5.7.21"] = OIDName{ShortName: "id-ppl", LongName: "id-ppl"} + oidDotNotationToNames["1.3.6.1.5.5.7.1.14"] = OIDName{ShortName: "proxyCertInfo", LongName: "Proxy Certificate Information"} + oidDotNotationToNames["1.3.6.1.5.5.7.21.0"] = OIDName{ShortName: "id-ppl-anyLanguage", LongName: "Any language"} + oidDotNotationToNames["1.3.6.1.5.5.7.21.1"] = OIDName{ShortName: "id-ppl-inheritAll", LongName: "Inherit all"} + oidDotNotationToNames["2.5.29.30"] = OIDName{ShortName: "nameConstraints", LongName: "X509v3 Name Constraints"} + oidDotNotationToNames["1.3.6.1.5.5.7.21.2"] = OIDName{ShortName: "id-ppl-independent", LongName: "Independent"} + oidDotNotationToNames["1.2.840.113549.1.1.11"] = OIDName{ShortName: "RSA-SHA256", LongName: "sha256WithRSAEncryption"} + oidDotNotationToNames["1.2.840.113549.1.1.12"] = OIDName{ShortName: "RSA-SHA384", LongName: "sha384WithRSAEncryption"} + oidDotNotationToNames["1.2.840.113549.1.1.13"] = OIDName{ShortName: "RSA-SHA512", LongName: "sha512WithRSAEncryption"} + oidDotNotationToNames["1.2.840.113549.1.1.14"] = OIDName{ShortName: "RSA-SHA224", LongName: "sha224WithRSAEncryption"} + oidDotNotationToNames["2.16.840.1.101.3.4.2.1"] = OIDName{ShortName: "SHA256", LongName: "sha256"} + oidDotNotationToNames["2.16.840.1.101.3.4.2.2"] = OIDName{ShortName: "SHA384", LongName: "sha384"} + oidDotNotationToNames["2.16.840.1.101.3.4.2.3"] = OIDName{ShortName: "SHA512", LongName: "sha512"} + oidDotNotationToNames["2.16.840.1.101.3.4.2.4"] = OIDName{ShortName: "SHA224", LongName: "sha224"} + oidDotNotationToNames["1.3"] = OIDName{ShortName: "identified-organization", LongName: "identified-organization"} + oidDotNotationToNames["1.3.132"] = OIDName{ShortName: "certicom-arc", LongName: "certicom-arc"} + oidDotNotationToNames["2.23.43"] = OIDName{ShortName: "wap", LongName: "wap"} + oidDotNotationToNames["2.23.43.1"] = OIDName{ShortName: "wap-wsg", LongName: "wap-wsg"} + oidDotNotationToNames["1.2.840.10045.1.2.3"] = OIDName{ShortName: "id-characteristic-two-basis", LongName: "id-characteristic-two-basis"} + oidDotNotationToNames["1.2.840.10045.1.2.3.1"] = OIDName{ShortName: "onBasis", LongName: "onBasis"} + oidDotNotationToNames["1.2.840.10045.1.2.3.2"] = OIDName{ShortName: "tpBasis", LongName: "tpBasis"} + oidDotNotationToNames["1.2.840.10045.1.2.3.3"] = OIDName{ShortName: "ppBasis", LongName: "ppBasis"} + oidDotNotationToNames["1.2.840.10045.3.0.1"] = OIDName{ShortName: "c2pnb163v1", LongName: "c2pnb163v1"} + oidDotNotationToNames["1.2.840.10045.3.0.2"] = OIDName{ShortName: "c2pnb163v2", LongName: "c2pnb163v2"} + oidDotNotationToNames["1.2.840.10045.3.0.3"] = OIDName{ShortName: "c2pnb163v3", LongName: "c2pnb163v3"} + oidDotNotationToNames["1.2.840.10045.3.0.4"] = OIDName{ShortName: "c2pnb176v1", LongName: "c2pnb176v1"} + oidDotNotationToNames["1.2.840.10045.3.0.5"] = OIDName{ShortName: "c2tnb191v1", LongName: "c2tnb191v1"} + oidDotNotationToNames["1.2.840.10045.3.0.6"] = OIDName{ShortName: "c2tnb191v2", LongName: "c2tnb191v2"} + oidDotNotationToNames["1.2.840.10045.3.0.7"] = OIDName{ShortName: "c2tnb191v3", LongName: "c2tnb191v3"} + oidDotNotationToNames["1.2.840.10045.3.0.8"] = OIDName{ShortName: "c2onb191v4", LongName: "c2onb191v4"} + oidDotNotationToNames["1.2.840.10045.3.0.9"] = OIDName{ShortName: "c2onb191v5", LongName: "c2onb191v5"} + oidDotNotationToNames["1.2.840.10045.3.0.10"] = OIDName{ShortName: "c2pnb208w1", LongName: "c2pnb208w1"} + oidDotNotationToNames["1.2.840.10045.3.0.11"] = OIDName{ShortName: "c2tnb239v1", LongName: "c2tnb239v1"} + oidDotNotationToNames["1.2.840.10045.3.0.12"] = OIDName{ShortName: "c2tnb239v2", LongName: "c2tnb239v2"} + oidDotNotationToNames["1.2.840.10045.3.0.13"] = OIDName{ShortName: "c2tnb239v3", LongName: "c2tnb239v3"} + oidDotNotationToNames["1.2.840.10045.3.0.14"] = OIDName{ShortName: "c2onb239v4", LongName: "c2onb239v4"} + oidDotNotationToNames["1.2.840.10045.3.0.15"] = OIDName{ShortName: "c2onb239v5", LongName: "c2onb239v5"} + oidDotNotationToNames["1.2.840.10045.3.0.16"] = OIDName{ShortName: "c2pnb272w1", LongName: "c2pnb272w1"} + oidDotNotationToNames["1.2.840.10045.3.0.17"] = OIDName{ShortName: "c2pnb304w1", LongName: "c2pnb304w1"} + oidDotNotationToNames["1.2.840.10045.3.0.18"] = OIDName{ShortName: "c2tnb359v1", LongName: "c2tnb359v1"} + oidDotNotationToNames["1.2.840.10045.3.0.19"] = OIDName{ShortName: "c2pnb368w1", LongName: "c2pnb368w1"} + oidDotNotationToNames["1.2.840.10045.3.0.20"] = OIDName{ShortName: "c2tnb431r1", LongName: "c2tnb431r1"} + oidDotNotationToNames["1.3.132.0.6"] = OIDName{ShortName: "secp112r1", LongName: "secp112r1"} + oidDotNotationToNames["1.3.132.0.7"] = OIDName{ShortName: "secp112r2", LongName: "secp112r2"} + oidDotNotationToNames["1.3.132.0.28"] = OIDName{ShortName: "secp128r1", LongName: "secp128r1"} + oidDotNotationToNames["1.3.132.0.29"] = OIDName{ShortName: "secp128r2", LongName: "secp128r2"} + oidDotNotationToNames["1.3.132.0.9"] = OIDName{ShortName: "secp160k1", LongName: "secp160k1"} + oidDotNotationToNames["1.3.132.0.8"] = OIDName{ShortName: "secp160r1", LongName: "secp160r1"} + oidDotNotationToNames["1.3.132.0.30"] = OIDName{ShortName: "secp160r2", LongName: "secp160r2"} + oidDotNotationToNames["1.3.132.0.31"] = OIDName{ShortName: "secp192k1", LongName: "secp192k1"} + oidDotNotationToNames["1.3.132.0.32"] = OIDName{ShortName: "secp224k1", LongName: "secp224k1"} + oidDotNotationToNames["1.3.132.0.33"] = OIDName{ShortName: "secp224r1", LongName: "secp224r1"} + oidDotNotationToNames["1.3.132.0.10"] = OIDName{ShortName: "secp256k1", LongName: "secp256k1"} + oidDotNotationToNames["1.3.132.0.34"] = OIDName{ShortName: "secp384r1", LongName: "secp384r1"} + oidDotNotationToNames["1.3.132.0.35"] = OIDName{ShortName: "secp521r1", LongName: "secp521r1"} + oidDotNotationToNames["1.3.132.0.4"] = OIDName{ShortName: "sect113r1", LongName: "sect113r1"} + oidDotNotationToNames["1.3.132.0.5"] = OIDName{ShortName: "sect113r2", LongName: "sect113r2"} + oidDotNotationToNames["1.3.132.0.22"] = OIDName{ShortName: "sect131r1", LongName: "sect131r1"} + oidDotNotationToNames["1.3.132.0.23"] = OIDName{ShortName: "sect131r2", LongName: "sect131r2"} + oidDotNotationToNames["1.3.132.0.1"] = OIDName{ShortName: "sect163k1", LongName: "sect163k1"} + oidDotNotationToNames["1.3.132.0.2"] = OIDName{ShortName: "sect163r1", LongName: "sect163r1"} + oidDotNotationToNames["1.3.132.0.15"] = OIDName{ShortName: "sect163r2", LongName: "sect163r2"} + oidDotNotationToNames["1.3.132.0.24"] = OIDName{ShortName: "sect193r1", LongName: "sect193r1"} + oidDotNotationToNames["1.3.132.0.25"] = OIDName{ShortName: "sect193r2", LongName: "sect193r2"} + oidDotNotationToNames["1.3.132.0.26"] = OIDName{ShortName: "sect233k1", LongName: "sect233k1"} + oidDotNotationToNames["1.3.132.0.27"] = OIDName{ShortName: "sect233r1", LongName: "sect233r1"} + oidDotNotationToNames["1.3.132.0.3"] = OIDName{ShortName: "sect239k1", LongName: "sect239k1"} + oidDotNotationToNames["1.3.132.0.16"] = OIDName{ShortName: "sect283k1", LongName: "sect283k1"} + oidDotNotationToNames["1.3.132.0.17"] = OIDName{ShortName: "sect283r1", LongName: "sect283r1"} + oidDotNotationToNames["1.3.132.0.36"] = OIDName{ShortName: "sect409k1", LongName: "sect409k1"} + oidDotNotationToNames["1.3.132.0.37"] = OIDName{ShortName: "sect409r1", LongName: "sect409r1"} + oidDotNotationToNames["1.3.132.0.38"] = OIDName{ShortName: "sect571k1", LongName: "sect571k1"} + oidDotNotationToNames["1.3.132.0.39"] = OIDName{ShortName: "sect571r1", LongName: "sect571r1"} + oidDotNotationToNames["2.23.43.1.4.1"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls1", LongName: "wap-wsg-idm-ecid-wtls1"} + oidDotNotationToNames["2.23.43.1.4.3"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls3", LongName: "wap-wsg-idm-ecid-wtls3"} + oidDotNotationToNames["2.23.43.1.4.4"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls4", LongName: "wap-wsg-idm-ecid-wtls4"} + oidDotNotationToNames["2.23.43.1.4.5"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls5", LongName: "wap-wsg-idm-ecid-wtls5"} + oidDotNotationToNames["2.23.43.1.4.6"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls6", LongName: "wap-wsg-idm-ecid-wtls6"} + oidDotNotationToNames["2.23.43.1.4.7"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls7", LongName: "wap-wsg-idm-ecid-wtls7"} + oidDotNotationToNames["2.23.43.1.4.8"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls8", LongName: "wap-wsg-idm-ecid-wtls8"} + oidDotNotationToNames["2.23.43.1.4.9"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls9", LongName: "wap-wsg-idm-ecid-wtls9"} + oidDotNotationToNames["2.23.43.1.4.10"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls10", LongName: "wap-wsg-idm-ecid-wtls10"} + oidDotNotationToNames["2.23.43.1.4.11"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls11", LongName: "wap-wsg-idm-ecid-wtls11"} + oidDotNotationToNames["2.23.43.1.4.12"] = OIDName{ShortName: "wap-wsg-idm-ecid-wtls12", LongName: "wap-wsg-idm-ecid-wtls12"} + oidDotNotationToNames["2.5.29.32.0"] = OIDName{ShortName: "anyPolicy", LongName: "X509v3 Any Policy"} + oidDotNotationToNames["2.5.29.33"] = OIDName{ShortName: "policyMappings", LongName: "X509v3 Policy Mappings"} + oidDotNotationToNames["2.5.29.54"] = OIDName{ShortName: "inhibitAnyPolicy", LongName: "X509v3 Inhibit Any Policy"} + oidDotNotationToNames["1.2.392.200011.61.1.1.1.2"] = OIDName{ShortName: "CAMELLIA-128-CBC", LongName: "camellia-128-cbc"} + oidDotNotationToNames["1.2.392.200011.61.1.1.1.3"] = OIDName{ShortName: "CAMELLIA-192-CBC", LongName: "camellia-192-cbc"} + oidDotNotationToNames["1.2.392.200011.61.1.1.1.4"] = OIDName{ShortName: "CAMELLIA-256-CBC", LongName: "camellia-256-cbc"} + oidDotNotationToNames["0.3.4401.5.3.1.9.1"] = OIDName{ShortName: "CAMELLIA-128-ECB", LongName: "camellia-128-ecb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.21"] = OIDName{ShortName: "CAMELLIA-192-ECB", LongName: "camellia-192-ecb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.41"] = OIDName{ShortName: "CAMELLIA-256-ECB", LongName: "camellia-256-ecb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.4"] = OIDName{ShortName: "CAMELLIA-128-CFB", LongName: "camellia-128-cfb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.24"] = OIDName{ShortName: "CAMELLIA-192-CFB", LongName: "camellia-192-cfb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.44"] = OIDName{ShortName: "CAMELLIA-256-CFB", LongName: "camellia-256-cfb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.3"] = OIDName{ShortName: "CAMELLIA-128-OFB", LongName: "camellia-128-ofb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.23"] = OIDName{ShortName: "CAMELLIA-192-OFB", LongName: "camellia-192-ofb"} + oidDotNotationToNames["0.3.4401.5.3.1.9.43"] = OIDName{ShortName: "CAMELLIA-256-OFB", LongName: "camellia-256-ofb"} + oidDotNotationToNames["2.5.29.9"] = OIDName{ShortName: "subjectDirectoryAttributes", LongName: "X509v3 Subject Directory Attributes"} + oidDotNotationToNames["2.5.29.28"] = OIDName{ShortName: "issuingDistributionPoint", LongName: "X509v3 Issuing Distrubution Point"} + oidDotNotationToNames["2.5.29.29"] = OIDName{ShortName: "certificateIssuer", LongName: "X509v3 Certificate Issuer"} + oidDotNotationToNames["1.2.410.200004"] = OIDName{ShortName: "KISA", LongName: "kisa"} + oidDotNotationToNames["1.2.410.200004.1.3"] = OIDName{ShortName: "SEED-ECB", LongName: "seed-ecb"} + oidDotNotationToNames["1.2.410.200004.1.4"] = OIDName{ShortName: "SEED-CBC", LongName: "seed-cbc"} + oidDotNotationToNames["1.2.410.200004.1.6"] = OIDName{ShortName: "SEED-OFB", LongName: "seed-ofb"} + oidDotNotationToNames["1.2.410.200004.1.5"] = OIDName{ShortName: "SEED-CFB", LongName: "seed-cfb"} + oidDotNotationToNames["1.3.6.1.5.5.8.1.1"] = OIDName{ShortName: "HMAC-MD5", LongName: "hmac-md5"} + oidDotNotationToNames["1.3.6.1.5.5.8.1.2"] = OIDName{ShortName: "HMAC-SHA1", LongName: "hmac-sha1"} + oidDotNotationToNames["1.2.840.113533.7.66.13"] = OIDName{ShortName: "id-PasswordBasedMAC", LongName: "password based MAC"} + oidDotNotationToNames["1.2.840.113533.7.66.30"] = OIDName{ShortName: "id-DHBasedMac", LongName: "Diffie-Hellman based MAC"} + oidDotNotationToNames["1.3.6.1.5.5.7.4.16"] = OIDName{ShortName: "id-it-suppLangTags", LongName: "id-it-suppLangTags"} + oidDotNotationToNames["1.3.6.1.5.5.7.48.5"] = OIDName{ShortName: "caRepository", LongName: "CA Repository"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.9"] = OIDName{ShortName: "id-smime-ct-compressedData", LongName: "id-smime-ct-compressedData"} + oidDotNotationToNames["1.2.840.113549.1.9.16.1.27"] = OIDName{ShortName: "id-ct-asciiTextWithCRLF", LongName: "id-ct-asciiTextWithCRLF"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.5"] = OIDName{ShortName: "id-aes128-wrap", LongName: "id-aes128-wrap"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.25"] = OIDName{ShortName: "id-aes192-wrap", LongName: "id-aes192-wrap"} + oidDotNotationToNames["2.16.840.1.101.3.4.1.45"] = OIDName{ShortName: "id-aes256-wrap", LongName: "id-aes256-wrap"} + oidDotNotationToNames["1.2.840.10045.4.2"] = OIDName{ShortName: "ecdsa-with-Recommended", LongName: "ecdsa-with-Recommended"} + oidDotNotationToNames["1.2.840.10045.4.3"] = OIDName{ShortName: "ecdsa-with-Specified", LongName: "ecdsa-with-Specified"} + oidDotNotationToNames["1.2.840.10045.4.3.1"] = OIDName{ShortName: "ecdsa-with-SHA224", LongName: "ecdsa-with-SHA224"} + oidDotNotationToNames["1.2.840.10045.4.3.2"] = OIDName{ShortName: "ecdsa-with-SHA256", LongName: "ecdsa-with-SHA256"} + oidDotNotationToNames["1.2.840.10045.4.3.3"] = OIDName{ShortName: "ecdsa-with-SHA384", LongName: "ecdsa-with-SHA384"} + oidDotNotationToNames["1.2.840.10045.4.3.4"] = OIDName{ShortName: "ecdsa-with-SHA512", LongName: "ecdsa-with-SHA512"} + oidDotNotationToNames["1.2.840.113549.2.6"] = OIDName{ShortName: "hmacWithMD5", LongName: "hmacWithMD5"} + oidDotNotationToNames["1.2.840.113549.2.8"] = OIDName{ShortName: "hmacWithSHA224", LongName: "hmacWithSHA224"} + oidDotNotationToNames["1.2.840.113549.2.9"] = OIDName{ShortName: "hmacWithSHA256", LongName: "hmacWithSHA256"} + oidDotNotationToNames["1.2.840.113549.2.10"] = OIDName{ShortName: "hmacWithSHA384", LongName: "hmacWithSHA384"} + oidDotNotationToNames["1.2.840.113549.2.11"] = OIDName{ShortName: "hmacWithSHA512", LongName: "hmacWithSHA512"} + oidDotNotationToNames["2.16.840.1.101.3.4.3.1"] = OIDName{ShortName: "dsa_with_SHA224", LongName: "dsa_with_SHA224"} + oidDotNotationToNames["2.16.840.1.101.3.4.3.2"] = OIDName{ShortName: "dsa_with_SHA256", LongName: "dsa_with_SHA256"} + oidDotNotationToNames["1.0.10118.3.0.55"] = OIDName{ShortName: "whirlpool", LongName: "whirlpool"} + oidDotNotationToNames["1.2.643.2.2"] = OIDName{ShortName: "cryptopro", LongName: "cryptopro"} + oidDotNotationToNames["1.2.643.2.9"] = OIDName{ShortName: "cryptocom", LongName: "cryptocom"} + oidDotNotationToNames["1.2.643.2.2.3"] = OIDName{ShortName: "id-GostR3411-94-with-GostR3410-2001", LongName: "GOST R 34.11-94 with GOST R 34.10-2001"} + oidDotNotationToNames["1.2.643.2.2.4"] = OIDName{ShortName: "id-GostR3411-94-with-GostR3410-94", LongName: "GOST R 34.11-94 with GOST R 34.10-94"} + oidDotNotationToNames["1.2.643.2.2.9"] = OIDName{ShortName: "md_gost94", LongName: "GOST R 34.11-94"} + oidDotNotationToNames["1.2.643.2.2.10"] = OIDName{ShortName: "id-HMACGostR3411-94", LongName: "HMAC GOST 34.11-94"} + oidDotNotationToNames["1.2.643.2.2.19"] = OIDName{ShortName: "gost2001", LongName: "GOST R 34.10-2001"} + oidDotNotationToNames["1.2.643.2.2.20"] = OIDName{ShortName: "gost94", LongName: "GOST R 34.10-94"} + oidDotNotationToNames["1.2.643.2.2.21"] = OIDName{ShortName: "gost89", LongName: "GOST 28147-89"} + oidDotNotationToNames["1.2.643.2.2.22"] = OIDName{ShortName: "gost-mac", LongName: "GOST 28147-89 MAC"} + oidDotNotationToNames["1.2.643.2.2.23"] = OIDName{ShortName: "prf-gostr3411-94", LongName: "GOST R 34.11-94 PRF"} + oidDotNotationToNames["1.2.643.2.2.98"] = OIDName{ShortName: "id-GostR3410-2001DH", LongName: "GOST R 34.10-2001 DH"} + oidDotNotationToNames["1.2.643.2.2.99"] = OIDName{ShortName: "id-GostR3410-94DH", LongName: "GOST R 34.10-94 DH"} + oidDotNotationToNames["1.2.643.2.2.14.1"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-KeyMeshing", LongName: "id-Gost28147-89-CryptoPro-KeyMeshing"} + oidDotNotationToNames["1.2.643.2.2.14.0"] = OIDName{ShortName: "id-Gost28147-89-None-KeyMeshing", LongName: "id-Gost28147-89-None-KeyMeshing"} + oidDotNotationToNames["1.2.643.2.2.30.0"] = OIDName{ShortName: "id-GostR3411-94-TestParamSet", LongName: "id-GostR3411-94-TestParamSet"} + oidDotNotationToNames["1.2.643.2.2.30.1"] = OIDName{ShortName: "id-GostR3411-94-CryptoProParamSet", LongName: "id-GostR3411-94-CryptoProParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.0"] = OIDName{ShortName: "id-Gost28147-89-TestParamSet", LongName: "id-Gost28147-89-TestParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.1"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-A-ParamSet", LongName: "id-Gost28147-89-CryptoPro-A-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.2"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-B-ParamSet", LongName: "id-Gost28147-89-CryptoPro-B-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.3"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-C-ParamSet", LongName: "id-Gost28147-89-CryptoPro-C-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.4"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-D-ParamSet", LongName: "id-Gost28147-89-CryptoPro-D-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.5"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet", LongName: "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.6"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet", LongName: "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.31.7"] = OIDName{ShortName: "id-Gost28147-89-CryptoPro-RIC-1-ParamSet", LongName: "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.32.0"] = OIDName{ShortName: "id-GostR3410-94-TestParamSet", LongName: "id-GostR3410-94-TestParamSet"} + oidDotNotationToNames["1.2.643.2.2.32.2"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-A-ParamSet", LongName: "id-GostR3410-94-CryptoPro-A-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.32.3"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-B-ParamSet", LongName: "id-GostR3410-94-CryptoPro-B-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.32.4"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-C-ParamSet", LongName: "id-GostR3410-94-CryptoPro-C-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.32.5"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-D-ParamSet", LongName: "id-GostR3410-94-CryptoPro-D-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.33.1"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-XchA-ParamSet", LongName: "id-GostR3410-94-CryptoPro-XchA-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.33.2"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-XchB-ParamSet", LongName: "id-GostR3410-94-CryptoPro-XchB-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.33.3"] = OIDName{ShortName: "id-GostR3410-94-CryptoPro-XchC-ParamSet", LongName: "id-GostR3410-94-CryptoPro-XchC-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.35.0"] = OIDName{ShortName: "id-GostR3410-2001-TestParamSet", LongName: "id-GostR3410-2001-TestParamSet"} + oidDotNotationToNames["1.2.643.2.2.35.1"] = OIDName{ShortName: "id-GostR3410-2001-CryptoPro-A-ParamSet", LongName: "id-GostR3410-2001-CryptoPro-A-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.35.2"] = OIDName{ShortName: "id-GostR3410-2001-CryptoPro-B-ParamSet", LongName: "id-GostR3410-2001-CryptoPro-B-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.35.3"] = OIDName{ShortName: "id-GostR3410-2001-CryptoPro-C-ParamSet", LongName: "id-GostR3410-2001-CryptoPro-C-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.36.0"] = OIDName{ShortName: "id-GostR3410-2001-CryptoPro-XchA-ParamSet", LongName: "id-GostR3410-2001-CryptoPro-XchA-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.36.1"] = OIDName{ShortName: "id-GostR3410-2001-CryptoPro-XchB-ParamSet", LongName: "id-GostR3410-2001-CryptoPro-XchB-ParamSet"} + oidDotNotationToNames["1.2.643.2.2.20.1"] = OIDName{ShortName: "id-GostR3410-94-a", LongName: "id-GostR3410-94-a"} + oidDotNotationToNames["1.2.643.2.2.20.2"] = OIDName{ShortName: "id-GostR3410-94-aBis", LongName: "id-GostR3410-94-aBis"} + oidDotNotationToNames["1.2.643.2.2.20.3"] = OIDName{ShortName: "id-GostR3410-94-b", LongName: "id-GostR3410-94-b"} + oidDotNotationToNames["1.2.643.2.2.20.4"] = OIDName{ShortName: "id-GostR3410-94-bBis", LongName: "id-GostR3410-94-bBis"} + oidDotNotationToNames["1.2.643.2.9.1.6.1"] = OIDName{ShortName: "id-Gost28147-89-cc", LongName: "GOST 28147-89 Cryptocom ParamSet"} + oidDotNotationToNames["1.2.643.2.9.1.5.3"] = OIDName{ShortName: "gost94cc", LongName: "GOST 34.10-94 Cryptocom"} + oidDotNotationToNames["1.2.643.2.9.1.5.4"] = OIDName{ShortName: "gost2001cc", LongName: "GOST 34.10-2001 Cryptocom"} + oidDotNotationToNames["1.2.643.2.9.1.3.3"] = OIDName{ShortName: "id-GostR3411-94-with-GostR3410-94-cc", LongName: "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"} + oidDotNotationToNames["1.2.643.2.9.1.3.4"] = OIDName{ShortName: "id-GostR3411-94-with-GostR3410-2001-cc", LongName: "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"} + oidDotNotationToNames["1.2.643.2.9.1.8.1"] = OIDName{ShortName: "id-GostR3410-2001-ParamSet-cc", LongName: "GOST R 3410-2001 Parameter Set Cryptocom"} + oidDotNotationToNames["1.3.6.1.4.1.311.17.2"] = OIDName{ShortName: "LocalKeySet", LongName: "Microsoft Local Key set"} + oidDotNotationToNames["2.5.29.46"] = OIDName{ShortName: "freshestCRL", LongName: "X509v3 Freshest CRL"} + oidDotNotationToNames["1.3.6.1.5.5.7.8.3"] = OIDName{ShortName: "id-on-permanentIdentifier", LongName: "Permanent Identifier"} + oidDotNotationToNames["2.5.4.14"] = OIDName{ShortName: "searchGuide", LongName: "searchGuide"} + oidDotNotationToNames["2.5.4.15"] = OIDName{ShortName: "businessCategory", LongName: "businessCategory"} + oidDotNotationToNames["2.5.4.16"] = OIDName{ShortName: "postalAddress", LongName: "postalAddress"} + oidDotNotationToNames["2.5.4.18"] = OIDName{ShortName: "postOfficeBox", LongName: "postOfficeBox"} + oidDotNotationToNames["2.5.4.19"] = OIDName{ShortName: "physicalDeliveryOfficeName", LongName: "physicalDeliveryOfficeName"} + oidDotNotationToNames["2.5.4.20"] = OIDName{ShortName: "telephoneNumber", LongName: "telephoneNumber"} + oidDotNotationToNames["2.5.4.21"] = OIDName{ShortName: "telexNumber", LongName: "telexNumber"} + oidDotNotationToNames["2.5.4.22"] = OIDName{ShortName: "teletexTerminalIdentifier", LongName: "teletexTerminalIdentifier"} + oidDotNotationToNames["2.5.4.23"] = OIDName{ShortName: "facsimileTelephoneNumber", LongName: "facsimileTelephoneNumber"} + oidDotNotationToNames["2.5.4.24"] = OIDName{ShortName: "x121Address", LongName: "x121Address"} + oidDotNotationToNames["2.5.4.25"] = OIDName{ShortName: "internationaliSDNNumber", LongName: "internationaliSDNNumber"} + oidDotNotationToNames["2.5.4.26"] = OIDName{ShortName: "registeredAddress", LongName: "registeredAddress"} + oidDotNotationToNames["2.5.4.27"] = OIDName{ShortName: "destinationIndicator", LongName: "destinationIndicator"} + oidDotNotationToNames["2.5.4.28"] = OIDName{ShortName: "preferredDeliveryMethod", LongName: "preferredDeliveryMethod"} + oidDotNotationToNames["2.5.4.29"] = OIDName{ShortName: "presentationAddress", LongName: "presentationAddress"} + oidDotNotationToNames["2.5.4.30"] = OIDName{ShortName: "supportedApplicationContext", LongName: "supportedApplicationContext"} + oidDotNotationToNames["2.5.4.31"] = OIDName{ShortName: "member", LongName: "member"} + oidDotNotationToNames["2.5.4.32"] = OIDName{ShortName: "owner", LongName: "owner"} + oidDotNotationToNames["2.5.4.33"] = OIDName{ShortName: "roleOccupant", LongName: "roleOccupant"} + oidDotNotationToNames["2.5.4.34"] = OIDName{ShortName: "seeAlso", LongName: "seeAlso"} + oidDotNotationToNames["2.5.4.35"] = OIDName{ShortName: "userPassword", LongName: "userPassword"} + oidDotNotationToNames["2.5.4.36"] = OIDName{ShortName: "userCertificate", LongName: "userCertificate"} + oidDotNotationToNames["2.5.4.37"] = OIDName{ShortName: "cACertificate", LongName: "cACertificate"} + oidDotNotationToNames["2.5.4.38"] = OIDName{ShortName: "authorityRevocationList", LongName: "authorityRevocationList"} + oidDotNotationToNames["2.5.4.39"] = OIDName{ShortName: "certificateRevocationList", LongName: "certificateRevocationList"} + oidDotNotationToNames["2.5.4.40"] = OIDName{ShortName: "crossCertificatePair", LongName: "crossCertificatePair"} + oidDotNotationToNames["2.5.4.47"] = OIDName{ShortName: "enhancedSearchGuide", LongName: "enhancedSearchGuide"} + oidDotNotationToNames["2.5.4.48"] = OIDName{ShortName: "protocolInformation", LongName: "protocolInformation"} + oidDotNotationToNames["2.5.4.49"] = OIDName{ShortName: "distinguishedName", LongName: "distinguishedName"} + oidDotNotationToNames["2.5.4.50"] = OIDName{ShortName: "uniqueMember", LongName: "uniqueMember"} + oidDotNotationToNames["2.5.4.51"] = OIDName{ShortName: "houseIdentifier", LongName: "houseIdentifier"} + oidDotNotationToNames["2.5.4.52"] = OIDName{ShortName: "supportedAlgorithms", LongName: "supportedAlgorithms"} + oidDotNotationToNames["2.5.4.53"] = OIDName{ShortName: "deltaRevocationList", LongName: "deltaRevocationList"} + oidDotNotationToNames["2.5.4.54"] = OIDName{ShortName: "dmdName", LongName: "dmdName"} + oidDotNotationToNames["1.3.6.1.4.1.311.17.1"] = OIDName{ShortName: "MS_LOCAL_MACHINE_KEYSET", LongName: "MS_LOCAL_MACHINE_KEYSET"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.4.1"] = OIDName{ShortName: "MS_YESNO_TRUST_ATTR", LongName: "MS_YESNO_TRUST_ATTR"} + oidDotNotationToNames["1.3.6.1.4.1.311.13.2.1"] = OIDName{ShortName: "MS_ENROLLMENT_NAME_VALUE_PAIR", LongName: "MS_ENROLLMENT_NAME_VALUE_PAIR"} + oidDotNotationToNames["1.3.6.1.4.1.311.13.2.3"] = OIDName{ShortName: "MS_OS_VERSION", LongName: "MS_OS_VERSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.13.2.2"] = OIDName{ShortName: "MS_ENROLLMENT_CSP_PROVIDER", LongName: "MS_ENROLLMENT_CSP_PROVIDER"} + oidDotNotationToNames["1.3.6.1.4.1.311.12.1.2"] = OIDName{ShortName: "MS_CATALOG_LIST_MEMBER", LongName: "MS_CATALOG_LIST_MEMBER"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.11"] = OIDName{ShortName: "MS_CERT_PROP_ID_PREFIX", LongName: "MS_CERT_PROP_ID_PREFIX"} + oidDotNotationToNames["1.3.6.1.4.1.311.13.1"] = OIDName{ShortName: "MS_RENEWAL_CERTIFICATE", LongName: "MS_RENEWAL_CERTIFICATE"} + oidDotNotationToNames["1.3.6.1.4.1.311"] = OIDName{ShortName: "MS_OID", LongName: "MS_OID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.30"] = OIDName{ShortName: "MS_SPC_SIPINFO_OBJID", LongName: "MS_SPC_SIPINFO_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.88.3"] = OIDName{ShortName: "MS_CAPICOM_ENCRYPTED_DATA", LongName: "MS_CAPICOM_ENCRYPTED_DATA"} + oidDotNotationToNames["1.3.6.1.4.1.311.88.2"] = OIDName{ShortName: "MS_CAPICOM_ATTRIBUTE", LongName: "MS_CAPICOM_ATTRIBUTE"} + oidDotNotationToNames["1.3.6.1.4.1.311.88.1"] = OIDName{ShortName: "MS_CAPICOM_VERSION", LongName: "MS_CAPICOM_VERSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.6.2"] = OIDName{ShortName: "MS_LICENSE_SERVER", LongName: "MS_LICENSE_SERVER"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.10.1"] = OIDName{ShortName: "MS_CMC_ADD_ATTRIBUTES", LongName: "MS_CMC_ADD_ATTRIBUTES"} + oidDotNotationToNames["1.3.6.1.4.1.311.3.2.1"] = OIDName{ShortName: "MS_SPC_TIME_STAMP_REQUEST_OBJID", LongName: "MS_SPC_TIME_STAMP_REQUEST_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.12.1"] = OIDName{ShortName: "MS_ANY_APPLICATION_POLICY", LongName: "MS_ANY_APPLICATION_POLICY"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.0.4"] = OIDName{ShortName: "MS_PEERNET_CERT_VERSION", LongName: "MS_PEERNET_CERT_VERSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.19"] = OIDName{ShortName: "MS_DS_EMAIL_REPLICATION", LongName: "MS_DS_EMAIL_REPLICATION"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.16"] = OIDName{ShortName: "MS_ARCHIVED_KEY_CERT_HASH", LongName: "MS_ARCHIVED_KEY_CERT_HASH"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.17"] = OIDName{ShortName: "MS_ISSUED_CERT_HASH", LongName: "MS_ISSUED_CERT_HASH"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.14"] = OIDName{ShortName: "MS_CRL_SELF_CDP", LongName: "MS_CRL_SELF_CDP"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.15"] = OIDName{ShortName: "MS_REQUIRE_CERT_CHAIN_POLICY", LongName: "MS_REQUIRE_CERT_CHAIN_POLICY"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.12"] = OIDName{ShortName: "MS_APPLICATION_POLICY_CONSTRAINTS", LongName: "MS_APPLICATION_POLICY_CONSTRAINTS"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.13"] = OIDName{ShortName: "MS_ARCHIVED_KEY_ATTR", LongName: "MS_ARCHIVED_KEY_ATTR"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.10"] = OIDName{ShortName: "MS_APPLICATION_CERT_POLICIES", LongName: "MS_APPLICATION_CERT_POLICIES"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.11"] = OIDName{ShortName: "MS_APPLICATION_POLICY_MAPPINGS", LongName: "MS_APPLICATION_POLICY_MAPPINGS"} + oidDotNotationToNames["1.3.6.1.4.1.311.44"] = OIDName{ShortName: "MS_Peer_Networking", LongName: "MS_Peer_Networking"} + oidDotNotationToNames["1.3.6.1.4.1.311.12.2.1"] = OIDName{ShortName: "MS_CAT_NAMEVALUE_OBJID", LongName: "MS_CAT_NAMEVALUE_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.5.1"] = OIDName{ShortName: "MS_DRM", LongName: "MS_DRM"} + oidDotNotationToNames["1.3.6.1.4.1.311.43"] = OIDName{ShortName: "MS_WWOps_BizExt", LongName: "MS_WWOps_BizExt"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.5.2"] = OIDName{ShortName: "MS_DRM_INDIVIDUALIZATION", LongName: "MS_DRM_INDIVIDUALIZATION"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.13"] = OIDName{ShortName: "MS_KP_LIFETIME_SIGNING", LongName: "MS_KP_LIFETIME_SIGNING"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.12"] = OIDName{ShortName: "MS_KP_DOCUMENT_SIGNING", LongName: "MS_KP_DOCUMENT_SIGNING"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.11"] = OIDName{ShortName: "MS_KP_KEY_RECOVERY", LongName: "MS_KP_KEY_RECOVERY"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.10"] = OIDName{ShortName: "MS_KP_QUALIFIED_SUBORDINATION", LongName: "MS_KP_QUALIFIED_SUBORDINATION"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.1"] = OIDName{ShortName: "MS_PKIX_LICENSE_INFO", LongName: "MS_PKIX_LICENSE_INFO"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.2"] = OIDName{ShortName: "MS_PKIX_MANUFACTURER", LongName: "MS_PKIX_MANUFACTURER"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.3"] = OIDName{ShortName: "MS_PKIX_MANUFACTURER_MS_SPECIFIC", LongName: "MS_PKIX_MANUFACTURER_MS_SPECIFIC"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.4"] = OIDName{ShortName: "MS_PKIX_HYDRA_CERT_VERSION", LongName: "MS_PKIX_HYDRA_CERT_VERSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.5"] = OIDName{ShortName: "MS_PKIX_LICENSED_PRODUCT_INFO", LongName: "MS_PKIX_LICENSED_PRODUCT_INFO"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.6"] = OIDName{ShortName: "MS_PKIX_MS_LICENSE_SERVER_INFO", LongName: "MS_PKIX_MS_LICENSE_SERVER_INFO"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.7"] = OIDName{ShortName: "MS_PKIS_PRODUCT_SPECIFIC_OID", LongName: "MS_PKIS_PRODUCT_SPECIFIC_OID"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.22"] = OIDName{ShortName: "MS_CERTSRV_CROSSCA_VERSION", LongName: "MS_CERTSRV_CROSSCA_VERSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.21"] = OIDName{ShortName: "MS_ENCRYPTED_KEY_HASH", LongName: "MS_ENCRYPTED_KEY_HASH"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.20"] = OIDName{ShortName: "MS_REQUEST_CLIENT_INFO", LongName: "MS_REQUEST_CLIENT_INFO"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.3"] = OIDName{ShortName: "MS_CERT_MANIFOLD", LongName: "MS_CERT_MANIFOLD"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.1.1"] = OIDName{ShortName: "MS_SORTED_CTL", LongName: "MS_SORTED_CTL"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.1.3"] = OIDName{ShortName: "MS_PEERNET_PNRP_PAYLOAD", LongName: "MS_PEERNET_PNRP_PAYLOAD"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.7.1"] = OIDName{ShortName: "MS_KEYID_RDN", LongName: "MS_KEYID_RDN"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.1.1"] = OIDName{ShortName: "MS_PEERNET_PNRP_ADDRESS", LongName: "MS_PEERNET_PNRP_ADDRESS"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.8"] = OIDName{ShortName: "MS_ENTERPRISE_OID_ROOT", LongName: "MS_ENTERPRISE_OID_ROOT"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.1.4"] = OIDName{ShortName: "MS_PEERNET_PNRP_ID", LongName: "MS_PEERNET_PNRP_ID"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.3.1"] = OIDName{ShortName: "MS_PEERNET_GROUPING_PEERNAME", LongName: "MS_PEERNET_GROUPING_PEERNAME"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.12"] = OIDName{ShortName: "MS_CryptUI", LongName: "MS_CryptUI"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.10"] = OIDName{ShortName: "MS_CMC_OIDs", LongName: "MS_CMC_OIDs"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.11"] = OIDName{ShortName: "MS_certificate_property_OIDs", LongName: "MS_certificate_property_OIDs"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.4"] = OIDName{ShortName: "MS_SPC_INDIRECT_DATA_OBJID", LongName: "MS_SPC_INDIRECT_DATA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.2"] = OIDName{ShortName: "MS_CTL_for_Software_Publishers_Trusted_CAs", LongName: "MS_CTL_for_Software_Publishers_Trusted_CAs"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.3.5"] = OIDName{ShortName: "MS_PEERNET_GROUPING_CLASSIFIERS", LongName: "MS_PEERNET_GROUPING_CLASSIFIERS"} + oidDotNotationToNames["1.3.6.1.4.1.311.2"] = OIDName{ShortName: "MS_Authenticode", LongName: "MS_Authenticode"} + oidDotNotationToNames["1.3.6.1.4.1.311.3"] = OIDName{ShortName: "MS_Time_Stamping", LongName: "MS_Time_Stamping"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.7"] = OIDName{ShortName: "MS_CERTIFICATE_TEMPLATE", LongName: "MS_CERTIFICATE_TEMPLATE"} + oidDotNotationToNames["1.3.6.1.4.1.311.4"] = OIDName{ShortName: "MS_Permissions", LongName: "MS_Permissions"} + oidDotNotationToNames["1.3.6.1.4.1.311.30"] = OIDName{ShortName: "MS_IIS", LongName: "MS_IIS"} + oidDotNotationToNames["1.3.6.1.4.1.311.19"] = OIDName{ShortName: "MS_ISPU_Test", LongName: "MS_ISPU_Test"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.7"] = OIDName{ShortName: "MS_OEM_WHQL_CRYPTO", LongName: "MS_OEM_WHQL_CRYPTO"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.6"] = OIDName{ShortName: "MS_NT5_CRYPTO", LongName: "MS_NT5_CRYPTO"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.5"] = OIDName{ShortName: "MS_WHQL_CRYPTO", LongName: "MS_WHQL_CRYPTO"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.4"] = OIDName{ShortName: "MS_EFS_CRYPTO", LongName: "MS_EFS_CRYPTO"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.2.3"] = OIDName{ShortName: "MS_NT_PRINCIPAL_NAME", LongName: "MS_NT_PRINCIPAL_NAME"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.2.2"] = OIDName{ShortName: "MS_KP_SMARTCARD_LOGON", LongName: "MS_KP_SMARTCARD_LOGON"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.2.1"] = OIDName{ShortName: "MS_ENROLLMENT_AGENT", LongName: "MS_ENROLLMENT_AGENT"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.9"] = OIDName{ShortName: "MS_ROOT_LIST_SIGNER", LongName: "MS_ROOT_LIST_SIGNER"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.8"] = OIDName{ShortName: "MS_EMBEDDED_NT_CRYPTO", LongName: "MS_EMBEDDED_NT_CRYPTO"} + oidDotNotationToNames["1.3.6.1.4.1.311.18.8"] = OIDName{ShortName: "MS_PKIS_TLSERVER_SPK_OID", LongName: "MS_PKIS_TLSERVER_SPK_OID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.2.2"] = OIDName{ShortName: "MS_TRUSTED_CLIENT_AUTH_CA_LIST", LongName: "MS_TRUSTED_CLIENT_AUTH_CA_LIST"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.2.3"] = OIDName{ShortName: "MS_TRUSTED_SERVER_AUTH_CA_LIST", LongName: "MS_TRUSTED_SERVER_AUTH_CA_LIST"} + oidDotNotationToNames["1.3.6.1.4.1.311.12.1.1"] = OIDName{ShortName: "MS_CATALOG_LIST", LongName: "MS_CATALOG_LIST"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.2.1"] = OIDName{ShortName: "MS_TRUSTED_CODESIGNING_CA_LIST", LongName: "MS_TRUSTED_CODESIGNING_CA_LIST"} + oidDotNotationToNames["1.3.6.1.4.1.311.45"] = OIDName{ShortName: "MS_Mobile_Devices_Code_Signing", LongName: "MS_Mobile_Devices_Code_Signing"} + oidDotNotationToNames["1.3.6.1.4.1.311.30.1"] = OIDName{ShortName: "MS_IIS_VIRTUAL_SERVER", LongName: "MS_IIS_VIRTUAL_SERVER"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.14"] = OIDName{ShortName: "MS_KP_MOBILE_DEVICE_SOFTWARE", LongName: "MS_KP_MOBILE_DEVICE_SOFTWARE"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.8.1"] = OIDName{ShortName: "MS_REMOVE_CERTIFICATE", LongName: "MS_REMOVE_CERTIFICATE"} + oidDotNotationToNames["1.3.6.1.4.1.311.42"] = OIDName{ShortName: "MS_Corporate_PKI_(ITG)", LongName: "MS_Corporate_PKI_(ITG)"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.26"] = OIDName{ShortName: "MS_SPC_MINIMAL_CRITERIA_OBJID", LongName: "MS_SPC_MINIMAL_CRITERIA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.3.2"] = OIDName{ShortName: "MS_PEERNET_GROUPING_FLAGS", LongName: "MS_PEERNET_GROUPING_FLAGS"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.3.3"] = OIDName{ShortName: "MS_PEERNET_GROUPING_ROLES", LongName: "MS_PEERNET_GROUPING_ROLES"} + oidDotNotationToNames["1.3.6.1.4.1.311.41"] = OIDName{ShortName: "MS_Licensing_and_Registration", LongName: "MS_Licensing_and_Registration"} + oidDotNotationToNames["1.3.6.1.4.1.311.20"] = OIDName{ShortName: "MS_Enrollment_Infrastructure", LongName: "MS_Enrollment_Infrastructure"} + oidDotNotationToNames["1.3.6.1.4.1.311.40"] = OIDName{ShortName: "MS_Fonts", LongName: "MS_Fonts"} + oidDotNotationToNames["1.3.6.1.4.1.311.21"] = OIDName{ShortName: "MS_CertSrv_Infrastructure", LongName: "MS_CertSrv_Infrastructure"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.3.1"] = OIDName{ShortName: "MS_SERIALIZED", LongName: "MS_SERIALIZED"} + oidDotNotationToNames["1.3.6.1.4.1.311.12.2.2"] = OIDName{ShortName: "MS_CAT_MEMBERINFO_OBJID", LongName: "MS_CAT_MEMBERINFO_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.25"] = OIDName{ShortName: "MS_Directory_Service", LongName: "MS_Directory_Service"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.0.3"] = OIDName{ShortName: "MS_PEERNET_CLASSIFIER", LongName: "MS_PEERNET_CLASSIFIER"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.0.1"] = OIDName{ShortName: "MS_PEERNET_CERT_TYPE", LongName: "MS_PEERNET_CERT_TYPE"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.1"] = OIDName{ShortName: "MS_PEERNET_PNRP", LongName: "MS_PEERNET_PNRP"} + oidDotNotationToNames["1.3.6.1.4.1.311.88.3.1"] = OIDName{ShortName: "MS_CAPICOM_ENCRYPTED_CONTENT", LongName: "MS_CAPICOM_ENCRYPTED_CONTENT"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.0.2"] = OIDName{ShortName: "MS_PEERNET_PEERNAME", LongName: "MS_PEERNET_PEERNAME"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.3"] = OIDName{ShortName: "MS_PEERNET_GROUPING", LongName: "MS_PEERNET_GROUPING"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.1.2"] = OIDName{ShortName: "MS_PEERNET_PNRP_FLAGS", LongName: "MS_PEERNET_PNRP_FLAGS"} + oidDotNotationToNames["1.3.6.1.4.1.311.15"] = OIDName{ShortName: "MS_Java", LongName: "MS_Java"} + oidDotNotationToNames["1.3.6.1.4.1.311.16"] = OIDName{ShortName: "MS_Outlook/Exchange", LongName: "MS_Outlook/Exchange"} + oidDotNotationToNames["1.3.6.1.4.1.311.17"] = OIDName{ShortName: "MS_PKCS12_attributes", LongName: "MS_PKCS12_attributes"} + oidDotNotationToNames["1.3.6.1.4.1.311.10"] = OIDName{ShortName: "MS_Crypto_2.0", LongName: "MS_Crypto_2.0"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.9"] = OIDName{ShortName: "MS_RDN_DUMMY_SIGNER", LongName: "MS_RDN_DUMMY_SIGNER"} + oidDotNotationToNames["1.3.6.1.4.1.311.12"] = OIDName{ShortName: "MS_Catalog", LongName: "MS_Catalog"} + oidDotNotationToNames["1.3.6.1.4.1.311.13"] = OIDName{ShortName: "MS_PKCS10_OIDs", LongName: "MS_PKCS10_OIDs"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.4"] = OIDName{ShortName: "MS_CRL_NEXT_PUBLISH", LongName: "MS_CRL_NEXT_PUBLISH"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.5"] = OIDName{ShortName: "MS_KP_CA_EXCHANGE", LongName: "MS_KP_CA_EXCHANGE"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.6"] = OIDName{ShortName: "MS_KP_KEY_RECOVERY_AGENT", LongName: "MS_KP_KEY_RECOVERY_AGENT"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.6.1"] = OIDName{ShortName: "MS_LICENSES", LongName: "MS_LICENSES"} + oidDotNotationToNames["1.3.6.1.4.1.311.18"] = OIDName{ShortName: "MS_Hydra", LongName: "MS_Hydra"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.1"] = OIDName{ShortName: "MS_CERTSRV_CA_VERSION", LongName: "MS_CERTSRV_CA_VERSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.2"] = OIDName{ShortName: "MS_CERTSRV_PREVIOUS_CERT_HASH", LongName: "MS_CERTSRV_PREVIOUS_CERT_HASH"} + oidDotNotationToNames["1.3.6.1.4.1.311.21.3"] = OIDName{ShortName: "MS_CRL_VIRTUAL_BASE", LongName: "MS_CRL_VIRTUAL_BASE"} + oidDotNotationToNames["1.3.6.1.4.1.311.31.1"] = OIDName{ShortName: "MS_PRODUCT_UPDATE", LongName: "MS_PRODUCT_UPDATE"} + oidDotNotationToNames["1.3.6.1.4.1.311.16.4"] = OIDName{ShortName: "MS_MICROSOFT_Encryption_Key_Preference", LongName: "MS_MICROSOFT_Encryption_Key_Preference"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.2"] = OIDName{ShortName: "MS_PEERNET_IDENTITY", LongName: "MS_PEERNET_IDENTITY"} + oidDotNotationToNames["1.3.6.1.4.1.311.88"] = OIDName{ShortName: "MS_CAPICOM", LongName: "MS_CAPICOM"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.9.1"] = OIDName{ShortName: "MS_CROSS_CERT_DIST_POINTS", LongName: "MS_CROSS_CERT_DIST_POINTS"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.19"] = OIDName{ShortName: "MS_SPC_STRUCTURED_STORAGE_DATA_OBJID", LongName: "MS_SPC_STRUCTURED_STORAGE_DATA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.18"] = OIDName{ShortName: "MS_SPC_RAW_FILE_DATA_OBJID", LongName: "MS_SPC_RAW_FILE_DATA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.25"] = OIDName{ShortName: "MS_SPC_GLUE_RDN_OBJID", LongName: "MS_SPC_GLUE_RDN_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.11"] = OIDName{ShortName: "MS_SPC_STATEMENT_TYPE_OBJID", LongName: "MS_SPC_STATEMENT_TYPE_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.10"] = OIDName{ShortName: "MS_SPC_SP_AGENCY_INFO_OBJID", LongName: "MS_SPC_SP_AGENCY_INFO_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.4.1"] = OIDName{ShortName: "MS_EFS_RECOVERY", LongName: "MS_EFS_RECOVERY"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.12"] = OIDName{ShortName: "MS_SPC_SP_OPUS_INFO_OBJID", LongName: "MS_SPC_SP_OPUS_INFO_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.15"] = OIDName{ShortName: "MS_SPC_PE_IMAGE_DATA_OBJID", LongName: "MS_SPC_PE_IMAGE_DATA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.14"] = OIDName{ShortName: "MS_SPC_CERT_EXTENSIONS_OBJID", LongName: "MS_SPC_CERT_EXTENSIONS_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.25.1"] = OIDName{ShortName: "MS_NTDS_REPLICATION", LongName: "MS_NTDS_REPLICATION"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.27"] = OIDName{ShortName: "MS_SPC_FINANCIAL_CRITERIA_OBJID", LongName: "MS_SPC_FINANCIAL_CRITERIA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.3"] = OIDName{ShortName: "MS_SERVER_GATED_CRYPTO", LongName: "MS_SERVER_GATED_CRYPTO"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.11.1"] = OIDName{ShortName: "MS_CERT_PROP_ID_PREFIX", LongName: "MS_CERT_PROP_ID_PREFIX"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.2"] = OIDName{ShortName: "MS_KP_TIME_STAMP_SIGNING", LongName: "MS_KP_TIME_STAMP_SIGNING"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.3.1"] = OIDName{ShortName: "MS_KP_CTL_USAGE_SIGNING", LongName: "MS_KP_CTL_USAGE_SIGNING"} + oidDotNotationToNames["1.3.6.1.4.1.311.31"] = OIDName{ShortName: "MS_Windows_updates_and_service_packs", LongName: "MS_Windows_updates_and_service_packs"} + oidDotNotationToNames["1.3.6.1.4.1.311.88.2.1"] = OIDName{ShortName: "MS_CAPICOM_DOCUMENT_NAME", LongName: "MS_CAPICOM_DOCUMENT_NAME"} + oidDotNotationToNames["1.3.6.1.4.1.311.88.2.2"] = OIDName{ShortName: "MS_CAPICOM_DOCUMENT_DESCRIPTION", LongName: "MS_CAPICOM_DOCUMENT_DESCRIPTION"} + oidDotNotationToNames["1.3.6.1.4.1.311.44.2.2"] = OIDName{ShortName: "MS_PEERNET_IDENTITY_FLAGS", LongName: "MS_PEERNET_IDENTITY_FLAGS"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.1"] = OIDName{ShortName: "MS_AUTO_ENROLL_CTL_USAGE", LongName: "MS_AUTO_ENROLL_CTL_USAGE"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.1"] = OIDName{ShortName: "MS_CTL", LongName: "MS_CTL"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.2"] = OIDName{ShortName: "MS_NEXT_UPDATE_LOCATION", LongName: "MS_NEXT_UPDATE_LOCATION"} + oidDotNotationToNames["1.3.6.1.4.1.311.20.2"] = OIDName{ShortName: "MS_ENROLL_CERTTYPE_EXTENSION", LongName: "MS_ENROLL_CERTTYPE_EXTENSION"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.20"] = OIDName{ShortName: "MS_SPC_JAVA_CLASS_DATA_OBJID", LongName: "MS_SPC_JAVA_CLASS_DATA_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.21"] = OIDName{ShortName: "MS_SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID", LongName: "MS_SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.22"] = OIDName{ShortName: "MS_SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID", LongName: "MS_SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID"} + oidDotNotationToNames["1.3.6.1.4.1.311.10.7"] = OIDName{ShortName: "MS_MICROSOFT_RDN_PREFIX", LongName: "MS_MICROSOFT_RDN_PREFIX"} + oidDotNotationToNames["1.3.6.1.4.1.311.2.1.28"] = OIDName{ShortName: "MS_SPC_LINK_OBJID", LongName: "MS_SPC_LINK_OBJID"} + // EV Certificates + oidDotNotationToNames["1.3.6.1.4.1.311.60.2.1.1"] = OIDName{ShortName: "jurisdictionLocality", LongName: "jurisdictionLocalityName"} + oidDotNotationToNames["1.3.6.1.4.1.311.60.2.1.2"] = OIDName{ShortName: "jurisdictionStateOrProvince", LongName: "jurisdictionStateOrProvinceName"} + oidDotNotationToNames["1.3.6.1.4.1.311.60.2.1.3"] = OIDName{ShortName: "jurisdictionCountry", LongName: "jurisdictionCountryName"} + +} diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go b/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go new file mode 100644 index 0000000000..5f3f013c6b --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go @@ -0,0 +1,299 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package pkix contains shared, low level structures used for ASN.1 parsing +// and serialization of X.509 certificates, CRL and OCSP. +package pkix + +import ( + "encoding/asn1" + "math/big" + "strings" + "time" +) + +// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC +// 5280, section 4.1.1.2. +type AlgorithmIdentifier struct { + Algorithm asn1.ObjectIdentifier + Parameters asn1.RawValue `asn1:"optional"` +} + +type RDNSequence []RelativeDistinguishedNameSET + +type RelativeDistinguishedNameSET []AttributeTypeAndValue + +// AttributeTypeAndValue mirrors the ASN.1 structure of the same name in +// http://tools.ietf.org/html/rfc5280#section-4.1.2.4 +type AttributeTypeAndValue struct { + Type asn1.ObjectIdentifier `json:"type"` + Value interface{} `json:"value"` +} + +// AttributeTypeAndValueSET represents a set of ASN.1 sequences of +// AttributeTypeAndValue sequences from RFC 2986 (PKCS #10). +type AttributeTypeAndValueSET struct { + Type asn1.ObjectIdentifier + Value [][]AttributeTypeAndValue `asn1:"set"` +} + +// Extension represents the ASN.1 structure of the same name. See RFC +// 5280, section 4.2. +type Extension struct { + Id asn1.ObjectIdentifier + Critical bool `asn1:"optional"` + Value []byte +} + +// Name represents an X.509 distinguished name. This only includes the common +// elements of a DN. Additional elements in the name are ignored. +type Name struct { + Country, Organization, OrganizationalUnit []string + Locality, Province []string + StreetAddress, PostalCode, DomainComponent []string + EmailAddress []string + SerialNumber, CommonName string + SerialNumbers, CommonNames []string + GivenName, Surname []string + OrganizationIDs []string + // EV Components + JurisdictionLocality, JurisdictionProvince, JurisdictionCountry []string + + Names []AttributeTypeAndValue + ExtraNames []AttributeTypeAndValue + + // OriginalRDNS is saved if the name is populated using FillFromRDNSequence. + // Additionally, if OriginalRDNS is non-nil, the String and ToRDNSequence + // methods will simply use this. + OriginalRDNS RDNSequence +} + +// FillFromRDNSequence populates n based on the AttributeTypeAndValueSETs in the +// RDNSequence. It save the sequence as OriginalRDNS. +func (n *Name) FillFromRDNSequence(rdns *RDNSequence) { + n.OriginalRDNS = *rdns + for _, rdn := range *rdns { + if len(rdn) == 0 { + continue + } + atv := rdn[0] + n.Names = append(n.Names, atv) + value, ok := atv.Value.(string) + if !ok { + continue + } + + t := atv.Type + if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { + switch t[3] { + case 3: + n.CommonName = value + n.CommonNames = append(n.CommonNames, value) + case 4: + n.Surname = append(n.Surname, value) + case 5: + n.SerialNumber = value + n.SerialNumbers = append(n.SerialNumbers, value) + case 6: + n.Country = append(n.Country, value) + case 7: + n.Locality = append(n.Locality, value) + case 8: + n.Province = append(n.Province, value) + case 9: + n.StreetAddress = append(n.StreetAddress, value) + case 10: + n.Organization = append(n.Organization, value) + case 11: + n.OrganizationalUnit = append(n.OrganizationalUnit, value) + case 17: + n.PostalCode = append(n.PostalCode, value) + case 42: + n.GivenName = append(n.GivenName, value) + case 97: + n.OrganizationIDs = append(n.OrganizationIDs, value) + } + } else if t.Equal(oidDomainComponent) { + n.DomainComponent = append(n.DomainComponent, value) + } else if t.Equal(oidDNEmailAddress) { + // Deprecated, see RFC 5280 Section 4.1.2.6 + n.EmailAddress = append(n.EmailAddress, value) + } else if t.Equal(oidJurisdictionLocality) { + n.JurisdictionLocality = append(n.JurisdictionLocality, value) + } else if t.Equal(oidJurisdictionProvince) { + n.JurisdictionProvince = append(n.JurisdictionProvince, value) + } else if t.Equal(oidJurisdictionCountry) { + n.JurisdictionCountry = append(n.JurisdictionCountry, value) + } + } +} + +var ( + oidCountry = []int{2, 5, 4, 6} + oidOrganization = []int{2, 5, 4, 10} + oidOrganizationalUnit = []int{2, 5, 4, 11} + oidCommonName = []int{2, 5, 4, 3} + oidSurname = []int{2, 5, 4, 4} + oidSerialNumber = []int{2, 5, 4, 5} + oidLocality = []int{2, 5, 4, 7} + oidProvince = []int{2, 5, 4, 8} + oidStreetAddress = []int{2, 5, 4, 9} + oidPostalCode = []int{2, 5, 4, 17} + oidGivenName = []int{2, 5, 4, 42} + oidDomainComponent = []int{0, 9, 2342, 19200300, 100, 1, 25} + oidDNEmailAddress = []int{1, 2, 840, 113549, 1, 9, 1} + // EV + oidJurisdictionLocality = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 1} + oidJurisdictionProvince = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 2} + oidJurisdictionCountry = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 3} + // QWACS + oidOrganizationID = []int{2, 5, 4, 97} +) + +// appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence +// and returns the new value. The relativeDistinguishedNameSET contains an +// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and +// search for AttributeTypeAndValue. +func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence { + // NOTE: stdlib prevents adding if the oid is already present in n.ExtraNames + //if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) { + if len(values) == 0 { + return in + } + + s := make([]AttributeTypeAndValue, len(values)) + for i, value := range values { + s[i].Type = oid + s[i].Value = value + } + + return append(in, s) +} + +// String returns an RDNSequence as comma seperated list of +// AttributeTypeAndValues in canonical form. +func (seq RDNSequence) String() string { + out := make([]string, 0, len(seq)) + // An RDNSequence is effectively an [][]AttributeTypeAndValue + for _, atvSet := range seq { + for _, atv := range atvSet { + // Convert each individual AttributeTypeAndValue to X=Y + attrParts := make([]string, 0, 2) + oidString := atv.Type.String() + oidName, ok := oidDotNotationToNames[oidString] + if ok { + attrParts = append(attrParts, oidName.ShortName) + } else { + attrParts = append(attrParts, oidString) + } + switch value := atv.Value.(type) { + case string: + attrParts = append(attrParts, value) + case []byte: + attrParts = append(attrParts, string(value)) + default: + continue + } + attrString := strings.Join(attrParts, "=") + out = append(out, attrString) + } + } + return strings.Join(out, ", ") +} + +// ToRDNSequence returns OriginalRDNS is populated. Otherwise, it builds an +// RDNSequence in canonical order. +func (n Name) ToRDNSequence() (ret RDNSequence) { + if n.OriginalRDNS != nil { + return n.OriginalRDNS + } + if len(n.CommonName) > 0 { + ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName) + } + ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit) + ret = n.appendRDNs(ret, n.Organization, oidOrganization) + ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress) + ret = n.appendRDNs(ret, n.Locality, oidLocality) + ret = n.appendRDNs(ret, n.Province, oidProvince) + ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode) + ret = n.appendRDNs(ret, n.Country, oidCountry) + ret = n.appendRDNs(ret, n.DomainComponent, oidDomainComponent) + // EV Components + ret = n.appendRDNs(ret, n.JurisdictionLocality, oidJurisdictionLocality) + ret = n.appendRDNs(ret, n.JurisdictionProvince, oidJurisdictionProvince) + ret = n.appendRDNs(ret, n.JurisdictionCountry, oidJurisdictionCountry) + // QWACS + ret = n.appendRDNs(ret, n.OrganizationIDs, oidOrganizationID) + if len(n.SerialNumber) > 0 { + ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber) + } + ret = append(ret, n.ExtraNames) + return ret +} + +// oidInAttributeTypeAndValue returns whether a type with the given OID exists +// in atv. +func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool { + for _, a := range atv { + if a.Type.Equal(oid) { + return true + } + } + return false +} + +// CertificateList represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the +// signature. +type CertificateList struct { + TBSCertList TBSCertificateList + SignatureAlgorithm AlgorithmIdentifier + SignatureValue asn1.BitString +} + +// HasExpired reports whether now is past the expiry time of certList. +func (certList *CertificateList) HasExpired(now time.Time) bool { + return now.After(certList.TBSCertList.NextUpdate) +} + +// String returns a canonical representation of a DistinguishedName +func (n *Name) String() string { + seq := n.ToRDNSequence() + return seq.String() +} + +// OtherName represents the ASN.1 structure of the same name. See RFC +// 5280, section 4.2.1.6. +type OtherName struct { + TypeID asn1.ObjectIdentifier + Value asn1.RawValue `asn1:"explicit"` +} + +// EDIPartyName represents the ASN.1 structure of the same name. See RFC +// 5280, section 4.2.1.6. +type EDIPartyName struct { + NameAssigner string `asn1:"tag:0,optional,explicit" json:"name_assigner,omitempty"` + PartyName string `asn1:"tag:1,explicit" json:"party_name"` +} + +// TBSCertificateList represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. +type TBSCertificateList struct { + Raw asn1.RawContent + Version int `asn1:"optional,default:0"` + Signature AlgorithmIdentifier + Issuer RDNSequence + ThisUpdate time.Time + NextUpdate time.Time `asn1:"optional"` + RevokedCertificates []RevokedCertificate `asn1:"optional"` + Extensions []Extension `asn1:"tag:0,optional,explicit"` +} + +// RevokedCertificate represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. +type RevokedCertificate struct { + SerialNumber *big.Int + RevocationTime time.Time + Extensions []Extension `asn1:"optional"` +} diff --git a/vendor/github.com/zmap/zcrypto/x509/qc_statements.go b/vendor/github.com/zmap/zcrypto/x509/qc_statements.go new file mode 100644 index 0000000000..3adecd5c7b --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/qc_statements.go @@ -0,0 +1,173 @@ +package x509 + +import ( + "encoding/asn1" + "encoding/json" + "errors" +) + +type QCStatementASN struct { + StatementID asn1.ObjectIdentifier + StatementInfo asn1.RawValue `asn1:"optional"` +} + +func (s *QCStatementASN) MarshalJSON() ([]byte, error) { + aux := struct { + ID string `json:"id,omitempty"` + Value []byte `json:"value,omitempty"` + }{ + ID: s.StatementID.String(), + Value: s.StatementInfo.Bytes, + } + return json.Marshal(&aux) +} + +type QCStatementsASN struct { + QCStatements []QCStatementASN +} + +// ETSI OIDS from https://www.etsi.org/deliver/etsi_en/319400_319499/31941205/02.02.03_20/en_31941205v020203a.pdf +var ( + oidEtsiQcsQcCompliance = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 1} + oidEtsiQcsQcLimitValue = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 2} + oidEtsiQcsQcRetentionPeriod = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 3} + oidEtsiQcsQcSSCD = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 4} + oidEtsiQcsQcEuPDS = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 5} + oidEtsiQcsQcType = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6} + oidEtsiQcsQcCCLegislation = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 7} + oidEtsiQcsQctEsign = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 1} + oidEtsiQcsQctEseal = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 2} + oidEtsiQcsQctWeb = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 3} +) + +type QCStatements struct { + StatementIDs []string `json:"ids,omitempty"` + ParsedStatements *ParsedQCStatements `json:"parsed,omitempty"` +} + +type ParsedQCStatements struct { + ETSICompliance []bool `json:"etsi_compliance,omitempty"` + SSCD []bool `json:"sscd,omitempty"` + Types []QCType `json:"types,omitempty"` + Limit []MonetaryValue `json:"limit,omitempty"` + PDSLocations []PDSLocations `json:"pds_locations,omitempty"` + RetentionPeriod []int `json:"retention_period,omitempty"` + Legislation []QCLegistation `json:"legislation,omitempty"` +} + +type MonetaryValue struct { + Currency string `json:"currency,omitempty"` + CurrencyNumber int `json:"currency_number,omitempty"` + Amount int `json:"amount,omitempty"` + Exponent int `json:"exponent,omitempty"` +} + +type monetaryValueASNString struct { + Currency string `asn1:"printable"` + Amount int + Exponent int +} + +type monetaryValueASNNumber struct { + Currency int + Amount int + Exponent int +} + +type PDSLocations struct { + Locations []PDSLocation `json:"locations,omitempty"` +} + +type PDSLocation struct { + URL string `json:"url,omitempty" asn1:"ia5"` + Language string `json:"language,omitempty" asn1:"printable"` +} + +type QCType struct { + TypeIdentifiers []asn1.ObjectIdentifier +} + +type QCLegistation struct { + CountryCodes []string `json:"country_codes,omitempty"` +} + +func (qt *QCType) MarshalJSON() ([]byte, error) { + aux := struct { + Types []string `json:"ids,omitempty"` + }{ + Types: make([]string, len(qt.TypeIdentifiers)), + } + for idx := range qt.TypeIdentifiers { + aux.Types[idx] = qt.TypeIdentifiers[idx].String() + } + return json.Marshal(&aux) +} + +func (q *QCStatements) Parse(in *QCStatementsASN) error { + q.StatementIDs = make([]string, len(in.QCStatements)) + known := ParsedQCStatements{} + for i, s := range in.QCStatements { + val := in.QCStatements[i].StatementInfo.FullBytes + q.StatementIDs[i] = s.StatementID.String() + if s.StatementID.Equal(oidEtsiQcsQcCompliance) { + known.ETSICompliance = append(known.ETSICompliance, true) + if val != nil { + return errors.New("EtsiQcsQcCompliance QCStatement must not contain a statementInfo") + } + } else if s.StatementID.Equal(oidEtsiQcsQcLimitValue) { + // TODO + mvs := monetaryValueASNString{} + mvn := monetaryValueASNNumber{} + out := MonetaryValue{} + if _, err := asn1.Unmarshal(val, &mvs); err == nil { + out.Currency = mvs.Currency + out.Amount = mvs.Amount + out.Exponent = mvs.Exponent + } else if _, err := asn1.Unmarshal(val, &mvn); err == nil { + out.CurrencyNumber = mvn.Currency + out.Amount = mvn.Amount + out.Exponent = mvn.Exponent + } else { + return err + } + known.Limit = append(known.Limit, out) + } else if s.StatementID.Equal(oidEtsiQcsQcRetentionPeriod) { + var retentionPeriod int + if _, err := asn1.Unmarshal(val, &retentionPeriod); err != nil { + return err + } + known.RetentionPeriod = append(known.RetentionPeriod, retentionPeriod) + } else if s.StatementID.Equal(oidEtsiQcsQcSSCD) { + known.SSCD = append(known.SSCD, true) + if val != nil { + return errors.New("EtsiQcsQcSSCD QCStatement must not contain a statementInfo") + } + } else if s.StatementID.Equal(oidEtsiQcsQcEuPDS) { + locations := make([]PDSLocation, 0) + if _, err := asn1.Unmarshal(val, &locations); err != nil { + return err + } + known.PDSLocations = append(known.PDSLocations, PDSLocations{ + Locations: locations, + }) + } else if s.StatementID.Equal(oidEtsiQcsQcType) { + typeIds := make([]asn1.ObjectIdentifier, 0) + if _, err := asn1.Unmarshal(val, &typeIds); err != nil { + return err + } + known.Types = append(known.Types, QCType{ + TypeIdentifiers: typeIds, + }) + } else if s.StatementID.Equal(oidEtsiQcsQcCCLegislation) { + countryCodes := make([]string, 0) + if _, err := asn1.Unmarshal(val, &countryCodes); err != nil { + return err + } + known.Legislation = append(known.Legislation, QCLegistation{ + CountryCodes: countryCodes, + }) + } + } + q.ParsedStatements = &known + return nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/sec1.go b/vendor/github.com/zmap/zcrypto/x509/sec1.go new file mode 100644 index 0000000000..33f376c072 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/sec1.go @@ -0,0 +1,105 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "encoding/asn1" + "errors" + "fmt" + "math/big" +) + +const ecPrivKeyVersion = 1 + +// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure. +// References: +// RFC 5915 +// SEC1 - http://www.secg.org/sec1-v2.pdf +// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in +// most cases it is not. +type ecPrivateKey struct { + Version int + PrivateKey []byte + NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` + PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` +} + +// ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. +func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) { + return parseECPrivateKey(nil, der) +} + +// MarshalECPrivateKey marshals an EC private key into ASN.1, DER format. +func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { + oid, ok := oidFromNamedCurve(key.Curve) + if !ok { + return nil, errors.New("x509: unknown elliptic curve") + } + + privateKeyBytes := key.D.Bytes() + paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) + copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes) + + return asn1.Marshal(ecPrivateKey{ + Version: 1, + PrivateKey: paddedPrivateKey, + NamedCurveOID: oid, + PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, + }) +} + +// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. +// The OID for the named curve may be provided from another source (such as +// the PKCS8 container) - if it is provided then use this instead of the OID +// that may exist in the EC private key structure. +func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { + var privKey ecPrivateKey + if _, err := asn1.Unmarshal(der, &privKey); err != nil { + return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) + } + if privKey.Version != ecPrivKeyVersion { + return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) + } + + var curve elliptic.Curve + if namedCurveOID != nil { + curve = namedCurveFromOID(*namedCurveOID) + } else { + curve = namedCurveFromOID(privKey.NamedCurveOID) + } + if curve == nil { + return nil, errors.New("x509: unknown elliptic curve") + } + + k := new(big.Int).SetBytes(privKey.PrivateKey) + curveOrder := curve.Params().N + if k.Cmp(curveOrder) >= 0 { + return nil, errors.New("x509: invalid elliptic curve private key value") + } + priv := new(ecdsa.PrivateKey) + priv.Curve = curve + priv.D = k + + privateKey := make([]byte, (curveOrder.BitLen()+7)/8) + + // Some private keys have leading zero padding. This is invalid + // according to [SEC1], but this code will ignore it. + for len(privKey.PrivateKey) > len(privateKey) { + if privKey.PrivateKey[0] != 0 { + return nil, errors.New("x509: invalid private key length") + } + privKey.PrivateKey = privKey.PrivateKey[1:] + } + + // Some private keys remove all leading zeros, this is also invalid + // according to [SEC1] but since OpenSSL used to do this, we ignore + // this too. + copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey) + priv.X, priv.Y = curve.ScalarBaseMult(privateKey) + + return priv, nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go b/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go new file mode 100644 index 0000000000..366bd95910 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go @@ -0,0 +1,158 @@ +package x509 + +import ( + "encoding/asn1" + "github.com/zmap/zcrypto/x509/pkix" +) + +var ( + // oidBRTorServiceDescriptor is the assigned OID for the CAB Forum Tor Service + // Descriptor Hash extension (see EV Guidelines Appendix F) + oidBRTorServiceDescriptor = asn1.ObjectIdentifier{2, 23, 140, 1, 31} +) + +// TorServiceDescriptorHash is a structure corrsponding to the +// TorServiceDescriptorHash SEQUENCE described in Appendix F ("Issuance of +// Certificates for .onion Domain Names"). +// +// Each TorServiceDescriptorHash holds an onion URI (a utf8 string with the +// .onion address that was validated), a hash algorithm name (computed based on +// the pkix.AlgorithmIdentifier in the TorServiceDescriptorHash), the hash bytes +// (computed over the DER encoding of the ASN.1 SubjectPublicKey of the .onion +// service), and the number of bits in the hash bytes. +type TorServiceDescriptorHash struct { + Onion string `json:"onion"` + Algorithm pkix.AlgorithmIdentifier `json:"-"` + AlgorithmName string `json:"algorithm_name"` + Hash CertificateFingerprint `json:"hash"` + HashBits int `json:"hash_bits"` +} + +// parseTorServiceDescriptorSyntax parses the given pkix.Extension (assumed to +// have OID == oidBRTorServiceDescriptor) and returns a slice of parsed +// TorServiceDescriptorHash objects, or an error. An error will be returned if +// there are any structural errors related to the ASN.1 content (wrong tags, +// trailing data, missing fields, etc). +func parseTorServiceDescriptorSyntax(ext pkix.Extension) ([]*TorServiceDescriptorHash, error) { + // TorServiceDescriptorSyntax ::= + // SEQUENCE ( 1..MAX ) of TorServiceDescriptorHash + var seq asn1.RawValue + rest, err := asn1.Unmarshal(ext.Value, &seq) + if err != nil { + return nil, asn1.SyntaxError{ + Msg: "unable to unmarshal outer TorServiceDescriptor SEQUENCE", + } + } + if len(rest) != 0 { + return nil, asn1.SyntaxError{ + Msg: "trailing data after outer TorServiceDescriptor SEQUENCE", + } + } + if seq.Tag != asn1.TagSequence || seq.Class != asn1.ClassUniversal || !seq.IsCompound { + return nil, asn1.SyntaxError{ + Msg: "invalid outer TorServiceDescriptor SEQUENCE", + } + } + + var descriptors []*TorServiceDescriptorHash + rest = seq.Bytes + for len(rest) > 0 { + var descriptor *TorServiceDescriptorHash + descriptor, rest, err = parseTorServiceDescriptorHash(rest) + if err != nil { + return nil, err + } + descriptors = append(descriptors, descriptor) + } + return descriptors, nil +} + +// parseTorServiceDescriptorHash unmarshals a SEQUENCE from the provided data +// and parses a TorServiceDescriptorHash using the data contained in the +// sequence. The TorServiceDescriptorHash object and the remaining data are +// returned if no error occurs. +func parseTorServiceDescriptorHash(data []byte) (*TorServiceDescriptorHash, []byte, error) { + // TorServiceDescriptorHash:: = SEQUENCE { + // onionURI UTF8String + // algorithm AlgorithmIdentifier + // subjectPublicKeyHash BIT STRING + // } + var outerSeq asn1.RawValue + var err error + data, err = asn1.Unmarshal(data, &outerSeq) + if err != nil { + return nil, data, asn1.SyntaxError{ + Msg: "error unmarshaling TorServiceDescriptorHash SEQUENCE", + } + } + if outerSeq.Tag != asn1.TagSequence || + outerSeq.Class != asn1.ClassUniversal || + !outerSeq.IsCompound { + return nil, data, asn1.SyntaxError{ + Msg: "TorServiceDescriptorHash missing compound SEQUENCE tag", + } + } + fieldData := outerSeq.Bytes + + // Unmarshal and verify the structure of the onionURI UTF8String field. + var rawOnionURI asn1.RawValue + fieldData, err = asn1.Unmarshal(fieldData, &rawOnionURI) + if err != nil { + return nil, data, asn1.SyntaxError{ + Msg: "error unmarshaling TorServiceDescriptorHash onionURI", + } + } + if rawOnionURI.Tag != asn1.TagUTF8String || + rawOnionURI.Class != asn1.ClassUniversal || + rawOnionURI.IsCompound { + return nil, data, asn1.SyntaxError{ + Msg: "TorServiceDescriptorHash missing non-compound UTF8String tag", + } + } + + // Unmarshal and verify the structure of the algorithm UTF8String field. + var algorithm pkix.AlgorithmIdentifier + fieldData, err = asn1.Unmarshal(fieldData, &algorithm) + if err != nil { + return nil, nil, asn1.SyntaxError{ + Msg: "error unmarshaling TorServiceDescriptorHash algorithm", + } + } + + var algorithmName string + if algorithm.Algorithm.Equal(oidSHA256) { + algorithmName = "SHA256" + } else if algorithm.Algorithm.Equal(oidSHA384) { + algorithmName = "SHA384" + } else if algorithm.Algorithm.Equal(oidSHA512) { + algorithmName = "SHA512" + } else { + algorithmName = "Unknown" + } + + // Unmarshal and verify the structure of the Subject Public Key Hash BitString + // field. + var spkh asn1.BitString + fieldData, err = asn1.Unmarshal(fieldData, &spkh) + if err != nil { + return nil, data, asn1.SyntaxError{ + Msg: "error unmarshaling TorServiceDescriptorHash Hash", + } + } + + // There should be no trailing data after the TorServiceDescriptorHash + // SEQUENCE. + if len(fieldData) > 0 { + return nil, data, asn1.SyntaxError{ + Msg: "trailing data after TorServiceDescriptorHash", + } + } + + return &TorServiceDescriptorHash{ + Onion: string(rawOnionURI.Bytes), + Algorithm: algorithm, + AlgorithmName: algorithmName, + HashBits: spkh.BitLength, + Hash: CertificateFingerprint(spkh.Bytes), + }, data, nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/validation.go b/vendor/github.com/zmap/zcrypto/x509/validation.go new file mode 100644 index 0000000000..e582e54ff7 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/validation.go @@ -0,0 +1,60 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import "time" + +// Validation stores different validation levels for a given certificate +type Validation struct { + BrowserTrusted bool `json:"browser_trusted"` + BrowserError string `json:"browser_error,omitempty"` + MatchesDomain bool `json:"matches_domain,omitempty"` + Domain string `json:"-"` +} + +// ValidateWithStupidDetail fills out a Validation struct given a leaf +// certificate and intermediates / roots. If opts.DNSName is set, then it will +// also check if the domain matches. +// +// Deprecated: Use verifier.Verify() instead. +func (c *Certificate) ValidateWithStupidDetail(opts VerifyOptions) (chains []CertificateChain, validation *Validation, err error) { + + // Manually set the time, so that all verifies we do get the same time + if opts.CurrentTime.IsZero() { + opts.CurrentTime = time.Now() + } + + // XXX: Don't pass a KeyUsage to the Verify API + opts.KeyUsages = nil + domain := opts.DNSName + opts.DNSName = "" + + out := new(Validation) + out.Domain = domain + + if chains, _, _, err = c.Verify(opts); err != nil { + out.BrowserError = err.Error() + } else { + out.BrowserTrusted = true + } + + if domain != "" { + nameErr := c.VerifyHostname(domain) + if nameErr != nil { + out.MatchesDomain = false + } else { + out.MatchesDomain = true + } + + // Make sure we return an error if either chain building or hostname + // verification fails. + if err == nil && nameErr != nil { + err = nameErr + } + } + validation = out + + return +} diff --git a/vendor/github.com/zmap/zcrypto/x509/verify.go b/vendor/github.com/zmap/zcrypto/x509/verify.go new file mode 100644 index 0000000000..450f985c15 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/verify.go @@ -0,0 +1,635 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "errors" + "fmt" + "net" + "strings" + "time" + "unicode/utf8" +) + +type InvalidReason int + +const ( + // NotAuthorizedToSign results when a certificate is signed by another + // which isn't marked as a CA certificate. + NotAuthorizedToSign InvalidReason = iota + + // Expired results when a certificate has expired, based on the time + // given in the VerifyOptions. + Expired + + // CANotAuthorizedForThisName results when an intermediate or root + // certificate has a name constraint which doesn't include the name + // being checked. + CANotAuthorizedForThisName + + // CANotAuthorizedForThisEmail results when an intermediate or root + // certificate has a name constraint which doesn't include the email + // being checked. + CANotAuthorizedForThisEmail + + // CANotAuthorizedForThisIP results when an intermediate or root + // certificate has a name constraint which doesn't include the IP + // being checked. + CANotAuthorizedForThisIP + + // CANotAuthorizedForThisDirectory results when an intermediate or root + // certificate has a name constraint which doesn't include the directory + // being checked. + CANotAuthorizedForThisDirectory + + // TooManyIntermediates results when a path length constraint is + // violated. + TooManyIntermediates + + // IncompatibleUsage results when the certificate's key usage indicates + // that it may only be used for a different purpose. + IncompatibleUsage + + // NameMismatch results when the subject name of a parent certificate + // does not match the issuer name in the child. + NameMismatch + + // NeverValid results when the certificate could never have been valid due to + // some date-related issue, e.g. NotBefore > NotAfter. + NeverValid + + // IsSelfSigned results when the certificate is self-signed and not a trusted + // root. + IsSelfSigned +) + +// CertificateInvalidError results when an odd error occurs. Users of this +// library probably want to handle all these errors uniformly. +type CertificateInvalidError struct { + Cert *Certificate + Reason InvalidReason +} + +func (e CertificateInvalidError) Error() string { + switch e.Reason { + case NotAuthorizedToSign: + return "x509: certificate is not authorized to sign other certificates" + case Expired: + return "x509: certificate has expired or is not yet valid" + case CANotAuthorizedForThisName: + return "x509: a root or intermediate certificate is not authorized to sign in this domain" + case CANotAuthorizedForThisEmail: + return "x509: a root or intermediate certificate is not authorized to sign this email address" + case CANotAuthorizedForThisIP: + return "x509: a root or intermediate certificate is not authorized to sign this IP address" + case CANotAuthorizedForThisDirectory: + return "x509: a root or intermediate certificate is not authorized to sign in this directory" + case TooManyIntermediates: + return "x509: too many intermediates for path length constraint" + case IncompatibleUsage: + return "x509: certificate specifies an incompatible key usage" + case NameMismatch: + return "x509: issuer name does not match subject from issuing certificate" + case NeverValid: + return "x509: certificate will never be valid" + } + return "x509: unknown error" +} + +// HostnameError results when the set of authorized names doesn't match the +// requested name. +type HostnameError struct { + Certificate *Certificate + Host string +} + +func (h HostnameError) Error() string { + c := h.Certificate + + var valid string + if ip := net.ParseIP(h.Host); ip != nil { + // Trying to validate an IP + if len(c.IPAddresses) == 0 { + return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs" + } + for _, san := range c.IPAddresses { + if len(valid) > 0 { + valid += ", " + } + valid += san.String() + } + } else { + if c.hasSANExtension() { + valid = strings.Join(c.DNSNames, ", ") + } else { + valid = c.Subject.CommonName + } + } + + if len(valid) == 0 { + return "x509: certificate is not valid for any names, but wanted to match " + h.Host + } + return "x509: certificate is valid for " + valid + ", not " + h.Host +} + +// UnknownAuthorityError results when the certificate issuer is unknown +type UnknownAuthorityError struct { + Cert *Certificate + // hintErr contains an error that may be helpful in determining why an + // authority wasn't found. + hintErr error + // hintCert contains a possible authority certificate that was rejected + // because of the error in hintErr. + hintCert *Certificate +} + +func (e UnknownAuthorityError) Error() string { + s := "x509: certificate signed by unknown authority" + if e.hintErr != nil { + certName := e.hintCert.Subject.CommonName + if len(certName) == 0 { + if len(e.hintCert.Subject.Organization) > 0 { + certName = e.hintCert.Subject.Organization[0] + } else { + certName = "serial:" + e.hintCert.SerialNumber.String() + } + } + s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName) + } + return s +} + +// SystemRootsError results when we fail to load the system root certificates. +type SystemRootsError struct { + Err error +} + +func (se SystemRootsError) Error() string { + msg := "x509: failed to load system roots and no roots provided" + if se.Err != nil { + return msg + "; " + se.Err.Error() + } + return msg +} + +// errNotParsed is returned when a certificate without ASN.1 contents is +// verified. Platform-specific verification needs the ASN.1 contents. +var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate") + +const maxIntermediateCount = 10 + +// VerifyOptions contains parameters for Certificate.Verify. It's a structure +// because other PKIX verification APIs have ended up needing many options. +type VerifyOptions struct { + DNSName string + EmailAddress string + IPAddress net.IP + + Intermediates *CertPool + Roots *CertPool // if nil, the system roots are used + CurrentTime time.Time // if zero, the current time is used + // KeyUsage specifies which Extended Key Usage values are acceptable. + // An empty list means ExtKeyUsageServerAuth. Key usage is considered a + // constraint down the chain which mirrors Windows CryptoAPI behaviour, + // but not the spec. To accept any key usage, include ExtKeyUsageAny. + KeyUsages []ExtKeyUsage +} + +const ( + leafCertificate = iota + intermediateCertificate + rootCertificate +) + +func matchNameConstraint(domain, constraint string) bool { + // The meaning of zero length constraints is not specified, but this + // code follows NSS and accepts them as matching everything. + if len(constraint) == 0 { + return true + } + + if len(domain) < len(constraint) { + return false + } + + prefixLen := len(domain) - len(constraint) + if !strings.EqualFold(domain[prefixLen:], constraint) { + return false + } + + if prefixLen == 0 { + return true + } + + isSubdomain := domain[prefixLen-1] == '.' + constraintHasLeadingDot := constraint[0] == '.' + return isSubdomain != constraintHasLeadingDot +} + +// NOTE: the stdlib function does many more checks and is preferable. For backwards compatibility using this version + +// isValid performs validity checks on the c. It will never return a +// date-related error. +func (c *Certificate) isValid(certType CertificateType, currentChain CertificateChain) error { + + // KeyUsage status flags are ignored. From Engineering Security, Peter + // Gutmann: A European government CA marked its signing certificates as + // being valid for encryption only, but no-one noticed. Another + // European CA marked its signature keys as not being valid for + // signatures. A different CA marked its own trusted root certificate + // as being invalid for certificate signing. Another national CA + // distributed a certificate to be used to encrypt data for the + // country’s tax authority that was marked as only being usable for + // digital signatures but not for encryption. Yet another CA reversed + // the order of the bit flags in the keyUsage due to confusion over + // encoding endianness, essentially setting a random keyUsage in + // certificates that it issued. Another CA created a self-invalidating + // certificate by adding a certificate policy statement stipulating + // that the certificate had to be used strictly as specified in the + // keyUsage, and a keyUsage containing a flag indicating that the RSA + // encryption key could only be used for Diffie-Hellman key agreement. + + if certType == CertificateTypeIntermediate && (!c.BasicConstraintsValid || !c.IsCA) { + return CertificateInvalidError{c, NotAuthorizedToSign} + } + + if c.BasicConstraintsValid && c.MaxPathLen >= 0 { + numIntermediates := len(currentChain) - 1 + if numIntermediates > c.MaxPathLen { + return CertificateInvalidError{c, TooManyIntermediates} + } + } + + if len(currentChain) > maxIntermediateCount { + return CertificateInvalidError{c, TooManyIntermediates} + } + + return nil +} + +// Verify attempts to verify c by building one or more chains from c to a +// certificate in opts.Roots, using certificates in opts.Intermediates if +// needed. If successful, it returns one or more chains where the first +// element of the chain is c and the last element is from opts.Roots. +// +// If opts.Roots is nil and system roots are unavailable the returned error +// will be of type SystemRootsError. +// +// WARNING: this doesn't do any revocation checking. +func (c *Certificate) Verify(opts VerifyOptions) (current, expired, never []CertificateChain, err error) { + + if opts.Roots == nil { + err = SystemRootsError{} + return + } + + err = c.isValid(CertificateTypeLeaf, nil) + if err != nil { + return + } + + candidateChains, err := c.buildChains(make(map[int][]CertificateChain), []*Certificate{c}, &opts) + if err != nil { + return + } + + keyUsages := opts.KeyUsages + if len(keyUsages) == 0 { + keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} + } + + // If any key usage is acceptable then we're done. + hasKeyUsageAny := false + for _, usage := range keyUsages { + if usage == ExtKeyUsageAny { + hasKeyUsageAny = true + break + } + } + + var chains []CertificateChain + if hasKeyUsageAny { + chains = candidateChains + } else { + for _, candidate := range candidateChains { + if checkChainForKeyUsage(candidate, keyUsages) { + chains = append(chains, candidate) + } + } + } + + if len(chains) == 0 { + err = CertificateInvalidError{c, IncompatibleUsage} + return + } + + current, expired, never = FilterByDate(chains, opts.CurrentTime) + if len(current) == 0 { + if len(expired) > 0 { + err = CertificateInvalidError{c, Expired} + } else if len(never) > 0 { + err = CertificateInvalidError{c, NeverValid} + } + return + } + + if len(opts.DNSName) > 0 { + err = c.VerifyHostname(opts.DNSName) + if err != nil { + return + } + } + return +} + +func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { + n := make([]*Certificate, len(chain)+1) + copy(n, chain) + n[len(chain)] = cert + return n +} + +// buildChains returns all chains of length < maxIntermediateCount. Chains begin +// the certificate being validated (chain[0] = c), and end at a root. It +// enforces that all intermediates can sign certificates, and checks signatures. +// It does not enforce expiration. +func (c *Certificate) buildChains(cache map[int][]CertificateChain, currentChain CertificateChain, opts *VerifyOptions) (chains []CertificateChain, err error) { + + // If the certificate being validated is a root, add the chain of length one + // containing just the root. Only do this on the first call to buildChains, + // when the len(currentChain) = 1. + if len(currentChain) == 1 && opts.Roots.Contains(c) { + chains = append(chains, CertificateChain{c}) + } + + if len(chains) == 0 && c.SelfSigned { + err = CertificateInvalidError{c, IsSelfSigned} + } + + // Find roots that signed c and have matching SKID/AKID and Subject/Issuer. + possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c) + + // If any roots are parents of c, create new chain for each one of them. + for _, rootNum := range possibleRoots { + root := opts.Roots.certs[rootNum] + err = root.isValid(CertificateTypeRoot, currentChain) + if err != nil { + continue + } + if !currentChain.CertificateInChain(root) { + chains = append(chains, currentChain.AppendToFreshChain(root)) + } + } + + // The root chains of length N+1 are now "done". Now we'll look for any + // intermediates that issue this certificate, meaning that any chain to a root + // through these intermediates is at least length N+2. + possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c) + + for _, intermediateNum := range possibleIntermediates { + intermediate := opts.Intermediates.certs[intermediateNum] + if opts.Roots.Contains(intermediate) { + continue + } + if currentChain.CertificateSubjectAndKeyInChain(intermediate) { + continue + } + err = intermediate.isValid(CertificateTypeIntermediate, currentChain) + if err != nil { + continue + } + + // We don't want to add any certificate to chains that doesn't somehow get + // to a root. We don't know if all chains through the intermediates will end + // at a root, so we slice off the back half of the chain and try to build + // that part separately. + childChains, ok := cache[intermediateNum] + if !ok { + childChains, err = intermediate.buildChains(cache, currentChain.AppendToFreshChain(intermediate), opts) + cache[intermediateNum] = childChains + } + chains = append(chains, childChains...) + } + + if len(chains) > 0 { + err = nil + } + + if len(chains) == 0 && err == nil { + hintErr := rootErr + hintCert := failedRoot + if hintErr == nil { + hintErr = intermediateErr + hintCert = failedIntermediate + } + err = UnknownAuthorityError{c, hintErr, hintCert} + } + + return +} + +func matchHostnames(pattern, host string) bool { + host = strings.TrimSuffix(host, ".") + pattern = strings.TrimSuffix(pattern, ".") + + if len(pattern) == 0 || len(host) == 0 { + return false + } + + patternParts := strings.Split(pattern, ".") + hostParts := strings.Split(host, ".") + + if len(patternParts) != len(hostParts) { + return false + } + + for i, patternPart := range patternParts { + if /*i == 0 &&*/ patternPart == "*" { + continue + } + if patternPart != hostParts[i] { + return false + } + } + + return true +} + +// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use +// an explicitly ASCII function to avoid any sharp corners resulting from +// performing Unicode operations on DNS labels. +func toLowerCaseASCII(in string) string { + // If the string is already lower-case then there's nothing to do. + isAlreadyLowerCase := true + for _, c := range in { + if c == utf8.RuneError { + // If we get a UTF-8 error then there might be + // upper-case ASCII bytes in the invalid sequence. + isAlreadyLowerCase = false + break + } + if 'A' <= c && c <= 'Z' { + isAlreadyLowerCase = false + break + } + } + + if isAlreadyLowerCase { + return in + } + + out := []byte(in) + for i, c := range out { + if 'A' <= c && c <= 'Z' { + out[i] += 'a' - 'A' + } + } + return string(out) +} + +// VerifyHostname returns nil if c is a valid certificate for the named host. +// Otherwise it returns an error describing the mismatch. +func (c *Certificate) VerifyHostname(h string) error { + // IP addresses may be written in [ ]. + candidateIP := h + if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { + candidateIP = h[1 : len(h)-1] + } + if ip := net.ParseIP(candidateIP); ip != nil { + // We only match IP addresses against IP SANs. + // https://tools.ietf.org/html/rfc6125#appendix-B.2 + for _, candidate := range c.IPAddresses { + if ip.Equal(candidate) { + return nil + } + } + return HostnameError{c, candidateIP} + } + + lowered := toLowerCaseASCII(h) + + if c.hasSANExtension() { + for _, match := range c.DNSNames { + if matchHostnames(toLowerCaseASCII(match), lowered) { + return nil + } + } + // If Subject Alt Name is given, we ignore the common name. + } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { + return nil + } + + return HostnameError{c, h} +} + +func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { + usages := make([]ExtKeyUsage, len(keyUsages)) + copy(usages, keyUsages) + + if len(chain) == 0 { + return false + } + + usagesRemaining := len(usages) + + // We walk down the list and cross out any usages that aren't supported + // by each certificate. If we cross out all the usages, then the chain + // is unacceptable. + +NextCert: + for i := len(chain) - 1; i >= 0; i-- { + cert := chain[i] + if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { + // The certificate doesn't have any extended key usage specified. + continue + } + + for _, usage := range cert.ExtKeyUsage { + if usage == ExtKeyUsageAny { + // The certificate is explicitly good for any usage. + continue NextCert + } + } + + const invalidUsage ExtKeyUsage = -1 + + NextRequestedUsage: + for i, requestedUsage := range usages { + if requestedUsage == invalidUsage { + continue + } + + for _, usage := range cert.ExtKeyUsage { + if requestedUsage == usage { + continue NextRequestedUsage + } else if requestedUsage == ExtKeyUsageServerAuth && + (usage == ExtKeyUsageNetscapeServerGatedCrypto || + usage == ExtKeyUsageMicrosoftServerGatedCrypto) { + // In order to support COMODO + // certificate chains, we have to + // accept Netscape or Microsoft SGC + // usages as equal to ServerAuth. + continue NextRequestedUsage + } + } + + usages[i] = invalidUsage + usagesRemaining-- + if usagesRemaining == 0 { + return false + } + } + } + + return true +} + +// earlier returns the earlier of a and b +func earlier(a, b time.Time) time.Time { + if a.Before(b) { + return a + } + return b +} + +// later returns the later of a and b +func later(a, b time.Time) time.Time { + if a.After(b) { + return a + } + return b +} + +// check expirations divides chains into a set of disjoint chains, containing +// current chains valid now, expired chains that were valid at some point, and +// the set of chains that were never valid. +func FilterByDate(chains []CertificateChain, now time.Time) (current, expired, never []CertificateChain) { + for _, chain := range chains { + if len(chain) == 0 { + continue + } + leaf := chain[0] + lowerBound := leaf.NotBefore + upperBound := leaf.NotAfter + for _, c := range chain[1:] { + lowerBound = later(lowerBound, c.NotBefore) + upperBound = earlier(upperBound, c.NotAfter) + } + valid := lowerBound.Before(now) && upperBound.After(now) + wasValid := lowerBound.Before(upperBound) + if valid && !wasValid { + // Math/logic tells us this is impossible. + panic("valid && !wasValid should not be possible") + } + if valid { + current = append(current, chain) + } else if wasValid { + expired = append(expired, chain) + } else { + never = append(never, chain) + } + } + return +} diff --git a/vendor/github.com/zmap/zcrypto/x509/x509.go b/vendor/github.com/zmap/zcrypto/x509/x509.go new file mode 100644 index 0000000000..160fca3df3 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/x509/x509.go @@ -0,0 +1,3042 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package x509 parses X.509-encoded keys and certificates. +// +// Originally based on the go/crypto/x509 standard library, +// this package has now diverged enough that it is no longer +// updated with direct correspondence to new go releases. + +package x509 + +import ( + // all of the hash libraries need to be imported for side-effects, + // so that crypto.RegisterHash is called + _ "crypto/md5" + "crypto/sha256" + _ "crypto/sha512" + "io" + "strings" + + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/asn1" + "encoding/pem" + "errors" + "fmt" + "math/big" + "net" + "strconv" + "time" + + "github.com/zmap/zcrypto/dsa" + + "github.com/weppos/publicsuffix-go/publicsuffix" + "github.com/zmap/zcrypto/x509/ct" + "github.com/zmap/zcrypto/x509/pkix" + "golang.org/x/crypto/ed25519" +) + +// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo +// in RFC 3280. +type pkixPublicKey struct { + Algo pkix.AlgorithmIdentifier + BitString asn1.BitString +} + +// ParsePKIXPublicKey parses a DER encoded public key. These values are +// typically found in PEM blocks with "BEGIN PUBLIC KEY". +// +// Supported key types include RSA, DSA, and ECDSA. Unknown key +// types result in an error. +// +// On success, pub will be of type *rsa.PublicKey, *dsa.PublicKey, +// or *ecdsa.PublicKey. +func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) { + var pki publicKeyInfo + if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after ASN.1 of public-key") + } + algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm) + if algo == UnknownPublicKeyAlgorithm { + return nil, errors.New("x509: unknown public key algorithm") + } + return parsePublicKey(algo, &pki) +} + +func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) { + switch pub := pub.(type) { + case *rsa.PublicKey: + publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{ + N: pub.N, + E: pub.E, + }) + if err != nil { + return nil, pkix.AlgorithmIdentifier{}, err + } + publicKeyAlgorithm.Algorithm = oidPublicKeyRSA + // This is a NULL parameters value which is required by + // https://tools.ietf.org/html/rfc3279#section-2.3.1. + publicKeyAlgorithm.Parameters = asn1.NullRawValue + case *ecdsa.PublicKey: + publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) + oid, ok := oidFromNamedCurve(pub.Curve) + if !ok { + return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve") + } + publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA + var paramBytes []byte + paramBytes, err = asn1.Marshal(oid) + if err != nil { + return + } + publicKeyAlgorithm.Parameters.FullBytes = paramBytes + case *AugmentedECDSA: + return marshalPublicKey(pub.Pub) + case ed25519.PublicKey: + publicKeyAlgorithm.Algorithm = oidKeyEd25519 + return []byte(pub), publicKeyAlgorithm, nil + case X25519PublicKey: + publicKeyAlgorithm.Algorithm = oidKeyX25519 + return []byte(pub), publicKeyAlgorithm, nil + default: + return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: only RSA, ECDSA, ed25519, or X25519 public keys supported") + } + + return publicKeyBytes, publicKeyAlgorithm, nil +} + +// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format. +func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) { + var publicKeyBytes []byte + var publicKeyAlgorithm pkix.AlgorithmIdentifier + var err error + + if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil { + return nil, err + } + + pkix := pkixPublicKey{ + Algo: publicKeyAlgorithm, + BitString: asn1.BitString{ + Bytes: publicKeyBytes, + BitLength: 8 * len(publicKeyBytes), + }, + } + + ret, _ := asn1.Marshal(pkix) + return ret, nil +} + +// These structures reflect the ASN.1 structure of X.509 certificates.: + +type certificate struct { + Raw asn1.RawContent + TBSCertificate tbsCertificate + SignatureAlgorithm pkix.AlgorithmIdentifier + SignatureValue asn1.BitString +} + +type tbsCertificate struct { + Raw asn1.RawContent + Version int `asn1:"optional,explicit,default:0,tag:0"` + SerialNumber *big.Int + SignatureAlgorithm pkix.AlgorithmIdentifier + Issuer asn1.RawValue + Validity validity + Subject asn1.RawValue + PublicKey publicKeyInfo + UniqueId asn1.BitString `asn1:"optional,tag:1"` + SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"` + Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"` +} + +type dsaAlgorithmParameters struct { + P, Q, G *big.Int +} + +type dsaSignature struct { + R, S *big.Int +} + +type ecdsaSignature dsaSignature + +type AugmentedECDSA struct { + Pub *ecdsa.PublicKey + Raw asn1.BitString +} + +type validity struct { + NotBefore, NotAfter time.Time +} + +type publicKeyInfo struct { + Raw asn1.RawContent + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString +} + +// RFC 5280, 4.2.1.1 +type authKeyId struct { + Id []byte `asn1:"optional,tag:0"` +} + +type SignatureAlgorithmOID asn1.ObjectIdentifier + +type SignatureAlgorithm int + +const ( + UnknownSignatureAlgorithm SignatureAlgorithm = iota + MD2WithRSA + MD5WithRSA + SHA1WithRSA + SHA256WithRSA + SHA384WithRSA + SHA512WithRSA + DSAWithSHA1 + DSAWithSHA256 + ECDSAWithSHA1 + ECDSAWithSHA256 + ECDSAWithSHA384 + ECDSAWithSHA512 + SHA256WithRSAPSS + SHA384WithRSAPSS + SHA512WithRSAPSS + Ed25519Sig +) + +func (algo SignatureAlgorithm) isRSAPSS() bool { + switch algo { + case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS: + return true + default: + return false + } +} + +var algoName = [...]string{ + MD2WithRSA: "MD2-RSA", + MD5WithRSA: "MD5-RSA", + SHA1WithRSA: "SHA1-RSA", + SHA256WithRSA: "SHA256-RSA", + SHA384WithRSA: "SHA384-RSA", + SHA512WithRSA: "SHA512-RSA", + SHA256WithRSAPSS: "SHA256-RSAPSS", + SHA384WithRSAPSS: "SHA384-RSAPSS", + SHA512WithRSAPSS: "SHA512-RSAPSS", + DSAWithSHA1: "DSA-SHA1", + DSAWithSHA256: "DSA-SHA256", + ECDSAWithSHA1: "ECDSA-SHA1", + ECDSAWithSHA256: "ECDSA-SHA256", + ECDSAWithSHA384: "ECDSA-SHA384", + ECDSAWithSHA512: "ECDSA-SHA512", + Ed25519Sig: "Ed25519", +} + +func (algo SignatureAlgorithm) String() string { + if 0 < algo && int(algo) < len(algoName) { + return algoName[algo] + } + return strconv.Itoa(int(algo)) +} + +var keyAlgorithmNames = []string{ + "unknown_algorithm", + "RSA", + "DSA", + "ECDSA", + "Ed25519", + "X25519", +} + +type PublicKeyAlgorithm int + +const ( + UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota + RSA + DSA + ECDSA + Ed25519 + X25519 + total_key_algorithms +) + +// curve25519 package does not expose key types +type X25519PublicKey []byte + +// OIDs for signature algorithms +// +// pkcs-1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } +// +// +// RFC 3279 2.2.1 RSA Signature Algorithms +// +// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } +// +// md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } +// +// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } +// +// dsaWithSha1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 } +// +// RFC 3279 2.2.3 ECDSA Signature Algorithm +// +// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) ansi-x962(10045) +// signatures(4) ecdsa-with-SHA1(1)} +// +// +// RFC 4055 5 PKCS #1 Version 1.5 +// +// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } +// +// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } +// +// sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } +// +// +// RFC 5758 3.1 DSA Signature Algorithms +// +// dsaWithSha256 OBJECT IDENTIFIER ::= { +// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101) +// csor(3) algorithms(4) id-dsa-with-sha2(3) 2} +// +// RFC 5758 3.2 ECDSA Signature Algorithm +// +// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } +// +// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 } +// +// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 } + +var ( + oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} + oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} + oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} + oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} + oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} + oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} + oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} + oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} + oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} + oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} + oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} + oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} + oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} + + oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} + oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} + oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} + + oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8} + + // oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA + // but it's specified by ISO. Microsoft's makecert.exe has been known + // to produce certificates with this OID. + oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29} +) + +// cryptoNoDigest means that the signature algorithm does not require a hash +// digest. The distinction between cryptoNoDigest and crypto.Hash(0) +// is purely superficial. crypto.Hash(0) is used in place of a null value +// when hashing is not supported for the given algorithm (as in the case of +// MD2WithRSA below). +var cryptoNoDigest = crypto.Hash(0) + +var signatureAlgorithmDetails = []struct { + algo SignatureAlgorithm + oid asn1.ObjectIdentifier + pubKeyAlgo PublicKeyAlgorithm + hash crypto.Hash +}{ + {MD2WithRSA, oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */}, + {MD5WithRSA, oidSignatureMD5WithRSA, RSA, crypto.MD5}, + {SHA1WithRSA, oidSignatureSHA1WithRSA, RSA, crypto.SHA1}, + {SHA1WithRSA, oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1}, + {SHA256WithRSA, oidSignatureSHA256WithRSA, RSA, crypto.SHA256}, + {SHA384WithRSA, oidSignatureSHA384WithRSA, RSA, crypto.SHA384}, + {SHA512WithRSA, oidSignatureSHA512WithRSA, RSA, crypto.SHA512}, + {SHA256WithRSAPSS, oidSignatureRSAPSS, RSA, crypto.SHA256}, + {SHA384WithRSAPSS, oidSignatureRSAPSS, RSA, crypto.SHA384}, + {SHA512WithRSAPSS, oidSignatureRSAPSS, RSA, crypto.SHA512}, + {DSAWithSHA1, oidSignatureDSAWithSHA1, DSA, crypto.SHA1}, + {DSAWithSHA256, oidSignatureDSAWithSHA256, DSA, crypto.SHA256}, + {ECDSAWithSHA1, oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1}, + {ECDSAWithSHA256, oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256}, + {ECDSAWithSHA384, oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384}, + {ECDSAWithSHA512, oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512}, + {Ed25519Sig, oidKeyEd25519, Ed25519, cryptoNoDigest}, +} + +// pssParameters reflects the parameters in an AlgorithmIdentifier that +// specifies RSA PSS. See https://tools.ietf.org/html/rfc3447#appendix-A.2.3 +type pssParameters struct { + // The following three fields are not marked as + // optional because the default values specify SHA-1, + // which is no longer suitable for use in signatures. + Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"` + MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"` + SaltLength int `asn1:"explicit,tag:2"` + TrailerField int `asn1:"optional,explicit,tag:3,default:1"` +} + +// rsaPSSParameters returns an asn1.RawValue suitable for use as the Parameters +// in an AlgorithmIdentifier that specifies RSA PSS. +func rsaPSSParameters(hashFunc crypto.Hash) asn1.RawValue { + var hashOID asn1.ObjectIdentifier + + switch hashFunc { + case crypto.SHA256: + hashOID = oidSHA256 + case crypto.SHA384: + hashOID = oidSHA384 + case crypto.SHA512: + hashOID = oidSHA512 + } + + params := pssParameters{ + Hash: pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.NullRawValue, + }, + MGF: pkix.AlgorithmIdentifier{ + Algorithm: oidMGF1, + }, + SaltLength: hashFunc.Size(), + TrailerField: 1, + } + + mgf1Params := pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.NullRawValue, + } + + var err error + params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params) + if err != nil { + panic(err) + } + + serialized, err := asn1.Marshal(params) + if err != nil { + panic(err) + } + + return asn1.RawValue{FullBytes: serialized} +} + +// GetSignatureAlgorithmFromAI converts asn1 AlgorithmIdentifier to SignatureAlgorithm int +func GetSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm { + if !ai.Algorithm.Equal(oidSignatureRSAPSS) { + for _, details := range signatureAlgorithmDetails { + if ai.Algorithm.Equal(details.oid) { + return details.algo + } + } + return UnknownSignatureAlgorithm + } + + // RSA PSS is special because it encodes important parameters + // in the Parameters. + + var params pssParameters + if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, ¶ms); err != nil { + return UnknownSignatureAlgorithm + } + + var mgf1HashFunc pkix.AlgorithmIdentifier + if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil { + return UnknownSignatureAlgorithm + } + + // PSS is greatly overburdened with options. This code forces + // them into three buckets by requiring that the MGF1 hash + // function always match the message hash function (as + // recommended in + // https://tools.ietf.org/html/rfc3447#section-8.1), that the + // salt length matches the hash length, and that the trailer + // field has the default value. + if !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes) || + !params.MGF.Algorithm.Equal(oidMGF1) || + !mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) || + !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes) || + params.TrailerField != 1 { + return UnknownSignatureAlgorithm + } + + switch { + case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32: + return SHA256WithRSAPSS + case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48: + return SHA384WithRSAPSS + case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64: + return SHA512WithRSAPSS + } + + return UnknownSignatureAlgorithm +} + +// RFC 3279, 2.3 Public Key Algorithms +// +// pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840) +// rsadsi(113549) pkcs(1) 1 } +// +// rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 } +// +// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840) +// x9-57(10040) x9cm(4) 1 } +// +// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters +// +// id-ecPublicKey OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } +var ( + oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} + oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1} + oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} +) + +func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm { + switch { + case oid.Equal(oidPublicKeyRSA): + return RSA + case oid.Equal(oidPublicKeyDSA): + return DSA + case oid.Equal(oidPublicKeyECDSA): + return ECDSA + case oid.Equal(oidKeyEd25519): + return Ed25519 + case oid.Equal(oidKeyX25519): + return X25519 + } + return UnknownPublicKeyAlgorithm +} + +// RFC 5480, 2.1.1.1. Named Curve +// +// secp224r1 OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) certicom(132) curve(0) 33 } +// +// secp256r1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) +// prime(1) 7 } +// +// secp384r1 OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) certicom(132) curve(0) 34 } +// +// secp521r1 OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) certicom(132) curve(0) 35 } +// +// NB: secp256r1 is equivalent to prime256v1 +var ( + oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} + oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} + oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} + oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} +) + +// https://datatracker.ietf.org/doc/draft-ietf-curdle-pkix/?include_text=1 +// id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } +// id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } +var ( + oidKeyX25519 = asn1.ObjectIdentifier{1, 3, 101, 110} + oidKeyEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} +) + +func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { + switch { + case oid.Equal(oidNamedCurveP224): + return elliptic.P224() + case oid.Equal(oidNamedCurveP256): + return elliptic.P256() + case oid.Equal(oidNamedCurveP384): + return elliptic.P384() + case oid.Equal(oidNamedCurveP521): + return elliptic.P521() + } + return nil +} + +func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { + switch curve { + case elliptic.P224(): + return oidNamedCurveP224, true + case elliptic.P256(): + return oidNamedCurveP256, true + case elliptic.P384(): + return oidNamedCurveP384, true + case elliptic.P521(): + return oidNamedCurveP521, true + } + + return nil, false +} + +// KeyUsage represents the set of actions that are valid for a given key. It's +// a bitmap of the KeyUsage* constants. +type KeyUsage int + +const ( + KeyUsageDigitalSignature KeyUsage = 1 << iota + KeyUsageContentCommitment + KeyUsageKeyEncipherment + KeyUsageDataEncipherment + KeyUsageKeyAgreement + KeyUsageCertSign + KeyUsageCRLSign + KeyUsageEncipherOnly + KeyUsageDecipherOnly +) + +// RFC 5280, 4.2.1.12 Extended Key Usage +// +// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } +// +// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } +// +// id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } +// id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } +// id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } +// id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } +// id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } +// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } +//var ( +// oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0} +// oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} +// oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} +// oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3} +// oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4} +// oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5} +// oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6} +// oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7} +// oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} +// oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9} +// oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3} +// oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1} +//) + +// ExtKeyUsage represents an extended set of actions that are valid for a given key. +// Each of the ExtKeyUsage* constants define a unique action. +type ExtKeyUsage int + +// TODO: slight differences in case in some names. Should be easy to align with stdlib. +// leaving for now to not break compatibility + +// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID. +var extKeyUsageOIDs = []struct { + extKeyUsage ExtKeyUsage + oid asn1.ObjectIdentifier +}{ + {ExtKeyUsageAny, oidExtKeyUsageAny}, + {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth}, + {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth}, + {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning}, + {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection}, + //{ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem}, + {ExtKeyUsageIpsecUser, oidExtKeyUsageIpsecEndSystem}, + //{ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel}, + {ExtKeyUsageIpsecTunnel, oidExtKeyUsageIpsecTunnel}, + //{ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser}, + {ExtKeyUsageIpsecUser, oidExtKeyUsageIpsecUser}, + {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping}, + //{ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning}, + {ExtKeyUsageOcspSigning, oidExtKeyUsageOcspSigning}, + {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto}, + {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto}, +} + +// TODO: slight differences in case in some names. Should be easy to align with stdlib. +// leaving for now to not break compatibility + +// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID. +var nativeExtKeyUsageOIDs = []struct { + extKeyUsage ExtKeyUsage + oid asn1.ObjectIdentifier +}{ + {ExtKeyUsageAny, oidExtKeyUsageAny}, + {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth}, + {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth}, + {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning}, + {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection}, + {ExtKeyUsageIpsecEndSystem, oidExtKeyUsageIpsecEndSystem}, + {ExtKeyUsageIpsecTunnel, oidExtKeyUsageIpsecTunnel}, + {ExtKeyUsageIpsecUser, oidExtKeyUsageIpsecUser}, + {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping}, + {ExtKeyUsageOcspSigning, oidExtKeyUsageOcspSigning}, + {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto}, + {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto}, +} + +func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) { + s := oid.String() + eku, ok = ekuConstants[s] + return +} + +func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) { + for _, pair := range nativeExtKeyUsageOIDs { + if eku == pair.extKeyUsage { + return pair.oid, true + } + } + return +} + +// A Certificate represents an X.509 certificate. +type Certificate struct { + Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature). + RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content. + RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. + RawSubject []byte // DER encoded Subject + RawIssuer []byte // DER encoded Issuer + + Signature []byte + SignatureAlgorithm SignatureAlgorithm + + SelfSigned bool + + SignatureAlgorithmOID asn1.ObjectIdentifier + + PublicKeyAlgorithm PublicKeyAlgorithm + PublicKey interface{} + + PublicKeyAlgorithmOID asn1.ObjectIdentifier + + Version int + SerialNumber *big.Int + Issuer pkix.Name + Subject pkix.Name + NotBefore, NotAfter time.Time // Validity bounds. + ValidityPeriod int + KeyUsage KeyUsage + + IssuerUniqueId asn1.BitString + SubjectUniqueId asn1.BitString + + // Extensions contains raw X.509 extensions. When parsing certificates, + // this can be used to extract non-critical extensions that are not + // parsed by this package. When marshaling certificates, the Extensions + // field is ignored, see ExtraExtensions. + Extensions []pkix.Extension + + // ExtensionsMap contains raw x.509 extensions keyed by OID (in string + // representation). It allows fast membership testing of specific OIDs. Like + // the Extensions field this field is ignored when marshaling certificates. If + // multiple extensions with the same OID are present only the last + // pkix.Extension will be in this map. Consult the `Extensions` slice when it + // is required to process all extensions including duplicates. + ExtensionsMap map[string]pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any + // marshaled certificates. Values override any extensions that would + // otherwise be produced based on the other fields. The ExtraExtensions + // field is not populated when parsing certificates, see Extensions. + ExtraExtensions []pkix.Extension + + // UnhandledCriticalExtensions contains a list of extension IDs that + // were not (fully) processed when parsing. Verify will fail if this + // slice is non-empty, unless verification is delegated to an OS + // library which understands all the critical extensions. + // + // Users can access these extensions using Extensions and can remove + // elements from this slice if they believe that they have been + // handled. + UnhandledCriticalExtensions []asn1.ObjectIdentifier + + ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages. + UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package. + + BasicConstraintsValid bool // if true then the next two fields are valid. + IsCA bool + + // MaxPathLen and MaxPathLenZero indicate the presence and + // value of the BasicConstraints' "pathLenConstraint". + // + // When parsing a certificate, a positive non-zero MaxPathLen + // means that the field was specified, -1 means it was unset, + // and MaxPathLenZero being true mean that the field was + // explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false + // should be treated equivalent to -1 (unset). + // + // When generating a certificate, an unset pathLenConstraint + // can be requested with either MaxPathLen == -1 or using the + // zero value for both MaxPathLen and MaxPathLenZero. + MaxPathLen int + // MaxPathLenZero indicates that BasicConstraintsValid==true and + // MaxPathLen==0 should be interpreted as an actual Max path length + // of zero. Otherwise, that combination is interpreted as MaxPathLen + // not being set. + MaxPathLenZero bool + + SubjectKeyId []byte + AuthorityKeyId []byte + + // RFC 5280, 4.2.2.1 (Authority Information Access) + OCSPServer []string + IssuingCertificateURL []string + + // Subject Alternate Name values + OtherNames []pkix.OtherName + DNSNames []string + EmailAddresses []string + DirectoryNames []pkix.Name + EDIPartyNames []pkix.EDIPartyName + URIs []string + IPAddresses []net.IP + RegisteredIDs []asn1.ObjectIdentifier + + // Issuer Alternative Name values + IANOtherNames []pkix.OtherName + IANDNSNames []string + IANEmailAddresses []string + IANDirectoryNames []pkix.Name + IANEDIPartyNames []pkix.EDIPartyName + IANURIs []string + IANIPAddresses []net.IP + IANRegisteredIDs []asn1.ObjectIdentifier + + // Certificate Policies values + QualifierId [][]asn1.ObjectIdentifier + CPSuri [][]string + ExplicitTexts [][]asn1.RawValue + NoticeRefOrgnization [][]asn1.RawValue + NoticeRefNumbers [][]NoticeNumber + + ParsedExplicitTexts [][]string + ParsedNoticeRefOrganization [][]string + + // Name constraints + NameConstraintsCritical bool // if true then the name constraints are marked critical. + PermittedDNSNames []GeneralSubtreeString + ExcludedDNSNames []GeneralSubtreeString + PermittedEmailAddresses []GeneralSubtreeString + ExcludedEmailAddresses []GeneralSubtreeString + PermittedURIs []GeneralSubtreeString + ExcludedURIs []GeneralSubtreeString + PermittedIPAddresses []GeneralSubtreeIP + ExcludedIPAddresses []GeneralSubtreeIP + PermittedDirectoryNames []GeneralSubtreeName + ExcludedDirectoryNames []GeneralSubtreeName + PermittedEdiPartyNames []GeneralSubtreeEdi + ExcludedEdiPartyNames []GeneralSubtreeEdi + PermittedRegisteredIDs []GeneralSubtreeOid + ExcludedRegisteredIDs []GeneralSubtreeOid + PermittedX400Addresses []GeneralSubtreeRaw + ExcludedX400Addresses []GeneralSubtreeRaw + + // CRL Distribution Points + CRLDistributionPoints []string + + PolicyIdentifiers []asn1.ObjectIdentifier + ValidationLevel CertValidationLevel + + // Fingerprints + FingerprintMD5 CertificateFingerprint + FingerprintSHA1 CertificateFingerprint + FingerprintSHA256 CertificateFingerprint + FingerprintNoCT CertificateFingerprint + + // SPKI + SPKIFingerprint CertificateFingerprint + SPKISubjectFingerprint CertificateFingerprint + TBSCertificateFingerprint CertificateFingerprint + + IsPrecert bool + + // Internal + validSignature bool + + // CT + SignedCertificateTimestampList []*ct.SignedCertificateTimestamp + + // QWACS + CABFOrganizationIdentifier *CABFOrganizationIdentifier + QCStatements *QCStatements + + // Used to speed up the zlint checks. Populated by the GetParsedDNSNames method. + parsedDNSNames []ParsedDomainName + // Used to speed up the zlint checks. Populated by the GetParsedCommonName method + parsedCommonName *ParsedDomainName + + // CAB Forum Tor Service Descriptor Hash Extensions (see EV Guidelines + // Appendix F) + TorServiceDescriptors []*TorServiceDescriptorHash +} + +// ParsedDomainName is a structure holding a parsed domain name (CommonName or +// DNS SAN) and a parsing error. +type ParsedDomainName struct { + DomainString string + ParsedDomain *publicsuffix.DomainName + ParseError error +} + +// GetParsedDNSNames returns a list of parsed SAN DNS names. It is used to cache the parsing result and +// speed up zlint linters. If invalidateCache is true, then the cache is repopulated with current list of string from +// Certificate.DNSNames. This parameter should always be false, unless the Certificate.DNSNames have been modified +// after calling GetParsedDNSNames the previous time. +func (c *Certificate) GetParsedDNSNames(invalidateCache bool) []ParsedDomainName { + if c.parsedDNSNames != nil && !invalidateCache { + return c.parsedDNSNames + } + c.parsedDNSNames = make([]ParsedDomainName, len(c.DNSNames)) + + for i := range c.DNSNames { + var parsedDomain, parseError = publicsuffix.ParseFromListWithOptions(publicsuffix.DefaultList, + c.DNSNames[i], + &publicsuffix.FindOptions{IgnorePrivate: true, DefaultRule: publicsuffix.DefaultRule}) + + c.parsedDNSNames[i].DomainString = c.DNSNames[i] + c.parsedDNSNames[i].ParsedDomain = parsedDomain + c.parsedDNSNames[i].ParseError = parseError + } + + return c.parsedDNSNames +} + +// GetParsedCommonName returns parsed subject CommonName. It is used to cache the parsing result and +// speed up zlint linters. If invalidateCache is true, then the cache is repopulated with current subject CommonName. +// This parameter should always be false, unless the Certificate.Subject.CommonName have been modified +// after calling GetParsedSubjectCommonName the previous time. +func (c *Certificate) GetParsedSubjectCommonName(invalidateCache bool) ParsedDomainName { + if c.parsedCommonName != nil && !invalidateCache { + return *c.parsedCommonName + } + + var parsedDomain, parseError = publicsuffix.ParseFromListWithOptions(publicsuffix.DefaultList, + c.Subject.CommonName, + &publicsuffix.FindOptions{IgnorePrivate: true, DefaultRule: publicsuffix.DefaultRule}) + + c.parsedCommonName = &ParsedDomainName{ + DomainString: c.Subject.CommonName, + ParsedDomain: parsedDomain, + ParseError: parseError, + } + + return *c.parsedCommonName +} + +// ErrUnsupportedAlgorithm results from attempting to perform an operation that +// involves algorithms that are not currently implemented. +var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") + +// An InsecureAlgorithmError +type InsecureAlgorithmError SignatureAlgorithm + +func (e InsecureAlgorithmError) Error() string { + return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) +} + +// ConstraintViolationError results when a requested usage is not permitted by +// a certificate. For example: checking a signature when the public key isn't a +// certificate signing key. +type ConstraintViolationError struct{} + +func (ConstraintViolationError) Error() string { + return "x509: invalid signature: parent certificate cannot sign this kind of certificate" +} + +func (c *Certificate) Equal(other *Certificate) bool { + return bytes.Equal(c.Raw, other.Raw) +} + +func (c *Certificate) hasSANExtension() bool { + return oidInExtensions(oidExtensionSubjectAltName, c.Extensions) +} + +// Entrust have a broken root certificate (CN=Entrust.net Certification +// Authority (2048)) which isn't marked as a CA certificate and is thus invalid +// according to PKIX. +// We recognise this certificate by its SubjectPublicKeyInfo and exempt it +// from the Basic Constraints requirement. +// See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869 +// +// TODO(agl): remove this hack once their reissued root is sufficiently +// widespread. +var entrustBrokenSPKI = []byte{ + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, + 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, + 0x00, 0x97, 0xa3, 0x2d, 0x3c, 0x9e, 0xde, 0x05, + 0xda, 0x13, 0xc2, 0x11, 0x8d, 0x9d, 0x8e, 0xe3, + 0x7f, 0xc7, 0x4b, 0x7e, 0x5a, 0x9f, 0xb3, 0xff, + 0x62, 0xab, 0x73, 0xc8, 0x28, 0x6b, 0xba, 0x10, + 0x64, 0x82, 0x87, 0x13, 0xcd, 0x57, 0x18, 0xff, + 0x28, 0xce, 0xc0, 0xe6, 0x0e, 0x06, 0x91, 0x50, + 0x29, 0x83, 0xd1, 0xf2, 0xc3, 0x2a, 0xdb, 0xd8, + 0xdb, 0x4e, 0x04, 0xcc, 0x00, 0xeb, 0x8b, 0xb6, + 0x96, 0xdc, 0xbc, 0xaa, 0xfa, 0x52, 0x77, 0x04, + 0xc1, 0xdb, 0x19, 0xe4, 0xae, 0x9c, 0xfd, 0x3c, + 0x8b, 0x03, 0xef, 0x4d, 0xbc, 0x1a, 0x03, 0x65, + 0xf9, 0xc1, 0xb1, 0x3f, 0x72, 0x86, 0xf2, 0x38, + 0xaa, 0x19, 0xae, 0x10, 0x88, 0x78, 0x28, 0xda, + 0x75, 0xc3, 0x3d, 0x02, 0x82, 0x02, 0x9c, 0xb9, + 0xc1, 0x65, 0x77, 0x76, 0x24, 0x4c, 0x98, 0xf7, + 0x6d, 0x31, 0x38, 0xfb, 0xdb, 0xfe, 0xdb, 0x37, + 0x02, 0x76, 0xa1, 0x18, 0x97, 0xa6, 0xcc, 0xde, + 0x20, 0x09, 0x49, 0x36, 0x24, 0x69, 0x42, 0xf6, + 0xe4, 0x37, 0x62, 0xf1, 0x59, 0x6d, 0xa9, 0x3c, + 0xed, 0x34, 0x9c, 0xa3, 0x8e, 0xdb, 0xdc, 0x3a, + 0xd7, 0xf7, 0x0a, 0x6f, 0xef, 0x2e, 0xd8, 0xd5, + 0x93, 0x5a, 0x7a, 0xed, 0x08, 0x49, 0x68, 0xe2, + 0x41, 0xe3, 0x5a, 0x90, 0xc1, 0x86, 0x55, 0xfc, + 0x51, 0x43, 0x9d, 0xe0, 0xb2, 0xc4, 0x67, 0xb4, + 0xcb, 0x32, 0x31, 0x25, 0xf0, 0x54, 0x9f, 0x4b, + 0xd1, 0x6f, 0xdb, 0xd4, 0xdd, 0xfc, 0xaf, 0x5e, + 0x6c, 0x78, 0x90, 0x95, 0xde, 0xca, 0x3a, 0x48, + 0xb9, 0x79, 0x3c, 0x9b, 0x19, 0xd6, 0x75, 0x05, + 0xa0, 0xf9, 0x88, 0xd7, 0xc1, 0xe8, 0xa5, 0x09, + 0xe4, 0x1a, 0x15, 0xdc, 0x87, 0x23, 0xaa, 0xb2, + 0x75, 0x8c, 0x63, 0x25, 0x87, 0xd8, 0xf8, 0x3d, + 0xa6, 0xc2, 0xcc, 0x66, 0xff, 0xa5, 0x66, 0x68, + 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, +} + +// CheckSignatureFrom verifies that the signature on c is a valid signature +// from parent. +func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) { + // RFC 5280, 4.2.1.9: + // "If the basic constraints extension is not present in a version 3 + // certificate, or the extension is present but the cA boolean is not + // asserted, then the certified public key MUST NOT be used to verify + // certificate signatures." + // (except for Entrust, see comment above entrustBrokenSPKI) + if (parent.Version == 3 && !parent.BasicConstraintsValid || + parent.BasicConstraintsValid && !parent.IsCA) && + !bytes.Equal(c.RawSubjectPublicKeyInfo, entrustBrokenSPKI) { + return ConstraintViolationError{} + } + + if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 { + return ConstraintViolationError{} + } + + if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm { + return ErrUnsupportedAlgorithm + } + + // TODO(agl): don't ignore the path length constraint. + + if !bytes.Equal(parent.RawSubject, c.RawIssuer) { + return errors.New("Mis-match issuer/subject") + } + + return parent.CheckSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature) +} + +func CheckSignatureFromKey(publicKey interface{}, algo SignatureAlgorithm, signed, signature []byte) (err error) { + var hashType crypto.Hash + + switch algo { + // NOTE: exception to stdlib, allow MD5 algorithm + case MD5WithRSA: + hashType = crypto.MD5 + case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1: + hashType = crypto.SHA1 + case SHA256WithRSA, SHA256WithRSAPSS, DSAWithSHA256, ECDSAWithSHA256: + hashType = crypto.SHA256 + case SHA384WithRSA, SHA384WithRSAPSS, ECDSAWithSHA384: + hashType = crypto.SHA384 + case SHA512WithRSA, SHA512WithRSAPSS, ECDSAWithSHA512: + hashType = crypto.SHA512 + //case MD2WithRSA, MD5WithRSA: + case MD2WithRSA: + return InsecureAlgorithmError(algo) + case Ed25519Sig: + hashType = 0 + default: + return ErrUnsupportedAlgorithm + } + + if hashType != 0 && !hashType.Available() { + return ErrUnsupportedAlgorithm + } + digest := hash(hashType, signed) + + switch pub := publicKey.(type) { + case *rsa.PublicKey: + if algo.isRSAPSS() { + return rsa.VerifyPSS(pub, hashType, digest, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}) + } else { + return rsa.VerifyPKCS1v15(pub, hashType, digest, signature) + } + case *dsa.PublicKey: + dsaSig := new(dsaSignature) + if rest, err := asn1.Unmarshal(signature, dsaSig); err != nil { + return err + } else if len(rest) != 0 { + return errors.New("x509: trailing data after DSA signature") + } + if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 { + return errors.New("x509: DSA signature contained zero or negative values") + } + if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) { + return errors.New("x509: DSA verification failure") + } + return + case *ecdsa.PublicKey: + ecdsaSig := new(ecdsaSignature) + if rest, err := asn1.Unmarshal(signature, ecdsaSig); err != nil { + return err + } else if len(rest) != 0 { + return errors.New("x509: trailing data after ECDSA signature") + } + if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { + return errors.New("x509: ECDSA signature contained zero or negative values") + } + if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) { + return errors.New("x509: ECDSA verification failure") + } + return + case *AugmentedECDSA: + ecdsaSig := new(ecdsaSignature) + if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil { + return err + } + if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { + return errors.New("x509: ECDSA signature contained zero or negative values") + } + if !ecdsa.Verify(pub.Pub, digest, ecdsaSig.R, ecdsaSig.S) { + return errors.New("x509: ECDSA verification failure") + } + return + case ed25519.PublicKey: + if !ed25519.Verify(pub, digest, signature) { + return errors.New("x509: Ed25519 verification failure") + } + return + } + return ErrUnsupportedAlgorithm +} + +// CheckSignature verifies that signature is a valid signature over signed from +// c's public key. +func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err error) { + return CheckSignatureFromKey(c.PublicKey, algo, signed, signature) +} + +// CheckCRLSignature checks that the signature in crl is from c. +func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error { + algo := GetSignatureAlgorithmFromAI(crl.SignatureAlgorithm) + return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign()) +} + +// UnhandledCriticalExtension results when the certificate contains an +// unimplemented X.509 extension marked as critical. +type UnhandledCriticalExtension struct { + oid asn1.ObjectIdentifier + message string +} + +func (h UnhandledCriticalExtension) Error() string { + return fmt.Sprintf("x509: unhandled critical extension: %s | %s", h.oid, h.message) +} + +// TimeInValidityPeriod returns true if NotBefore < t < NotAfter +func (c *Certificate) TimeInValidityPeriod(t time.Time) bool { + return c.NotBefore.Before(t) && c.NotAfter.After(t) +} + +// RFC 5280 4.2.1.4 +type policyInformation struct { + Policy asn1.ObjectIdentifier + Qualifiers []policyQualifierInfo `asn1:"optional"` +} + +type policyQualifierInfo struct { + PolicyQualifierId asn1.ObjectIdentifier + Qualifier asn1.RawValue +} + +type userNotice struct { + NoticeRef noticeReference `asn1:"optional"` + ExplicitText asn1.RawValue `asn1:"optional"` +} + +type noticeReference struct { + Organization asn1.RawValue + NoticeNumbers []int +} + +type NoticeNumber []int + +type generalSubtree struct { + Value asn1.RawValue `asn1:"optional"` + Min int `asn1:"tag:0,default:0,optional"` + Max int `asn1:"tag:1,optional"` +} + +type GeneralSubtreeString struct { + Data string + Max int + Min int +} + +type GeneralSubtreeIP struct { + Data net.IPNet + Max int + Min int +} + +type GeneralSubtreeName struct { + Data pkix.Name + Max int + Min int +} + +type GeneralSubtreeEdi struct { + Data pkix.EDIPartyName + Max int + Min int +} + +type GeneralSubtreeOid struct { + Data asn1.ObjectIdentifier + Max int + Min int +} + +type GeneralSubtreeRaw struct { + Data asn1.RawValue + Max int + Min int +} + +type basicConstraints struct { + IsCA bool `asn1:"optional"` + MaxPathLen int `asn1:"optional,default:-1"` +} + +// RFC 5280, 4.2.1.10 +type nameConstraints struct { + Permitted []generalSubtree `asn1:"optional,tag:0"` + Excluded []generalSubtree `asn1:"optional,tag:1"` +} + +// RFC 5280, 4.2.2.1 +type authorityInfoAccess struct { + Method asn1.ObjectIdentifier + Location asn1.RawValue +} + +// RFC 5280, 4.2.1.14 +type distributionPoint struct { + DistributionPoint distributionPointName `asn1:"optional,tag:0"` + Reason asn1.BitString `asn1:"optional,tag:1"` + CRLIssuer asn1.RawValue `asn1:"optional,tag:2"` +} + +type distributionPointName struct { + FullName asn1.RawValue `asn1:"optional,tag:0"` + RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` +} + +func maxValidationLevel(a, b CertValidationLevel) CertValidationLevel { + if a > b { + return a + } + return b +} + +func hash(hashFunc crypto.Hash, raw []byte) []byte { + digest := raw + if hashFunc != 0 { + h := hashFunc.New() + h.Write(raw) + digest = h.Sum(nil) + } + return digest +} + +func getMaxCertValidationLevel(oids []asn1.ObjectIdentifier) CertValidationLevel { + maxOID := UnknownValidationLevel + for _, oid := range oids { + if _, ok := ExtendedValidationOIDs[oid.String()]; ok { + return EV + } else if _, ok := OrganizationValidationOIDs[oid.String()]; ok { + maxOID = maxValidationLevel(maxOID, OV) + } else if _, ok := DomainValidationOIDs[oid.String()]; ok { + maxOID = maxValidationLevel(maxOID, DV) + } + } + return maxOID +} + +func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { + asn1Data := keyData.PublicKey.RightAlign() + switch algo { + case RSA: + + // TODO: disabled since current behaviour does not expect it. Should be enabled though + // RSA public keys must have a NULL in the parameters + // (https://tools.ietf.org/html/rfc3279#section-2.3.1). + //if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) { + // return nil, errors.New("x509: RSA key missing NULL parameters") + //} + + p := new(pkcs1PublicKey) + rest, err := asn1.Unmarshal(asn1Data, p) + if err != nil { + return nil, err + } + if len(rest) != 0 { + return nil, errors.New("x509: trailing data after RSA public key") + } + + if p.N.Sign() <= 0 { + return nil, errors.New("x509: RSA modulus is not a positive number") + } + if p.E <= 0 { + return nil, errors.New("x509: RSA public exponent is not a positive number") + } + + pub := &rsa.PublicKey{ + E: p.E, + N: p.N, + } + return pub, nil + case DSA: + var p *big.Int + rest, err := asn1.Unmarshal(asn1Data, &p) + if err != nil { + return nil, err + } + if len(rest) != 0 { + return nil, errors.New("x509: trailing data after DSA public key") + } + paramsData := keyData.Algorithm.Parameters.FullBytes + params := new(dsaAlgorithmParameters) + rest, err = asn1.Unmarshal(paramsData, params) + if err != nil { + return nil, err + } + if len(rest) != 0 { + return nil, errors.New("x509: trailing data after DSA parameters") + } + if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 { + return nil, errors.New("x509: zero or negative DSA parameter") + } + pub := &dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: params.P, + Q: params.Q, + G: params.G, + }, + Y: p, + } + return pub, nil + case ECDSA: + paramsData := keyData.Algorithm.Parameters.FullBytes + namedCurveOID := new(asn1.ObjectIdentifier) + rest, err := asn1.Unmarshal(paramsData, namedCurveOID) + if err != nil { + return nil, err + } + if len(rest) != 0 { + return nil, errors.New("x509: trailing data after ECDSA parameters") + } + namedCurve := namedCurveFromOID(*namedCurveOID) + if namedCurve == nil { + return nil, errors.New("x509: unsupported elliptic curve") + } + x, y := elliptic.Unmarshal(namedCurve, asn1Data) + if x == nil { + return nil, errors.New("x509: failed to unmarshal elliptic curve point") + } + key := &ecdsa.PublicKey{ + Curve: namedCurve, + X: x, + Y: y, + } + + pub := &AugmentedECDSA{ + Pub: key, + Raw: keyData.PublicKey, + } + return pub, nil + case Ed25519: + p := ed25519.PublicKey(asn1Data) + if len(p) > ed25519.PublicKeySize { + return nil, errors.New("x509: trailing data after Ed25519 data") + } + return p, nil + case X25519: + p := X25519PublicKey(asn1Data) + if len(p) > 32 { + return nil, errors.New("x509: trailing data after X25519 public key") + } + return p, nil + default: + return nil, nil + } +} + +func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, err error) { + // RFC 5280, 4.2.1.6 + + // SubjectAltName ::= GeneralNames + // + // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + // + // GeneralName ::= CHOICE { + // otherName [0] OtherName, + // rfc822Name [1] IA5String, + // dNSName [2] IA5String, + // x400Address [3] ORAddress, + // directoryName [4] Name, + // ediPartyName [5] EDIPartyName, + // uniformResourceIdentifier [6] IA5String, + // iPAddress [7] OCTET STRING, + // registeredID [8] OBJECT IDENTIFIER } + var seq asn1.RawValue + var rest []byte + if rest, err = asn1.Unmarshal(value, &seq); err != nil { + return + } else if len(rest) != 0 { + err = errors.New("x509: trailing data after X.509 extension") + return + } + if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { + err = asn1.StructuralError{Msg: "bad SAN sequence"} + return + } + + rest = seq.Bytes + for len(rest) > 0 { + var v asn1.RawValue + rest, err = asn1.Unmarshal(rest, &v) + if err != nil { + return + } + switch v.Tag { + case 1: + emailAddresses = append(emailAddresses, string(v.Bytes)) + case 2: + dnsNames = append(dnsNames, string(v.Bytes)) + case 7: + switch len(v.Bytes) { + case net.IPv4len, net.IPv6len: + ipAddresses = append(ipAddresses, v.Bytes) + default: + err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) + return + } + } + } + + return +} + +func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, emailAddresses, URIs []string, directoryNames []pkix.Name, ediPartyNames []pkix.EDIPartyName, ipAddresses []net.IP, registeredIDs []asn1.ObjectIdentifier, err error) { + // RFC 5280, 4.2.1.6 + + // SubjectAltName ::= GeneralNames + // + // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + // + // GeneralName ::= CHOICE { + // otherName [0] OtherName, + // rfc822Name [1] IA5String, + // dNSName [2] IA5String, + // x400Address [3] ORAddress, + // directoryName [4] Name, + // ediPartyName [5] EDIPartyName, + // uniformResourceIdentifier [6] IA5String, + // iPAddress [7] OCTET STRING, + // registeredID [8] OBJECT IDENTIFIER } + var seq asn1.RawValue + if _, err = asn1.Unmarshal(value, &seq); err != nil { + return + } + if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { + err = asn1.StructuralError{Msg: "bad SAN sequence"} + return + } + + rest := seq.Bytes + for len(rest) > 0 { + var v asn1.RawValue + rest, err = asn1.Unmarshal(rest, &v) + if err != nil { + return + } + switch v.Tag { + case 0: + var oName pkix.OtherName + _, err = asn1.UnmarshalWithParams(v.FullBytes, &oName, "tag:0") + if err != nil { + return + } + otherNames = append(otherNames, oName) + case 1: + emailAddresses = append(emailAddresses, string(v.Bytes)) + case 2: + dnsNames = append(dnsNames, string(v.Bytes)) + case 4: + var rdn pkix.RDNSequence + _, err = asn1.Unmarshal(v.Bytes, &rdn) + if err != nil { + return + } + var dir pkix.Name + dir.FillFromRDNSequence(&rdn) + directoryNames = append(directoryNames, dir) + case 5: + var ediName pkix.EDIPartyName + _, err = asn1.UnmarshalWithParams(v.FullBytes, &ediName, "tag:5") + if err != nil { + return + } + ediPartyNames = append(ediPartyNames, ediName) + case 6: + URIs = append(URIs, string(v.Bytes)) + case 7: + switch len(v.Bytes) { + case net.IPv4len, net.IPv6len: + ipAddresses = append(ipAddresses, v.Bytes) + default: + err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) + return + } + case 8: + var id asn1.ObjectIdentifier + _, err = asn1.UnmarshalWithParams(v.FullBytes, &id, "tag:8") + if err != nil { + return + } + registeredIDs = append(registeredIDs, id) + } + } + + return +} + +//TODO +func parseCertificate(in *certificate) (*Certificate, error) { + out := new(Certificate) + out.Raw = in.Raw + out.RawTBSCertificate = in.TBSCertificate.Raw + out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw + out.RawSubject = in.TBSCertificate.Subject.FullBytes + out.RawIssuer = in.TBSCertificate.Issuer.FullBytes + + // Fingerprints + out.FingerprintMD5 = MD5Fingerprint(in.Raw) + out.FingerprintSHA1 = SHA1Fingerprint(in.Raw) + out.FingerprintSHA256 = SHA256Fingerprint(in.Raw) + out.SPKIFingerprint = SHA256Fingerprint(in.TBSCertificate.PublicKey.Raw) + out.TBSCertificateFingerprint = SHA256Fingerprint(in.TBSCertificate.Raw) + + tbs := in.TBSCertificate + originalExtensions := in.TBSCertificate.Extensions + + // Blow away the raw data since it also includes CT data + tbs.Raw = nil + + // remove the CT extensions + extensions := make([]pkix.Extension, 0, len(originalExtensions)) + for _, extension := range originalExtensions { + if extension.Id.Equal(oidExtensionCTPrecertificatePoison) { + continue + } + if extension.Id.Equal(oidExtensionSignedCertificateTimestampList) { + continue + } + extensions = append(extensions, extension) + } + + tbs.Extensions = extensions + + tbsbytes, err := asn1.Marshal(tbs) + if err != nil { + return nil, err + } + if tbsbytes == nil { + return nil, asn1.SyntaxError{Msg: "Trailing data"} + } + out.FingerprintNoCT = SHA256Fingerprint(tbsbytes[:]) + + // Hash both SPKI and Subject to create a fingerprint that we can use to describe a CA + hasher := sha256.New() + hasher.Write(in.TBSCertificate.PublicKey.Raw) + hasher.Write(in.TBSCertificate.Subject.FullBytes) + out.SPKISubjectFingerprint = hasher.Sum(nil) + + out.Signature = in.SignatureValue.RightAlign() + out.SignatureAlgorithm = + GetSignatureAlgorithmFromAI(in.TBSCertificate.SignatureAlgorithm) + + out.SignatureAlgorithmOID = in.TBSCertificate.SignatureAlgorithm.Algorithm + + out.PublicKeyAlgorithm = + getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm) + out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey) + if err != nil { + return nil, err + } + + out.PublicKeyAlgorithmOID = in.TBSCertificate.PublicKey.Algorithm.Algorithm + out.Version = in.TBSCertificate.Version + 1 + out.SerialNumber = in.TBSCertificate.SerialNumber + + var issuer, subject pkix.RDNSequence + if _, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil { + return nil, err + } + if _, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil { + return nil, err + } + + out.Issuer.FillFromRDNSequence(&issuer) + out.Subject.FillFromRDNSequence(&subject) + + // Check if self-signed + if bytes.Equal(out.RawSubject, out.RawIssuer) { + // Possibly self-signed, check the signature against itself. + if err := out.CheckSignature(out.SignatureAlgorithm, out.RawTBSCertificate, out.Signature); err == nil { + out.SelfSigned = true + } + } + + out.NotBefore = in.TBSCertificate.Validity.NotBefore + out.NotAfter = in.TBSCertificate.Validity.NotAfter + + out.ValidityPeriod = int(out.NotAfter.Sub(out.NotBefore).Seconds()) + + out.IssuerUniqueId = in.TBSCertificate.UniqueId + out.SubjectUniqueId = in.TBSCertificate.SubjectUniqueId + + out.ExtensionsMap = make(map[string]pkix.Extension, len(in.TBSCertificate.Extensions)) + for _, e := range in.TBSCertificate.Extensions { + out.Extensions = append(out.Extensions, e) + out.ExtensionsMap[e.Id.String()] = e + + if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { + switch e.Id[3] { + case 15: + // RFC 5280, 4.2.1.3 + var usageBits asn1.BitString + _, err := asn1.Unmarshal(e.Value, &usageBits) + + if err == nil { + var usage int + for i := 0; i < 9; i++ { + if usageBits.At(i) != 0 { + usage |= 1 << uint(i) + } + } + out.KeyUsage = KeyUsage(usage) + continue + } + case 19: + // RFC 5280, 4.2.1.9 + var constraints basicConstraints + _, err := asn1.Unmarshal(e.Value, &constraints) + + if err == nil { + out.BasicConstraintsValid = true + out.IsCA = constraints.IsCA + out.MaxPathLen = constraints.MaxPathLen + out.MaxPathLenZero = out.MaxPathLen == 0 + continue + } + case 17: + out.OtherNames, out.DNSNames, out.EmailAddresses, out.URIs, out.DirectoryNames, out.EDIPartyNames, out.IPAddresses, out.RegisteredIDs, err = parseGeneralNames(e.Value) + if err != nil { + return nil, err + } + + if len(out.DNSNames) > 0 || len(out.EmailAddresses) > 0 || len(out.IPAddresses) > 0 { + continue + } + // If we didn't parse any of the names then we + // fall through to the critical check below. + case 18: + out.IANOtherNames, out.IANDNSNames, out.IANEmailAddresses, out.IANURIs, out.IANDirectoryNames, out.IANEDIPartyNames, out.IANIPAddresses, out.IANRegisteredIDs, err = parseGeneralNames(e.Value) + if err != nil { + return nil, err + } + + if len(out.IANDNSNames) > 0 || len(out.IANEmailAddresses) > 0 || len(out.IANIPAddresses) > 0 { + continue + } + case 30: + // RFC 5280, 4.2.1.10 + + // NameConstraints ::= SEQUENCE { + // permittedSubtrees [0] GeneralSubtrees OPTIONAL, + // excludedSubtrees [1] GeneralSubtrees OPTIONAL } + // + // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + // + // GeneralSubtree ::= SEQUENCE { + // base GeneralName, + // Min [0] BaseDistance DEFAULT 0, + // Max [1] BaseDistance OPTIONAL } + // + // BaseDistance ::= INTEGER (0..MAX) + + var constraints nameConstraints + _, err := asn1.Unmarshal(e.Value, &constraints) + if err != nil { + return nil, err + } + + if e.Critical { + out.NameConstraintsCritical = true + } + + for _, subtree := range constraints.Permitted { + switch subtree.Value.Tag { + case 1: + out.PermittedEmailAddresses = append(out.PermittedEmailAddresses, GeneralSubtreeString{Data: string(subtree.Value.Bytes), Max: subtree.Max, Min: subtree.Min}) + case 2: + out.PermittedDNSNames = append(out.PermittedDNSNames, GeneralSubtreeString{Data: string(subtree.Value.Bytes), Max: subtree.Max, Min: subtree.Min}) + case 3: + out.PermittedX400Addresses = append(out.PermittedX400Addresses, GeneralSubtreeRaw{Data: subtree.Value, Max: subtree.Max, Min: subtree.Min}) + case 4: + var rawdn pkix.RDNSequence + if _, err := asn1.Unmarshal(subtree.Value.Bytes, &rawdn); err != nil { + return out, err + } + var dn pkix.Name + dn.FillFromRDNSequence(&rawdn) + out.PermittedDirectoryNames = append(out.PermittedDirectoryNames, GeneralSubtreeName{Data: dn, Max: subtree.Max, Min: subtree.Min}) + case 5: + var ediName pkix.EDIPartyName + _, err = asn1.UnmarshalWithParams(subtree.Value.FullBytes, &ediName, "tag:5") + if err != nil { + return out, err + } + out.PermittedEdiPartyNames = append(out.PermittedEdiPartyNames, GeneralSubtreeEdi{Data: ediName, Max: subtree.Max, Min: subtree.Min}) + case 6: + out.PermittedURIs = append(out.PermittedURIs, GeneralSubtreeString{Data: string(subtree.Value.Bytes), Max: subtree.Max, Min: subtree.Min}) + case 7: + switch len(subtree.Value.Bytes) { + case net.IPv4len * 2: + ip := net.IPNet{IP: subtree.Value.Bytes[:net.IPv4len], Mask: subtree.Value.Bytes[net.IPv4len:]} + out.PermittedIPAddresses = append(out.PermittedIPAddresses, GeneralSubtreeIP{Data: ip, Max: subtree.Max, Min: subtree.Min}) + case net.IPv6len * 2: + ip := net.IPNet{IP: subtree.Value.Bytes[:net.IPv6len], Mask: subtree.Value.Bytes[net.IPv6len:]} + out.PermittedIPAddresses = append(out.PermittedIPAddresses, GeneralSubtreeIP{Data: ip, Max: subtree.Max, Min: subtree.Min}) + default: + return out, errors.New("x509: certificate name constraint contained IP address range of length " + strconv.Itoa(len(subtree.Value.Bytes))) + } + case 8: + var id asn1.ObjectIdentifier + _, err = asn1.UnmarshalWithParams(subtree.Value.FullBytes, &id, "tag:8") + if err != nil { + return out, err + } + out.PermittedRegisteredIDs = append(out.PermittedRegisteredIDs, GeneralSubtreeOid{Data: id, Max: subtree.Max, Min: subtree.Min}) + } + } + for _, subtree := range constraints.Excluded { + switch subtree.Value.Tag { + case 1: + out.ExcludedEmailAddresses = append(out.ExcludedEmailAddresses, GeneralSubtreeString{Data: string(subtree.Value.Bytes), Max: subtree.Max, Min: subtree.Min}) + case 2: + out.ExcludedDNSNames = append(out.ExcludedDNSNames, GeneralSubtreeString{Data: string(subtree.Value.Bytes), Max: subtree.Max, Min: subtree.Min}) + case 3: + out.ExcludedX400Addresses = append(out.ExcludedX400Addresses, GeneralSubtreeRaw{Data: subtree.Value, Max: subtree.Max, Min: subtree.Min}) + case 4: + var rawdn pkix.RDNSequence + if _, err := asn1.Unmarshal(subtree.Value.Bytes, &rawdn); err != nil { + return out, err + } + var dn pkix.Name + dn.FillFromRDNSequence(&rawdn) + out.ExcludedDirectoryNames = append(out.ExcludedDirectoryNames, GeneralSubtreeName{Data: dn, Max: subtree.Max, Min: subtree.Min}) + case 5: + var ediName pkix.EDIPartyName + _, err = asn1.Unmarshal(subtree.Value.Bytes, &ediName) + if err != nil { + return out, err + } + out.ExcludedEdiPartyNames = append(out.ExcludedEdiPartyNames, GeneralSubtreeEdi{Data: ediName, Max: subtree.Max, Min: subtree.Min}) + case 6: + out.ExcludedURIs = append(out.ExcludedURIs, GeneralSubtreeString{Data: string(subtree.Value.Bytes), Max: subtree.Max, Min: subtree.Min}) + case 7: + switch len(subtree.Value.Bytes) { + case net.IPv4len * 2: + ip := net.IPNet{IP: subtree.Value.Bytes[:net.IPv4len], Mask: subtree.Value.Bytes[net.IPv4len:]} + out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, GeneralSubtreeIP{Data: ip, Max: subtree.Max, Min: subtree.Min}) + case net.IPv6len * 2: + ip := net.IPNet{IP: subtree.Value.Bytes[:net.IPv6len], Mask: subtree.Value.Bytes[net.IPv6len:]} + out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, GeneralSubtreeIP{Data: ip, Max: subtree.Max, Min: subtree.Min}) + default: + return out, errors.New("x509: certificate name constraint contained IP address range of length " + strconv.Itoa(len(subtree.Value.Bytes))) + } + case 8: + var id asn1.ObjectIdentifier + _, err = asn1.Unmarshal(subtree.Value.Bytes, &id) + if err != nil { + return out, err + } + out.ExcludedRegisteredIDs = append(out.ExcludedRegisteredIDs, GeneralSubtreeOid{Data: id, Max: subtree.Max, Min: subtree.Min}) + } + } + continue + + case 31: + // RFC 5280, 4.2.1.14 + + // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + // + // DistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // reasons [1] ReasonFlags OPTIONAL, + // cRLIssuer [2] GeneralNames OPTIONAL } + // + // DistributionPointName ::= CHOICE { + // fullName [0] GeneralNames, + // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + + var cdp []distributionPoint + _, err := asn1.Unmarshal(e.Value, &cdp) + if err != nil { + return nil, err + } + + for _, dp := range cdp { + // Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty. + if len(dp.DistributionPoint.FullName.Bytes) == 0 { + continue + } + + var n asn1.RawValue + dpName := dp.DistributionPoint.FullName.Bytes + // FullName is a GeneralNames, which is a SEQUENCE OF + // GeneralName, which in turn is a CHOICE. + // Per https://www.ietf.org/rfc/rfc5280.txt, multiple names + // for a single DistributionPoint give different pointers to + // the same CRL. + for len(dpName) > 0 { + dpName, err = asn1.Unmarshal(dpName, &n) + if err != nil { + return nil, err + } + if n.Tag == 6 { + out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes)) + } + } + } + continue + + case 35: + // RFC 5280, 4.2.1.1 + var a authKeyId + _, err = asn1.Unmarshal(e.Value, &a) + if err != nil { + return nil, err + } + out.AuthorityKeyId = a.Id + continue + + case 37: + // RFC 5280, 4.2.1.12. Extended Key Usage + + // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } + // + // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + // + // KeyPurposeId ::= OBJECT IDENTIFIER + + var keyUsage []asn1.ObjectIdentifier + _, err = asn1.Unmarshal(e.Value, &keyUsage) + if err != nil { + return nil, err + } + + for _, u := range keyUsage { + if extKeyUsage, ok := extKeyUsageFromOID(u); ok { + out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage) + } else { + out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u) + } + } + + continue + + case 14: + // RFC 5280, 4.2.1.2 + var keyid []byte + _, err = asn1.Unmarshal(e.Value, &keyid) + if err != nil { + return nil, err + } + out.SubjectKeyId = keyid + continue + + case 32: + // RFC 5280 4.2.1.4: Certificate Policies + var policies []policyInformation + if _, err = asn1.Unmarshal(e.Value, &policies); err != nil { + return nil, err + } + out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies)) + out.QualifierId = make([][]asn1.ObjectIdentifier, len(policies)) + out.ExplicitTexts = make([][]asn1.RawValue, len(policies)) + out.NoticeRefOrgnization = make([][]asn1.RawValue, len(policies)) + out.NoticeRefNumbers = make([][]NoticeNumber, len(policies)) + out.ParsedExplicitTexts = make([][]string, len(policies)) + out.ParsedNoticeRefOrganization = make([][]string, len(policies)) + out.CPSuri = make([][]string, len(policies)) + + for i, policy := range policies { + out.PolicyIdentifiers[i] = policy.Policy + // parse optional Qualifier for zlint + for _, qualifier := range policy.Qualifiers { + out.QualifierId[i] = append(out.QualifierId[i], qualifier.PolicyQualifierId) + userNoticeOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2} + cpsURIOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} + if qualifier.PolicyQualifierId.Equal(userNoticeOID) { + var un userNotice + if _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &un); err != nil { + return nil, err + } + if len(un.ExplicitText.Bytes) != 0 { + out.ExplicitTexts[i] = append(out.ExplicitTexts[i], un.ExplicitText) + out.ParsedExplicitTexts[i] = append(out.ParsedExplicitTexts[i], string(un.ExplicitText.Bytes)) + } + if un.NoticeRef.Organization.Bytes != nil || un.NoticeRef.NoticeNumbers != nil { + out.NoticeRefOrgnization[i] = append(out.NoticeRefOrgnization[i], un.NoticeRef.Organization) + out.NoticeRefNumbers[i] = append(out.NoticeRefNumbers[i], un.NoticeRef.NoticeNumbers) + out.ParsedNoticeRefOrganization[i] = append(out.ParsedNoticeRefOrganization[i], string(un.NoticeRef.Organization.Bytes)) + } + } + if qualifier.PolicyQualifierId.Equal(cpsURIOID) { + var cpsURIRaw asn1.RawValue + if _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &cpsURIRaw); err != nil { + return nil, err + } + out.CPSuri[i] = append(out.CPSuri[i], string(cpsURIRaw.Bytes)) + } + } + } + if out.SelfSigned { + out.ValidationLevel = UnknownValidationLevel + } else { + // See http://unmitigatedrisk.com/?p=203 + validationLevel := getMaxCertValidationLevel(out.PolicyIdentifiers) + if validationLevel == UnknownValidationLevel { + if (len(out.Subject.Organization) > 0 && out.Subject.Organization[0] == out.Subject.CommonName) || (len(out.Subject.OrganizationalUnit) > 0 && strings.Contains(out.Subject.OrganizationalUnit[0], "Domain Control Validated")) { + if len(out.Subject.Locality) == 0 && len(out.Subject.Province) == 0 && len(out.Subject.PostalCode) == 0 { + validationLevel = DV + } + } else if len(out.Subject.Organization) > 0 && out.Subject.Organization[0] == "Persona Not Validated" && strings.Contains(out.Issuer.CommonName, "StartCom") { + validationLevel = DV + } + } + out.ValidationLevel = validationLevel + } + } + } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) { + // RFC 5280 4.2.2.1: Authority Information Access + var aia []authorityInfoAccess + if _, err = asn1.Unmarshal(e.Value, &aia); err != nil { + return nil, err + } + + for _, v := range aia { + // GeneralName: uniformResourceIdentifier [6] IA5String + if v.Location.Tag != 6 { + continue + } + if v.Method.Equal(oidAuthorityInfoAccessOcsp) { + out.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes)) + } else if v.Method.Equal(oidAuthorityInfoAccessIssuers) { + out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes)) + } + } + } else if e.Id.Equal(oidExtensionSignedCertificateTimestampList) { + err := parseSignedCertificateTimestampList(out, e) + if err != nil { + return nil, err + } + } else if e.Id.Equal(oidExtensionCTPrecertificatePoison) { + if e.Value[0] == 5 && e.Value[1] == 0 { + out.IsPrecert = true + continue + } else { + return nil, UnhandledCriticalExtension{e.Id, "Malformed precert poison"} + } + } else if e.Id.Equal(oidBRTorServiceDescriptor) { + descs, err := parseTorServiceDescriptorSyntax(e) + if err != nil { + return nil, err + } + out.TorServiceDescriptors = descs + } else if e.Id.Equal(oidExtCABFOrganizationID) { + cabf := CABFOrganizationIDASN{} + _, err := asn1.Unmarshal(e.Value, &cabf) + if err != nil { + return nil, err + } + out.CABFOrganizationIdentifier = &CABFOrganizationIdentifier{ + Scheme: cabf.RegistrationSchemeIdentifier, + Country: cabf.RegistrationCountry, + Reference: cabf.RegistrationReference, + State: cabf.RegistrationStateOrProvince, + } + } else if e.Id.Equal(oidExtQCStatements) { + rawStatements := QCStatementsASN{} + _, err := asn1.Unmarshal(e.Value, &rawStatements.QCStatements) + if err != nil { + return nil, err + } + qcStatements := QCStatements{} + if err := qcStatements.Parse(&rawStatements); err != nil { + return nil, err + } + out.QCStatements = &qcStatements + } + + //if e.Critical { + // return out, UnhandledCriticalExtension{e.Id} + //} + } + + return out, nil +} + +func parseSignedCertificateTimestampList(out *Certificate, ext pkix.Extension) error { + var scts []byte + if _, err := asn1.Unmarshal(ext.Value, &scts); err != nil { + return err + } + // ignore length of + if len(scts) < 2 { + return errors.New("malformed SCT extension: incomplete length field") + } + scts = scts[2:] + headerLength := 2 + for { + switch len(scts) { + case 0: + return nil + case 1: + return errors.New("malformed SCT extension: trailing data") + default: + sctLength := int(scts[1]) + (int(scts[0]) << 8) + headerLength + if !(sctLength <= len(scts)) { + return errors.New("malformed SCT extension: incomplete SCT") + } + sct, err := ct.DeserializeSCT(bytes.NewReader(scts[headerLength:sctLength])) + if err != nil { + return fmt.Errorf("malformed SCT extension: SCT parse err: %v", err) + } + out.SignedCertificateTimestampList = append(out.SignedCertificateTimestampList, sct) + scts = scts[sctLength:] + } + } +} + +// ParseCertificate parses a single certificate from the given ASN.1 DER data. +func ParseCertificate(asn1Data []byte) (*Certificate, error) { + var cert certificate + rest, err := asn1.Unmarshal(asn1Data, &cert) + if err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + + return parseCertificate(&cert) +} + +// ParseCertificates parses one or more certificates from the given ASN.1 DER +// data. The certificates must be concatenated with no intermediate padding. +func ParseCertificates(asn1Data []byte) ([]*Certificate, error) { + var v []*certificate + + for len(asn1Data) > 0 { + cert := new(certificate) + var err error + asn1Data, err = asn1.Unmarshal(asn1Data, cert) + if err != nil { + return nil, err + } + v = append(v, cert) + } + + ret := make([]*Certificate, len(v)) + for i, ci := range v { + cert, err := parseCertificate(ci) + if err != nil { + return nil, err + } + ret[i] = cert + } + + return ret, nil +} + +func ParseTBSCertificate(asn1Data []byte) (*Certificate, error) { + var tbsCert tbsCertificate + rest, err := asn1.Unmarshal(asn1Data, &tbsCert) + if err != nil { + //log.Print("Err unmarshalling asn1Data", asn1Data, rest) + return nil, err + } + if len(rest) > 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + return parseCertificate(&certificate{ + Raw: tbsCert.Raw, + TBSCertificate: tbsCert}) +} + +// SubjectAndKey represents a (subjecty, subject public key info) tuple. +type SubjectAndKey struct { + RawSubject []byte + RawSubjectPublicKeyInfo []byte + Fingerprint CertificateFingerprint + PublicKey interface{} + PublicKeyAlgorithm PublicKeyAlgorithm +} + +// SubjectAndKey returns a SubjectAndKey for this certificate. +func (c *Certificate) SubjectAndKey() *SubjectAndKey { + return &SubjectAndKey{ + RawSubject: c.RawSubject, + RawSubjectPublicKeyInfo: c.RawSubjectPublicKeyInfo, + Fingerprint: c.SPKISubjectFingerprint, + PublicKey: c.PublicKey, + PublicKeyAlgorithm: c.PublicKeyAlgorithm, + } +} + +func reverseBitsInAByte(in byte) byte { + b1 := in>>4 | in<<4 + b2 := b1>>2&0x33 | b1<<2&0xcc + b3 := b2>>1&0x55 | b2<<1&0xaa + return b3 +} + +// asn1BitLength returns the bit-length of bitString by considering the +// most-significant bit in a byte to be the "first" bit. This convention +// matches ASN.1, but differs from almost everything else. +func asn1BitLength(bitString []byte) int { + bitLen := len(bitString) * 8 + + for i := range bitString { + b := bitString[len(bitString)-i-1] + + for bit := uint(0); bit < 8; bit++ { + if (b>>bit)&1 == 1 { + return bitLen + } + bitLen-- + } + } + + return 0 +} + +var ( + oidExtensionSubjectKeyId = []int{2, 5, 29, 14} + oidExtensionKeyUsage = []int{2, 5, 29, 15} + oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37} + oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} + oidExtensionBasicConstraints = []int{2, 5, 29, 19} + oidExtensionSubjectAltName = []int{2, 5, 29, 17} + oidExtensionIssuerAltName = []int{2, 5, 29, 18} + oidExtensionCertificatePolicies = []int{2, 5, 29, 32} + oidExtensionNameConstraints = []int{2, 5, 29, 30} + oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31} + oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1} + oidExtensionSignedCertificateTimestampList = []int{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2} +) + +var ( + oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1} + oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2} +) + +// oidNotInExtensions returns whether an extension with the given oid exists in +// extensions. +func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool { + for _, e := range extensions { + if e.Id.Equal(oid) { + return true + } + } + return false +} + +// marshalSANs marshals a list of addresses into a the contents of an X.509 +// SubjectAlternativeName extension. +func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP) (derBytes []byte, err error) { + var rawValues []asn1.RawValue + for _, name := range dnsNames { + rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)}) + } + for _, email := range emailAddresses { + rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)}) + } + for _, rawIP := range ipAddresses { + // If possible, we always want to encode IPv4 addresses in 4 bytes. + ip := rawIP.To4() + if ip == nil { + ip = rawIP + } + rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip}) + } + return asn1.Marshal(rawValues) +} + +// NOTE ignoring authorityKeyID argument +func buildExtensions(template *Certificate, _ []byte) (ret []pkix.Extension, err error) { + ret = make([]pkix.Extension, 10 /* Max number of elements. */) + n := 0 + + if template.KeyUsage != 0 && + !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) { + ret[n].Id = oidExtensionKeyUsage + ret[n].Critical = true + + var a [2]byte + a[0] = reverseBitsInAByte(byte(template.KeyUsage)) + a[1] = reverseBitsInAByte(byte(template.KeyUsage >> 8)) + + l := 1 + if a[1] != 0 { + l = 2 + } + + ret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: a[0:l], BitLength: l * 8}) + if err != nil { + return + } + n++ + } + + if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) && + !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) { + ret[n].Id = oidExtensionExtendedKeyUsage + + var oids []asn1.ObjectIdentifier + for _, u := range template.ExtKeyUsage { + if oid, ok := oidFromExtKeyUsage(u); ok { + oids = append(oids, oid) + } else { + panic("internal error") + } + } + + oids = append(oids, template.UnknownExtKeyUsage...) + + ret[n].Value, err = asn1.Marshal(oids) + if err != nil { + return + } + n++ + } + + if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) { + // Leaving MaxPathLen as zero indicates that no Max path + // length is desired, unless MaxPathLenZero is set. A value of + // -1 causes encoding/asn1 to omit the value as desired. + maxPathLen := template.MaxPathLen + if maxPathLen == 0 && !template.MaxPathLenZero { + maxPathLen = -1 + } + ret[n].Id = oidExtensionBasicConstraints + ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, maxPathLen}) + ret[n].Critical = true + if err != nil { + return + } + n++ + } + + if len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) { + ret[n].Id = oidExtensionSubjectKeyId + ret[n].Value, err = asn1.Marshal(template.SubjectKeyId) + if err != nil { + return + } + n++ + } + + if len(template.AuthorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) { + ret[n].Id = oidExtensionAuthorityKeyId + ret[n].Value, err = asn1.Marshal(authKeyId{template.AuthorityKeyId}) + if err != nil { + return + } + n++ + } + + if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) && + !oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) { + ret[n].Id = oidExtensionAuthorityInfoAccess + var aiaValues []authorityInfoAccess + for _, name := range template.OCSPServer { + aiaValues = append(aiaValues, authorityInfoAccess{ + Method: oidAuthorityInfoAccessOcsp, + Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, + }) + } + for _, name := range template.IssuingCertificateURL { + aiaValues = append(aiaValues, authorityInfoAccess{ + Method: oidAuthorityInfoAccessIssuers, + Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, + }) + } + ret[n].Value, err = asn1.Marshal(aiaValues) + if err != nil { + return + } + n++ + } + + if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) && + !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { + ret[n].Id = oidExtensionSubjectAltName + ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses) + if err != nil { + return + } + n++ + } + + if len(template.PolicyIdentifiers) > 0 && + !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) { + ret[n].Id = oidExtensionCertificatePolicies + policies := make([]policyInformation, len(template.PolicyIdentifiers)) + for i, policy := range template.PolicyIdentifiers { + policies[i].Policy = policy + } + ret[n].Value, err = asn1.Marshal(policies) + if err != nil { + return + } + n++ + } + + // TODO: this can be cleaned up in go1.10 + if (len(template.PermittedEmailAddresses) > 0 || len(template.PermittedDNSNames) > 0 || len(template.PermittedDirectoryNames) > 0 || + len(template.PermittedIPAddresses) > 0 || len(template.ExcludedEmailAddresses) > 0 || len(template.ExcludedDNSNames) > 0 || + len(template.ExcludedDirectoryNames) > 0 || len(template.ExcludedIPAddresses) > 0) && + !oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) { + ret[n].Id = oidExtensionNameConstraints + if template.NameConstraintsCritical { + ret[n].Critical = true + } + + var out nameConstraints + + for _, permitted := range template.PermittedEmailAddresses { + out.Permitted = append(out.Permitted, generalSubtree{Value: asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(permitted.Data)}}) + } + for _, excluded := range template.ExcludedEmailAddresses { + out.Excluded = append(out.Excluded, generalSubtree{Value: asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(excluded.Data)}}) + } + for _, permitted := range template.PermittedDNSNames { + out.Permitted = append(out.Permitted, generalSubtree{Value: asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(permitted.Data)}}) + } + for _, excluded := range template.ExcludedDNSNames { + out.Excluded = append(out.Excluded, generalSubtree{Value: asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(excluded.Data)}}) + } + for _, permitted := range template.PermittedDirectoryNames { + var dn []byte + dn, err = asn1.Marshal(permitted.Data.ToRDNSequence()) + if err != nil { + return + } + out.Permitted = append(out.Permitted, generalSubtree{Value: asn1.RawValue{Tag: 4, Class: 2, IsCompound: true, Bytes: dn}}) + } + for _, excluded := range template.ExcludedDirectoryNames { + var dn []byte + dn, err = asn1.Marshal(excluded.Data.ToRDNSequence()) + if err != nil { + return + } + out.Excluded = append(out.Excluded, generalSubtree{Value: asn1.RawValue{Tag: 4, Class: 2, IsCompound: true, Bytes: dn}}) + } + for _, permitted := range template.PermittedIPAddresses { + ip := append(permitted.Data.IP, permitted.Data.Mask...) + out.Permitted = append(out.Permitted, generalSubtree{Value: asn1.RawValue{Tag: 7, Class: 2, Bytes: ip}}) + } + for _, excluded := range template.ExcludedIPAddresses { + ip := append(excluded.Data.IP, excluded.Data.Mask...) + out.Excluded = append(out.Excluded, generalSubtree{Value: asn1.RawValue{Tag: 7, Class: 2, Bytes: ip}}) + } + ret[n].Value, err = asn1.Marshal(out) + if err != nil { + return + } + n++ + } + + if len(template.CRLDistributionPoints) > 0 && + !oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) { + ret[n].Id = oidExtensionCRLDistributionPoints + + var crlDp []distributionPoint + for _, name := range template.CRLDistributionPoints { + rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}) + + dp := distributionPoint{ + DistributionPoint: distributionPointName{ + FullName: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: rawFullName}, + }, + } + crlDp = append(crlDp, dp) + } + + ret[n].Value, err = asn1.Marshal(crlDp) + if err != nil { + return + } + n++ + } + + // Adding another extension here? Remember to update the Max number + // of elements in the make() at the top of the function. + + return append(ret[:n], template.ExtraExtensions...), nil +} + +func subjectBytes(cert *Certificate) ([]byte, error) { + if len(cert.RawSubject) > 0 { + return cert.RawSubject, nil + } + + return asn1.Marshal(cert.Subject.ToRDNSequence()) +} + +// signingParamsForPublicKey returns the parameters to use for signing with +// priv. If requestedSigAlgo is not zero then it overrides the default +// signature algorithm. +func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { + var pubType PublicKeyAlgorithm + shouldHash := true + + switch pub := pub.(type) { + case *rsa.PublicKey: + pubType = RSA + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureSHA256WithRSA + sigAlgo.Parameters = asn1.NullRawValue + + case *ecdsa.PublicKey: + pubType = ECDSA + + switch pub.Curve { + case elliptic.P224(), elliptic.P256(): + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 + case elliptic.P384(): + hashFunc = crypto.SHA384 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 + case elliptic.P521(): + hashFunc = crypto.SHA512 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 + default: + err = errors.New("x509: unknown elliptic curve") + } + + case ed25519.PublicKey: + pubType = Ed25519 + hashFunc = 0 + shouldHash = false + sigAlgo.Algorithm = oidKeyEd25519 + + default: + err = errors.New("x509: only RSA, ECDSA, Ed25519, and X25519 keys supported") + } + + if err != nil { + return + } + + if requestedSigAlgo == 0 { + return + } + + found := false + for _, details := range signatureAlgorithmDetails { + if details.algo == requestedSigAlgo { + if details.pubKeyAlgo != pubType { + err = errors.New("x509: requested SignatureAlgorithm does not match private key type") + return + } + sigAlgo.Algorithm, hashFunc = details.oid, details.hash + if hashFunc == 0 && shouldHash { + err = errors.New("x509: cannot sign with hash function requested") + return + } + if requestedSigAlgo.isRSAPSS() { + sigAlgo.Parameters = rsaPSSParameters(hashFunc) + } + found = true + break + } + } + + if !found { + err = errors.New("x509: unknown SignatureAlgorithm") + } + + return +} + +// CreateCertificate creates a new certificate based on a template. +// The following members of template are used: AuthorityKeyId, +// BasicConstraintsValid, DNSNames, ExcludedDNSDomains, ExtKeyUsage, +// IsCA, KeyUsage, MaxPathLen, MaxPathLenZero, NotAfter, NotBefore, +// PermittedDNSDomains, PermittedDNSDomainsCritical, SerialNumber, +// SignatureAlgorithm, Subject, SubjectKeyId, and UnknownExtKeyUsage. +// +// The certificate is signed by parent. If parent is equal to template then the +// certificate is self-signed. The parameter pub is the public key of the +// signee and priv is the private key of the signer. +// +// The returned slice is the certificate in DER encoding. +// +// All keys types that are implemented via crypto.Signer are supported (This +// includes *rsa.PublicKey and *ecdsa.PublicKey.) +// +// The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any, +// unless the resulting certificate is self-signed. Otherwise the value from +// template will be used. +func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) { + key, ok := priv.(crypto.Signer) + if !ok { + return nil, errors.New("x509: certificate private key does not implement crypto.Signer") + } + + if template.SerialNumber == nil { + return nil, errors.New("x509: no SerialNumber given") + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub) + if err != nil { + return nil, err + } + + asn1Issuer, err := subjectBytes(parent) + if err != nil { + return + } + + asn1Subject, err := subjectBytes(template) + if err != nil { + return + } + + authorityKeyId := template.AuthorityKeyId + if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 { + authorityKeyId = parent.SubjectKeyId + } + + extensions, err := buildExtensions(template, authorityKeyId) + if err != nil { + return + } + + encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} + c := tbsCertificate{ + Version: 2, + SerialNumber: template.SerialNumber, + SignatureAlgorithm: signatureAlgorithm, + Issuer: asn1.RawValue{FullBytes: asn1Issuer}, + Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, + Subject: asn1.RawValue{FullBytes: asn1Subject}, + PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}, + Extensions: extensions, + } + + tbsCertContents, err := asn1.Marshal(c) + if err != nil { + return + } + c.Raw = tbsCertContents + + digest := hash(hashFunc, c.Raw) + + var signerOpts crypto.SignerOpts + signerOpts = hashFunc + if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() { + signerOpts = &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: hashFunc, + } + } + + var signature []byte + signature, err = key.Sign(rand, digest, signerOpts) + if err != nil { + return + } + + return asn1.Marshal(certificate{ + nil, + c, + signatureAlgorithm, + asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, + }) +} + +// pemCRLPrefix is the magic string that indicates that we have a PEM encoded +// CRL. +var pemCRLPrefix = []byte("-----BEGIN X509 CRL") + +// pemType is the type of a PEM encoded CRL. +var pemType = "X509 CRL" + +// ParseCRL parses a CRL from the given bytes. It's often the case that PEM +// encoded CRLs will appear where they should be DER encoded, so this function +// will transparently handle PEM encoding as long as there isn't any leading +// garbage. +func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) { + if bytes.HasPrefix(crlBytes, pemCRLPrefix) { + block, _ := pem.Decode(crlBytes) + if block != nil && block.Type == pemType { + crlBytes = block.Bytes + } + } + return ParseDERCRL(crlBytes) +} + +// ParseDERCRL parses a DER encoded CRL from the given bytes. +func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) { + certList := new(pkix.CertificateList) + if rest, err := asn1.Unmarshal(derBytes, certList); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after CRL") + } + return certList, nil +} + +// CreateCRL returns a DER encoded CRL, signed by this Certificate, that +// contains the given list of revoked certificates. +func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { + key, ok := priv.(crypto.Signer) + if !ok { + return nil, errors.New("x509: certificate private key does not implement crypto.Signer") + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0) + if err != nil { + return nil, err + } + + // Force revocation times to UTC per RFC 5280. + revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts)) + for i, rc := range revokedCerts { + rc.RevocationTime = rc.RevocationTime.UTC() + revokedCertsUTC[i] = rc + } + + tbsCertList := pkix.TBSCertificateList{ + Version: 1, + Signature: signatureAlgorithm, + Issuer: c.Subject.ToRDNSequence(), + ThisUpdate: now.UTC(), + NextUpdate: expiry.UTC(), + RevokedCertificates: revokedCertsUTC, + } + + // Authority Key Id + if len(c.SubjectKeyId) > 0 { + var aki pkix.Extension + aki.Id = oidExtensionAuthorityKeyId + aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId}) + if err != nil { + return + } + tbsCertList.Extensions = append(tbsCertList.Extensions, aki) + } + + tbsCertListContents, err := asn1.Marshal(tbsCertList) + if err != nil { + return + } + + digest := hash(hashFunc, tbsCertListContents) + + var signature []byte + signature, err = key.Sign(rand, digest, hashFunc) + if err != nil { + return + } + + return asn1.Marshal(pkix.CertificateList{ + TBSCertList: tbsCertList, + SignatureAlgorithm: signatureAlgorithm, + SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, + }) +} + +// CertificateRequest represents a PKCS #10, certificate signature request. +type CertificateRequest struct { + Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature). + RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content. + RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. + RawSubject []byte // DER encoded Subject. + + Version int + Signature []byte + SignatureAlgorithm SignatureAlgorithm + + PublicKeyAlgorithm PublicKeyAlgorithm + PublicKey interface{} + + Subject pkix.Name + + // Attributes is the dried husk of a bug and shouldn't be used. + Attributes []pkix.AttributeTypeAndValueSET + + // Extensions contains raw X.509 extensions. When parsing CSRs, this + // can be used to extract extensions that are not parsed by this + // package. + Extensions []pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any + // marshaled CSR. Values override any extensions that would otherwise + // be produced based on the other fields but are overridden by any + // extensions specified in Attributes. + // + // The ExtraExtensions field is not populated when parsing CSRs, see + // Extensions. + ExtraExtensions []pkix.Extension + + // Subject Alternate Name values. + DNSNames []string + EmailAddresses []string + IPAddresses []net.IP +} + +// These structures reflect the ASN.1 structure of X.509 certificate +// signature requests (see RFC 2986): + +type tbsCertificateRequest struct { + Raw asn1.RawContent + Version int + Subject asn1.RawValue + PublicKey publicKeyInfo + RawAttributes []asn1.RawValue `asn1:"tag:0"` +} + +type certificateRequest struct { + Raw asn1.RawContent + TBSCSR tbsCertificateRequest + SignatureAlgorithm pkix.AlgorithmIdentifier + SignatureValue asn1.BitString +} + +// oidExtensionRequest is a PKCS#9 OBJECT IDENTIFIER that indicates requested +// extensions in a CSR. +var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14} + +// newRawAttributes converts AttributeTypeAndValueSETs from a template +// CertificateRequest's Attributes into tbsCertificateRequest RawAttributes. +func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) { + var rawAttributes []asn1.RawValue + b, err := asn1.Marshal(attributes) + if err != nil { + return nil, err + } + rest, err := asn1.Unmarshal(b, &rawAttributes) + if err != nil { + return nil, err + } + if len(rest) != 0 { + return nil, errors.New("x509: failed to unmarshal raw CSR Attributes") + } + return rawAttributes, nil +} + +// parseRawAttributes Unmarshals RawAttributes intos AttributeTypeAndValueSETs. +func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET { + var attributes []pkix.AttributeTypeAndValueSET + for _, rawAttr := range rawAttributes { + var attr pkix.AttributeTypeAndValueSET + rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr) + // Ignore attributes that don't parse into pkix.AttributeTypeAndValueSET + // (i.e.: challengePassword or unstructuredName). + if err == nil && len(rest) == 0 { + attributes = append(attributes, attr) + } + } + return attributes +} + +// parseCSRExtensions parses the attributes from a CSR and extracts any +// requested extensions. +func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) { + // pkcs10Attribute reflects the Attribute structure from section 4.1 of + // https://tools.ietf.org/html/rfc2986. + type pkcs10Attribute struct { + Id asn1.ObjectIdentifier + Values []asn1.RawValue `asn1:"set"` + } + + var ret []pkix.Extension + for _, rawAttr := range rawAttributes { + var attr pkcs10Attribute + if rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 { + // Ignore attributes that don't parse. + continue + } + + if !attr.Id.Equal(oidExtensionRequest) { + continue + } + + var extensions []pkix.Extension + if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil { + return nil, err + } + ret = append(ret, extensions...) + } + + return ret, nil +} + +// CreateCertificateRequest creates a new certificate request based on a +// template. The following members of template are used: Attributes, DNSNames, +// EmailAddresses, ExtraExtensions, IPAddresses, SignatureAlgorithm, and +// Subject. The private key is the private key of the signer. +// +// The returned slice is the certificate request in DER encoding. +// +// All keys types that are implemented via crypto.Signer are supported (This +// includes *rsa.PublicKey and *ecdsa.PublicKey.) +func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) { + key, ok := priv.(crypto.Signer) + if !ok { + return nil, errors.New("x509: certificate private key does not implement crypto.Signer") + } + + var hashFunc crypto.Hash + var sigAlgo pkix.AlgorithmIdentifier + hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + var publicKeyBytes []byte + var publicKeyAlgorithm pkix.AlgorithmIdentifier + publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public()) + if err != nil { + return nil, err + } + + var extensions []pkix.Extension + + if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) && + !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { + sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses) + if err != nil { + return nil, err + } + + extensions = append(extensions, pkix.Extension{ + Id: oidExtensionSubjectAltName, + Value: sanBytes, + }) + } + + extensions = append(extensions, template.ExtraExtensions...) + + var attributes []pkix.AttributeTypeAndValueSET + attributes = append(attributes, template.Attributes...) + + if len(extensions) > 0 { + // specifiedExtensions contains all the extensions that we + // found specified via template.Attributes. + specifiedExtensions := make(map[string]bool) + + for _, atvSet := range template.Attributes { + if !atvSet.Type.Equal(oidExtensionRequest) { + continue + } + + for _, atvs := range atvSet.Value { + for _, atv := range atvs { + specifiedExtensions[atv.Type.String()] = true + } + } + } + + atvs := make([]pkix.AttributeTypeAndValue, 0, len(extensions)) + for _, e := range extensions { + if specifiedExtensions[e.Id.String()] { + // Attributes already contained a value for + // this extension and it takes priority. + continue + } + + atvs = append(atvs, pkix.AttributeTypeAndValue{ + // There is no place for the critical flag in a CSR. + Type: e.Id, + Value: e.Value, + }) + } + + // Append the extensions to an existing attribute if possible. + appended := false + for _, atvSet := range attributes { + if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 { + continue + } + + atvSet.Value[0] = append(atvSet.Value[0], atvs...) + appended = true + break + } + + // Otherwise, add a new attribute for the extensions. + if !appended { + attributes = append(attributes, pkix.AttributeTypeAndValueSET{ + Type: oidExtensionRequest, + Value: [][]pkix.AttributeTypeAndValue{ + atvs, + }, + }) + } + } + + asn1Subject := template.RawSubject + if len(asn1Subject) == 0 { + asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) + if err != nil { + return + } + } + + rawAttributes, err := newRawAttributes(attributes) + if err != nil { + return + } + + tbsCSR := tbsCertificateRequest{ + Version: 0, // PKCS #10, RFC 2986 + Subject: asn1.RawValue{FullBytes: asn1Subject}, + PublicKey: publicKeyInfo{ + Algorithm: publicKeyAlgorithm, + PublicKey: asn1.BitString{ + Bytes: publicKeyBytes, + BitLength: len(publicKeyBytes) * 8, + }, + }, + RawAttributes: rawAttributes, + } + + tbsCSRContents, err := asn1.Marshal(tbsCSR) + if err != nil { + return + } + tbsCSR.Raw = tbsCSRContents + + digest := hash(hashFunc, tbsCSRContents) + + var signature []byte + signature, err = key.Sign(rand, digest, hashFunc) + if err != nil { + return + } + + return asn1.Marshal(certificateRequest{ + TBSCSR: tbsCSR, + SignatureAlgorithm: sigAlgo, + SignatureValue: asn1.BitString{ + Bytes: signature, + BitLength: len(signature) * 8, + }, + }) +} + +// ParseCertificateRequest parses a single certificate request from the +// given ASN.1 DER data. +func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) { + var csr certificateRequest + + rest, err := asn1.Unmarshal(asn1Data, &csr) + if err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + + return parseCertificateRequest(&csr) +} + +func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) { + out := &CertificateRequest{ + Raw: in.Raw, + RawTBSCertificateRequest: in.TBSCSR.Raw, + RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw, + RawSubject: in.TBSCSR.Subject.FullBytes, + + Signature: in.SignatureValue.RightAlign(), + SignatureAlgorithm: GetSignatureAlgorithmFromAI(in.SignatureAlgorithm), + + PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm), + + Version: in.TBSCSR.Version, + Attributes: parseRawAttributes(in.TBSCSR.RawAttributes), + } + + var err error + out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCSR.PublicKey) + if err != nil { + return nil, err + } + + var subject pkix.RDNSequence + if rest, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after X.509 Subject") + } + + out.Subject.FillFromRDNSequence(&subject) + + if out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil { + return nil, err + } + + for _, extension := range out.Extensions { + if extension.Id.Equal(oidExtensionSubjectAltName) { + out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(extension.Value) + if err != nil { + return nil, err + } + } + } + + return out, nil +} + +// CheckSignature reports whether the signature on c is valid. +func (c *CertificateRequest) CheckSignature() error { + return CheckSignatureFromKey(c.PublicKey, c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature) +} diff --git a/vendor/github.com/zmap/zlint/v3/.goreleaser.yml b/vendor/github.com/zmap/zlint/v3/.goreleaser.yml new file mode 100644 index 0000000000..2b84be004b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/.goreleaser.yml @@ -0,0 +1,30 @@ +project_name: zlint +before: + hooks: + - go mod tidy +builds: + - + main: ./cmd/zlint/main.go + binary: zlint + env: + - CGO_ENABLED=0 + goos: + - linux + - freebsd + - windows + - darwin + goarch: + - amd64 +archives: + - + wrap_in_directory: true + replacements: + darwin: Darwin + linux: Linux + windows: Windows + amd64: x86_64 +snapshot: + name_template: "{{ .Tag }}-next" +release: + draft: true + prerelease: auto diff --git a/vendor/github.com/zmap/zlint/v3/LICENSE b/vendor/github.com/zmap/zlint/v3/LICENSE new file mode 100644 index 0000000000..b209ae0fca --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Regents of the University of Michigan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/zmap/zlint/v3/lint/base.go b/vendor/github.com/zmap/zlint/v3/lint/base.go new file mode 100644 index 0000000000..efecfa97e1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lint/base.go @@ -0,0 +1,96 @@ +package lint + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/util" +) + +// LintInterface is implemented by each Lint. +type LintInterface interface { + // Initialize runs once per-lint. It is called during RegisterLint(). + Initialize() error + + // CheckApplies runs once per certificate. It returns true if the Lint should + // run on the given certificate. If CheckApplies returns false, the Lint + // result is automatically set to NA without calling CheckEffective() or + // Run(). + CheckApplies(c *x509.Certificate) bool + + // Execute() is the body of the lint. It is called for every certificate for + // which CheckApplies() returns true. + Execute(c *x509.Certificate) *LintResult +} + +// A Lint struct represents a single lint, e.g. +// "e_basic_constraints_not_critical". It contains an implementation of LintInterface. +type Lint struct { + + // Name is a lowercase underscore-separated string describing what a given + // Lint checks. If Name beings with "w", the lint MUST NOT return Error, only + // Warn. If Name beings with "e", the Lint MUST NOT return Warn, only Error. + Name string `json:"name,omitempty"` + + // A human-readable description of what the Lint checks. Usually copied + // directly from the CA/B Baseline Requirements or RFC 5280. + Description string `json:"description,omitempty"` + + // The source of the check, e.g. "BRs: 6.1.6" or "RFC 5280: 4.1.2.6". + Citation string `json:"citation,omitempty"` + + // Programmatic source of the check, BRs, RFC5280, or ZLint + Source LintSource `json:"source"` + + // Lints automatically returns NE for all certificates where CheckApplies() is + // true but with NotBefore < EffectiveDate. This check is bypassed if + // EffectiveDate is zero. + EffectiveDate time.Time `json:"-"` + + // The implementation of the lint logic. + Lint LintInterface `json:"-"` +} + +// CheckEffective returns true if c was issued on or after the EffectiveDate. If +// EffectiveDate is zero, CheckEffective always returns true. +func (l *Lint) CheckEffective(c *x509.Certificate) bool { + if l.EffectiveDate.IsZero() || !l.EffectiveDate.After(c.NotBefore) { + return true + } + return false +} + +// Execute runs the lint against a certificate. For lints that are +// sourced from the CA/B Forum Baseline Requirements, we first determine +// if they are within the purview of the BRs. See LintInterface for details +// about the other methods called. The ordering is as follows: +// +// CheckApplies() +// CheckEffective() +// Execute() +func (l *Lint) Execute(cert *x509.Certificate) *LintResult { + if l.Source == CABFBaselineRequirements && !util.IsServerAuthCert(cert) { + return &LintResult{Status: NA} + } + if !l.Lint.CheckApplies(cert) { + return &LintResult{Status: NA} + } else if !l.CheckEffective(cert) { + return &LintResult{Status: NE} + } + res := l.Lint.Execute(cert) + return res +} diff --git a/vendor/github.com/zmap/zlint/v3/lint/registration.go b/vendor/github.com/zmap/zlint/v3/lint/registration.go new file mode 100644 index 0000000000..694ae1faa1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lint/registration.go @@ -0,0 +1,351 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package lint + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "regexp" + "sort" + "strings" + "sync" +) + +// FilterOptions is a struct used by Registry.Filter to create a sub registry +// containing only lints that meet the filter options specified. +// +// Source based exclusion/inclusion is evaluated before Lint name based +// exclusion/inclusion. In both cases exclusion is processed before inclusion. +// +// Only one of NameFilter or IncludeNames/ExcludeNames can be provided at +// a time. +type FilterOptions struct { + // NameFilter is a regexp used to filter lints by their name. It is mutually + // exclusive with IncludeNames and ExcludeNames. + NameFilter *regexp.Regexp + // IncludeNames is a case sensitive list of lint names to include in the + // registry being filtered. + IncludeNames []string + // ExcludeNames is a case sensitive list of lint names to exclude from the + // registry being filtered. + ExcludeNames []string + // IncludeSource is a SourceList of LintSource's to be included in the + // registry being filtered. + IncludeSources SourceList + // ExcludeSources is a SourceList of LintSources's to be excluded in the + // registry being filtered. + ExcludeSources SourceList +} + +// Empty returns true if the FilterOptions is empty and does not specify any +// elements to filter by. +func (opts FilterOptions) Empty() bool { + return opts.NameFilter == nil && + len(opts.IncludeNames) == 0 && + len(opts.ExcludeNames) == 0 && + len(opts.IncludeSources) == 0 && + len(opts.ExcludeSources) == 0 +} + +// Registry is an interface describing a collection of registered lints. +// A Registry instance can be given to zlint.LintCertificateEx() to control what +// lints are run for a given certificate. +// +// Typically users will interact with the global Registry returned by +// GlobalRegistry(), or a filtered Registry created by applying FilterOptions to +// the GlobalRegistry()'s Filter function. +type Registry interface { + // Names returns a list of all of the lint names that have been registered + // in string sorted order. + Names() []string + // Sources returns a SourceList of registered LintSources. The list is not + // sorted but can be sorted by the caller with sort.Sort() if required. + Sources() SourceList + // ByName returns a pointer to the registered lint with the given name, or nil + // if there is no such lint registered in the registry. + ByName(name string) *Lint + // BySource returns a list of registered lints that have the same LintSource as + // provided (or nil if there were no such lints in the registry). + BySource(s LintSource) []*Lint + // Filter returns a new Registry containing only lints that match the + // FilterOptions criteria. + Filter(opts FilterOptions) (Registry, error) + // WriteJSON writes a description of each registered lint as + // a JSON object, one object per line, to the provided writer. + WriteJSON(w io.Writer) +} + +// registryImpl implements the Registry interface to provide a global collection +// of Lints that have been registered. +type registryImpl struct { + sync.RWMutex + // lintsByName is a map of all registered lints by name. + lintsByName map[string]*Lint + // lintNames is a sorted list of all of the registered lint names. It is + // equivalent to collecting the keys from lintsByName into a slice and sorting + // them lexicographically. + lintNames []string + // lintsBySource is a map of all registered lints by source category. Lints + // are added to the lintsBySource map by RegisterLint. + lintsBySource map[LintSource][]*Lint +} + +var ( + // errNilLint is returned from registry.Register if the provided lint was nil. + errNilLint = errors.New("can not register a nil lint") + // errNilLintPtr is returned from registry.Register if the provided lint had + // a nil Lint field. + errNilLintPtr = errors.New("can not register a lint with a nil Lint pointer") + // errEmptyName is returned from registry.Register if the provided lint had an + // empty Name field. + errEmptyName = errors.New("can not register a lint with an empty Name") +) + +// errDuplicateName is returned from registry.Register if the provided lint had +// a Name field matching a lint that was previously registered. +type errDuplicateName struct { + lintName string +} + +func (e errDuplicateName) Error() string { + return fmt.Sprintf( + "can not register lint with name %q - it has already been registered", + e.lintName) +} + +// errBadInit is returned from registry.Register if the provided lint's +// Initialize function returned an error. +type errBadInit struct { + lintName string + err error +} + +func (e errBadInit) Error() string { + return fmt.Sprintf( + "failed to register lint with name %q - failed to Initialize: %q", + e.lintName, e.err) +} + +// register adds the provided lint to the Registry. If initialize is true then +// the lint's Initialize() function will be called before registering the lint. +// +// An error is returned if the lint or lint's Lint pointer is nil, if the Lint +// has an empty Name or if the Name was previously registered. +func (r *registryImpl) register(l *Lint, initialize bool) error { + if l == nil { + return errNilLint + } + if l.Lint == nil { + return errNilLintPtr + } + if l.Name == "" { + return errEmptyName + } + if existing := r.ByName(l.Name); existing != nil { + return &errDuplicateName{l.Name} + } + if initialize { + if err := l.Lint.Initialize(); err != nil { + return &errBadInit{l.Name, err} + } + } + r.Lock() + defer r.Unlock() + r.lintNames = append(r.lintNames, l.Name) + r.lintsByName[l.Name] = l + r.lintsBySource[l.Source] = append(r.lintsBySource[l.Source], l) + sort.Strings(r.lintNames) + return nil +} + +// ByName returns the Lint previously registered under the given name with +// Register, or nil if no matching lint name has been registered. +func (r *registryImpl) ByName(name string) *Lint { + r.RLock() + defer r.RUnlock() + return r.lintsByName[name] +} + +// Names returns a list of all of the lint names that have been registered +// in string sorted order. +func (r *registryImpl) Names() []string { + r.RLock() + defer r.RUnlock() + return r.lintNames +} + +// BySource returns a list of registered lints that have the same LintSource as +// provided (or nil if there were no such lints). +func (r *registryImpl) BySource(s LintSource) []*Lint { + r.RLock() + defer r.RUnlock() + return r.lintsBySource[s] +} + +// Sources returns a SourceList of registered LintSources. The list is not +// sorted but can be sorted by the caller with sort.Sort() if required. +func (r *registryImpl) Sources() SourceList { + r.RLock() + defer r.RUnlock() + var results SourceList + for k := range r.lintsBySource { + results = append(results, k) + } + return results +} + +// lintNamesToMap converts a list of lit names into a bool hashmap useful for +// filtering. If any of the lint names are not known by the registry an error is +// returned. +func (r *registryImpl) lintNamesToMap(names []string) (map[string]bool, error) { + if len(names) == 0 { + return nil, nil + } + + namesMap := make(map[string]bool, len(names)) + for _, n := range names { + n = strings.TrimSpace(n) + if l := r.ByName(n); l == nil { + return nil, fmt.Errorf("unknown lint name %q", n) + } + namesMap[n] = true + } + return namesMap, nil +} + +func sourceListToMap(sources SourceList) map[LintSource]bool { + if len(sources) == 0 { + return nil + } + sourceMap := make(map[LintSource]bool, len(sources)) + for _, s := range sources { + sourceMap[s] = true + } + return sourceMap +} + +// Filter creates a new Registry with only the lints that meet the FilterOptions +// criteria included. +// +// FilterOptions are applied in the following order of precedence: +// ExcludeSources > IncludeSources > NameFilter > ExcludeNames > IncludeNames +func (r *registryImpl) Filter(opts FilterOptions) (Registry, error) { + // If there's no filtering to be done, return the existing Registry. + if opts.Empty() { + return r, nil + } + + filteredRegistry := NewRegistry() + + sourceExcludes := sourceListToMap(opts.ExcludeSources) + sourceIncludes := sourceListToMap(opts.IncludeSources) + + nameExcludes, err := r.lintNamesToMap(opts.ExcludeNames) + if err != nil { + return nil, err + } + nameIncludes, err := r.lintNamesToMap(opts.IncludeNames) + if err != nil { + return nil, err + } + + if opts.NameFilter != nil && (len(nameExcludes) != 0 || len(nameIncludes) != 0) { + return nil, errors.New( + "FilterOptions.NameFilter cannot be used at the same time as " + + "FilterOptions.ExcludeNames or FilterOptions.IncludeNames") + } + + for _, name := range r.Names() { + l := r.ByName(name) + + if sourceExcludes != nil && sourceExcludes[l.Source] { + continue + } + if sourceIncludes != nil && !sourceIncludes[l.Source] { + continue + } + if opts.NameFilter != nil && !opts.NameFilter.MatchString(name) { + continue + } + if nameExcludes != nil && nameExcludes[name] { + continue + } + if nameIncludes != nil && !nameIncludes[name] { + continue + } + + // when adding lints to a filtered registry we do not want Initialize() to + // be called a second time, so provide false as the initialize argument. + if err := filteredRegistry.register(l, false); err != nil { + return nil, err + } + } + + return filteredRegistry, nil +} + +// WriteJSON writes a description of each registered lint as +// a JSON object, one object per line, to the provided writer. +func (r *registryImpl) WriteJSON(w io.Writer) { + enc := json.NewEncoder(w) + enc.SetEscapeHTML(false) + for _, name := range r.Names() { + _ = enc.Encode(r.ByName(name)) + } +} + +// NewRegistry constructs a Registry implementation that can be used to register +// lints. +func NewRegistry() *registryImpl { + return ®istryImpl{ + lintsByName: make(map[string]*Lint), + lintsBySource: make(map[LintSource][]*Lint), + } +} + +// globalRegistry is the Registry used by all loaded lints that call +// RegisterLint(). +var globalRegistry *registryImpl = NewRegistry() + +// RegisterLint must be called once for each lint to be executed. Normally, +// RegisterLint is called from the Go init() function of a lint implementation. +// +// RegsterLint will call l.Lint's Initialize() function as part of the +// registration process. +// +// IMPORTANT: RegisterLint will panic if given a nil lint, or a lint with a nil +// Lint pointer, or if the lint's Initialize function errors, or if the lint +// name matches a previously registered lint's name. These conditions all +// indicate a bug that should be addressed by a developer. +func RegisterLint(l *Lint) { + // RegisterLint always sets initialize to true. It's assumed this is called by + // the package init() functions and therefore must be doing the first + // initialization of a lint. + if err := globalRegistry.register(l, true); err != nil { + panic(fmt.Sprintf("RegisterLint error: %v\n", err.Error())) + } +} + +// GlobalRegistry is the Registry used by RegisterLint and contains all of the +// lints that are loaded. +// +// If you want to run only a subset of the globally registered lints use +// GloablRegistry().Filter with FilterOptions to create a filtered +// Registry. +func GlobalRegistry() Registry { + return globalRegistry +} diff --git a/vendor/github.com/zmap/zlint/v3/lint/result.go b/vendor/github.com/zmap/zlint/v3/lint/result.go new file mode 100644 index 0000000000..71b43be9c6 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lint/result.go @@ -0,0 +1,106 @@ +package lint + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/json" + "fmt" + "strings" +) + +// LintStatus is an enum returned by lints inside of a LintResult. +type LintStatus int + +// Known LintStatus values +const ( + // Unused / unset LintStatus + Reserved LintStatus = 0 + + // Not Applicable + NA LintStatus = 1 + + // Not Effective + NE LintStatus = 2 + + Pass LintStatus = 3 + Notice LintStatus = 4 + Warn LintStatus = 5 + Error LintStatus = 6 + Fatal LintStatus = 7 +) + +var ( + // StatusLabelToLintStatus is used to work backwards from + // a LintStatus.String() to the LintStatus. This is used by + // LintStatus.Unmarshal. + StatusLabelToLintStatus = map[string]LintStatus{ + Reserved.String(): Reserved, + NA.String(): NA, + NE.String(): NE, + Pass.String(): Pass, + Notice.String(): Notice, + Warn.String(): Warn, + Error.String(): Error, + Fatal.String(): Fatal, + } +) + +// LintResult contains a LintStatus, and an optional human-readable description. +// The output of a lint is a LintResult. +type LintResult struct { + Status LintStatus `json:"result"` + Details string `json:"details,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +func (e LintStatus) MarshalJSON() ([]byte, error) { + s := e.String() + return json.Marshal(s) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (e *LintStatus) UnmarshalJSON(data []byte) error { + key := strings.ReplaceAll(string(data), `"`, "") + if status, ok := StatusLabelToLintStatus[key]; ok { + *e = status + } else { + return fmt.Errorf("bad LintStatus JSON value: %s", string(data)) + } + return nil +} + +// String returns the canonical representation of a LintStatus as a string. +func (e LintStatus) String() string { + switch e { + case Reserved: + return "reserved" + case NA: + return "NA" + case NE: + return "NE" + case Pass: + return "pass" + case Notice: + return "info" + case Warn: + return "warn" + case Error: + return "error" + case Fatal: + return "fatal" + default: + return "" + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lint/source.go b/vendor/github.com/zmap/zlint/v3/lint/source.go new file mode 100644 index 0000000000..226a7c0d5e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lint/source.go @@ -0,0 +1,129 @@ +package lint + +import ( + "encoding/json" + "fmt" + "strings" +) + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// LintSource is a type representing a known lint source that lints cite +// requirements from. +type LintSource string + +const ( + UnknownLintSource LintSource = "Unknown" + RFC5280 LintSource = "RFC5280" + RFC5480 LintSource = "RFC5480" + RFC5891 LintSource = "RFC5891" + CABFBaselineRequirements LintSource = "CABF_BR" + CABFEVGuidelines LintSource = "CABF_EV" + MozillaRootStorePolicy LintSource = "Mozilla" + AppleRootStorePolicy LintSource = "Apple" + Community LintSource = "Community" + EtsiEsi LintSource = "ETSI_ESI" +) + +// UnmarshalJSON implements the json.Unmarshaler interface. It ensures that the +// unmarshaled value is a known LintSource. +func (s *LintSource) UnmarshalJSON(data []byte) error { + var throwAway string + if err := json.Unmarshal(data, &throwAway); err != nil { + return err + } + + switch LintSource(throwAway) { + case RFC5280, RFC5480, RFC5891, CABFBaselineRequirements, CABFEVGuidelines, MozillaRootStorePolicy, AppleRootStorePolicy, Community, EtsiEsi: + *s = LintSource(throwAway) + return nil + default: + *s = UnknownLintSource + return fmt.Errorf("unknown LintSource value %q", throwAway) + } +} + +// FromString sets the LintSource value based on the source string provided +// (case sensitive). If the src string does not match any of the known +// LintSource's then s is set to the UnknownLintSource. +func (s *LintSource) FromString(src string) { + // Start with the unknown lint source + *s = UnknownLintSource + // Trim space and try to match a known value + src = strings.TrimSpace(src) + switch LintSource(src) { + case RFC5280: + *s = RFC5280 + case RFC5480: + *s = RFC5480 + case RFC5891: + *s = RFC5891 + case CABFBaselineRequirements: + *s = CABFBaselineRequirements + case CABFEVGuidelines: + *s = CABFEVGuidelines + case MozillaRootStorePolicy: + *s = MozillaRootStorePolicy + case AppleRootStorePolicy: + *s = AppleRootStorePolicy + case Community: + *s = Community + case EtsiEsi: + *s = EtsiEsi + } +} + +// SourceList is a slice of LintSources that can be sorted. +type SourceList []LintSource + +// Len returns the length of the list. +func (l SourceList) Len() int { + return len(l) +} + +// Swap swaps the LintSource at index i and j in the list. +func (l SourceList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +// Less compares the LintSources at index i and j lexicographically. +func (l SourceList) Less(i, j int) bool { + return l[i] < l[j] +} + +// FromString populates a SourceList (replacing any existing content) with the +// comma separated list of sources provided in raw. If any of the comma +// separated values are not known LintSource's an error is returned. +func (l *SourceList) FromString(raw string) error { + // Start with an empty list + *l = SourceList{} + + values := strings.Split(raw, ",") + for _, val := range values { + val = strings.TrimSpace(val) + if val == "" { + continue + } + // Populate the LintSource with the trimmed value. + var src LintSource + src.FromString(val) + // If the LintSource is UnknownLintSource then return an error. + if src == UnknownLintSource { + return fmt.Errorf("unknown lint source in list: %q", val) + } + *l = append(*l, src) + } + return nil +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go new file mode 100644 index 0000000000..cf77a6f20a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go @@ -0,0 +1,157 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package apple + +import ( + "fmt" + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/ct" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sctPolicyCount struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ct_sct_policy_count_unsatisfied", + Description: "Check if certificate has enough embedded SCTs to meet Apple CT Policy", + Citation: "https://support.apple.com/en-us/HT205280", + Source: lint.AppleRootStorePolicy, + EffectiveDate: util.AppleCTPolicyDate, + Lint: &sctPolicyCount{}, + }) +} + +// Initialize for a sctPolicyCount instance does nothing. +func (l *sctPolicyCount) Initialize() error { + return nil +} + +// CheckApplies returns true for any subscriber certificates that are not +// precertificates (e.g. that do not have the CT poison extension defined in RFC +// 6962. +func (l *sctPolicyCount) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && !util.IsExtInCert(c, util.CtPoisonOID) +} + +// Execute checks if the provided certificate has embedded SCTs from +// a sufficient number of unique CT logs to meet Apple's CT log policy[0], +// effective Oct 15th, 2018. +// +// The number of required SCTs from different logs is calculated based on the +// Certificate's lifetime. If the number of required SCTs are not embedded in +// the certificate a Notice level lint.LintResult is returned. +// +// | Certificate lifetime | # of SCTs from separate logs | +// ------------------------------------------------------- +// | Less than 15 months | 2 | +// | 15 to 27 months | 3 | +// | 27 to 39 months | 4 | +// | More than 39 months | 5 | +// ------------------------------------------------------- +// +// Important note 1: We can't know whether additional SCTs were presented +// alongside the certificate via OCSP stapling. This linter assumes only +// embedded SCTs are used and ignores the portion of the Apple policy related to +// SCTs delivered via OCSP. This is one limitation that restricts the linter's +// findings to Notice level. See more background discussion in Issue 226[1]. +// +// Important note 2: The linter doesn't maintain a list of Apple's trusted +// logs. The SCTs embedded in the certificate may not be from log's Apple +// actually trusts. Similarly the embedded SCT signatures are not validated +// in any way. +// +// [0]: https://support.apple.com/en-us/HT205280 +// [1]: https://github.com/zmap/zlint/issues/226 +func (l *sctPolicyCount) Execute(c *x509.Certificate) *lint.LintResult { + // Determine the required number of SCTs from separate logs + expected := appleCTPolicyExpectedSCTs(c) + + // If there are no SCTs then the job is easy. We can return a Notice + // lint.LintResult immediately. + if len(c.SignedCertificateTimestampList) == 0 && expected > 0 { + return &lint.LintResult{ + Status: lint.Notice, + Details: fmt.Sprintf( + "Certificate had 0 embedded SCTs. Browser policy may require %d for this certificate.", + expected), + } + } + + // Build a map from LogID to SCT so that we can count embedded SCTs by unique + // log. + sctsByLogID := make(map[ct.SHA256Hash]*ct.SignedCertificateTimestamp) + for _, sct := range c.SignedCertificateTimestampList { + sctsByLogID[sct.LogID] = sct + } + + // If the number of embedded SCTs from separate logs meets expected return + // a lint.Pass result. + if len(sctsByLogID) >= expected { + return &lint.LintResult{Status: lint.Pass} + } + + // Otherwise return a Notice result - there weren't enough SCTs embedded in + // the certificate. More must be provided by OCSP stapling if the certificate + // is to meet Apple's CT policy. + return &lint.LintResult{ + Status: lint.Notice, + Details: fmt.Sprintf( + "Certificate had %d embedded SCTs from distinct log IDs. "+ + "Browser policy may require %d for this certificate.", + len(sctsByLogID), expected), + } +} + +// appleCTPolicyExpectedSCTs returns a count of the number of SCTs expected to +// be embedded in the given certificate based on its lifetime. +// +// For this function the relevant portion of Apple's policy is the table +// "Number of embedded SCTs based on certificate lifetime" (Also reproduced in +// the `Execute` godoc comment). +func appleCTPolicyExpectedSCTs(cert *x509.Certificate) int { + // Lifetime is relative to the certificate's NotBefore date. + start := cert.NotBefore + + // Thresholds is an ordered array of lifetime periods and their expected # of + // SCTs. A lifetime period is defined by the cutoff date relative to the + // start of the certificate's lifetime. + thresholds := []struct { + CutoffDate time.Time + Expected int + }{ + // Start date ... 15 months + {CutoffDate: start.AddDate(0, 15, 0), Expected: 2}, + // Start date ... 27 months + {CutoffDate: start.AddDate(0, 27, 0), Expected: 3}, + // Start date ... 39 months + {CutoffDate: start.AddDate(0, 39, 0), Expected: 4}, + } + + // If the certificate's lifetime falls into any of the cutoff date ranges then + // we expect that range's expected # of SCTs for this certificate. This loop + // assumes the `thresholds` list is sorted in ascending order. + for _, threshold := range thresholds { + if cert.NotAfter.Before(threshold.CutoffDate) { + return threshold.Expected + } + } + + // The certificate had a validity > 39 months. + return 5 +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go new file mode 100644 index 0000000000..b6077bff79 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go @@ -0,0 +1,61 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package apple + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type serverCertValidityTooLong struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_tls_server_cert_valid_time_longer_than_398_days", + Description: "TLS server certificates issued on or after September 1, 2020 " + + "00:00 GMT/UTC must not have a validity period greater than 398 days", + Citation: "https://support.apple.com/en-us/HT211025", + Source: lint.AppleRootStorePolicy, + EffectiveDate: util.AppleReducedLifetimeDate, + Lint: &serverCertValidityTooLong{}, + }) +} + +func (l *serverCertValidityTooLong) Initialize() error { + return nil +} + +func (l *serverCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *serverCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + // "TLS server certificates issued on or after September 1, 2020 00:00 GMT/UTC + // must not have a validity period greater than 398 days." + maxValidity := 398 * appleDayLength + + // RFC 5280, section 4.1.2.5: "The validity period for a certificate is the period + // of time from notBefore through notAfter, inclusive." + certValidity := c.NotAfter.Add(1 * time.Second).Sub(c.NotBefore) + + if certValidity > maxValidity { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go new file mode 100644 index 0000000000..26a483fbe6 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go @@ -0,0 +1,67 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package apple + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type serverCertValidityAlmostTooLong struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_tls_server_cert_valid_time_longer_than_397_days", + Description: "TLS server certificates issued on or after September 1, 2020 " + + "00:00 GMT/UTC should not have a validity period greater than 397 days", + Citation: "https://support.apple.com/en-us/HT211025", + Source: lint.AppleRootStorePolicy, + EffectiveDate: util.AppleReducedLifetimeDate, + Lint: &serverCertValidityAlmostTooLong{}, + }) +} + +func (l *serverCertValidityAlmostTooLong) Initialize() error { + return nil +} + +func (l *serverCertValidityAlmostTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *serverCertValidityAlmostTooLong) Execute(c *x509.Certificate) *lint.LintResult { + // "We recommend that certificates be issued with a maximum validity of 397 days." + warnValidity := 397 * appleDayLength + + // RFC 5280, section 4.1.2.5: "The validity period for a certificate is the period + // of time from notBefore through notAfter, inclusive." + certValidity := c.NotAfter.Add(1 * time.Second).Sub(c.NotBefore) + + if certValidity > warnValidity { + return &lint.LintResult{ + // RFC 2119 has SHOULD and RECOMMENDED as equal. Since Apple recommends + // 397 days we treat this as a lint.Warn result as a violation of + // a SHOULD. + Status: lint.Warn, + Details: "Apple recommends that certificates be issued with a maximum " + + "validity of 397 days.", + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/time.go b/vendor/github.com/zmap/zlint/v3/lints/apple/time.go new file mode 100644 index 0000000000..cd56e87903 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/time.go @@ -0,0 +1,13 @@ +package apple + +import "time" + +// In the context of a root policy update on trusted certificate lifetimes[0] +// Apple provided an unambiguous definition for the length of a day: +// "398 days is measured with a day being equal to 86,400 seconds. Any time +// greater than this indicates an additional day of validity." +// +// We provide that value as a constant here for lints to use. +// +// [0]: https://support.apple.com/en-us/HT211025 +var appleDayLength = 86400 * time.Second diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go new file mode 100644 index 0000000000..e5918f29f0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go @@ -0,0 +1,50 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caCommonNameMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_common_name_missing", + Description: "CA Certificates common name MUST be included.", + Citation: "BRs: 7.1.4.3.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV148Date, + Lint: &caCommonNameMissing{}, + }) +} + +func (l *caCommonNameMissing) Initialize() error { + return nil +} + +func (l *caCommonNameMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsCACert(c) +} + +func (l *caCommonNameMissing) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName == "" { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go new file mode 100644 index 0000000000..6fa2acbf7a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go @@ -0,0 +1,63 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caCountryNameInvalid struct{} + +/************************************************ +BRs: 7.1.2.1e +The Certificate Subject MUST contain the following: +‐ countryName (OID 2.5.4.6). +This field MUST contain the two‐letter ISO 3166‐1 country code for the country +in which the CA’s place of business is located. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_country_name_invalid", + Description: "Root and Subordinate CA certificates MUST have a two-letter country code specified in ISO 3166-1", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caCountryNameInvalid{}, + }) +} + +func (l *caCountryNameInvalid) Initialize() error { + return nil +} + +func (l *caCountryNameInvalid) CheckApplies(c *x509.Certificate) bool { + return c.IsCA +} + +func (l *caCountryNameInvalid) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.Country != nil { + for _, j := range c.Subject.Country { + if !util.IsISOCountryCode(j) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.NA} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go new file mode 100644 index 0000000000..3472daa21a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caCountryNameMissing struct{} + +/************************************************ +BRs: 7.1.2.1e +The Certificate Subject MUST contain the following: +‐ countryName (OID 2.5.4.6). +This field MUST contain the two‐letter ISO 3166‐1 country code for the country +in which the CA’s place of business is located. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_country_name_missing", + Description: "Root and Subordinate CA certificates MUST have a countryName present in subject information", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caCountryNameMissing{}, + }) +} + +func (l *caCountryNameMissing) Initialize() error { + return nil +} + +func (l *caCountryNameMissing) CheckApplies(c *x509.Certificate) bool { + return c.IsCA +} + +func (l *caCountryNameMissing) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.Country != nil && c.Subject.Country[0] != "" { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go new file mode 100644 index 0000000000..d842f47126 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go @@ -0,0 +1,57 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caCRLSignNotSet struct{} + +/************************************************ +BRs: 7.1.2.1b +This extension MUST be present and MUST be marked critical. Bit positions for +keyCertSign and cRLSign MUST be set. If the Root CA Private Key is used for +signing OCSP responses, then the digitalSignature bit MUST be set. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_crl_sign_not_set", + Description: "Root and Subordinate CA certificate keyUsage extension's crlSign bit MUST be set", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caCRLSignNotSet{}, + }) +} + +func (l *caCRLSignNotSet) Initialize() error { + return nil +} + +func (l *caCRLSignNotSet) CheckApplies(c *x509.Certificate) bool { + return c.IsCA && util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *caCRLSignNotSet) Execute(c *x509.Certificate) *lint.LintResult { + if c.KeyUsage&x509.KeyUsageCRLSign != 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go new file mode 100644 index 0000000000..057f420328 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caDigSignNotSet struct{} + +/************************************************ +BRs: 7.1.2.1b: Root CA Certificate keyUsage +This extension MUST be present and MUST be marked critical. Bit positions for keyCertSign and cRLSign MUST be set. +If the Root CA Private Key is used for signing OCSP responses, then the digitalSignature bit MUST be set. + +BRs: 7.1.2.2e: Subordinate CA Certificate keyUsage +This extension MUST be present and MUST be marked critical. Bit positions for keyCertSign and cRLSign MUST be set. +If the Root CA Private Key is used for signing OCSP responses, then the digitalSignature bit MUST be set. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_ca_digital_signature_not_set", + Description: "Root and Subordinate CA Certificates that wish to use their private key for signing OCSP responses will not be able to without their digital signature set", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caDigSignNotSet{}, + }) +} + +func (l *caDigSignNotSet) Initialize() error { + return nil +} + +func (l *caDigSignNotSet) CheckApplies(c *x509.Certificate) bool { + return c.IsCA && util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *caDigSignNotSet) Execute(c *x509.Certificate) *lint.LintResult { + if c.KeyUsage&x509.KeyUsageDigitalSignature != 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Notice} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go new file mode 100644 index 0000000000..838c0a7001 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go @@ -0,0 +1,63 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caIsCA struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_is_ca", + Description: "Root and Sub CA Certificate: The CA field MUST be set to true.", + Citation: "BRs: 7.1.2.1, BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caIsCA{}, + }) +} + +type basicConstraints struct { + IsCA bool `asn1:"optional"` + MaxPathLen int `asn1:"optional,default:-1"` +} + +func (l *caIsCA) Initialize() error { + return nil +} + +func (l *caIsCA) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) && c.KeyUsage&x509.KeyUsageCertSign != 0 && util.IsExtInCert(c, util.BasicConstOID) +} + +func (l *caIsCA) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.BasicConstOID) + var constraints basicConstraints + _, err := asn1.Unmarshal(e.Value, &constraints) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if constraints.IsCA { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go new file mode 100644 index 0000000000..86206b774f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caKeyCertSignNotSet struct{} + +/************************************************ +BRs: 7.1.2.1b +This extension MUST be present and MUST be marked critical. Bit positions for keyCertSign and cRLSign MUST be set. +If the Root CA Private Key is used for signing OCSP responses, then the digitalSignature bit MUST be set. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_key_cert_sign_not_set", + Description: "Root CA Certificate: Bit positions for keyCertSign and cRLSign MUST be set.", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caKeyCertSignNotSet{}, + }) +} + +func (l *caKeyCertSignNotSet) Initialize() error { + return nil +} + +func (l *caKeyCertSignNotSet) CheckApplies(c *x509.Certificate) bool { + return c.IsCA && util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *caKeyCertSignNotSet) Execute(c *x509.Certificate) *lint.LintResult { + if c.KeyUsage&x509.KeyUsageCertSign != 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go new file mode 100644 index 0000000000..4264e92e74 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caKeyUsageMissing struct{} + +/************************************************ +RFC 5280: 4.2.1.3 +Conforming CAs MUST include this extension in certificates that + contain public keys that are used to validate digital signatures on + other public key certificates or CRLs. When present, conforming CAs + SHOULD mark this extension as critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_key_usage_missing", + Description: "Root and Subordinate CA certificate keyUsage extension MUST be present", + Citation: "BRs: 7.1.2.1, RFC 5280: 4.2.1.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC3280Date, + Lint: &caKeyUsageMissing{}, + }) +} + +func (l *caKeyUsageMissing) Initialize() error { + return nil +} + +func (l *caKeyUsageMissing) CheckApplies(c *x509.Certificate) bool { + return c.IsCA +} + +func (l *caKeyUsageMissing) Execute(c *x509.Certificate) *lint.LintResult { + if c.KeyUsage != x509.KeyUsage(0) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go new file mode 100644 index 0000000000..375b22c532 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caKeyUsageNotCrit struct{} + +/************************************************ +BRs: 7.1.2.1b +This extension MUST be present and MUST be marked critical. Bit positions for keyCertSign and cRLSign MUST be set. +If the Root CA Private Key is used for signing OCSP responses, then the digitalSignature bit MUST be set. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_key_usage_not_critical", + Description: "Root and Subordinate CA certificate keyUsage extension MUST be marked as critical", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caKeyUsageNotCrit{}, + }) +} + +func (l *caKeyUsageNotCrit) Initialize() error { + return nil +} + +func (l *caKeyUsageNotCrit) CheckApplies(c *x509.Certificate) bool { + return c.IsCA && util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *caKeyUsageNotCrit) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.KeyUsageOID); e.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go new file mode 100644 index 0000000000..98bc43cf01 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go @@ -0,0 +1,55 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caOrganizationNameMissing struct{} + +/************************************************ +BRs: 7.1.2.1e +The Certificate Subject MUST contain the following: organizationName (OID 2.5.4.10): This field MUST be present and the contents MUST contain either the Subject CA’s name or DBA as verified under Section 3.2.2.2. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_organization_name_missing", + Description: "Root and Subordinate CA certificates MUST have a organizationName present in subject information", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caOrganizationNameMissing{}, + }) +} + +func (l *caOrganizationNameMissing) Initialize() error { + return nil +} + +func (l *caOrganizationNameMissing) CheckApplies(c *x509.Certificate) bool { + return c.IsCA +} + +func (l *caOrganizationNameMissing) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.Organization != nil && c.Subject.Organization[0] != "" { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go new file mode 100644 index 0000000000..992fe0ecbe --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go @@ -0,0 +1,52 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// If the Certificate asserts the policy identifier of 2.23.140.1.2.1, then it MUST NOT include +// organizationName, streetAddress, localityName, stateOrProvinceName, or postalCode in the Subject field. + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type certPolicyConflictsWithLocality struct{} + +func (l *certPolicyConflictsWithLocality) Initialize() error { + return nil +} + +func (l *certPolicyConflictsWithLocality) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRDomainValidatedOID) && !util.IsCACert(cert) +} + +func (l *certPolicyConflictsWithLocality) Execute(cert *x509.Certificate) *lint.LintResult { + if util.TypeInName(&cert.Subject, util.LocalityNameOID) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_dv_conflicts_with_locality", + Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, locality name MUST NOT be included in subject", + Citation: "BRs: 7.1.6.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &certPolicyConflictsWithLocality{}, + }) +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go new file mode 100644 index 0000000000..a9cc3f4c4a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type certPolicyConflictsWithOrg struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.1 +If the Certificate complies with these requirements and lacks Subject identity information that +has been verified in accordance with Section 3.2.2.1 or Section 3.2.3. +Such Certificates MUST NOT include organizationName, givenName, surname, +streetAddress, localityName, stateOrProvinceName, or postalCode in the Subject +field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_dv_conflicts_with_org", + Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, organization name MUST NOT be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &certPolicyConflictsWithOrg{}, + }) +} + +func (l *certPolicyConflictsWithOrg) Initialize() error { + return nil +} + +func (l *certPolicyConflictsWithOrg) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRDomainValidatedOID) && !util.IsCACert(cert) +} + +func (l *certPolicyConflictsWithOrg) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.OrganizationNameOID) { + out.Status = lint.Error + } else { + out.Status = lint.Pass + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go new file mode 100644 index 0000000000..5ad1b85a5b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type certPolicyConflictsWithPostal struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.1 +If the Certificate complies with these requirements and lacks Subject identity information that +has been verified in accordance with Section 3.2.2.1 or Section 3.2.3. +Such Certificates MUST NOT include organizationName, givenName, surname, +streetAddress, localityName, stateOrProvinceName, or postalCode in the Subject +field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_dv_conflicts_with_postal", + Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, postalCode MUST NOT be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &certPolicyConflictsWithPostal{}, + }) +} + +func (l *certPolicyConflictsWithPostal) Initialize() error { + return nil +} + +func (l *certPolicyConflictsWithPostal) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRDomainValidatedOID) && !util.IsCACert(cert) +} + +func (l *certPolicyConflictsWithPostal) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.PostalCodeOID) { + out.Status = lint.Error + } else { + out.Status = lint.Pass + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go new file mode 100644 index 0000000000..b0e4b7de36 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type certPolicyConflictsWithProvince struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.1 +If the Certificate complies with these requirements and lacks Subject identity information that +has been verified in accordance with Section 3.2.2.1 or Section 3.2.3. +Such Certificates MUST NOT include organizationName, givenName, surname, +streetAddress, localityName, stateOrProvinceName, or postalCode in the Subject +field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_dv_conflicts_with_province", + Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, stateOrProvinceName MUST NOT be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &certPolicyConflictsWithProvince{}, + }) +} + +func (l *certPolicyConflictsWithProvince) Initialize() error { + return nil +} + +func (l *certPolicyConflictsWithProvince) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRDomainValidatedOID) && !util.IsCACert(cert) +} + +func (l *certPolicyConflictsWithProvince) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.StateOrProvinceNameOID) { + out.Status = lint.Error + } else { + out.Status = lint.Pass + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go new file mode 100644 index 0000000000..ed217c4d48 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type certPolicyConflictsWithStreet struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.1 +If the Certificate complies with these requirements and lacks Subject identity information that +has been verified in accordance with Section 3.2.2.1 or Section 3.2.3. +Such Certificates MUST NOT include organizationName, givenName, surname, +streetAddress, localityName, stateOrProvinceName, or postalCode in the Subject +field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_dv_conflicts_with_street", + Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, streetAddress MUST NOT be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &certPolicyConflictsWithStreet{}, + }) +} + +func (l *certPolicyConflictsWithStreet) Initialize() error { + return nil +} + +func (l *certPolicyConflictsWithStreet) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRDomainValidatedOID) && !util.IsCACert(cert) +} + +func (l *certPolicyConflictsWithStreet) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.StreetAddressOID) { + out.Status = lint.Error + } else { + out.Status = lint.Pass + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go new file mode 100644 index 0000000000..5da044fe6b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go @@ -0,0 +1,63 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertPolicyRequiresPersonalName struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.3 +If the Certificate complies with these Requirements and includes Subject Identity Information +that is verified in accordance with Section 3.2.3. +Such Certificates MUST also include either organizationName or both givenName and +surname, localityName (to the extent such field is required under Section 7.1.4.2.2), +stateOrProvinceName (to the extent required under Section 7.1.4.2.2), and countryName in +the Subject field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_iv_requires_personal_name", + Description: "If certificate policy 2.23.140.1.2.3 is included, either organizationName or givenName and surname MUST be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV131Date, + Lint: &CertPolicyRequiresPersonalName{}, + }) +} + +func (l *CertPolicyRequiresPersonalName) Initialize() error { + return nil +} + +func (l *CertPolicyRequiresPersonalName) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRIndividualValidatedOID) && !util.IsCACert(cert) +} + +func (l *CertPolicyRequiresPersonalName) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.OrganizationNameOID) || (util.TypeInName(&cert.Subject, util.GivenNameOID) && util.TypeInName(&cert.Subject, util.SurnameOID)) { + out.Status = lint.Pass + } else { + out.Status = lint.Error + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go new file mode 100644 index 0000000000..fcfe4e6f69 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertPolicyRequiresOrg struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.2 +If the Certificate complies with these Requirements and includes Subject Identity Information +that is verified in accordance with Section 3.2.2.1. +Such Certificates MUST also include organizationName, localityName (to the extent such +field is required under Section 7.1.4.2.2), stateOrProvinceName (to the extent such field is +required under Section 7.1.4.2.2), and countryName in the Subject field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_ov_requires_org", + Description: "If certificate policy 2.23.140.1.2.2 is included, organizationName MUST be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &CertPolicyRequiresOrg{}, + }) +} + +func (l *CertPolicyRequiresOrg) Initialize() error { + return nil +} + +func (l *CertPolicyRequiresOrg) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BROrganizationValidatedOID) && !util.IsCACert(cert) +} + +func (l *CertPolicyRequiresOrg) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.OrganizationNameOID) { + out.Status = lint.Pass + } else { + out.Status = lint.Error + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go new file mode 100644 index 0000000000..5a05e49d39 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go @@ -0,0 +1,63 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertPolicyIVRequiresCountry struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.3 +If the Certificate complies with these Requirements and includes Subject Identity Information +that is verified in accordance with Section 3.2.3. +Such Certificates MUST also include either organizationName or both givenName and +surname, localityName (to the extent such field is required under Section 7.1.4.2.2), +stateOrProvinceName (to the extent required under Section 7.1.4.2.2), and countryName in +the Subject field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_policy_iv_requires_country", + Description: "If certificate policy 2.23.140.1.2.3 is included, countryName MUST be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV131Date, + Lint: &CertPolicyIVRequiresCountry{}, + }) +} + +func (l *CertPolicyIVRequiresCountry) Initialize() error { + return nil +} + +func (l *CertPolicyIVRequiresCountry) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRIndividualValidatedOID) +} + +func (l *CertPolicyIVRequiresCountry) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.CountryNameOID) { + out.Status = lint.Pass + } else { + out.Status = lint.Error + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go new file mode 100644 index 0000000000..23a7c48b95 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go @@ -0,0 +1,64 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertPolicyIVRequiresProvinceOrLocal struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.3 +If the Certificate complies with these Requirements and includes Subject Identity Information +that is verified in accordance with Section 3.2.3. +Such Certificates MUST also include either organizationName or both givenName and +surname, localityName (to the extent such field is required under Section 7.1.4.2.2), +stateOrProvinceName (to the extent required under Section 7.1.4.2.2), and countryName in +the Subject field. +************************************************/ +// 7.1.4.2.2 applies only to subscriber certificates. + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_policy_iv_requires_province_or_locality", + Description: "If certificate policy 2.23.140.1.2.3 is included, localityName or stateOrProvinceName MUST be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV131Date, + Lint: &CertPolicyIVRequiresProvinceOrLocal{}, + }) +} + +func (l *CertPolicyIVRequiresProvinceOrLocal) Initialize() error { + return nil +} + +func (l *CertPolicyIVRequiresProvinceOrLocal) CheckApplies(cert *x509.Certificate) bool { + return util.IsSubscriberCert(cert) && util.SliceContainsOID(cert.PolicyIdentifiers, util.BRIndividualValidatedOID) +} + +func (l *CertPolicyIVRequiresProvinceOrLocal) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.LocalityNameOID) || util.TypeInName(&cert.Subject, util.StateOrProvinceNameOID) { + out.Status = lint.Pass + } else { + out.Status = lint.Error + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go new file mode 100644 index 0000000000..fb8cae0cd4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertPolicyOVRequiresCountry struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.2 +If the Certificate complies with these Requirements and includes Subject Identity Information +that is verified in accordance with Section 3.2.2.1. +Such Certificates MUST also include organizationName, localityName (to the extent such +field is required under Section 7.1.4.2.2), stateOrProvinceName (to the extent such field is +required under Section 7.1.4.2.2), and countryName in the Subject field. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_policy_ov_requires_country", + Description: "If certificate policy 2.23.140.1.2.2 is included, countryName MUST be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &CertPolicyOVRequiresCountry{}, + }) +} + +func (l *CertPolicyOVRequiresCountry) Initialize() error { + return nil +} + +func (l *CertPolicyOVRequiresCountry) CheckApplies(cert *x509.Certificate) bool { + return util.SliceContainsOID(cert.PolicyIdentifiers, util.BROrganizationValidatedOID) +} + +func (l *CertPolicyOVRequiresCountry) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.CountryNameOID) { + out.Status = lint.Pass + } else { + out.Status = lint.Error + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go new file mode 100644 index 0000000000..7a219ddb31 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go @@ -0,0 +1,64 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertPolicyOVRequiresProvinceOrLocal struct{} + +/************************************************ +BRs: 7.1.6.4 +Certificate Policy Identifier: 2.23.140.1.2.2 +If the Certificate complies with these Requirements and includes Subject Identity Information +that is verified in accordance with Section 3.2.2.1. +Such Certificates MUST also include organizationName, localityName (to the extent such +field is required under Section 7.1.4.2.2), stateOrProvinceName (to the extent such field is +required under Section 7.1.4.2.2), and countryName in the Subject field. + +Note: 7.1.4.2.2 applies only to subscriber certificates. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_policy_ov_requires_province_or_locality", + Description: "If certificate policy 2.23.140.1.2.2 is included, localityName or stateOrProvinceName MUST be included in subject", + Citation: "BRs: 7.1.6.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &CertPolicyOVRequiresProvinceOrLocal{}, + }) +} + +func (l *CertPolicyOVRequiresProvinceOrLocal) Initialize() error { + return nil +} + +func (l *CertPolicyOVRequiresProvinceOrLocal) CheckApplies(cert *x509.Certificate) bool { + return util.IsSubscriberCert(cert) && util.SliceContainsOID(cert.PolicyIdentifiers, util.BROrganizationValidatedOID) +} + +func (l *CertPolicyOVRequiresProvinceOrLocal) Execute(cert *x509.Certificate) *lint.LintResult { + var out lint.LintResult + if util.TypeInName(&cert.Subject, util.LocalityNameOID) || util.TypeInName(&cert.Subject, util.StateOrProvinceNameOID) { + out.Status = lint.Pass + } else { + out.Status = lint.Error + } + return &out +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go new file mode 100644 index 0000000000..2ea2193c07 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/dsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type dsaParamsMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dsa_params_missing", + Description: "DSA: Certificates MUST include all domain parameters", + Citation: "BRs v1.7.0: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &dsaParamsMissing{}, + }) +} + +func (l *dsaParamsMissing) Initialize() error { + return nil +} + +func (l *dsaParamsMissing) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.DSA +} + +func (l *dsaParamsMissing) Execute(c *x509.Certificate) *lint.LintResult { + dsaKey, ok := c.PublicKey.(*dsa.PublicKey) + if !ok { + return &lint.LintResult{Status: lint.Fatal} + } + params := dsaKey.Parameters + if params.P.BitLen() == 0 || params.Q.BitLen() == 0 || params.G.BitLen() == 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go new file mode 100644 index 0000000000..838a6ef1a0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go @@ -0,0 +1,64 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "regexp" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameProperCharacters struct { + CompiledExpression *regexp.Regexp +} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_bad_character_in_label", + Description: "Characters in labels of DNSNames MUST be alphanumeric, - , _ or *", + Citation: "BRs: 7.1.4.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameProperCharacters{}, + }) +} + +func (l *DNSNameProperCharacters) Initialize() error { + const dnsNameRegexp = `^(\*\.)?(\?\.)*([A-Za-z0-9*_-]+\.)*[A-Za-z0-9*_-]*$` + var err error + l.CompiledExpression, err = regexp.Compile(dnsNameRegexp) + + return err +} + +func (l *DNSNameProperCharacters) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameProperCharacters) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + if !l.CompiledExpression.MatchString(c.Subject.CommonName) { + return &lint.LintResult{Status: lint.Error} + } + } + for _, dns := range c.DNSNames { + if !l.CompiledExpression.MatchString(dns) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go new file mode 100644 index 0000000000..3c9c6c26d4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go @@ -0,0 +1,67 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameLeftLabelWildcardCheck struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_left_label_wildcard_correct", + Description: "Wildcards in the left label of DNSName should only be *", + Citation: "BRs: 1.6.1, Wildcard Certificate and Wildcard Domain Name", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameLeftLabelWildcardCheck{}, + }) +} + +func (l *DNSNameLeftLabelWildcardCheck) Initialize() error { + return nil +} + +func (l *DNSNameLeftLabelWildcardCheck) CheckApplies(c *x509.Certificate) bool { + return true +} + +func wildcardInLeftLabelIncorrect(domain string) bool { + labels := strings.Split(domain, ".") + if len(labels) >= 1 { + leftLabel := labels[0] + if strings.Contains(leftLabel, "*") && leftLabel != "*" { + return true + } + } + return false +} + +func (l *DNSNameLeftLabelWildcardCheck) Execute(c *x509.Certificate) *lint.LintResult { + if wildcardInLeftLabelIncorrect(c.Subject.CommonName) { + return &lint.LintResult{Status: lint.Error} + } + for _, dns := range c.DNSNames { + if wildcardInLeftLabelIncorrect(dns) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go new file mode 100644 index 0000000000..bbf31a53ba --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type dnsNameContainsBareIANASuffix struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_contains_bare_iana_suffix", + Description: "DNSNames should not contain a bare IANA suffix.", + Citation: "BRs: 1.6.1, Base Domain Name", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &dnsNameContainsBareIANASuffix{}, + }) +} + +func (l *dnsNameContainsBareIANASuffix) Initialize() error { + return nil +} + +func (l *dnsNameContainsBareIANASuffix) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *dnsNameContainsBareIANASuffix) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + if util.IsInTLDMap(c.Subject.CommonName) { + return &lint.LintResult{Status: lint.Error} + } + } + for _, dns := range c.DNSNames { + if util.IsInTLDMap(dns) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go new file mode 100644 index 0000000000..c617460fea --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go @@ -0,0 +1,68 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameEmptyLabel struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_empty_label", + Description: "DNSNames should not have an empty label.", + Citation: "BRs: 7.1.4.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameEmptyLabel{}, + }) +} + +func (l *DNSNameEmptyLabel) Initialize() error { + return nil +} + +func (l *DNSNameEmptyLabel) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func domainHasEmptyLabel(domain string) bool { + labels := strings.Split(domain, ".") + for _, elem := range labels { + if elem == "" { + return true + } + } + return false +} + +func (l *DNSNameEmptyLabel) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + if domainHasEmptyLabel(c.Subject.CommonName) { + return &lint.LintResult{Status: lint.Error} + } + } + for _, dns := range c.DNSNames { + if domainHasEmptyLabel(dns) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go new file mode 100644 index 0000000000..f2687edc58 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go @@ -0,0 +1,67 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameHyphenInSLD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_hyphen_in_sld", + Description: "DNSName should not have a hyphen beginning or ending the SLD", + Citation: "BRs 7.1.4.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC5280Date, + Lint: &DNSNameHyphenInSLD{}, + }) +} + +func (l *DNSNameHyphenInSLD) Initialize() error { + return nil +} + +func (l *DNSNameHyphenInSLD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameHyphenInSLD) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + domainInfo := c.GetParsedSubjectCommonName(false) + if domainInfo.ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.HasPrefix(domainInfo.ParsedDomain.SLD, "-") || strings.HasSuffix(domainInfo.ParsedDomain.SLD, "-") { + return &lint.LintResult{Status: lint.Error} + } + } + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.HasPrefix(parsedSANDNSNames[i].ParsedDomain.SLD, "-") || + strings.HasSuffix(parsedSANDNSNames[i].ParsedDomain.SLD, "-") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go new file mode 100644 index 0000000000..f13f93358d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go @@ -0,0 +1,70 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameLabelLengthTooLong struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_label_too_long", + Description: "DNSName labels MUST be less than or equal to 63 characters", + Citation: "RFC 1035", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameLabelLengthTooLong{}, + }) +} + +func (l *DNSNameLabelLengthTooLong) Initialize() error { + return nil +} + +func (l *DNSNameLabelLengthTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func labelLengthTooLong(domain string) bool { + labels := strings.Split(domain, ".") + for _, label := range labels { + if len(label) > 63 { + return true + } + } + return false +} + +func (l *DNSNameLabelLengthTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + labelTooLong := labelLengthTooLong(c.Subject.CommonName) + if labelTooLong { + return &lint.LintResult{Status: lint.Error} + } + } + for _, dns := range c.DNSNames { + labelTooLong := labelLengthTooLong(dns) + if labelTooLong { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go new file mode 100644 index 0000000000..23998b5b84 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameValidTLD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_not_valid_tld", + Description: "DNSNames must have a valid TLD.", + Citation: "BRs: 3.2.2.4", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameValidTLD{}, + }) +} + +func (l *DNSNameValidTLD) Initialize() error { + return nil +} + +func (l *DNSNameValidTLD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameValidTLD) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + if !util.HasValidTLD(c.Subject.CommonName, c.NotBefore) { + return &lint.LintResult{Status: lint.Error} + } + } + for _, dns := range c.DNSNames { + if !util.HasValidTLD(dns, c.NotBefore) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go new file mode 100644 index 0000000000..f02a86f028 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go @@ -0,0 +1,67 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameUnderscoreInSLD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_underscore_in_sld", + Description: "DNSName MUST NOT contain underscore characters", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC5280Date, + Lint: &DNSNameUnderscoreInSLD{}, + }) +} + +func (l *DNSNameUnderscoreInSLD) Initialize() error { + return nil +} + +func (l *DNSNameUnderscoreInSLD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameUnderscoreInSLD) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + domainInfo := c.GetParsedSubjectCommonName(false) + if domainInfo.ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.Contains(domainInfo.ParsedDomain.SLD, "_") { + return &lint.LintResult{Status: lint.Error} + } + } + + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.Contains(parsedSANDNSNames[i].ParsedDomain.SLD, "_") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go new file mode 100644 index 0000000000..0e8e02e59a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go @@ -0,0 +1,68 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameUnderscoreInTRD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_dnsname_underscore_in_trd", + Description: "DNSName MUST NOT contain underscore characters", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC5280Date, + Lint: &DNSNameUnderscoreInTRD{}, + }) +} + +func (l *DNSNameUnderscoreInTRD) Initialize() error { + return nil +} + +func (l *DNSNameUnderscoreInTRD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameUnderscoreInTRD) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + domainInfo := c.GetParsedSubjectCommonName(false) + if domainInfo.ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.Contains(domainInfo.ParsedDomain.TRD, "_") { + return &lint.LintResult{Status: lint.Warn} + } + } + + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.Contains(parsedSANDNSNames[i].ParsedDomain.TRD, "_") { + return &lint.LintResult{Status: lint.Warn} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go new file mode 100644 index 0000000000..a2d0eb927e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go @@ -0,0 +1,67 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameWildcardLeftofPublicSuffix struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_dnsname_wildcard_left_of_public_suffix", + Description: "the CA MUST establish and follow a documented procedure[^pubsuffix] that determines if the wildcard character occurs in the first label position to the left of a “registry‐controlled” label or “public suffix”", + Citation: "BRs: 3.2.2.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameWildcardLeftofPublicSuffix{}, + }) +} + +func (l *DNSNameWildcardLeftofPublicSuffix) Initialize() error { + return nil +} + +func (l *DNSNameWildcardLeftofPublicSuffix) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameWildcardLeftofPublicSuffix) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" && !util.CommonNameIsIP(c) { + domainInfo := c.GetParsedSubjectCommonName(false) + if domainInfo.ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + + if domainInfo.ParsedDomain.SLD == "*" { + return &lint.LintResult{Status: lint.Notice} + } + } + + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + + if parsedSANDNSNames[i].ParsedDomain.SLD == "*" { + return &lint.LintResult{Status: lint.Notice} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go new file mode 100644 index 0000000000..1bcc08021a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go @@ -0,0 +1,69 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameWildcardOnlyInLeftlabel struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_wildcard_only_in_left_label", + Description: "DNSName should not have wildcards except in the left-most label", + Citation: "BRs: 1.6.1, Wildcard Domain Name", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &DNSNameWildcardOnlyInLeftlabel{}, + }) +} + +func (l *DNSNameWildcardOnlyInLeftlabel) Initialize() error { + return nil +} + +func (l *DNSNameWildcardOnlyInLeftlabel) CheckApplies(c *x509.Certificate) bool { + return true +} + +func wildcardNotInLeftLabel(domain string) bool { + labels := strings.Split(domain, ".") + if len(labels) > 1 { + labels = labels[1:] + for _, label := range labels { + if strings.Contains(label, "*") { + return true + } + } + } + return false +} + +func (l *DNSNameWildcardOnlyInLeftlabel) Execute(c *x509.Certificate) *lint.LintResult { + if wildcardNotInLeftLabel(c.Subject.CommonName) { + return &lint.LintResult{Status: lint.Error} + } + for _, dns := range c.DNSNames { + if wildcardNotInLeftLabel(dns) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go new file mode 100644 index 0000000000..5109a57877 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go @@ -0,0 +1,66 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/dsa" + "math/big" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type dsaSubgroup struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dsa_correct_order_in_subgroup", + Description: "DSA: Public key value has the unique correct representation in the field, and that the key has the correct order in the subgroup", + Citation: "BRs v1.7.0: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &dsaSubgroup{}, + }) +} + +func (l *dsaSubgroup) Initialize() error { + return nil +} + +func (l *dsaSubgroup) CheckApplies(c *x509.Certificate) bool { + if c.PublicKeyAlgorithm != x509.DSA { + return false + } + if _, ok := c.PublicKey.(*dsa.PublicKey); !ok { + return false + } + return true +} + +func (l *dsaSubgroup) Execute(c *x509.Certificate) *lint.LintResult { + dsaKey, ok := c.PublicKey.(*dsa.PublicKey) + if !ok { + return &lint.LintResult{Status: lint.NA} + } + output := big.Int{} + + // Enforce that Y^Q == 1 mod P, e.g. that Order(Y) == Q mod P. + output.Exp(dsaKey.Y, dsaKey.Q, dsaKey.P) + if output.Cmp(big.NewInt(1)) == 0 { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go new file mode 100644 index 0000000000..d991d872bd --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go @@ -0,0 +1,57 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/dsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type dsaImproperSize struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dsa_improper_modulus_or_divisor_size", + Description: "Certificates MUST meet the following requirements for DSA algorithm type and key size: L=2048 and N=224,256 or L=3072 and N=256", + Citation: "BRs v1.7.0: 6.1.5", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + Lint: &dsaImproperSize{}, + }) +} + +func (l *dsaImproperSize) Initialize() error { + return nil +} + +func (l *dsaImproperSize) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.DSA +} + +func (l *dsaImproperSize) Execute(c *x509.Certificate) *lint.LintResult { + dsaKey, ok := c.PublicKey.(*dsa.PublicKey) + if !ok { + return &lint.LintResult{Status: lint.NA} + } + L := dsaKey.Parameters.P.BitLen() + N := dsaKey.Parameters.Q.BitLen() + if (L == 2048 && N == 224) || (L == 2048 && N == 256) || (L == 3072 && N == 256) { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go new file mode 100644 index 0000000000..bbf7b4f604 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/dsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type dsaTooShort struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dsa_shorter_than_2048_bits", + Description: "DSA modulus size must be at least 2048 bits", + Citation: "BRs v1.7.0: 6.1.5", + // Refer to BRs: 6.1.5, taking the statement "Before 31 Dec 2010" literally + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + Lint: &dsaTooShort{}, + }) +} + +func (l *dsaTooShort) Initialize() error { + return nil +} + +func (l *dsaTooShort) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.DSA +} + +func (l *dsaTooShort) Execute(c *x509.Certificate) *lint.LintResult { + dsaKey, ok := c.PublicKey.(*dsa.PublicKey) + if !ok { + return &lint.LintResult{Status: lint.NA} + } + dsaParams := dsaKey.Parameters + L := dsaParams.P.BitLen() + N := dsaParams.Q.BitLen() + if L >= 2048 && N >= 244 { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go new file mode 100644 index 0000000000..da36d97d61 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/dsa" + "math/big" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type dsaUniqueCorrectRepresentation struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dsa_unique_correct_representation", + Description: "DSA: Public key value has the unique correct representation in the field, and that the key has the correct order in the subgroup", + Citation: "BRs v1.7.0: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &dsaUniqueCorrectRepresentation{}, + }) +} + +func (l *dsaUniqueCorrectRepresentation) Initialize() error { + return nil +} + +func (l *dsaUniqueCorrectRepresentation) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.DSA +} + +func (l *dsaUniqueCorrectRepresentation) Execute(c *x509.Certificate) *lint.LintResult { + dsaKey, ok := c.PublicKey.(*dsa.PublicKey) + if !ok { + return &lint.LintResult{Status: lint.NA} + } + // Verify that 2 ≤ y ≤ p-2. + two := big.NewInt(2) + pMinusTwo := big.NewInt(0) + pMinusTwo.Sub(dsaKey.P, two) + if two.Cmp(dsaKey.Y) > 0 || dsaKey.Y.Cmp(pMinusTwo) > 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go new file mode 100644 index 0000000000..9e894b4b72 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go @@ -0,0 +1,71 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/ecdsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ecImproperCurves struct{} + +/************************************************ +BRs: 6.1.5 +Certificates MUST meet the following requirements for algorithm type and key size. +ECC Curve: NIST P-256, P-384, or P-521 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ec_improper_curves", + Description: "Only one of NIST P‐256, P‐384, or P‐521 can be used", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + // Refer to BRs: 6.1.5, taking the statement "Before 31 Dec 2010" literally + EffectiveDate: util.ZeroDate, + Lint: &ecImproperCurves{}, + }) +} + +func (l *ecImproperCurves) Initialize() error { + return nil +} + +func (l *ecImproperCurves) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.ECDSA +} + +func (l *ecImproperCurves) Execute(c *x509.Certificate) *lint.LintResult { + /* Declare theKey to be a ECDSA Public Key */ + var theKey *ecdsa.PublicKey + /* Need to do different things based on what c.PublicKey is */ + switch keyType := c.PublicKey.(type) { + case *x509.AugmentedECDSA: + theKey = keyType.Pub + case *ecdsa.PublicKey: + theKey = keyType + } + /* Now can actually check the params */ + theParams := theKey.Curve.Params() + switch theParams.Name { + case "P-256", "P-384", "P-521": + return &lint.LintResult{Status: lint.Pass} + default: + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go new file mode 100644 index 0000000000..df33ab21a4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go @@ -0,0 +1,63 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type NCReservedIPNet struct{} + +/************************************************ +BRs: 7.1.5 +(b) For each iPAddress range in permittedSubtrees, the CA MUST confirm that the +Applicant has been assigned the iPAddress range or has been authorized by the +assigner to act on the assignee's behalf. + +BRs: 7.1.4.2.1 +CAs SHALL NOT issue certificates with a subjectAlternativeName extension or +Subject commonName field containing a Reserved IP Address or Internal Name. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_nc_intersects_reserved_ip", + Description: "iPAddress name constraint intersects an IANA reserved network", + Citation: "BRs: 7.1.5 / 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &NCReservedIPNet{}, + }) +} + +func (l *NCReservedIPNet) Initialize() error { + return nil +} + +func (l *NCReservedIPNet) CheckApplies(c *x509.Certificate) bool { + return c.NotAfter.After(util.NoReservedIP) && util.IsExtInCert(c, util.NameConstOID) +} + +func (l *NCReservedIPNet) Execute(c *x509.Certificate) *lint.LintResult { + for _, constraint := range c.PermittedIPAddresses { + if util.IntersectsIANAReserved(constraint.Data) { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go new file mode 100644 index 0000000000..7270857458 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go @@ -0,0 +1,52 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANReservedIP struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_contains_reserved_ip", + Description: "CAs SHALL NOT issue certificates with a subjectAltName extension or subject:commonName field containing a Reserved IP Address or Internal Name.", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANReservedIP{}, + }) +} + +func (l *SANReservedIP) Initialize() error { + return nil +} + +func (l *SANReservedIP) CheckApplies(c *x509.Certificate) bool { + return c.NotAfter.After(util.NoReservedIP) +} + +func (l *SANReservedIP) Execute(c *x509.Certificate) *lint.LintResult { + for _, ip := range c.IPAddresses { + if util.IsIANAReserved(ip) { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go new file mode 100644 index 0000000000..ccb3d325d1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go @@ -0,0 +1,61 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ExtSANCriticalWithSubjectDN struct{} + +/************************************************ +Further, if the only subject identity included in the certificate is an + alternative name form (e.g., an electronic mail address), then the subject + distinguished name MUST be empty (an empty sequence), and the subjectAltName + extension MUST be present. If the subject field contains an empty sequence, + then the issuing CA MUST include a subjectAltName extension that is marked as + critical. When including the subjectAltName extension in a certificate that + has a non-empty subject distinguished name, conforming CAs SHOULD mark the + subjectAltName extension as non-critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_san_critical_with_subject_dn", + Description: "If the subject contains a distinguished name, subjectAlternateName SHOULD be non-critical", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC5280Date, + Lint: &ExtSANCriticalWithSubjectDN{}, + }) +} + +func (l *ExtSANCriticalWithSubjectDN) Initialize() error { + return nil +} + +func (l *ExtSANCriticalWithSubjectDN) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.SubjectAlternateNameOID) +} + +func (l *ExtSANCriticalWithSubjectDN) Execute(cert *x509.Certificate) *lint.LintResult { + san := util.GetExtFromCert(cert, util.SubjectAlternateNameOID) + if san.Critical && util.NotAllNameFieldsAreEmpty(&cert.Subject) { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go new file mode 100644 index 0000000000..6d1aa59203 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANDirName struct{} + +/************************************************************************************************************ +7.1.4.2.1. Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +Contents: This extension MUST contain at least one entry. Each entry MUST be either a dNSName containing +the Fully‐Qualified Domain Name or an iPAddress containing the IP address of a server. The CA MUST +confirm that the Applicant controls the Fully‐Qualified Domain Name or IP address or has been granted the +right to use it by the Domain Name Registrant or IP address assignee, as appropriate. +Wildcard FQDNs are permitted. +*************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_directory_name_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' and 'ipaddress' name types", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANDirName{}, + }) +} + +func (l *SANDirName) Initialize() error { + return nil +} + +func (l *SANDirName) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANDirName) Execute(c *x509.Certificate) *lint.LintResult { + if c.DirectoryNames != nil { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go new file mode 100644 index 0000000000..42c193dc4b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANEDI struct{} + +/************************************************************************************************************ +7.1.4.2.1. Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +Contents: This extension MUST contain at least one entry. Each entry MUST be either a dNSName containing +the Fully‐Qualified Domain Name or an iPAddress containing the IP address of a server. The CA MUST +confirm that the Applicant controls the Fully‐Qualified Domain Name or IP address or has been granted the +right to use it by the Domain Name Registrant or IP address assignee, as appropriate. +Wildcard FQDNs are permitted. +*************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_edi_party_name_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' and 'ipaddress' name types", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANEDI{}, + }) +} + +func (l *SANEDI) Initialize() error { + return nil +} + +func (l *SANEDI) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANEDI) Execute(c *x509.Certificate) *lint.LintResult { + if c.EDIPartyNames != nil { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go new file mode 100644 index 0000000000..59aae44c27 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go @@ -0,0 +1,57 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANMissing struct{} + +/************************************************ +BRs: 7.1.4.2.1 +Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_missing", + Description: "Subscriber certificates MUST contain the Subject Alternate Name extension", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANMissing{}, + }) +} + +func (l *SANMissing) Initialize() error { + return nil +} + +func (l *SANMissing) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *SANMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.SubjectAlternateNameOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go new file mode 100644 index 0000000000..fa6f90d5fb --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANOtherName struct{} + +/************************************************************************************************************ +7.1.4.2.1. Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +Contents: This extension MUST contain at least one entry. Each entry MUST be either a dNSName containing +the Fully‐Qualified Domain Name or an iPAddress containing the IP address of a server. The CA MUST +confirm that the Applicant controls the Fully‐Qualified Domain Name or IP address or has been granted the +right to use it by the Domain Name Registrant or IP address assignee, as appropriate. +Wildcard FQDNs are permitted. +*************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_other_name_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' and 'ipaddress' name types.", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANOtherName{}, + }) +} + +func (l *SANOtherName) Initialize() error { + return nil +} + +func (l *SANOtherName) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANOtherName) Execute(c *x509.Certificate) *lint.LintResult { + if c.OtherNames != nil { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go new file mode 100644 index 0000000000..ef9bea512d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANRegId struct{} + +/************************************************************************************************************ +7.1.4.2.1. Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +Contents: This extension MUST contain at least one entry. Each entry MUST be either a dNSName containing +the Fully‐Qualified Domain Name or an iPAddress containing the IP address of a server. The CA MUST +confirm that the Applicant controls the Fully‐Qualified Domain Name or IP address or has been granted the +right to use it by the Domain Name Registrant or IP address assignee, as appropriate. +Wildcard FQDNs are permitted. +*************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_registered_id_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' and 'ipaddress' name types.", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANRegId{}, + }) +} + +func (l *SANRegId) Initialize() error { + return nil +} + +func (l *SANRegId) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANRegId) Execute(c *x509.Certificate) *lint.LintResult { + if c.RegisteredIDs != nil { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go new file mode 100644 index 0000000000..27e1b401f0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANRfc822 struct{} + +/************************************************************************************************************ +7.1.4.2.1. Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +Contents: This extension MUST contain at least one entry. Each entry MUST be either a dNSName containing +the Fully‐Qualified Domain Name or an iPAddress containing the IP address of a server. The CA MUST +confirm that the Applicant controls the Fully‐Qualified Domain Name or IP address or has been granted the +right to use it by the Domain Name Registrant or IP address assignee, as appropriate. +Wildcard FQDNs are permitted. +*************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_rfc822_name_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' and 'ipaddress' name types.", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANRfc822{}, + }) +} + +func (l *SANRfc822) Initialize() error { + return nil +} + +func (l *SANRfc822) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANRfc822) Execute(c *x509.Certificate) *lint.LintResult { + if c.EmailAddresses != nil { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go new file mode 100644 index 0000000000..203c7cd6e0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANURI struct{} + +/************************************************************************************************************ +7.1.4.2.1. Subject Alternative Name Extension +Certificate Field: extensions:subjectAltName +Required/Optional: Required +Contents: This extension MUST contain at least one entry. Each entry MUST be either a dNSName containing +the Fully‐Qualified Domain Name or an iPAddress containing the IP address of a server. The CA MUST +confirm that the Applicant controls the Fully‐Qualified Domain Name or IP address or has been granted the +right to use it by the Domain Name Registrant or IP address assignee, as appropriate. +Wildcard FQDNs are permitted. +*************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_uniform_resource_identifier_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' and 'ipaddress' name types", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &SANURI{}, + }) +} + +func (l *SANURI) Initialize() error { + return nil +} + +func (l *SANURI) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANURI) Execute(c *x509.Certificate) *lint.LintResult { + if c.URIs != nil { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go new file mode 100644 index 0000000000..aa550b1a24 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go @@ -0,0 +1,220 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + "net/url" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type torServiceDescHashInvalid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_tor_service_descriptor_hash_invalid", + Description: "certificates with v2 .onion names need valid TorServiceDescriptors in extension", + Citation: "BRs: Ballot 201, Ballot SC27", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV201Date, + Lint: &torServiceDescHashInvalid{}, + }) +} + +func (l *torServiceDescHashInvalid) Initialize() error { + // There is nothing to initialize for a torServiceDescHashInvalid linter. + return nil +} + +// CheckApplies returns true if the TorServiceDescriptor extension is present +// or if the certificate is an EV subscriber certificate with one or more +// subject names ending in `.onion`. +func (l *torServiceDescHashInvalid) CheckApplies(c *x509.Certificate) bool { + ext := util.GetExtFromCert(c, util.BRTorServiceDescriptor) + return ext != nil || (util.IsSubscriberCert(c) && + util.CertificateSubjInTLD(c, util.OnionTLD) && + util.IsEV(c.PolicyIdentifiers)) +} + +// failResult is a small utility function for creating a failed lint result. +func failResult(format string, args ...interface{}) *lint.LintResult { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf(format, args...), + } +} + +// torServiceDescExtName is a common string prefix used in many lint result +// detail messages to identify the extension at fault. +var torServiceDescExtName = fmt.Sprintf( + "TorServiceDescriptor extension (oid %s)", + util.BRTorServiceDescriptor.String()) + +// lintOnionURL verifies that an Onion URI value from a TorServiceDescriptorHash +// is: +// +// 1) a valid parseable url. +// 2) a URL with a non-empty hostname +// 3) a URL with an https:// protocol scheme +// +// If all of the above hold then nil is returned. If any of the above conditions +// are not met an error lint result pointer is returned. +func lintOnionURL(onion string) *lint.LintResult { + if onionURL, err := url.Parse(onion); err != nil { + return failResult( + "%s contained "+ + "TorServiceDescriptorHash object with invalid Onion URI", + torServiceDescExtName) + } else if onionURL.Host == "" { + return failResult( + "%s contained "+ + "TorServiceDescriptorHash object with Onion URI missing a hostname", + torServiceDescExtName) + } else if onionURL.Scheme != "https" { + return failResult( + "%s contained "+ + "TorServiceDescriptorHash object with Onion URI using a non-HTTPS "+ + "protocol scheme", + torServiceDescExtName) + } + return nil +} + +// Execute will lint the provided certificate. An lint.Error lint.LintResult will be +// returned if: +// +// 1) There is no TorServiceDescriptor extension present and it's required +// 2) There were no TorServiceDescriptors parsed by zcrypto +// 3) There are TorServiceDescriptorHash entries with an invalid Onion URL. +// 4) There are TorServiceDescriptorHash entries with an unknown hash +// algorithm or incorrect hash bit length. +// 5) There is a TorServiceDescriptorHash entry that doesn't correspond to +// an onion subject in the cert. +// 6) There is an onion subject in the cert that doesn't correspond to +// a TorServiceDescriptorHash, if required. +func (l *torServiceDescHashInvalid) Execute(c *x509.Certificate) *lint.LintResult { + // If the certificate is EV, the BRTorServiceDescriptor extension is required. + // We know that `CheckApplies` will only apply if the certificate has the + // extension or that it's required, so this will only fail when it's + // required. + if ext := util.GetExtFromCert(c, util.BRTorServiceDescriptor); ext == nil { + return failResult( + "certificate contained a %s domain but is missing a TorServiceDescriptor "+ + "extension (oid %s)", + util.OnionTLD, util.BRTorServiceDescriptor.String()) + } + + // The certificate should have at least one TorServiceDescriptorHash in the + // TorServiceDescriptor extension. + descriptors := c.TorServiceDescriptors + if len(descriptors) == 0 { + return failResult( + "certificate contained a %s domain but TorServiceDescriptor "+ + "extension (oid %s) had no TorServiceDescriptorHash objects", + util.OnionTLD, util.BRTorServiceDescriptor.String()) + } + + // Build a map of all the eTLD+1 onion subjects in the cert to compare against + // the service descriptors. + onionETLDPlusOneMap := make(map[string]string) + for _, subj := range append(c.DNSNames, c.Subject.CommonName) { + if !strings.HasSuffix(subj, util.OnionTLD) { + continue + } + labels := strings.Split(subj, ".") + if len(labels) < 2 { + return failResult("certificate contained a %s domain with too few "+ + "labels: %q", + util.OnionTLD, subj) + } + eTLDPlusOne := strings.Join(labels[len(labels)-2:], ".") + onionETLDPlusOneMap[eTLDPlusOne] = subj + } + + expectedHashBits := map[string]int{ + "SHA256": 256, + "SHA384": 384, + "SHA512": 512, + } + + // Build a map of onion hostname -> TorServiceDescriptorHash using the parsed + // TorServiceDescriptors from zcrypto. + descriptorMap := make(map[string]*x509.TorServiceDescriptorHash) + for _, descriptor := range descriptors { + // each descriptor's Onion URL must be valid + if errResult := lintOnionURL(descriptor.Onion); errResult != nil { + return errResult + } + // each descriptor should have a known hash algorithm and the correct + // corresponding size of hash. + if expectedBits, found := expectedHashBits[descriptor.AlgorithmName]; !found { + return failResult( + "%s contained a TorServiceDescriptorHash for Onion URI %q with an "+ + "unknown hash algorithm", + torServiceDescExtName, descriptor.Onion) + } else if expectedBits != descriptor.HashBits { + return failResult( + "%s contained a TorServiceDescriptorHash with hash algorithm %q but "+ + "only %d bits of hash not %d", + torServiceDescExtName, descriptor.AlgorithmName, + descriptor.HashBits, expectedBits) + } + // NOTE(@cpu): Throwing out the err result here because lintOnionURL already + // ensured the URL is valid. + url, _ := url.Parse(descriptor.Onion) + hostname := url.Hostname() + // there should only be one TorServiceDescriptorHash for each Onion hostname. + if _, exists := descriptorMap[hostname]; exists { + return failResult( + "%s contained more than one TorServiceDescriptorHash for base "+ + "Onion URI %q", + torServiceDescExtName, descriptor.Onion) + } + // there shouldn't be a TorServiceDescriptorHash for a Onion hostname that + // isn't an eTLD+1 in the certificate's subjects. + if _, found := onionETLDPlusOneMap[hostname]; !found { + return failResult( + "%s contained a TorServiceDescriptorHash with a hostname (%q) not "+ + "present as a subject in the certificate", + torServiceDescExtName, hostname) + } + descriptorMap[hostname] = descriptor + } + + // For EV certificates, every `.onion` name is required to have a + // TorServiceDescriptorHash, so check if any of the onion subjects in the + // certificate don't have a TorServiceDescriptorHash for the eTLD+1 in the + // descriptorMap. + // See also https://github.com/cabforum/documents/issues/190 + if util.IsEV(c.PolicyIdentifiers) { + for eTLDPlusOne, subjDomain := range onionETLDPlusOneMap { + if _, found := descriptorMap[eTLDPlusOne]; !found { + return failResult( + "%s subject domain name %q does not have a corresponding "+ + "TorServiceDescriptorHash for its eTLD+1", + util.OnionTLD, subjDomain) + } + } + } + + // Everything checks out! + return &lint.LintResult{ + Status: lint.Pass, + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go new file mode 100644 index 0000000000..43c1ebd1b1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go @@ -0,0 +1,52 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type extraSubjectCommonNames struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_extra_subject_common_names", + Description: "if present the subject commonName field MUST contain a single IP address or Fully-Qualified Domain Name", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &extraSubjectCommonNames{}, + }) +} + +func (l *extraSubjectCommonNames) Initialize() error { + return nil +} + +func (l *extraSubjectCommonNames) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *extraSubjectCommonNames) Execute(c *x509.Certificate) *lint.LintResult { + // Multiple subject commonName fields are not expressly prohibited by section + // 7.1.4.2.2 but do seem to run afoul of the intent. For that reason we return + // only a lint.Warn level finding here. + if len(c.Subject.CommonNames) > 1 { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go new file mode 100644 index 0000000000..24e63be410 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go @@ -0,0 +1,53 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type InvalidCertificateVersion struct{} + +/************************************************ +Certificates MUST be of type X.509 v3. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_invalid_certificate_version", + Description: "Certificates MUST be of type X.590 v3", + Citation: "BRs: 7.1.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV130Date, + Lint: &InvalidCertificateVersion{}, + }) +} + +func (l *InvalidCertificateVersion) Initialize() error { + return nil +} + +func (l *InvalidCertificateVersion) CheckApplies(cert *x509.Certificate) bool { + return true +} + +func (l *InvalidCertificateVersion) Execute(cert *x509.Certificate) *lint.LintResult { + if cert.Version != 3 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go new file mode 100644 index 0000000000..94c3159773 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go @@ -0,0 +1,55 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth", + Description: "OCSP signing Certificate MUST contain an extension of type id-pkixocsp-nocheck, as" + + " defined by RFC6960", + Citation: "BRs: 4.9.9", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth{}, + }) +} + +func (l *OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth) Initialize() error { + return nil +} + +func (l *OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth) CheckApplies(c *x509.Certificate) bool { + return util.IsDelegatedOCSPResponderCert(c) && util.IsServerAuthCert(c) +} + +func (l *OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth) Execute(c *x509.Certificate) *lint.LintResult { + // If the id-pkix-ocsp-nocheck extension, as specified in RFC 6960, Section 4.2.2.2.1, is present, then + // the certificate complies. + if util.IsExtInCert(c, util.OscpNoCheckOID) { + return &lint.LintResult{Status: lint.Pass} + } + + // This certificate is a TLS certificate, so the Baseline Requirements apply, which require the presence + // of id-pkix-ocsp-nocheck as an extension. + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go new file mode 100644 index 0000000000..bff2178637 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go @@ -0,0 +1,55 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rootCaModSize struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_old_root_ca_rsa_mod_less_than_2048_bits", + Description: "In a validity period beginning on or before 31 Dec 2010, root CA certificates using RSA public key algorithm MUST use a 2048 bit modulus", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + Lint: &rootCaModSize{}, + }) +} + +func (l *rootCaModSize) Initialize() error { + return nil +} + +func (l *rootCaModSize) CheckApplies(c *x509.Certificate) bool { + issueDate := c.NotBefore + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA && util.IsRootCA(c) && issueDate.Before(util.NoRSA1024RootDate) +} + +func (l *rootCaModSize) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.N.BitLen() < 2048 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go new file mode 100644 index 0000000000..974ef8c8d3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// CHANGE THIS COMMENT TO MATCH SOURCE TEXT + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCaModSize struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_old_sub_ca_rsa_mod_less_than_1024_bits", + Description: "In a validity period beginning on or before 31 Dec 2010 and ending on or before 31 Dec 2013, subordinate CA certificates using RSA public key algorithm MUST use a 1024 bit modulus", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + // since effective date should be checked against end date in this specific case, putting time check into checkApplies instead, ZeroDate here to automatically pass NE test + EffectiveDate: util.ZeroDate, + Lint: &subCaModSize{}, + }) +} + +func (l *subCaModSize) Initialize() error { + return nil +} + +func (l *subCaModSize) CheckApplies(c *x509.Certificate) bool { + issueDate := c.NotBefore + endDate := c.NotAfter + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && util.IsSubCA(c) && issueDate.Before(util.NoRSA1024RootDate) && endDate.Before(util.NoRSA1024Date) +} + +func (l *subCaModSize) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.N.BitLen() < 1024 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go new file mode 100644 index 0000000000..989f3ab422 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subModSize struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_old_sub_cert_rsa_mod_less_than_1024_bits", + Description: "In a validity period ending on or before 31 Dec 2013, subscriber certificates using RSA public key algorithm MUST use a 1024 bit modulus", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + // since effective date should be checked against end date in this specific case, putting time check into checkApplies instead, ZeroDate here to automatically pass NE test + EffectiveDate: util.ZeroDate, + Lint: &subModSize{}, + }) +} + +func (l *subModSize) Initialize() error { + return nil +} + +func (l *subModSize) CheckApplies(c *x509.Certificate) bool { + endDate := c.NotAfter + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA && !util.IsCACert(c) && endDate.Before(util.NoRSA1024Date) +} + +func (l *subModSize) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.N.BitLen() < 1024 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go new file mode 100644 index 0000000000..dcc9cc7f5e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type publicKeyAllowed struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_public_key_type_not_allowed", + Description: "Certificates MUST have RSA, DSA, or ECDSA public key type", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &publicKeyAllowed{}, + }) +} + +func (l *publicKeyAllowed) Initialize() error { + return nil +} + +func (l *publicKeyAllowed) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *publicKeyAllowed) Execute(c *x509.Certificate) *lint.LintResult { + alg := c.PublicKeyAlgorithm + if alg != x509.UnknownPublicKeyAlgorithm { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go new file mode 100644 index 0000000000..d62f41fd10 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go @@ -0,0 +1,71 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rootCaPathLenPresent struct{} + +/************************************************************************************************************ +7.1.2.1. Root CA Certificate +a. basicConstraints +This extension MUST appear as a critical extension. The cA field MUST be set true. The pathLenConstraint field SHOULD NOT be present. +***********************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_root_ca_basic_constraints_path_len_constraint_field_present", + Description: "Root CA certificate basicConstraint extension pathLenConstraint field SHOULD NOT be present", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &rootCaPathLenPresent{}, + }) +} + +func (l *rootCaPathLenPresent) Initialize() error { + return nil +} + +func (l *rootCaPathLenPresent) CheckApplies(c *x509.Certificate) bool { + return util.IsRootCA(c) && util.IsExtInCert(c, util.BasicConstOID) +} + +func (l *rootCaPathLenPresent) Execute(c *x509.Certificate) *lint.LintResult { + bc := util.GetExtFromCert(c, util.BasicConstOID) + var seq asn1.RawValue + var isCa bool + _, err := asn1.Unmarshal(bc.Value, &seq) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(seq.Bytes) == 0 { + return &lint.LintResult{Status: lint.Pass} + } + rest, err := asn1.Unmarshal(seq.Bytes, &isCa) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(rest) > 0 { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go new file mode 100644 index 0000000000..1707726164 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go @@ -0,0 +1,55 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rootCAContainsCertPolicy struct{} + +/************************************************ +BRs: 7.1.2.1c certificatePolicies +This extension SHOULD NOT be present. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_root_ca_contains_cert_policy", + Description: "Root CA Certificate: certificatePolicies SHOULD NOT be present.", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &rootCAContainsCertPolicy{}, + }) +} + +func (l *rootCAContainsCertPolicy) Initialize() error { + return nil +} + +func (l *rootCAContainsCertPolicy) CheckApplies(c *x509.Certificate) bool { + return util.IsRootCA(c) +} + +func (l *rootCAContainsCertPolicy) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.CertPolicyOID) { + return &lint.LintResult{Status: lint.Warn} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go new file mode 100644 index 0000000000..843a2e89ad --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go @@ -0,0 +1,55 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rootCAContainsEKU struct{} + +/************************************************ +BRs: 7.1.2.1d extendedKeyUsage +This extension MUST NOT be present. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_root_ca_extended_key_usage_present", + Description: "Root CA Certificate: extendedKeyUsage MUST NOT be present.t", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &rootCAContainsEKU{}, + }) +} + +func (l *rootCAContainsEKU) Initialize() error { + return nil +} + +func (l *rootCAContainsEKU) CheckApplies(c *x509.Certificate) bool { + return util.IsRootCA(c) +} + +func (l *rootCAContainsEKU) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.EkuSynOid) { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go new file mode 100644 index 0000000000..23167e8d98 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rootCAKeyUsageMustBeCritical struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_root_ca_key_usage_must_be_critical", + Description: "Root CA certificates MUST have Key Usage Extension marked critical", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC2459Date, + Lint: &rootCAKeyUsageMustBeCritical{}, + }) +} + +func (l *rootCAKeyUsageMustBeCritical) Initialize() error { + return nil +} + +func (l *rootCAKeyUsageMustBeCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsRootCA(c) && util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *rootCAKeyUsageMustBeCritical) Execute(c *x509.Certificate) *lint.LintResult { + keyUsageExtension := util.GetExtFromCert(c, util.KeyUsageOID) + if keyUsageExtension.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go new file mode 100644 index 0000000000..0fc91f40d8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go @@ -0,0 +1,50 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rootCAKeyUsagePresent struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_root_ca_key_usage_present", + Description: "Root CA certificates MUST have Key Usage Extension Present", + Citation: "BRs: 7.1.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.RFC2459Date, + Lint: &rootCAKeyUsagePresent{}, + }) +} + +func (l *rootCAKeyUsagePresent) Initialize() error { + return nil +} + +func (l *rootCAKeyUsagePresent) CheckApplies(c *x509.Certificate) bool { + return util.IsRootCA(c) +} + +func (l *rootCAKeyUsagePresent) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.KeyUsageOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go new file mode 100644 index 0000000000..856a9882c7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaModSmallFactor struct{} + +/************************************************************************************************** +6.1.6. Public Key Parameters Generation and Quality Checking +RSA: The CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more. Additionally, the public exponent SHOULD be in the range between 2^16+1 and 2^256-1. The modulus SHOULD also have the following characteristics: an odd number, not the power of a prime, and have no factors smaller than 752. [Citation: Section 5.3.3, NIST SP 800‐89]. +**************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_rsa_mod_factors_smaller_than_752", + Description: "RSA: Modulus SHOULD also have the following characteristics: no factors smaller than 752", + Citation: "BRs: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV113Date, + Lint: &rsaModSmallFactor{}, + }) +} + +func (l *rsaModSmallFactor) Initialize() error { + return nil +} + +func (l *rsaModSmallFactor) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaModSmallFactor) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if util.PrimeNoSmallerThan752(key.N) { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.Warn} + +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go new file mode 100644 index 0000000000..6e1fee4fdf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go @@ -0,0 +1,54 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaParsedTestsKeySize struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_mod_less_than_2048_bits", + Description: "For certificates valid after 31 Dec 2013, all certificates using RSA public key algorithm MUST have 2048 bits of modulus", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + Lint: &rsaParsedTestsKeySize{}, + }) +} + +func (l *rsaParsedTestsKeySize) Initialize() error { + return nil +} + +func (l *rsaParsedTestsKeySize) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA && c.NotAfter.After(util.NoRSA1024Date.Add(-1)) +} + +func (l *rsaParsedTestsKeySize) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.N.BitLen() < 2048 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go new file mode 100644 index 0000000000..910d77d603 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go @@ -0,0 +1,61 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + "math/big" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaParsedTestsKeyModOdd struct{} + +/******************************************************************************************************* +"BRs: 6.1.6" +RSA: The CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more. Additionally, the public exponent SHOULD be in the range between 2^16+1 and 2^256-1. The modulus SHOULD also have the following characteristics: an odd number, not the power of a prime, and have no factors smaller than 752. [Citation: Section 5.3.3, NIST SP 800‐89]. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_rsa_mod_not_odd", + Description: "RSA: Modulus SHOULD also have the following characteristics: an odd number", + Citation: "BRs: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV113Date, + Lint: &rsaParsedTestsKeyModOdd{}, + }) +} + +func (l *rsaParsedTestsKeyModOdd) Initialize() error { + return nil +} + +func (l *rsaParsedTestsKeyModOdd) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaParsedTestsKeyModOdd) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + z := big.NewInt(0) + if (z.Mod(key.N, big.NewInt(2)).Cmp(big.NewInt(1))) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go new file mode 100644 index 0000000000..9015140bda --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go @@ -0,0 +1,65 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + "math/big" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaParsedTestsExpInRange struct { + upperBound *big.Int +} + +/******************************************************************************************************* +"BRs: 6.1.6" +RSA: The CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more. Additionally, the public exponent SHOULD be in the range between 2^16+1 and 2^256-1. The modulus SHOULD also have the following characteristics: an odd number, not the power of a prime, and have no factors smaller than 752. [Citation: Section 5.3.3, NIST SP 800-89]. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_rsa_public_exponent_not_in_range", + Description: "RSA: Public exponent SHOULD be in the range between 2^16 + 1 and 2^256 - 1", + Citation: "BRs: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV113Date, + Lint: &rsaParsedTestsExpInRange{}, + }) +} + +func (l *rsaParsedTestsExpInRange) Initialize() error { + l.upperBound = &big.Int{} + l.upperBound.Exp(big.NewInt(2), big.NewInt(256), nil) + return nil +} + +func (l *rsaParsedTestsExpInRange) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaParsedTestsExpInRange) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + exponent := key.E + const lowerBound = 65536 // 2^16 + 1 + if exponent > lowerBound && l.upperBound.Cmp(big.NewInt(int64(exponent))) == 1 { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.Warn} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go new file mode 100644 index 0000000000..9b39ca6497 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaParsedTestsKeyExpOdd struct{} + +/******************************************************************************************************* +"BRs: 6.1.6" +RSA: The CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more. Additionally, the public exponent SHOULD be in the range between 2^16+1 and 2^256-1. The modulus SHOULD also have the following characteristics: an odd number, not the power of a prime, and have no factors smaller than 752. [Citation: Section 5.3.3, NIST SP 800-89]. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_public_exponent_not_odd", + Description: "RSA: Value of public exponent is an odd number equal to 3 or more.", + Citation: "BRs: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV113Date, + Lint: &rsaParsedTestsKeyExpOdd{}, + }) +} + +func (l *rsaParsedTestsKeyExpOdd) Initialize() error { + return nil +} + +func (l *rsaParsedTestsKeyExpOdd) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaParsedTestsKeyExpOdd) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.E%2 == 1 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go new file mode 100644 index 0000000000..76620a8b03 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaParsedTestsExpBounds struct{} + +/******************************************************************************************************* +"BRs: 6.1.6" +RSA: The CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more. Additionally, the public exponent SHOULD be in the range between 2^16+1 and 2^256-1. The modulus SHOULD also have the following characteristics: an odd number, not the power of a prime, and have no factors smaller than 752. [Citation: Section 5.3.3, NIST SP 800-89]. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_public_exponent_too_small", + Description: "RSA: Value of public exponent is an odd number equal to 3 or more.", + Citation: "BRs: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV113Date, + Lint: &rsaParsedTestsExpBounds{}, + }) +} + +func (l *rsaParsedTestsExpBounds) Initialize() error { + return nil +} + +func (l *rsaParsedTestsExpBounds) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaParsedTestsExpBounds) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.E >= 3 { //If Cmp returns 1, means N > E + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go new file mode 100644 index 0000000000..f3e2f8e60c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go @@ -0,0 +1,151 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + "regexp" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +var ( + // Per 2.4 of Rendezvous v2: + // Valid onion addresses contain 16 characters in a-z2-7 plus ".onion" + onionV2Len = 16 + + // Per 1.2 of Rendezvous v3: + // A hidden service's name is its long term master identity key. This is + // encoded as a hostname by encoding the entire key in Base 32, including + // a version byte and a checksum, and then appending the string ".onion" + // at the end. The result is a 56-character domain name. + onionV3Len = 56 + + // Per RFC 4648, Section 6, the Base-32 alphabet is A-Z, 2-7, and =. + // Because v2/v3 addresses are always aligned, they should never be padded, + // and so omit = from the character set, as it's also not permitted in a + // domain in the "preferred name syntax". Because `.onion` names appear in + // DNS, which is case insensitive, the alphabet is extended to include a-z, + // as the names are tested for well-formedness prior to normalization to + // uppercase. + base32SubsetRegex = regexp.MustCompile(`^[a-zA-Z2-7]+$`) +) + +type onionNotValid struct{} + +/******************************************************************* +https://tools.ietf.org/html/rfc7686#section-1 + + Note that .onion names are required to conform with DNS name syntax + (as defined in Section 3.5 of [RFC1034] and Section 2.1 of + [RFC1123]), as they will still be exposed to DNS implementations. + + See [tor-address] and [tor-rendezvous] for the details of the + creation and use of .onion names. + +Baseline Requirements, v1.6.9, Appendix C (Ballot SC27) + +The Domain Name MUST contain at least two labels, where the right-most label +is "onion", and the label immediately preceding the right-most "onion" label +is a valid Version 3 Onion Address, as defined in section 6 of the Tor +Rendezvous Specification - Version 3 located at +https://spec.torproject.org/rend-spec-v3. + +Explanation: +Since CA/Browser Forum Ballot 144, `.onion` names have been permitted, +predating the ratification of RFC 7686. RFC 7686 introduced a normative +dependency on the Tor address and rendezvous specifications, which describe +v2 addresses. As the EV Guidelines have, since v1.5.3, required that the CA +obtain a demonstration of control from the Applicant, which effectively +requires the `.onion` name to be well-formed, even prior to RFC 7686. + +See also https://github.com/cabforum/documents/issues/191 +*******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_san_dns_name_onion_invalid", + Description: "certificates with a .onion subject name must be issued in accordance with the Tor address/rendezvous specification", + Citation: "RFC 7686, EVGs v1.7.2: Appendix F, BRs v1.6.9: Appendix C", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.OnionOnlyEVDate, + Lint: &onionNotValid{}, + }) +} + +func (l *onionNotValid) Initialize() error { + return nil +} + +// CheckApplies returns true if the certificate contains one or more subject +// names ending in `.onion`. +func (l *onionNotValid) CheckApplies(c *x509.Certificate) bool { + // TODO(sleevi): This should also be extended to support nameConstraints + // in the future. + return util.CertificateSubjInTLD(c, util.OnionTLD) +} + +// Execute will lint the provided certificate. A lint.Error lint.LintResult will +// be returned if: +// +// 1) The certificate contains a Tor Rendezvous Spec v2 address and is not an +// EV certificate (BRs: Appendix C). +// 2) The certificate contains a `.onion` subject name/SAN that is neither a +// Rendezvous Spec v2 or v3 address. +func (l *onionNotValid) Execute(c *x509.Certificate) *lint.LintResult { + for _, subj := range append(c.DNSNames, c.Subject.CommonName) { + if !strings.HasSuffix(subj, util.OnionTLD) { + continue + } + labels := strings.Split(subj, ".") + if len(labels) < 2 { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("certificate contained a %s domain with too "+ + "few labels: %q", util.OnionTLD, subj), + } + } + onionDomain := labels[len(labels)-2] + if len(onionDomain) == onionV2Len { + // Onion v2 address. These are only permitted for EV, per BRs Appendix C. + if !util.IsEV(c.PolicyIdentifiers) { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("%q is a v2 address, but the certificate is not "+ + "EV", subj), + } + } + } else if len(onionDomain) == onionV3Len { + // Onion v3 address. Permitted for all certificates by CA/Browser Forum + // Ballot SC27. + } else { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("%q is not a v2 or v3 Tor address", subj), + } + } + if !base32SubsetRegex.MatchString(onionDomain) { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("%q contains invalid characters not permitted "+ + "within base-32", subj), + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go new file mode 100644 index 0000000000..d26a277ed4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go @@ -0,0 +1,69 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type onionNotEV struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_san_dns_name_onion_not_ev_cert", + Description: "certificates with a .onion subject name must be issued in accordance with EV Guidelines", + Citation: "CABF Ballot 144", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.OnionOnlyEVDate, + Lint: &onionNotEV{}, + }) +} + +func (l *onionNotEV) Initialize() error { + return nil +} + +// This lint only applies for certificates issued before CA/Browser Forum +// Ballot SC27, which permitted .onion within non-EV certificates +func (l *onionNotEV) CheckApplies(c *x509.Certificate) bool { + return c.NotBefore.Before(util.CABFBRs_1_6_9_Date) && + util.IsSubscriberCert(c) && + util.CertificateSubjInTLD(c, util.OnionTLD) +} + +// Execute returns an lint.Error lint.LintResult if the certificate is not an EV +// certificate. CheckApplies has already verified the certificate contains one +// or more `.onion` subjects and so it must be an EV certificate. +func (l *onionNotEV) Execute(c *x509.Certificate) *lint.LintResult { + /* + * Effective May 1, 2015, each CA SHALL revoke all unexpired Certificates with an + * Internal Name using onion as the right-most label in an entry in the + * subjectAltName Extension or commonName field unless such Certificate was + * issued in accordance with Appendix F of the EV Guidelines. + */ + if !util.IsEV(c.PolicyIdentifiers) { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf( + "certificate contains one or more %s subject domains but is not an EV certificate", + util.OnionTLD), + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go new file mode 100644 index 0000000000..2e25a3b787 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go @@ -0,0 +1,87 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +var ( + // Any of the following x509.SignatureAlgorithms are acceptable per §6.1.5 of + // the BRs. + passSigAlgs = map[x509.SignatureAlgorithm]bool{ + x509.SHA256WithRSA: true, + x509.SHA384WithRSA: true, + x509.SHA512WithRSA: true, + x509.DSAWithSHA256: true, + x509.ECDSAWithSHA256: true, + x509.ECDSAWithSHA384: true, + x509.ECDSAWithSHA512: true, + // NOTE: BRs section §6.1.5 does not include SHA1 digest algorithms in the + // current version. We allow these here for historic reasons and check for + // SHA1 usage after the deprecation date in the separate + // `e_sub_cert_or_sub_ca_using_sha1` lint. + x509.SHA1WithRSA: true, + x509.DSAWithSHA1: true, + x509.ECDSAWithSHA1: true, + } + // The BRs do not forbid the use of RSA-PSS as a signature scheme in + // certificates but it is not broadly supported by user-agents. Since + // the BRs do not forbid the practice we return a warning result. + // NOTE: The Mozilla root program policy *does* forbid their use since v2.7. + // This should be covered by a lint scoped to the Mozilla source instead of in + // this CABF lint. + warnSigAlgs = map[x509.SignatureAlgorithm]bool{ + x509.SHA256WithRSAPSS: true, + x509.SHA384WithRSAPSS: true, + x509.SHA512WithRSAPSS: true, + } +) + +type signatureAlgorithmNotSupported struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_signature_algorithm_not_supported", + Description: "Certificates MUST meet the following requirements for algorithm Source: SHA-1*, SHA-256, SHA-384, SHA-512", + Citation: "BRs: 6.1.5", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + Lint: &signatureAlgorithmNotSupported{}, + }) +} + +func (l *signatureAlgorithmNotSupported) Initialize() error { + return nil +} + +func (l *signatureAlgorithmNotSupported) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *signatureAlgorithmNotSupported) Execute(c *x509.Certificate) *lint.LintResult { + sigAlg := c.SignatureAlgorithm + status := lint.Error + if passSigAlgs[sigAlg] { + status = lint.Pass + } else if warnSigAlgs[sigAlg] { + status = lint.Warn + } + return &lint.LintResult{ + Status: status, + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go new file mode 100644 index 0000000000..0a4e7b14a8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go @@ -0,0 +1,61 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCaIssuerUrl struct{} + +/*********************************************** +BRs: 7.1.2.2c +This extension SHOULD be present. It MUST NOT be marked critical. +It SHOULD contain the HTTP URL of the Issuing CA’s certificate (accessMethod = +1.3.6.1.5.5.7.48.2). It MAY contain the HTTP URL of the Issuing CA’s OCSP responder +(accessMethod = 1.3.6.1.5.5.7.48.1). +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_ca_aia_does_not_contain_issuing_ca_url", + Description: "Subordinate CA Certificate: authorityInformationAccess SHOULD also contain the HTTP URL of the Issuing CA's certificate.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCaIssuerUrl{}, + }) +} + +func (l *subCaIssuerUrl) Initialize() error { + return nil +} + +func (l *subCaIssuerUrl) CheckApplies(c *x509.Certificate) bool { + return util.IsCACert(c) && !util.IsRootCA(c) +} + +func (l *subCaIssuerUrl) Execute(c *x509.Certificate) *lint.LintResult { + for _, url := range c.IssuingCertificateURL { + if strings.HasPrefix(url, "http://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Warn} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go new file mode 100644 index 0000000000..247a1b8bc4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCaAIAMarkedCritical struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_ca_aia_marked_critical", + Description: "Subordinate CA Certificate: authorityInformationAccess MUST NOT be marked critical", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + Lint: &subCaAIAMarkedCritical{}, + }) +} + +func (l *subCaAIAMarkedCritical) Initialize() error { + return nil +} + +func (l *subCaAIAMarkedCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && util.IsExtInCert(c, util.AiaOID) +} + +func (l *subCaAIAMarkedCritical) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.AiaOID) + if e.Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go new file mode 100644 index 0000000000..14c70565e9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caAiaMissing struct{} + +/*********************************************** +CAB 7.1.2.2c +With the exception of stapling, which is noted below, this extension MUST be present. It MUST NOT be +marked critical, and it MUST contain the HTTP URL of the Issuing CA’s OCSP responder (accessMethod += 1.3.6.1.5.5.7.48.1). It SHOULD also contain the HTTP URL of the Issuing CA’s certificate +(accessMethod = 1.3.6.1.5.5.7.48.2). +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_ca_aia_missing", + Description: "Subordinate CA Certificate: authorityInformationAccess MUST be present, with the exception of stapling.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &caAiaMissing{}, + }) +} + +func (l *caAiaMissing) Initialize() error { + return nil +} + +func (l *caAiaMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsCACert(c) && !util.IsRootCA(c) +} + +func (l *caAiaMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.AiaOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go new file mode 100644 index 0000000000..a0932fc24b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCACertPolicyCrit struct{} + +/************************************************ +BRs: 7.1.2.2a certificatePolicies +This extension MUST be present and SHOULD NOT be marked critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_ca_certificate_policies_marked_critical", + Description: "Subordinate CA certificates certificatePolicies extension should not be marked as critical", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCACertPolicyCrit{}, + }) +} + +func (l *subCACertPolicyCrit) Initialize() error { + return nil +} + +func (l *subCACertPolicyCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && util.IsExtInCert(c, util.CertPolicyOID) +} + +func (l *subCACertPolicyCrit) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.CertPolicyOID); e.Critical { + return &lint.LintResult{Status: lint.Warn} + } else { + return &lint.LintResult{Status: lint.Pass} + } + +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go new file mode 100644 index 0000000000..636274e3e2 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go @@ -0,0 +1,55 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCACertPolicyMissing struct{} + +/************************************************ +BRs: 7.1.2.2a certificatePolicies +This extension MUST be present and SHOULD NOT be marked critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_ca_certificate_policies_missing", + Description: "Subordinate CA certificates must have a certificatePolicies extension", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCACertPolicyMissing{}, + }) +} + +func (l *subCACertPolicyMissing) Initialize() error { + return nil +} + +func (l *subCACertPolicyMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) +} + +func (l *subCACertPolicyMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.CertPolicyOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go new file mode 100644 index 0000000000..7e377534c8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCACRLDistNoUrl struct{} + +/************************************************ +BRs: 7.1.2.2b cRLDistributionPoints +This extension MUST be present and MUST NOT be marked critical. +It MUST contain the HTTP URL of the CA’s CRL service. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_ca_crl_distribution_points_does_not_contain_url", + Description: "Subordinate CA Certificate: cRLDistributionPoints MUST contain the HTTP URL of the CA's CRL service.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCACRLDistNoUrl{}, + }) +} + +func (l *subCACRLDistNoUrl) Initialize() error { + return nil +} + +func (l *subCACRLDistNoUrl) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && util.IsExtInCert(c, util.CrlDistOID) +} + +func (l *subCACRLDistNoUrl) Execute(c *x509.Certificate) *lint.LintResult { + for _, s := range c.CRLDistributionPoints { + if strings.HasPrefix(s, "http://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go new file mode 100644 index 0000000000..a04c39f767 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCACRLDistCrit struct{} + +/************************************************ +BRs: 7.1.2.2b cRLDistributionPoints +This extension MUST be present and MUST NOT be marked critical. +It MUST contain the HTTP URL of the CA’s CRL service. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_ca_crl_distribution_points_marked_critical", + Description: "Subordinate CA Certificate: cRLDistributionPoints MUST be present and MUST NOT be marked critical.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCACRLDistCrit{}, + }) +} + +func (l *subCACRLDistCrit) Initialize() error { + return nil +} + +func (l *subCACRLDistCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && util.IsExtInCert(c, util.CrlDistOID) +} + +func (l *subCACRLDistCrit) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.CrlDistOID); e.Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go new file mode 100644 index 0000000000..7f12361834 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCACRLDistMissing struct{} + +/************************************************ +BRs: 7.1.2.2b cRLDistributionPoints +This extension MUST be present and MUST NOT be marked critical. +It MUST contain the HTTP URL of the CA’s CRL service. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_ca_crl_distribution_points_missing", + Description: "Subordinate CA Certificate: cRLDistributionPoints MUST be present and MUST NOT be marked critical.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCACRLDistMissing{}, + }) +} + +func (l *subCACRLDistMissing) Initialize() error { + return nil +} + +func (l *subCACRLDistMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) +} + +func (l *subCACRLDistMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.CrlDistOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go new file mode 100644 index 0000000000..5bb416d41f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCAEKUCrit struct{} + +/************************************************ +BRs: 7.1.2.2g extkeyUsage (optional) +For Subordinate CA Certificates to be Technically constrained in line with section 7.1.5, then either the value +id‐kp‐serverAuth [RFC5280] or id‐kp‐clientAuth [RFC5280] or both values MUST be present**. +Other values MAY be present. +If present, this extension SHOULD be marked non‐critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_ca_eku_critical", + Description: "Subordinate CA certificate extkeyUsage extension should be marked non-critical if present", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV116Date, + Lint: &subCAEKUCrit{}, + }) +} + +func (l *subCAEKUCrit) Initialize() error { + return nil +} + +func (l *subCAEKUCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && util.IsExtInCert(c, util.EkuSynOid) +} + +func (l *subCAEKUCrit) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.EkuSynOid); e.Critical { + return &lint.LintResult{Status: lint.Warn} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go new file mode 100644 index 0000000000..31add62b3f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go @@ -0,0 +1,50 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCAEKUMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_sub_ca_eku_missing", + Description: "To be considered Technically Constrained, the Subordinate CA certificate MUST have extkeyUsage extension", + Citation: "BRs: 7.1.5", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCAEKUMissing{}, + }) +} + +func (l *subCAEKUMissing) Initialize() error { + return nil +} + +func (l *subCAEKUMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) +} + +func (l *subCAEKUMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.EkuSynOid) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Notice} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go new file mode 100644 index 0000000000..1893dfcb24 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go @@ -0,0 +1,57 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCAEKUValidFields struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_sub_ca_eku_not_technically_constrained", + Description: "Subordinate CA extkeyUsage, either id-kp-serverAuth or id-kp-clientAuth or both values MUST be present to be technically constrained.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV116Date, + Lint: &subCAEKUValidFields{}, + }) +} + +func (l *subCAEKUValidFields) Initialize() error { + return nil +} + +func (l *subCAEKUValidFields) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && util.IsExtInCert(c, util.EkuSynOid) +} + +func (l *subCAEKUValidFields) Execute(c *x509.Certificate) *lint.LintResult { + validFieldsPresent := false + for _, ekuValue := range c.ExtKeyUsage { + if ekuValue == x509.ExtKeyUsageServerAuth || + ekuValue == x509.ExtKeyUsageClientAuth { + validFieldsPresent = true + } + } + if validFieldsPresent { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Notice} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go new file mode 100644 index 0000000000..24fb899327 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go @@ -0,0 +1,61 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubCANameConstraintsNotCritical struct{} + +/************************************************ +CA Brower Forum Baseline Requirements, Section 7.1.2.2: + + f. nameConstraints (optional) +If present, this extension SHOULD be marked critical*. + +* Non-critical Name Constraints are an exception to RFC 5280 (4.2.1.10), however, they MAY be used until the +Name Constraints extension is supported by Application Software Suppliers whose software is used by a +substantial portion of Relying Parties worldwide +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_ca_name_constraints_not_critical", + Description: "Subordinate CA Certificate: NameConstraints if present, SHOULD be marked critical.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABV102Date, + Lint: &SubCANameConstraintsNotCritical{}, + }) +} + +func (l *SubCANameConstraintsNotCritical) Initialize() error { + return nil +} + +func (l *SubCANameConstraintsNotCritical) CheckApplies(cert *x509.Certificate) bool { + return util.IsSubCA(cert) && util.IsExtInCert(cert, util.NameConstOID) +} + +func (l *SubCANameConstraintsNotCritical) Execute(cert *x509.Certificate) *lint.LintResult { + if ski := util.GetExtFromCert(cert, util.NameConstOID); ski.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go new file mode 100644 index 0000000000..2d8b98e34d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertIssuerUrl struct{} + +/************************************************************************ +BRs: 7.1.2.3 +cRLDistributionPoints +This extension MAY be present. If present, it MUST NOT be marked critical, and it MUST contain the +HTTP URL of the CA’s CRL service. +*************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_cert_aia_does_not_contain_issuing_ca_url", + Description: "Subscriber certificates authorityInformationAccess extension should contain the HTTP URL of the issuing CA’s certificate", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertIssuerUrl{}, + }) +} + +func (l *subCertIssuerUrl) Initialize() error { + return nil +} + +func (l *subCertIssuerUrl) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertIssuerUrl) Execute(c *x509.Certificate) *lint.LintResult { + for _, url := range c.IssuingCertificateURL { + if strings.HasPrefix(url, "http://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Warn} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go new file mode 100644 index 0000000000..3bbd9bb052 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertOcspUrl struct{} + +/************************************************************************************************** +BRs: 7.1.2.3 +authorityInformationAccess +This extension MUST be present. It MUST NOT be marked critical, and it MUST contain +the HTTP URL of the Issuing CA’s OCSP responder (accessMethod = 1.3.6.1.5.5.7.48.1). +It SHOULD also contain the HTTP URL of the Issuing CA’s certificate (accessMethod = +1.3.6.1.5.5.7.48.2). +***************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_aia_does_not_contain_ocsp_url", + Description: "Subscriber Certificate: authorityInformationAccess MUST contain the HTTP URL of the Issuing CA's OSCP responder.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertOcspUrl{}, + }) +} + +func (l *subCertOcspUrl) Initialize() error { + return nil +} + +func (l *subCertOcspUrl) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *subCertOcspUrl) Execute(c *x509.Certificate) *lint.LintResult { + for _, url := range c.OCSPServer { + if strings.HasPrefix(url, "http://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go new file mode 100644 index 0000000000..7429b758ec --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertAiaMarkedCritical struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_aia_marked_critical", + Description: "Subscriber Certificate: authorityInformationAccess MUST NOT be marked critical", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertAiaMarkedCritical{}, + }) +} + +func (l *subCertAiaMarkedCritical) Initialize() error { + return nil +} + +func (l *subCertAiaMarkedCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.IsExtInCert(c, util.AiaOID) +} + +func (l *subCertAiaMarkedCritical) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.AiaOID) + if e.Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go new file mode 100644 index 0000000000..90278c4032 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go @@ -0,0 +1,59 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertAiaMissing struct{} + +/************************************************************************************************** +BRs: 7.1.2.3 +authorityInformationAccess +With the exception of stapling, which is noted below, this extension MUST be present. It MUST NOT be +marked critical, and it MUST contain the HTTP URL of the Issuing CA’s OCSP responder (accessMethod += 1.3.6.1.5.5.7.48.1). It SHOULD also contain the HTTP URL of the Issuing CA’s certificate +(accessMethod = 1.3.6.1.5.5.7.48.2). See Section 13.2.1 for details. +***************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_aia_missing", + Description: "Subscriber Certificate: authorityInformationAccess MUST be present.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertAiaMissing{}, + }) +} + +func (l *subCertAiaMissing) Initialize() error { + return nil +} + +func (l *subCertAiaMissing) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *subCertAiaMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.AiaOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go new file mode 100644 index 0000000000..5da91655f0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go @@ -0,0 +1,50 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertPolicyEmpty struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_cert_policy_empty", + Description: "Subscriber certificates must contain at least one policy identifier that indicates adherence to CAB standards", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertPolicyEmpty{}, + }) +} + +func (l *subCertPolicyEmpty) Initialize() error { + return nil +} + +func (l *subCertPolicyEmpty) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *subCertPolicyEmpty) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.CertPolicyOID) && c.PolicyIdentifiers != nil { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go new file mode 100644 index 0000000000..da89e0f5ee --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go @@ -0,0 +1,57 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertPolicyCrit struct{} + +/****************************************************************************** +BRs: 7.1.2.3 +certificatePolicies +This extension MUST be present and SHOULD NOT be marked critical. +******************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_cert_certificate_policies_marked_critical", + Description: "Subscriber Certificate: certificatePolicies MUST be present and SHOULD NOT be marked critical.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertPolicyCrit{}, + }) +} + +func (l *subCertPolicyCrit) Initialize() error { + return nil +} + +func (l *subCertPolicyCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CertPolicyOID) +} + +func (l *subCertPolicyCrit) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.CertPolicyOID) + if !e.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go new file mode 100644 index 0000000000..95dbb20e80 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertPolicy struct{} + +/****************************************************************************** +BRs: 7.1.2.3 +certificatePolicies +This extension MUST be present and SHOULD NOT be marked critical. +******************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_certificate_policies_missing", + Description: "Subscriber Certificate: certificatePolicies MUST be present and SHOULD NOT be marked critical.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertPolicy{}, + }) +} + +func (l *subCertPolicy) Initialize() error { + return nil +} + +func (l *subCertPolicy) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *subCertPolicy) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.CertPolicyOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go new file mode 100644 index 0000000000..033407bc3e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertCountryNameMustAppear struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_country_name_must_appear", + Description: "Subscriber Certificate: subject:countryName MUST appear if the subject:organizationName field, subject:givenName field, or subject:surname fields are present.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertCountryNameMustAppear{}, + }) +} + +func (l *subCertCountryNameMustAppear) Initialize() error { + return nil +} + +func (l *subCertCountryNameMustAppear) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertCountryNameMustAppear) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.Subject.Organization) > 0 || len(c.Subject.GivenName) > 0 || len(c.Subject.Surname) > 0 { + if len(c.Subject.Country) == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go new file mode 100644 index 0000000000..7e81f60b88 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCRLDistNoURL struct{} + +/******************************************************************************************************* +BRs: 7.1.2.3 +cRLDistributionPoints +This extension MAY be present. If present, it MUST NOT be marked critical, and it MUST contain the HTTP +URL of the CA’s CRL service. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_crl_distribution_points_does_not_contain_url", + Description: "Subscriber certificate cRLDistributionPoints extension must contain the HTTP URL of the CA’s CRL service", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCRLDistNoURL{}, + }) +} + +func (l *subCRLDistNoURL) Initialize() error { + return nil +} + +func (l *subCRLDistNoURL) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CrlDistOID) +} + +func (l *subCRLDistNoURL) Execute(c *x509.Certificate) *lint.LintResult { + for _, s := range c.CRLDistributionPoints { + if strings.HasPrefix(s, "http://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go new file mode 100644 index 0000000000..aa4cc8caaf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCrlDistCrit struct{} + +/******************************************************************************************************* +BRs: 7.1.2.3 +cRLDistributionPoints +This extension MAY be present. If present, it MUST NOT be marked critical, and it MUST contain the HTTP +URL of the CA’s CRL service. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_crl_distribution_points_marked_critical", + Description: "Subscriber Certificate: cRLDistributionPoints MUST NOT be marked critical, and MUST contain the HTTP URL of the CA's CRL service.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCrlDistCrit{}, + }) +} + +func (l *subCrlDistCrit) Initialize() error { + return nil +} + +func (l *subCrlDistCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CrlDistOID) +} + +func (l *subCrlDistCrit) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.CrlDistOID) + if !e.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go new file mode 100644 index 0000000000..cd75f5958d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go @@ -0,0 +1,67 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subExtKeyUsageLegalUsage struct{} + +/******************************************************************************************************* +BRs: 7.1.2.3 +extKeyUsage (required) +Either the value id-kp-serverAuth [RFC5280] or id-kp-clientAuth [RFC5280] or +both values MUST be present. id-kp-emailProtection [RFC5280] MAY be present. +Other values SHOULD NOT be present. The value anyExtendedKeyUsage MUST NOT be +present. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_cert_eku_extra_values", + Description: "Subscriber Certificate: extKeyUsage values other than id-kp-serverAuth, id-kp-clientAuth, and id-kp-emailProtection SHOULD NOT be present.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subExtKeyUsageLegalUsage{}, + }) +} + +func (l *subExtKeyUsageLegalUsage) Initialize() error { + return nil +} + +func (l *subExtKeyUsageLegalUsage) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && c.ExtKeyUsage != nil +} + +func (l *subExtKeyUsageLegalUsage) Execute(c *x509.Certificate) *lint.LintResult { + for _, kp := range c.ExtKeyUsage { + if kp == x509.ExtKeyUsageServerAuth || + kp == x509.ExtKeyUsageClientAuth || + kp == x509.ExtKeyUsageEmailProtection { + // If we find any of these three, considered passing, continue + continue + } else { + // A bad usage was found, report and leave + return &lint.LintResult{Status: lint.Warn} + } + } + // If no bad usage was found, pass + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go new file mode 100644 index 0000000000..b18bbad87a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subExtKeyUsage struct{} + +/******************************************************************************************************* +BRs: 7.1.2.3 +extKeyUsage (required) +Either the value id-kp-serverAuth [RFC5280] or id-kp-clientAuth [RFC5280] or +both values MUST be present. id-kp-emailProtection [RFC5280] MAY be present. +Other values SHOULD NOT be present. The value anyExtendedKeyUsage MUST NOT be +present. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_eku_missing", + Description: "Subscriber certificates MUST have the extended key usage extension present", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subExtKeyUsage{}, + }) +} + +func (l *subExtKeyUsage) Initialize() error { + return nil +} + +func (l *subExtKeyUsage) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *subExtKeyUsage) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.EkuSynOid) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go new file mode 100644 index 0000000000..2ef26e02bb --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go @@ -0,0 +1,62 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subExtKeyUsageClientOrServer struct{} + +/******************************************************************************************************* +BRs: 7.1.2.3 +extKeyUsage (required) +Either the value id-kp-serverAuth [RFC5280] or id-kp-clientAuth [RFC5280] or +both values MUST be present. id-kp-emailProtection [RFC5280] MAY be present. +Other values SHOULD NOT be present. The value anyExtendedKeyUsage MUST NOT be +present. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_eku_server_auth_client_auth_missing", + Description: "Subscriber certificates MUST have have either id-kp-serverAuth or id-kp-clientAuth or both present in extKeyUsage", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subExtKeyUsageClientOrServer{}, + }) +} + +func (l *subExtKeyUsageClientOrServer) Initialize() error { + return nil +} + +func (l *subExtKeyUsageClientOrServer) CheckApplies(c *x509.Certificate) bool { + return c.ExtKeyUsage != nil +} + +func (l *subExtKeyUsageClientOrServer) Execute(c *x509.Certificate) *lint.LintResult { + for _, kp := range c.ExtKeyUsage { + if kp == x509.ExtKeyUsageServerAuth || kp == x509.ExtKeyUsageClientAuth { + // If we find either of ServerAuth or ClientAuth, lint.Pass + return &lint.LintResult{Status: lint.Pass} + } + } + // If neither were found, lint.Error + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go new file mode 100644 index 0000000000..e8d49a5a9a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go @@ -0,0 +1,52 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertSubjectGnOrSnContainsPolicy struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_given_name_surname_contains_correct_policy", + Description: "Subscriber Certificate: A certificate containing a subject:givenName field or subject:surname field MUST contain the (2.23.140.1.2.3) certPolicy OID.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertSubjectGnOrSnContainsPolicy{}, + }) +} + +func (l *subCertSubjectGnOrSnContainsPolicy) Initialize() error { + return nil +} + +func (l *subCertSubjectGnOrSnContainsPolicy) CheckApplies(c *x509.Certificate) bool { + //Check if GivenName or Surname fields are filled out + return util.IsSubscriberCert(c) && (len(c.Subject.GivenName) != 0 || len(c.Subject.Surname) != 0) +} + +func (l *subCertSubjectGnOrSnContainsPolicy) Execute(c *x509.Certificate) *lint.LintResult { + for _, policyIds := range c.PolicyIdentifiers { + if policyIds.Equal(util.BRIndividualValidatedOID) { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go new file mode 100644 index 0000000000..0c014483d6 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go @@ -0,0 +1,57 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertNotCA struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_not_is_ca", + Description: "Subscriber Certificate: basicContrainsts cA field MUST NOT be true.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertNotCA{}, + }) +} + +func (l *subCertNotCA) Initialize() error { + return nil +} + +func (l *subCertNotCA) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) && c.KeyUsage&x509.KeyUsageCertSign == 0 && util.IsExtInCert(c, util.BasicConstOID) +} + +func (l *subCertNotCA) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.BasicConstOID) + var constraints basicConstraints + if _, err := asn1.Unmarshal(e.Value, &constraints); err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if constraints.IsCA { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go new file mode 100644 index 0000000000..584b8a9fbc --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertKeyUsageBitSet struct{} + +/************************************************************************** +BRs: 7.1.2.3 +keyUsage (optional) +If present, bit positions for keyCertSign and cRLSign MUST NOT be set. +***************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_key_usage_cert_sign_bit_set", + Description: "Subscriber Certificate: keyUsage if present, bit positions for keyCertSign and cRLSign MUST NOT be set.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCertKeyUsageBitSet{}, + }) +} + +func (l *subCertKeyUsageBitSet) Initialize() error { + return nil +} + +func (l *subCertKeyUsageBitSet) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) && !util.IsCACert(c) +} + +func (l *subCertKeyUsageBitSet) Execute(c *x509.Certificate) *lint.LintResult { + if (c.KeyUsage & x509.KeyUsageCertSign) == x509.KeyUsageCertSign { + return &lint.LintResult{Status: lint.Error} + } else { //key usage doesn't allow cert signing or isn't present + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go new file mode 100644 index 0000000000..fb44f79bab --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go @@ -0,0 +1,56 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCrlSignAllowed struct{} + +/************************************************************************** +BRs: 7.1.2.3 +keyUsage (optional) +If present, bit positions for keyCertSign and cRLSign MUST NOT be set. +***************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_key_usage_crl_sign_bit_set", + Description: "Subscriber Certificate: keyUsage if present, bit positions for keyCertSign and cRLSign MUST NOT be set.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subCrlSignAllowed{}, + }) +} + +func (l *subCrlSignAllowed) Initialize() error { + return nil +} + +func (l *subCrlSignAllowed) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) && !util.IsCACert(c) +} + +func (l *subCrlSignAllowed) Execute(c *x509.Certificate) *lint.LintResult { + if (c.KeyUsage & x509.KeyUsageCRLSign) == x509.KeyUsageCRLSign { + return &lint.LintResult{Status: lint.Error} + } else { //key usage doesn't allow cert signing or isn't present + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go new file mode 100644 index 0000000000..6333100d5f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go @@ -0,0 +1,53 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertLocalityNameMustAppear struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_locality_name_must_appear", + Description: "Subscriber Certificate: subject:localityName MUST appear if subject:organizationName, subject:givenName, or subject:surname fields are present but the subject:stateOrProvinceName field is absent.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertLocalityNameMustAppear{}, + }) +} + +func (l *subCertLocalityNameMustAppear) Initialize() error { + return nil +} + +func (l *subCertLocalityNameMustAppear) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertLocalityNameMustAppear) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.Subject.Organization) > 0 || len(c.Subject.GivenName) > 0 || len(c.Subject.Surname) > 0 { + if len(c.Subject.Province) == 0 { + if len(c.Subject.Locality) == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go new file mode 100644 index 0000000000..eca2b85397 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertLocalityNameMustNotAppear struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_locality_name_must_not_appear", + Description: "Subscriber Certificate: subject:localityName MUST NOT appear if subject:organizationName, subject:givenName, and subject:surname fields are absent.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertLocalityNameMustNotAppear{}, + }) +} + +func (l *subCertLocalityNameMustNotAppear) Initialize() error { + return nil +} + +func (l *subCertLocalityNameMustNotAppear) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertLocalityNameMustNotAppear) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.Subject.Organization) == 0 && len(c.Subject.GivenName) == 0 && len(c.Subject.Surname) == 0 { + if len(c.Subject.Locality) > 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go new file mode 100644 index 0000000000..157ce654ea --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go @@ -0,0 +1,54 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sigAlgTestsSHA1 struct{} + +/************************************************************************************************** +BRs: 7.1.3 +SHA‐1 MAY be used with RSA keys in accordance with the criteria defined in Section 7.1.3. +**************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_or_sub_ca_using_sha1", + Description: "CAs MUST NOT issue any new Subscriber certificates or Subordinate CA certificates using SHA-1 after 1 January 2016", + Citation: "BRs: 7.1.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.NO_SHA1, + Lint: &sigAlgTestsSHA1{}, + }) +} + +func (l *sigAlgTestsSHA1) Initialize() error { + return nil +} + +func (l *sigAlgTestsSHA1) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *sigAlgTestsSHA1) Execute(c *x509.Certificate) *lint.LintResult { + if c.SignatureAlgorithm == x509.SHA1WithRSA || c.SignatureAlgorithm == x509.DSAWithSHA1 || c.SignatureAlgorithm == x509.ECDSAWithSHA1 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go new file mode 100644 index 0000000000..f62129005d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go @@ -0,0 +1,52 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertPostalCodeMustNotAppear struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_postal_code_must_not_appear", + Description: "Subscriber Certificate: subject:postalCode MUST NOT appear if the subject:organizationName field, subject:givenName field, or subject:surname fields are absent.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertPostalCodeMustNotAppear{}, + }) +} + +func (l *subCertPostalCodeMustNotAppear) Initialize() error { + return nil +} + +func (l *subCertPostalCodeMustNotAppear) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertPostalCodeMustNotAppear) Execute(c *x509.Certificate) *lint.LintResult { + // BR 7.1.4.2.2 uses "or" and "and" interchangeably when they mean "and". + if len(c.Subject.Organization) == 0 && len(c.Subject.GivenName) == 0 && len(c.Subject.Surname) == 0 { + if len(c.Subject.PostalCode) > 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go new file mode 100644 index 0000000000..ec46039306 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go @@ -0,0 +1,53 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertProvinceMustAppear struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_province_must_appear", + Description: "Subscriber Certificate: subject:stateOrProvinceName MUST appear if the subject:organizationName, subject:givenName, or subject:surname fields are present and subject:localityName is absent.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertProvinceMustAppear{}, + }) +} + +func (l *subCertProvinceMustAppear) Initialize() error { + return nil +} + +func (l *subCertProvinceMustAppear) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertProvinceMustAppear) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.Subject.Organization) > 0 || len(c.Subject.GivenName) > 0 || len(c.Subject.Surname) > 0 { + if len(c.Subject.Locality) == 0 { + if len(c.Subject.Province) == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go new file mode 100644 index 0000000000..b61fdca2e7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go @@ -0,0 +1,51 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertProvinceMustNotAppear struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_province_must_not_appear", + Description: "Subscriber Certificate: subject:stateOrProvinceName MUST NOT appear if the subject:organizationName, subject:givenName, and subject:surname fields are absent.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertProvinceMustNotAppear{}, + }) +} + +func (l *subCertProvinceMustNotAppear) Initialize() error { + return nil +} + +func (l *subCertProvinceMustNotAppear) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertProvinceMustNotAppear) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.Subject.Organization) == 0 && len(c.Subject.GivenName) == 0 && len(c.Subject.Surname) == 0 { + if len(c.Subject.Province) > 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go new file mode 100644 index 0000000000..533584d178 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go @@ -0,0 +1,61 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sha1ExpireLong struct{} + +/*************************************************************************************************************** +Effective 16 January 2015, CAs SHOULD NOT issue Subscriber Certificates utilizing the SHA‐1 algorithm with +an Expiry Date greater than 1 January 2017 because Application Software Providers are in the process of +deprecating and/or removing the SHA‐1 algorithm from their software, and they have communicated that +CAs and Subscribers using such certificates do so at their own risk. +****************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_cert_sha1_expiration_too_long", + Description: "Subscriber certificates using the SHA-1 algorithm SHOULD NOT have an expiration date later than 1 Jan 2017", + Citation: "BRs: 7.1.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: time.Date(2015, time.January, 16, 0, 0, 0, 0, time.UTC), + Lint: &sha1ExpireLong{}, + }) +} + +func (l *sha1ExpireLong) Initialize() error { + return nil +} + +func (l *sha1ExpireLong) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) && (c.SignatureAlgorithm == x509.SHA1WithRSA || + c.SignatureAlgorithm == x509.DSAWithSHA1 || + c.SignatureAlgorithm == x509.ECDSAWithSHA1) +} + +func (l *sha1ExpireLong) Execute(c *x509.Certificate) *lint.LintResult { + if c.NotAfter.After(time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)) { + return &lint.LintResult{Status: lint.Warn} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go new file mode 100644 index 0000000000..9f3b39c7a3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go @@ -0,0 +1,52 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertStreetAddressShouldNotExist struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_street_address_should_not_exist", + Description: "Subscriber Certificate: subject:streetAddress MUST NOT appear if subject:organizationName, subject:givenName, and subject:surname fields are absent.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABGivenNameDate, + Lint: &subCertStreetAddressShouldNotExist{}, + }) +} + +func (l *subCertStreetAddressShouldNotExist) Initialize() error { + return nil +} + +func (l *subCertStreetAddressShouldNotExist) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertStreetAddressShouldNotExist) Execute(c *x509.Certificate) *lint.LintResult { + //If all fields are absent + if len(c.Subject.Organization) == 0 && len(c.Subject.GivenName) == 0 && len(c.Subject.Surname) == 0 { + if len(c.Subject.StreetAddress) > 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go new file mode 100644 index 0000000000..9a2e8d8fd9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go @@ -0,0 +1,49 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertValidTimeLongerThan39Months struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_valid_time_longer_than_39_months", + Description: "Subscriber Certificates issued after 1 July 2016 but prior to 1 March 2018 MUST have a Validity Period no greater than 39 months.", + Citation: "BRs: 6.3.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.SubCert39Month, + Lint: &subCertValidTimeLongerThan39Months{}, + }) +} + +func (l *subCertValidTimeLongerThan39Months) Initialize() error { + return nil +} + +func (l *subCertValidTimeLongerThan39Months) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertValidTimeLongerThan39Months) Execute(c *x509.Certificate) *lint.LintResult { + if c.NotBefore.AddDate(0, 39, 0).Before(c.NotAfter) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go new file mode 100644 index 0000000000..687a1c50e7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go @@ -0,0 +1,49 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subCertValidTimeLongerThan825Days struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_sub_cert_valid_time_longer_than_825_days", + Description: "Subscriber Certificates issued after 1 March 2018, but prior to 1 September 2020, MUST NOT have a Validity Period greater than 825 days.", + Citation: "BRs: 6.3.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.SubCert825Days, + Lint: &subCertValidTimeLongerThan825Days{}, + }) +} + +func (l *subCertValidTimeLongerThan825Days) Initialize() error { + return nil +} + +func (l *subCertValidTimeLongerThan825Days) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func (l *subCertValidTimeLongerThan825Days) Execute(c *x509.Certificate) *lint.LintResult { + if c.NotBefore.AddDate(0, 0, 825).Before(c.NotAfter) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go new file mode 100644 index 0000000000..9ded4d9b9b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go @@ -0,0 +1,55 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type commonNames struct{} + +/*************************************************************** +BRs: 7.1.4.2.2 +Required/Optional: Deprecated (Discouraged, but not prohibited) +***************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_subject_common_name_included", + Description: "Subscriber Certificate: commonName is deprecated.", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &commonNames{}, + }) +} + +func (l *commonNames) Initialize() error { + return nil +} + +func (l *commonNames) CheckApplies(c *x509.Certificate) bool { + return !util.IsCACert(c) +} + +func (l *commonNames) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName == "" { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Notice} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go new file mode 100644 index 0000000000..ae8f382b88 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go @@ -0,0 +1,69 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectCommonNameNotFromSAN struct{} + +/************************************************ +BRs: 7.1.4.2.2 +If present, this field MUST contain a single IP address +or Fully‐Qualified Domain Name that is one of the values +contained in the Certificate’s subjectAltName extension (see Section 7.1.4.2.1). +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_common_name_not_from_san", + Description: "The common name field in subscriber certificates must include only names from the SAN extension", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subjectCommonNameNotFromSAN{}, + }) +} + +func (l *subjectCommonNameNotFromSAN) Initialize() error { + return nil +} + +func (l *subjectCommonNameNotFromSAN) CheckApplies(c *x509.Certificate) bool { + return c.Subject.CommonName != "" && !util.IsCACert(c) +} + +func (l *subjectCommonNameNotFromSAN) Execute(c *x509.Certificate) *lint.LintResult { + cn := c.Subject.CommonName + + for _, dn := range c.DNSNames { + if strings.EqualFold(cn, dn) { + return &lint.LintResult{Status: lint.Pass} + } + } + + for _, ip := range c.IPAddresses { + if cn == ip.String() { + return &lint.LintResult{Status: lint.Pass} + } + } + + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go new file mode 100644 index 0000000000..6ecea2ff0f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go @@ -0,0 +1,150 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + "net" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +// arpaMalformedIP is a linter that warns for malformed names under the +// .in-addr.arpa or .ip6.arpa zones. +// See also: lint_subject_contains_reserved_arpa_ip.go for a lint that ensures +// well formed rDNS names in these zones do not specify an address in a IANA +// reserved network. +type arpaMalformedIP struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_subject_contains_malformed_arpa_ip", + Description: "Checks no subject domain name contains a rDNS entry in the " + + "registry-controlled .arpa zone with the wrong number of labels, or " + + "an invalid IP address (RFC 3596, BCP49)", + // NOTE(@cpu): 3.2.2.6 is particular to wildcard domain validation for names + // in a registry controlled zone (like .arpa), which would be an appropriate + // citation for when this lint finds a rDNS entry with the wrong + // number of labels/invalid IP because of the presence of a wildcard + // character. There is a larger on-going discussion[0] on the BRs stance on + // the .arpa zone entries that may produce a better citation to use here. + // + // [0]: https://github.com/cabforum/documents/issues/153 + Citation: "BRs: 3.2.2.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &arpaMalformedIP{}, + }) +} + +// Initialize for an arpaMalformedIP linter is a NOP to statisfy linting +// interfaces. +func (l *arpaMalformedIP) Initialize() error { + return nil +} + +// CheckApplies returns true if the certificate contains any names that end in +// one of the two designated zones for reverse DNS: in-addr.arpa or ip6.arpa. +func (l *arpaMalformedIP) CheckApplies(c *x509.Certificate) bool { + names := append([]string{c.Subject.CommonName}, c.DNSNames...) + for _, name := range names { + name = strings.ToLower(name) + if strings.HasSuffix(name, rdnsIPv4Suffix) || + strings.HasSuffix(name, rdnsIPv6Suffix) { + return true + } + } + return false +} + +// Execute will check the given certificate to ensure that all of the DNS +// subject alternate names that specify a reverse DNS name under the respective +// IPv4 or IPv6 arpa zones are well formed. A lint.Warn lint.LintResult is returned if +// the name is in a reverse DNS zone but has the wrong number of labels. +func (l *arpaMalformedIP) Execute(c *x509.Certificate) *lint.LintResult { + for _, name := range c.DNSNames { + name = strings.ToLower(name) + var err error + if strings.HasSuffix(name, rdnsIPv4Suffix) { + // If the name has the in-addr.arpa suffix then it should be an IPv4 reverse + // DNS name. + err = lintReversedIPAddressLabels(name, false) + } else if strings.HasSuffix(name, rdnsIPv6Suffix) { + // If the name has the ip6.arpa suffix then it should be an IPv6 reverse + // DNS name. + err = lintReversedIPAddressLabels(name, true) + } + // Return the first error as a negative lint result + if err != nil { + return &lint.LintResult{ + Status: lint.Warn, + Details: err.Error(), + } + } + } + + return &lint.LintResult{ + Status: lint.Pass, + } +} + +// lintReversedIPAddressLabels lints the given name as either a reversed IPv4 or +// IPv6 address under the respective ARPA zone based on the address class. An +// error is returned if there aren't enough labels in the name after removing +// the relevant arpa suffix. +func lintReversedIPAddressLabels(name string, ipv6 bool) error { + numRequiredLabels := rdnsIPv4Labels + zoneSuffix := rdnsIPv4Suffix + + if ipv6 { + numRequiredLabels = rdnsIPv6Labels + zoneSuffix = rdnsIPv6Suffix + } + + // Strip off the zone suffix to get only the reversed IP address + ipName := strings.TrimSuffix(name, zoneSuffix) + + // A well encoded IPv4 or IPv6 reverse DNS name will have the correct number + // of labels to express the address + ipLabels := strings.Split(ipName, ".") + if len(ipLabels) != numRequiredLabels { + return fmt.Errorf( + "name %q has too few leading labels (%d vs %d) to be a reverse DNS entry "+ + "in the %q zone.", + name, len(ipLabels), numRequiredLabels, zoneSuffix) + } + + // Reverse the IP labels and try to parse an IP address + var ip net.IP + if ipv6 { + ip = reversedLabelsToIPv6(ipLabels) + } else { + ip = reversedLabelsToIPv4(ipLabels) + } + + // If the result isn't an IP then a warning should be generated + if ip == nil { + return fmt.Errorf( + "the first %d labels of name %q did not parse as a reversed IP address", + numRequiredLabels, name) + } + + // Otherwise return no error - checking the actual value of the IP is left to + // `lint_subject_contains_reserved_arpa_ip.go`. + return nil +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go new file mode 100644 index 0000000000..fefe63e203 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go @@ -0,0 +1,80 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type illegalChar struct{} + +/********************************************************************************************************************** +BRs: 7.1.4.2.2 +Other Subject Attributes +With the exception of the subject:organizationalUnitName (OU) attribute, optional attributes, when present within +the subject field, MUST contain information that has been verified by the CA. Metadata such as ‘.’, ‘-‘, and ‘ ‘ (i.e. +space) characters, and/or any other indication that the value is absent, incomplete, or not applicable, SHALL NOT +be used. +**********************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_contains_noninformational_value", + Description: "Subject name fields must not contain '.','-',' ' or any other indication that the field has been omitted", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &illegalChar{}, + }) +} + +func (l *illegalChar) Initialize() error { + return nil +} + +func (l *illegalChar) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *illegalChar) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.Names { + value, ok := j.Value.(string) + if !ok { + continue + } + + if !checkAlphaNumericOrUTF8Present(value) { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("found only metadata %s in subjectDN attribute %s", value, j.Type.String())} + } + } + + return &lint.LintResult{Status: lint.Pass} +} + +// checkAlphaNumericOrUTF8Present checks if input string contains at least one occurrence of [a-Z0-9] or +// a UTF8 rune outside of ascii table +func checkAlphaNumericOrUTF8Present(input string) bool { + for _, r := range input { + if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r > 127 { + return true + } + } + + return false +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go new file mode 100644 index 0000000000..37b2d69f72 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go @@ -0,0 +1,233 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + "net" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +const ( + // arpaTLD holds a string constant for the .arpa TLD + arpaTLD = ".arpa" + + // rdnsIPv4Suffix is the expected suffix for IPv4 reverse DNS names as + // specified in https://tools.ietf.org/html/rfc1035#section-3.5 + rdnsIPv4Suffix = ".in-addr" + arpaTLD + // rndsIPv4Labels is the expected number of labels for an IPv4 reverse DNS + // name (not counting the rdnsIPv4Suffix labels). IPv4 addresses are four + // bytes. RFC 1035 uses one byte per label meaning there are 4 expected labels + // under the rdnsIPv4Suffix. + rdnsIPv4Labels = 4 + + // rdnsIPv6Suffix is the expected suffix for IPv6 reverse DNS names as + // specified in https://tools.ietf.org/html/rfc3596#section-2.5 + rdnsIPv6Suffix = ".ip6" + arpaTLD + // rndsIPv6Labels is the expected number of labels for an IPv6 reverse DNS + // name (not counting the rdnsIPv6Suffix labels). IPv6 addresses are 16 bytes. + // RFC 3596 Sec 2.5 uses one *nibble* per label meaning there are 16*2 + // expected labels under the rdnsIPv6Suffix. + rdnsIPv6Labels = 32 +) + +// arpaReservedIP is a linter that errors for any well formed rDNS names in the +// .in-addr.arpa or .ip6.arpa zones that specify an address in an IANA reserved +// network. +// See also: lint_subject_contains_malformed_arpa_ip.go for a lint that warns +// about malformed rDNS names in these zones. +type arpaReservedIP struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_contains_reserved_arpa_ip", + Description: "Checks no subject domain name contains a rDNS entry in an .arpa zone specifying a reserved IP address", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &arpaReservedIP{}, + }) +} + +// Initialize for an arpaReservedIP linter is a NOP to statisfy linting +// interfaces. +func (l *arpaReservedIP) Initialize() error { + return nil +} + +// CheckApplies returns true if the certificate contains any names that end in +// one of the two designated zones for reverse DNS: in-addr.arpa or ip6.arpa. +func (l *arpaReservedIP) CheckApplies(c *x509.Certificate) bool { + names := append([]string{c.Subject.CommonName}, c.DNSNames...) + for _, name := range names { + name = strings.ToLower(name) + if strings.HasSuffix(name, rdnsIPv4Suffix) || + strings.HasSuffix(name, rdnsIPv6Suffix) { + return true + } + } + return false +} + +// Execute will check the given certificate to ensure that all of the DNS +// subject alternate names that specify a well formed reverse DNS name under the +// respective IPv4 or IPv6 arpa zones do not specify an IP in an IANA +// reserved IP space. An lint.Error lint.LintResult is returned if the name specifies an +// IP address of the wrong class, or specifies an IP address in an IANA reserved +// network. +func (l *arpaReservedIP) Execute(c *x509.Certificate) *lint.LintResult { + for _, name := range c.DNSNames { + name = strings.ToLower(name) + var err error + if strings.HasSuffix(name, rdnsIPv4Suffix) { + // If the name has the in-addr.arpa suffix then it should be an IPv4 reverse + // DNS name. + err = lintReversedIPAddress(name, false) + } else if strings.HasSuffix(name, rdnsIPv6Suffix) { + // If the name has the ip6.arpa suffix then it should be an IPv6 reverse + // DNS name. + err = lintReversedIPAddress(name, true) + } + // Return the first error as a negative lint result + if err != nil { + return &lint.LintResult{ + Status: lint.Error, + Details: err.Error(), + } + } + } + + return &lint.LintResult{ + Status: lint.Pass, + } +} + +// reversedLabelsToIPv4 reverses the provided labels (assumed to be 4 labels, +// one per byte of the IPv6 address) and constructs an IPv4 address, returning +// the result of calling net.ParseIP for the constructed address. +func reversedLabelsToIPv4(labels []string) net.IP { + var buf strings.Builder + + // If there aren't the right number of labels, it isn't an IPv4 address. + if len(labels) != rdnsIPv4Labels { + return nil + } + + // An IPv4 address is represented as four groups of bytes separated by '.' + for i := len(labels) - 1; i >= 0; i-- { + buf.WriteString(labels[i]) + if i != 0 { + buf.WriteString(".") + } + } + return net.ParseIP(buf.String()) +} + +// reversedLabelsToIPv6 reverses the provided labels (assumed to be 32 labels, +// one per nibble of an IPv6 address) and constructs an IPv6 address, returning +// the result of calling net.ParseIP for the constructed address. +func reversedLabelsToIPv6(labels []string) net.IP { + var buf strings.Builder + + // If there aren't the right number of labels, it isn't an IPv6 address. + if len(labels) != rdnsIPv6Labels { + return nil + } + + // An IPv6 address is represented as eight groups of two bytes separated + // by `:` in hex form. Since each label in the rDNS form is one nibble we need + // four label components per IPv6 address component group. + for i := len(labels) - 1; i >= 0; i -= 4 { + buf.WriteString(labels[i]) + buf.WriteString(labels[i-1]) + buf.WriteString(labels[i-2]) + buf.WriteString(labels[i-3]) + if i > 4 { + buf.WriteString(":") + } + } + return net.ParseIP(buf.String()) +} + +// lintReversedIPAddress lints the given name as either a reversed IPv4 or IPv6 +// address under the respective ARPA zone based on the address class. An error +// is returned if: +// +// 1. The IP address labels parse as an IP of the wrong address class for the +// arpa suffix the name is using. +// 2. The IP address is within an IANA reserved range. +func lintReversedIPAddress(name string, ipv6 bool) error { + numRequiredLabels := rdnsIPv4Labels + zoneSuffix := rdnsIPv4Suffix + + if ipv6 { + numRequiredLabels = rdnsIPv6Labels + zoneSuffix = rdnsIPv6Suffix + } + + // Strip off the zone suffix to get only the reversed IP address + ipName := strings.TrimSuffix(name, zoneSuffix) + + // A well encoded IPv4 or IPv6 reverse DNS name will have the correct number + // of labels to express the address. If there isn't the right number of labels + // a separate `lint_subject_contains_malformed_arpa_ip.go` linter will flag it + // as a warning. This linter is specifically concerned with well formed rDNS + // that specifies a reserved IP. + ipLabels := strings.Split(ipName, ".") + if len(ipLabels) != numRequiredLabels { + return nil + } + + // Reverse the IP labels and try to parse an IP address + var ip net.IP + if ipv6 { + ip = reversedLabelsToIPv6(ipLabels) + } else { + ip = reversedLabelsToIPv4(ipLabels) + } + // If the result isn't an IP at all assume there is no problem - leave + // `lint_subject_contains_malformed_arpa_ip` to flag it as a warning. + if ip == nil { + return nil + } + + if !ipv6 && ip.To4() == nil { + // If we weren't expecting IPv6 and got it, that's a problem + return fmt.Errorf( + "the first %d labels of name %q parsed as a reversed IPv6 address but is "+ + "in the %q IPv4 reverse DNS zone.", + numRequiredLabels, name, rdnsIPv4Suffix) + } else if ipv6 && ip.To4() != nil { + // If we were expecting IPv6 and got an IPv4 address, that's a problem + return fmt.Errorf( + "the first %d labels of name %q parsed as a reversed IPv4 address but is "+ + "in the %q IPv4 reverse DNS zone.", + numRequiredLabels, name, rdnsIPv6Suffix) + } + + // If the IP address is in an IANA reserved space, that's a problem. + if util.IsIANAReserved(ip) { + return fmt.Errorf( + "the first %d labels of name %q parsed as a reversed IP address in "+ + "an IANA reserved IP space.", + numRequiredLabels, name) + } + + return nil +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go new file mode 100644 index 0000000000..6547857bcf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectReservedIP struct{} + +/************************************************ +BRs: 7.1.4.2.1 +Also as of the Effective Date, the CA SHALL NOT +issue a certificate with an Expiry Date later than +1 November 2015 with a subjectAlternativeName extension +or Subject commonName field containing a Reserved IP +Address or Internal Name. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_contains_reserved_ip", + Description: "Certificates expiring later than 11 Jan 2015 MUST NOT contain a reserved IP address in the common name field", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &subjectReservedIP{}, + }) +} + +func (l *subjectReservedIP) Initialize() error { + return nil +} + +func (l *subjectReservedIP) CheckApplies(c *x509.Certificate) bool { + return c.NotAfter.After(util.NoReservedIP) +} + +func (l *subjectReservedIP) Execute(c *x509.Certificate) *lint.LintResult { + if ip := net.ParseIP(c.Subject.CommonName); ip != nil && util.IsIANAReserved(ip) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go new file mode 100644 index 0000000000..71389890f1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go @@ -0,0 +1,61 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type countryNotIso struct{} + +/************************************************************************************************************** +BRs: 7.1.4.2.2 +Certificate Field: issuer:countryName (OID 2.5.4.6) +Required/Optional: Required +Contents: This field MUST contain the two-letter ISO 3166-1 country code for the country in which the issuer’s +place of business is located. +**************************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_country_not_iso", + Description: "The country name field MUST contain the two-letter ISO code for the country or XX", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: &countryNotIso{}, + }) +} + +func (l *countryNotIso) Initialize() error { + return nil +} + +func (l *countryNotIso) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *countryNotIso) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.Country { + if !util.IsISOCountryCode(strings.ToUpper(j)) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go new file mode 100644 index 0000000000..469b12c3e9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go @@ -0,0 +1,50 @@ +package cabf_ev + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type evNoBiz struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_business_category_missing", + Description: "EV certificates must include businessCategory in subject", + Citation: "EVGs: 9.2.3", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.ZeroDate, + Lint: &evNoBiz{}, + }) +} + +func (l *evNoBiz) Initialize() error { + return nil +} + +func (l *evNoBiz) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) && util.IsSubscriberCert(c) +} + +func (l *evNoBiz) Execute(c *x509.Certificate) *lint.LintResult { + if util.TypeInName(&c.Subject, util.BusinessOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go new file mode 100644 index 0000000000..fe9d71557e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go @@ -0,0 +1,50 @@ +package cabf_ev + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type evCountryMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_country_name_missing", + Description: "EV certificates must include countryName in subject", + Citation: "EVGs: 9.2.4", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.ZeroDate, + Lint: &evCountryMissing{}, + }) +} + +func (l *evCountryMissing) Initialize() error { + return nil +} + +func (l *evCountryMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) && util.IsSubscriberCert(c) +} + +func (l *evCountryMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.TypeInName(&c.Subject, util.CountryNameOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go new file mode 100644 index 0000000000..fca799b72d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go @@ -0,0 +1,53 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_ev + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type evOrgIdExtMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_organization_id_missing", + Description: "Effective January 31, 2020, if the subject:organizationIdentifier field is " + + "present, this [cabfOrganizationIdentifier] field MUST be present.", + Citation: "CA/Browser Forum EV Guidelines v1.7.0, Sec. 9.8.2", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.CABFEV_9_8_2, + Lint: &evOrgIdExtMissing{}, + }) +} + +func (l *evOrgIdExtMissing) Initialize() error { + return nil +} + +func (l *evOrgIdExtMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) && len(c.Subject.OrganizationIDs) > 0 +} + +func (l *evOrgIdExtMissing) Execute(c *x509.Certificate) *lint.LintResult { + if !util.IsExtInCert(c, util.CabfExtensionOrganizationIdentifier) { + return &lint.LintResult{ + Status: lint.Error, + Details: "subject:organizationIdentifier field is present in an EV certificate " + + "but the CA/Browser Forum Organization Identifier Field Extension is missing"} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go new file mode 100644 index 0000000000..34ceb20bfd --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go @@ -0,0 +1,50 @@ +package cabf_ev + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type evOrgMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_organization_name_missing", + Description: "EV certificates must include organizationName in subject", + Citation: "EVGs: 9.2.1", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.ZeroDate, + Lint: &evOrgMissing{}, + }) +} + +func (l *evOrgMissing) Initialize() error { + return nil +} + +func (l *evOrgMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) && util.IsSubscriberCert(c) +} + +func (l *evOrgMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.TypeInName(&c.Subject, util.OrganizationNameOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go new file mode 100644 index 0000000000..bfbfb04ad3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go @@ -0,0 +1,49 @@ +package cabf_ev + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type evSNMissing struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_serial_number_missing", + Description: "EV certificates must include serialNumber in subject", + Citation: "EVGs: 9.2.6", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.ZeroDate, + Lint: &evSNMissing{}, + }) +} + +func (l *evSNMissing) Initialize() error { + return nil +} + +func (l *evSNMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) && util.IsSubscriberCert(c) +} + +func (l *evSNMissing) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.Subject.SerialNumber) == 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go new file mode 100644 index 0000000000..e796a443ad --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go @@ -0,0 +1,54 @@ +package cabf_ev + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type evValidTooLong struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_valid_time_too_long", + Description: "EV certificates must be 27 months in validity or less", + Citation: "EVGs 1.0: 8(a), EVGs 1.6.1: 9.4", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.ZeroDate, + Lint: &evValidTooLong{}, + }) +} + +func (l *evValidTooLong) Initialize() error { + return nil +} + +func (l *evValidTooLong) CheckApplies(c *x509.Certificate) bool { + // CA/Browser Forum Ballot 193 changed the maximum validity period to be + // 825 days, which is more permissive than 27-month certificates, as that + // is 823 days. + return c.NotBefore.Before(util.SubCert825Days) && + util.IsSubscriberCert(c) && + util.IsEV(c.PolicyIdentifiers) +} + +func (l *evValidTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if c.NotBefore.AddDate(0, 27, 0).Before(c.NotAfter) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go new file mode 100644 index 0000000000..1efedcb007 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go @@ -0,0 +1,69 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_ev + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +const ( + // Ballot 144 specified: + // CAs MUST NOT issue a Certificate that includes a Domain Name where .onion + // is in the right-most label of the Domain Name with a validity period longer + // than 15 months + maxOnionValidityMonths = 15 +) + +type torValidityTooLarge struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_onion_subject_validity_time_too_large", + Description: fmt.Sprintf( + "certificates with .onion names can not be valid for more than %d months", + maxOnionValidityMonths), + Citation: "EVGs: Appendix F", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.OnionOnlyEVDate, + Lint: &torValidityTooLarge{}, + }) +} + +// Initialize for a torValidityTooLarge linter is a NOP. +func (l *torValidityTooLarge) Initialize() error { + return nil +} + +// CheckApplies returns true if the certificate is a subscriber certificate that +// contains a subject name ending in `.onion`. +func (l *torValidityTooLarge) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.CertificateSubjInTLD(c, util.OnionTLD) +} + +// Execute will return an lint.Error lint.LintResult if the provided certificate has +// a validity period longer than the maximum allowed validity for a certificate +// with a .onion subject. +func (l *torValidityTooLarge) Execute(c *x509.Certificate) *lint.LintResult { + if c.NotBefore.AddDate(0, maxOnionValidityMonths, 0).Before(c.NotAfter) { + return &lint.LintResult{ + Status: lint.Error, + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go new file mode 100644 index 0000000000..6629efb375 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type brIANBareWildcard struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ian_bare_wildcard", + Description: "A wildcard MUST be accompanied by other data to its right (Only checks IANDNSNames)", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &brIANBareWildcard{}, + }) +} + +func (l *brIANBareWildcard) Initialize() error { + return nil +} + +func (l *brIANBareWildcard) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *brIANBareWildcard) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.IANDNSNames { + if strings.HasSuffix(dns, "*") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go new file mode 100644 index 0000000000..9e29904b65 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANDNSNull struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ian_dns_name_includes_null_char", + Description: "DNSName MUST NOT include a null character", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &IANDNSNull{}, + }) +} + +func (l *IANDNSNull) Initialize() error { + return nil +} + +func (l *IANDNSNull) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANDNSNull) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.IANDNSNames { + for i := 0; i < len(dns); i++ { + if dns[i] == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go new file mode 100644 index 0000000000..e42fd77562 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANDNSPeriod struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ian_dns_name_starts_with_period", + Description: "DNSName MUST NOT start with a period", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &IANDNSPeriod{}, + }) +} + +func (l *IANDNSPeriod) Initialize() error { + return nil +} + +func (l *IANDNSPeriod) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANDNSPeriod) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.IANDNSNames { + if strings.HasPrefix(dns, ".") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go new file mode 100644 index 0000000000..290425045e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANPubSuffix struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ian_iana_pub_suffix_empty", + Description: "Domain SHOULD NOT have a bare public suffix", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &IANPubSuffix{}, + }) +} + +func (l *IANPubSuffix) Initialize() error { + return nil +} + +func (l *IANPubSuffix) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANPubSuffix) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.IANDNSNames { + if len(strings.Split(dns, ".")) < 3 { + return &lint.LintResult{Status: lint.Warn} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go new file mode 100644 index 0000000000..e9a4693b9a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type brIANWildcardFirst struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ian_wildcard_not_first", + Description: "A wildcard MUST be in the first label of FQDN (ie not: www.*.com) (Only checks IANDNSNames)", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &brIANWildcardFirst{}, + }) +} + +func (l *brIANWildcardFirst) Initialize() error { + return nil +} + +func (l *brIANWildcardFirst) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *brIANWildcardFirst) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.IANDNSNames { + for i := 1; i < len(dns); i++ { + if dns[i] == '*' { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go new file mode 100644 index 0000000000..74910d67a5 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go @@ -0,0 +1,63 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameRedacted struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_contains_redacted_dnsname", + Description: "Some precerts are redacted and of the form ?.?.a.com or *.?.a.com", + Source: lint.Community, + Citation: "IETF Draft: https://tools.ietf.org/id/draft-strad-trans-redaction-00.html", + EffectiveDate: util.ZeroDate, + Lint: &DNSNameRedacted{}, + }) +} + +func (l *DNSNameRedacted) Initialize() error { + return nil +} + +func (l *DNSNameRedacted) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) +} + +func isRedactedCertificate(domain string) bool { + domain = util.RemovePrependedWildcard(domain) + return strings.HasPrefix(domain, "?.") +} + +func (l *DNSNameRedacted) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.CommonName != "" { + if isRedactedCertificate(c.Subject.CommonName) { + return &lint.LintResult{Status: lint.Notice} + } + } + for _, domain := range c.DNSNames { + if isRedactedCertificate(domain) { + return &lint.LintResult{Status: lint.Notice} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go new file mode 100644 index 0000000000..7c87b5195c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IssuerDNLeadingSpace struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_issuer_dn_leading_whitespace", + Description: "AttributeValue in issuer RelativeDistinguishedName sequence SHOULD NOT have leading whitespace", + Citation: "lint.AWSLabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &IssuerDNLeadingSpace{}, + }) +} + +func (l *IssuerDNLeadingSpace) Initialize() error { + return nil +} + +func (l *IssuerDNLeadingSpace) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *IssuerDNLeadingSpace) Execute(c *x509.Certificate) *lint.LintResult { + leading, _, err := util.CheckRDNSequenceWhiteSpace(c.RawIssuer) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if leading { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go new file mode 100644 index 0000000000..67c69206b5 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IssuerDNTrailingSpace struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_issuer_dn_trailing_whitespace", + Description: "AttributeValue in issuer RelativeDistinguishedName sequence SHOULD NOT have trailing whitespace", + Citation: "lint.AWSLabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &IssuerDNTrailingSpace{}, + }) +} + +func (l *IssuerDNTrailingSpace) Initialize() error { + return nil +} + +func (l *IssuerDNTrailingSpace) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *IssuerDNTrailingSpace) Execute(c *x509.Certificate) *lint.LintResult { + _, trailing, err := util.CheckRDNSequenceWhiteSpace(c.RawIssuer) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if trailing { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go new file mode 100644 index 0000000000..780e65100d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go @@ -0,0 +1,59 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IssuerRDNHasMultipleAttribute struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_multiple_issuer_rdn", + Description: "Certificates should not have multiple attributes in a single RDN (issuer)", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &IssuerRDNHasMultipleAttribute{}, + }) +} + +func (l *IssuerRDNHasMultipleAttribute) Initialize() error { + return nil +} + +func (l *IssuerRDNHasMultipleAttribute) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *IssuerRDNHasMultipleAttribute) Execute(c *x509.Certificate) *lint.LintResult { + var issuer pkix.RDNSequence + _, err := asn1.Unmarshal(c.RawIssuer, &issuer) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + for _, rdn := range issuer { + if len(rdn) > 1 { + return &lint.LintResult{Status: lint.Warn} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go new file mode 100644 index 0000000000..03e9487159 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaExpNegative struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_exp_negative", + Description: "RSA public key exponent MUST be positive", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &rsaExpNegative{}, + }) +} + +func (l *rsaExpNegative) Initialize() error { + return nil +} + +func (l *rsaExpNegative) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaExpNegative) Execute(c *x509.Certificate) *lint.LintResult { + key := c.PublicKey.(*rsa.PublicKey) + if key.E < 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go new file mode 100644 index 0000000000..9b2eb14427 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaParsedPubKeyExist struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_no_public_key", + Description: "The RSA public key should be present", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &rsaParsedPubKeyExist{}, + }) +} + +func (l *rsaParsedPubKeyExist) Initialize() error { + return nil +} + +func (l *rsaParsedPubKeyExist) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA +} + +func (l *rsaParsedPubKeyExist) Execute(c *x509.Certificate) *lint.LintResult { + _, ok := c.PublicKey.(*rsa.PublicKey) + if !ok { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go new file mode 100644 index 0000000000..8dc7568d61 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type brSANBareWildcard struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_san_bare_wildcard", + Description: "A wildcard MUST be accompanied by other data to its right (Only checks DNSName)", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &brSANBareWildcard{}, + }) +} + +func (l *brSANBareWildcard) Initialize() error { + return nil +} + +func (l *brSANBareWildcard) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *brSANBareWildcard) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if strings.HasSuffix(dns, "*") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go new file mode 100644 index 0000000000..fb36c261ed --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go @@ -0,0 +1,58 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package community + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANDNSDuplicate struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_san_dns_name_duplicate", + Description: "SAN DNSName contains duplicate values", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SANDNSDuplicate{}, + }) +} + +func (l *SANDNSDuplicate) Initialize() error { + return nil +} + +func (l *SANDNSDuplicate) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANDNSDuplicate) Execute(c *x509.Certificate) *lint.LintResult { + checkedDNSNames := map[string]struct{}{} + for _, dns := range c.DNSNames { + normalizedDNSName := strings.ToLower(dns) + if _, isPresent := checkedDNSNames[normalizedDNSName]; isPresent { + return &lint.LintResult{Status: lint.Notice} + } + + checkedDNSNames[normalizedDNSName] = struct{}{} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go new file mode 100644 index 0000000000..b486d77f55 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANDNSNull struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_san_dns_name_includes_null_char", + Description: "DNSName MUST NOT include a null character", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SANDNSNull{}, + }) +} + +func (l *SANDNSNull) Initialize() error { + return nil +} + +func (l *SANDNSNull) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANDNSNull) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + for i := 0; i < len(dns); i++ { + if dns[i] == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go new file mode 100644 index 0000000000..3943620035 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANDNSPeriod struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_san_dns_name_starts_with_period", + Description: "DNSName MUST NOT start with a period", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SANDNSPeriod{}, + }) +} + +func (l *SANDNSPeriod) Initialize() error { + return nil +} + +func (l *SANDNSPeriod) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANDNSPeriod) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if strings.HasPrefix(dns, ".") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go new file mode 100644 index 0000000000..53be114dc8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go @@ -0,0 +1,67 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type pubSuffix struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_san_iana_pub_suffix_empty", + Description: "The domain SHOULD NOT have a bare public suffix", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &pubSuffix{}, + }) +} + +func (l *pubSuffix) Initialize() error { + return nil +} + +func (l *pubSuffix) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *pubSuffix) Execute(c *x509.Certificate) *lint.LintResult { + var badNames []string + for _, parsedName := range c.GetParsedDNSNames(false) { + if parseErr := parsedName.ParseError; parseErr == nil { + continue + } else if strings.HasSuffix(parseErr.Error(), "is a suffix") { + badNames = append(badNames, parsedName.DomainString) + } + } + + if badNamesCount := len(badNames); badNamesCount > 0 { + return &lint.LintResult{ + Status: lint.Notice, + Details: fmt.Sprintf( + "%d DNS name(s) are bare public suffixes: %s", + badNamesCount, strings.Join(badNames, ", ")), + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go new file mode 100644 index 0000000000..b94c7a07fe --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANWildCardFirst struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_san_wildcard_not_first", + Description: "A wildcard MUST be in the first label of FQDN (ie not: www.*.com) (Only checks DNSName)", + Citation: "awslabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SANWildCardFirst{}, + }) +} + +func (l *SANWildCardFirst) Initialize() error { + return nil +} + +func (l *SANWildCardFirst) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANWildCardFirst) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + for i := 1; i < len(dns); i++ { + if dns[i] == '*' { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go new file mode 100644 index 0000000000..fcd1328606 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectDNLeadingSpace struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_subject_dn_leading_whitespace", + Description: "AttributeValue in subject RelativeDistinguishedName sequence SHOULD NOT have leading whitespace", + Citation: "lint.AWSLabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SubjectDNLeadingSpace{}, + }) +} + +func (l *SubjectDNLeadingSpace) Initialize() error { + return nil +} + +func (l *SubjectDNLeadingSpace) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *SubjectDNLeadingSpace) Execute(c *x509.Certificate) *lint.LintResult { + leading, _, err := util.CheckRDNSequenceWhiteSpace(c.RawSubject) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if leading { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go new file mode 100644 index 0000000000..99ed4ea53d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go @@ -0,0 +1,53 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectDNTrailingSpace struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_subject_dn_trailing_whitespace", + Description: "AttributeValue in subject RelativeDistinguishedName sequence SHOULD NOT have trailing whitespace", + Citation: "lint.AWSLabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SubjectDNTrailingSpace{}, + }) +} + +func (l *SubjectDNTrailingSpace) Initialize() error { + return nil +} + +func (l *SubjectDNTrailingSpace) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *SubjectDNTrailingSpace) Execute(c *x509.Certificate) *lint.LintResult { + _, trailing, err := util.CheckRDNSequenceWhiteSpace(c.RawSubject) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if trailing { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go new file mode 100644 index 0000000000..e40b3e0fcc --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go @@ -0,0 +1,58 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectRDNHasMultipleAttribute struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_multiple_subject_rdn", + Description: "Certificates typically do not have have multiple attributes in a single RDN (subject). This may be an error.", + Citation: "lint.AWSLabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &SubjectRDNHasMultipleAttribute{}, + }) +} + +func (l *SubjectRDNHasMultipleAttribute) Initialize() error { + return nil +} + +func (l *SubjectRDNHasMultipleAttribute) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *SubjectRDNHasMultipleAttribute) Execute(c *x509.Certificate) *lint.LintResult { + var subject pkix.RDNSequence + if _, err := asn1.Unmarshal(c.RawSubject, &subject); err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + for _, rdn := range subject { + if len(rdn) > 1 { + return &lint.LintResult{Status: lint.Notice} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go new file mode 100644 index 0000000000..3a931ff5c8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go @@ -0,0 +1,49 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type validityNegative struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_validity_time_not_positive", + Description: "Certificates MUST have a positive time for which they are valid", + Citation: "lint.AWSLabs certlint", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: &validityNegative{}, + }) +} + +func (l *validityNegative) Initialize() error { + return nil +} + +func (l *validityNegative) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *validityNegative) Execute(c *x509.Certificate) *lint.LintResult { + if c.NotBefore.After(c.NotAfter) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go new file mode 100644 index 0000000000..f7ddd7cb9f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go @@ -0,0 +1,62 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcEtsiPresentQcsCritical struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_etsi_present_qcs_critical", + Description: "Checks that a QC Statement which contains any of the id-etsi-qcs-... QC Statements is not marked critical", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.1", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcEtsiPresentQcsCritical{}, + }) +} + +func (l *qcStatemQcEtsiPresentQcsCritical) Initialize() error { + return nil +} + +func (l *qcStatemQcEtsiPresentQcsCritical) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.IsAnyEtsiQcStatementPresent(util.GetExtFromCert(c, util.QcStateOid).Value) { + return true + } + return false +} + +func (l *qcStatemQcEtsiPresentQcsCritical) Execute(c *x509.Certificate) *lint.LintResult { + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + if ext.Critical { + errString = "ETSI QC Statement is present and QC Statements extension is marked critical" + } + + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go new file mode 100644 index 0000000000..d93ebd1695 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go @@ -0,0 +1,69 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemEtsiTypeAsStatem struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_etsi_type_as_statem", + Description: "Checks for erroneous QC Statement OID that actually are represented by ETSI ESI QC type OID.", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.3", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemEtsiTypeAsStatem{}, + }) +} + +func (l *qcStatemEtsiTypeAsStatem) Initialize() error { + return nil +} + +func (l *qcStatemEtsiTypeAsStatem) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.QcStateOid) +} + +func (l *qcStatemEtsiTypeAsStatem) Execute(c *x509.Certificate) *lint.LintResult { + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + + oidList := make([]*asn1.ObjectIdentifier, 3) + oidList[0] = &util.IdEtsiQcsQctEsign + oidList[1] = &util.IdEtsiQcsQctEseal + oidList[2] = &util.IdEtsiQcsQctWeb + + for _, oid := range oidList { + r := util.ParseQcStatem(ext.Value, *oid) + util.AppendToStringSemicolonDelim(&errString, r.GetErrorInfo()) + if r.IsPresent() { + util.AppendToStringSemicolonDelim(&errString, fmt.Sprintf("ETSI QC Type OID %v used as QC statement", oid)) + } + } + + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go new file mode 100644 index 0000000000..37d9b8650b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go @@ -0,0 +1,72 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcmandatoryEtsiStatems struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_mandatory_etsi_statems", + Description: "Checks that a QC Statement that contains at least one of the ETSI ESI statements, also features the set of mandatory ETSI ESI QC statements.", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 5", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcmandatoryEtsiStatems{}, + }) +} + +func (l *qcStatemQcmandatoryEtsiStatems) Initialize() error { + return nil +} + +func (l *qcStatemQcmandatoryEtsiStatems) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.IsAnyEtsiQcStatementPresent(util.GetExtFromCert(c, util.QcStateOid).Value) { + return true + } + return false +} + +func (l *qcStatemQcmandatoryEtsiStatems) Execute(c *x509.Certificate) *lint.LintResult { + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + + oidList := make([]*asn1.ObjectIdentifier, 1) + oidList[0] = &util.IdEtsiQcsQcCompliance + + for _, oid := range oidList { + r := util.ParseQcStatem(ext.Value, *oid) + util.AppendToStringSemicolonDelim(&errString, r.GetErrorInfo()) + if !r.IsPresent() { + util.AppendToStringSemicolonDelim(&errString, "missing mandatory ETSI QC statement") + } + } + + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go new file mode 100644 index 0000000000..2494268e5a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go @@ -0,0 +1,67 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcComplianceValid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_qccompliance_valid", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcCompliance has the correct form", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.1", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcComplianceValid{}, + }) +} + +func (this *qcStatemQcComplianceValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcCompliance +} + +func (l *qcStatemQcComplianceValid) Initialize() error { + return nil +} + +func (l *qcStatemQcComplianceValid) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func (l *qcStatemQcComplianceValid) Execute(c *x509.Certificate) *lint.LintResult { + + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go new file mode 100644 index 0000000000..27678b99cf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go @@ -0,0 +1,100 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + "unicode" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcLimitValueValid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_qclimitvalue_valid", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcLimitValue has the correct form", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.3.2", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcLimitValueValid{}, + }) +} + +func (this *qcStatemQcLimitValueValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcLimitValue +} + +func (l *qcStatemQcLimitValueValid) Initialize() error { + return nil +} + +func (l *qcStatemQcLimitValueValid) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func isOnlyLetters(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) { + return false + } + } + return true +} + +func (l *qcStatemQcLimitValueValid) Execute(c *x509.Certificate) *lint.LintResult { + + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + qcLv, ok := s.(util.EtsiQcLimitValue) + if !ok { + return &lint.LintResult{Status: lint.Error, Details: "parsed QcStatem is not a EtsiQcLimitValue"} + } + if qcLv.Amount < 0 { + util.AppendToStringSemicolonDelim(&errString, "amount is negative") + } + if qcLv.IsNum { + if qcLv.CurrencyNum < 1 || qcLv.CurrencyNum > 999 { + util.AppendToStringSemicolonDelim(&errString, "numeric currency code is out of range") + } + } else { + if len(qcLv.CurrencyAlph) != 3 { + util.AppendToStringSemicolonDelim(&errString, "invalid string length of currency code") + } + if !isOnlyLetters(qcLv.CurrencyAlph) { + util.AppendToStringSemicolonDelim(&errString, "currency code string contains not only letters") + } + + } + + } + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go new file mode 100644 index 0000000000..8aa87c9443 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go @@ -0,0 +1,91 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + "fmt" + "unicode" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcPdsLangCase struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_qcstatem_qcpds_lang_case", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcPDS features a language code comprised of only lower case letters", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.3.4", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcPdsLangCase{}, + }) +} + +func (this *qcStatemQcPdsLangCase) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcEuPDS +} + +func (l *qcStatemQcPdsLangCase) Initialize() error { + return nil +} + +func (l *qcStatemQcPdsLangCase) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func isOnlyLowerCaseLetters(s string) bool { + for _, c := range s { + if !unicode.IsLower(c) { + return false + } + } + return true +} + +func (l *qcStatemQcPdsLangCase) Execute(c *x509.Certificate) *lint.LintResult { + errString := "" + wrnString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + pds := s.(util.EtsiQcPds) + for i, loc := range pds.PdsLocations { + if !isOnlyLowerCaseLetters(loc.Language) { + util.AppendToStringSemicolonDelim(&wrnString, fmt.Sprintf("PDS location %d has a language code containing invalid letters", i)) + } + + } + } + if len(errString) == 0 { + if len(wrnString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn, Details: wrnString} + } + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go new file mode 100644 index 0000000000..5f0fda22ea --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go @@ -0,0 +1,101 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcPdsValid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_qcpds_valid", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcPDS has the correct form", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.3.4", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcPdsValid{}, + }) +} + +func (this *qcStatemQcPdsValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcEuPDS +} + +func (l *qcStatemQcPdsValid) Initialize() error { + return nil +} + +func (l *qcStatemQcPdsValid) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func isInList(s string, list []string) bool { + for _, i := range list { + if strings.Compare(i, s) == 0 { + return true + } + } + return false +} + +func (l *qcStatemQcPdsValid) Execute(c *x509.Certificate) *lint.LintResult { + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + codeList := make([]string, 0) + foundEn := false + pds := s.(util.EtsiQcPds) + if len(pds.PdsLocations) == 0 { + util.AppendToStringSemicolonDelim(&errString, "PDS list is empty") + } + for i, loc := range pds.PdsLocations { + if len(loc.Language) != 2 { + util.AppendToStringSemicolonDelim(&errString, fmt.Sprintf("PDS location %d has a language code with an invalid length", i)) + } + if strings.Compare(strings.ToLower(loc.Language), "en") == 0 { + foundEn = true + } + if isInList(strings.ToLower(loc.Language), codeList) { + util.AppendToStringSemicolonDelim(&errString, "country code '"+loc.Language+"' appears multiple times") + } + codeList = append(codeList, loc.Language) + + } + if !foundEn { + util.AppendToStringSemicolonDelim(&errString, "no english PDS present") + } + } + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go new file mode 100644 index 0000000000..626b53279d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go @@ -0,0 +1,74 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcRetentionPeriodValid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_qcretentionperiod_valid", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcRetentionPeriod has the correct form", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11)/ Section 4.3.3", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcRetentionPeriodValid{}, + }) +} + +func (this *qcStatemQcRetentionPeriodValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcRetentionPeriod +} + +func (l *qcStatemQcRetentionPeriodValid) Initialize() error { + return nil +} + +func (l *qcStatemQcRetentionPeriodValid) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func (l *qcStatemQcRetentionPeriodValid) Execute(c *x509.Certificate) *lint.LintResult { + + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + + rp := s.(util.EtsiQcRetentionPeriod) + if rp.Period < 0 { + util.AppendToStringSemicolonDelim(&errString, "retention period is negative") + } + } + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go new file mode 100644 index 0000000000..199fdba403 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go @@ -0,0 +1,68 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQcSscdValid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_qcsscd_valid", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcSSCD has the correct form", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.2", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQcSscdValid{}, + }) +} + +func (this *qcStatemQcSscdValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcSSCD +} + +func (l *qcStatemQcSscdValid) Initialize() error { + return nil +} + +func (l *qcStatemQcSscdValid) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func (l *qcStatemQcSscdValid) Execute(c *x509.Certificate) *lint.LintResult { + + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go new file mode 100644 index 0000000000..ed382d26f6 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go @@ -0,0 +1,84 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQctypeValid struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_qcstatem_qctype_valid", + Description: "Checks that a QC Statement of the type Id-etsi-qcs-QcType features a non-empty list of only the allowed QcType OIDs", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.3", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQctypeValid{}, + }) +} + +func (this *qcStatemQctypeValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcType +} + +func (l *qcStatemQctypeValid) Initialize() error { + return nil +} + +func (l *qcStatemQctypeValid) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func (l *qcStatemQctypeValid) Execute(c *x509.Certificate) *lint.LintResult { + + errString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + qcType := s.(util.Etsi423QcType) + if len(qcType.TypeOids) == 0 { + errString += "no QcType present, sequence of OIDs is empty" + } + for _, t := range qcType.TypeOids { + + if !t.Equal(util.IdEtsiQcsQctEsign) && !t.Equal(util.IdEtsiQcsQctEseal) && !t.Equal(util.IdEtsiQcsQctWeb) { + if len(errString) > 0 { + errString += "; " + } + errString += fmt.Sprintf("encountered invalid ETSI QcType OID: %v", t) + } + } + } + + if len(errString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go new file mode 100644 index 0000000000..71a75c9cb7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go @@ -0,0 +1,90 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package etsi + +import ( + "encoding/asn1" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemQctypeWeb struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_qcstatem_qctype_web", + Description: "Checks that a QC Statement of the type Id-etsi-qcs-QcType features features at least the type IdEtsiQcsQctWeb", + Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.3", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, + Lint: &qcStatemQctypeWeb{}, + }) +} + +func (this *qcStatemQctypeWeb) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcType +} + +func (l *qcStatemQctypeWeb) Initialize() error { + return nil +} + +func (l *qcStatemQctypeWeb) CheckApplies(c *x509.Certificate) bool { + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *l.getStatementOid()).IsPresent() { + return true + } + return false +} + +func (l *qcStatemQctypeWeb) Execute(c *x509.Certificate) *lint.LintResult { + + errString := "" + wrnString := "" + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, *l.getStatementOid()) + errString += s.GetErrorInfo() + if len(errString) == 0 { + qcType := s.(util.Etsi423QcType) + if len(qcType.TypeOids) == 0 { + errString += "no QcType present, sequence of OIDs is empty" + } + found := false + for _, t := range qcType.TypeOids { + + if t.Equal(util.IdEtsiQcsQctWeb) { + found = true + } + } + if !found { + wrnString += fmt.Sprintf("etsi Type does not indicate certificate as a 'web' certificate") + } + } + + if len(errString) == 0 { + if len(wrnString) == 0 { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn, Details: wrnString} + } + } else { + return &lint.LintResult{Status: lint.Error, Details: errString} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go new file mode 100644 index 0000000000..774bf4675c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go @@ -0,0 +1,76 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package mozilla + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type allowedEKU struct{} + +/******************************************************************** +Section 5.3 - Intermediate Certificates +Intermediate certificates created after January 1, 2019, with the exception +of cross-certificates that share a private key with a corresponding root +certificate: MUST contain an EKU extension; and, MUST NOT include the +anyExtendedKeyUsage KeyPurposeId; and, * MUST NOT include both the +id-kp-serverAuth and id-kp-emailProtection KeyPurposeIds in the same +certificate. +Note that the lint cannot distinguish cross-certificates from other +intermediates. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_mp_allowed_eku", + Description: "A SubCA certificate must not have key usage that allows for both server auth and email protection, and must not use anyKeyUsage", + Citation: "Mozilla Root Store Policy / Section 5.3", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC), + Lint: &allowedEKU{}, + }) +} + +func (l *allowedEKU) Initialize() error { + return nil +} + +func (l *allowedEKU) CheckApplies(c *x509.Certificate) bool { + // TODO(@cpu): This lint should be limited to SubCAs that do not share + // a private key with a corresponding root certificate in the Mozilla root + // store. See https://github.com/zmap/zlint/issues/352 + return util.IsSubCA(c) +} + +func (l *allowedEKU) Execute(c *x509.Certificate) *lint.LintResult { + noEKU := len(c.ExtKeyUsage) == 0 + anyEKU := util.HasEKU(c, x509.ExtKeyUsageAny) + emailAndServerAuthEKU := + util.HasEKU(c, x509.ExtKeyUsageEmailProtection) && + util.HasEKU(c, x509.ExtKeyUsageServerAuth) + + if noEKU || anyEKU || emailAndServerAuthEKU { + // NOTE(@cpu): When this lint's scope is improved (see CheckApplies TODO) + // this should be a lint.Error result instead of lint.Notice. See + // https://github.com/zmap/zlint/issues/352 + return &lint.LintResult{Status: lint.Notice} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go new file mode 100644 index 0000000000..004f012848 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go @@ -0,0 +1,78 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package mozilla + +import ( + "encoding/asn1" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type keyIdentifier struct { + KeyIdentifier asn1.RawValue `asn1:"optional,tag:0"` + AuthorityCertIssuer asn1.RawValue `asn1:"optional,tag:1"` + AuthorityCertSerialNumber asn1.RawValue `asn1:"optional,tag:2"` +} + +type authorityKeyIdentifierCorrect struct{} + +/******************************************************************** +Section 5.2 - Forbidden and Required Practices +CAs MUST NOT issue certificates that have: +- incorrect extensions (e.g., SSL certificates that exclude SSL usage, or authority key IDs + that include both the key ID and the issuer’s issuer name and serial number); +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_authority_key_identifier_correct", + Description: "CAs MUST NOT issue certificates that have authority key IDs that include both the key ID and the issuer's issuer name and serial number", + Citation: "Mozilla Root Store Policy / Section 5.2", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy22Date, + Lint: &authorityKeyIdentifierCorrect{}, + }) +} + +func (l *authorityKeyIdentifierCorrect) Initialize() error { + return nil +} + +func (l *authorityKeyIdentifierCorrect) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.AuthkeyOID) +} + +func (l *authorityKeyIdentifierCorrect) Execute(c *x509.Certificate) *lint.LintResult { + var keyID keyIdentifier + + // ext is assumed not-nil based on CheckApplies. + ext := util.GetExtFromCert(c, util.AuthkeyOID) + if _, err := asn1.Unmarshal(ext.Value, &keyID); err != nil { + return &lint.LintResult{ + Status: lint.Fatal, + Details: fmt.Sprintf("error unmarshalling authority key identifier extension: %v", err), + } + } + + hasKeyID := len(keyID.KeyIdentifier.Bytes) > 0 + hasCertIssuer := len(keyID.AuthorityCertIssuer.Bytes) > 0 + if hasKeyID && hasCertIssuer { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go new file mode 100644 index 0000000000..92b7ebbcba --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go @@ -0,0 +1,88 @@ +package mozilla + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ecdsaPubKeyAidEncoding struct{} + +/************************************************ +https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/ + +When ECDSA keys are encoded in a SubjectPublicKeyInfo structure, the algorithm field MUST be one of the following, as +specified by RFC 5480, Section 2.1.1: + +The encoded AlgorithmIdentifier for a P-256 key MUST match the following hex-encoded +bytes: > 301306072a8648ce3d020106082a8648ce3d030107. + +The encoded AlgorithmIdentifier for a P-384 key MUST match the following hex-encoded +bytes: > 301006072a8648ce3d020106052b81040022. + +The above encodings consist of an ecPublicKey OID (1.2.840.10045.2.1) with a named curve parameter of the corresponding +curve OID. Certificates MUST NOT use the implicit or specified curve forms. + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_ecdsa_pub_key_encoding_correct", + Description: "The encoded algorithm identifiers for ECDSA public keys MUST match specific bytes", + Citation: "Mozilla Root Store Policy / Section 5.1.2", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy27Date, + Lint: &ecdsaPubKeyAidEncoding{}, + }) +} + +var acceptedAlgIDEncodingsDER = [2][]byte{ + // encoded AlgorithmIdentifier for a P-256 key + {0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, + // encoded AlgorithmIdentifier for a P-384 key + {0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22}, +} + +func (l *ecdsaPubKeyAidEncoding) Initialize() error { + return nil +} + +func (l *ecdsaPubKeyAidEncoding) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.ECDSA +} + +func (l *ecdsaPubKeyAidEncoding) Execute(c *x509.Certificate) *lint.LintResult { + encodedPublicKeyAid, err := util.GetPublicKeyAidEncoded(c) + if err != nil { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("error reading public key algorithm identifier: %v", err), + } + } + + for _, encoding := range acceptedAlgIDEncodingsDER { + if bytes.Equal(encodedPublicKeyAid, encoding) { + return &lint.LintResult{Status: lint.Pass} + } + } + + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Wrong encoding of ECC public key. Got the unsupported %s", hex.EncodeToString(encodedPublicKeyAid))} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go new file mode 100644 index 0000000000..71dd0d8ea9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go @@ -0,0 +1,121 @@ +package mozilla + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ecdsaSignatureAidEncoding struct{} + +/************************************************ +https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/ + +When a root or intermediate certificate's ECDSA key is used to produce a signature, only the following algorithms may +be used, and with the following encoding requirements: + +If the signing key is P-256, the signature MUST use ECDSA with SHA-256. The encoded AlgorithmIdentifier MUST match the +following hex-encoded bytes: 300a06082a8648ce3d040302. + +If the signing key is P-384, the signature MUST use ECDSA with SHA-384. The encoded AlgorithmIdentifier MUST match the +following hex-encoded bytes: 300a06082a8648ce3d040303. + +The above encodings consist of the corresponding OID with the parameters field omitted, as specified by RFC 5758, +Section 3.2. Certificates MUST NOT include a NULL parameter. Note this differs from RSASSA-PKCS1-v1_5, which includes +an explicit NULL. + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_ecdsa_signature_encoding_correct", + Description: "The encoded algorithm identifiers for ECDSA signatures MUST match specific hex-encoded bytes", + Citation: "Mozilla Root Store Policy / Section 5.1.2", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy27Date, + Lint: &ecdsaSignatureAidEncoding{}, + }) +} + +func (l *ecdsaSignatureAidEncoding) Initialize() error { + return nil +} + +func (l *ecdsaSignatureAidEncoding) CheckApplies(c *x509.Certificate) bool { + // check for all ECDSA signature algorithms to avoid missing this lint if an unsupported algorithm is used in the first place + // 1.2.840.10045.4.3.1 is SHA224withECDSA + return c.SignatureAlgorithm == x509.ECDSAWithSHA1 || + c.SignatureAlgorithm == x509.ECDSAWithSHA256 || + c.SignatureAlgorithm == x509.ECDSAWithSHA384 || + c.SignatureAlgorithm == x509.ECDSAWithSHA512 || + c.SignatureAlgorithmOID.Equal(util.OidSignatureSHA224withECDSA) +} + +func (l *ecdsaSignatureAidEncoding) Execute(c *x509.Certificate) *lint.LintResult { + // We must check consistency of the issuer public key to the signature algorithm + // (see for example: If the signing key is P-256, the signature MUST use ECDSA with SHA-256. + // The encoded AlgorithmIdentifier MUST match the following hex-encoded bytes: 300a06082a8648ce3d040302.) + // Thus we need the issuer public key which it is not available so easy. + // At this stage all certificates (also of sub-CAs and root-CAs, provided they are linted) are either + // P-256 or P-384 (see lint e_mp_ecdsa_pub_key_encoding_correct). + // Therefore we check the length of the signature in the certificate. If it is 0 ... 72 bytes then it is + // assumed done by a P-256 key and if it is 73 ... 104 bytes it is assumed done by a P-384 key. + + signature := c.Signature + signatureSize := len(signature) + encoded, err := util.GetSignatureAlgorithmInTBSEncoded(c) + if err != nil { + return &lint.LintResult{Status: lint.Error, Details: err.Error()} + } + + // Signatures made with P-256 are not going to be greater than 72 bytes long + // Seq Tag+Length = 2, r Tag+length = 2, s Tag+length = 2, r max 32+1 (unsigned representation), same for s + // len <= 2+2+2+33+33 (= 72) + const maxP256SigByteLen = 72 + // len <= 2+2+2+49+49 (= 104) + const maxP384SigByteLen = 104 + + if signatureSize <= maxP256SigByteLen { + expectedEncoding := []byte{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02} + + if bytes.Equal(encoded, expectedEncoding) { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("Encoding of signature algorithm does not match signing key on P-256 curve. Got the unsupported %s", hex.EncodeToString(encoded)), + } + } else if signatureSize <= maxP384SigByteLen { + expectedEncoding := []byte{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03} + + if bytes.Equal(encoded, expectedEncoding) { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("Encoding of signature algorithm does not match signing key on P-384 curve. Got the unsupported %s", hex.EncodeToString(encoded)), + } + } + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("Encoding of signature algorithm does not match signing key. Got signature length %v", signatureSize), + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go new file mode 100644 index 0000000000..42bae8c315 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go @@ -0,0 +1,66 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package mozilla + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type exponentCannotBeOne struct{} + +/******************************************************************** +Section 5.2 - Forbidden and Required Practices +CAs MUST NOT issue certificates that have: +- invalid public keys (e.g., RSA certificates with public exponent equal to 1); +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_exponent_cannot_be_one", + Description: "CAs MUST NOT issue certificates that have invalid public keys (e.g., RSA certificates with public exponent equal to 1)", + Citation: "Mozilla Root Store Policy / Section 5.2", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy24Date, + Lint: &exponentCannotBeOne{}, + }) +} + +func (l *exponentCannotBeOne) Initialize() error { + return nil +} + +func (l *exponentCannotBeOne) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA +} + +func (l *exponentCannotBeOne) Execute(c *x509.Certificate) *lint.LintResult { + pubKey, ok := c.PublicKey.(*rsa.PublicKey) + if !ok { + return &lint.LintResult{ + Status: lint.Fatal, + Details: "certificate public key was not an RSA public key", + } + } + + if pubKey.E == 1 { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go new file mode 100644 index 0000000000..b6689a1f13 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go @@ -0,0 +1,65 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package mozilla + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type modulus2048OrMore struct{} + +/******************************************************************** +Section 5.1 - Algorithms +RSA keys whose modulus size in bits is divisible by 8, and is at least 2048. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_modulus_must_be_2048_bits_or_more", + Description: "RSA keys must have modulus size of at least 2048 bits", + Citation: "Mozilla Root Store Policy / Section 5.1", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy24Date, + Lint: &modulus2048OrMore{}, + }) +} + +func (l *modulus2048OrMore) Initialize() error { + return nil +} + +func (l *modulus2048OrMore) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA +} + +func (l *modulus2048OrMore) Execute(c *x509.Certificate) *lint.LintResult { + pubKey, ok := c.PublicKey.(*rsa.PublicKey) + if !ok { + return &lint.LintResult{ + Status: lint.Fatal, + Details: "certificate public key was not an RSA public key", + } + } + + if bitLen := pubKey.N.BitLen(); bitLen < 2048 { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go new file mode 100644 index 0000000000..e21b9faf55 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go @@ -0,0 +1,65 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package mozilla + +import ( + "crypto/rsa" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type modulusDivisibleBy8 struct{} + +/******************************************************************** +Section 5.1 - Algorithms +RSA keys whose modulus size in bits is divisible by 8, and is at least 2048. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_modulus_must_be_divisible_by_8", + Description: "RSA keys must have a modulus size divisible by 8", + Citation: "Mozilla Root Store Policy / Section 5.1", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy24Date, + Lint: &modulusDivisibleBy8{}, + }) +} + +func (l *modulusDivisibleBy8) Initialize() error { + return nil +} + +func (l *modulusDivisibleBy8) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA +} + +func (l *modulusDivisibleBy8) Execute(c *x509.Certificate) *lint.LintResult { + pubKey, ok := c.PublicKey.(*rsa.PublicKey) + if !ok { + return &lint.LintResult{ + Status: lint.Fatal, + Details: "certificate public key was not an RSA public key", + } + } + + if bitLen := pubKey.N.BitLen(); (bitLen % 8) != 0 { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go new file mode 100644 index 0000000000..f1d0fc91b0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go @@ -0,0 +1,101 @@ +package mozilla + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaPssAidEncoding struct{} + +/************************************************ + +https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/ + +Section 5.1.1 RSA + +RSASSA-PSS with SHA-256, MGF-1 with SHA-256, and a salt length of 32 bytes. + +The encoded AlgorithmIdentifier MUST match the following hex-encoded bytes: + +304106092a864886f70d01010a3034a00f300d0609608648016503040201 +0500a11c301a06092a864886f70d010108300d0609608648016503040201 +0500a203020120 + +RSASSA-PSS with SHA-384, MGF-1 with SHA-384, and a salt length of 48 bytes. + +The encoded AlgorithmIdentifier MUST match the following hex-encoded bytes: + +304106092a864886f70d01010a3034a00f300d0609608648016503040202 +0500a11c301a06092a864886f70d010108300d0609608648016503040202 +0500a203020130 + +RSASSA-PSS with SHA-512, MGF-1 with SHA-512, and a salt length of 64 bytes. + +The encoded AlgorithmIdentifier MUST match the following hex-encoded bytes: + +304106092a864886f70d01010a3034a00f300d0609608648016503040203 +0500a11c301a06092a864886f70d010108300d0609608648016503040203 +0500a203020140 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_rsassa-pss_parameters_encoding_in_signature_algorithm_correct", + Description: "The encoded AlgorithmIdentifier for RSASSA-PSS in the signature algorithm MUST match specific bytes", + Citation: "Mozilla Root Store Policy / Section 5.1.1", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy27Date, + Lint: &rsaPssAidEncoding{}, + }) +} + +var RSASSAPSSAlgorithmIDToDER = [3][]byte{ + // RSASSA-PSS with SHA-256, MGF-1 with SHA-256, salt length 32 bytes + {0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20}, + // RSASSA-PSS with SHA-384, MGF-1 with SHA-384, salt length 48 bytes + {0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x30}, + // RSASSA-PSS with SHA-512, MGF-1 with SHA-512, salt length 64 bytes + {0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x40}, +} + +func (l *rsaPssAidEncoding) Initialize() error { + return nil +} + +func (l *rsaPssAidEncoding) CheckApplies(c *x509.Certificate) bool { + return c.SignatureAlgorithmOID.Equal(util.OidRSASSAPSS) +} + +func (l *rsaPssAidEncoding) Execute(c *x509.Certificate) *lint.LintResult { + signatureAlgoID, err := util.GetSignatureAlgorithmInTBSEncoded(c) + if err != nil { + return &lint.LintResult{Status: lint.Error, Details: err.Error()} + } + + for _, encoding := range RSASSAPSSAlgorithmIDToDER { + if bytes.Equal(signatureAlgoID, encoding) { + return &lint.LintResult{Status: lint.Pass} + } + } + + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("RSASSA-PSS parameters are not properly encoded. %v presentations are allowed but got the unsupported %s", len(RSASSAPSSAlgorithmIDToDER), hex.EncodeToString(signatureAlgoID))} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go new file mode 100644 index 0000000000..b978cce4ce --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go @@ -0,0 +1,66 @@ +package mozilla + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaPssInSPKI struct{} + +/************************************************ +https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/ + +Section 5.1.1 RSA + +CAs MUST NOT use the id-RSASSA-PSS OID (1.2.840.113549.1.1.10) within a SubjectPublicKeyInfo to represent a RSA key. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_mp_rsassa-pss_in_spki", + Description: "CAs MUST NOT use the id-RSASSA-PSS OID (1.2.840.113549.1.1.10) within a SubjectPublicKeyInfo to represent a RSA key.", + Citation: "Mozilla Root Store Policy / Section 5.1.1", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy27Date, + Lint: &rsaPssInSPKI{}, + }) +} + +func (l *rsaPssInSPKI) Initialize() error { + return nil +} + +func (l *rsaPssInSPKI) CheckApplies(c *x509.Certificate) bool { + // always check, no certificate is allowed to contain the PSS OID in public key + return true +} + +func (l *rsaPssInSPKI) Execute(c *x509.Certificate) *lint.LintResult { + publicKeyOID, err := util.GetPublicKeyOID(c) + if err != nil { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("error reading OID in certificate SubjectPublicKeyInfo: %v", err)} + } + + if publicKeyOID.Equal(util.OidRSASSAPSS) { + return &lint.LintResult{Status: lint.Error, Details: "id-RSASSA-PSS OID found in certificate SubjectPublicKeyInfo"} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go new file mode 100644 index 0000000000..55866ec440 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go @@ -0,0 +1,66 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type basicConstCrit struct{} + +/************************************************ +RFC 5280: 4.2.1.9 +Conforming CAs MUST include this extension in all CA certificates that contain +public keys used to validate digital signatures on certificates and MUST mark +the extension as critical in such certificates. This extension MAY appear as a +critical or non- critical extension in CA certificates that contain public keys +used exclusively for purposes other than validating digital signatures on +certificates. Such CA certificates include ones that contain public keys used +exclusively for validating digital signatures on CRLs and ones that contain key +management public keys used with certificate. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_basic_constraints_not_critical", + Description: "basicConstraints MUST appear as a critical extension", + Citation: "RFC 5280: 4.2.1.9", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &basicConstCrit{}, + }) +} + +func (l *basicConstCrit) Initialize() error { + return nil +} + +func (l *basicConstCrit) CheckApplies(c *x509.Certificate) bool { + return c.IsCA && util.IsExtInCert(c, util.BasicConstOID) +} + +func (l *basicConstCrit) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.BasicConstOID); e != nil { + if e.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } + } else { + return &lint.LintResult{Status: lint.NA} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go new file mode 100644 index 0000000000..f6a55d7813 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caSubjectEmpty struct{} + +/************************************************ +RFC 5280: 4.1.2.6 +The subject field identifies the entity associated with the public + key stored in the subject public key field. The subject name MAY be + carried in the subject field and/or the subjectAltName extension. If + the subject is a CA (e.g., the basic constraints extension, as + discussed in Section 4.2.1.9, is present and the value of cA is + TRUE), then the subject field MUST be populated with a non-empty + distinguished name matching the contents of the issuer field (Section + 4.1.2.4) in all certificates issued by the subject CA. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ca_subject_field_empty", + Description: "CA Certificates subject field MUST not be empty and MUST have a non-empty distinguished name", + Citation: "RFC 5280: 4.1.2.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &caSubjectEmpty{}, + }) +} + +func (l *caSubjectEmpty) Initialize() error { + return nil +} + +func (l *caSubjectEmpty) CheckApplies(c *x509.Certificate) bool { + return c.IsCA +} + +func (l *caSubjectEmpty) Execute(c *x509.Certificate) *lint.LintResult { + if util.NotAllNameFieldsAreEmpty(&c.Subject) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go new file mode 100644 index 0000000000..13d5f5e79a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertContainsUniqueIdentifier struct{} + +/************************************************ + These fields MUST only appear if the version is 2 or 3 (Section 4.1.2.1). + These fields MUST NOT appear if the version is 1. The subject and issuer + unique identifiers are present in the certificate to handle the possibility + of reuse of subject and/or issuer names over time. This profile RECOMMENDS + that names not be reused for different entities and that Internet certificates + not make use of unique identifiers. CAs conforming to this profile MUST NOT + generate certificates with unique identifiers. Applications conforming to + this profile SHOULD be capable of parsing certificates that include unique + identifiers, but there are no processing requirements associated with the + unique identifiers. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_contains_unique_identifier", + Description: "CAs MUST NOT generate certificate with unique identifiers", + Source: lint.RFC5280, + Citation: "RFC 5280: 4.1.2.8", + EffectiveDate: util.RFC5280Date, + Lint: &CertContainsUniqueIdentifier{}, + }) +} + +func (l *CertContainsUniqueIdentifier) Initialize() error { + return nil +} + +func (l *CertContainsUniqueIdentifier) CheckApplies(cert *x509.Certificate) bool { + return true +} + +func (l *CertContainsUniqueIdentifier) Execute(cert *x509.Certificate) *lint.LintResult { + if cert.IssuerUniqueId.Bytes == nil && cert.SubjectUniqueId.Bytes == nil { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.Error} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go new file mode 100644 index 0000000000..18a82c6273 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go @@ -0,0 +1,68 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type CertExtensionsVersonNot3 struct{} + +/************************************************ +4.1.2.1. Version + This field describes the version of the encoded certificate. When + extensions are used, as expected in this profile, version MUST be 3 + (value is 2). If no extensions are present, but a UniqueIdentifier + is present, the version SHOULD be 2 (value is 1); however, the version + MAY be 3. If only basic fields are present, the version SHOULD be 1 + (the value is omitted from the certificate as the default value); + however, the version MAY be 2 or 3. + + Implementations SHOULD be prepared to accept any version certificate. + At a minimum, conforming implementations MUST recognize version 3 certificates. +4.1.2.9. Extensions + This field MUST only appear if the version is 3 (Section 4.1.2.1). + If present, this field is a SEQUENCE of one or more certificate + extensions. The format and content of certificate extensions in the + Internet PKI are defined in Section 4.2. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_extensions_version_not_3", + Description: "The extensions field MUST only appear in version 3 certificates", + Citation: "RFC 5280: 4.1.2.9", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &CertExtensionsVersonNot3{}, + }) +} + +func (l *CertExtensionsVersonNot3) Initialize() error { + return nil +} + +func (l *CertExtensionsVersonNot3) CheckApplies(cert *x509.Certificate) bool { + return true +} + +func (l *CertExtensionsVersonNot3) Execute(cert *x509.Certificate) *lint.LintResult { + if cert.Version != 3 && len(cert.Extensions) != 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go new file mode 100644 index 0000000000..476d88932a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type certUniqueIdVersion struct{} + +/************************************************************************** +RFC 5280: 4.1.2.8 + These fields MUST only appear if the version is 2 or 3 (Section 4.1.2.1). + These fields MUST NOT appear if the version is 1. The subject and issuer + unique identifiers are present in the certificate to handle the possibility + of reuse of subject and/or issuer names over time. This profile RECOMMENDS + that names not be reused for different entities and that Internet certificates + not make use of unique identifiers. CAs conforming to this profile MUST NOT + generate certificates with unique identifiers. Applications conforming to + this profile SHOULD be capable of parsing certificates that include unique + identifiers, but there are no processing requirements associated with the + unique identifiers. +****************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_unique_identifier_version_not_2_or_3", + Description: "Unique identifiers MUST only appear if the X.509 version is 2 or 3", + Citation: "RFC 5280: 4.1.2.8", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &certUniqueIdVersion{}, + }) +} + +func (l *certUniqueIdVersion) Initialize() error { + return nil +} + +func (l *certUniqueIdVersion) CheckApplies(c *x509.Certificate) bool { + return c.IssuerUniqueId.Bytes != nil || c.SubjectUniqueId.Bytes != nil +} + +func (l *certUniqueIdVersion) Execute(c *x509.Certificate) *lint.LintResult { + if (c.Version) != 2 && (c.Version) != 3 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go new file mode 100644 index 0000000000..32ccb94756 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go @@ -0,0 +1,85 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type distributionPoint struct { + DistributionPoint distributionPointName `asn1:"optional,tag:0"` + Reason asn1.BitString `asn1:"optional,tag:1"` + CRLIssuer asn1.RawValue `asn1:"optional,tag:2"` +} + +type distributionPointName struct { + FullName asn1.RawValue `asn1:"optional,tag:0"` + RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` +} + +type dpIncomplete struct{} + +/******************************************************************** +The cRLDistributionPoints extension is a SEQUENCE of +DistributionPoint. A DistributionPoint consists of three fields, +each of which is optional: distributionPoint, reasons, and cRLIssuer. +While each of these fields is optional, a DistributionPoint MUST NOT +consist of only the reasons field; either distributionPoint or +cRLIssuer MUST be present. If the certificate issuer is not the CRL +issuer, then the cRLIssuer field MUST be present and contain the Name +of the CRL issuer. If the certificate issuer is also the CRL issuer, +then conforming CAs MUST omit the cRLIssuer field and MUST include +the distributionPoint field. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_distribution_point_incomplete", + Description: "A DistributionPoint from the CRLDistributionPoints extension MUST NOT consist of only the reasons field; either distributionPoint or CRLIssuer must be present", + Citation: "RFC 5280: 4.2.1.13", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &dpIncomplete{}, + }) +} + +func (l *dpIncomplete) Initialize() error { + return nil +} + +func (l *dpIncomplete) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CrlDistOID) +} + +func (l *dpIncomplete) Execute(c *x509.Certificate) *lint.LintResult { + dp := util.GetExtFromCert(c, util.CrlDistOID) + var cdp []distributionPoint + _, err := asn1.Unmarshal(dp.Value, &cdp) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + for _, dp := range cdp { + if dp.Reason.BitLength != 0 && len(dp.DistributionPoint.FullName.Bytes) == 0 && + dp.DistributionPoint.RelativeName == nil && len(dp.CRLIssuer.Bytes) == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go new file mode 100644 index 0000000000..1ad537db0f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go @@ -0,0 +1,58 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type distribNoLDAPorURI struct{} + +/************************************************ +RFC 5280: 4.2.1.13 +When present, DistributionPointName SHOULD include at least one LDAP or HTTP URI. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_distribution_point_missing_ldap_or_uri", + Description: "When present in the CRLDistributionPoints extension, DistributionPointName SHOULD include at least one LDAP or HTTP URI", + Citation: "RFC 5280: 4.2.1.13", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &distribNoLDAPorURI{}, + }) +} + +func (l *distribNoLDAPorURI) Initialize() error { + return nil +} + +func (l *distribNoLDAPorURI) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CrlDistOID) +} + +func (l *distribNoLDAPorURI) Execute(c *x509.Certificate) *lint.LintResult { + for _, point := range c.CRLDistributionPoints { + if point = strings.ToLower(point); strings.HasPrefix(point, "http://") || strings.HasPrefix(point, "ldap://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Warn} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go new file mode 100644 index 0000000000..be191d1ac1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go @@ -0,0 +1,99 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "fmt" + "sort" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ecdsaInvalidKU struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "n_ecdsa_ee_invalid_ku", + Description: "ECDSA end-entity certificates MAY have key usages: digitalSignature, nonRepudiation and keyAgreement", + Citation: "RFC 5480 Section 3", + Source: lint.RFC5480, + EffectiveDate: util.CABEffectiveDate, + Lint: &ecdsaInvalidKU{}, + }) +} + +// Initialize is a no-op for this lint. +func (l *ecdsaInvalidKU) Initialize() error { + return nil +} + +// CheckApplies returns true when the certificate is a subscriber cert using an +// ECDSA public key algorithm. +func (l *ecdsaInvalidKU) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && c.PublicKeyAlgorithm == x509.ECDSA +} + +// Execute returns a Notice level lint.LintResult if the ECDSA end entity certificate +// being linted has Key Usage bits set other than digitalSignature, +// nonRepudiation/contentCommentment, and keyAgreement. +func (l *ecdsaInvalidKU) Execute(c *x509.Certificate) *lint.LintResult { + // RFC 5480, Section 3 "Key Usage Bits" says: + // + // If the keyUsage extension is present in an End Entity (EE) + // certificate that indicates id-ecPublicKey in SubjectPublicKeyInfo, + // then any combination of the following values MAY be present: + // + // digitalSignature; + // nonRepudiation; and + // keyAgreement. + // + // So we set up `allowedKUs` to match. Note that per RFC 5280: recent editions + // of X.509 renamed "nonRepudiation" to "contentCommitment", which is the name + // of the Go x509 constant we use here alongside the digitalSignature and + // keyAgreement constants. + allowedKUs := map[x509.KeyUsage]bool{ + x509.KeyUsageDigitalSignature: true, + x509.KeyUsageContentCommitment: true, + x509.KeyUsageKeyAgreement: true, + } + + var invalidKUs []string + for ku, kuName := range util.KeyUsageToString { + if c.KeyUsage&ku != 0 { + if !allowedKUs[ku] { + invalidKUs = append(invalidKUs, kuName) + } + } + } + + if len(invalidKUs) > 0 { + // Sort the invalid KUs to allow consistent ordering of Details messages for + // unit testing + sort.Strings(invalidKUs) + return &lint.LintResult{ + Status: lint.Notice, + Details: fmt.Sprintf( + "Certificate had unexpected key usage(s): %s", + strings.Join(invalidKUs, ", ")), + } + } + + return &lint.LintResult{ + Status: lint.Pass, + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go new file mode 100644 index 0000000000..d6051db4e7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ekuBadCritical struct{} + +/************************************************ +RFC 5280: 4.2.1.12 +If a CA includes extended key usages to satisfy such applications, + but does not wish to restrict usages of the key, the CA can include + the special KeyPurposeId anyExtendedKeyUsage in addition to the + particular key purposes required by the applications. Conforming CAs + SHOULD NOT mark this extension as critical if the anyExtendedKeyUsage + KeyPurposeId is present. Applications that require the presence of a + particular purpose MAY reject certificates that include the + anyExtendedKeyUsage OID but not the particular OID expected for the + application. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_eku_critical_improperly", + Description: "Conforming CAs SHOULD NOT mark extended key usage extension as critical if the anyExtendedKeyUsage KeyPurposedID is present", + Citation: "RFC 5280: 4.2.1.12", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &ekuBadCritical{}, + }) +} + +func (l *ekuBadCritical) Initialize() error { + return nil +} + +func (l *ekuBadCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.EkuSynOid) +} + +func (l *ekuBadCritical) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.EkuSynOid); e.Critical { + for _, single_use := range c.ExtKeyUsage { + if single_use == x509.ExtKeyUsageAny { + return &lint.LintResult{Status: lint.Warn} + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go new file mode 100644 index 0000000000..df2e41a9b1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type aiaNoHTTPorLDAP struct{} + +/************************************************ +RFC 5280: 4.2.2.1 +An authorityInfoAccess extension may include multiple instances of + the id-ad-caIssuers accessMethod. The different instances may + specify different methods for accessing the same information or may + point to different information. When the id-ad-caIssuers + accessMethod is used, at least one instance SHOULD specify an + accessLocation that is an HTTP [RFC2616] or LDAP [RFC4516] URI. + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_aia_access_location_missing", + Description: "When the id-ad-caIssuers accessMethod is used, at least one instance SHOULD specify an accessLocation that is an HTTP or LDAP URI", + Citation: "RFC 5280: 4.2.2.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &aiaNoHTTPorLDAP{}, + }) +} + +func (l *aiaNoHTTPorLDAP) Initialize() error { + return nil +} + +func (l *aiaNoHTTPorLDAP) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.AiaOID) && c.IssuingCertificateURL != nil +} + +func (l *aiaNoHTTPorLDAP) Execute(c *x509.Certificate) *lint.LintResult { + for _, caIssuer := range c.IssuingCertificateURL { + if caIssuer = strings.ToLower(caIssuer); strings.HasPrefix(caIssuer, "http://") || strings.HasPrefix(caIssuer, "ldap://") { + return &lint.LintResult{Status: lint.Pass} + } + } + return &lint.LintResult{Status: lint.Warn} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go new file mode 100644 index 0000000000..dce31de95c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go @@ -0,0 +1,56 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ExtAiaMarkedCritical struct{} + +/************************************************ +Authority Information Access + The authority information access extension indicates how to access information and services for the issuer of the certificate in which the extension appears. Information and services may include on-line validation services and CA policy data. (The location of CRLs is not specified in this extension; that information is provided by the cRLDistributionPoints extension.) This extension may be included in end entity or CA certificates. Conforming CAs MUST mark this extension as non-critical. +************************************************/ +//See also: BRs: 7.1.2.3 & CAB: 7.1.2.2 + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_aia_marked_critical", + Description: "Conforming CAs must mark the Authority Information Access extension as non-critical", + Citation: "RFC 5280: 4.2.2.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &ExtAiaMarkedCritical{}, + }) +} + +func (l *ExtAiaMarkedCritical) Initialize() error { + return nil +} + +func (l *ExtAiaMarkedCritical) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.AiaOID) +} + +func (l *ExtAiaMarkedCritical) Execute(cert *x509.Certificate) *lint.LintResult { + if util.GetExtFromCert(cert, util.AiaOID).Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go new file mode 100644 index 0000000000..768a474920 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go @@ -0,0 +1,56 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type authorityKeyIdCritical struct{} + +/********************************************************* +RFC 5280: 4.2.1.1 +Conforming CAs MUST mark this extension as non-critical. +**********************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_authority_key_identifier_critical", + Description: "The authority key identifier extension must be non-critical", + Citation: "RFC 5280: 4.2.1.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &authorityKeyIdCritical{}, + }) +} + +func (l *authorityKeyIdCritical) Initialize() error { + return nil +} + +func (l *authorityKeyIdCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.AuthkeyOID) +} + +func (l *authorityKeyIdCritical) Execute(c *x509.Certificate) *lint.LintResult { + aki := util.GetExtFromCert(c, util.AuthkeyOID) //pointer to the extension + if aki.Critical { + return &lint.LintResult{Status: lint.Error} + } else { //implies !aki.Critical + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go new file mode 100644 index 0000000000..76488f76a8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type authorityKeyIdMissing struct{} + +/*********************************************************************** +RFC 5280: 4.2.1.1 +The keyIdentifier field of the authorityKeyIdentifier extension MUST + be included in all certificates generated by conforming CAs to + facilitate certification path construction. There is one exception; + where a CA distributes its public key in the form of a "self-signed" + certificate, the authority key identifier MAY be omitted. The + signature on a self-signed certificate is generated with the private + key associated with the certificate's subject public key. (This + proves that the issuer possesses both the public and private keys.) + In this case, the subject and authority key identifiers would be + identical, but only the subject key identifier is needed for + certification path building. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_authority_key_identifier_missing", + Description: "CAs must support key identifiers and include them in all certificates", + Citation: "RFC 5280: 4.2 & 4.2.1.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &authorityKeyIdMissing{}, + }) +} + +func (l *authorityKeyIdMissing) Initialize() error { + return nil +} + +func (l *authorityKeyIdMissing) CheckApplies(c *x509.Certificate) bool { + return !util.IsRootCA(c) +} + +func (l *authorityKeyIdMissing) Execute(c *x509.Certificate) *lint.LintResult { + if !util.IsExtInCert(c, util.AuthkeyOID) && !util.IsSelfSigned(c) { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go new file mode 100644 index 0000000000..fdf2a2add4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type authorityKeyIdNoKeyIdField struct{} + +/*********************************************************************** +RFC 5280: 4.2.1.1 +The keyIdentifier field of the authorityKeyIdentifier extension MUST + be included in all certificates generated by conforming CAs to + facilitate certification path construction. There is one exception; + where a CA distributes its public key in the form of a "self-signed" + certificate, the authority key identifier MAY be omitted. The + signature on a self-signed certificate is generated with the private + key associated with the certificate's subject public key. (This + proves that the issuer possesses both the public and private keys.) + In this case, the subject and authority key identifiers would be + identical, but only the subject key identifier is needed for + certification path building. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_authority_key_identifier_no_key_identifier", + Description: "CAs must include keyIdentifer field of AKI in all non-self-issued certificates", + Citation: "RFC 5280: 4.2.1.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &authorityKeyIdNoKeyIdField{}, + }) +} + +func (l *authorityKeyIdNoKeyIdField) Initialize() error { + return nil +} + +func (l *authorityKeyIdNoKeyIdField) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *authorityKeyIdNoKeyIdField) Execute(c *x509.Certificate) *lint.LintResult { + if c.AuthorityKeyId == nil && !util.IsSelfSigned(c) { //will be nil by default if not found in x509.parseCert + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go new file mode 100644 index 0000000000..f64aab142e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type noticeRefPres struct{} + +/******************************************************************** +The user notice has two optional fields: the noticeRef field and the +explicitText field. Conforming CAs SHOULD NOT use the noticeRef +option. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_cert_policy_contains_noticeref", + Description: "Compliant certificates SHOULD NOT use the noticeRef option", + Citation: "RFC 5280: 4.2.1.4", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: ¬iceRefPres{}, + }) +} + +func (l *noticeRefPres) Initialize() error { + return nil +} + +func (l *noticeRefPres) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CertPolicyOID) +} + +func (l *noticeRefPres) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.NoticeRefNumbers { + for _, number := range firstLvl { + if number != nil { + return &lint.LintResult{Status: lint.Warn} + } + } + } + for _, firstLvl := range c.NoticeRefOrgnization { + for _, org := range firstLvl { + if len(org.Bytes) != 0 { + return &lint.LintResult{Status: lint.Warn} + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go new file mode 100644 index 0000000000..042e5798d5 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type unrecommendedQualifier struct{} + +/******************************************************************* +RFC 5280: 4.2.1.4 +To promote interoperability, this profile RECOMMENDS that policy +information terms consist of only an OID. Where an OID alone is +insufficient, this profile strongly recommends that the use of +qualifiers be limited to those identified in this section. When +qualifiers are used with the special policy anyPolicy, they MUST be +limited to the qualifiers identified in this section. Only those +qualifiers returned as a result of path validation are considered. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_cert_policy_disallowed_any_policy_qualifier", + Description: "When qualifiers are used with the special policy anyPolicy, they must be limited to qualifiers identified in this section: (4.2.1.4)", + Citation: "RFC 5280: 4.2.1.4", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &unrecommendedQualifier{}, + }) +} + +func (l *unrecommendedQualifier) Initialize() error { + return nil +} + +func (l *unrecommendedQualifier) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.CertPolicyOID) +} + +func (l *unrecommendedQualifier) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.QualifierId { + for _, qualifierId := range firstLvl { + if !qualifierId.Equal(util.CpsOID) && !qualifierId.Equal(util.UserNoticeOID) { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go new file mode 100644 index 0000000000..cffa718d43 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go @@ -0,0 +1,63 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ExtCertPolicyDuplicate struct{} + +/************************************************ + The certificate policies extension contains a sequence of one or more + policy information terms, each of which consists of an object identifier + (OID) and optional qualifiers. Optional qualifiers, which MAY be present, + are not expected to change the definition of the policy. A certificate + policy OID MUST NOT appear more than once in a certificate policies extension. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_cert_policy_duplicate", + Description: "A certificate policy OID must not appear more than once in the extension", + Citation: "RFC 5280: 4.2.1.4", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &ExtCertPolicyDuplicate{}, + }) +} + +func (l *ExtCertPolicyDuplicate) Initialize() error { + return nil +} + +func (l *ExtCertPolicyDuplicate) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.CertPolicyOID) +} + +func (l *ExtCertPolicyDuplicate) Execute(cert *x509.Certificate) *lint.LintResult { + // O(n^2) is not terrible here because n is small + for i := 0; i < len(cert.PolicyIdentifiers); i++ { + for j := i + 1; j < len(cert.PolicyIdentifiers); j++ { + if i != j && cert.PolicyIdentifiers[i].Equal(cert.PolicyIdentifiers[j]) { + // Any one duplicate fails the test, so return here + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go new file mode 100644 index 0000000000..d5233cd44f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go @@ -0,0 +1,72 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type explicitTextIA5String struct{} + +/******************************************************************** + +An explicitText field includes the textual statement directly in +the certificate. The explicitText field is a string with a +maximum size of 200 characters. Conforming CAs SHOULD use the +UTF8String encoding for explicitText. VisibleString or BMPString +are acceptable but less preferred alternatives. Conforming CAs +MUST NOT encode explicitText as IA5String. The explicitText string +SHOULD NOT include any control characters (e.g., U+0000 to U+001F +and U+007F to U+009F). When the UTF8String or BMPString encoding +is used, all character sequences SHOULD be normalized according +to Unicode normalization form C (NFC) [NFC]. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_cert_policy_explicit_text_ia5_string", + Description: "Compliant certificates must not encode explicitTest as an IA5String", + Citation: "RFC 6818: 3", + Source: lint.RFC5280, + EffectiveDate: util.RFC6818Date, + Lint: &explicitTextIA5String{}, + }) +} + +func (l *explicitTextIA5String) Initialize() error { + return nil +} + +func (l *explicitTextIA5String) CheckApplies(c *x509.Certificate) bool { + for _, text := range c.ExplicitTexts { + if text != nil { + return true + } + } + return false +} + +func (l *explicitTextIA5String) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.ExplicitTexts { + for _, text := range firstLvl { + if text.Tag == 22 { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go new file mode 100644 index 0000000000..41e7527404 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go @@ -0,0 +1,91 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type controlChar struct{} + +/********************************************************************* +An explicitText field includes the textual statement directly in +the certificate. The explicitText field is a string with a +maximum size of 200 characters. Conforming CAs SHOULD use the +UTF8String encoding for explicitText, but MAY use IA5String. +Conforming CAs MUST NOT encode explicitText as VisibleString or +BMPString. The explicitText string SHOULD NOT include any control +characters (e.g., U+0000 to U+001F and U+007F to U+009F). When +the UTF8String encoding is used, all character sequences SHOULD be +normalized according to Unicode normalization form C (NFC) [NFC]. +*********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_cert_policy_explicit_text_includes_control", + Description: "Explicit text should not include any control characters", + Citation: "RFC 6818: 3", + Source: lint.RFC5280, + EffectiveDate: util.RFC6818Date, + Lint: &controlChar{}, + }) +} + +func (l *controlChar) Initialize() error { + return nil +} + +func (l *controlChar) CheckApplies(c *x509.Certificate) bool { + for _, text := range c.ExplicitTexts { + if text != nil { + return true + } + } + return false +} + +//nolint:nestif +func (l *controlChar) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.ExplicitTexts { + for _, text := range firstLvl { + if text.Tag == 12 { + for i := 0; i < len(text.Bytes); i++ { + if text.Bytes[i]&0x80 == 0 { + if text.Bytes[i] < 0x20 || text.Bytes[i] == 0x7f { + return &lint.LintResult{Status: lint.Warn} + } + } else if text.Bytes[i]&0x20 == 0 { + if text.Bytes[i] == 0xc2 && text.Bytes[i+1] >= 0x80 && text.Bytes[i+1] <= 0x9f { + return &lint.LintResult{Status: lint.Warn} + } + i += 1 + } else if text.Bytes[i]&0x10 == 0 { + i += 2 + } else if text.Bytes[i]&0x08 == 0 { + i += 3 + } else if text.Bytes[i]&0x04 == 0 { + i += 4 + } else if text.Bytes[i]&0x02 == 0 { + i += 5 + } + } + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go new file mode 100644 index 0000000000..7d68b8f0b5 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go @@ -0,0 +1,66 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + "golang.org/x/text/unicode/norm" +) + +type ExtCertPolicyExplicitTextNotNFC struct{} + +/************************************************ + When the UTF8String encoding is used, all character sequences SHOULD be + normalized according to Unicode normalization form C (NFC) [NFC]. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_cert_policy_explicit_text_not_nfc", + Description: "When utf8string or bmpstring encoding is used for explicitText field in certificate policy, it SHOULD be normalized by NFC format", + Citation: "RFC6181 3", + Source: lint.RFC5280, + EffectiveDate: util.RFC6818Date, + Lint: &ExtCertPolicyExplicitTextNotNFC{}, + }) +} + +func (l *ExtCertPolicyExplicitTextNotNFC) Initialize() error { + return nil +} + +func (l *ExtCertPolicyExplicitTextNotNFC) CheckApplies(c *x509.Certificate) bool { + for _, text := range c.ExplicitTexts { + if text != nil { + return true + } + } + return false +} + +func (l *ExtCertPolicyExplicitTextNotNFC) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.ExplicitTexts { + for _, text := range firstLvl { + if text.Tag == 12 || text.Tag == 30 { + if !norm.NFC.IsNormal(text.Bytes) { + return &lint.LintResult{Status: lint.Warn} + } + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go new file mode 100644 index 0000000000..7c283b2075 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go @@ -0,0 +1,73 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type explicitTextUtf8 struct{} + +/******************************************************************* +https://tools.ietf.org/html/rfc6818#section-3 + +An explicitText field includes the textual statement directly in +the certificate. The explicitText field is a string with a +maximum size of 200 characters. Conforming CAs SHOULD use the +UTF8String encoding for explicitText. VisibleString or BMPString +are acceptable but less preferred alternatives. Conforming CAs +MUST NOT encode explicitText as IA5String. The explicitText string +SHOULD NOT include any control characters (e.g., U+0000 to U+001F +and U+007F to U+009F). When the UTF8String or BMPString encoding +is used, all character sequences SHOULD be normalized according +to Unicode normalization form C (NFC) [NFC]. +*******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_cert_policy_explicit_text_not_utf8", + Description: "Compliant certificates should use the utf8string encoding for explicitText", + Citation: "RFC 6818: 3", + Source: lint.RFC5280, + EffectiveDate: util.RFC6818Date, + Lint: &explicitTextUtf8{}, + }) +} + +func (l *explicitTextUtf8) Initialize() error { + return nil +} + +func (l *explicitTextUtf8) CheckApplies(c *x509.Certificate) bool { + for _, text := range c.ExplicitTexts { + if text != nil { + return true + } + } + return false +} + +func (l *explicitTextUtf8) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.ExplicitTexts { + for _, text := range firstLvl { + if text.Tag != 12 { + return &lint.LintResult{Status: lint.Warn} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go new file mode 100644 index 0000000000..b728daea6f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go @@ -0,0 +1,82 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type explicitTextTooLong struct{} + +/******************************************************************* +An explicitText field includes the textual statement directly in +the certificate. The explicitText field is a string with a +maximum size of 200 characters. Conforming CAs SHOULD use the +UTF8String encoding for explicitText. VisibleString or BMPString +are acceptable but less preferred alternatives. Conforming CAs +MUST NOT encode explicitText as IA5String. The explicitText string +SHOULD NOT include any control characters (e.g., U+0000 to U+001F +and U+007F to U+009F). When the UTF8String or BMPString encoding +is used, all character sequences SHOULD be normalized according +to Unicode normalization form C (NFC) [NFC]. +*******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_cert_policy_explicit_text_too_long", + Description: "Explicit text has a maximum size of 200 characters", + Citation: "RFC 6818: 3", + Source: lint.RFC5280, + EffectiveDate: util.RFC6818Date, + Lint: &explicitTextTooLong{}, + }) +} + +const tagBMPString int = 30 + +func (l *explicitTextTooLong) Initialize() error { + return nil +} + +func (l *explicitTextTooLong) CheckApplies(c *x509.Certificate) bool { + for _, text := range c.ExplicitTexts { + if text != nil { + return true + } + } + return false +} + +func (l *explicitTextTooLong) Execute(c *x509.Certificate) *lint.LintResult { + for _, firstLvl := range c.ExplicitTexts { + for _, text := range firstLvl { + var runes string + // If the field is a BMPString, we need to parse the bytes out into + // UTF-16-BE runes in order to check their length accurately + // The `Bytes` attribute here is the raw representation of the userNotice + if text.Tag == tagBMPString { + runes, _ = util.ParseBMPString(text.Bytes) + } else { + runes = string(text.Bytes) + } + if len(runes) > 200 { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go new file mode 100644 index 0000000000..8016b419cf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go @@ -0,0 +1,57 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ExtCrlDistributionMarkedCritical struct{} + +/************************************************ +The CRL distribution points extension identifies how CRL information is obtained. The extension SHOULD be non-critical, but this profile RECOMMENDS support for this extension by CAs and applications. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_crl_distribution_marked_critical", + Description: "If included, the CRL Distribution Points extension SHOULD NOT be marked critical", + Citation: "RFC 5280: 4.2.1.13", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &ExtCrlDistributionMarkedCritical{}, + }) +} + +func (l *ExtCrlDistributionMarkedCritical) Initialize() error { + return nil +} + +func (l *ExtCrlDistributionMarkedCritical) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.CrlDistOID) +} + +func (l *ExtCrlDistributionMarkedCritical) Execute(cert *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(cert, util.CrlDistOID); e != nil { + if !e.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } + } + return &lint.LintResult{Status: lint.NA} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go new file mode 100644 index 0000000000..8eb32ee6bb --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go @@ -0,0 +1,88 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type extDuplicateExtension struct{} + +/************************************************ +"A certificate MUST NOT include more than one instance of a particular extension." +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_duplicate_extension", + Description: "A certificate MUST NOT include more than one instance of a particular extension", + Citation: "RFC 5280: 4.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &extDuplicateExtension{}, + }) +} + +func (l *extDuplicateExtension) Initialize() error { + return nil +} + +func (l *extDuplicateExtension) CheckApplies(cert *x509.Certificate) bool { + return cert.Version == 3 +} + +func (l *extDuplicateExtension) Execute(cert *x509.Certificate) *lint.LintResult { + // Make two maps: one for all of the extensions in the cert, and one for any + // OIDs that are found more than once. + extensionOIDs := make(map[string]bool) + duplicateOIDs := make(map[string]bool) + + // Iterate through the certificate extensions and update the maps. + for _, ext := range cert.Extensions { + // We can't use the `asn1.ObjectIdentifier` as a key (it's an int slice) so use + // the str representation. + oid := ext.Id.String() + + if alreadySeen := extensionOIDs[oid]; alreadySeen { + duplicateOIDs[oid] = true + } else { + extensionOIDs[oid] = true + } + } + + // If there were no duplicates we're done, the cert passes. + if len(duplicateOIDs) == 0 { + return &lint.LintResult{Status: lint.Pass} + } + + // If there were duplicates turn the map keys into a list so we + // can join them for the details string. + var duplicateOIDsList []string + for oid := range duplicateOIDs { + duplicateOIDsList = append(duplicateOIDsList, oid) + } + + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf( + "The following extensions are duplicated: %s", + strings.Join(duplicateOIDsList, ", ")), + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go new file mode 100644 index 0000000000..0417c4c8da --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go @@ -0,0 +1,57 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ExtFreshestCrlMarkedCritical struct{} + +/************************************************ +The freshest CRL extension identifies how delta CRL information is obtained. The extension MUST be marked as non-critical by conforming CAs. Further discussion of CRL management is contained in Section 5. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_freshest_crl_marked_critical", + Description: "Freshest CRL MUST be marked as non-critical by conforming CAs", + Citation: "RFC 5280: 4.2.1.15", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &ExtFreshestCrlMarkedCritical{}, + }) +} + +func (l *ExtFreshestCrlMarkedCritical) Initialize() error { + return nil +} + +func (l *ExtFreshestCrlMarkedCritical) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.FreshCRLOID) +} + +func (l *ExtFreshestCrlMarkedCritical) Execute(cert *x509.Certificate) *lint.LintResult { + var fCRL *pkix.Extension = util.GetExtFromCert(cert, util.FreshCRLOID) + if fCRL != nil && fCRL.Critical { + return &lint.LintResult{Status: lint.Error} + } else if fCRL != nil && !fCRL.Critical { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{Status: lint.NA} //shouldn't happen +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go new file mode 100644 index 0000000000..75eb2427b7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go @@ -0,0 +1,56 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ExtIANCritical struct{} + +/************************************************ +Issuer Alternative Name + As with Section 4.2.1.6, this extension is used to associate Internet style identities with the certificate issuer. Issuer alternative name MUST be encoded as in 4.2.1.6. Issuer alternative names are not processed as part of the certification path validation algorithm in Section 6. (That is, issuer alternative names are not used in name chaining and name constraints are not enforced.) + Where present, conforming CAs SHOULD mark this extension as non-critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_ian_critical", + Description: "Issuer alternate name should be marked as non-critical", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &ExtIANCritical{}, + }) +} + +func (l *ExtIANCritical) Initialize() error { + return nil +} + +func (l *ExtIANCritical) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.IssuerAlternateNameOID) +} + +func (l *ExtIANCritical) Execute(cert *x509.Certificate) *lint.LintResult { + if util.GetExtFromCert(cert, util.IssuerAlternateNameOID).Critical { + return &lint.LintResult{Status: lint.Warn} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go new file mode 100644 index 0000000000..1d440f092e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go @@ -0,0 +1,74 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANDNSNotIA5String struct{} + +/******************************************************************** +RFC 5280: 4.2.1.7 +When the subjectAltName extension contains a domain name system +label, the domain name MUST be stored in the DNSName (an IA5String). +The name MUST be in the "preferred name syntax", as specified by +Section 3.5 of [RFC1034] and as modified by Section 2.1 of +[RFC1123]. Note that while uppercase and lowercase letters are +allowed in domain names, no significance is attached to the case. In +addition, while the string " " is a legal domain name, subjectAltName +extensions with a DNSName of " " MUST NOT be used. Finally, the use +of the DNS representation for Internet mail addresses +(subscriber.example.com instead of subscriber@example.com) MUST NOT +be used; such identities are to be encoded as rfc822Name. Rules for +encoding internationalized domain names are specified in Section 7.2. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_dns_not_ia5_string", + Description: "DNSNames MUST be IA5 strings", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &IANDNSNotIA5String{}, + }) +} + +func (l *IANDNSNotIA5String) Initialize() error { + return nil +} + +func (l *IANDNSNotIA5String) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANDNSNotIA5String) Execute(c *x509.Certificate) *lint.LintResult { + ext := util.GetExtFromCert(c, util.IssuerAlternateNameOID) + if ext == nil { + return &lint.LintResult{Status: lint.Fatal} + } + ok, err := util.AllAlternateNameWithTagAreIA5(ext, util.DNSNameTag) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if ok { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go new file mode 100644 index 0000000000..a2dc53e0ed --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go @@ -0,0 +1,81 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANEmptyName struct{} + +/****************************************************************** +RFC 5280: 4.2.1.7 +If the subjectAltName extension is present, the sequence MUST contain +at least one entry. Unlike the subject field, conforming CAs MUST +NOT issue certificates with subjectAltNames containing empty +GeneralName fields. For example, an rfc822Name is represented as an +IA5String. While an empty string is a valid IA5String, such an +rfc822Name is not permitted by this profile. The behavior of clients +that encounter such a certificate when processing a certification +path is not defined by this profile. +******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_empty_name", + Description: "General name fields must not be empty in IAN", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &IANEmptyName{}, + }) +} + +func (l *IANEmptyName) Initialize() error { + return nil +} + +func (l *IANEmptyName) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANEmptyName) Execute(c *x509.Certificate) *lint.LintResult { + value := util.GetExtFromCert(c, util.IssuerAlternateNameOID).Value + var seq asn1.RawValue + if _, err := asn1.Unmarshal(value, &seq); err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { + return &lint.LintResult{Status: lint.Fatal} + } + + rest := seq.Bytes + for len(rest) > 0 { + var v asn1.RawValue + var err error + rest, err = asn1.Unmarshal(rest, &v) + if err != nil { + return &lint.LintResult{Status: lint.NA} + } + if len(v.Bytes) == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go new file mode 100644 index 0000000000..b23f7f8399 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go @@ -0,0 +1,63 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANNoEntry struct{} + +/********************************************************************** +RFC 5280: 4.2.1.7 +If the issuerAltName extension is present, the sequence MUST contain + at least one entry. Unlike the subject field, conforming CAs MUST + NOT issue certificates with subjectAltNames containing empty + GeneralName fields. For example, an rfc822Name is represented as an + IA5String. While an empty string is a valid IA5String, such an + rfc822Name is not permitted by this profile. The behavior of clients + that encounter such a certificate when processing a certification + path is not defined by this profile. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_no_entries", + Description: "If present, the IAN extension must contain at least one entry", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &IANNoEntry{}, + }) +} + +func (l *IANNoEntry) Initialize() error { + return nil +} + +func (l *IANNoEntry) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANNoEntry) Execute(c *x509.Certificate) *lint.LintResult { + ian := util.GetExtFromCert(c, util.IssuerAlternateNameOID) + if util.IsEmptyASN1Sequence(ian.Value) { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go new file mode 100644 index 0000000000..122f2010df --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go @@ -0,0 +1,70 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANEmail struct{} + +/************************************************************************ +RFC 5280: 4.2.1.6 + When the issuerAltName extension contains an Internet mail address, + the address MUST be stored in the rfc822Name. The format of an + rfc822Name is a "Mailbox" as defined in Section 4.1.2 of [RFC2821]. + A Mailbox has the form "Local-part@Domain". Note that a Mailbox has + no phrase (such as a common name) before it, has no comment (text + surrounded in parentheses) after it, and is not surrounded by "<" and + ">". Rules for encoding Internet mail addresses that include + internationalized domain names are specified in Section 7.5. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_rfc822_format_invalid", + Description: "Email must not be surrounded with `<>`, and there MUST NOT be trailing comments in `()`", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &IANEmail{}, + }) +} + +func (l *IANEmail) Initialize() error { + return nil +} + +func (l *IANEmail) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANEmail) Execute(c *x509.Certificate) *lint.LintResult { + for _, str := range c.IANEmailAddresses { + if str == "" { + continue + } + if strings.Contains(str, " ") { + return &lint.LintResult{Status: lint.Error} + } else if str[0] == '<' || str[len(str)-1] == ')' { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go new file mode 100644 index 0000000000..6311236c2a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANSpace struct{} + +/********************************************************************** +RFC 5280: 4.2.1.7 +When the issuerAltName extension contains a domain name system +label, the domain name MUST be stored in the dNSName (an IA5String). +The name MUST be in the "preferred name syntax", as specified by +Section 3.5 of [RFC1034] and as modified by Section 2.1 of +[RFC1123]. Note that while uppercase and lowercase letters are +allowed in domain names, no significance is attached to the case. In +addition, while the string " " is a legal domain name, subjectAltName +extensions with a dNSName of " " MUST NOT be used. Finally, the use +of the DNS representation for Internet mail addresses +(subscriber.example.com instead of subscriber@example.com) MUST NOT +be used; such identities are to be encoded as rfc822Name. Rules for +encoding internationalized domain names are specified in Section 7.2. +**********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_space_dns_name", + Description: "dNSName ' ' MUST NOT be used", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &IANSpace{}, + }) +} + +func (l *IANSpace) Initialize() error { + return nil +} + +func (l *IANSpace) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANSpace) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.IANDNSNames { + if dns == " " { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go new file mode 100644 index 0000000000..e461d5bd4b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go @@ -0,0 +1,70 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANURIFormat struct{} + +/************************************************ +The name MUST include both a +scheme (e.g., "http" or "ftp") and a scheme-specific-part. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_uri_format_invalid", + Description: "URIs in the subjectAltName extension MUST have a scheme and scheme specific part", + Citation: "RFC5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &IANURIFormat{}, + }) +} + +func (l *IANURIFormat) Initialize() error { + return nil +} + +func (l *IANURIFormat) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANURIFormat) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.IANURIs { + parsed_uri, err := url.Parse(uri) + + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + + //scheme + if parsed_uri.Scheme == "" { + return &lint.LintResult{Status: lint.Error} + } + + //scheme-specific part + if parsed_uri.Host == "" && parsed_uri.User == nil && parsed_uri.Opaque == "" && parsed_uri.Path == "" { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go new file mode 100644 index 0000000000..70eabf2d5a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go @@ -0,0 +1,72 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANURIFQDNOrIP struct{} + +/********************************************************************* +When the issuerAltName extension contains a URI, the name MUST be +stored in the uniformResourceIdentifier (an IA5String). The name +MUST NOT be a relative URI, and it MUST follow the URI syntax and +encoding rules specified in [RFC3986]. The name MUST include both a +scheme (e.g., "http" or "ftp") and a scheme-specific-part. URIs that +include an authority ([RFC3986], Section 3.2) MUST include a fully +qualified domain name or IP address as the host. Rules for encoding +Internationalized Resource Identifiers (IRIs) are specified in +Section 7.4. +*********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_uri_host_not_fqdn_or_ip", + Description: "URIs that include an authority ([RFC3986], Section 3.2) MUST include a fully qualified domain name or IP address as the host", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &IANURIFQDNOrIP{}, + }) +} + +func (l *IANURIFQDNOrIP) Initialize() error { + return nil +} + +func (l *IANURIFQDNOrIP) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANURIFQDNOrIP) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.IANURIs { + if uri != "" { + parsedUrl, err := url.Parse(uri) + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + host := parsedUrl.Host + if !util.AuthIsFQDNOrIP(host) { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go new file mode 100644 index 0000000000..6fe0286487 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go @@ -0,0 +1,60 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IANURIIA5String struct{} + +/************************************************ +When the issuerAltName extension contains a URI, the name MUST be +stored in the uniformResourceIdentifier (an IA5String). +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_uri_not_ia5", + Description: "When issuer alternative name contains a URI, the name MUST be an IA5 string", + Citation: "RFC5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &IANURIIA5String{}, + }) +} + +func (l *IANURIIA5String) Initialize() error { + return nil +} + +func (l *IANURIIA5String) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *IANURIIA5String) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.IANURIs { + for _, c := range uri { + if c > unicode.MaxASCII { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go new file mode 100644 index 0000000000..0a14d22f48 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go @@ -0,0 +1,71 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type uriRelative struct{} + +/************************************************************************* +When the issuerAltName extension contains a URI, the name MUST be +stored in the uniformResourceIdentifier (an IA5String). The name +MUST NOT be a relative URI, and it MUST follow the URI syntax and +encoding rules specified in [RFC3986]. The name MUST include both a +scheme (e.g., "http" or "ftp") and a scheme-specific-part. URIs that +include an authority ([RFC3986], Section 3.2) MUST include a fully +qualified domain name or IP address as the host. Rules for encoding +Internationalized Resource Identifiers (IRIs) are specified in +Section 7.4. +*************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_ian_uri_relative", + Description: "When issuerAltName extension is present and the URI is used, the name MUST NOT be a relative URI", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &uriRelative{}, + }) +} + +func (l *uriRelative) Initialize() error { + return nil +} + +func (l *uriRelative) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.IssuerAlternateNameOID) +} + +func (l *uriRelative) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.IANURIs { + parsed_uri, err := url.Parse(uri) + + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + + if !parsed_uri.IsAbs() { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go new file mode 100644 index 0000000000..4e2e853fc2 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type keyUsageCertSignNoCa struct{} + +/************************************************************************ +RFC 5280: 4.2.1.9 +The cA boolean indicates whether the certified public key may be used + to verify certificate signatures. If the cA boolean is not asserted, + then the keyCertSign bit in the key usage extension MUST NOT be + asserted. If the basic constraints extension is not present in a + version 3 certificate, or the extension is present but the cA boolean + is not asserted, then the certified public key MUST NOT be used to + verify certificate signatures. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_key_usage_cert_sign_without_ca", + Description: "if the keyCertSign bit is asserted, then the cA bit in the basic constraints extension MUST also be asserted", + Citation: "RFC 5280: 4.2.1.3 & 4.2.1.9", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &keyUsageCertSignNoCa{}, + }) +} + +func (l *keyUsageCertSignNoCa) Initialize() error { + return nil +} + +func (l *keyUsageCertSignNoCa) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *keyUsageCertSignNoCa) Execute(c *x509.Certificate) *lint.LintResult { + if (c.KeyUsage & x509.KeyUsageCertSign) != 0 { + if c.BasicConstraintsValid && util.IsCACert(c) { //CA certs may assert certificate signing usage + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go new file mode 100644 index 0000000000..6bc6546945 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go @@ -0,0 +1,56 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type checkKeyUsageCritical struct{} + +// "When present, conforming CAs SHOULD mark this extension as critical." + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_key_usage_not_critical", + Description: "The keyUsage extension SHOULD be critical", + Citation: "RFC 5280: 4.2.1.3", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &checkKeyUsageCritical{}, + }) +} + +func (l *checkKeyUsageCritical) Initialize() error { + return nil +} + +func (l *checkKeyUsageCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *checkKeyUsageCritical) Execute(c *x509.Certificate) *lint.LintResult { + keyUsage := util.GetExtFromCert(c, util.KeyUsageOID) + if keyUsage == nil { + return &lint.LintResult{Status: lint.NA} + } + if keyUsage.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go new file mode 100644 index 0000000000..4da1b36c9a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go @@ -0,0 +1,59 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type keyUsageBitsSet struct{} + +/*********************************************************************** + This profile does not restrict the combinations of bits that may be + set in an instantiation of the keyUsage extension. However, + appropriate values for keyUsage extensions for particular algorithms + are specified in [RFC3279], [RFC4055], and [RFC4491]. When the + keyUsage extension appears in a certificate, at least one of the bits + MUST be set to 1. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_key_usage_without_bits", + Description: "When the keyUsage extension is included, at least one bit MUST be set to 1", + Citation: "RFC 5280: 4.2.1.3", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &keyUsageBitsSet{}, + }) +} + +func (l *keyUsageBitsSet) Initialize() error { + return nil +} + +func (l *keyUsageBitsSet) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) +} + +func (l *keyUsageBitsSet) Execute(c *x509.Certificate) *lint.LintResult { + if c.KeyUsage == 0 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go new file mode 100644 index 0000000000..17272b7027 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go @@ -0,0 +1,63 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintCrit struct{} + +/************************************************************************ +Restrictions are defined in terms of permitted or excluded name + subtrees. Any name matching a restriction in the excludedSubtrees + field is invalid regardless of information appearing in the + permittedSubtrees. Conforming CAs MUST mark this extension as + critical and SHOULD NOT impose name constraints on the x400Address, + ediPartyName, or registeredID name forms. Conforming CAs MUST NOT + issue certificates where name constraints is an empty sequence. That + is, either the permittedSubtrees field or the excludedSubtrees MUST + be present. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_name_constraints_not_critical", + Description: "If it is included, conforming CAs MUST mark the name constrains extension as critical", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &nameConstraintCrit{}, + }) +} + +func (l *nameConstraintCrit) Initialize() error { + return nil +} + +func (l *nameConstraintCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +func (l *nameConstraintCrit) Execute(c *x509.Certificate) *lint.LintResult { + e := util.GetExtFromCert(c, util.NameConstOID) + if e.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go new file mode 100644 index 0000000000..18c0b7e727 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go @@ -0,0 +1,61 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintNotCa struct{} + +/*********************************************************************** +RFC 5280: 4.2.1.10 +The name constraints extension, which MUST be used only in a CA + certificate, indicates a name space within which all subject names in + subsequent certificates in a certification path MUST be located. + Restrictions apply to the subject distinguished name and apply to + subject alternative names. Restrictions apply only when the + specified name form is present. If no name of the type is in the + certificate, the certificate is acceptable. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_name_constraints_not_in_ca", + Description: "The name constraints extension MUST only be used in CA certificates", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &nameConstraintNotCa{}, + }) +} + +func (l *nameConstraintNotCa) Initialize() error { + return nil +} + +func (l *nameConstraintNotCa) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +func (l *nameConstraintNotCa) Execute(c *x509.Certificate) *lint.LintResult { + if !util.IsCACert(c) { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go new file mode 100644 index 0000000000..d4797f7b03 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go @@ -0,0 +1,76 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type policyConstraintsContents struct{} + +/************************************************************************* +RFC 5280: 4.2.1.11 +Conforming CAs MUST NOT issue certificates where policy constraints + is an empty sequence. That is, either the inhibitPolicyMapping field + or the requireExplicitPolicy field MUST be present. The behavior of + clients that encounter an empty policy constraints field is not + addressed in this profile. +*************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_policy_constraints_empty", + Description: "Conforming CAs MUST NOT issue certificates where policy constraints is an empty sequence. That is, either the inhibitPolicyMapping field or the requireExplicityPolicy field MUST be present", + Citation: "RFC 5280: 4.2.1.11", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &policyConstraintsContents{}, + }) +} + +func (l *policyConstraintsContents) Initialize() error { + return nil +} + +func (l *policyConstraintsContents) CheckApplies(c *x509.Certificate) bool { + if !(util.IsExtInCert(c, util.PolicyConstOID)) { + return false + } + pc := util.GetExtFromCert(c, util.PolicyConstOID) + var seq asn1.RawValue + rest, err := asn1.Unmarshal(pc.Value, &seq) //only one sequence, so rest should be empty + if err != nil || len(rest) != 0 || seq.Tag != 16 || seq.Class != 0 || !seq.IsCompound { + return false + } + return true +} + +func (l *policyConstraintsContents) Execute(c *x509.Certificate) *lint.LintResult { + pc := util.GetExtFromCert(c, util.PolicyConstOID) + var seq asn1.RawValue + _, err := asn1.Unmarshal(pc.Value, &seq) //only one sequence, so rest should be empty + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(seq.Bytes) == 0 { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go new file mode 100644 index 0000000000..307abff69a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go @@ -0,0 +1,56 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type policyConstraintsCritical struct{} + +/************************************************ +RFC 5280: 4.2.1.11 +Conforming CAs MUST mark this extension as critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_policy_constraints_not_critical", + Description: "Conforming CAs MUST mark the policy constraints extension as critical", + Citation: "RFC 5280: 4.2.1.11", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &policyConstraintsCritical{}, + }) +} + +func (l *policyConstraintsCritical) Initialize() error { + return nil +} + +func (l *policyConstraintsCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.PolicyConstOID) +} + +func (l *policyConstraintsCritical) Execute(c *x509.Certificate) *lint.LintResult { + pc := util.GetExtFromCert(c, util.PolicyConstOID) + if !pc.Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go new file mode 100644 index 0000000000..9fb661c379 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type policyMapAnyPolicy struct{} + +/******************************************************************** +RFC 5280: 4.2.1.5 +Each issuerDomainPolicy named in the policy mappings extension SHOULD + also be asserted in a certificate policies extension in the same + certificate. Policies MUST NOT be mapped either to or from the + special value anyPolicy (Section 4.2.1.4). +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_policy_map_any_policy", + Description: "Policies must not be mapped to or from the anyPolicy value", + Citation: "RFC 5280: 4.2.1.5", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &policyMapAnyPolicy{}, + }) +} + +func (l *policyMapAnyPolicy) Initialize() error { + return nil +} + +func (l *policyMapAnyPolicy) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.PolicyMapOID) +} + +func (l *policyMapAnyPolicy) Execute(c *x509.Certificate) *lint.LintResult { + extPolMap := util.GetExtFromCert(c, util.PolicyMapOID) + polMap, err := util.GetMappedPolicies(extPolMap) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + + for _, pair := range polMap { + if util.AnyPolicyOID.Equal(pair[0]) || util.AnyPolicyOID.Equal(pair[1]) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go new file mode 100644 index 0000000000..4d5d98011f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go @@ -0,0 +1,57 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type policyMapCritical struct{} + +/********************************************************** +RFC 5280: 4.2.1.5. Policy Mappings +This extension MAY be supported by CAs and/or applications. + Conforming CAs SHOULD mark this extension as critical. +**********************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_policy_map_not_critical", + Description: "Policy mappings should be marked as critical", + Citation: "RFC 5280: 4.2.1.5", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &policyMapCritical{}, + }) +} + +func (l *policyMapCritical) Initialize() error { + return nil +} + +func (l *policyMapCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.PolicyMapOID) +} + +func (l *policyMapCritical) Execute(c *x509.Certificate) *lint.LintResult { + polMap := util.GetExtFromCert(c, util.PolicyMapOID) + if polMap.Critical { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go new file mode 100644 index 0000000000..8906cedc62 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type policyMapMatchesCertPolicy struct{} + +/********************************************************************* +RFC 5280: 4.2.1.5 +Each issuerDomainPolicy named in the policy mapping extension SHOULD + also be asserted in a certificate policies extension in the same + certificate. Policies SHOULD NOT be mapped either to or from the + special value anyPolicy (section 4.2.1.5). +*********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_policy_map_not_in_cert_policy", + Description: "Each issuerDomainPolicy named in the policy mappings extension should also be asserted in a certificate policies extension", + Citation: "RFC 5280: 4.2.1.5", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &policyMapMatchesCertPolicy{}, + }) +} + +func (l *policyMapMatchesCertPolicy) Initialize() error { + return nil +} + +func (l *policyMapMatchesCertPolicy) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.PolicyMapOID) +} + +func (l *policyMapMatchesCertPolicy) Execute(c *x509.Certificate) *lint.LintResult { + extPolMap := util.GetExtFromCert(c, util.PolicyMapOID) + polMap, err := util.GetMappedPolicies(extPolMap) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + for _, pair := range polMap { + if !util.SliceContainsOID(c.PolicyIdentifiers, pair[0]) { + return &lint.LintResult{Status: lint.Warn} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go new file mode 100644 index 0000000000..daaea49cc3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go @@ -0,0 +1,51 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANDNSTooLong struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_dns_name_too_long", + Description: "DNSName must be less than or equal to 253 bytes", + Citation: "RFC 5280", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &SANDNSTooLong{}, + }) +} + +func (l *SANDNSTooLong) Initialize() error { + return nil +} + +func (l *SANDNSTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) && len(c.DNSNames) > 0 +} + +func (l *SANDNSTooLong) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if len(dns) > 253 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go new file mode 100644 index 0000000000..46d0068451 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go @@ -0,0 +1,74 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANDNSNotIA5String struct{} + +/******************************************************************** +RFC 5280: 4.2.1.6 +When the subjectAltName extension contains a domain name system +label, the domain name MUST be stored in the dNSName (an IA5String). +The name MUST be in the "preferred name syntax", as specified by +Section 3.5 of [RFC1034] and as modified by Section 2.1 of +[RFC1123]. Note that while uppercase and lowercase letters are +allowed in domain names, no significance is attached to the case. In +addition, while the string " " is a legal domain name, subjectAltName +extensions with a dNSName of " " MUST NOT be used. Finally, the use +of the DNS representation for Internet mail addresses +(subscriber.example.com instead of subscriber@example.com) MUST NOT +be used; such identities are to be encoded as rfc822Name. Rules for +encoding internationalized domain names are specified in Section 7.2. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_dns_not_ia5_string", + Description: "dNSNames MUST be IA5 strings", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &SANDNSNotIA5String{}, + }) +} + +func (l *SANDNSNotIA5String) Initialize() error { + return nil +} + +func (l *SANDNSNotIA5String) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANDNSNotIA5String) Execute(c *x509.Certificate) *lint.LintResult { + ext := util.GetExtFromCert(c, util.SubjectAlternateNameOID) + if ext == nil { + return &lint.LintResult{Status: lint.Fatal} + } + ok, err := util.AllAlternateNameWithTagAreIA5(ext, util.DNSNameTag) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if ok { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go new file mode 100644 index 0000000000..8f1b152292 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go @@ -0,0 +1,81 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANEmptyName struct{} + +/****************************************************************** +RFC 5280: 4.2.1.6 +If the subjectAltName extension is present, the sequence MUST contain +at least one entry. Unlike the subject field, conforming CAs MUST +NOT issue certificates with subjectAltNames containing empty +GeneralName fields. For example, an rfc822Name is represented as an +IA5String. While an empty string is a valid IA5String, such an +rfc822Name is not permitted by this profile. The behavior of clients +that encounter such a certificate when processing a certification +path is not defined by this profile. +******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_empty_name", + Description: "General name fields MUST NOT be empty in subjectAlternateNames", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &SANEmptyName{}, + }) +} + +func (l *SANEmptyName) Initialize() error { + return nil +} + +func (l *SANEmptyName) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANEmptyName) Execute(c *x509.Certificate) *lint.LintResult { + value := util.GetExtFromCert(c, util.SubjectAlternateNameOID).Value + var seq asn1.RawValue + if _, err := asn1.Unmarshal(value, &seq); err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { + return &lint.LintResult{Status: lint.Fatal} + } + + rest := seq.Bytes + for len(rest) > 0 { + var v asn1.RawValue + var err error + rest, err = asn1.Unmarshal(rest, &v) + if err != nil { + return &lint.LintResult{Status: lint.NA} + } + if len(v.Bytes) == 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go new file mode 100644 index 0000000000..dae062c72a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go @@ -0,0 +1,63 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANNoEntry struct{} + +/********************************************************************** +RFC 5280: 4.2.1.6 +If the subjectAltName extension is present, the sequence MUST contain + at least one entry. Unlike the subject field, conforming CAs MUST + NOT issue certificates with subjectAltNames containing empty + GeneralName fields. For example, an rfc822Name is represented as an + IA5String. While an empty string is a valid IA5String, such an + rfc822Name is not permitted by this profile. The behavior of clients + that encounter such a certificate when processing a certification + path is not defined by this profile. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_no_entries", + Description: "If present, the SAN extension MUST contain at least one entry", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &SANNoEntry{}, + }) +} + +func (l *SANNoEntry) Initialize() error { + return nil +} + +func (l *SANNoEntry) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANNoEntry) Execute(c *x509.Certificate) *lint.LintResult { + san := util.GetExtFromCert(c, util.SubjectAlternateNameOID) + if util.IsEmptyASN1Sequence(san.Value) { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go new file mode 100644 index 0000000000..99cf835c1e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go @@ -0,0 +1,63 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type extSANNotCritNoSubject struct{} + +/************************************************ +RFC 5280: 4.2.1.6 +Further, if the only subject identity included in the certificate is + an alternative name form (e.g., an electronic mail address), then the + subject distinguished name MUST be empty (an empty sequence), and the + subjectAltName extension MUST be present. If the subject field + contains an empty sequence, then the issuing CA MUST include a + subjectAltName extension that is marked as critical. When including + the subjectAltName extension in a certificate that has a non-empty + subject distinguished name, conforming CAs SHOULD mark the + subjectAltName extension as non-critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_not_critical_without_subject", + Description: "If there is an empty subject field, then the SAN extension MUST be critical", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &extSANNotCritNoSubject{}, + }) +} + +func (l *extSANNotCritNoSubject) Initialize() error { + return nil +} + +func (l *extSANNotCritNoSubject) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *extSANNotCritNoSubject) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.SubjectAlternateNameOID); !util.NotAllNameFieldsAreEmpty(&c.Subject) && !e.Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go new file mode 100644 index 0000000000..2797f60c2a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go @@ -0,0 +1,70 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type invalidEmail struct{} + +/************************************************************************ +RFC 5280: 4.2.1.6 + When the subjectAltName extension contains an Internet mail address, + the address MUST be stored in the rfc822Name. The format of an + rfc822Name is a "Mailbox" as defined in Section 4.1.2 of [RFC2821]. + A Mailbox has the form "Local-part@Domain". Note that a Mailbox has + no phrase (such as a common name) before it, has no comment (text + surrounded in parentheses) after it, and is not surrounded by "<" and + ">". Rules for encoding Internet mail addresses that include + internationalized domain names are specified in Section 7.5. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_rfc822_format_invalid", + Description: "Email MUST NOT be surrounded with `<>`, and there must be no trailing comments in `()`", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &invalidEmail{}, + }) +} + +func (l *invalidEmail) Initialize() error { + return nil +} + +func (l *invalidEmail) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *invalidEmail) Execute(c *x509.Certificate) *lint.LintResult { + for _, str := range c.EmailAddresses { + if str == "" { + continue + } + if strings.Contains(str, " ") { + return &lint.LintResult{Status: lint.Error} + } else if str[0] == '<' || str[len(str)-1] == ')' { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go new file mode 100644 index 0000000000..8fb6f2197b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANIsSpaceDNS struct{} + +/************************************************************************ +RFC 5280: 4.2.1.6 +When the subjectAltName extension contains a domain name system + label, the domain name MUST be stored in the dNSName (an IA5String). + The name MUST be in the "preferred name syntax", as specified by + Section 3.5 of [RFC1034] and as modified by Section 2.1 of + [RFC1123]. Note that while uppercase and lowercase letters are + allowed in domain names, no significance is attached to the case. In + addition, while the string " " is a legal domain name, subjectAltName + extensions with a dNSName of " " MUST NOT be used. Finally, the use + of the DNS representation for Internet mail addresses + (subscriber.example.com instead of subscriber@example.com) MUST NOT + be used; such identities are to be encoded as rfc822Name. Rules for + encoding internationalized domain names are specified in Section 7.2. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_space_dns_name", + Description: "The dNSName ` ` MUST NOT be used", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &SANIsSpaceDNS{}, + }) +} + +func (l *SANIsSpaceDNS) Initialize() error { + return nil +} + +func (l *SANIsSpaceDNS) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *SANIsSpaceDNS) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if dns == " " { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go new file mode 100644 index 0000000000..de462c86fa --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go @@ -0,0 +1,70 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type extSANURIFormatInvalid struct{} + +/************************************************ +The name MUST include both a +scheme (e.g., "http" or "ftp") and a scheme-specific-part. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_uri_format_invalid", + Description: "URIs in SAN extension must have a scheme and scheme specific part", + Citation: "RFC5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &extSANURIFormatInvalid{}, + }) +} + +func (l *extSANURIFormatInvalid) Initialize() error { + return nil +} + +func (l *extSANURIFormatInvalid) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *extSANURIFormatInvalid) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.URIs { + parsed_uri, err := url.Parse(uri) + + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + + //scheme + if parsed_uri.Scheme == "" { + return &lint.LintResult{Status: lint.Error} + } + + //scheme-specific part + if parsed_uri.Host == "" && parsed_uri.User == nil && parsed_uri.Opaque == "" && parsed_uri.Path == "" { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go new file mode 100644 index 0000000000..929e70a914 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go @@ -0,0 +1,79 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SANURIHost struct{} + +/********************************************************************* +When the subjectAltName extension contains a URI, the name MUST be +stored in the uniformResourceIdentifier (an IA5String). The name +MUST NOT be a relative URI, and it MUST follow the URI syntax and +encoding rules specified in [RFC3986]. The name MUST include both a +scheme (e.g., "http" or "ftp") and a scheme-specific-part. URIs that +include an authority ([RFC3986], Section 3.2) MUST include a fully +qualified domain name or IP address as the host. Rules for encoding +Internationalized Resource Identifiers (IRIs) are specified in +Section 7.4. +*********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_uri_host_not_fqdn_or_ip", + Description: "URIs that include an authority ([RFC3986], Section 3.2) MUST include a fully qualified domain name or IP address as the host", + Citation: "RFC 5280: 4.2.1.7", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &SANURIHost{}, + }) +} + +func (l *SANURIHost) Initialize() error { + return nil +} + +func (l *SANURIHost) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +//nolint:nestif +func (l *SANURIHost) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.URIs { + if uri != "" { + parsed, err := url.Parse(uri) + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + if parsed.Opaque == "" { + // if Opaque is not empty, that means there is no authority, which means that the URI is vacuously OK + if parsed.Host == "" { + return &lint.LintResult{Status: lint.Error} + } + if !util.IsFQDNOrIP(parsed.Host) { + return &lint.LintResult{Status: lint.Error} + } + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go new file mode 100644 index 0000000000..ff75b29fcd --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go @@ -0,0 +1,60 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type extSANURINotIA5 struct{} + +/************************************************ +When the subjectAltName extension contains a URI, the name MUST be +stored in the uniformResourceIdentifier (an IA5String). +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_uri_not_ia5", + Description: "When subjectAlternateName contains a URI, the name MUST be an IA5 string", + Citation: "RFC5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &extSANURINotIA5{}, + }) +} + +func (l *extSANURINotIA5) Initialize() error { + return nil +} + +func (l *extSANURINotIA5) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *extSANURINotIA5) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.URIs { + for _, c := range uri { + if c > unicode.MaxASCII { + return &lint.LintResult{Status: lint.Error} + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go new file mode 100644 index 0000000000..3abfd70958 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go @@ -0,0 +1,71 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type extSANURIRelative struct{} + +/************************************************************************* +When the subjectAltName extension contains a URI, the name MUST be +stored in the uniformResourceIdentifier (an IA5String). The name +MUST NOT be a relative URI, and it MUST follow the URI syntax and +encoding rules specified in [RFC3986]. The name MUST include both a +scheme (e.g., "http" or "ftp") and a scheme-specific-part. URIs that +include an authority ([RFC3986], Section 3.2) MUST include a fully +qualified domain name or IP address as the host. Rules for encoding +Internationalized Resource Identifiers (IRIs) are specified in +Section 7.4. +*************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_san_uri_relative", + Description: "When the subjectAlternateName extension is present and a URI is used, the name MUST NOT be a relative URI", + Citation: "RFC 5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &extSANURIRelative{}, + }) +} + +func (l *extSANURIRelative) Initialize() error { + return nil +} + +func (l *extSANURIRelative) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *extSANURIRelative) Execute(c *x509.Certificate) *lint.LintResult { + for _, uri := range c.URIs { + parsed_uri, err := url.Parse(uri) + + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + + if !parsed_uri.IsAbs() { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go new file mode 100644 index 0000000000..f24fe5c08f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go @@ -0,0 +1,58 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subDirAttrCrit struct{} + +/************************************************ +RFC 5280: 4.2.1.8 +The subject directory attributes extension is used to convey + identification attributes (e.g., nationality) of the subject. The + extension is defined as a sequence of one or more attributes. + Conforming CAs MUST mark this extension as non-critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_subject_directory_attr_critical", + Description: "Conforming CAs MUST mark the Subject Directory Attributes extension as not critical", + Citation: "RFC 5280: 4.2.1.8", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subDirAttrCrit{}, + }) +} + +func (l *subDirAttrCrit) Initialize() error { + return nil +} + +func (l *subDirAttrCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectDirAttrOID) +} + +func (l *subDirAttrCrit) Execute(c *x509.Certificate) *lint.LintResult { + if e := util.GetExtFromCert(c, util.SubjectDirAttrOID); e.Critical { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go new file mode 100644 index 0000000000..8979ef13cb --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go @@ -0,0 +1,56 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectKeyIdCritical struct{} + +/********************************************************** +RFC 5280: 4.2.1.2 + Conforming CAs MUST mark this extension as non-critical. +**********************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_subject_key_identifier_critical", + Description: "The subject key identifier extension MUST be non-critical", + Citation: "RFC 5280: 4.2.1.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectKeyIdCritical{}, + }) +} + +func (l *subjectKeyIdCritical) Initialize() error { + return nil +} + +func (l *subjectKeyIdCritical) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectKeyIdentityOID) +} + +func (l *subjectKeyIdCritical) Execute(c *x509.Certificate) *lint.LintResult { + ski := util.GetExtFromCert(c, util.SubjectKeyIdentityOID) //pointer to the extension + if ski.Critical { + return &lint.LintResult{Status: lint.Error} + } else { //implies !ski.Critical + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go new file mode 100644 index 0000000000..87e1f524ed --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go @@ -0,0 +1,70 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectKeyIdMissingCA struct{} + +/************************************************ + To facilitate certification path construction, this extension MUST + appear in all conforming CA certificates, that is, all certificates + including the basic constraints extension (Section 4.2.1.9) where the + value of cA is TRUE. In conforming CA certificates, the value of the + subject key identifier MUST be the value placed in the key identifier + field of the authority key identifier extension (Section 4.2.1.1) of + certificates issued by the subject of this certificate. Applications + are not required to verify that key identifiers match when performing + certification path validation. + ... + For end entity certificates, the subject key identifier extension provides + a means for identifying certificates containing the particular public key + used in an application. Where an end entity has obtained multiple certificates, + especially from multiple CAs, the subject key identifier provides a means to + quickly identify the set of certificates containing a particular public key. + To assist applications in identifying the appropriate end entity certificate, + this extension SHOULD be included in all end entity certificates. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ext_subject_key_identifier_missing_ca", + Description: "CAs MUST include a Subject Key Identifier in all CA certificates", + Citation: "RFC 5280: 4.2 & 4.2.1.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectKeyIdMissingCA{}, + }) +} + +func (l *subjectKeyIdMissingCA) Initialize() error { + return nil +} + +func (l *subjectKeyIdMissingCA) CheckApplies(cert *x509.Certificate) bool { + return util.IsCACert(cert) +} + +func (l *subjectKeyIdMissingCA) Execute(cert *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(cert, util.SubjectKeyIdentityOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go new file mode 100644 index 0000000000..9e89326137 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go @@ -0,0 +1,70 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectKeyIdMissingSubscriber struct{} + +/********************************************************************** + To facilitate certification path construction, this extension MUST + appear in all conforming CA certificates, that is, all certificates + including the basic constraints extension (Section 4.2.1.9) where the + value of cA is TRUE. In conforming CA certificates, the value of the + subject key identifier MUST be the value placed in the key identifier + field of the authority key identifier extension (Section 4.2.1.1) of + certificates issued by the subject of this certificate. Applications + are not required to verify that key identifiers match when performing + certification path validation. + ... + For end entity certificates, the subject key identifier extension provides + a means for identifying certificates containing the particular public key + used in an application. Where an end entity has obtained multiple certificates, + especially from multiple CAs, the subject key identifier provides a means to + quickly identify the set of certificates containing a particular public key. + To assist applications in identifying the appropriate end entity certificate, + this extension SHOULD be included in all end entity certificates. +**********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_ext_subject_key_identifier_missing_sub_cert", + Description: "Sub certificates SHOULD include Subject Key Identifier in end entity certs", + Citation: "RFC 5280: 4.2 & 4.2.1.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectKeyIdMissingSubscriber{}, + }) +} + +func (l *subjectKeyIdMissingSubscriber) Initialize() error { + return nil +} + +func (l *subjectKeyIdMissingSubscriber) CheckApplies(cert *x509.Certificate) bool { + return !util.IsCACert(cert) +} + +func (l *subjectKeyIdMissingSubscriber) Execute(cert *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(cert, util.SubjectKeyIdentityOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go new file mode 100644 index 0000000000..702e2f703c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go @@ -0,0 +1,98 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type generalizedNoSeconds struct { +} + +/******************************************************************** +4.1.2.5.2. GeneralizedTime +The generalized time type, GeneralizedTime, is a standard ASN.1 type +for variable precision representation of time. Optionally, the +GeneralizedTime field can include a representation of the time +differential between local and Greenwich Mean Time. + +For the purposes of this profile, GeneralizedTime values MUST be +expressed in Greenwich Mean Time (Zulu) and MUST include seconds +(i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds +is zero. GeneralizedTime values MUST NOT include fractional seconds. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_generalized_time_does_not_include_seconds", + Description: "Generalized time values MUST include seconds", + Citation: "RFC 5280: 4.1.2.5.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &generalizedNoSeconds{}, + }) +} + +func (l *generalizedNoSeconds) Initialize() error { + return nil +} + +func (l *generalizedNoSeconds) CheckApplies(c *x509.Certificate) bool { + firstDate, secondDate := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(firstDate, secondDate) + date1Gen := beforeTag == 24 + date2Gen := afterTag == 24 + return date1Gen || date2Gen +} + +func (l *generalizedNoSeconds) Execute(c *x509.Certificate) *lint.LintResult { + r := lint.Pass + date1, date2 := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(date1, date2) + date1Gen := beforeTag == 24 + date2Gen := afterTag == 24 + if date1Gen { + // UTC Tests on notBefore + checkSeconds(&r, date1) + if r == lint.Error { + return &lint.LintResult{Status: r} + } + } + if date2Gen { + checkSeconds(&r, date2) + } + return &lint.LintResult{Status: r} +} + +//nolint:nestif +func checkSeconds(r *lint.LintStatus, t asn1.RawValue) { + if t.Bytes[len(t.Bytes)-1] == 'Z' { + if len(t.Bytes) < 15 { + *r = lint.Error + } + } else if t.Bytes[len(t.Bytes)-5] == '-' || t.Bytes[len(t.Bytes)-1] == '+' { + if len(t.Bytes) < 19 { + *r = lint.Error + } + } else { + if len(t.Bytes) < 14 { + *r = lint.Error + } + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go new file mode 100644 index 0000000000..0fb5911180 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go @@ -0,0 +1,98 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type generalizedTimeFraction struct { +} + +/******************************************************************** +4.1.2.5.2. GeneralizedTime +The generalized time type, GeneralizedTime, is a standard ASN.1 type +for variable precision representation of time. Optionally, the +GeneralizedTime field can include a representation of the time +differential between local and Greenwich Mean Time. + +For the purposes of this profile, GeneralizedTime values MUST be +expressed in Greenwich Mean Time (Zulu) and MUST include seconds +(i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds +is zero. GeneralizedTime values MUST NOT include fractional seconds. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_generalized_time_includes_fraction_seconds", + Description: "Generalized time values MUST NOT include fractional seconds", + Citation: "RFC 5280: 4.1.2.5.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &generalizedTimeFraction{}, + }) +} + +func (l *generalizedTimeFraction) Initialize() error { + return nil +} + +func (l *generalizedTimeFraction) CheckApplies(c *x509.Certificate) bool { + firstDate, secondDate := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(firstDate, secondDate) + date1Gen := beforeTag == 24 + date2Gen := afterTag == 24 + return date1Gen || date2Gen +} + +func (l *generalizedTimeFraction) Execute(c *x509.Certificate) *lint.LintResult { + r := lint.Pass + date1, date2 := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(date1, date2) + date1Gen := beforeTag == 24 + date2Gen := afterTag == 24 + if date1Gen { + // UTC Tests on notBefore + checkFraction(&r, date1) + if r == lint.Error { + return &lint.LintResult{Status: r} + } + } + if date2Gen { + checkFraction(&r, date2) + } + return &lint.LintResult{Status: r} +} + +//nolint:nestif +func checkFraction(r *lint.LintStatus, t asn1.RawValue) { + if t.Bytes[len(t.Bytes)-1] == 'Z' { + if len(t.Bytes) > 15 { + *r = lint.Error + } + } else if t.Bytes[len(t.Bytes)-5] == '-' || t.Bytes[len(t.Bytes)-1] == '+' { + if len(t.Bytes) > 19 { + *r = lint.Error + } + } else { + if len(t.Bytes) > 14 { + *r = lint.Error + } + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go new file mode 100644 index 0000000000..353d7f99fc --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go @@ -0,0 +1,78 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type generalizedNotZulu struct { +} + +/******************************************************************** +4.1.2.5.2. GeneralizedTime +The generalized time type, GeneralizedTime, is a standard ASN.1 type +for variable precision representation of time. Optionally, the +GeneralizedTime field can include a representation of the time +differential between local and Greenwich Mean Time. + +For the purposes of this profile, GeneralizedTime values MUST be +expressed in Greenwich Mean Time (Zulu) and MUST include seconds +(i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds +is zero. GeneralizedTime values MUST NOT include fractional seconds. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_generalized_time_not_in_zulu", + Description: "Generalized time values MUST be expressed in Greenwich Mean Time (Zulu)", + Citation: "RFC 5280: 4.1.2.5.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &generalizedNotZulu{}, + }) +} + +func (l *generalizedNotZulu) Initialize() error { + return nil +} + +func (l *generalizedNotZulu) CheckApplies(c *x509.Certificate) bool { + firstDate, secondDate := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(firstDate, secondDate) + date1Gen := beforeTag == 24 + date2Gen := afterTag == 24 + return date1Gen || date2Gen +} + +func (l *generalizedNotZulu) Execute(c *x509.Certificate) *lint.LintResult { + date1, date2 := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(date1, date2) + date1Gen := beforeTag == 24 + date2Gen := afterTag == 24 + if date1Gen { + if date1.Bytes[len(date1.Bytes)-1] != 'Z' { + return &lint.LintResult{Status: lint.Error} + } + } + if date2Gen { + if date2.Bytes[len(date2.Bytes)-1] != 'Z' { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go new file mode 100644 index 0000000000..65322734b0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go @@ -0,0 +1,60 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + "golang.org/x/net/idna" +) + +type IDNMalformedUnicode struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_international_dns_name_not_unicode", + Description: "Internationalized DNSNames punycode not valid unicode", + Citation: "RFC 3490", + EffectiveDate: util.RFC3490Date, + Source: lint.RFC5280, + Lint: &IDNMalformedUnicode{}, + }) +} + +func (l *IDNMalformedUnicode) Initialize() error { + return nil +} + +func (l *IDNMalformedUnicode) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *IDNMalformedUnicode) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + labels := strings.Split(dns, ".") + for _, label := range labels { + if strings.HasPrefix(label, "xn--") { + _, err := idna.ToUnicode(label) + if err != nil { + return &lint.LintResult{Status: lint.Error} + } + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go new file mode 100644 index 0000000000..13b69762c1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + "golang.org/x/net/idna" + "golang.org/x/text/unicode/norm" +) + +type IDNNotNFC struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_international_dns_name_not_nfc", + Description: "Internationalized DNSNames must be normalized by unicode normalization form C", + Citation: "RFC 8399", + Source: lint.RFC5891, + EffectiveDate: util.RFC8399Date, + Lint: &IDNNotNFC{}, + }) +} + +func (l *IDNNotNFC) Initialize() error { + return nil +} + +func (l *IDNNotNFC) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectAlternateNameOID) +} + +func (l *IDNNotNFC) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + labels := strings.Split(dns, ".") + for _, label := range labels { + if strings.HasPrefix(label, "xn--") { + unicodeLabel, err := idna.ToUnicode(label) + if err != nil { + return &lint.LintResult{Status: lint.NA} + } + if !norm.NFC.IsNormalString(unicodeLabel) { + return &lint.LintResult{Status: lint.Error} + } + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go new file mode 100644 index 0000000000..93cb4b6546 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type InhibitAnyPolicyNotCritical struct{} + +/************************************************ +4.2.1.14. Inhibit anyPolicy + The inhibit anyPolicy extension can be used in certificates issued to CAs. + The inhibit anyPolicy extension indicates that the special anyPolicy OID, + with the value { 2 5 29 32 0 }, is not considered an explicit match for other + certificate policies except when it appears in an intermediate self-issued + CA certificate. The value indicates the number of additional non-self-issued + certificates that may appear in the path before anyPolicy is no longer permitted. + For example, a value of one indicates that anyPolicy may be processed in + certificates issued by the subject of this certificate, but not in additional + certificates in the path. + + Conforming CAs MUST mark this extension as critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_inhibit_any_policy_not_critical", + Description: "CAs MUST mark the inhibitAnyPolicy extension as critical", + Citation: "RFC 5280: 4.2.1.14", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &InhibitAnyPolicyNotCritical{}, + }) +} + +func (l *InhibitAnyPolicyNotCritical) Initialize() error { + return nil +} + +func (l *InhibitAnyPolicyNotCritical) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.InhibitAnyPolicyOID) +} + +func (l *InhibitAnyPolicyNotCritical) Execute(cert *x509.Certificate) *lint.LintResult { + if anyPol := util.GetExtFromCert(cert, util.InhibitAnyPolicyOID); !anyPol.Critical { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go new file mode 100644 index 0000000000..504a36d331 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type IssuerDNCountryNotPrintableString struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_issuer_dn_country_not_printable_string", + Description: "X520 Distinguished Name Country MUST BE encoded as PrintableString", + Citation: "RFC 5280: Appendix A", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: &IssuerDNCountryNotPrintableString{}, + }) +} + +func (l *IssuerDNCountryNotPrintableString) Initialize() error { + return nil +} + +func (l *IssuerDNCountryNotPrintableString) CheckApplies(c *x509.Certificate) bool { + return len(c.Issuer.Country) > 0 +} + +func (l *IssuerDNCountryNotPrintableString) Execute(c *x509.Certificate) *lint.LintResult { + rdnSequence := util.RawRDNSequence{} + rest, err := asn1.Unmarshal(c.RawIssuer, &rdnSequence) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(rest) > 0 { + return &lint.LintResult{Status: lint.Fatal} + } + + for _, attrTypeAndValueSet := range rdnSequence { + for _, attrTypeAndValue := range attrTypeAndValueSet { + if attrTypeAndValue.Type.Equal(util.CountryNameOID) && attrTypeAndValue.Value.Tag != asn1.TagPrintableString { + return &lint.LintResult{Status: lint.Error} + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go new file mode 100644 index 0000000000..f13c26ad0e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go @@ -0,0 +1,58 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type issuerFieldEmpty struct{} + +/************************************************ +RFC 5280: 4.1.2.4 +The issuer field identifies the entity that has signed and issued the + certificate. The issuer field MUST contain a non-empty distinguished + name (DN). The issuer field is defined as the X.501 type Name + [X.501]. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_issuer_field_empty", + Description: "Certificate issuer field MUST NOT be empty and must have a non-empty distinguished name", + Citation: "RFC 5280: 4.1.2.4", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &issuerFieldEmpty{}, + }) +} + +func (l *issuerFieldEmpty) Initialize() error { + return nil +} + +func (l *issuerFieldEmpty) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *issuerFieldEmpty) Execute(c *x509.Certificate) *lint.LintResult { + if util.NotAllNameFieldsAreEmpty(&c.Issuer) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Error} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go new file mode 100644 index 0000000000..958bca6606 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go @@ -0,0 +1,79 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintEmpty struct{} + +/*********************************************************************** + Restrictions are defined in terms of permitted or excluded name + subtrees. Any name matching a restriction in the excludedSubtrees + field is invalid regardless of information appearing in the + permittedSubtrees. Conforming CAs MUST mark this extension as + critical and SHOULD NOT impose name constraints on the x400Address, + ediPartyName, or registeredID name forms. Conforming CAs MUST NOT + issue certificates where name constraints is an empty sequence. That + is, either the permittedSubtrees field or the excludedSubtrees MUST + be present. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_name_constraint_empty", + Description: "Conforming CAs MUST NOT issue certificates where name constraints is an empty sequence. That is, either the permittedSubtree or excludedSubtree fields must be present", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &nameConstraintEmpty{}, + }) +} + +func (l *nameConstraintEmpty) Initialize() error { + return nil +} + +func (l *nameConstraintEmpty) CheckApplies(c *x509.Certificate) bool { + if !(util.IsExtInCert(c, util.NameConstOID)) { + return false + } + nc := util.GetExtFromCert(c, util.NameConstOID) + var seq asn1.RawValue + rest, err := asn1.Unmarshal(nc.Value, &seq) //only one sequence, so rest should be empty + if err != nil || len(rest) != 0 || seq.Tag != 16 || seq.Class != 0 || !seq.IsCompound { + return false + } + return true +} + +func (l *nameConstraintEmpty) Execute(c *x509.Certificate) *lint.LintResult { + nc := util.GetExtFromCert(c, util.NameConstOID) + var seq asn1.RawValue + _, err := asn1.Unmarshal(nc.Value, &seq) //only one sequence, so rest should be empty + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(seq.Bytes) == 0 { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go new file mode 100644 index 0000000000..2a5c653f2e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go @@ -0,0 +1,128 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintMax struct{} + +/************************************************************************ +RFC 5280: 4.2.1.10 +Within this profile, the minimum and maximum fields are not used with +any name forms, thus, the minimum MUST be zero, and maximum MUST be +absent. However, if an application encounters a critical name +constraints extension that specifies other values for minimum or +maximum for a name form that appears in a subsequent certificate, the +application MUST either process these fields or reject the +certificate. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_name_constraint_maximum_not_absent", + Description: "Within the name constraints name form, the maximum field is not used and therefore MUST be absent", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &nameConstraintMax{}, + }) +} + +func (l *nameConstraintMax) Initialize() error { + return nil +} + +func (l *nameConstraintMax) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +//nolint:gocyclo +func (l *nameConstraintMax) Execute(c *x509.Certificate) *lint.LintResult { + for _, i := range c.PermittedDNSNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedDNSNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedDNSNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedEmailAddresses { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedIPAddresses { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedIPAddresses { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedDirectoryNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedDirectoryNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedEdiPartyNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedEdiPartyNames { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedRegisteredIDs { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedRegisteredIDs { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedX400Addresses { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedX400Addresses { + if i.Max != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go new file mode 100644 index 0000000000..a64a67b645 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go @@ -0,0 +1,128 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstMin struct{} + +/************************************************************************ +RFC 5280: 4.2.1.10 +Within this profile, the minimum and maximum fields are not used with +any name forms, thus, the minimum MUST be zero, and maximum MUST be +absent. However, if an application encounters a critical name +constraints extension that specifies other values for minimum or +maximum for a name form that appears in a subsequent certificate, the +application MUST either process these fields or reject the +certificate. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_name_constraint_minimum_non_zero", + Description: "Within the name constraints name forms, the minimum field is not used and therefore MUST be zero", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &nameConstMin{}, + }) +} + +func (l *nameConstMin) Initialize() error { + return nil +} + +func (l *nameConstMin) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +//nolint:gocyclo +func (l *nameConstMin) Execute(c *x509.Certificate) *lint.LintResult { + for _, i := range c.PermittedDNSNames { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedDNSNames { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedEmailAddresses { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedEmailAddresses { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedIPAddresses { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedIPAddresses { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedDirectoryNames { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedDirectoryNames { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedEdiPartyNames { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedEdiPartyNames { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedRegisteredIDs { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedRegisteredIDs { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.PermittedX400Addresses { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + for _, i := range c.ExcludedX400Addresses { + if i.Min != 0 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go new file mode 100644 index 0000000000..ae283df50c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go @@ -0,0 +1,132 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintNotFQDN struct{} + +/*********************************************************************** + For URIs, the constraint applies to the host part of the name. The + constraint MUST be specified as a fully qualified domain name and MAY + specify a host or a domain. Examples would be "host.example.com" and + ".example.com". When the constraint begins with a period, it MAY be + expanded with one or more labels. That is, the constraint + ".example.com" is satisfied by both host.example.com and + my.host.example.com. However, the constraint ".example.com" is not + satisfied by "example.com". When the constraint does not begin with + a period, it specifies a host. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_name_constraint_not_fqdn", + Description: "For URIs, the constraint MUST be specified as a fully qualified domain name [...] When the constraint begins with a period, it MAY be expanded with one or more labels.", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &nameConstraintNotFQDN{}, + }) +} + +func (l *nameConstraintNotFQDN) Initialize() error { + return nil +} + +func (l *nameConstraintNotFQDN) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +func (l *nameConstraintNotFQDN) Execute(c *x509.Certificate) *lint.LintResult { + + var incorrectPermittedHosts []string + var incorrectExcludedHosts []string + var errString string + + incorrectPermittedHosts = collectNotFQDNEntries(c.PermittedURIs) + incorrectExcludedHosts = collectNotFQDNEntries(c.ExcludedURIs) + + if len(incorrectPermittedHosts) != 0 { + errString += buildErrorString(incorrectPermittedHosts, true) + } + if len(incorrectPermittedHosts) != 0 && len(incorrectExcludedHosts) != 0 { + errString += "; " + } + if len(incorrectExcludedHosts) != 0 { + errString += buildErrorString(incorrectExcludedHosts, false) + } + + if len(errString) != 0 { + return &lint.LintResult{ + Status: lint.Error, + Details: errString, + } + } + + return &lint.LintResult{Status: lint.Pass} +} + +func collectNotFQDNEntries(hosts []x509.GeneralSubtreeString) []string { + var incorrectHosts []string + + for _, subtreeString := range hosts { + host := subtreeString.Data + + host = strings.TrimPrefix(host, ".") + + if !util.IsFQDN(host) { + incorrectHosts = append(incorrectHosts, host) + } + } + + return incorrectHosts +} + +func buildErrorString(incorrectHosts []string, isInclusion bool) string { + + errString := "certificate contained " + + if len(incorrectHosts) > 1 { + errString += "multiple " + } else { + errString += "an " + } + + if isInclusion { + errString += "inclusion " + } else { + errString += "exclusion " + } + + if len(incorrectHosts) > 1 { + + errString += "name constraints that are not fully qualified domain names: " + incorrectHosts[0] + for _, incorrectHost := range incorrectHosts[1:] { + util.AppendToStringSemicolonDelim(&errString, incorrectHost) + } + return errString + + } + + errString += "name constraint that is not a fully qualified domain name: " + incorrectHosts[0] + return errString + +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go new file mode 100644 index 0000000000..13150c7cd8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintOnEDI struct{} + +/******************************************************************* +RFC 5280: 4.2.1.10 +Restrictions are defined in terms of permitted or excluded name +subtrees. Any name matching a restriction in the excludedSubtrees +field is invalid regardless of information appearing in the +permittedSubtrees. Conforming CAs MUST mark this extension as +critical and SHOULD NOT impose name constraints on the x400Address, +ediPartyName, or registeredID name forms. Conforming CAs MUST NOT +issue certificates where name constraints is an empty sequence. That +is, either the permittedSubtrees field or the excludedSubtrees MUST +be present. +*******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_name_constraint_on_edi_party_name", + Description: "The name constraints extension SHOULD NOT impose constraints on the ediPartyName name form", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &nameConstraintOnEDI{}, + }) +} + +func (l *nameConstraintOnEDI) Initialize() error { + return nil +} + +func (l *nameConstraintOnEDI) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +func (l *nameConstraintOnEDI) Execute(c *x509.Certificate) *lint.LintResult { + if c.PermittedEdiPartyNames != nil || c.ExcludedEdiPartyNames != nil { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go new file mode 100644 index 0000000000..583c680fb8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintOnRegisteredId struct{} + +/******************************************************************* +RFC 5280: 4.2.1.10 +Restrictions are defined in terms of permitted or excluded name +subtrees. Any name matching a restriction in the excludedSubtrees +field is invalid regardless of information appearing in the +permittedSubtrees. Conforming CAs MUST mark this extension as +critical and SHOULD NOT impose name constraints on the x400Address, +ediPartyName, or registeredID name forms. Conforming CAs MUST NOT +issue certificates where name constraints is an empty sequence. That +is, either the permittedSubtrees field or the excludedSubtrees MUST +be present. +*******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_name_constraint_on_registered_id", + Description: "The name constraints extension SHOULD NOT impose constraints on the registeredID name form", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &nameConstraintOnRegisteredId{}, + }) +} + +func (l *nameConstraintOnRegisteredId) Initialize() error { + return nil +} + +func (l *nameConstraintOnRegisteredId) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +func (l *nameConstraintOnRegisteredId) Execute(c *x509.Certificate) *lint.LintResult { + if c.PermittedRegisteredIDs != nil || c.ExcludedRegisteredIDs != nil { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go new file mode 100644 index 0000000000..1bfb012c03 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type nameConstraintOnX400 struct{} + +/******************************************************************* +RFC 5280: 4.2.1.10 +Restrictions are defined in terms of permitted or excluded name +subtrees. Any name matching a restriction in the excludedSubtrees +field is invalid regardless of information appearing in the +permittedSubtrees. Conforming CAs MUST mark this extension as +critical and SHOULD NOT impose name constraints on the x400Address, +ediPartyName, or registeredID name forms. Conforming CAs MUST NOT +issue certificates where name constraints is an empty sequence. That +is, either the permittedSubtrees field or the excludedSubtrees MUST +be present. +*******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_name_constraint_on_x400", + Description: "The name constraints extension SHOULD NOT impose constraints on the x400Address name form", + Citation: "RFC 5280: 4.2.1.10", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &nameConstraintOnX400{}, + }) +} + +func (l *nameConstraintOnX400) Initialize() error { + return nil +} + +func (l *nameConstraintOnX400) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.NameConstOID) +} + +func (l *nameConstraintOnX400) Execute(c *x509.Certificate) *lint.LintResult { + if c.PermittedX400Addresses != nil || c.ExcludedX400Addresses != nil { + return &lint.LintResult{Status: lint.Warn} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go new file mode 100644 index 0000000000..7fc68a799e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go @@ -0,0 +1,73 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type pathLenIncluded struct{} + +/****************************************************************** +RFC 5280: 4.2.1.9 +CAs MUST NOT include the pathLenConstraint field unless the cA +boolean is asserted and the key usage extension asserts the +keyCertSign bit. +******************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_path_len_constraint_improperly_included", + Description: "CAs MUST NOT include the pathLenConstraint field unless the CA boolean is asserted and the keyCertSign bit is set", + Citation: "RFC 5280: 4.2.1.9", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &pathLenIncluded{}, + }) +} + +func (l *pathLenIncluded) Initialize() error { + return nil +} + +func (l *pathLenIncluded) CheckApplies(cert *x509.Certificate) bool { + return util.IsExtInCert(cert, util.BasicConstOID) +} + +func (l *pathLenIncluded) Execute(cert *x509.Certificate) *lint.LintResult { + bc := util.GetExtFromCert(cert, util.BasicConstOID) + var seq asn1.RawValue + var isCa bool + _, err := asn1.Unmarshal(bc.Value, &seq) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(seq.Bytes) == 0 { + return &lint.LintResult{Status: lint.Pass} + } + rest, err := asn1.UnmarshalWithParams(seq.Bytes, &isCa, "optional") + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + keyUsageValue := util.IsExtInCert(cert, util.KeyUsageOID) + if len(rest) > 0 && (!cert.IsCA || !keyUsageValue || (keyUsageValue && cert.KeyUsage&x509.KeyUsageCertSign == 0)) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go new file mode 100644 index 0000000000..0bc2d08921 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go @@ -0,0 +1,79 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type basicConst struct { + CA bool `asn1:"optional"` + PathLenConstraint int `asn1:"optional"` +} + +type pathLenNonPositive struct { +} + +/******************************************************************** +The pathLenConstraint field is meaningful only if the cA boolean is +asserted and the key usage extension, if present, asserts the +keyCertSign bit (Section 4.2.1.3). In this case, it gives the +maximum number of non-self-issued intermediate certificates that may +follow this certificate in a valid certification path. (Note: The +last certificate in the certification path is not an intermediate +certificate, and is not included in this limit. Usually, the last +certificate is an end entity certificate, but it can be a CA +certificate.) A pathLenConstraint of zero indicates that no non- +self-issued intermediate CA certificates may follow in a valid +certification path. Where it appears, the pathLenConstraint field +MUST be greater than or equal to zero. Where pathLenConstraint does +not appear, no limit is imposed. +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_path_len_constraint_zero_or_less", + Description: "Where it appears, the pathLenConstraint field MUST be greater than or equal to zero", + Citation: "RFC 5280: 4.2.1.9", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &pathLenNonPositive{}, + }) +} + +func (l *pathLenNonPositive) Initialize() error { + return nil +} + +func (l *pathLenNonPositive) CheckApplies(cert *x509.Certificate) bool { + return cert.BasicConstraintsValid +} + +func (l *pathLenNonPositive) Execute(cert *x509.Certificate) *lint.LintResult { + var bc basicConst + + ext := util.GetExtFromCert(cert, util.BasicConstOID) + if _, err := asn1.Unmarshal(ext.Value, &bc); err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if bc.PathLenConstraint < 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go new file mode 100644 index 0000000000..71f661b717 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go @@ -0,0 +1,89 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type serialNumberTooLong struct{} + +/************************************************ +RFC 5280: 4.1.2.2. Serial Number + The serial number MUST be a positive integer assigned by the CA to each + certificate. It MUST be unique for each certificate issued by a given CA + (i.e., the issuer name and serial number identify a unique certificate). + CAs MUST force the serialNumber to be a non-negative integer. + + Given the uniqueness requirements above, serial numbers can be expected to + contain long integers. Certificate users MUST be able to handle serialNumber + values up to 20 octets. Conforming CAs MUST NOT use serialNumber values longer + than 20 octets. + + Note: Non-conforming CAs may issue certificates with serial numbers that are + negative or zero. Certificate users SHOULD be prepared togracefully handle + such certificates. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_serial_number_longer_than_20_octets", + Description: "Certificates must not have a DER encoded serial number longer than 20 octets", + Citation: "RFC 5280: 4.1.2.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &serialNumberTooLong{}, + }) +} + +func (l *serialNumberTooLong) Initialize() error { + return nil +} + +func (l *serialNumberTooLong) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *serialNumberTooLong) Execute(c *x509.Certificate) *lint.LintResult { + // Re-encode the certificate serial number and decode it back into + // an ASN1 raw value (which does little more than perform length computations, + // figures out the tag, etc.) so that we can easily see what the actual + // DER encoded lengths are without having to guess. + encoding, err := asn1.Marshal(c.SerialNumber) + if err != nil { + return &lint.LintResult{Status: lint.Fatal, Details: fmt.Sprint(err)} + } + serial := new(asn1.RawValue) + _, err = asn1.Unmarshal(encoding, serial) + if err != nil { + return &lint.LintResult{Status: lint.Fatal, Details: fmt.Sprint(err)} + } + length := len(serial.Bytes) + if length > 20 { + details := fmt.Sprintf("The DER encoded certificate serial number is %d octets long. "+ + "If this is surprising to you, note that DER integers are signed and that SNs that are "+ + "20 octets long with an MSB of 1 will be automatically prefixed with 0x00, thus bumping "+ + "it up to 21 octets long. "+ + "SN: %X", length, serial.Bytes) + return &lint.LintResult{Status: lint.Error, Details: details} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go new file mode 100644 index 0000000000..c2cc419009 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SerialNumberNotPositive struct{} + +/************************************************ +4.1.2.2. Serial Number + The serial number MUST be a positive integer assigned by the CA to each + certificate. It MUST be unique for each certificate issued by a given CA + (i.e., the issuer name and serial number identify a unique certificate). + CAs MUST force the serialNumber to be a non-negative integer. + + Given the uniqueness requirements above, serial numbers can be expected to + contain long integers. Certificate users MUST be able to handle serialNumber + values up to 20 octets. Conforming CAs MUST NOT use serialNumber values longer + than 20 octets. + + Note: Non-conforming CAs may issue certificates with serial numbers that are + negative or zero. Certificate users SHOULD be prepared togracefully handle + such certificates. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_serial_number_not_positive", + Description: "Certificates must have a positive serial number", + Citation: "RFC 5280: 4.1.2.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &SerialNumberNotPositive{}, + }) +} + +func (l *SerialNumberNotPositive) Initialize() error { + return nil +} + +func (l *SerialNumberNotPositive) CheckApplies(cert *x509.Certificate) bool { + return true +} + +func (l *SerialNumberNotPositive) Execute(cert *x509.Certificate) *lint.LintResult { + if cert.SerialNumber.Sign() == -1 { // -1 Means negative when using big.Sign() + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go new file mode 100644 index 0000000000..b4c6a0fbc9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go @@ -0,0 +1,66 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaSPKIEncryptionParamNotNULL struct{} + +/******************************************************************************************************* +"RFC5280: RFC 4055, Section 1.2" +RSA: Encoded algorithm identifier MUST have NULL parameters. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_spki_rsa_encryption_parameter_not_null", + Description: "RSA: Encoded public key algorithm identifier MUST have NULL parameters", + Citation: "RFC 4055, Section 1.2", + Source: lint.RFC5280, // RFC4055 is referenced in lint.RFC5280, Section 1 + EffectiveDate: util.RFC5280Date, + Lint: &rsaSPKIEncryptionParamNotNULL{}, + }) +} + +func (l *rsaSPKIEncryptionParamNotNULL) Initialize() error { + return nil +} + +func (l *rsaSPKIEncryptionParamNotNULL) CheckApplies(c *x509.Certificate) bool { + // explicitly check for util.OidRSAEncryption, as RSA-PSS or RSA-OAEP certificates might be classified with c.PublicKeyAlgorithm = RSA + return c.PublicKeyAlgorithmOID.Equal(util.OidRSAEncryption) +} + +func (l *rsaSPKIEncryptionParamNotNULL) Execute(c *x509.Certificate) *lint.LintResult { + encodedPublicKeyAid, err := util.GetPublicKeyAidEncoded(c) + if err != nil { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("error reading public key algorithm identifier: %v", err), + } + } + + if err := util.CheckAlgorithmIDParamNotNULL(encodedPublicKeyAid, util.OidRSAEncryption); err != nil { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("certificate pkixPublicKey %s", err.Error())} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go new file mode 100644 index 0000000000..7a6daeef00 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go @@ -0,0 +1,59 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectCommonNameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-common-name INTEGER ::= 64 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_common_name_max_length", + Description: "The commonName field of the subject MUST be less than 65 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectCommonNameMaxLength{}, + }) +} + +func (l *subjectCommonNameMaxLength) Initialize() error { + return nil +} + +func (l *subjectCommonNameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectCommonNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + if utf8.RuneCountInString(c.Subject.CommonName) > 64 { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go new file mode 100644 index 0000000000..e1ad97aa7c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectDNCountryNotPrintableString struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_dn_country_not_printable_string", + Description: "X520 Distinguished Name Country MUST be encoded as PrintableString", + Citation: "RFC 5280: Appendix A", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: &SubjectDNCountryNotPrintableString{}, + }) +} + +func (l *SubjectDNCountryNotPrintableString) Initialize() error { + return nil +} + +func (l *SubjectDNCountryNotPrintableString) CheckApplies(c *x509.Certificate) bool { + return len(c.Subject.Country) > 0 +} + +func (l *SubjectDNCountryNotPrintableString) Execute(c *x509.Certificate) *lint.LintResult { + rdnSequence := util.RawRDNSequence{} + rest, err := asn1.Unmarshal(c.RawSubject, &rdnSequence) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(rest) > 0 { + return &lint.LintResult{Status: lint.Fatal} + } + + for _, attrTypeAndValueSet := range rdnSequence { + for _, attrTypeAndValue := range attrTypeAndValueSet { + if attrTypeAndValue.Type.Equal(util.CountryNameOID) && attrTypeAndValue.Value.Tag != asn1.TagPrintableString { + return &lint.LintResult{Status: lint.Error} + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go new file mode 100644 index 0000000000..f5f97e5e5b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go @@ -0,0 +1,74 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "encoding/asn1" + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectDNNotPrintableCharacters struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_dn_not_printable_characters", + Description: "X520 Subject fields MUST only contain printable control characters", + Citation: "RFC 5280: Appendix A", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: &subjectDNNotPrintableCharacters{}, + }) +} + +func (l *subjectDNNotPrintableCharacters) Initialize() error { + return nil +} + +func (l *subjectDNNotPrintableCharacters) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectDNNotPrintableCharacters) Execute(c *x509.Certificate) *lint.LintResult { + rdnSequence := util.RawRDNSequence{} + rest, err := asn1.Unmarshal(c.RawSubject, &rdnSequence) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(rest) > 0 { + return &lint.LintResult{Status: lint.Fatal} + } + + for _, attrTypeAndValueSet := range rdnSequence { + for _, attrTypeAndValue := range attrTypeAndValueSet { + bytes := attrTypeAndValue.Value.Bytes + for len(bytes) > 0 { + r, size := utf8.DecodeRune(bytes) + if r < 0x20 { + return &lint.LintResult{Status: lint.Error} + } + if r >= 0x7F && r <= 0x9F { + return &lint.LintResult{Status: lint.Error} + } + bytes = bytes[size:] + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go new file mode 100644 index 0000000000..f84855e627 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go @@ -0,0 +1,51 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectDNSerialNumberMaxLength struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_dn_serial_number_max_length", + Description: "The 'Serial Number' field of the subject MUST be less than 65 characters", + Citation: "RFC 5280: Appendix A", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: &SubjectDNSerialNumberMaxLength{}, + }) +} + +func (l *SubjectDNSerialNumberMaxLength) Initialize() error { + return nil +} + +func (l *SubjectDNSerialNumberMaxLength) CheckApplies(c *x509.Certificate) bool { + return len(c.Subject.SerialNumber) > 0 +} + +func (l *SubjectDNSerialNumberMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + if utf8.RuneCountInString(c.Subject.SerialNumber) > 64 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go new file mode 100644 index 0000000000..18b54c57e7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go @@ -0,0 +1,65 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectDNSerialNumberNotPrintableString struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_dn_serial_number_not_printable_string", + Description: "X520 Distinguished Name SerialNumber MUST be encoded as PrintableString", + Citation: "RFC 5280: Appendix A", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: &SubjectDNSerialNumberNotPrintableString{}, + }) +} + +func (l *SubjectDNSerialNumberNotPrintableString) Initialize() error { + return nil +} + +func (l *SubjectDNSerialNumberNotPrintableString) CheckApplies(c *x509.Certificate) bool { + return len(c.Subject.SerialNumber) > 0 +} + +func (l *SubjectDNSerialNumberNotPrintableString) Execute(c *x509.Certificate) *lint.LintResult { + rdnSequence := util.RawRDNSequence{} + rest, err := asn1.Unmarshal(c.RawSubject, &rdnSequence) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if len(rest) > 0 { + return &lint.LintResult{Status: lint.Fatal} + } + + for _, attrTypeAndValueSet := range rdnSequence { + for _, attrTypeAndValue := range attrTypeAndValueSet { + if attrTypeAndValue.Type.Equal(util.SerialOID) && attrTypeAndValue.Value.Tag != asn1.TagPrintableString { + return &lint.LintResult{Status: lint.Error} + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go new file mode 100644 index 0000000000..88259b731a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go @@ -0,0 +1,68 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectEmailMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-emailaddress-length INTEGER ::= 128 + +The ASN.1 modules in Appendix A are unchanged from RFC 3280, except +that ub-emailaddress-length was changed from 128 to 255 in order to +align with PKCS #9 [RFC2985]. + +ub-emailaddress-length INTEGER ::= 255 + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_email_max_length", + Description: "The 'Email' field of the subject MUST be less than 256 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectEmailMaxLength{}, + }) +} + +func (l *subjectEmailMaxLength) Initialize() error { + return nil +} + +func (l *subjectEmailMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectEmailMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.EmailAddress { + if utf8.RuneCountInString(j) > 255 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go new file mode 100644 index 0000000000..17649ea5a6 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type emptyWithoutSAN struct{} + +/************************************************************************* +RFC 5280: 4.2 & 4.2.1.6 +Further, if the only subject identity included in the certificate is +an alternative name form (e.g., an electronic mail address), then the +subject distinguished name MUST be empty (an empty sequence), and the +subjectAltName extension MUST be present. If the subject field +contains an empty sequence, then the issuing CA MUST include a +subjectAltName extension that is marked as critical. When including +the subjectAltName extension in a certificate that has a non-empty +subject distinguished name, conforming CAs SHOULD mark the +subjectAltName extension as non-critical. +*************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_empty_without_san", + Description: "CAs MUST support subject alternative name if the subject field is an empty sequence", + Citation: "RFC 5280: 4.2 & 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &emptyWithoutSAN{}, + }) +} + +func (l *emptyWithoutSAN) Initialize() error { + return nil +} + +func (l *emptyWithoutSAN) CheckApplies(cert *x509.Certificate) bool { + return true +} + +func (l *emptyWithoutSAN) Execute(cert *x509.Certificate) *lint.LintResult { + if subjectIsEmpty(cert) && !util.IsExtInCert(cert, util.SubjectAlternateNameOID) { + return &lint.LintResult{Status: lint.Error} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} + +func subjectIsEmpty(cert *x509.Certificate) bool { + return len(cert.Subject.Names) == 0 +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go new file mode 100644 index 0000000000..2de691db6d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectGivenNameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-given-name-length INTEGER ::= 16 + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_given_name_max_length", + Description: "The 'GivenName' field of the subject MUST be less than 17 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectGivenNameMaxLength{}, + }) +} + +func (l *subjectGivenNameMaxLength) Initialize() error { + return nil +} + +func (l *subjectGivenNameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectGivenNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.GivenName { + if utf8.RuneCountInString(j) > 16 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go new file mode 100644 index 0000000000..9cc46945bf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go @@ -0,0 +1,54 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type siaCrit struct{} + +/************************************************ +The subject information access extension indicates how to access information and services for the subject of the certificate in which the extension appears. When the subject is a CA, information and services may include certificate validation services and CA policy data. When the subject is an end entity, the information describes the type of services offered and how to access them. In this case, the contents of this extension are defined in the protocol specifications for the supported services. This extension may be included in end entity or CA certificates. Conforming CAs MUST mark this extension as non-critical. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_info_access_marked_critical", + Description: "Conforming CAs MUST mark the Subject Info Access extension as non-critical", + Citation: "RFC 5280: 4.2.2.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC3280Date, + Lint: &siaCrit{}, + }) +} + +func (l *siaCrit) Initialize() error { + return nil +} + +func (l *siaCrit) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.SubjectInfoAccessOID) +} + +func (l *siaCrit) Execute(c *x509.Certificate) *lint.LintResult { + sia := util.GetExtFromCert(c, util.SubjectInfoAccessOID) + if sia.Critical { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go new file mode 100644 index 0000000000..7268f3f014 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go @@ -0,0 +1,61 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectLocalityNameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-locality-name INTEGER ::= 128 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_locality_name_max_length", + Description: "The 'Locality Name' field of the subject MUST be less than 129 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectLocalityNameMaxLength{}, + }) +} + +func (l *subjectLocalityNameMaxLength) Initialize() error { + return nil +} + +func (l *subjectLocalityNameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectLocalityNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.Locality { + if utf8.RuneCountInString(j) > 128 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go new file mode 100644 index 0000000000..e0ad56e574 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go @@ -0,0 +1,61 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "reflect" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectDN struct{} + +/************************************************************************* + RFC 5280: 4.1.2.6 + Where it is non-empty, the subject field MUST contain an X.500 + distinguished name (DN). The DN MUST be unique for each subject + entity certified by the one CA as defined by the issuer name field. A + CA may issue more than one certificate with the same DN to the same + subject entity. +*************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_not_dn", + Description: "When not empty, the subject field MUST be a distinguished name", + Citation: "RFC 5280: 4.1.2.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectDN{}, + }) +} + +func (l *subjectDN) Initialize() error { + return nil +} + +func (l *subjectDN) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectDN) Execute(c *x509.Certificate) *lint.LintResult { + if reflect.TypeOf(c.Subject) != reflect.TypeOf(*(new(pkix.Name))) { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go new file mode 100644 index 0000000000..7a18e338d3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go @@ -0,0 +1,61 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectOrganizationNameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-organization-name INTEGER ::= 64 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_organization_name_max_length", + Description: "The 'Organization Name' field of the subject MUST be less than 65 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectOrganizationNameMaxLength{}, + }) +} + +func (l *subjectOrganizationNameMaxLength) Initialize() error { + return nil +} + +func (l *subjectOrganizationNameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectOrganizationNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.Organization { + if utf8.RuneCountInString(j) > 64 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go new file mode 100644 index 0000000000..2b7a0b6597 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go @@ -0,0 +1,61 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectOrganizationalUnitNameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-organizational-unit-name INTEGER ::= 64 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_organizational_unit_name_max_length", + Description: "The 'Organizational Unit Name' field of the subject MUST be less than 65 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectOrganizationalUnitNameMaxLength{}, + }) +} + +func (l *subjectOrganizationalUnitNameMaxLength) Initialize() error { + return nil +} + +func (l *subjectOrganizationalUnitNameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectOrganizationalUnitNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.OrganizationalUnit { + if utf8.RuneCountInString(j) > 64 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go new file mode 100644 index 0000000000..f23770dfdf --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectPostalCodeMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-postal-code-length INTEGER ::= 16 + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_postal_code_max_length", + Description: "The 'PostalCode' field of the subject MUST be less than 17 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectPostalCodeMaxLength{}, + }) +} + +func (l *subjectPostalCodeMaxLength) Initialize() error { + return nil +} + +func (l *subjectPostalCodeMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectPostalCodeMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.PostalCode { + if utf8.RuneCountInString(j) > 16 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go new file mode 100644 index 0000000000..801fa92fc2 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go @@ -0,0 +1,109 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "encoding/asn1" + "errors" + "fmt" + "regexp" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +var ( + // Per RFC 5280, Appendix B. ASN.1 Notes: + // The character string type PrintableString supports a very basic Latin + // character set: the lowercase letters 'a' through 'z', uppercase + // letters 'A' through 'Z', the digits '0' through '9', eleven special + // characters ' = ( ) + , - . / : ? and space. + printableStringRegex = regexp.MustCompile(`^[a-zA-Z0-9\=\(\)\+,\-.\/:\? ']+$`) +) + +// validatePrintableString returns an error if the provided encoded printable +// string doesn't adhere to the character set defined in RFC 5280. +func validatePrintableString(rawPS []byte) error { + if !printableStringRegex.Match(rawPS) { + return errors.New("encoded PrintableString contained illegal characters") + } + return nil +} + +type subjectPrintableStringBadAlpha struct { +} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_printable_string_badalpha", + Description: "PrintableString type's alphabet only includes a-z, A-Z, 0-9, and 11 special characters", + Citation: "RFC 5280: Appendix B. ASN.1 Notes", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectPrintableStringBadAlpha{}, + }) +} + +func (l *subjectPrintableStringBadAlpha) Initialize() error { + return nil +} + +// CheckApplies returns true for any certificate with a non-empty RawSubject. +func (l *subjectPrintableStringBadAlpha) CheckApplies(c *x509.Certificate) bool { + return len(c.RawSubject) > 0 +} + +// Execute checks the certificate's RawSubject to ensure that any +// PrintableString attribute/value pairs in the Subject match the character set +// defined for this type in RFC 5280. An lint.Error level lint.LintResult is returned if any +// of the PrintableString attributes do not match a regular expression for the +// allowed character set. +func (l *subjectPrintableStringBadAlpha) Execute(c *x509.Certificate) *lint.LintResult { + rdnSequence := util.RawRDNSequence{} + rest, err := asn1.Unmarshal(c.RawSubject, &rdnSequence) + if err != nil { + return &lint.LintResult{ + Status: lint.Fatal, + Details: "Failed to Unmarshal RawSubject into RawRDNSequence", + } + } + if len(rest) > 0 { + return &lint.LintResult{ + Status: lint.Fatal, + Details: "Trailing data after RawSubject RawRDNSequence", + } + } + + for _, attrTypeAndValueSet := range rdnSequence { + for _, attrTypeAndValue := range attrTypeAndValueSet { + // If the attribute type is a PrintableString the bytes of the attribute + // value must match the printable string alphabet. + if attrTypeAndValue.Value.Tag == asn1.TagPrintableString { + if err := validatePrintableString(attrTypeAndValue.Value.Bytes); err != nil { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("RawSubject attr oid %s %s", + attrTypeAndValue.Type, err.Error()), + } + } + } + } + } + + return &lint.LintResult{ + Status: lint.Pass, + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go new file mode 100644 index 0000000000..172aea8a3b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go @@ -0,0 +1,61 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectStateNameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-state-name INTEGER ::= 128 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_state_name_max_length", + Description: "The 'State Name' field of the subject MUST be less than 129 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectStateNameMaxLength{}, + }) +} + +func (l *subjectStateNameMaxLength) Initialize() error { + return nil +} + +func (l *subjectStateNameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectStateNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.Province { + if utf8.RuneCountInString(j) > 128 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go new file mode 100644 index 0000000000..5459853e52 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go @@ -0,0 +1,60 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectStreetAddressMaxLength struct{} + +/************************************************ +ITU-T X.520 (02/2001) UpperBounds +ub-street-address INTEGER ::= 128 + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_street_address_max_length", + Description: "The 'StreetAddress' field of the subject MUST be less than 129 characters", + Citation: "ITU-T X.520 (02/2001) UpperBounds", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectStreetAddressMaxLength{}, + }) +} + +func (l *subjectStreetAddressMaxLength) Initialize() error { + return nil +} + +func (l *subjectStreetAddressMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectStreetAddressMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.StreetAddress { + if utf8.RuneCountInString(j) > 128 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go new file mode 100644 index 0000000000..0053127da3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go @@ -0,0 +1,62 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectSurnameMaxLength struct{} + +/************************************************ +RFC 5280: A.1 + * In this Appendix, there is a list of upperbounds + for fields in a x509 Certificate. * + ub-surname-length INTEGER ::= 40 + +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_surname_max_length", + Description: "The 'Surname' field of the subject MUST be less than 41 characters", + Citation: "RFC 5280: A.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &subjectSurnameMaxLength{}, + }) +} + +func (l *subjectSurnameMaxLength) Initialize() error { + return nil +} + +func (l *subjectSurnameMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *subjectSurnameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, j := range c.Subject.Surname { + if utf8.RuneCountInString(j) > 40 { + return &lint.LintResult{Status: lint.Error} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go new file mode 100644 index 0000000000..28a8aa586a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go @@ -0,0 +1,88 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "bytes" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +type mismatchingSigAlg struct{} + +/******************************************************************* +RFC 5280: 4.1.1.2 +[the Certificate signatureAlgorithm] field MUST contain the same +algorithm identifier as the signature field in the sequence +tbsCertificate +********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cert_sig_alg_not_match_tbs_sig_alg", + Description: "Certificate signature field must match TBSCertificate signature field", + Citation: "RFC 5280, Section 4.1.1.2", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: &mismatchingSigAlg{}, + }) +} + +func (l *mismatchingSigAlg) Initialize() error { + return nil +} + +func (l *mismatchingSigAlg) CheckApplies(_ *x509.Certificate) bool { + return true +} + +func (l *mismatchingSigAlg) Execute(c *x509.Certificate) *lint.LintResult { + // parse out certificate signatureAlgorithm + input := cryptobyte.String(c.Raw) + var cert cryptobyte.String + if !input.ReadASN1(&cert, cryptobyte_asn1.SEQUENCE) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading certificate"} + } + var tbsCert cryptobyte.String + if !cert.ReadASN1(&tbsCert, cryptobyte_asn1.SEQUENCE) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading certificate.tbsCertificate"} + } + var certSigAlg cryptobyte.String + if !cert.ReadASN1(&certSigAlg, cryptobyte_asn1.SEQUENCE) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading certificate.signatureAlgorithm"} + } + + // parse out tbsCertificate signature + if !tbsCert.SkipOptionalASN1(cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate.version"} + } + if !tbsCert.SkipASN1(cryptobyte_asn1.INTEGER) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate.serialNumber"} + } + var tbsSigAlg cryptobyte.String + if !tbsCert.ReadASN1(&tbsSigAlg, cryptobyte_asn1.SEQUENCE) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate.signature"} + } + + if !bytes.Equal(certSigAlg, tbsSigAlg) { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go new file mode 100644 index 0000000000..f80bb6a6a2 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go @@ -0,0 +1,82 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +type rsaTBSSignatureEncryptionParamNotNULL struct{} + +/******************************************************************************************************* +"RFC5280: RFC 4055, Section 5" +RSA: Encoded algorithm identifier MUST have NULL parameters. +*******************************************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_tbs_signature_rsa_encryption_parameter_not_null", + Description: "RSA: Encoded signature algorithm identifier MUST have NULL parameters", + Citation: "RFC 4055, Section 5", + Source: lint.RFC5280, // RFC4055 is referenced in RFC5280, Section 1 + EffectiveDate: util.RFC5280Date, + Lint: &rsaTBSSignatureEncryptionParamNotNULL{}, + }) +} + +func (l *rsaTBSSignatureEncryptionParamNotNULL) Initialize() error { + return nil +} + +func (l *rsaTBSSignatureEncryptionParamNotNULL) CheckApplies(c *x509.Certificate) bool { + _, ok := util.RSAAlgorithmIDToDER[c.SignatureAlgorithmOID.String()] + return ok +} + +func (l *rsaTBSSignatureEncryptionParamNotNULL) Execute(c *x509.Certificate) *lint.LintResult { + input := cryptobyte.String(c.RawTBSCertificate) + + var tbsCert cryptobyte.String + if !input.ReadASN1(&tbsCert, cryptobyte_asn1.SEQUENCE) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate"} + } + + if !tbsCert.SkipOptionalASN1(cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate.version"} + } + + if !tbsCert.SkipASN1(cryptobyte_asn1.INTEGER) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate.serialNumber"} + } + + var signatureAlgoID cryptobyte.String + var tag cryptobyte_asn1.Tag + // use ReadAnyElement to preserve tag and length octets + if !tbsCert.ReadAnyASN1Element(&signatureAlgoID, &tag) { + return &lint.LintResult{Status: lint.Fatal, Details: "error reading tbsCertificate.signature"} + } + + if err := util.CheckAlgorithmIDParamNotNULL(signatureAlgoID, c.SignatureAlgorithmOID); err != nil { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("certificate tbsCertificate.signature %s", err.Error())} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go new file mode 100644 index 0000000000..851d247b9d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go @@ -0,0 +1,82 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type utcNoSecond struct{} + +/************************************************************************ +4.1.2.5.1. UTCTime +The universal time type, UTCTime, is a standard ASN.1 type intended +for representation of dates and time. UTCTime specifies the year +through the two low-order digits and time is specified to the +precision of one minute or one second. UTCTime includes either Z +(for Zulu, or Greenwich Mean Time) or a time differential. +For the purposes of this profile, UTCTime values MUST be expressed in +Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are +YYMMDDHHMMSSZ), even where the number of seconds is zero. Conforming +systems MUST interpret the year field (YY) as follows: + + Where YY is greater than or equal to 50, the year SHALL be + interpreted as 19YY; and + + Where YY is less than 50, the year SHALL be interpreted as 20YY. +************************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_utc_time_does_not_include_seconds", + Description: "UTCTime values MUST include seconds", + Citation: "RFC 5280: 4.1.2.5.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &utcNoSecond{}, + }) +} + +func (l *utcNoSecond) Initialize() error { + return nil +} + +func (l *utcNoSecond) CheckApplies(c *x509.Certificate) bool { + firstDate, secondDate := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(firstDate, secondDate) + date1Utc := beforeTag == 23 + date2Utc := afterTag == 23 + return date1Utc || date2Utc +} + +func (l *utcNoSecond) Execute(c *x509.Certificate) *lint.LintResult { + date1, date2 := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(date1, date2) + date1Utc := beforeTag == 23 + date2Utc := afterTag == 23 + if date1Utc { + if len(date1.Bytes) != 13 && len(date1.Bytes) != 17 { + return &lint.LintResult{Status: lint.Error} + } + } + if date2Utc { + if len(date2.Bytes) != 13 && len(date2.Bytes) != 17 { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go new file mode 100644 index 0000000000..648f78256f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go @@ -0,0 +1,97 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type utcTimeGMT struct{} + +/*********************************************************************** +4.1.2.5.1. UTCTime + The universal time type, UTCTime, is a standard ASN.1 type intended + for representation of dates and time. UTCTime specifies the year + through the two low-order digits and time is specified to the + precision of one minute or one second. UTCTime includes either Z + (for Zulu, or Greenwich Mean Time) or a time differential. + + For the purposes of this profile, UTCTime values MUST be expressed in + Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are + YYMMDDHHMMSSZ), even where the number of seconds is zero. Conforming + systems MUST interpret the year field (YY) as follows: + + Where YY is greater than or equal to 50, the year SHALL be + interpreted as 19YY; and + + Where YY is less than 50, the year SHALL be interpreted as 20YY. +***********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_utc_time_not_in_zulu", + Description: "UTCTime values MUST be expressed in Greenwich Mean Time (Zulu)", + Citation: "RFC 5280: 4.1.2.5.1", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &utcTimeGMT{}, + }) +} + +func (l *utcTimeGMT) Initialize() error { + return nil +} + +func (l *utcTimeGMT) CheckApplies(c *x509.Certificate) bool { + firstDate, secondDate := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(firstDate, secondDate) + date1Utc := beforeTag == 23 + date2Utc := afterTag == 23 + return date1Utc || date2Utc +} + +func (l *utcTimeGMT) Execute(c *x509.Certificate) *lint.LintResult { + var r lint.LintStatus + firstDate, secondDate := util.GetTimes(c) + beforeTag, afterTag := util.FindTimeType(firstDate, secondDate) + date1Utc := beforeTag == 23 + date2Utc := afterTag == 23 + if date1Utc { + // UTC Tests on notBefore + utcNotGmt(c.NotBefore, &r) + } + if date2Utc { + // UTC Tests on NotAfter + utcNotGmt(c.NotAfter, &r) + } + return &lint.LintResult{Status: r} +} + +func utcNotGmt(t time.Time, r *lint.LintStatus) { + // If we already ran this test and it resulted in error, don't want to discard that + // And now we use the afterBool to make sure we test the right time + if *r == lint.Error { + return + } + if t.Location() != time.UTC { + *r = lint.Error + } else { + *r = lint.Pass + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go new file mode 100644 index 0000000000..3edaaf2bbd --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go @@ -0,0 +1,86 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type generalizedPre2050 struct{} + +/********************************************************************* +CAs conforming to this profile MUST always encode certificate +validity dates through the year 2049 as UTCTime; certificate validity +dates in 2050 or later MUST be encoded as GeneralizedTime. +Conforming applications MUST be able to process validity dates that +are encoded in either UTCTime or GeneralizedTime. +*********************************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_wrong_time_format_pre2050", + Description: "Certificates valid through the year 2049 MUST be encoded in UTC time", + Citation: "RFC 5280: 4.1.2.5", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: &generalizedPre2050{}, + }) +} + +func (l *generalizedPre2050) Initialize() error { + return nil +} + +func (l *generalizedPre2050) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *generalizedPre2050) Execute(c *x509.Certificate) *lint.LintResult { + date1, date2 := util.GetTimes(c) + var t time.Time + type1, type2 := util.FindTimeType(date1, date2) + if type1 == 24 { + temp, err := asn1.Marshal(date1) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + _, err = asn1.Unmarshal(temp, &t) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if t.Before(util.GeneralizedDate) { + return &lint.LintResult{Status: lint.Error} + } + } + if type2 == 24 { + temp, err := asn1.Marshal(date2) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + _, err = asn1.Unmarshal(temp, &t) + if err != nil { + return &lint.LintResult{Status: lint.Fatal} + } + if t.Before(util.GeneralizedDate) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/makefile b/vendor/github.com/zmap/zlint/v3/makefile new file mode 100644 index 0000000000..6fb343ddb4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/makefile @@ -0,0 +1,42 @@ +SHELL := /bin/bash +# Number of linting Go routines to use in integration tests +PARALLELISM := 5 +# Additional integration test flags. Example usage: +# make integration PARALLELISM=99 INT_FLAGS="-fingerprintSummary -forceDownload" +# make integration INT_FLAGS="-overwriteExpected -config custom.config.json" +# make integration INT_FLAGS="-fingerprintSummary -lintSummary -fingerprintFilter='^[ea]' -lintFilter='^w_ext_cert_policy_explicit_text_not_utf8' -config small.config.json" +# make integration INT_FLAGS="-lintSummary -fingerprintSummary -lintFilter='^e_' -config small.config.json" +# make integration INT_FLAGS="-lintSummary -fingerprintSummary -excludeSources='Mozilla,ETSI_ESI' -config small.config.json" +# make integration INT_FLAGS="-includeSources='Mozilla,ETSI_ESI' -config small.config.json" +INT_FLAGS := + +CMDS = zlint zlint-gtld-update +CMD_PREFIX = ./cmd/ +BUILD = $(GO_ENV) go build +TEST = $(GO_ENV) GORACE=halt_on_error=1 go test -race +INT_TEST = $(GO_ENV) go test -v -tags integration -timeout 20m ./integration/... -parallelism $(PARALLELISM) $(INT_FLAGS) + +all: $(CMDS) + +zlint: + $(BUILD) $(CMD_PREFIX)$(@) + +zlint-gtld-update: + $(BUILD) $(CMD_PREFIX)$(@) + +clean: + rm -f $(CMDS) + +test: + $(TEST) ./... + +integration: + $(INT_TEST) + +code-lint: + golangci-lint run + +testdata-lint: + ./test/prepend_testcerts_openssl.sh && git diff --exit-code testdata/ + +.PHONY: clean zlint zlint-gtld-update test integration code-lint testdata-lint diff --git a/vendor/github.com/zmap/zlint/v3/newLint.sh b/vendor/github.com/zmap/zlint/v3/newLint.sh new file mode 100644 index 0000000000..9bfd13ad70 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/newLint.sh @@ -0,0 +1,50 @@ +# Script to create new lint from template + +USAGE="Usage: $0 + +ARG1: Path_name +ARG2: File_name/TestName (no 'lint_' prefix) +ARG3: Struct_name" + +if [ $# -eq 0 ]; then + echo "No arguments provided..." + echo "$USAGE" + exit 1 +fi + +if [ $# -eq 1 ]; then + echo "Not enough arguments provided..." + echo "$USAGE" + exit 1 +fi + +if [ $# -eq 2 ]; then + echo "Not enough arguments provided..." + echo "$USAGE" + exit 1 +fi + +if [ ! -d lints/$1 ] +then + echo "Directory 'lints/$1' does not exist. Can't make new file." + exit 1 +fi + + +if [ -e lints/$1/lint_$2.go ] +then + echo "File already exists. Can't make new file." + exit 1 +fi + +PATHNAME=$1 +LINTNAME=$2 +# Remove the first two characters from ${LINTNAME} and save the resulting string into FILENAME +FILENAME=${LINTNAME:2} +STRUCTNAME=$3 + +sed -e "s/PACKAGE/${PATHNAME}/" \ + -e "s/SUBST/${STRUCTNAME}/g" \ + -e "s/SUBTEST/${LINTNAME}/g" template > lints/${PATHNAME}/lint_${FILENAME}.go + +echo "Created file lints/${PATHNAME}/lint_${FILENAME}.go with struct name ${STRUCTNAME}" diff --git a/vendor/github.com/zmap/zlint/v3/resultset.go b/vendor/github.com/zmap/zlint/v3/resultset.go new file mode 100644 index 0000000000..f1e4db3c92 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/resultset.go @@ -0,0 +1,58 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package zlint + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" +) + +// ResultSet contains the output of running all lints in a registry against +// a single certificate. +type ResultSet struct { + Version int64 `json:"version"` + Timestamp int64 `json:"timestamp"` + Results map[string]*lint.LintResult `json:"lints"` + NoticesPresent bool `json:"notices_present"` + WarningsPresent bool `json:"warnings_present"` + ErrorsPresent bool `json:"errors_present"` + FatalsPresent bool `json:"fatals_present"` +} + +// Execute lints the given certificate with all of the lints in the provided +// registry. The ResultSet is mutated to trace the lint results obtained from +// linting the certificate. +func (z *ResultSet) execute(cert *x509.Certificate, registry lint.Registry) { + z.Results = make(map[string]*lint.LintResult, len(registry.Names())) + // Run each lints from the registry. + for _, name := range registry.Names() { + res := registry.ByName(name).Execute(cert) + z.Results[name] = res + z.updateErrorStatePresent(res) + } +} + +func (z *ResultSet) updateErrorStatePresent(result *lint.LintResult) { + switch result.Status { + case lint.Notice: + z.NoticesPresent = true + case lint.Warn: + z.WarningsPresent = true + case lint.Error: + z.ErrorsPresent = true + case lint.Fatal: + z.FatalsPresent = true + } +} diff --git a/vendor/github.com/zmap/zlint/v3/template b/vendor/github.com/zmap/zlint/v3/template new file mode 100644 index 0000000000..77311118c9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/template @@ -0,0 +1,45 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package PACKAGE + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v2/lint" +) + +type SUBST struct{} + +func (l *SUBST) Initialize() error { + return nil +} + +func (l *SUBST) CheckApplies(c *x509.Certificate) bool { + // Add conditions for application here +} + +func (l *SUBST) Execute(c *x509.Certificate) *lint.LintResult { + // Add actual lint here +} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "SUBTEST", + Description: "Fill this in...", + Citation: "Fill this in...", + Source: UnknownLintSource, + EffectiveDate: "Change this...", + Lint: &SUBST{}, + }) +} diff --git a/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go b/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go new file mode 100644 index 0000000000..07df3a4e9d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go @@ -0,0 +1,190 @@ +package util + +import ( + "bytes" + "encoding/asn1" + "errors" + "fmt" + + "github.com/zmap/zcrypto/x509" + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +// additional OIDs not provided by the x509 package. +var ( + // 1.2.840.10045.4.3.1 is SHA224withECDSA + OidSignatureSHA224withECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 1} +) + +// RSAAlgorithmIDToDER contains DER representations of pkix.AlgorithmIdentifier for different RSA OIDs with Parameters as asn1.NULL. +var RSAAlgorithmIDToDER = map[string][]byte{ + // rsaEncryption + "1.2.840.113549.1.1.1": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x1, 0x5, 0x0}, + // md2WithRSAEncryption + "1.2.840.113549.1.1.2": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x2, 0x5, 0x0}, + // md5WithRSAEncryption + "1.2.840.113549.1.1.4": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x4, 0x5, 0x0}, + // sha-1WithRSAEncryption + "1.2.840.113549.1.1.5": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5, 0x5, 0x0}, + // sha224WithRSAEncryption + "1.2.840.113549.1.1.14": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xe, 0x5, 0x0}, + // sha256WithRSAEncryption + "1.2.840.113549.1.1.11": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 0x5, 0x0}, + // sha384WithRSAEncryption + "1.2.840.113549.1.1.12": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xc, 0x5, 0x0}, + // sha512WithRSAEncryption + "1.2.840.113549.1.1.13": {0x30, 0x0d, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xd, 0x5, 0x0}, +} + +// CheckAlgorithmIDParamNotNULL parses an AlgorithmIdentifier with algorithm OID rsaEncryption to check the Param field is asn1.NULL +// Expects DER-encoded AlgorithmIdentifier including tag and length. +func CheckAlgorithmIDParamNotNULL(algorithmIdentifier []byte, requiredAlgoID asn1.ObjectIdentifier) error { + expectedAlgoIDBytes, ok := RSAAlgorithmIDToDER[requiredAlgoID.String()] + if !ok { + return errors.New("error algorithmID to check is not RSA") + } + + algorithmSequence := cryptobyte.String(algorithmIdentifier) + + // byte comparison of algorithm sequence and checking no trailing data is present + var algorithmBytes []byte + if algorithmSequence.ReadBytes(&algorithmBytes, len(expectedAlgoIDBytes)) { + if bytes.Equal(algorithmBytes, expectedAlgoIDBytes) && algorithmSequence.Empty() { + return nil + } + } + + // re-parse to get an error message detailing what did not match in the byte comparison + algorithmSequence = cryptobyte.String(algorithmIdentifier) + var algorithm cryptobyte.String + if !algorithmSequence.ReadASN1(&algorithm, cryptobyte_asn1.SEQUENCE) { + return errors.New("error reading algorithm") + } + + encryptionOID := asn1.ObjectIdentifier{} + if !algorithm.ReadASN1ObjectIdentifier(&encryptionOID) { + return errors.New("error reading algorithm OID") + } + + if !encryptionOID.Equal(requiredAlgoID) { + return fmt.Errorf("algorithm OID is not equal to %s", requiredAlgoID.String()) + } + + if algorithm.Empty() { + return errors.New("RSA algorithm identifier missing required NULL parameter") + } + + var nullValue cryptobyte.String + if !algorithm.ReadASN1(&nullValue, cryptobyte_asn1.NULL) { + return errors.New("RSA algorithm identifier with non-NULL parameter") + } + + if len(nullValue) != 0 { + return errors.New("RSA algorithm identifier with NULL parameter containing data") + } + + // ensure algorithm is empty and no trailing data is present + if !algorithm.Empty() { + return errors.New("RSA algorithm identifier with trailing data") + } + + return errors.New("RSA algorithm appears correct, but didn't match byte-wise comparison") +} + +// Returns the signature field of the tbsCertificate of this certificate in a DER encoded form or an error +// if the signature field could not be extracted. The encoded form contains the tag and the length. +// +// TBSCertificate ::= SEQUENCE { +// version [0] EXPLICIT Version DEFAULT v1, +// serialNumber CertificateSerialNumber, +// signature AlgorithmIdentifier, +// issuer Name, +// validity Validity, +// subject Name, +// subjectPublicKeyInfo SubjectPublicKeyInfo, +// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, +// -- If present, version MUST be v2 or v3 +// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, +// -- If present, version MUST be v2 or v3 +// extensions [3] EXPLICIT Extensions OPTIONAL +// -- If present, version MUST be v3 +// } +func GetSignatureAlgorithmInTBSEncoded(c *x509.Certificate) ([]byte, error) { + input := cryptobyte.String(c.RawTBSCertificate) + + var tbsCert cryptobyte.String + if !input.ReadASN1(&tbsCert, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("error reading tbsCertificate") + } + + if !tbsCert.SkipOptionalASN1(cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return nil, errors.New("error reading tbsCertificate.version") + } + + if !tbsCert.SkipASN1(cryptobyte_asn1.INTEGER) { + return nil, errors.New("error reading tbsCertificate.serialNumber") + } + + var signatureAlgoID cryptobyte.String + var tag cryptobyte_asn1.Tag + // use ReadAnyElement to preserve tag and length octets + if !tbsCert.ReadAnyASN1Element(&signatureAlgoID, &tag) { + return nil, errors.New("error reading tbsCertificate.signature") + } + + return signatureAlgoID, nil +} + +// Returns the algorithm field of the SubjectPublicKeyInfo of the certificate or an error +// if the algorithm field could not be extracted. +// +// SubjectPublicKeyInfo ::= SEQUENCE { +// algorithm AlgorithmIdentifier, +// subjectPublicKey BIT STRING } +// +func GetPublicKeyOID(c *x509.Certificate) (asn1.ObjectIdentifier, error) { + input := cryptobyte.String(c.RawSubjectPublicKeyInfo) + + var publicKeyInfo cryptobyte.String + if !input.ReadASN1(&publicKeyInfo, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("error reading pkixPublicKey") + } + + var algorithm cryptobyte.String + if !publicKeyInfo.ReadASN1(&algorithm, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("error reading public key algorithm identifier") + } + + publicKeyOID := asn1.ObjectIdentifier{} + if !algorithm.ReadASN1ObjectIdentifier(&publicKeyOID) { + return nil, errors.New("error reading public key OID") + } + + return publicKeyOID, nil +} + +// Returns the algorithm field of the SubjectPublicKeyInfo of the certificate in its encoded form (containing Tag +// and Length) or an error if the algorithm field could not be extracted. +// +// SubjectPublicKeyInfo ::= SEQUENCE { +// algorithm AlgorithmIdentifier, +// subjectPublicKey BIT STRING } +// +func GetPublicKeyAidEncoded(c *x509.Certificate) ([]byte, error) { + input := cryptobyte.String(c.RawSubjectPublicKeyInfo) + var spkiContent cryptobyte.String + + if !input.ReadASN1(&spkiContent, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("error reading pkixPublicKey") + } + + var algorithm cryptobyte.String + var tag cryptobyte_asn1.Tag + + if !spkiContent.ReadAnyASN1Element(&algorithm, &tag) { + return nil, errors.New("error reading public key algorithm identifier") + } + + return algorithm, nil +} diff --git a/vendor/github.com/zmap/zlint/v3/util/ca.go b/vendor/github.com/zmap/zlint/v3/util/ca.go new file mode 100644 index 0000000000..43e2755b0b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/ca.go @@ -0,0 +1,64 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "github.com/zmap/zcrypto/x509" +) + +// IsCACert returns true if c has IsCA set. +func IsCACert(c *x509.Certificate) bool { + return c.IsCA +} + +// IsRootCA returns true if c has IsCA set and is also self-signed. +func IsRootCA(c *x509.Certificate) bool { + return IsCACert(c) && IsSelfSigned(c) +} + +// IsSubCA returns true if c has IsCA set, but is not self-signed. +func IsSubCA(c *x509.Certificate) bool { + return IsCACert(c) && !IsSelfSigned(c) +} + +// IsSelfSigned returns true if SelfSigned is set. +func IsSelfSigned(c *x509.Certificate) bool { + return c.SelfSigned +} + +// IsSubscriberCert returns true for if a certificate is not a CA and not +// self-signed. +func IsSubscriberCert(c *x509.Certificate) bool { + return !IsCACert(c) && !IsSelfSigned(c) +} + +// IsDelegatedOCSPResponderCert returns true if the id-kp-OCSPSigning EKU is set +// According https://tools.ietf.org/html/rfc6960#section-4.2.2.2 it is not sufficient +// to have only the id-kp-anyExtendedKeyUsage included +func IsDelegatedOCSPResponderCert(cert *x509.Certificate) bool { + return HasEKU(cert, x509.ExtKeyUsageOcspSigning) +} + +func IsServerAuthCert(cert *x509.Certificate) bool { + if len(cert.ExtKeyUsage) == 0 { + return true + } + for _, eku := range cert.ExtKeyUsage { + if eku == x509.ExtKeyUsageAny || eku == x509.ExtKeyUsageServerAuth { + return true + } + } + return false +} diff --git a/vendor/github.com/zmap/zlint/v3/util/countries.go b/vendor/github.com/zmap/zlint/v3/util/countries.go new file mode 100644 index 0000000000..66dfa72428 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/countries.go @@ -0,0 +1,51 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import "strings" + +var countries = map[string]bool{ + "AD": true, "AE": true, "AF": true, "AG": true, "AI": true, "AL": true, "AM": true, "AN": true, "AO": true, "AQ": true, "AR": true, + "AS": true, "AT": true, "AU": true, "AW": true, "AX": true, "AZ": true, "BA": true, "BB": true, "BD": true, "BE": true, "BF": true, "BG": true, + "BH": true, "BI": true, "BJ": true, "BL": true, "BM": true, "BN": true, "BO": true, "BQ": true, "BR": true, "BS": true, "BT": true, "BV": true, + "BW": true, "BY": true, "BZ": true, "CA": true, "CC": true, "CD": true, "CF": true, "CG": true, "CH": true, "CI": true, "CK": true, "CL": true, + "CM": true, "CN": true, "CO": true, "CR": true, "CU": true, "CV": true, "CW": true, "CX": true, "CY": true, "CZ": true, "DE": true, "DJ": true, + "DK": true, "DM": true, "DO": true, "DZ": true, "EC": true, "EE": true, "EG": true, "EH": true, "ER": true, "ES": true, "ET": true, "FI": true, + "FJ": true, "FK": true, "FM": true, "FO": true, "FR": true, "GA": true, "GB": true, "GD": true, "GE": true, "GF": true, "GG": true, "GH": true, + "GI": true, "GL": true, "GM": true, "GN": true, "GP": true, "GQ": true, "GR": true, "GS": true, "GT": true, "GU": true, "GW": true, "GY": true, + "HK": true, "HM": true, "HN": true, "HR": true, "HT": true, "HU": true, "ID": true, "IE": true, "IL": true, "IM": true, "IN": true, "IO": true, + "IQ": true, "IR": true, "IS": true, "IT": true, "JE": true, "JM": true, "JO": true, "JP": true, "KE": true, "KG": true, "KH": true, "KI": true, + "KM": true, "KN": true, "KP": true, "KR": true, "KW": true, "KY": true, "KZ": true, "LA": true, "LB": true, "LC": true, "LI": true, "LK": true, + "LR": true, "LS": true, "LT": true, "LU": true, "LV": true, "LY": true, "MA": true, "MC": true, "MD": true, "ME": true, "MF": true, "MG": true, + "MH": true, "MK": true, "ML": true, "MM": true, "MN": true, "MO": true, "MP": true, "MQ": true, "MR": true, "MS": true, "MT": true, "MU": true, + "MV": true, "MW": true, "MX": true, "MY": true, "MZ": true, "NA": true, "NC": true, "NE": true, "NF": true, "NG": true, "NI": true, "NL": true, + "NO": true, "NP": true, "NR": true, "NU": true, "NZ": true, "OM": true, "PA": true, "PE": true, "PF": true, "PG": true, "PH": true, "PK": true, + "PL": true, "PM": true, "PN": true, "PR": true, "PS": true, "PT": true, "PW": true, "PY": true, "QA": true, "RE": true, "RO": true, "RS": true, + "RU": true, "RW": true, "SA": true, "SB": true, "SC": true, "SD": true, "SE": true, "SG": true, "SH": true, "SI": true, "SJ": true, "SK": true, + "SL": true, "SM": true, "SN": true, "SO": true, "SR": true, "SS": true, "ST": true, "SV": true, "SX": true, "SY": true, "SZ": true, "TC": true, + "TD": true, "TF": true, "TG": true, "TH": true, "TJ": true, "TK": true, "TL": true, "TM": true, "TN": true, "TO": true, "TR": true, "TT": true, + "TV": true, "TW": true, "TZ": true, "UA": true, "UG": true, "UM": true, "US": true, "UY": true, "UZ": true, "VA": true, "VC": true, "VE": true, + "VG": true, "VI": true, "VN": true, "VU": true, "WF": true, "WS": true, "YE": true, "YT": true, "ZA": true, "ZM": true, "ZW": true, "XX": true, +} + +// IsISOCountryCode returns true if the input is a known two-letter country +// code. +// +// TODO: Document where the list of known countries came from. +func IsISOCountryCode(in string) bool { + in = strings.ToUpper(in) + _, ok := countries[in] + return ok +} diff --git a/vendor/github.com/zmap/zlint/v3/util/eku.go b/vendor/github.com/zmap/zlint/v3/util/eku.go new file mode 100644 index 0000000000..9b2b53695f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/eku.go @@ -0,0 +1,14 @@ +package util + +import "github.com/zmap/zcrypto/x509" + +// HasEKU tests whether an Extended Key Usage (EKU) is present in a certificate. +func HasEKU(cert *x509.Certificate, eku x509.ExtKeyUsage) bool { + for _, currentEku := range cert.ExtKeyUsage { + if currentEku == eku { + return true + } + } + + return false +} diff --git a/vendor/github.com/zmap/zlint/v3/util/encodings.go b/vendor/github.com/zmap/zlint/v3/util/encodings.go new file mode 100644 index 0000000000..fc28c350f5 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/encodings.go @@ -0,0 +1,136 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "bytes" + "encoding/asn1" + "errors" + "regexp" + "strings" + "unicode" + "unicode/utf16" + + "github.com/zmap/zcrypto/x509/pkix" +) + +// CheckRDNSequenceWhiteSpace returns true if there is leading or trailing +// whitespace in any name attribute in the sequence, respectively. +func CheckRDNSequenceWhiteSpace(raw []byte) (leading, trailing bool, err error) { + var seq pkix.RDNSequence + if _, err = asn1.Unmarshal(raw, &seq); err != nil { + return + } + for _, rdn := range seq { + for _, atv := range rdn { + if !IsNameAttribute(atv.Type) { + continue + } + value, ok := atv.Value.(string) + if !ok { + continue + } + if leftStrip := strings.TrimLeftFunc(value, unicode.IsSpace); leftStrip != value { + leading = true + } + if rightStrip := strings.TrimRightFunc(value, unicode.IsSpace); rightStrip != value { + trailing = true + } + } + } + return +} + +// IsIA5String returns true if raw is an IA5String, and returns false otherwise. +func IsIA5String(raw []byte) bool { + for _, b := range raw { + i := int(b) + if i > 127 || i < 0 { + return false + } + } + return true +} + +func IsInPrefSyn(name string) bool { + // If the DNS name is just a space, it is valid + if name == " " { + return true + } + // This is the expression that matches the ABNF syntax from RFC 1034: Sec 3.5, specifically for subdomain since the " " case for domain is covered above + prefsyn := regexp.MustCompile(`^([[:alpha:]]{1}(([[:alnum:]]|[-])*[[:alnum:]]{1})*){1}([.][[:alpha:]]{1}(([[:alnum:]]|[-])*[[:alnum:]]{1})*)*$`) + return prefsyn.MatchString(name) +} + +// AllAlternateNameWithTagAreIA5 returns true if all sequence members with the +// given tag are encoded as IA5 strings, and false otherwise. If it encounters +// errors parsing asn1, err will be non-nil. +func AllAlternateNameWithTagAreIA5(ext *pkix.Extension, tag int) (bool, error) { + var seq asn1.RawValue + var err error + // Unmarshal the extension as a sequence + if _, err = asn1.Unmarshal(ext.Value, &seq); err != nil { + return false, err + } + // Ensure the sequence matches what we expect for SAN/IAN + if !seq.IsCompound || seq.Tag != asn1.TagSequence || seq.Class != asn1.ClassUniversal { + err = asn1.StructuralError{Msg: "bad alternate name sequence"} + return false, err + } + + // Iterate over the sequence and look for items tagged with tag + rest := seq.Bytes + for len(rest) > 0 { + var v asn1.RawValue + rest, err = asn1.Unmarshal(rest, &v) + if err != nil { + return false, err + } + if v.Tag == tag { + if !IsIA5String(v.Bytes) { + return false, nil + } + } + } + + return true, nil +} + +// IsEmptyASN1Sequence returns true if +// *input is an empty sequence (0x30, 0x00) or +// *len(inout) < 2 +// This check covers more cases than just empty sequence checks but it makes sense from the usage perspective +var emptyASN1Sequence = []byte{0x30, 0x00} + +func IsEmptyASN1Sequence(input []byte) bool { + return len(input) < 2 || bytes.Equal(input, emptyASN1Sequence) +} + +// ParseBMPString returns a uint16 encoded string following the specification for a BMPString type +func ParseBMPString(bmpString []byte) (string, error) { + if len(bmpString)%2 != 0 { + return "", errors.New("odd-length BMP string") + } + // strip terminator if present + if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { + bmpString = bmpString[:l-2] + } + s := make([]uint16, 0, len(bmpString)/2) + for len(bmpString) > 0 { + s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) + bmpString = bmpString[2:] + } + return string(utf16.Decode(s)), nil +} diff --git a/vendor/github.com/zmap/zlint/v3/util/ev.go b/vendor/github.com/zmap/zlint/v3/util/ev.go new file mode 100644 index 0000000000..68ef5df3a1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/ev.go @@ -0,0 +1,73 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "encoding/asn1" +) + +var evoids = map[string]bool{ + "1.3.159.1.17.1": true, + "1.3.6.1.4.1.34697.2.1": true, + "1.3.6.1.4.1.34697.2.2": true, + "1.3.6.1.4.1.34697.2.3": true, + "1.3.6.1.4.1.34697.2.4": true, + "1.2.40.0.17.1.22": true, + "2.16.578.1.26.1.3.3": true, + "1.3.6.1.4.1.17326.10.14.2.1.2": true, + "1.3.6.1.4.1.17326.10.8.2.1.2": true, + "1.3.6.1.4.1.6449.1.2.1.5.1": true, + "2.16.840.1.114412.2.1": true, + "2.16.840.1.114412.1.3.0.2": true, + "2.16.528.1.1001.1.1.1.12.6.1.1.1": true, + "2.16.792.3.0.4.1.1.4": true, + "2.16.840.1.114028.10.1.2": true, + "0.4.0.2042.1.4": true, + "0.4.0.2042.1.5": true, + "1.3.6.1.4.1.13177.10.1.3.10": true, + "1.3.6.1.4.1.14370.1.6": true, + "1.3.6.1.4.1.4146.1.1": true, + "2.16.840.1.114413.1.7.23.3": true, + "1.3.6.1.4.1.14777.6.1.1": true, + "2.16.792.1.2.1.1.5.7.1.9": true, + "1.3.6.1.4.1.782.1.2.1.8.1": true, + "1.3.6.1.4.1.22234.2.5.2.3.1": true, + "1.3.6.1.4.1.8024.0.2.100.1.2": true, + "1.2.392.200091.100.721.1": true, + "2.16.840.1.114414.1.7.23.3": true, + "1.3.6.1.4.1.23223.2": true, + "1.3.6.1.4.1.23223.1.1.1": true, + "2.16.756.1.83.21.0": true, + "2.16.756.1.89.1.2.1.1": true, + "1.3.6.1.4.1.7879.13.24.1": true, + "2.16.840.1.113733.1.7.48.1": true, + "2.16.840.1.114404.1.1.2.4.1": true, + "2.16.840.1.113733.1.7.23.6": true, + "1.3.6.1.4.1.6334.1.100.1": true, + "2.16.840.1.114171.500.9": true, + "1.3.6.1.4.1.36305.2": true, +} + +// IsEV returns true if the input is a known Extended Validation OID. +func IsEV(in []asn1.ObjectIdentifier) bool { + for _, oid := range in { + if _, ok := evoids[oid.String()]; ok { + return true + } + } + return false +} + +const OnionTLD = ".onion" diff --git a/vendor/github.com/zmap/zlint/v3/util/fqdn.go b/vendor/github.com/zmap/zlint/v3/util/fqdn.go new file mode 100644 index 0000000000..7051049125 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/fqdn.go @@ -0,0 +1,119 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "net" + "net/url" + "strings" + + zcutil "github.com/zmap/zcrypto/util" + "github.com/zmap/zcrypto/x509" +) + +func RemovePrependedQuestionMarks(domain string) string { + for strings.HasPrefix(domain, "?.") { + domain = domain[2:] + } + return domain +} + +func RemovePrependedWildcard(domain string) string { + return strings.TrimPrefix(domain, "*.") +} + +func IsFQDN(domain string) bool { + domain = RemovePrependedWildcard(domain) + domain = RemovePrependedQuestionMarks(domain) + return zcutil.IsURL(domain) +} + +func GetAuthority(uri string) string { + parsed, err := url.Parse(uri) + if err != nil { + return "" + } + if parsed.Opaque != "" { + // non-empty Opaque means that there is no authority + return "" + } + if len(uri) < 4 { + return "" + } + // https://tools.ietf.org/html/rfc3986#section-3 + // The only time an authority is present is if there is a // after the scheme. + firstColon := strings.Index(uri, ":") + postScheme := uri[firstColon+1:] + // After the scheme, there is the hier-part, optionally followed by a query or fragment. + if !strings.HasPrefix(postScheme, "//") { + // authority is always prefixed by // + return "" + } + for i := 2; i < len(postScheme); i++ { + // in the hier-part, the authority is followed by either an absolute path, or the empty string. + // So, the authority is terminated by the start of an absolute path (/), the start of a fragment (#) or the start of a query(?) + if postScheme[i] == '/' || postScheme[i] == '#' || postScheme[i] == '?' { + return postScheme[2:i] + } + } + // Found no absolute path, fragment or query -- so the authority is the only data after the scheme:// + return postScheme[2:] +} + +func GetHost(auth string) string { + begin := strings.Index(auth, "@") + if begin == len(auth)-1 { + begin = -1 + } + end := strings.Index(auth, ":") + if end == -1 { + end = len(auth) + } + if end < begin { + return "" + } + return auth[begin+1 : end] +} + +func AuthIsFQDNOrIP(auth string) bool { + return IsFQDNOrIP(GetHost(auth)) +} + +func IsFQDNOrIP(host string) bool { + if IsFQDN(host) { + return true + } + if net.ParseIP(host) != nil { + return true + } + return false +} + +func DNSNamesExist(cert *x509.Certificate) bool { + if cert.Subject.CommonName == "" && len(cert.DNSNames) == 0 { + return false + } else { + return true + } +} + +func CommonNameIsIP(cert *x509.Certificate) bool { + ip := net.ParseIP(cert.Subject.CommonName) + if ip == nil { + return false + } else { + return true + } +} diff --git a/vendor/github.com/zmap/zlint/v3/util/gtld.go b/vendor/github.com/zmap/zlint/v3/util/gtld.go new file mode 100644 index 0000000000..3bc325ce8c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/gtld.go @@ -0,0 +1,120 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "fmt" + "strings" + "time" + + "github.com/zmap/zcrypto/x509" +) + +// This package uses the `zlint-gtld-update` command to generate a `tldMap` map. +//go:generate zlint-gtld-update ./gtld_map.go + +const ( + GTLDPeriodDateFormat = "2006-01-02" +) + +// GTLDPeriod is a struct representing a gTLD's validity period. The field names +// are chosen to match the data returned by the ICANN gTLD v2 JSON registry[0]. +// See the `zlint-gtld-update` command for more information. +// [0] - https://www.icann.org/resources/registries/gtlds/v2/gtlds.json +type GTLDPeriod struct { + // GTLD is the GTLD the period corresponds to. It is used only for friendly + // error messages from `Valid` + GTLD string + // DelegationDate is the date at which ICANN delegated the gTLD into existence + // from the root DNS, or is empty if the gTLD was never delegated. + DelegationDate string + // RemovalDate is the date at which ICANN removed the gTLD delegation from the + // root DNS, or is empty if the gTLD is still delegated and has not been + // removed. + RemovalDate string +} + +// Valid determines if the provided `when` time is within the GTLDPeriod for the +// gTLD. E.g. whether a certificate issued at `when` with a subject identifier +// using the specified gTLD can be considered a valid use of the gTLD. +func (p GTLDPeriod) Valid(when time.Time) error { + // NOTE: We can throw away the errors from time.Parse in this function because + // the zlint-gtld-update command only writes entries to the generated gTLD map + // after the dates have been verified as parseable + notBefore, _ := time.Parse(GTLDPeriodDateFormat, p.DelegationDate) + if when.Before(notBefore) { + return fmt.Errorf(`gTLD ".%s" is not valid until %s`, + p.GTLD, p.DelegationDate) + } + // The removal date may be empty. We only need to check `when` against the + // removal when it isn't empty + if p.RemovalDate != "" { + notAfter, _ := time.Parse(GTLDPeriodDateFormat, p.RemovalDate) + if when.After(notAfter) { + return fmt.Errorf(`gTLD ".%s" is not valid after %s`, + p.GTLD, p.RemovalDate) + } + } + return nil +} + +// HasValidTLD checks that a domain ends in a valid TLD that was delegated in +// the root DNS at the time specified. +func HasValidTLD(domain string, when time.Time) bool { + labels := strings.Split(strings.ToLower(domain), ".") + rightLabel := labels[len(labels)-1] + // if the rightmost label is not present in the tldMap, it isn't valid and + // never was. + if tldPeriod, present := tldMap[rightLabel]; !present { + return false + } else if tldPeriod.Valid(when) != nil { + // If the TLD exists but the date is outside of the gTLD's validity period + // then it is not a valid TLD. + return false + } + // Otherwise the TLD exists, and was a valid TLD delegated in the root DNS + // at the time of the given date. + return true +} + +// IsInTLDMap checks that a label is present in the TLD map. It does not +// consider the TLD's validity period and whether the TLD may have been removed, +// only whether it was ever a TLD that was delegated. +func IsInTLDMap(label string) bool { + label = strings.ToLower(label) + if _, ok := tldMap[label]; ok { + return true + } else { + return false + } +} + +// CertificateSubjContainsTLD checks whether the provided Certificate has +// a Subject Common Name or DNS Subject Alternate Name that ends in the provided +// TLD label. If IsInTLDMap(label) returns false then CertificateSubjInTLD will +// return false. +func CertificateSubjInTLD(c *x509.Certificate, label string) bool { + label = strings.ToLower(label) + label = strings.TrimPrefix(label, ".") + if !IsInTLDMap(label) { + return false + } + for _, name := range append(c.DNSNames, c.Subject.CommonName) { + if strings.HasSuffix(name, "."+label) { + return true + } + } + return false +} diff --git a/vendor/github.com/zmap/zlint/v3/util/gtld_map.go b/vendor/github.com/zmap/zlint/v3/util/gtld_map.go new file mode 100644 index 0000000000..7137627d4b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/gtld_map.go @@ -0,0 +1,7880 @@ +// Code generated by go generate; DO NOT EDIT. +// This file was generated by zlint-gtld-update. + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +var tldMap = map[string]GTLDPeriod{ + "aaa": { + GTLD: "aaa", + DelegationDate: "2015-08-28", + RemovalDate: "", + }, + "aarp": { + GTLD: "aarp", + DelegationDate: "2015-11-03", + RemovalDate: "", + }, + "abarth": { + GTLD: "abarth", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "abb": { + GTLD: "abb", + DelegationDate: "2015-04-25", + RemovalDate: "", + }, + "abbott": { + GTLD: "abbott", + DelegationDate: "2015-03-07", + RemovalDate: "", + }, + "abbvie": { + GTLD: "abbvie", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "abc": { + GTLD: "abc", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "able": { + GTLD: "able", + DelegationDate: "2016-06-21", + RemovalDate: "", + }, + "abogado": { + GTLD: "abogado", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "abudhabi": { + GTLD: "abudhabi", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "ac": { + GTLD: "ac", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "academy": { + GTLD: "academy", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "accenture": { + GTLD: "accenture", + DelegationDate: "2015-05-09", + RemovalDate: "", + }, + "accountant": { + GTLD: "accountant", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "accountants": { + GTLD: "accountants", + DelegationDate: "2014-05-07", + RemovalDate: "", + }, + "aco": { + GTLD: "aco", + DelegationDate: "2015-08-27", + RemovalDate: "", + }, + "active": { + GTLD: "active", + DelegationDate: "2014-06-26", + RemovalDate: "2019-02-17", + }, + "actor": { + GTLD: "actor", + DelegationDate: "2014-02-26", + RemovalDate: "", + }, + "ad": { + GTLD: "ad", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "adac": { + GTLD: "adac", + DelegationDate: "2016-01-26", + RemovalDate: "", + }, + "ads": { + GTLD: "ads", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "adult": { + GTLD: "adult", + DelegationDate: "2014-12-06", + RemovalDate: "", + }, + "ae": { + GTLD: "ae", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "aeg": { + GTLD: "aeg", + DelegationDate: "2015-06-20", + RemovalDate: "", + }, + "aero": { + GTLD: "aero", + DelegationDate: "2002-03-02", + RemovalDate: "", + }, + "aetna": { + GTLD: "aetna", + DelegationDate: "2016-05-20", + RemovalDate: "", + }, + "af": { + GTLD: "af", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "afamilycompany": { + GTLD: "afamilycompany", + DelegationDate: "2016-07-31", + RemovalDate: "", + }, + "afl": { + GTLD: "afl", + DelegationDate: "2015-03-28", + RemovalDate: "", + }, + "africa": { + GTLD: "africa", + DelegationDate: "2017-02-15", + RemovalDate: "", + }, + "ag": { + GTLD: "ag", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "agakhan": { + GTLD: "agakhan", + DelegationDate: "2016-04-16", + RemovalDate: "", + }, + "agency": { + GTLD: "agency", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "ai": { + GTLD: "ai", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "aig": { + GTLD: "aig", + DelegationDate: "2015-05-02", + RemovalDate: "", + }, + "aigo": { + GTLD: "aigo", + DelegationDate: "2016-08-16", + RemovalDate: "2020-06-26", + }, + "airbus": { + GTLD: "airbus", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "airforce": { + GTLD: "airforce", + DelegationDate: "2014-04-30", + RemovalDate: "", + }, + "airtel": { + GTLD: "airtel", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "akdn": { + GTLD: "akdn", + DelegationDate: "2016-04-16", + RemovalDate: "", + }, + "al": { + GTLD: "al", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "alfaromeo": { + GTLD: "alfaromeo", + DelegationDate: "2016-08-02", + RemovalDate: "", + }, + "alibaba": { + GTLD: "alibaba", + DelegationDate: "2016-01-16", + RemovalDate: "", + }, + "alipay": { + GTLD: "alipay", + DelegationDate: "2016-01-16", + RemovalDate: "", + }, + "allfinanz": { + GTLD: "allfinanz", + DelegationDate: "2014-10-01", + RemovalDate: "", + }, + "allstate": { + GTLD: "allstate", + DelegationDate: "2016-07-14", + RemovalDate: "", + }, + "ally": { + GTLD: "ally", + DelegationDate: "2016-03-24", + RemovalDate: "", + }, + "alsace": { + GTLD: "alsace", + DelegationDate: "2014-10-04", + RemovalDate: "", + }, + "alstom": { + GTLD: "alstom", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "am": { + GTLD: "am", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "amazon": { + GTLD: "amazon", + DelegationDate: "2020-06-02", + RemovalDate: "", + }, + "americanexpress": { + GTLD: "americanexpress", + DelegationDate: "2016-08-08", + RemovalDate: "", + }, + "americanfamily": { + GTLD: "americanfamily", + DelegationDate: "2016-07-26", + RemovalDate: "", + }, + "amex": { + GTLD: "amex", + DelegationDate: "2016-08-08", + RemovalDate: "", + }, + "amfam": { + GTLD: "amfam", + DelegationDate: "2016-07-23", + RemovalDate: "", + }, + "amica": { + GTLD: "amica", + DelegationDate: "2015-08-29", + RemovalDate: "", + }, + "amsterdam": { + GTLD: "amsterdam", + DelegationDate: "2014-12-25", + RemovalDate: "", + }, + "analytics": { + GTLD: "analytics", + DelegationDate: "2015-12-21", + RemovalDate: "", + }, + "android": { + GTLD: "android", + DelegationDate: "2014-11-12", + RemovalDate: "", + }, + "anquan": { + GTLD: "anquan", + DelegationDate: "2016-03-30", + RemovalDate: "", + }, + "anz": { + GTLD: "anz", + DelegationDate: "2016-06-21", + RemovalDate: "", + }, + "ao": { + GTLD: "ao", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "aol": { + GTLD: "aol", + DelegationDate: "2016-11-04", + RemovalDate: "", + }, + "apartments": { + GTLD: "apartments", + DelegationDate: "2015-02-10", + RemovalDate: "", + }, + "app": { + GTLD: "app", + DelegationDate: "2015-07-02", + RemovalDate: "", + }, + "apple": { + GTLD: "apple", + DelegationDate: "2015-11-03", + RemovalDate: "", + }, + "aq": { + GTLD: "aq", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "aquarelle": { + GTLD: "aquarelle", + DelegationDate: "2014-12-02", + RemovalDate: "", + }, + "ar": { + GTLD: "ar", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "arab": { + GTLD: "arab", + DelegationDate: "2017-05-23", + RemovalDate: "", + }, + "aramco": { + GTLD: "aramco", + DelegationDate: "2015-10-15", + RemovalDate: "", + }, + "archi": { + GTLD: "archi", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "army": { + GTLD: "army", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "arpa": { + GTLD: "arpa", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "art": { + GTLD: "art", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "arte": { + GTLD: "arte", + DelegationDate: "2015-10-20", + RemovalDate: "", + }, + "as": { + GTLD: "as", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "asda": { + GTLD: "asda", + DelegationDate: "2016-08-14", + RemovalDate: "", + }, + "asia": { + GTLD: "asia", + DelegationDate: "2007-05-02", + RemovalDate: "", + }, + "associates": { + GTLD: "associates", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "at": { + GTLD: "at", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "athleta": { + GTLD: "athleta", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "attorney": { + GTLD: "attorney", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "au": { + GTLD: "au", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "auction": { + GTLD: "auction", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "audi": { + GTLD: "audi", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "audible": { + GTLD: "audible", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "audio": { + GTLD: "audio", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "auspost": { + GTLD: "auspost", + DelegationDate: "2016-08-17", + RemovalDate: "", + }, + "author": { + GTLD: "author", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "auto": { + GTLD: "auto", + DelegationDate: "2015-05-02", + RemovalDate: "", + }, + "autos": { + GTLD: "autos", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "avianca": { + GTLD: "avianca", + DelegationDate: "2016-03-09", + RemovalDate: "", + }, + "aw": { + GTLD: "aw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "aws": { + GTLD: "aws", + DelegationDate: "2016-03-25", + RemovalDate: "", + }, + "ax": { + GTLD: "ax", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "axa": { + GTLD: "axa", + DelegationDate: "2014-03-19", + RemovalDate: "", + }, + "az": { + GTLD: "az", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "azure": { + GTLD: "azure", + DelegationDate: "2015-06-06", + RemovalDate: "", + }, + "ba": { + GTLD: "ba", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "baby": { + GTLD: "baby", + DelegationDate: "2016-04-08", + RemovalDate: "", + }, + "baidu": { + GTLD: "baidu", + DelegationDate: "2016-01-05", + RemovalDate: "", + }, + "banamex": { + GTLD: "banamex", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "bananarepublic": { + GTLD: "bananarepublic", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "band": { + GTLD: "band", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "bank": { + GTLD: "bank", + DelegationDate: "2015-01-09", + RemovalDate: "", + }, + "bar": { + GTLD: "bar", + DelegationDate: "2014-02-27", + RemovalDate: "", + }, + "barcelona": { + GTLD: "barcelona", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "barclaycard": { + GTLD: "barclaycard", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "barclays": { + GTLD: "barclays", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "barefoot": { + GTLD: "barefoot", + DelegationDate: "2016-03-24", + RemovalDate: "", + }, + "bargains": { + GTLD: "bargains", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "baseball": { + GTLD: "baseball", + DelegationDate: "2016-10-30", + RemovalDate: "", + }, + "basketball": { + GTLD: "basketball", + DelegationDate: "2016-10-19", + RemovalDate: "", + }, + "bauhaus": { + GTLD: "bauhaus", + DelegationDate: "2015-04-05", + RemovalDate: "", + }, + "bayern": { + GTLD: "bayern", + DelegationDate: "2014-05-03", + RemovalDate: "", + }, + "bb": { + GTLD: "bb", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bbc": { + GTLD: "bbc", + DelegationDate: "2015-03-21", + RemovalDate: "", + }, + "bbt": { + GTLD: "bbt", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "bbva": { + GTLD: "bbva", + DelegationDate: "2015-05-27", + RemovalDate: "", + }, + "bcg": { + GTLD: "bcg", + DelegationDate: "2016-03-09", + RemovalDate: "", + }, + "bcn": { + GTLD: "bcn", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "bd": { + GTLD: "bd", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "be": { + GTLD: "be", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "beats": { + GTLD: "beats", + DelegationDate: "2015-11-03", + RemovalDate: "", + }, + "beauty": { + GTLD: "beauty", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "beer": { + GTLD: "beer", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "bentley": { + GTLD: "bentley", + DelegationDate: "2015-07-09", + RemovalDate: "", + }, + "berlin": { + GTLD: "berlin", + DelegationDate: "2014-01-08", + RemovalDate: "", + }, + "best": { + GTLD: "best", + DelegationDate: "2014-02-27", + RemovalDate: "", + }, + "bestbuy": { + GTLD: "bestbuy", + DelegationDate: "2016-07-19", + RemovalDate: "", + }, + "bet": { + GTLD: "bet", + DelegationDate: "2015-07-24", + RemovalDate: "", + }, + "bf": { + GTLD: "bf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bg": { + GTLD: "bg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bh": { + GTLD: "bh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bharti": { + GTLD: "bharti", + DelegationDate: "2015-06-14", + RemovalDate: "", + }, + "bi": { + GTLD: "bi", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bible": { + GTLD: "bible", + DelegationDate: "2015-06-02", + RemovalDate: "", + }, + "bid": { + GTLD: "bid", + DelegationDate: "2014-03-02", + RemovalDate: "", + }, + "bike": { + GTLD: "bike", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "bing": { + GTLD: "bing", + DelegationDate: "2015-06-10", + RemovalDate: "", + }, + "bingo": { + GTLD: "bingo", + DelegationDate: "2015-02-04", + RemovalDate: "", + }, + "bio": { + GTLD: "bio", + DelegationDate: "2014-06-02", + RemovalDate: "", + }, + "biz": { + GTLD: "biz", + DelegationDate: "2001-09-25", + RemovalDate: "", + }, + "bj": { + GTLD: "bj", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "black": { + GTLD: "black", + DelegationDate: "2014-03-27", + RemovalDate: "", + }, + "blackfriday": { + GTLD: "blackfriday", + DelegationDate: "2014-04-22", + RemovalDate: "", + }, + "blanco": { + GTLD: "blanco", + DelegationDate: "2016-06-21", + RemovalDate: "2019-02-13", + }, + "blockbuster": { + GTLD: "blockbuster", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "blog": { + GTLD: "blog", + DelegationDate: "2016-05-18", + RemovalDate: "", + }, + "bloomberg": { + GTLD: "bloomberg", + DelegationDate: "2014-11-05", + RemovalDate: "", + }, + "blue": { + GTLD: "blue", + DelegationDate: "2014-02-05", + RemovalDate: "", + }, + "bm": { + GTLD: "bm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bms": { + GTLD: "bms", + DelegationDate: "2015-09-22", + RemovalDate: "", + }, + "bmw": { + GTLD: "bmw", + DelegationDate: "2014-06-21", + RemovalDate: "", + }, + "bn": { + GTLD: "bn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bnl": { + GTLD: "bnl", + DelegationDate: "2015-06-26", + RemovalDate: "2019-07-30", + }, + "bnpparibas": { + GTLD: "bnpparibas", + DelegationDate: "2014-08-14", + RemovalDate: "", + }, + "bo": { + GTLD: "bo", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "boats": { + GTLD: "boats", + DelegationDate: "2015-02-25", + RemovalDate: "", + }, + "boehringer": { + GTLD: "boehringer", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "bofa": { + GTLD: "bofa", + DelegationDate: "2016-08-02", + RemovalDate: "", + }, + "bom": { + GTLD: "bom", + DelegationDate: "2015-09-26", + RemovalDate: "", + }, + "bond": { + GTLD: "bond", + DelegationDate: "2015-03-27", + RemovalDate: "", + }, + "boo": { + GTLD: "boo", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "book": { + GTLD: "book", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "booking": { + GTLD: "booking", + DelegationDate: "2016-07-23", + RemovalDate: "", + }, + "boots": { + GTLD: "boots", + DelegationDate: "2015-08-05", + RemovalDate: "2018-04-06", + }, + "bosch": { + GTLD: "bosch", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "bostik": { + GTLD: "bostik", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "boston": { + GTLD: "boston", + DelegationDate: "2016-11-29", + RemovalDate: "", + }, + "bot": { + GTLD: "bot", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "boutique": { + GTLD: "boutique", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "box": { + GTLD: "box", + DelegationDate: "2016-11-11", + RemovalDate: "", + }, + "br": { + GTLD: "br", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bradesco": { + GTLD: "bradesco", + DelegationDate: "2015-06-26", + RemovalDate: "", + }, + "bridgestone": { + GTLD: "bridgestone", + DelegationDate: "2015-05-01", + RemovalDate: "", + }, + "broadway": { + GTLD: "broadway", + DelegationDate: "2015-11-18", + RemovalDate: "", + }, + "broker": { + GTLD: "broker", + DelegationDate: "2015-04-29", + RemovalDate: "", + }, + "brother": { + GTLD: "brother", + DelegationDate: "2015-05-12", + RemovalDate: "", + }, + "brussels": { + GTLD: "brussels", + DelegationDate: "2014-06-18", + RemovalDate: "", + }, + "bs": { + GTLD: "bs", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bt": { + GTLD: "bt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "budapest": { + GTLD: "budapest", + DelegationDate: "2014-09-23", + RemovalDate: "", + }, + "bugatti": { + GTLD: "bugatti", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "build": { + GTLD: "build", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "builders": { + GTLD: "builders", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "business": { + GTLD: "business", + DelegationDate: "2014-08-22", + RemovalDate: "", + }, + "buy": { + GTLD: "buy", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "buzz": { + GTLD: "buzz", + DelegationDate: "2013-12-18", + RemovalDate: "", + }, + "bv": { + GTLD: "bv", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bw": { + GTLD: "bw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "by": { + GTLD: "by", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bz": { + GTLD: "bz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "bzh": { + GTLD: "bzh", + DelegationDate: "2014-06-17", + RemovalDate: "", + }, + "ca": { + GTLD: "ca", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cab": { + GTLD: "cab", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "cafe": { + GTLD: "cafe", + DelegationDate: "2015-04-05", + RemovalDate: "", + }, + "cal": { + GTLD: "cal", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "call": { + GTLD: "call", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "calvinklein": { + GTLD: "calvinklein", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "cam": { + GTLD: "cam", + DelegationDate: "2016-06-16", + RemovalDate: "", + }, + "camera": { + GTLD: "camera", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "camp": { + GTLD: "camp", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "cancerresearch": { + GTLD: "cancerresearch", + DelegationDate: "2014-07-03", + RemovalDate: "", + }, + "canon": { + GTLD: "canon", + DelegationDate: "2015-02-04", + RemovalDate: "", + }, + "capetown": { + GTLD: "capetown", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "capital": { + GTLD: "capital", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "capitalone": { + GTLD: "capitalone", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "car": { + GTLD: "car", + DelegationDate: "2015-09-09", + RemovalDate: "", + }, + "caravan": { + GTLD: "caravan", + DelegationDate: "2014-08-15", + RemovalDate: "", + }, + "cards": { + GTLD: "cards", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "care": { + GTLD: "care", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "career": { + GTLD: "career", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "careers": { + GTLD: "careers", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "cars": { + GTLD: "cars", + DelegationDate: "2015-05-02", + RemovalDate: "", + }, + "cartier": { + GTLD: "cartier", + DelegationDate: "2014-12-11", + RemovalDate: "2019-11-14", + }, + "casa": { + GTLD: "casa", + DelegationDate: "2014-09-23", + RemovalDate: "", + }, + "case": { + GTLD: "case", + DelegationDate: "2016-10-30", + RemovalDate: "", + }, + "caseih": { + GTLD: "caseih", + DelegationDate: "2016-10-30", + RemovalDate: "", + }, + "cash": { + GTLD: "cash", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "casino": { + GTLD: "casino", + DelegationDate: "2015-02-19", + RemovalDate: "", + }, + "cat": { + GTLD: "cat", + DelegationDate: "2005-12-20", + RemovalDate: "", + }, + "catering": { + GTLD: "catering", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "catholic": { + GTLD: "catholic", + DelegationDate: "2016-12-01", + RemovalDate: "", + }, + "cba": { + GTLD: "cba", + DelegationDate: "2015-06-22", + RemovalDate: "", + }, + "cbn": { + GTLD: "cbn", + DelegationDate: "2015-02-13", + RemovalDate: "", + }, + "cbre": { + GTLD: "cbre", + DelegationDate: "2016-07-02", + RemovalDate: "", + }, + "cbs": { + GTLD: "cbs", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "cc": { + GTLD: "cc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cd": { + GTLD: "cd", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ceb": { + GTLD: "ceb", + DelegationDate: "2015-08-08", + RemovalDate: "2020-12-08", + }, + "center": { + GTLD: "center", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "ceo": { + GTLD: "ceo", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "cern": { + GTLD: "cern", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "cf": { + GTLD: "cf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cfa": { + GTLD: "cfa", + DelegationDate: "2015-05-02", + RemovalDate: "", + }, + "cfd": { + GTLD: "cfd", + DelegationDate: "2015-03-13", + RemovalDate: "", + }, + "cg": { + GTLD: "cg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ch": { + GTLD: "ch", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "chanel": { + GTLD: "chanel", + DelegationDate: "2015-08-05", + RemovalDate: "", + }, + "channel": { + GTLD: "channel", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "charity": { + GTLD: "charity", + DelegationDate: "2018-06-07", + RemovalDate: "", + }, + "chase": { + GTLD: "chase", + DelegationDate: "2016-02-27", + RemovalDate: "", + }, + "chat": { + GTLD: "chat", + DelegationDate: "2015-02-04", + RemovalDate: "", + }, + "cheap": { + GTLD: "cheap", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "chintai": { + GTLD: "chintai", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "chloe": { + GTLD: "chloe", + DelegationDate: "2015-03-09", + RemovalDate: "2017-10-06", + }, + "christmas": { + GTLD: "christmas", + DelegationDate: "2014-02-26", + RemovalDate: "", + }, + "chrome": { + GTLD: "chrome", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "chrysler": { + GTLD: "chrysler", + DelegationDate: "2016-07-28", + RemovalDate: "2019-11-19", + }, + "church": { + GTLD: "church", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "ci": { + GTLD: "ci", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cipriani": { + GTLD: "cipriani", + DelegationDate: "2015-10-09", + RemovalDate: "", + }, + "circle": { + GTLD: "circle", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "cisco": { + GTLD: "cisco", + DelegationDate: "2015-05-15", + RemovalDate: "", + }, + "citadel": { + GTLD: "citadel", + DelegationDate: "2016-07-23", + RemovalDate: "", + }, + "citi": { + GTLD: "citi", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "citic": { + GTLD: "citic", + DelegationDate: "2014-04-29", + RemovalDate: "", + }, + "city": { + GTLD: "city", + DelegationDate: "2014-07-10", + RemovalDate: "", + }, + "cityeats": { + GTLD: "cityeats", + DelegationDate: "2015-11-10", + RemovalDate: "", + }, + "ck": { + GTLD: "ck", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cl": { + GTLD: "cl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "claims": { + GTLD: "claims", + DelegationDate: "2014-05-07", + RemovalDate: "", + }, + "cleaning": { + GTLD: "cleaning", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "click": { + GTLD: "click", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "clinic": { + GTLD: "clinic", + DelegationDate: "2014-04-22", + RemovalDate: "", + }, + "clinique": { + GTLD: "clinique", + DelegationDate: "2015-12-28", + RemovalDate: "", + }, + "clothing": { + GTLD: "clothing", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "cloud": { + GTLD: "cloud", + DelegationDate: "2015-06-26", + RemovalDate: "", + }, + "club": { + GTLD: "club", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "clubmed": { + GTLD: "clubmed", + DelegationDate: "2015-10-02", + RemovalDate: "", + }, + "cm": { + GTLD: "cm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cn": { + GTLD: "cn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "co": { + GTLD: "co", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "coach": { + GTLD: "coach", + DelegationDate: "2014-11-26", + RemovalDate: "", + }, + "codes": { + GTLD: "codes", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "coffee": { + GTLD: "coffee", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "college": { + GTLD: "college", + DelegationDate: "2014-04-10", + RemovalDate: "", + }, + "cologne": { + GTLD: "cologne", + DelegationDate: "2014-03-19", + RemovalDate: "", + }, + "com": { + GTLD: "com", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "comcast": { + GTLD: "comcast", + DelegationDate: "2016-07-07", + RemovalDate: "", + }, + "commbank": { + GTLD: "commbank", + DelegationDate: "2015-06-22", + RemovalDate: "", + }, + "community": { + GTLD: "community", + DelegationDate: "2014-01-25", + RemovalDate: "", + }, + "company": { + GTLD: "company", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "compare": { + GTLD: "compare", + DelegationDate: "2016-01-15", + RemovalDate: "", + }, + "computer": { + GTLD: "computer", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "comsec": { + GTLD: "comsec", + DelegationDate: "2015-11-16", + RemovalDate: "", + }, + "condos": { + GTLD: "condos", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "construction": { + GTLD: "construction", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "consulting": { + GTLD: "consulting", + DelegationDate: "2014-04-01", + RemovalDate: "", + }, + "contact": { + GTLD: "contact", + DelegationDate: "2015-12-22", + RemovalDate: "", + }, + "contractors": { + GTLD: "contractors", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "cooking": { + GTLD: "cooking", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "cookingchannel": { + GTLD: "cookingchannel", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "cool": { + GTLD: "cool", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "coop": { + GTLD: "coop", + DelegationDate: "2001-12-20", + RemovalDate: "", + }, + "corsica": { + GTLD: "corsica", + DelegationDate: "2015-05-16", + RemovalDate: "", + }, + "country": { + GTLD: "country", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "coupon": { + GTLD: "coupon", + DelegationDate: "2016-02-19", + RemovalDate: "", + }, + "coupons": { + GTLD: "coupons", + DelegationDate: "2015-05-13", + RemovalDate: "", + }, + "courses": { + GTLD: "courses", + DelegationDate: "2015-02-25", + RemovalDate: "", + }, + "cpa": { + GTLD: "cpa", + DelegationDate: "2019-09-20", + RemovalDate: "", + }, + "cr": { + GTLD: "cr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "credit": { + GTLD: "credit", + DelegationDate: "2014-05-07", + RemovalDate: "", + }, + "creditcard": { + GTLD: "creditcard", + DelegationDate: "2014-04-29", + RemovalDate: "", + }, + "creditunion": { + GTLD: "creditunion", + DelegationDate: "2015-11-10", + RemovalDate: "", + }, + "cricket": { + GTLD: "cricket", + DelegationDate: "2014-11-17", + RemovalDate: "", + }, + "crown": { + GTLD: "crown", + DelegationDate: "2015-06-19", + RemovalDate: "", + }, + "crs": { + GTLD: "crs", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "cruise": { + GTLD: "cruise", + DelegationDate: "2016-11-12", + RemovalDate: "", + }, + "cruises": { + GTLD: "cruises", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "csc": { + GTLD: "csc", + DelegationDate: "2015-09-01", + RemovalDate: "", + }, + "cu": { + GTLD: "cu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cuisinella": { + GTLD: "cuisinella", + DelegationDate: "2014-07-03", + RemovalDate: "", + }, + "cv": { + GTLD: "cv", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cw": { + GTLD: "cw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cx": { + GTLD: "cx", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cy": { + GTLD: "cy", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "cymru": { + GTLD: "cymru", + DelegationDate: "2014-08-08", + RemovalDate: "", + }, + "cyou": { + GTLD: "cyou", + DelegationDate: "2015-04-03", + RemovalDate: "", + }, + "cz": { + GTLD: "cz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "dabur": { + GTLD: "dabur", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "dad": { + GTLD: "dad", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "dance": { + GTLD: "dance", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "data": { + GTLD: "data", + DelegationDate: "2016-12-20", + RemovalDate: "", + }, + "date": { + GTLD: "date", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "dating": { + GTLD: "dating", + DelegationDate: "2014-01-25", + RemovalDate: "", + }, + "datsun": { + GTLD: "datsun", + DelegationDate: "2015-03-04", + RemovalDate: "", + }, + "day": { + GTLD: "day", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "dclk": { + GTLD: "dclk", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "dds": { + GTLD: "dds", + DelegationDate: "2016-05-11", + RemovalDate: "", + }, + "de": { + GTLD: "de", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "deal": { + GTLD: "deal", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "dealer": { + GTLD: "dealer", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "deals": { + GTLD: "deals", + DelegationDate: "2014-07-10", + RemovalDate: "", + }, + "degree": { + GTLD: "degree", + DelegationDate: "2014-05-30", + RemovalDate: "", + }, + "delivery": { + GTLD: "delivery", + DelegationDate: "2014-11-01", + RemovalDate: "", + }, + "dell": { + GTLD: "dell", + DelegationDate: "2015-10-14", + RemovalDate: "", + }, + "deloitte": { + GTLD: "deloitte", + DelegationDate: "2016-01-29", + RemovalDate: "", + }, + "delta": { + GTLD: "delta", + DelegationDate: "2015-07-11", + RemovalDate: "", + }, + "democrat": { + GTLD: "democrat", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "dental": { + GTLD: "dental", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "dentist": { + GTLD: "dentist", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "desi": { + GTLD: "desi", + DelegationDate: "2014-04-10", + RemovalDate: "", + }, + "design": { + GTLD: "design", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "dev": { + GTLD: "dev", + DelegationDate: "2014-12-18", + RemovalDate: "", + }, + "dhl": { + GTLD: "dhl", + DelegationDate: "2016-06-02", + RemovalDate: "", + }, + "diamonds": { + GTLD: "diamonds", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "diet": { + GTLD: "diet", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "digital": { + GTLD: "digital", + DelegationDate: "2014-05-07", + RemovalDate: "", + }, + "direct": { + GTLD: "direct", + DelegationDate: "2014-07-02", + RemovalDate: "", + }, + "directory": { + GTLD: "directory", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "discount": { + GTLD: "discount", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "discover": { + GTLD: "discover", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "dish": { + GTLD: "dish", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "diy": { + GTLD: "diy", + DelegationDate: "2016-08-25", + RemovalDate: "", + }, + "dj": { + GTLD: "dj", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "dk": { + GTLD: "dk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "dm": { + GTLD: "dm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "dnp": { + GTLD: "dnp", + DelegationDate: "2014-03-11", + RemovalDate: "", + }, + "do": { + GTLD: "do", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "docs": { + GTLD: "docs", + DelegationDate: "2014-12-18", + RemovalDate: "", + }, + "doctor": { + GTLD: "doctor", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "dodge": { + GTLD: "dodge", + DelegationDate: "2016-08-04", + RemovalDate: "2019-11-19", + }, + "dog": { + GTLD: "dog", + DelegationDate: "2015-04-29", + RemovalDate: "", + }, + "doha": { + GTLD: "doha", + DelegationDate: "2015-03-25", + RemovalDate: "2019-04-09", + }, + "domains": { + GTLD: "domains", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "doosan": { + GTLD: "doosan", + DelegationDate: "2014-12-13", + RemovalDate: "2016-02-24", + }, + "dot": { + GTLD: "dot", + DelegationDate: "2016-05-18", + RemovalDate: "", + }, + "download": { + GTLD: "download", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "drive": { + GTLD: "drive", + DelegationDate: "2015-06-20", + RemovalDate: "", + }, + "dtv": { + GTLD: "dtv", + DelegationDate: "2016-05-27", + RemovalDate: "", + }, + "dubai": { + GTLD: "dubai", + DelegationDate: "2016-01-07", + RemovalDate: "", + }, + "duck": { + GTLD: "duck", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "dunlop": { + GTLD: "dunlop", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "duns": { + GTLD: "duns", + DelegationDate: "2016-07-23", + RemovalDate: "2019-08-30", + }, + "dupont": { + GTLD: "dupont", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "durban": { + GTLD: "durban", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "dvag": { + GTLD: "dvag", + DelegationDate: "2014-09-27", + RemovalDate: "", + }, + "dvr": { + GTLD: "dvr", + DelegationDate: "2016-09-30", + RemovalDate: "", + }, + "dz": { + GTLD: "dz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "earth": { + GTLD: "earth", + DelegationDate: "2015-05-14", + RemovalDate: "", + }, + "eat": { + GTLD: "eat", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "ec": { + GTLD: "ec", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "eco": { + GTLD: "eco", + DelegationDate: "2016-08-28", + RemovalDate: "", + }, + "edeka": { + GTLD: "edeka", + DelegationDate: "2016-01-21", + RemovalDate: "", + }, + "edu": { + GTLD: "edu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "education": { + GTLD: "education", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "ee": { + GTLD: "ee", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "eg": { + GTLD: "eg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "email": { + GTLD: "email", + DelegationDate: "2014-01-02", + RemovalDate: "", + }, + "emerck": { + GTLD: "emerck", + DelegationDate: "2014-10-22", + RemovalDate: "", + }, + "energy": { + GTLD: "energy", + DelegationDate: "2014-11-01", + RemovalDate: "", + }, + "engineer": { + GTLD: "engineer", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "engineering": { + GTLD: "engineering", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "enterprises": { + GTLD: "enterprises", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "epost": { + GTLD: "epost", + DelegationDate: "2016-06-07", + RemovalDate: "2019-02-15", + }, + "epson": { + GTLD: "epson", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "equipment": { + GTLD: "equipment", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "er": { + GTLD: "er", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ericsson": { + GTLD: "ericsson", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "erni": { + GTLD: "erni", + DelegationDate: "2015-03-12", + RemovalDate: "", + }, + "es": { + GTLD: "es", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "esq": { + GTLD: "esq", + DelegationDate: "2014-08-29", + RemovalDate: "", + }, + "estate": { + GTLD: "estate", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "esurance": { + GTLD: "esurance", + DelegationDate: "2016-07-23", + RemovalDate: "2020-05-26", + }, + "et": { + GTLD: "et", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "etisalat": { + GTLD: "etisalat", + DelegationDate: "2017-06-01", + RemovalDate: "", + }, + "eu": { + GTLD: "eu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "eurovision": { + GTLD: "eurovision", + DelegationDate: "2014-12-06", + RemovalDate: "", + }, + "eus": { + GTLD: "eus", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "events": { + GTLD: "events", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "everbank": { + GTLD: "everbank", + DelegationDate: "2014-11-26", + RemovalDate: "2019-11-14", + }, + "exchange": { + GTLD: "exchange", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "expert": { + GTLD: "expert", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "exposed": { + GTLD: "exposed", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "express": { + GTLD: "express", + DelegationDate: "2015-04-05", + RemovalDate: "", + }, + "extraspace": { + GTLD: "extraspace", + DelegationDate: "2016-03-25", + RemovalDate: "", + }, + "fage": { + GTLD: "fage", + DelegationDate: "2015-08-08", + RemovalDate: "", + }, + "fail": { + GTLD: "fail", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "fairwinds": { + GTLD: "fairwinds", + DelegationDate: "2015-11-13", + RemovalDate: "", + }, + "faith": { + GTLD: "faith", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "family": { + GTLD: "family", + DelegationDate: "2015-08-11", + RemovalDate: "", + }, + "fan": { + GTLD: "fan", + DelegationDate: "2015-03-16", + RemovalDate: "", + }, + "fans": { + GTLD: "fans", + DelegationDate: "2015-02-19", + RemovalDate: "", + }, + "farm": { + GTLD: "farm", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "farmers": { + GTLD: "farmers", + DelegationDate: "2016-06-25", + RemovalDate: "", + }, + "fashion": { + GTLD: "fashion", + DelegationDate: "2014-12-06", + RemovalDate: "", + }, + "fast": { + GTLD: "fast", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "fedex": { + GTLD: "fedex", + DelegationDate: "2016-06-25", + RemovalDate: "", + }, + "feedback": { + GTLD: "feedback", + DelegationDate: "2014-04-10", + RemovalDate: "", + }, + "ferrari": { + GTLD: "ferrari", + DelegationDate: "2016-08-02", + RemovalDate: "", + }, + "ferrero": { + GTLD: "ferrero", + DelegationDate: "2015-11-07", + RemovalDate: "", + }, + "fi": { + GTLD: "fi", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "fiat": { + GTLD: "fiat", + DelegationDate: "2016-08-02", + RemovalDate: "", + }, + "fidelity": { + GTLD: "fidelity", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "fido": { + GTLD: "fido", + DelegationDate: "2016-09-20", + RemovalDate: "", + }, + "film": { + GTLD: "film", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "final": { + GTLD: "final", + DelegationDate: "2015-09-26", + RemovalDate: "", + }, + "finance": { + GTLD: "finance", + DelegationDate: "2014-04-29", + RemovalDate: "", + }, + "financial": { + GTLD: "financial", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "fire": { + GTLD: "fire", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "firestone": { + GTLD: "firestone", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "firmdale": { + GTLD: "firmdale", + DelegationDate: "2014-11-20", + RemovalDate: "", + }, + "fish": { + GTLD: "fish", + DelegationDate: "2014-02-21", + RemovalDate: "", + }, + "fishing": { + GTLD: "fishing", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "fit": { + GTLD: "fit", + DelegationDate: "2015-01-09", + RemovalDate: "", + }, + "fitness": { + GTLD: "fitness", + DelegationDate: "2014-04-22", + RemovalDate: "", + }, + "fj": { + GTLD: "fj", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "fk": { + GTLD: "fk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "flickr": { + GTLD: "flickr", + DelegationDate: "2016-02-13", + RemovalDate: "", + }, + "flights": { + GTLD: "flights", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "flir": { + GTLD: "flir", + DelegationDate: "2016-05-10", + RemovalDate: "", + }, + "florist": { + GTLD: "florist", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "flowers": { + GTLD: "flowers", + DelegationDate: "2014-12-25", + RemovalDate: "", + }, + "flsmidth": { + GTLD: "flsmidth", + DelegationDate: "2014-10-15", + RemovalDate: "2016-07-29", + }, + "fly": { + GTLD: "fly", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "fm": { + GTLD: "fm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "fo": { + GTLD: "fo", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "foo": { + GTLD: "foo", + DelegationDate: "2014-04-19", + RemovalDate: "", + }, + "food": { + GTLD: "food", + DelegationDate: "2016-11-10", + RemovalDate: "", + }, + "foodnetwork": { + GTLD: "foodnetwork", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "football": { + GTLD: "football", + DelegationDate: "2015-02-19", + RemovalDate: "", + }, + "ford": { + GTLD: "ford", + DelegationDate: "2015-12-18", + RemovalDate: "", + }, + "forex": { + GTLD: "forex", + DelegationDate: "2015-03-12", + RemovalDate: "", + }, + "forsale": { + GTLD: "forsale", + DelegationDate: "2014-10-01", + RemovalDate: "", + }, + "forum": { + GTLD: "forum", + DelegationDate: "2015-07-01", + RemovalDate: "", + }, + "foundation": { + GTLD: "foundation", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "fox": { + GTLD: "fox", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "fr": { + GTLD: "fr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "free": { + GTLD: "free", + DelegationDate: "2016-11-08", + RemovalDate: "", + }, + "fresenius": { + GTLD: "fresenius", + DelegationDate: "2016-01-09", + RemovalDate: "", + }, + "frl": { + GTLD: "frl", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "frogans": { + GTLD: "frogans", + DelegationDate: "2014-04-19", + RemovalDate: "", + }, + "frontdoor": { + GTLD: "frontdoor", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "frontier": { + GTLD: "frontier", + DelegationDate: "2016-02-06", + RemovalDate: "", + }, + "ftr": { + GTLD: "ftr", + DelegationDate: "2016-04-17", + RemovalDate: "", + }, + "fujitsu": { + GTLD: "fujitsu", + DelegationDate: "2016-07-07", + RemovalDate: "", + }, + "fujixerox": { + GTLD: "fujixerox", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "fun": { + GTLD: "fun", + DelegationDate: "2016-12-21", + RemovalDate: "", + }, + "fund": { + GTLD: "fund", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "furniture": { + GTLD: "furniture", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "futbol": { + GTLD: "futbol", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "fyi": { + GTLD: "fyi", + DelegationDate: "2015-05-22", + RemovalDate: "", + }, + "ga": { + GTLD: "ga", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gal": { + GTLD: "gal", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "gallery": { + GTLD: "gallery", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "gallo": { + GTLD: "gallo", + DelegationDate: "2016-03-22", + RemovalDate: "", + }, + "gallup": { + GTLD: "gallup", + DelegationDate: "2016-02-11", + RemovalDate: "", + }, + "game": { + GTLD: "game", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "games": { + GTLD: "games", + DelegationDate: "2016-06-02", + RemovalDate: "", + }, + "gap": { + GTLD: "gap", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "garden": { + GTLD: "garden", + DelegationDate: "2014-12-13", + RemovalDate: "", + }, + "gay": { + GTLD: "gay", + DelegationDate: "2019-08-09", + RemovalDate: "", + }, + "gb": { + GTLD: "gb", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gbiz": { + GTLD: "gbiz", + DelegationDate: "2014-08-27", + RemovalDate: "", + }, + "gd": { + GTLD: "gd", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gdn": { + GTLD: "gdn", + DelegationDate: "2015-02-13", + RemovalDate: "", + }, + "ge": { + GTLD: "ge", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gea": { + GTLD: "gea", + DelegationDate: "2015-08-28", + RemovalDate: "", + }, + "gent": { + GTLD: "gent", + DelegationDate: "2014-07-12", + RemovalDate: "", + }, + "genting": { + GTLD: "genting", + DelegationDate: "2015-06-20", + RemovalDate: "", + }, + "george": { + GTLD: "george", + DelegationDate: "2016-08-18", + RemovalDate: "", + }, + "gf": { + GTLD: "gf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gg": { + GTLD: "gg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ggee": { + GTLD: "ggee", + DelegationDate: "2014-12-25", + RemovalDate: "", + }, + "gh": { + GTLD: "gh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gi": { + GTLD: "gi", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gift": { + GTLD: "gift", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "gifts": { + GTLD: "gifts", + DelegationDate: "2014-08-08", + RemovalDate: "", + }, + "gives": { + GTLD: "gives", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "giving": { + GTLD: "giving", + DelegationDate: "2015-08-06", + RemovalDate: "", + }, + "gl": { + GTLD: "gl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "glade": { + GTLD: "glade", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "glass": { + GTLD: "glass", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "gle": { + GTLD: "gle", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "global": { + GTLD: "global", + DelegationDate: "2014-06-11", + RemovalDate: "", + }, + "globo": { + GTLD: "globo", + DelegationDate: "2014-05-03", + RemovalDate: "", + }, + "gm": { + GTLD: "gm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gmail": { + GTLD: "gmail", + DelegationDate: "2014-08-27", + RemovalDate: "", + }, + "gmbh": { + GTLD: "gmbh", + DelegationDate: "2016-03-09", + RemovalDate: "", + }, + "gmo": { + GTLD: "gmo", + DelegationDate: "2014-05-03", + RemovalDate: "", + }, + "gmx": { + GTLD: "gmx", + DelegationDate: "2014-09-05", + RemovalDate: "", + }, + "gn": { + GTLD: "gn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "godaddy": { + GTLD: "godaddy", + DelegationDate: "2016-07-07", + RemovalDate: "", + }, + "gold": { + GTLD: "gold", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "goldpoint": { + GTLD: "goldpoint", + DelegationDate: "2015-02-19", + RemovalDate: "", + }, + "golf": { + GTLD: "golf", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "goo": { + GTLD: "goo", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "goodhands": { + GTLD: "goodhands", + DelegationDate: "2016-07-14", + RemovalDate: "2018-09-20", + }, + "goodyear": { + GTLD: "goodyear", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "goog": { + GTLD: "goog", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "google": { + GTLD: "google", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "gop": { + GTLD: "gop", + DelegationDate: "2014-04-04", + RemovalDate: "", + }, + "got": { + GTLD: "got", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "gov": { + GTLD: "gov", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gp": { + GTLD: "gp", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gq": { + GTLD: "gq", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gr": { + GTLD: "gr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "grainger": { + GTLD: "grainger", + DelegationDate: "2015-11-13", + RemovalDate: "", + }, + "graphics": { + GTLD: "graphics", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "gratis": { + GTLD: "gratis", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "green": { + GTLD: "green", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "gripe": { + GTLD: "gripe", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "grocery": { + GTLD: "grocery", + DelegationDate: "2017-06-28", + RemovalDate: "", + }, + "group": { + GTLD: "group", + DelegationDate: "2015-08-08", + RemovalDate: "", + }, + "gs": { + GTLD: "gs", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gt": { + GTLD: "gt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gu": { + GTLD: "gu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "guardian": { + GTLD: "guardian", + DelegationDate: "2016-05-13", + RemovalDate: "", + }, + "gucci": { + GTLD: "gucci", + DelegationDate: "2015-10-27", + RemovalDate: "", + }, + "guge": { + GTLD: "guge", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "guide": { + GTLD: "guide", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "guitars": { + GTLD: "guitars", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "guru": { + GTLD: "guru", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "gw": { + GTLD: "gw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "gy": { + GTLD: "gy", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "hair": { + GTLD: "hair", + DelegationDate: "2016-12-02", + RemovalDate: "", + }, + "hamburg": { + GTLD: "hamburg", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "hangout": { + GTLD: "hangout", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "haus": { + GTLD: "haus", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "hbo": { + GTLD: "hbo", + DelegationDate: "2016-08-14", + RemovalDate: "", + }, + "hdfc": { + GTLD: "hdfc", + DelegationDate: "2016-08-16", + RemovalDate: "", + }, + "hdfcbank": { + GTLD: "hdfcbank", + DelegationDate: "2016-02-11", + RemovalDate: "", + }, + "health": { + GTLD: "health", + DelegationDate: "2016-01-26", + RemovalDate: "", + }, + "healthcare": { + GTLD: "healthcare", + DelegationDate: "2014-07-30", + RemovalDate: "", + }, + "help": { + GTLD: "help", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "helsinki": { + GTLD: "helsinki", + DelegationDate: "2016-01-26", + RemovalDate: "", + }, + "here": { + GTLD: "here", + DelegationDate: "2014-08-29", + RemovalDate: "", + }, + "hermes": { + GTLD: "hermes", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "hgtv": { + GTLD: "hgtv", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "hiphop": { + GTLD: "hiphop", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "hisamitsu": { + GTLD: "hisamitsu", + DelegationDate: "2016-06-02", + RemovalDate: "", + }, + "hitachi": { + GTLD: "hitachi", + DelegationDate: "2015-05-01", + RemovalDate: "", + }, + "hiv": { + GTLD: "hiv", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "hk": { + GTLD: "hk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "hkt": { + GTLD: "hkt", + DelegationDate: "2016-05-12", + RemovalDate: "", + }, + "hm": { + GTLD: "hm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "hn": { + GTLD: "hn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "hockey": { + GTLD: "hockey", + DelegationDate: "2015-05-07", + RemovalDate: "", + }, + "holdings": { + GTLD: "holdings", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "holiday": { + GTLD: "holiday", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "homedepot": { + GTLD: "homedepot", + DelegationDate: "2015-06-04", + RemovalDate: "", + }, + "homegoods": { + GTLD: "homegoods", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "homes": { + GTLD: "homes", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "homesense": { + GTLD: "homesense", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "honda": { + GTLD: "honda", + DelegationDate: "2015-04-30", + RemovalDate: "", + }, + "honeywell": { + GTLD: "honeywell", + DelegationDate: "2016-07-26", + RemovalDate: "2019-06-06", + }, + "horse": { + GTLD: "horse", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "hospital": { + GTLD: "hospital", + DelegationDate: "2016-12-09", + RemovalDate: "", + }, + "host": { + GTLD: "host", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "hosting": { + GTLD: "hosting", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "hot": { + GTLD: "hot", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "hoteles": { + GTLD: "hoteles", + DelegationDate: "2015-06-26", + RemovalDate: "", + }, + "hotels": { + GTLD: "hotels", + DelegationDate: "2017-04-07", + RemovalDate: "", + }, + "hotmail": { + GTLD: "hotmail", + DelegationDate: "2015-06-10", + RemovalDate: "", + }, + "house": { + GTLD: "house", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "how": { + GTLD: "how", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "hr": { + GTLD: "hr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "hsbc": { + GTLD: "hsbc", + DelegationDate: "2015-07-10", + RemovalDate: "", + }, + "ht": { + GTLD: "ht", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "htc": { + GTLD: "htc", + DelegationDate: "2016-04-02", + RemovalDate: "2017-10-24", + }, + "hu": { + GTLD: "hu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "hughes": { + GTLD: "hughes", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "hyatt": { + GTLD: "hyatt", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "hyundai": { + GTLD: "hyundai", + DelegationDate: "2015-09-26", + RemovalDate: "", + }, + "ibm": { + GTLD: "ibm", + DelegationDate: "2014-10-01", + RemovalDate: "", + }, + "icbc": { + GTLD: "icbc", + DelegationDate: "2015-05-13", + RemovalDate: "", + }, + "ice": { + GTLD: "ice", + DelegationDate: "2015-07-22", + RemovalDate: "", + }, + "icu": { + GTLD: "icu", + DelegationDate: "2015-05-02", + RemovalDate: "", + }, + "id": { + GTLD: "id", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ie": { + GTLD: "ie", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ieee": { + GTLD: "ieee", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "ifm": { + GTLD: "ifm", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "iinet": { + GTLD: "iinet", + DelegationDate: "2015-07-09", + RemovalDate: "2016-12-21", + }, + "ikano": { + GTLD: "ikano", + DelegationDate: "2016-07-01", + RemovalDate: "", + }, + "il": { + GTLD: "il", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "im": { + GTLD: "im", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "imamat": { + GTLD: "imamat", + DelegationDate: "2016-04-16", + RemovalDate: "", + }, + "imdb": { + GTLD: "imdb", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "immo": { + GTLD: "immo", + DelegationDate: "2014-08-27", + RemovalDate: "", + }, + "immobilien": { + GTLD: "immobilien", + DelegationDate: "2014-01-02", + RemovalDate: "", + }, + "in": { + GTLD: "in", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "inc": { + GTLD: "inc", + DelegationDate: "2018-07-17", + RemovalDate: "", + }, + "industries": { + GTLD: "industries", + DelegationDate: "2014-02-21", + RemovalDate: "", + }, + "infiniti": { + GTLD: "infiniti", + DelegationDate: "2015-03-04", + RemovalDate: "", + }, + "info": { + GTLD: "info", + DelegationDate: "2001-09-19", + RemovalDate: "", + }, + "ing": { + GTLD: "ing", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "ink": { + GTLD: "ink", + DelegationDate: "2014-03-11", + RemovalDate: "", + }, + "institute": { + GTLD: "institute", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "insurance": { + GTLD: "insurance", + DelegationDate: "2015-12-03", + RemovalDate: "", + }, + "insure": { + GTLD: "insure", + DelegationDate: "2014-04-29", + RemovalDate: "", + }, + "int": { + GTLD: "int", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "intel": { + GTLD: "intel", + DelegationDate: "2016-07-28", + RemovalDate: "2020-10-07", + }, + "international": { + GTLD: "international", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "intuit": { + GTLD: "intuit", + DelegationDate: "2016-07-12", + RemovalDate: "", + }, + "investments": { + GTLD: "investments", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "io": { + GTLD: "io", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ipiranga": { + GTLD: "ipiranga", + DelegationDate: "2015-07-26", + RemovalDate: "", + }, + "iq": { + GTLD: "iq", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ir": { + GTLD: "ir", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "irish": { + GTLD: "irish", + DelegationDate: "2014-12-02", + RemovalDate: "", + }, + "is": { + GTLD: "is", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "iselect": { + GTLD: "iselect", + DelegationDate: "2016-01-15", + RemovalDate: "2019-08-05", + }, + "ismaili": { + GTLD: "ismaili", + DelegationDate: "2016-04-16", + RemovalDate: "", + }, + "ist": { + GTLD: "ist", + DelegationDate: "2015-07-11", + RemovalDate: "", + }, + "istanbul": { + GTLD: "istanbul", + DelegationDate: "2015-07-11", + RemovalDate: "", + }, + "it": { + GTLD: "it", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "itau": { + GTLD: "itau", + DelegationDate: "2015-07-22", + RemovalDate: "", + }, + "itv": { + GTLD: "itv", + DelegationDate: "2016-06-21", + RemovalDate: "", + }, + "iveco": { + GTLD: "iveco", + DelegationDate: "2016-10-30", + RemovalDate: "", + }, + "iwc": { + GTLD: "iwc", + DelegationDate: "2014-12-13", + RemovalDate: "2018-06-28", + }, + "jaguar": { + GTLD: "jaguar", + DelegationDate: "2015-10-27", + RemovalDate: "", + }, + "java": { + GTLD: "java", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "jcb": { + GTLD: "jcb", + DelegationDate: "2015-01-23", + RemovalDate: "", + }, + "jcp": { + GTLD: "jcp", + DelegationDate: "2016-03-30", + RemovalDate: "2020-11-20", + }, + "je": { + GTLD: "je", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "jeep": { + GTLD: "jeep", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "jetzt": { + GTLD: "jetzt", + DelegationDate: "2014-03-15", + RemovalDate: "", + }, + "jewelry": { + GTLD: "jewelry", + DelegationDate: "2015-04-16", + RemovalDate: "", + }, + "jio": { + GTLD: "jio", + DelegationDate: "2016-11-15", + RemovalDate: "", + }, + "jlc": { + GTLD: "jlc", + DelegationDate: "2015-06-10", + RemovalDate: "2018-09-18", + }, + "jll": { + GTLD: "jll", + DelegationDate: "2015-05-22", + RemovalDate: "", + }, + "jm": { + GTLD: "jm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "jmp": { + GTLD: "jmp", + DelegationDate: "2015-12-18", + RemovalDate: "", + }, + "jnj": { + GTLD: "jnj", + DelegationDate: "2016-04-08", + RemovalDate: "", + }, + "jo": { + GTLD: "jo", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "jobs": { + GTLD: "jobs", + DelegationDate: "2005-09-09", + RemovalDate: "", + }, + "joburg": { + GTLD: "joburg", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "jot": { + GTLD: "jot", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "joy": { + GTLD: "joy", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "jp": { + GTLD: "jp", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "jpmorgan": { + GTLD: "jpmorgan", + DelegationDate: "2016-02-27", + RemovalDate: "", + }, + "jprs": { + GTLD: "jprs", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "juegos": { + GTLD: "juegos", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "juniper": { + GTLD: "juniper", + DelegationDate: "2016-08-02", + RemovalDate: "", + }, + "kaufen": { + GTLD: "kaufen", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "kddi": { + GTLD: "kddi", + DelegationDate: "2015-01-09", + RemovalDate: "", + }, + "ke": { + GTLD: "ke", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "kerryhotels": { + GTLD: "kerryhotels", + DelegationDate: "2016-03-05", + RemovalDate: "", + }, + "kerrylogistics": { + GTLD: "kerrylogistics", + DelegationDate: "2016-03-05", + RemovalDate: "", + }, + "kerryproperties": { + GTLD: "kerryproperties", + DelegationDate: "2016-03-05", + RemovalDate: "", + }, + "kfh": { + GTLD: "kfh", + DelegationDate: "2015-12-15", + RemovalDate: "", + }, + "kg": { + GTLD: "kg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "kh": { + GTLD: "kh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ki": { + GTLD: "ki", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "kia": { + GTLD: "kia", + DelegationDate: "2015-09-26", + RemovalDate: "", + }, + "kim": { + GTLD: "kim", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "kinder": { + GTLD: "kinder", + DelegationDate: "2015-10-09", + RemovalDate: "", + }, + "kindle": { + GTLD: "kindle", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "kitchen": { + GTLD: "kitchen", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "kiwi": { + GTLD: "kiwi", + DelegationDate: "2014-01-03", + RemovalDate: "", + }, + "km": { + GTLD: "km", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "kn": { + GTLD: "kn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "koeln": { + GTLD: "koeln", + DelegationDate: "2014-03-05", + RemovalDate: "", + }, + "komatsu": { + GTLD: "komatsu", + DelegationDate: "2015-03-26", + RemovalDate: "", + }, + "kosher": { + GTLD: "kosher", + DelegationDate: "2016-06-10", + RemovalDate: "", + }, + "kp": { + GTLD: "kp", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "kpmg": { + GTLD: "kpmg", + DelegationDate: "2016-04-05", + RemovalDate: "", + }, + "kpn": { + GTLD: "kpn", + DelegationDate: "2015-12-15", + RemovalDate: "", + }, + "kr": { + GTLD: "kr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "krd": { + GTLD: "krd", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "kred": { + GTLD: "kred", + DelegationDate: "2014-02-27", + RemovalDate: "", + }, + "kuokgroup": { + GTLD: "kuokgroup", + DelegationDate: "2016-03-05", + RemovalDate: "", + }, + "kw": { + GTLD: "kw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ky": { + GTLD: "ky", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "kyoto": { + GTLD: "kyoto", + DelegationDate: "2015-01-28", + RemovalDate: "", + }, + "kz": { + GTLD: "kz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "la": { + GTLD: "la", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "lacaixa": { + GTLD: "lacaixa", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "ladbrokes": { + GTLD: "ladbrokes", + DelegationDate: "2016-07-29", + RemovalDate: "2019-11-19", + }, + "lamborghini": { + GTLD: "lamborghini", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "lamer": { + GTLD: "lamer", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "lancaster": { + GTLD: "lancaster", + DelegationDate: "2015-07-15", + RemovalDate: "", + }, + "lancia": { + GTLD: "lancia", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "lancome": { + GTLD: "lancome", + DelegationDate: "2016-07-15", + RemovalDate: "2019-11-28", + }, + "land": { + GTLD: "land", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "landrover": { + GTLD: "landrover", + DelegationDate: "2015-10-27", + RemovalDate: "", + }, + "lanxess": { + GTLD: "lanxess", + DelegationDate: "2016-01-26", + RemovalDate: "", + }, + "lasalle": { + GTLD: "lasalle", + DelegationDate: "2015-06-11", + RemovalDate: "", + }, + "lat": { + GTLD: "lat", + DelegationDate: "2015-01-09", + RemovalDate: "", + }, + "latino": { + GTLD: "latino", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "latrobe": { + GTLD: "latrobe", + DelegationDate: "2014-12-02", + RemovalDate: "", + }, + "law": { + GTLD: "law", + DelegationDate: "2015-06-26", + RemovalDate: "", + }, + "lawyer": { + GTLD: "lawyer", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "lb": { + GTLD: "lb", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "lc": { + GTLD: "lc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "lds": { + GTLD: "lds", + DelegationDate: "2014-11-19", + RemovalDate: "", + }, + "lease": { + GTLD: "lease", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "leclerc": { + GTLD: "leclerc", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "lefrak": { + GTLD: "lefrak", + DelegationDate: "2016-07-14", + RemovalDate: "", + }, + "legal": { + GTLD: "legal", + DelegationDate: "2014-11-26", + RemovalDate: "", + }, + "lego": { + GTLD: "lego", + DelegationDate: "2016-06-16", + RemovalDate: "", + }, + "lexus": { + GTLD: "lexus", + DelegationDate: "2015-07-26", + RemovalDate: "", + }, + "lgbt": { + GTLD: "lgbt", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "li": { + GTLD: "li", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "liaison": { + GTLD: "liaison", + DelegationDate: "2015-05-02", + RemovalDate: "2020-01-04", + }, + "lidl": { + GTLD: "lidl", + DelegationDate: "2014-12-13", + RemovalDate: "", + }, + "life": { + GTLD: "life", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "lifeinsurance": { + GTLD: "lifeinsurance", + DelegationDate: "2016-01-19", + RemovalDate: "", + }, + "lifestyle": { + GTLD: "lifestyle", + DelegationDate: "2015-11-10", + RemovalDate: "", + }, + "lighting": { + GTLD: "lighting", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "like": { + GTLD: "like", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "lilly": { + GTLD: "lilly", + DelegationDate: "2016-07-31", + RemovalDate: "", + }, + "limited": { + GTLD: "limited", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "limo": { + GTLD: "limo", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "lincoln": { + GTLD: "lincoln", + DelegationDate: "2015-12-18", + RemovalDate: "", + }, + "linde": { + GTLD: "linde", + DelegationDate: "2015-09-16", + RemovalDate: "", + }, + "link": { + GTLD: "link", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "lipsy": { + GTLD: "lipsy", + DelegationDate: "2016-05-03", + RemovalDate: "", + }, + "live": { + GTLD: "live", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "living": { + GTLD: "living", + DelegationDate: "2015-12-28", + RemovalDate: "", + }, + "lixil": { + GTLD: "lixil", + DelegationDate: "2015-07-30", + RemovalDate: "", + }, + "lk": { + GTLD: "lk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "llc": { + GTLD: "llc", + DelegationDate: "2018-02-22", + RemovalDate: "", + }, + "llp": { + GTLD: "llp", + DelegationDate: "2019-12-05", + RemovalDate: "", + }, + "loan": { + GTLD: "loan", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "loans": { + GTLD: "loans", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "locker": { + GTLD: "locker", + DelegationDate: "2016-05-27", + RemovalDate: "", + }, + "locus": { + GTLD: "locus", + DelegationDate: "2016-03-09", + RemovalDate: "", + }, + "loft": { + GTLD: "loft", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "lol": { + GTLD: "lol", + DelegationDate: "2015-05-02", + RemovalDate: "", + }, + "london": { + GTLD: "london", + DelegationDate: "2014-03-22", + RemovalDate: "", + }, + "lotte": { + GTLD: "lotte", + DelegationDate: "2015-01-14", + RemovalDate: "", + }, + "lotto": { + GTLD: "lotto", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "love": { + GTLD: "love", + DelegationDate: "2015-04-02", + RemovalDate: "", + }, + "lpl": { + GTLD: "lpl", + DelegationDate: "2016-07-19", + RemovalDate: "", + }, + "lplfinancial": { + GTLD: "lplfinancial", + DelegationDate: "2016-07-19", + RemovalDate: "", + }, + "lr": { + GTLD: "lr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ls": { + GTLD: "ls", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "lt": { + GTLD: "lt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ltd": { + GTLD: "ltd", + DelegationDate: "2015-09-23", + RemovalDate: "", + }, + "ltda": { + GTLD: "ltda", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "lu": { + GTLD: "lu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "lundbeck": { + GTLD: "lundbeck", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "lupin": { + GTLD: "lupin", + DelegationDate: "2015-05-16", + RemovalDate: "2020-12-10", + }, + "luxe": { + GTLD: "luxe", + DelegationDate: "2014-05-15", + RemovalDate: "", + }, + "luxury": { + GTLD: "luxury", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "lv": { + GTLD: "lv", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ly": { + GTLD: "ly", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ma": { + GTLD: "ma", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "macys": { + GTLD: "macys", + DelegationDate: "2016-07-12", + RemovalDate: "", + }, + "madrid": { + GTLD: "madrid", + DelegationDate: "2014-11-20", + RemovalDate: "", + }, + "maif": { + GTLD: "maif", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "maison": { + GTLD: "maison", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "makeup": { + GTLD: "makeup", + DelegationDate: "2016-01-15", + RemovalDate: "", + }, + "man": { + GTLD: "man", + DelegationDate: "2015-07-26", + RemovalDate: "", + }, + "management": { + GTLD: "management", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "mango": { + GTLD: "mango", + DelegationDate: "2014-02-16", + RemovalDate: "", + }, + "map": { + GTLD: "map", + DelegationDate: "2017-06-29", + RemovalDate: "", + }, + "market": { + GTLD: "market", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "marketing": { + GTLD: "marketing", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "markets": { + GTLD: "markets", + DelegationDate: "2015-03-12", + RemovalDate: "", + }, + "marriott": { + GTLD: "marriott", + DelegationDate: "2015-01-14", + RemovalDate: "", + }, + "marshalls": { + GTLD: "marshalls", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "maserati": { + GTLD: "maserati", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "mattel": { + GTLD: "mattel", + DelegationDate: "2016-05-28", + RemovalDate: "", + }, + "mba": { + GTLD: "mba", + DelegationDate: "2015-05-22", + RemovalDate: "", + }, + "mc": { + GTLD: "mc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mcd": { + GTLD: "mcd", + DelegationDate: "2016-08-08", + RemovalDate: "2017-08-31", + }, + "mcdonalds": { + GTLD: "mcdonalds", + DelegationDate: "2016-08-08", + RemovalDate: "2017-08-31", + }, + "mckinsey": { + GTLD: "mckinsey", + DelegationDate: "2016-07-31", + RemovalDate: "", + }, + "md": { + GTLD: "md", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "me": { + GTLD: "me", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "med": { + GTLD: "med", + DelegationDate: "2015-12-03", + RemovalDate: "", + }, + "media": { + GTLD: "media", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "meet": { + GTLD: "meet", + DelegationDate: "2014-03-27", + RemovalDate: "", + }, + "melbourne": { + GTLD: "melbourne", + DelegationDate: "2014-07-10", + RemovalDate: "", + }, + "meme": { + GTLD: "meme", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "memorial": { + GTLD: "memorial", + DelegationDate: "2014-11-26", + RemovalDate: "", + }, + "men": { + GTLD: "men", + DelegationDate: "2015-05-20", + RemovalDate: "", + }, + "menu": { + GTLD: "menu", + DelegationDate: "2013-11-30", + RemovalDate: "", + }, + "meo": { + GTLD: "meo", + DelegationDate: "2015-10-29", + RemovalDate: "2018-05-26", + }, + "merckmsd": { + GTLD: "merckmsd", + DelegationDate: "2017-07-10", + RemovalDate: "", + }, + "metlife": { + GTLD: "metlife", + DelegationDate: "2016-05-11", + RemovalDate: "2020-09-07", + }, + "mg": { + GTLD: "mg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mh": { + GTLD: "mh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "miami": { + GTLD: "miami", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "microsoft": { + GTLD: "microsoft", + DelegationDate: "2015-06-10", + RemovalDate: "", + }, + "mil": { + GTLD: "mil", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mini": { + GTLD: "mini", + DelegationDate: "2014-06-24", + RemovalDate: "", + }, + "mint": { + GTLD: "mint", + DelegationDate: "2016-07-12", + RemovalDate: "", + }, + "mit": { + GTLD: "mit", + DelegationDate: "2016-07-06", + RemovalDate: "", + }, + "mitsubishi": { + GTLD: "mitsubishi", + DelegationDate: "2016-07-07", + RemovalDate: "", + }, + "mk": { + GTLD: "mk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ml": { + GTLD: "ml", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mlb": { + GTLD: "mlb", + DelegationDate: "2016-05-25", + RemovalDate: "", + }, + "mls": { + GTLD: "mls", + DelegationDate: "2016-04-20", + RemovalDate: "", + }, + "mm": { + GTLD: "mm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mma": { + GTLD: "mma", + DelegationDate: "2015-03-31", + RemovalDate: "", + }, + "mn": { + GTLD: "mn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mo": { + GTLD: "mo", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mobi": { + GTLD: "mobi", + DelegationDate: "2005-10-20", + RemovalDate: "", + }, + "mobile": { + GTLD: "mobile", + DelegationDate: "2016-12-20", + RemovalDate: "", + }, + "mobily": { + GTLD: "mobily", + DelegationDate: "2015-12-23", + RemovalDate: "2019-09-09", + }, + "moda": { + GTLD: "moda", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "moe": { + GTLD: "moe", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "moi": { + GTLD: "moi", + DelegationDate: "2015-10-07", + RemovalDate: "", + }, + "mom": { + GTLD: "mom", + DelegationDate: "2015-08-19", + RemovalDate: "", + }, + "monash": { + GTLD: "monash", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "money": { + GTLD: "money", + DelegationDate: "2014-11-26", + RemovalDate: "", + }, + "monster": { + GTLD: "monster", + DelegationDate: "2016-09-14", + RemovalDate: "", + }, + "montblanc": { + GTLD: "montblanc", + DelegationDate: "2015-06-05", + RemovalDate: "2017-09-01", + }, + "mopar": { + GTLD: "mopar", + DelegationDate: "2016-08-02", + RemovalDate: "2019-11-19", + }, + "mormon": { + GTLD: "mormon", + DelegationDate: "2014-11-19", + RemovalDate: "", + }, + "mortgage": { + GTLD: "mortgage", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "moscow": { + GTLD: "moscow", + DelegationDate: "2014-04-24", + RemovalDate: "", + }, + "moto": { + GTLD: "moto", + DelegationDate: "2016-11-12", + RemovalDate: "", + }, + "motorcycles": { + GTLD: "motorcycles", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "mov": { + GTLD: "mov", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "movie": { + GTLD: "movie", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "movistar": { + GTLD: "movistar", + DelegationDate: "2015-06-26", + RemovalDate: "2019-12-23", + }, + "mp": { + GTLD: "mp", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mq": { + GTLD: "mq", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mr": { + GTLD: "mr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ms": { + GTLD: "ms", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "msd": { + GTLD: "msd", + DelegationDate: "2016-07-23", + RemovalDate: "", + }, + "mt": { + GTLD: "mt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mtn": { + GTLD: "mtn", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "mtpc": { + GTLD: "mtpc", + DelegationDate: "2015-03-04", + RemovalDate: "2017-05-15", + }, + "mtr": { + GTLD: "mtr", + DelegationDate: "2015-10-07", + RemovalDate: "", + }, + "mu": { + GTLD: "mu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "museum": { + GTLD: "museum", + DelegationDate: "2001-11-01", + RemovalDate: "", + }, + "mutual": { + GTLD: "mutual", + DelegationDate: "2016-04-05", + RemovalDate: "", + }, + "mutuelle": { + GTLD: "mutuelle", + DelegationDate: "2015-10-23", + RemovalDate: "2016-12-21", + }, + "mv": { + GTLD: "mv", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mw": { + GTLD: "mw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mx": { + GTLD: "mx", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "my": { + GTLD: "my", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "mz": { + GTLD: "mz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "na": { + GTLD: "na", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nab": { + GTLD: "nab", + DelegationDate: "2016-08-18", + RemovalDate: "", + }, + "nadex": { + GTLD: "nadex", + DelegationDate: "2015-05-02", + RemovalDate: "2020-03-27", + }, + "nagoya": { + GTLD: "nagoya", + DelegationDate: "2014-01-29", + RemovalDate: "", + }, + "name": { + GTLD: "name", + DelegationDate: "2002-01-04", + RemovalDate: "", + }, + "nationwide": { + GTLD: "nationwide", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "natura": { + GTLD: "natura", + DelegationDate: "2016-02-11", + RemovalDate: "", + }, + "navy": { + GTLD: "navy", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "nba": { + GTLD: "nba", + DelegationDate: "2016-08-02", + RemovalDate: "", + }, + "nc": { + GTLD: "nc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ne": { + GTLD: "ne", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nec": { + GTLD: "nec", + DelegationDate: "2015-05-09", + RemovalDate: "", + }, + "net": { + GTLD: "net", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "netbank": { + GTLD: "netbank", + DelegationDate: "2015-06-22", + RemovalDate: "", + }, + "netflix": { + GTLD: "netflix", + DelegationDate: "2016-05-28", + RemovalDate: "", + }, + "network": { + GTLD: "network", + DelegationDate: "2014-08-22", + RemovalDate: "", + }, + "neustar": { + GTLD: "neustar", + DelegationDate: "2014-02-19", + RemovalDate: "", + }, + "new": { + GTLD: "new", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "newholland": { + GTLD: "newholland", + DelegationDate: "2016-10-30", + RemovalDate: "", + }, + "news": { + GTLD: "news", + DelegationDate: "2015-03-21", + RemovalDate: "", + }, + "next": { + GTLD: "next", + DelegationDate: "2016-05-03", + RemovalDate: "", + }, + "nextdirect": { + GTLD: "nextdirect", + DelegationDate: "2016-05-03", + RemovalDate: "", + }, + "nexus": { + GTLD: "nexus", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "nf": { + GTLD: "nf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nfl": { + GTLD: "nfl", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "ng": { + GTLD: "ng", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ngo": { + GTLD: "ngo", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "nhk": { + GTLD: "nhk", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "ni": { + GTLD: "ni", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nico": { + GTLD: "nico", + DelegationDate: "2015-02-10", + RemovalDate: "", + }, + "nike": { + GTLD: "nike", + DelegationDate: "2016-07-09", + RemovalDate: "", + }, + "nikon": { + GTLD: "nikon", + DelegationDate: "2016-01-28", + RemovalDate: "", + }, + "ninja": { + GTLD: "ninja", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "nissan": { + GTLD: "nissan", + DelegationDate: "2015-03-04", + RemovalDate: "", + }, + "nissay": { + GTLD: "nissay", + DelegationDate: "2016-03-30", + RemovalDate: "", + }, + "nl": { + GTLD: "nl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "no": { + GTLD: "no", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nokia": { + GTLD: "nokia", + DelegationDate: "2015-07-15", + RemovalDate: "", + }, + "northwesternmutual": { + GTLD: "northwesternmutual", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "norton": { + GTLD: "norton", + DelegationDate: "2015-12-03", + RemovalDate: "", + }, + "now": { + GTLD: "now", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "nowruz": { + GTLD: "nowruz", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "nowtv": { + GTLD: "nowtv", + DelegationDate: "2016-05-11", + RemovalDate: "", + }, + "np": { + GTLD: "np", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nr": { + GTLD: "nr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nra": { + GTLD: "nra", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "nrw": { + GTLD: "nrw", + DelegationDate: "2014-07-11", + RemovalDate: "", + }, + "ntt": { + GTLD: "ntt", + DelegationDate: "2015-02-03", + RemovalDate: "", + }, + "nu": { + GTLD: "nu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "nyc": { + GTLD: "nyc", + DelegationDate: "2014-03-20", + RemovalDate: "", + }, + "nz": { + GTLD: "nz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "obi": { + GTLD: "obi", + DelegationDate: "2015-09-23", + RemovalDate: "", + }, + "observer": { + GTLD: "observer", + DelegationDate: "2016-09-27", + RemovalDate: "", + }, + "off": { + GTLD: "off", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "office": { + GTLD: "office", + DelegationDate: "2015-06-23", + RemovalDate: "", + }, + "okinawa": { + GTLD: "okinawa", + DelegationDate: "2014-03-02", + RemovalDate: "", + }, + "olayan": { + GTLD: "olayan", + DelegationDate: "2016-05-03", + RemovalDate: "", + }, + "olayangroup": { + GTLD: "olayangroup", + DelegationDate: "2016-05-06", + RemovalDate: "", + }, + "oldnavy": { + GTLD: "oldnavy", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "ollo": { + GTLD: "ollo", + DelegationDate: "2016-05-27", + RemovalDate: "", + }, + "om": { + GTLD: "om", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "omega": { + GTLD: "omega", + DelegationDate: "2015-06-26", + RemovalDate: "", + }, + "one": { + GTLD: "one", + DelegationDate: "2015-01-22", + RemovalDate: "", + }, + "ong": { + GTLD: "ong", + DelegationDate: "2014-07-27", + RemovalDate: "", + }, + "onl": { + GTLD: "onl", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "online": { + GTLD: "online", + DelegationDate: "2015-03-16", + RemovalDate: "", + }, + "onyourside": { + GTLD: "onyourside", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "ooo": { + GTLD: "ooo", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "open": { + GTLD: "open", + DelegationDate: "2016-08-08", + RemovalDate: "", + }, + "oracle": { + GTLD: "oracle", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "orange": { + GTLD: "orange", + DelegationDate: "2015-07-09", + RemovalDate: "", + }, + "org": { + GTLD: "org", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "organic": { + GTLD: "organic", + DelegationDate: "2014-06-13", + RemovalDate: "", + }, + "orientexpress": { + GTLD: "orientexpress", + DelegationDate: "2016-06-22", + RemovalDate: "2017-04-14", + }, + "origins": { + GTLD: "origins", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "osaka": { + GTLD: "osaka", + DelegationDate: "2014-12-13", + RemovalDate: "", + }, + "otsuka": { + GTLD: "otsuka", + DelegationDate: "2014-08-27", + RemovalDate: "", + }, + "ott": { + GTLD: "ott", + DelegationDate: "2016-05-27", + RemovalDate: "", + }, + "ovh": { + GTLD: "ovh", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "pa": { + GTLD: "pa", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "page": { + GTLD: "page", + DelegationDate: "2015-03-16", + RemovalDate: "", + }, + "pamperedchef": { + GTLD: "pamperedchef", + DelegationDate: "2016-01-21", + RemovalDate: "2017-09-20", + }, + "panasonic": { + GTLD: "panasonic", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "panerai": { + GTLD: "panerai", + DelegationDate: "2015-03-25", + RemovalDate: "2018-09-18", + }, + "paris": { + GTLD: "paris", + DelegationDate: "2014-04-19", + RemovalDate: "", + }, + "pars": { + GTLD: "pars", + DelegationDate: "2015-12-07", + RemovalDate: "", + }, + "partners": { + GTLD: "partners", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "parts": { + GTLD: "parts", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "party": { + GTLD: "party", + DelegationDate: "2014-11-17", + RemovalDate: "", + }, + "passagens": { + GTLD: "passagens", + DelegationDate: "2016-03-02", + RemovalDate: "", + }, + "pay": { + GTLD: "pay", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "pccw": { + GTLD: "pccw", + DelegationDate: "2016-05-11", + RemovalDate: "", + }, + "pe": { + GTLD: "pe", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pet": { + GTLD: "pet", + DelegationDate: "2015-07-26", + RemovalDate: "", + }, + "pf": { + GTLD: "pf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pfizer": { + GTLD: "pfizer", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "pg": { + GTLD: "pg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ph": { + GTLD: "ph", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pharmacy": { + GTLD: "pharmacy", + DelegationDate: "2014-09-05", + RemovalDate: "", + }, + "phd": { + GTLD: "phd", + DelegationDate: "2017-06-29", + RemovalDate: "", + }, + "philips": { + GTLD: "philips", + DelegationDate: "2015-05-09", + RemovalDate: "", + }, + "phone": { + GTLD: "phone", + DelegationDate: "2016-12-20", + RemovalDate: "", + }, + "photo": { + GTLD: "photo", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "photography": { + GTLD: "photography", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "photos": { + GTLD: "photos", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "physio": { + GTLD: "physio", + DelegationDate: "2014-06-19", + RemovalDate: "", + }, + "piaget": { + GTLD: "piaget", + DelegationDate: "2015-03-16", + RemovalDate: "2019-11-14", + }, + "pics": { + GTLD: "pics", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "pictet": { + GTLD: "pictet", + DelegationDate: "2015-03-07", + RemovalDate: "", + }, + "pictures": { + GTLD: "pictures", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "pid": { + GTLD: "pid", + DelegationDate: "2015-12-22", + RemovalDate: "", + }, + "pin": { + GTLD: "pin", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "ping": { + GTLD: "ping", + DelegationDate: "2015-10-29", + RemovalDate: "", + }, + "pink": { + GTLD: "pink", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "pioneer": { + GTLD: "pioneer", + DelegationDate: "2016-06-02", + RemovalDate: "", + }, + "pizza": { + GTLD: "pizza", + DelegationDate: "2014-08-27", + RemovalDate: "", + }, + "pk": { + GTLD: "pk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pl": { + GTLD: "pl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "place": { + GTLD: "place", + DelegationDate: "2014-07-02", + RemovalDate: "", + }, + "play": { + GTLD: "play", + DelegationDate: "2015-06-20", + RemovalDate: "", + }, + "playstation": { + GTLD: "playstation", + DelegationDate: "2015-11-07", + RemovalDate: "", + }, + "plumbing": { + GTLD: "plumbing", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "plus": { + GTLD: "plus", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "pm": { + GTLD: "pm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pn": { + GTLD: "pn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pnc": { + GTLD: "pnc", + DelegationDate: "2016-07-01", + RemovalDate: "", + }, + "pohl": { + GTLD: "pohl", + DelegationDate: "2014-09-27", + RemovalDate: "", + }, + "poker": { + GTLD: "poker", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "politie": { + GTLD: "politie", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "porn": { + GTLD: "porn", + DelegationDate: "2014-12-06", + RemovalDate: "", + }, + "post": { + GTLD: "post", + DelegationDate: "2012-08-07", + RemovalDate: "", + }, + "pr": { + GTLD: "pr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pramerica": { + GTLD: "pramerica", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "praxi": { + GTLD: "praxi", + DelegationDate: "2014-07-22", + RemovalDate: "", + }, + "press": { + GTLD: "press", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "prime": { + GTLD: "prime", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "pro": { + GTLD: "pro", + DelegationDate: "2004-05-27", + RemovalDate: "", + }, + "prod": { + GTLD: "prod", + DelegationDate: "2014-08-29", + RemovalDate: "", + }, + "productions": { + GTLD: "productions", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "prof": { + GTLD: "prof", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "progressive": { + GTLD: "progressive", + DelegationDate: "2016-04-20", + RemovalDate: "", + }, + "promo": { + GTLD: "promo", + DelegationDate: "2015-12-31", + RemovalDate: "", + }, + "properties": { + GTLD: "properties", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "property": { + GTLD: "property", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "protection": { + GTLD: "protection", + DelegationDate: "2015-09-13", + RemovalDate: "", + }, + "pru": { + GTLD: "pru", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "prudential": { + GTLD: "prudential", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "ps": { + GTLD: "ps", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pt": { + GTLD: "pt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pub": { + GTLD: "pub", + DelegationDate: "2014-02-26", + RemovalDate: "", + }, + "pw": { + GTLD: "pw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "pwc": { + GTLD: "pwc", + DelegationDate: "2016-02-11", + RemovalDate: "", + }, + "py": { + GTLD: "py", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "qa": { + GTLD: "qa", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "qpon": { + GTLD: "qpon", + DelegationDate: "2014-02-12", + RemovalDate: "", + }, + "quebec": { + GTLD: "quebec", + DelegationDate: "2014-04-16", + RemovalDate: "", + }, + "quest": { + GTLD: "quest", + DelegationDate: "2016-02-06", + RemovalDate: "", + }, + "qvc": { + GTLD: "qvc", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "racing": { + GTLD: "racing", + DelegationDate: "2015-04-03", + RemovalDate: "", + }, + "radio": { + GTLD: "radio", + DelegationDate: "2016-10-12", + RemovalDate: "", + }, + "raid": { + GTLD: "raid", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "re": { + GTLD: "re", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "read": { + GTLD: "read", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "realestate": { + GTLD: "realestate", + DelegationDate: "2016-05-23", + RemovalDate: "", + }, + "realtor": { + GTLD: "realtor", + DelegationDate: "2014-07-30", + RemovalDate: "", + }, + "realty": { + GTLD: "realty", + DelegationDate: "2015-07-01", + RemovalDate: "", + }, + "recipes": { + GTLD: "recipes", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "red": { + GTLD: "red", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "redstone": { + GTLD: "redstone", + DelegationDate: "2015-03-28", + RemovalDate: "", + }, + "redumbrella": { + GTLD: "redumbrella", + DelegationDate: "2015-12-11", + RemovalDate: "", + }, + "rehab": { + GTLD: "rehab", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "reise": { + GTLD: "reise", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "reisen": { + GTLD: "reisen", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "reit": { + GTLD: "reit", + DelegationDate: "2014-11-12", + RemovalDate: "", + }, + "reliance": { + GTLD: "reliance", + DelegationDate: "2016-11-15", + RemovalDate: "", + }, + "ren": { + GTLD: "ren", + DelegationDate: "2014-03-27", + RemovalDate: "", + }, + "rent": { + GTLD: "rent", + DelegationDate: "2015-04-30", + RemovalDate: "", + }, + "rentals": { + GTLD: "rentals", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "repair": { + GTLD: "repair", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "report": { + GTLD: "report", + DelegationDate: "2014-02-04", + RemovalDate: "", + }, + "republican": { + GTLD: "republican", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "rest": { + GTLD: "rest", + DelegationDate: "2014-04-02", + RemovalDate: "", + }, + "restaurant": { + GTLD: "restaurant", + DelegationDate: "2014-08-08", + RemovalDate: "", + }, + "review": { + GTLD: "review", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "reviews": { + GTLD: "reviews", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "rexroth": { + GTLD: "rexroth", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "rich": { + GTLD: "rich", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "richardli": { + GTLD: "richardli", + DelegationDate: "2016-05-11", + RemovalDate: "", + }, + "ricoh": { + GTLD: "ricoh", + DelegationDate: "2015-06-22", + RemovalDate: "", + }, + "rightathome": { + GTLD: "rightathome", + DelegationDate: "2016-07-21", + RemovalDate: "2020-07-28", + }, + "ril": { + GTLD: "ril", + DelegationDate: "2016-11-15", + RemovalDate: "", + }, + "rio": { + GTLD: "rio", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "rip": { + GTLD: "rip", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "rmit": { + GTLD: "rmit", + DelegationDate: "2016-11-24", + RemovalDate: "", + }, + "ro": { + GTLD: "ro", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "rocher": { + GTLD: "rocher", + DelegationDate: "2015-11-07", + RemovalDate: "", + }, + "rocks": { + GTLD: "rocks", + DelegationDate: "2014-04-10", + RemovalDate: "", + }, + "rodeo": { + GTLD: "rodeo", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "rogers": { + GTLD: "rogers", + DelegationDate: "2016-09-20", + RemovalDate: "", + }, + "room": { + GTLD: "room", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "rs": { + GTLD: "rs", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "rsvp": { + GTLD: "rsvp", + DelegationDate: "2014-08-30", + RemovalDate: "", + }, + "ru": { + GTLD: "ru", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "rugby": { + GTLD: "rugby", + DelegationDate: "2017-04-07", + RemovalDate: "", + }, + "ruhr": { + GTLD: "ruhr", + DelegationDate: "2013-12-10", + RemovalDate: "", + }, + "run": { + GTLD: "run", + DelegationDate: "2015-05-07", + RemovalDate: "", + }, + "rw": { + GTLD: "rw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "rwe": { + GTLD: "rwe", + DelegationDate: "2015-10-27", + RemovalDate: "", + }, + "ryukyu": { + GTLD: "ryukyu", + DelegationDate: "2014-04-03", + RemovalDate: "", + }, + "sa": { + GTLD: "sa", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "saarland": { + GTLD: "saarland", + DelegationDate: "2014-04-02", + RemovalDate: "", + }, + "safe": { + GTLD: "safe", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "safety": { + GTLD: "safety", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "sakura": { + GTLD: "sakura", + DelegationDate: "2015-07-02", + RemovalDate: "", + }, + "sale": { + GTLD: "sale", + DelegationDate: "2014-12-25", + RemovalDate: "", + }, + "salon": { + GTLD: "salon", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "samsclub": { + GTLD: "samsclub", + DelegationDate: "2016-08-18", + RemovalDate: "", + }, + "samsung": { + GTLD: "samsung", + DelegationDate: "2014-12-10", + RemovalDate: "", + }, + "sandvik": { + GTLD: "sandvik", + DelegationDate: "2015-05-27", + RemovalDate: "", + }, + "sandvikcoromant": { + GTLD: "sandvikcoromant", + DelegationDate: "2015-05-27", + RemovalDate: "", + }, + "sanofi": { + GTLD: "sanofi", + DelegationDate: "2015-07-24", + RemovalDate: "", + }, + "sap": { + GTLD: "sap", + DelegationDate: "2015-03-26", + RemovalDate: "", + }, + "sapo": { + GTLD: "sapo", + DelegationDate: "2015-10-29", + RemovalDate: "2018-05-26", + }, + "sarl": { + GTLD: "sarl", + DelegationDate: "2014-08-08", + RemovalDate: "", + }, + "sas": { + GTLD: "sas", + DelegationDate: "2015-12-18", + RemovalDate: "", + }, + "save": { + GTLD: "save", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "saxo": { + GTLD: "saxo", + DelegationDate: "2015-02-10", + RemovalDate: "", + }, + "sb": { + GTLD: "sb", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sbi": { + GTLD: "sbi", + DelegationDate: "2016-04-16", + RemovalDate: "", + }, + "sbs": { + GTLD: "sbs", + DelegationDate: "2015-10-29", + RemovalDate: "", + }, + "sc": { + GTLD: "sc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sca": { + GTLD: "sca", + DelegationDate: "2014-08-14", + RemovalDate: "", + }, + "scb": { + GTLD: "scb", + DelegationDate: "2014-07-11", + RemovalDate: "", + }, + "schaeffler": { + GTLD: "schaeffler", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "schmidt": { + GTLD: "schmidt", + DelegationDate: "2014-07-03", + RemovalDate: "", + }, + "scholarships": { + GTLD: "scholarships", + DelegationDate: "2015-04-02", + RemovalDate: "", + }, + "school": { + GTLD: "school", + DelegationDate: "2015-02-19", + RemovalDate: "", + }, + "schule": { + GTLD: "schule", + DelegationDate: "2014-04-22", + RemovalDate: "", + }, + "schwarz": { + GTLD: "schwarz", + DelegationDate: "2014-12-13", + RemovalDate: "", + }, + "science": { + GTLD: "science", + DelegationDate: "2014-11-15", + RemovalDate: "", + }, + "scjohnson": { + GTLD: "scjohnson", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "scor": { + GTLD: "scor", + DelegationDate: "2015-06-23", + RemovalDate: "2020-05-27", + }, + "scot": { + GTLD: "scot", + DelegationDate: "2014-06-13", + RemovalDate: "", + }, + "sd": { + GTLD: "sd", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "se": { + GTLD: "se", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "search": { + GTLD: "search", + DelegationDate: "2017-06-29", + RemovalDate: "", + }, + "seat": { + GTLD: "seat", + DelegationDate: "2015-04-18", + RemovalDate: "", + }, + "secure": { + GTLD: "secure", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "security": { + GTLD: "security", + DelegationDate: "2015-09-17", + RemovalDate: "", + }, + "seek": { + GTLD: "seek", + DelegationDate: "2015-08-11", + RemovalDate: "", + }, + "select": { + GTLD: "select", + DelegationDate: "2016-01-15", + RemovalDate: "", + }, + "sener": { + GTLD: "sener", + DelegationDate: "2015-05-01", + RemovalDate: "", + }, + "services": { + GTLD: "services", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "ses": { + GTLD: "ses", + DelegationDate: "2016-07-09", + RemovalDate: "", + }, + "seven": { + GTLD: "seven", + DelegationDate: "2015-09-26", + RemovalDate: "", + }, + "sew": { + GTLD: "sew", + DelegationDate: "2014-12-13", + RemovalDate: "", + }, + "sex": { + GTLD: "sex", + DelegationDate: "2015-04-18", + RemovalDate: "", + }, + "sexy": { + GTLD: "sexy", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "sfr": { + GTLD: "sfr", + DelegationDate: "2015-12-01", + RemovalDate: "", + }, + "sg": { + GTLD: "sg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sh": { + GTLD: "sh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "shangrila": { + GTLD: "shangrila", + DelegationDate: "2016-07-02", + RemovalDate: "", + }, + "sharp": { + GTLD: "sharp", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "shaw": { + GTLD: "shaw", + DelegationDate: "2016-03-22", + RemovalDate: "", + }, + "shell": { + GTLD: "shell", + DelegationDate: "2015-12-15", + RemovalDate: "", + }, + "shia": { + GTLD: "shia", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "shiksha": { + GTLD: "shiksha", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "shoes": { + GTLD: "shoes", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "shop": { + GTLD: "shop", + DelegationDate: "2016-05-23", + RemovalDate: "", + }, + "shopping": { + GTLD: "shopping", + DelegationDate: "2016-06-21", + RemovalDate: "", + }, + "shouji": { + GTLD: "shouji", + DelegationDate: "2016-03-30", + RemovalDate: "", + }, + "show": { + GTLD: "show", + DelegationDate: "2015-04-16", + RemovalDate: "", + }, + "showtime": { + GTLD: "showtime", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "shriram": { + GTLD: "shriram", + DelegationDate: "2014-12-30", + RemovalDate: "2020-11-24", + }, + "si": { + GTLD: "si", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "silk": { + GTLD: "silk", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "sina": { + GTLD: "sina", + DelegationDate: "2016-03-30", + RemovalDate: "", + }, + "singles": { + GTLD: "singles", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "site": { + GTLD: "site", + DelegationDate: "2015-03-16", + RemovalDate: "", + }, + "sj": { + GTLD: "sj", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sk": { + GTLD: "sk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ski": { + GTLD: "ski", + DelegationDate: "2015-05-30", + RemovalDate: "", + }, + "skin": { + GTLD: "skin", + DelegationDate: "2016-01-15", + RemovalDate: "", + }, + "sky": { + GTLD: "sky", + DelegationDate: "2014-12-12", + RemovalDate: "", + }, + "skype": { + GTLD: "skype", + DelegationDate: "2015-06-23", + RemovalDate: "", + }, + "sl": { + GTLD: "sl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sling": { + GTLD: "sling", + DelegationDate: "2016-08-10", + RemovalDate: "", + }, + "sm": { + GTLD: "sm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "smart": { + GTLD: "smart", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "smile": { + GTLD: "smile", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "sn": { + GTLD: "sn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sncf": { + GTLD: "sncf", + DelegationDate: "2015-06-03", + RemovalDate: "", + }, + "so": { + GTLD: "so", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "soccer": { + GTLD: "soccer", + DelegationDate: "2015-05-13", + RemovalDate: "", + }, + "social": { + GTLD: "social", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "softbank": { + GTLD: "softbank", + DelegationDate: "2016-01-16", + RemovalDate: "", + }, + "software": { + GTLD: "software", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "sohu": { + GTLD: "sohu", + DelegationDate: "2014-03-25", + RemovalDate: "", + }, + "solar": { + GTLD: "solar", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "solutions": { + GTLD: "solutions", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "song": { + GTLD: "song", + DelegationDate: "2016-02-24", + RemovalDate: "", + }, + "sony": { + GTLD: "sony", + DelegationDate: "2015-04-16", + RemovalDate: "", + }, + "soy": { + GTLD: "soy", + DelegationDate: "2014-04-19", + RemovalDate: "", + }, + "spa": { + GTLD: "spa", + DelegationDate: "2020-10-17", + RemovalDate: "", + }, + "space": { + GTLD: "space", + DelegationDate: "2014-05-30", + RemovalDate: "", + }, + "spiegel": { + GTLD: "spiegel", + DelegationDate: "2014-07-18", + RemovalDate: "2018-12-15", + }, + "sport": { + GTLD: "sport", + DelegationDate: "2018-01-10", + RemovalDate: "", + }, + "spot": { + GTLD: "spot", + DelegationDate: "2016-02-19", + RemovalDate: "", + }, + "spreadbetting": { + GTLD: "spreadbetting", + DelegationDate: "2015-03-13", + RemovalDate: "", + }, + "sr": { + GTLD: "sr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "srl": { + GTLD: "srl", + DelegationDate: "2015-07-24", + RemovalDate: "", + }, + "srt": { + GTLD: "srt", + DelegationDate: "2016-07-28", + RemovalDate: "2019-11-19", + }, + "ss": { + GTLD: "ss", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "st": { + GTLD: "st", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "stada": { + GTLD: "stada", + DelegationDate: "2015-09-13", + RemovalDate: "", + }, + "staples": { + GTLD: "staples", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "star": { + GTLD: "star", + DelegationDate: "2015-12-22", + RemovalDate: "", + }, + "starhub": { + GTLD: "starhub", + DelegationDate: "2015-06-22", + RemovalDate: "2019-08-02", + }, + "statebank": { + GTLD: "statebank", + DelegationDate: "2016-04-16", + RemovalDate: "", + }, + "statefarm": { + GTLD: "statefarm", + DelegationDate: "2015-12-24", + RemovalDate: "", + }, + "statoil": { + GTLD: "statoil", + DelegationDate: "2015-06-19", + RemovalDate: "2018-10-03", + }, + "stc": { + GTLD: "stc", + DelegationDate: "2015-08-29", + RemovalDate: "", + }, + "stcgroup": { + GTLD: "stcgroup", + DelegationDate: "2015-08-28", + RemovalDate: "", + }, + "stockholm": { + GTLD: "stockholm", + DelegationDate: "2015-09-26", + RemovalDate: "", + }, + "storage": { + GTLD: "storage", + DelegationDate: "2015-12-18", + RemovalDate: "", + }, + "store": { + GTLD: "store", + DelegationDate: "2016-02-22", + RemovalDate: "", + }, + "stream": { + GTLD: "stream", + DelegationDate: "2016-03-18", + RemovalDate: "", + }, + "studio": { + GTLD: "studio", + DelegationDate: "2015-07-08", + RemovalDate: "", + }, + "study": { + GTLD: "study", + DelegationDate: "2015-02-25", + RemovalDate: "", + }, + "style": { + GTLD: "style", + DelegationDate: "2015-02-04", + RemovalDate: "", + }, + "su": { + GTLD: "su", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sucks": { + GTLD: "sucks", + DelegationDate: "2015-02-25", + RemovalDate: "", + }, + "supplies": { + GTLD: "supplies", + DelegationDate: "2014-02-25", + RemovalDate: "", + }, + "supply": { + GTLD: "supply", + DelegationDate: "2014-02-21", + RemovalDate: "", + }, + "support": { + GTLD: "support", + DelegationDate: "2013-12-18", + RemovalDate: "", + }, + "surf": { + GTLD: "surf", + DelegationDate: "2014-06-18", + RemovalDate: "", + }, + "surgery": { + GTLD: "surgery", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "suzuki": { + GTLD: "suzuki", + DelegationDate: "2014-07-02", + RemovalDate: "", + }, + "sv": { + GTLD: "sv", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "swatch": { + GTLD: "swatch", + DelegationDate: "2015-06-26", + RemovalDate: "", + }, + "swiftcover": { + GTLD: "swiftcover", + DelegationDate: "2016-07-21", + RemovalDate: "", + }, + "swiss": { + GTLD: "swiss", + DelegationDate: "2015-04-29", + RemovalDate: "", + }, + "sx": { + GTLD: "sx", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sy": { + GTLD: "sy", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "sydney": { + GTLD: "sydney", + DelegationDate: "2014-11-05", + RemovalDate: "", + }, + "symantec": { + GTLD: "symantec", + DelegationDate: "2015-12-03", + RemovalDate: "2020-07-17", + }, + "systems": { + GTLD: "systems", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "sz": { + GTLD: "sz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tab": { + GTLD: "tab", + DelegationDate: "2015-11-13", + RemovalDate: "", + }, + "taipei": { + GTLD: "taipei", + DelegationDate: "2014-10-23", + RemovalDate: "", + }, + "talk": { + GTLD: "talk", + DelegationDate: "2016-03-25", + RemovalDate: "", + }, + "taobao": { + GTLD: "taobao", + DelegationDate: "2016-01-21", + RemovalDate: "", + }, + "target": { + GTLD: "target", + DelegationDate: "2016-08-04", + RemovalDate: "", + }, + "tatamotors": { + GTLD: "tatamotors", + DelegationDate: "2015-07-24", + RemovalDate: "", + }, + "tatar": { + GTLD: "tatar", + DelegationDate: "2014-08-07", + RemovalDate: "", + }, + "tattoo": { + GTLD: "tattoo", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "tax": { + GTLD: "tax", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "taxi": { + GTLD: "taxi", + DelegationDate: "2015-05-07", + RemovalDate: "", + }, + "tc": { + GTLD: "tc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tci": { + GTLD: "tci", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "td": { + GTLD: "td", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tdk": { + GTLD: "tdk", + DelegationDate: "2016-06-07", + RemovalDate: "", + }, + "team": { + GTLD: "team", + DelegationDate: "2015-04-16", + RemovalDate: "", + }, + "tech": { + GTLD: "tech", + DelegationDate: "2015-03-21", + RemovalDate: "", + }, + "technology": { + GTLD: "technology", + DelegationDate: "2013-11-14", + RemovalDate: "", + }, + "tel": { + GTLD: "tel", + DelegationDate: "2007-03-02", + RemovalDate: "", + }, + "telecity": { + GTLD: "telecity", + DelegationDate: "2016-02-25", + RemovalDate: "2018-08-19", + }, + "telefonica": { + GTLD: "telefonica", + DelegationDate: "2015-06-26", + RemovalDate: "2019-12-23", + }, + "temasek": { + GTLD: "temasek", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "tennis": { + GTLD: "tennis", + DelegationDate: "2015-02-04", + RemovalDate: "", + }, + "teva": { + GTLD: "teva", + DelegationDate: "2016-04-13", + RemovalDate: "", + }, + "tf": { + GTLD: "tf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tg": { + GTLD: "tg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "th": { + GTLD: "th", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "thd": { + GTLD: "thd", + DelegationDate: "2015-05-22", + RemovalDate: "", + }, + "theater": { + GTLD: "theater", + DelegationDate: "2015-05-06", + RemovalDate: "", + }, + "theatre": { + GTLD: "theatre", + DelegationDate: "2015-09-13", + RemovalDate: "", + }, + "tiaa": { + GTLD: "tiaa", + DelegationDate: "2016-07-20", + RemovalDate: "", + }, + "tickets": { + GTLD: "tickets", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "tienda": { + GTLD: "tienda", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "tiffany": { + GTLD: "tiffany", + DelegationDate: "2016-01-21", + RemovalDate: "", + }, + "tips": { + GTLD: "tips", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "tires": { + GTLD: "tires", + DelegationDate: "2014-12-18", + RemovalDate: "", + }, + "tirol": { + GTLD: "tirol", + DelegationDate: "2014-06-04", + RemovalDate: "", + }, + "tj": { + GTLD: "tj", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tjmaxx": { + GTLD: "tjmaxx", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "tjx": { + GTLD: "tjx", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "tk": { + GTLD: "tk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tkmaxx": { + GTLD: "tkmaxx", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "tl": { + GTLD: "tl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tm": { + GTLD: "tm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tmall": { + GTLD: "tmall", + DelegationDate: "2016-01-21", + RemovalDate: "", + }, + "tn": { + GTLD: "tn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "to": { + GTLD: "to", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "today": { + GTLD: "today", + DelegationDate: "2013-11-19", + RemovalDate: "", + }, + "tokyo": { + GTLD: "tokyo", + DelegationDate: "2014-01-29", + RemovalDate: "", + }, + "tools": { + GTLD: "tools", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "top": { + GTLD: "top", + DelegationDate: "2014-08-03", + RemovalDate: "", + }, + "toray": { + GTLD: "toray", + DelegationDate: "2015-05-01", + RemovalDate: "", + }, + "toshiba": { + GTLD: "toshiba", + DelegationDate: "2015-02-04", + RemovalDate: "", + }, + "total": { + GTLD: "total", + DelegationDate: "2016-03-09", + RemovalDate: "", + }, + "tours": { + GTLD: "tours", + DelegationDate: "2015-03-24", + RemovalDate: "", + }, + "town": { + GTLD: "town", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "toyota": { + GTLD: "toyota", + DelegationDate: "2015-07-26", + RemovalDate: "", + }, + "toys": { + GTLD: "toys", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "tr": { + GTLD: "tr", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "trade": { + GTLD: "trade", + DelegationDate: "2014-03-19", + RemovalDate: "", + }, + "trading": { + GTLD: "trading", + DelegationDate: "2015-03-13", + RemovalDate: "", + }, + "training": { + GTLD: "training", + DelegationDate: "2013-12-28", + RemovalDate: "", + }, + "travel": { + GTLD: "travel", + DelegationDate: "2005-07-21", + RemovalDate: "", + }, + "travelchannel": { + GTLD: "travelchannel", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "travelers": { + GTLD: "travelers", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "travelersinsurance": { + GTLD: "travelersinsurance", + DelegationDate: "2015-12-15", + RemovalDate: "", + }, + "trust": { + GTLD: "trust", + DelegationDate: "2014-12-06", + RemovalDate: "", + }, + "trv": { + GTLD: "trv", + DelegationDate: "2015-12-11", + RemovalDate: "", + }, + "tt": { + GTLD: "tt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tube": { + GTLD: "tube", + DelegationDate: "2016-01-11", + RemovalDate: "", + }, + "tui": { + GTLD: "tui", + DelegationDate: "2014-09-27", + RemovalDate: "", + }, + "tunes": { + GTLD: "tunes", + DelegationDate: "2016-02-25", + RemovalDate: "", + }, + "tushu": { + GTLD: "tushu", + DelegationDate: "2015-12-14", + RemovalDate: "", + }, + "tv": { + GTLD: "tv", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tvs": { + GTLD: "tvs", + DelegationDate: "2016-02-13", + RemovalDate: "", + }, + "tw": { + GTLD: "tw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "tz": { + GTLD: "tz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ua": { + GTLD: "ua", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ubank": { + GTLD: "ubank", + DelegationDate: "2016-08-18", + RemovalDate: "", + }, + "ubs": { + GTLD: "ubs", + DelegationDate: "2015-07-11", + RemovalDate: "", + }, + "uconnect": { + GTLD: "uconnect", + DelegationDate: "2016-07-28", + RemovalDate: "2019-11-19", + }, + "ug": { + GTLD: "ug", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "uk": { + GTLD: "uk", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "unicom": { + GTLD: "unicom", + DelegationDate: "2016-02-04", + RemovalDate: "", + }, + "university": { + GTLD: "university", + DelegationDate: "2014-04-11", + RemovalDate: "", + }, + "uno": { + GTLD: "uno", + DelegationDate: "2013-11-30", + RemovalDate: "", + }, + "uol": { + GTLD: "uol", + DelegationDate: "2014-08-16", + RemovalDate: "", + }, + "ups": { + GTLD: "ups", + DelegationDate: "2016-05-31", + RemovalDate: "", + }, + "us": { + GTLD: "us", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "uy": { + GTLD: "uy", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "uz": { + GTLD: "uz", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "va": { + GTLD: "va", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "vacations": { + GTLD: "vacations", + DelegationDate: "2014-02-21", + RemovalDate: "", + }, + "vana": { + GTLD: "vana", + DelegationDate: "2015-11-10", + RemovalDate: "", + }, + "vanguard": { + GTLD: "vanguard", + DelegationDate: "2016-08-28", + RemovalDate: "", + }, + "vc": { + GTLD: "vc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "ve": { + GTLD: "ve", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "vegas": { + GTLD: "vegas", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "ventures": { + GTLD: "ventures", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "verisign": { + GTLD: "verisign", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "versicherung": { + GTLD: "versicherung", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "vet": { + GTLD: "vet", + DelegationDate: "2014-05-31", + RemovalDate: "", + }, + "vg": { + GTLD: "vg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "vi": { + GTLD: "vi", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "viajes": { + GTLD: "viajes", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "video": { + GTLD: "video", + DelegationDate: "2014-12-25", + RemovalDate: "", + }, + "vig": { + GTLD: "vig", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "viking": { + GTLD: "viking", + DelegationDate: "2016-02-22", + RemovalDate: "", + }, + "villas": { + GTLD: "villas", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "vin": { + GTLD: "vin", + DelegationDate: "2015-08-05", + RemovalDate: "", + }, + "vip": { + GTLD: "vip", + DelegationDate: "2015-11-25", + RemovalDate: "", + }, + "virgin": { + GTLD: "virgin", + DelegationDate: "2015-10-07", + RemovalDate: "", + }, + "visa": { + GTLD: "visa", + DelegationDate: "2016-07-28", + RemovalDate: "", + }, + "vision": { + GTLD: "vision", + DelegationDate: "2014-02-11", + RemovalDate: "", + }, + "vista": { + GTLD: "vista", + DelegationDate: "2015-06-22", + RemovalDate: "2018-09-13", + }, + "vistaprint": { + GTLD: "vistaprint", + DelegationDate: "2015-06-22", + RemovalDate: "2020-03-13", + }, + "viva": { + GTLD: "viva", + DelegationDate: "2015-08-28", + RemovalDate: "", + }, + "vivo": { + GTLD: "vivo", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "vlaanderen": { + GTLD: "vlaanderen", + DelegationDate: "2014-06-18", + RemovalDate: "", + }, + "vn": { + GTLD: "vn", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "vodka": { + GTLD: "vodka", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "volkswagen": { + GTLD: "volkswagen", + DelegationDate: "2016-01-09", + RemovalDate: "", + }, + "volvo": { + GTLD: "volvo", + DelegationDate: "2016-10-24", + RemovalDate: "", + }, + "vote": { + GTLD: "vote", + DelegationDate: "2014-03-02", + RemovalDate: "", + }, + "voting": { + GTLD: "voting", + DelegationDate: "2014-01-29", + RemovalDate: "", + }, + "voto": { + GTLD: "voto", + DelegationDate: "2014-03-02", + RemovalDate: "", + }, + "voyage": { + GTLD: "voyage", + DelegationDate: "2013-11-06", + RemovalDate: "", + }, + "vu": { + GTLD: "vu", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "vuelos": { + GTLD: "vuelos", + DelegationDate: "2016-03-02", + RemovalDate: "", + }, + "wales": { + GTLD: "wales", + DelegationDate: "2014-08-07", + RemovalDate: "", + }, + "walmart": { + GTLD: "walmart", + DelegationDate: "2016-08-18", + RemovalDate: "", + }, + "walter": { + GTLD: "walter", + DelegationDate: "2015-05-27", + RemovalDate: "", + }, + "wang": { + GTLD: "wang", + DelegationDate: "2014-01-03", + RemovalDate: "", + }, + "wanggou": { + GTLD: "wanggou", + DelegationDate: "2015-12-15", + RemovalDate: "", + }, + "warman": { + GTLD: "warman", + DelegationDate: "2016-05-03", + RemovalDate: "2019-11-19", + }, + "watch": { + GTLD: "watch", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "watches": { + GTLD: "watches", + DelegationDate: "2015-12-14", + RemovalDate: "", + }, + "weather": { + GTLD: "weather", + DelegationDate: "2016-01-12", + RemovalDate: "", + }, + "weatherchannel": { + GTLD: "weatherchannel", + DelegationDate: "2016-01-28", + RemovalDate: "", + }, + "webcam": { + GTLD: "webcam", + DelegationDate: "2014-03-19", + RemovalDate: "", + }, + "weber": { + GTLD: "weber", + DelegationDate: "2015-12-22", + RemovalDate: "", + }, + "website": { + GTLD: "website", + DelegationDate: "2014-05-30", + RemovalDate: "", + }, + "wed": { + GTLD: "wed", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "wedding": { + GTLD: "wedding", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "weibo": { + GTLD: "weibo", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "weir": { + GTLD: "weir", + DelegationDate: "2015-04-17", + RemovalDate: "", + }, + "wf": { + GTLD: "wf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "whoswho": { + GTLD: "whoswho", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "wien": { + GTLD: "wien", + DelegationDate: "2014-01-03", + RemovalDate: "", + }, + "wiki": { + GTLD: "wiki", + DelegationDate: "2014-02-19", + RemovalDate: "", + }, + "williamhill": { + GTLD: "williamhill", + DelegationDate: "2014-07-27", + RemovalDate: "", + }, + "win": { + GTLD: "win", + DelegationDate: "2015-03-25", + RemovalDate: "", + }, + "windows": { + GTLD: "windows", + DelegationDate: "2015-06-10", + RemovalDate: "", + }, + "wine": { + GTLD: "wine", + DelegationDate: "2015-08-05", + RemovalDate: "", + }, + "winners": { + GTLD: "winners", + DelegationDate: "2016-07-15", + RemovalDate: "", + }, + "wme": { + GTLD: "wme", + DelegationDate: "2014-09-10", + RemovalDate: "", + }, + "wolterskluwer": { + GTLD: "wolterskluwer", + DelegationDate: "2016-02-11", + RemovalDate: "", + }, + "woodside": { + GTLD: "woodside", + DelegationDate: "2016-06-23", + RemovalDate: "", + }, + "work": { + GTLD: "work", + DelegationDate: "2014-09-23", + RemovalDate: "", + }, + "works": { + GTLD: "works", + DelegationDate: "2014-01-23", + RemovalDate: "", + }, + "world": { + GTLD: "world", + DelegationDate: "2014-09-19", + RemovalDate: "", + }, + "wow": { + GTLD: "wow", + DelegationDate: "2016-09-26", + RemovalDate: "", + }, + "ws": { + GTLD: "ws", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "wtc": { + GTLD: "wtc", + DelegationDate: "2014-04-29", + RemovalDate: "", + }, + "wtf": { + GTLD: "wtf", + DelegationDate: "2014-04-23", + RemovalDate: "", + }, + "xbox": { + GTLD: "xbox", + DelegationDate: "2015-06-04", + RemovalDate: "", + }, + "xerox": { + GTLD: "xerox", + DelegationDate: "2015-04-16", + RemovalDate: "", + }, + "xfinity": { + GTLD: "xfinity", + DelegationDate: "2016-07-07", + RemovalDate: "", + }, + "xihuan": { + GTLD: "xihuan", + DelegationDate: "2016-03-30", + RemovalDate: "", + }, + "xin": { + GTLD: "xin", + DelegationDate: "2015-03-07", + RemovalDate: "", + }, + "xn--11b4c3d": { + GTLD: "xn--11b4c3d", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--1ck2e1b": { + GTLD: "xn--1ck2e1b", + DelegationDate: "2016-02-19", + RemovalDate: "", + }, + "xn--1qqw23a": { + GTLD: "xn--1qqw23a", + DelegationDate: "2014-08-14", + RemovalDate: "", + }, + "xn--2scrj9c": { + GTLD: "xn--2scrj9c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--30rr7y": { + GTLD: "xn--30rr7y", + DelegationDate: "2015-03-31", + RemovalDate: "", + }, + "xn--3bst00m": { + GTLD: "xn--3bst00m", + DelegationDate: "2014-01-03", + RemovalDate: "", + }, + "xn--3ds443g": { + GTLD: "xn--3ds443g", + DelegationDate: "2014-01-02", + RemovalDate: "", + }, + "xn--3e0b707e": { + GTLD: "xn--3e0b707e", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--3hcrj9c": { + GTLD: "xn--3hcrj9c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--3oq18vl8pn36a": { + GTLD: "xn--3oq18vl8pn36a", + DelegationDate: "2016-08-16", + RemovalDate: "", + }, + "xn--3pxu8k": { + GTLD: "xn--3pxu8k", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--42c2d9a": { + GTLD: "xn--42c2d9a", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--45br5cyl": { + GTLD: "xn--45br5cyl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--45brj9c": { + GTLD: "xn--45brj9c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--45q11c": { + GTLD: "xn--45q11c", + DelegationDate: "2014-11-17", + RemovalDate: "", + }, + "xn--4gbrim": { + GTLD: "xn--4gbrim", + DelegationDate: "2014-05-28", + RemovalDate: "", + }, + "xn--54b7fta0cc": { + GTLD: "xn--54b7fta0cc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--55qw42g": { + GTLD: "xn--55qw42g", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "xn--55qx5d": { + GTLD: "xn--55qx5d", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "xn--5su34j936bgsg": { + GTLD: "xn--5su34j936bgsg", + DelegationDate: "2016-07-02", + RemovalDate: "", + }, + "xn--5tzm5g": { + GTLD: "xn--5tzm5g", + DelegationDate: "2016-04-17", + RemovalDate: "", + }, + "xn--6frz82g": { + GTLD: "xn--6frz82g", + DelegationDate: "2014-02-05", + RemovalDate: "", + }, + "xn--6qq986b3xl": { + GTLD: "xn--6qq986b3xl", + DelegationDate: "2014-01-03", + RemovalDate: "", + }, + "xn--80adxhks": { + GTLD: "xn--80adxhks", + DelegationDate: "2014-04-24", + RemovalDate: "", + }, + "xn--80ao21a": { + GTLD: "xn--80ao21a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--80aqecdr1a": { + GTLD: "xn--80aqecdr1a", + DelegationDate: "2016-12-01", + RemovalDate: "", + }, + "xn--80asehdb": { + GTLD: "xn--80asehdb", + DelegationDate: "2013-10-23", + RemovalDate: "", + }, + "xn--80aswg": { + GTLD: "xn--80aswg", + DelegationDate: "2013-10-23", + RemovalDate: "", + }, + "xn--8y0a063a": { + GTLD: "xn--8y0a063a", + DelegationDate: "2016-02-06", + RemovalDate: "", + }, + "xn--90a3ac": { + GTLD: "xn--90a3ac", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--90ae": { + GTLD: "xn--90ae", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--90ais": { + GTLD: "xn--90ais", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--9dbq2a": { + GTLD: "xn--9dbq2a", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--9et52u": { + GTLD: "xn--9et52u", + DelegationDate: "2015-03-27", + RemovalDate: "", + }, + "xn--9krt00a": { + GTLD: "xn--9krt00a", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "xn--b4w605ferd": { + GTLD: "xn--b4w605ferd", + DelegationDate: "2015-01-24", + RemovalDate: "", + }, + "xn--bck1b9a5dre4c": { + GTLD: "xn--bck1b9a5dre4c", + DelegationDate: "2016-02-21", + RemovalDate: "", + }, + "xn--c1avg": { + GTLD: "xn--c1avg", + DelegationDate: "2014-03-05", + RemovalDate: "", + }, + "xn--c2br7g": { + GTLD: "xn--c2br7g", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--cck2b3b": { + GTLD: "xn--cck2b3b", + DelegationDate: "2016-02-19", + RemovalDate: "", + }, + "xn--cckwcxetd": { + GTLD: "xn--cckwcxetd", + DelegationDate: "2020-06-02", + RemovalDate: "", + }, + "xn--cg4bki": { + GTLD: "xn--cg4bki", + DelegationDate: "2014-02-21", + RemovalDate: "", + }, + "xn--clchc0ea0b2g2a9gcd": { + GTLD: "xn--clchc0ea0b2g2a9gcd", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--czr694b": { + GTLD: "xn--czr694b", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "xn--czrs0t": { + GTLD: "xn--czrs0t", + DelegationDate: "2014-12-06", + RemovalDate: "", + }, + "xn--czru2d": { + GTLD: "xn--czru2d", + DelegationDate: "2014-03-31", + RemovalDate: "", + }, + "xn--d1acj3b": { + GTLD: "xn--d1acj3b", + DelegationDate: "2014-02-26", + RemovalDate: "", + }, + "xn--d1alf": { + GTLD: "xn--d1alf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--e1a4c": { + GTLD: "xn--e1a4c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--eckvdtc9d": { + GTLD: "xn--eckvdtc9d", + DelegationDate: "2015-12-14", + RemovalDate: "", + }, + "xn--efvy88h": { + GTLD: "xn--efvy88h", + DelegationDate: "2015-08-24", + RemovalDate: "", + }, + "xn--estv75g": { + GTLD: "xn--estv75g", + DelegationDate: "2015-05-07", + RemovalDate: "2020-04-01", + }, + "xn--fct429k": { + GTLD: "xn--fct429k", + DelegationDate: "2016-03-25", + RemovalDate: "", + }, + "xn--fhbei": { + GTLD: "xn--fhbei", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--fiq228c5hs": { + GTLD: "xn--fiq228c5hs", + DelegationDate: "2014-01-03", + RemovalDate: "", + }, + "xn--fiq64b": { + GTLD: "xn--fiq64b", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "xn--fiqs8s": { + GTLD: "xn--fiqs8s", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--fiqz9s": { + GTLD: "xn--fiqz9s", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--fjq720a": { + GTLD: "xn--fjq720a", + DelegationDate: "2015-05-09", + RemovalDate: "", + }, + "xn--flw351e": { + GTLD: "xn--flw351e", + DelegationDate: "2014-11-20", + RemovalDate: "", + }, + "xn--fpcrj9c3d": { + GTLD: "xn--fpcrj9c3d", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--fzc2c9e2c": { + GTLD: "xn--fzc2c9e2c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--fzys8d69uvgm": { + GTLD: "xn--fzys8d69uvgm", + DelegationDate: "2016-05-11", + RemovalDate: "", + }, + "xn--g2xx48c": { + GTLD: "xn--g2xx48c", + DelegationDate: "2016-01-16", + RemovalDate: "", + }, + "xn--gckr3f0f": { + GTLD: "xn--gckr3f0f", + DelegationDate: "2016-02-19", + RemovalDate: "", + }, + "xn--gecrj9c": { + GTLD: "xn--gecrj9c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--gk3at1e": { + GTLD: "xn--gk3at1e", + DelegationDate: "2016-09-30", + RemovalDate: "", + }, + "xn--h2breg3eve": { + GTLD: "xn--h2breg3eve", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--h2brj9c": { + GTLD: "xn--h2brj9c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--h2brj9c8c": { + GTLD: "xn--h2brj9c8c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--hxt814e": { + GTLD: "xn--hxt814e", + DelegationDate: "2014-12-02", + RemovalDate: "", + }, + "xn--i1b6b1a6a2e": { + GTLD: "xn--i1b6b1a6a2e", + DelegationDate: "2014-03-09", + RemovalDate: "", + }, + "xn--imr513n": { + GTLD: "xn--imr513n", + DelegationDate: "2015-05-30", + RemovalDate: "", + }, + "xn--io0a7i": { + GTLD: "xn--io0a7i", + DelegationDate: "2014-01-18", + RemovalDate: "", + }, + "xn--j1aef": { + GTLD: "xn--j1aef", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--j1amh": { + GTLD: "xn--j1amh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--j6w193g": { + GTLD: "xn--j6w193g", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--jlq480n2rg": { + GTLD: "xn--jlq480n2rg", + DelegationDate: "2020-06-02", + RemovalDate: "", + }, + "xn--jlq61u9w7b": { + GTLD: "xn--jlq61u9w7b", + DelegationDate: "2015-12-18", + RemovalDate: "", + }, + "xn--jvr189m": { + GTLD: "xn--jvr189m", + DelegationDate: "2016-02-22", + RemovalDate: "", + }, + "xn--kcrx77d1x4a": { + GTLD: "xn--kcrx77d1x4a", + DelegationDate: "2015-04-07", + RemovalDate: "", + }, + "xn--kprw13d": { + GTLD: "xn--kprw13d", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--kpry57d": { + GTLD: "xn--kpry57d", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--kpu716f": { + GTLD: "xn--kpu716f", + DelegationDate: "2015-12-15", + RemovalDate: "2020-06-26", + }, + "xn--kput3i": { + GTLD: "xn--kput3i", + DelegationDate: "2014-06-17", + RemovalDate: "", + }, + "xn--l1acc": { + GTLD: "xn--l1acc", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--lgbbat1ad8j": { + GTLD: "xn--lgbbat1ad8j", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgb9awbf": { + GTLD: "xn--mgb9awbf", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgba3a3ejt": { + GTLD: "xn--mgba3a3ejt", + DelegationDate: "2015-10-15", + RemovalDate: "", + }, + "xn--mgba3a4f16a": { + GTLD: "xn--mgba3a4f16a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgba7c0bbn0a": { + GTLD: "xn--mgba7c0bbn0a", + DelegationDate: "2016-05-03", + RemovalDate: "", + }, + "xn--mgbaakc7dvf": { + GTLD: "xn--mgbaakc7dvf", + DelegationDate: "2017-06-10", + RemovalDate: "", + }, + "xn--mgbaam7a8h": { + GTLD: "xn--mgbaam7a8h", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbab2bd": { + GTLD: "xn--mgbab2bd", + DelegationDate: "2014-02-18", + RemovalDate: "", + }, + "xn--mgbah1a3hjkrd": { + GTLD: "xn--mgbah1a3hjkrd", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbai9azgqp6j": { + GTLD: "xn--mgbai9azgqp6j", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbayh7gpa": { + GTLD: "xn--mgbayh7gpa", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbb9fbpob": { + GTLD: "xn--mgbb9fbpob", + DelegationDate: "2015-12-23", + RemovalDate: "2019-09-09", + }, + "xn--mgbbh1a": { + GTLD: "xn--mgbbh1a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbbh1a71e": { + GTLD: "xn--mgbbh1a71e", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbc0a9azcg": { + GTLD: "xn--mgbc0a9azcg", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbca7dzdo": { + GTLD: "xn--mgbca7dzdo", + DelegationDate: "2016-04-06", + RemovalDate: "", + }, + "xn--mgbcpq6gpa1a": { + GTLD: "xn--mgbcpq6gpa1a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgberp4a5d4ar": { + GTLD: "xn--mgberp4a5d4ar", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbgu82a": { + GTLD: "xn--mgbgu82a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbi4ecexp": { + GTLD: "xn--mgbi4ecexp", + DelegationDate: "2016-12-01", + RemovalDate: "", + }, + "xn--mgbpl2fh": { + GTLD: "xn--mgbpl2fh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbt3dhd": { + GTLD: "xn--mgbt3dhd", + DelegationDate: "2015-12-07", + RemovalDate: "", + }, + "xn--mgbtx2b": { + GTLD: "xn--mgbtx2b", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mgbx4cd0ab": { + GTLD: "xn--mgbx4cd0ab", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mix891f": { + GTLD: "xn--mix891f", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--mk1bu44c": { + GTLD: "xn--mk1bu44c", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--mxtq1m": { + GTLD: "xn--mxtq1m", + DelegationDate: "2015-03-03", + RemovalDate: "", + }, + "xn--ngbc5azd": { + GTLD: "xn--ngbc5azd", + DelegationDate: "2013-10-23", + RemovalDate: "", + }, + "xn--ngbe9e0a": { + GTLD: "xn--ngbe9e0a", + DelegationDate: "2015-12-15", + RemovalDate: "", + }, + "xn--ngbrx": { + GTLD: "xn--ngbrx", + DelegationDate: "2017-05-23", + RemovalDate: "", + }, + "xn--node": { + GTLD: "xn--node", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--nqv7f": { + GTLD: "xn--nqv7f", + DelegationDate: "2014-03-09", + RemovalDate: "", + }, + "xn--nqv7fs00ema": { + GTLD: "xn--nqv7fs00ema", + DelegationDate: "2014-03-09", + RemovalDate: "", + }, + "xn--nyqy26a": { + GTLD: "xn--nyqy26a", + DelegationDate: "2015-04-02", + RemovalDate: "", + }, + "xn--o3cw4h": { + GTLD: "xn--o3cw4h", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--ogbpf8fl": { + GTLD: "xn--ogbpf8fl", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--otu796d": { + GTLD: "xn--otu796d", + DelegationDate: "2018-01-24", + RemovalDate: "", + }, + "xn--p1acf": { + GTLD: "xn--p1acf", + DelegationDate: "2014-09-27", + RemovalDate: "", + }, + "xn--p1ai": { + GTLD: "xn--p1ai", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--pbt977c": { + GTLD: "xn--pbt977c", + DelegationDate: "2015-12-15", + RemovalDate: "2020-06-26", + }, + "xn--pgbs0dh": { + GTLD: "xn--pgbs0dh", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--pssy2u": { + GTLD: "xn--pssy2u", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--q7ce6a": { + GTLD: "xn--q7ce6a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--q9jyb4c": { + GTLD: "xn--q9jyb4c", + DelegationDate: "2013-11-23", + RemovalDate: "", + }, + "xn--qcka1pmc": { + GTLD: "xn--qcka1pmc", + DelegationDate: "2014-11-20", + RemovalDate: "", + }, + "xn--qxa6a": { + GTLD: "xn--qxa6a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--qxam": { + GTLD: "xn--qxam", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--rhqv96g": { + GTLD: "xn--rhqv96g", + DelegationDate: "2014-03-12", + RemovalDate: "", + }, + "xn--rovu88b": { + GTLD: "xn--rovu88b", + DelegationDate: "2016-02-19", + RemovalDate: "", + }, + "xn--rvc1e0am3e": { + GTLD: "xn--rvc1e0am3e", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--s9brj9c": { + GTLD: "xn--s9brj9c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--ses554g": { + GTLD: "xn--ses554g", + DelegationDate: "2014-04-10", + RemovalDate: "", + }, + "xn--t60b56a": { + GTLD: "xn--t60b56a", + DelegationDate: "2015-07-28", + RemovalDate: "", + }, + "xn--tckwe": { + GTLD: "xn--tckwe", + DelegationDate: "2015-07-29", + RemovalDate: "", + }, + "xn--tiq49xqyj": { + GTLD: "xn--tiq49xqyj", + DelegationDate: "2016-12-01", + RemovalDate: "", + }, + "xn--unup4y": { + GTLD: "xn--unup4y", + DelegationDate: "2013-10-23", + RemovalDate: "", + }, + "xn--vermgensberater-ctb": { + GTLD: "xn--vermgensberater-ctb", + DelegationDate: "2014-09-27", + RemovalDate: "", + }, + "xn--vermgensberatung-pwb": { + GTLD: "xn--vermgensberatung-pwb", + DelegationDate: "2014-09-27", + RemovalDate: "", + }, + "xn--vhquv": { + GTLD: "xn--vhquv", + DelegationDate: "2014-08-22", + RemovalDate: "", + }, + "xn--vuq861b": { + GTLD: "xn--vuq861b", + DelegationDate: "2015-03-18", + RemovalDate: "", + }, + "xn--w4r85el8fhu5dnra": { + GTLD: "xn--w4r85el8fhu5dnra", + DelegationDate: "2016-03-05", + RemovalDate: "", + }, + "xn--w4rs40l": { + GTLD: "xn--w4rs40l", + DelegationDate: "2016-05-16", + RemovalDate: "", + }, + "xn--wgbh1c": { + GTLD: "xn--wgbh1c", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--wgbl6a": { + GTLD: "xn--wgbl6a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--xhq521b": { + GTLD: "xn--xhq521b", + DelegationDate: "2014-08-14", + RemovalDate: "", + }, + "xn--xkc2al3hye2a": { + GTLD: "xn--xkc2al3hye2a", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--xkc2dl3a5ee0h": { + GTLD: "xn--xkc2dl3a5ee0h", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--y9a3aq": { + GTLD: "xn--y9a3aq", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--yfro4i67o": { + GTLD: "xn--yfro4i67o", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--ygbi2ammx": { + GTLD: "xn--ygbi2ammx", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "xn--zfr164b": { + GTLD: "xn--zfr164b", + DelegationDate: "2013-12-17", + RemovalDate: "", + }, + "xperia": { + GTLD: "xperia", + DelegationDate: "2015-08-05", + RemovalDate: "2018-07-20", + }, + "xxx": { + GTLD: "xxx", + DelegationDate: "2011-04-15", + RemovalDate: "", + }, + "xyz": { + GTLD: "xyz", + DelegationDate: "2014-02-19", + RemovalDate: "", + }, + "yachts": { + GTLD: "yachts", + DelegationDate: "2014-05-22", + RemovalDate: "", + }, + "yahoo": { + GTLD: "yahoo", + DelegationDate: "2016-02-13", + RemovalDate: "", + }, + "yamaxun": { + GTLD: "yamaxun", + DelegationDate: "2015-10-07", + RemovalDate: "", + }, + "yandex": { + GTLD: "yandex", + DelegationDate: "2014-07-18", + RemovalDate: "", + }, + "ye": { + GTLD: "ye", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "yodobashi": { + GTLD: "yodobashi", + DelegationDate: "2015-02-19", + RemovalDate: "", + }, + "yoga": { + GTLD: "yoga", + DelegationDate: "2014-10-15", + RemovalDate: "", + }, + "yokohama": { + GTLD: "yokohama", + DelegationDate: "2014-04-03", + RemovalDate: "", + }, + "you": { + GTLD: "you", + DelegationDate: "2016-03-25", + RemovalDate: "", + }, + "youtube": { + GTLD: "youtube", + DelegationDate: "2014-08-29", + RemovalDate: "", + }, + "yt": { + GTLD: "yt", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "yun": { + GTLD: "yun", + DelegationDate: "2016-03-30", + RemovalDate: "", + }, + "za": { + GTLD: "za", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "zappos": { + GTLD: "zappos", + DelegationDate: "2016-06-02", + RemovalDate: "", + }, + "zara": { + GTLD: "zara", + DelegationDate: "2015-10-27", + RemovalDate: "", + }, + "zero": { + GTLD: "zero", + DelegationDate: "2015-12-05", + RemovalDate: "", + }, + "zip": { + GTLD: "zip", + DelegationDate: "2014-09-15", + RemovalDate: "", + }, + "zippo": { + GTLD: "zippo", + DelegationDate: "2016-07-02", + RemovalDate: "2019-02-15", + }, + "zm": { + GTLD: "zm", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + "zone": { + GTLD: "zone", + DelegationDate: "2014-01-14", + RemovalDate: "", + }, + "zuerich": { + GTLD: "zuerich", + DelegationDate: "2014-12-25", + RemovalDate: "", + }, + "zw": { + GTLD: "zw", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, + // .onion is a special case and not a general gTLD. However, it is allowed in + // some circumstances in the web PKI so the Zlint gtldMap includes it with + // a delegationDate based on the CABF ballot to allow EV issuance for .onion + // domains: https://cabforum.org/2015/02/18/ballot-144-validation-rules-dot-onion-names/ + "onion": { + GTLD: "onion", + DelegationDate: "2015-02-18", + RemovalDate: "", + }, +} diff --git a/vendor/github.com/zmap/zlint/v3/util/ip.go b/vendor/github.com/zmap/zlint/v3/util/ip.go new file mode 100644 index 0000000000..c171eb4ca2 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/ip.go @@ -0,0 +1,127 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// contains helper functions for ip address lints + +package util + +import ( + "fmt" + "net" +) + +type subnetCategory int + +const ( + privateUse subnetCategory = iota + sharedAddressSpace + benchmarking + documentation + reserved + protocolAssignment + as112 + amt + orchidV2 + _ // deprecated: lisp + thisHostOnThisNetwork + translatableAddress6to4 + translatableAddress4to6 + dummyAddress + portControlProtocolAnycast + traversalUsingRelaysAroundNATAnycast + nat64DNS64Discovery + limitedBroadcast + discardOnly + teredo + uniqueLocal + linkLocalUnicast + ianaReservedForFutureUse + ianaReservedMulticast +) + +var reservedNetworks []*net.IPNet + +// IsIANAReserved checks IP validity as per IANA reserved IPs +// IPv4 +// https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml +// https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml +// IPv6 +// https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml +// https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml +func IsIANAReserved(ip net.IP) bool { + if !ip.IsGlobalUnicast() { + return true + } + + for _, network := range reservedNetworks { + if network.Contains(ip) { + return true + } + } + + return false +} + +// IntersectsIANAReserved checks if a CIDR intersects any IANA reserved CIDRs +func IntersectsIANAReserved(net net.IPNet) bool { + if !net.IP.IsGlobalUnicast() { + return true + } + for _, reserved := range reservedNetworks { + if reserved.Contains(net.IP) || net.Contains(reserved.IP) { + return true + } + } + return false +} + +func init() { + var networks = map[subnetCategory][]string{ + privateUse: {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"}, + sharedAddressSpace: {"100.64.0.0/10"}, + benchmarking: {"198.18.0.0/15", "2001:2::/48"}, + documentation: {"192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24", "2001:db8::/32"}, + reserved: {"240.0.0.0/4", "0400::/6", "0800::/5", "1000::/4", "4000::/3", "6000::/3", "8000::/3", "a000::/3", "c000::/3", "e000::/4", "f000::/5", "f800::/6", "fe00::/9"}, // https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml + protocolAssignment: {"192.0.0.0/24", "2001::/23"}, // 192.0.0.0/24 contains 192.0.0.0/29 - IPv4 Service Continuity Prefix + as112: {"192.31.196.0/24", "192.175.48.0/24", "2001:4:112::/48", "2620:4f:8000::/48"}, + amt: {"192.52.193.0/24", "2001:3::/32"}, + orchidV2: {"2001:20::/28"}, + thisHostOnThisNetwork: {"0.0.0.0/8"}, + translatableAddress4to6: {"2002::/16"}, + translatableAddress6to4: {"64:ff9b::/96", "64:ff9b:1::/48"}, + dummyAddress: {"192.0.0.8/32"}, + portControlProtocolAnycast: {"192.0.0.9/32", "2001:1::1/128"}, + traversalUsingRelaysAroundNATAnycast: {"192.0.0.10/32", "2001:1::2/128"}, + nat64DNS64Discovery: {"192.0.0.170/32", "192.0.0.171/32"}, + limitedBroadcast: {"255.255.255.255/32"}, + discardOnly: {"100::/64"}, + teredo: {"2001::/32"}, + uniqueLocal: {"fc00::/7"}, + linkLocalUnicast: {"fe80::/10", "169.254.0.0/16"}, // this range is covered by ip.IsLinkLocalUnicast(), which is in turn called by net.IP.IsGlobalUnicast(ip) + ianaReservedForFutureUse: {"255.0.0.0/8", "254.0.0.0/8", "253.0.0.0/8", "252.0.0.0/8", "251.0.0.0/8", "250.0.0.0/8", "249.0.0.0/8", "248.0.0.0/8", "247.0.0.0/8", "246.0.0.0/8", "245.0.0.0/8", "244.0.0.0/8", "243.0.0.0/8", "242.0.0.0/8", "241.0.0.0/8", "240.0.0.0/8"}, + ianaReservedMulticast: {"239.0.0.0/8", "238.0.0.0/8", "237.0.0.0/8", "236.0.0.0/8", "235.0.0.0/8", "234.0.0.0/8", "233.0.0.0/8", "232.0.0.0/8", "231.0.0.0/8", "230.0.0.0/8", "229.0.0.0/8", "228.0.0.0/8", "227.0.0.0/8", "226.0.0.0/8", "225.0.0.0/8", "224.0.0.0/8", "ff00::/8"}, // this range is covered by ip.IsMulticast() call, which is in turn called by net.IP.IsGlobalUnicast(ip) + } + + for _, netList := range networks { + for _, network := range netList { + var ipNet *net.IPNet + var err error + + if _, ipNet, err = net.ParseCIDR(network); err != nil { + panic(fmt.Sprintf("unexpected internal network value provided: %s", err.Error())) + } + reservedNetworks = append(reservedNetworks, ipNet) + } + } +} diff --git a/vendor/github.com/zmap/zlint/v3/util/ku.go b/vendor/github.com/zmap/zlint/v3/util/ku.go new file mode 100644 index 0000000000..31a828fb4e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/ku.go @@ -0,0 +1,18 @@ +package util + +import "github.com/zmap/zcrypto/x509" + +var ( + // KeyUsageToString maps an x509.KeyUsage bitmask to its name. + KeyUsageToString = map[x509.KeyUsage]string{ + x509.KeyUsageDigitalSignature: "KeyUsageDigitalSignature", + x509.KeyUsageContentCommitment: "KeyUsageContentCommitment", + x509.KeyUsageKeyEncipherment: "KeyUsageKeyEncipherment", + x509.KeyUsageDataEncipherment: "KeyUsageDataEncipherment", + x509.KeyUsageKeyAgreement: "KeyUsageKeyAgreement", + x509.KeyUsageCertSign: "KeyUsageCertSign", + x509.KeyUsageCRLSign: "KeyUsageCRLSign", + x509.KeyUsageEncipherOnly: "KeyUsageEncipherOnly", + x509.KeyUsageDecipherOnly: "KeyUsageDecipherOnly", + } +) diff --git a/vendor/github.com/zmap/zlint/v3/util/names.go b/vendor/github.com/zmap/zlint/v3/util/names.go new file mode 100644 index 0000000000..f8e4936f18 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/names.go @@ -0,0 +1,64 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "encoding/asn1" + + "github.com/zmap/zcrypto/x509/pkix" +) + +type empty struct{} + +var nameAttributePrefix = asn1.ObjectIdentifier{2, 5, 4} +var nameAttributeLeaves = map[int]empty{ + // Name attributes defined in RFC 5280 appendix A + 3: {}, // id-at-commonName AttributeType ::= { id-at 3 } + 4: {}, // id-at-surname AttributeType ::= { id-at 4 } + 5: {}, // id-at-serialNumber AttributeType ::= { id-at 5 } + 6: {}, // id-at-countryName AttributeType ::= { id-at 6 } + 7: {}, // id-at-localityName AttributeType ::= { id-at 7 } + 8: {}, // id-at-stateOrProvinceName AttributeType ::= { id-at 8 } + 10: {}, // id-at-organizationName AttributeType ::= { id-at 10 } + 11: {}, // id-at-organizationalUnitName AttributeType ::= { id-at 11 } + 12: {}, // id-at-title AttributeType ::= { id-at 12 } + 41: {}, // id-at-name AttributeType ::= { id-at 41 } + 42: {}, // id-at-givenName AttributeType ::= { id-at 42 } + 43: {}, // id-at-initials AttributeType ::= { id-at 43 } + 44: {}, // id-at-generationQualifier AttributeType ::= { id-at 44 } + 46: {}, // id-at-dnQualifier AttributeType ::= { id-at 46 } + + // Name attributes not present in RFC 5280, but appeared in Go's crypto/x509/pkix.go + 9: {}, // id-at-streetName AttributeType ::= { id-at 9 } + 17: {}, // id-at-postalCodeName AttributeType ::= { id-at 17 } +} + +// IsNameAttribute returns true if the given ObjectIdentifier corresponds with +// the type of any name attribute for PKIX. +func IsNameAttribute(oid asn1.ObjectIdentifier) bool { + if len(oid) != 4 { + return false + } + if !nameAttributePrefix.Equal(oid[0:3]) { + return false + } + _, ok := nameAttributeLeaves[oid[3]] + return ok +} + +func NotAllNameFieldsAreEmpty(name *pkix.Name) bool { + //Return true if at least one field is non-empty + return len(name.Names) >= 1 +} diff --git a/vendor/github.com/zmap/zlint/v3/util/oid.go b/vendor/github.com/zmap/zlint/v3/util/oid.go new file mode 100644 index 0000000000..652bd60d23 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/oid.go @@ -0,0 +1,184 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "encoding/asn1" + "errors" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" +) + +var ( + //extension OIDs + AiaOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 1} // Authority Information Access + AuthkeyOID = asn1.ObjectIdentifier{2, 5, 29, 35} // Authority Key Identifier + BasicConstOID = asn1.ObjectIdentifier{2, 5, 29, 19} // Basic Constraints + CertPolicyOID = asn1.ObjectIdentifier{2, 5, 29, 32} // Certificate Policies + CrlDistOID = asn1.ObjectIdentifier{2, 5, 29, 31} // CRL Distribution Points + CtPoisonOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3} // CT Poison + EkuSynOid = asn1.ObjectIdentifier{2, 5, 29, 37} // Extended Key Usage Syntax + FreshCRLOID = asn1.ObjectIdentifier{2, 5, 29, 46} // Freshest CRL + InhibitAnyPolicyOID = asn1.ObjectIdentifier{2, 5, 29, 54} // Inhibit Any Policy + IssuerAlternateNameOID = asn1.ObjectIdentifier{2, 5, 29, 18} // Issuer Alt Name + KeyUsageOID = asn1.ObjectIdentifier{2, 5, 29, 15} // Key Usage + LogoTypeOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 12} // Logo Type Ext + NameConstOID = asn1.ObjectIdentifier{2, 5, 29, 30} // Name Constraints + OscpNoCheckOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5} // OSCP No Check + PolicyConstOID = asn1.ObjectIdentifier{2, 5, 29, 36} // Policy Constraints + PolicyMapOID = asn1.ObjectIdentifier{2, 5, 29, 33} // Policy Mappings + PrivKeyUsageOID = asn1.ObjectIdentifier{2, 5, 29, 16} // Private Key Usage Period + QcStateOid = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3} // QC Statements + TimestampOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2} // Signed Certificate Timestamp List + SmimeOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 15} // Smime Capabilities + SubjectAlternateNameOID = asn1.ObjectIdentifier{2, 5, 29, 17} // Subject Alt Name + SubjectDirAttrOID = asn1.ObjectIdentifier{2, 5, 29, 9} // Subject Directory Attributes + SubjectInfoAccessOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 11} // Subject Info Access Syntax + SubjectKeyIdentityOID = asn1.ObjectIdentifier{2, 5, 29, 14} // Subject Key Identifier + // CA/B reserved policies + BRDomainValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1} // CA/B BR Domain-Validated + BROrganizationValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 2} // CA/B BR Organization-Validated + BRIndividualValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 3} // CA/B BR Individual-Validated + BRTorServiceDescriptor = asn1.ObjectIdentifier{2, 23, 140, 1, 31} // CA/B BR Tor Service Descriptor + CabfExtensionOrganizationIdentifier = asn1.ObjectIdentifier{2, 23, 140, 3, 1} // CA/B EV 9.8.2 cabfOrganizationIdentifier + //X.500 attribute types + CommonNameOID = asn1.ObjectIdentifier{2, 5, 4, 3} + SurnameOID = asn1.ObjectIdentifier{2, 5, 4, 4} + SerialOID = asn1.ObjectIdentifier{2, 5, 4, 5} + CountryNameOID = asn1.ObjectIdentifier{2, 5, 4, 6} + LocalityNameOID = asn1.ObjectIdentifier{2, 5, 4, 7} + StateOrProvinceNameOID = asn1.ObjectIdentifier{2, 5, 4, 8} + StreetAddressOID = asn1.ObjectIdentifier{2, 5, 4, 9} + OrganizationNameOID = asn1.ObjectIdentifier{2, 5, 4, 10} + OrganizationalUnitNameOID = asn1.ObjectIdentifier{2, 5, 4, 11} + BusinessOID = asn1.ObjectIdentifier{2, 5, 4, 15} + PostalCodeOID = asn1.ObjectIdentifier{2, 5, 4, 17} + GivenNameOID = asn1.ObjectIdentifier{2, 5, 4, 42} + // Hash algorithms - see https://golang.org/src/crypto/x509/x509.go + SHA256OID = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} + SHA384OID = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} + SHA512OID = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} + // other OIDs + OidRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} + OidRSASSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} + OidMD2WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} + OidMD5WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} + OidSHA1WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} + OidSHA224WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 14} + OidSHA256WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} + OidSHA384WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} + OidSHA512WithRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} + AnyPolicyOID = asn1.ObjectIdentifier{2, 5, 29, 32, 0} + UserNoticeOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2} + CpsOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} + IdEtsiQcsQcCompliance = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 1} + IdEtsiQcsQcLimitValue = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 2} + IdEtsiQcsQcRetentionPeriod = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 3} + IdEtsiQcsQcSSCD = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 4} + IdEtsiQcsQcEuPDS = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 5} + IdEtsiQcsQcType = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6} + IdEtsiQcsQctEsign = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 1} + IdEtsiQcsQctEseal = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 2} + IdEtsiQcsQctWeb = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 3} +) + +const ( + // Tags + DNSNameTag = 2 +) + +// IsExtInCert is equivalent to GetExtFromCert() != nil. +func IsExtInCert(cert *x509.Certificate, oid asn1.ObjectIdentifier) bool { + if cert != nil && GetExtFromCert(cert, oid) != nil { + return true + } + return false +} + +// GetExtFromCert returns the extension with the matching OID, if present. If +// the extension if not present, it returns nil. +//nolint:interfacer +func GetExtFromCert(cert *x509.Certificate, oid asn1.ObjectIdentifier) *pkix.Extension { + // Since this function is called by many Lint CheckApplies functions we use + // the x509.Certificate.ExtensionsMap field added by zcrypto to check for + // the extension in O(1) instead of looping through the + // `x509.Certificate.Extensions` in O(n). + if ext, found := cert.ExtensionsMap[oid.String()]; found { + return &ext + } + return nil +} + +// Helper function that checks if an []asn1.ObjectIdentifier slice contains an asn1.ObjectIdentifier +func SliceContainsOID(list []asn1.ObjectIdentifier, oid asn1.ObjectIdentifier) bool { + for _, v := range list { + if oid.Equal(v) { + return true + } + } + return false +} + +// Helper function that checks for a name type in a pkix.Name +func TypeInName(name *pkix.Name, oid asn1.ObjectIdentifier) bool { + for _, v := range name.Names { + if oid.Equal(v.Type) { + return true + } + } + return false +} + +//helper function to parse policyMapping extensions, returns slices of CertPolicyIds separated by domain +func GetMappedPolicies(polMap *pkix.Extension) ([][2]asn1.ObjectIdentifier, error) { + if polMap == nil { + return nil, errors.New("policyMap: null pointer") + } + var outSeq, inSeq asn1.RawValue + + empty, err := asn1.Unmarshal(polMap.Value, &outSeq) //strip outer sequence tag/length should be nothing extra + if err != nil || len(empty) != 0 || outSeq.Class != 0 || outSeq.Tag != 16 || !outSeq.IsCompound { + return nil, errors.New("policyMap: Could not unmarshal outer sequence.") + } + + var out [][2]asn1.ObjectIdentifier + for done := false; !done; { //loop through SEQUENCE OF + outSeq.Bytes, err = asn1.Unmarshal(outSeq.Bytes, &inSeq) //extract next inner SEQUENCE (OID pair) + if err != nil || inSeq.Class != 0 || inSeq.Tag != 16 || !inSeq.IsCompound { + return nil, errors.New("policyMap: Could not unmarshal inner sequence.") + } + if len(outSeq.Bytes) == 0 { //nothing remaining to parse, stop looping after + done = true + } + + var oidIssue, oidSubject asn1.ObjectIdentifier + var restIn asn1.RawContent + restIn, err = asn1.Unmarshal(inSeq.Bytes, &oidIssue) //extract first inner CertPolicyId (issuer domain) + if err != nil || len(restIn) == 0 { + return nil, errors.New("policyMap: Could not unmarshal inner sequence.") + } + + empty, err = asn1.Unmarshal(restIn, &oidSubject) //extract second inner CertPolicyId (subject domain) + if err != nil || len(empty) != 0 { + return nil, errors.New("policyMap: Could not unmarshal inner sequence.") + } + + //append found OIDs + out = append(out, [2]asn1.ObjectIdentifier{oidIssue, oidSubject}) + } + + return out, nil +} diff --git a/vendor/github.com/zmap/zlint/v3/util/primes.go b/vendor/github.com/zmap/zlint/v3/util/primes.go new file mode 100644 index 0000000000..def1e631b8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/primes.go @@ -0,0 +1,57 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import "math/big" + +var bigIntPrimes = []*big.Int{ + big.NewInt(2), big.NewInt(3), big.NewInt(5), big.NewInt(7), big.NewInt(11), big.NewInt(13), + big.NewInt(17), big.NewInt(19), big.NewInt(23), big.NewInt(29), big.NewInt(31), big.NewInt(37), + big.NewInt(41), big.NewInt(43), big.NewInt(47), big.NewInt(53), big.NewInt(59), big.NewInt(61), + big.NewInt(67), big.NewInt(71), big.NewInt(73), big.NewInt(79), big.NewInt(83), big.NewInt(89), + big.NewInt(97), big.NewInt(101), big.NewInt(103), big.NewInt(107), big.NewInt(109), big.NewInt(113), + big.NewInt(127), big.NewInt(131), big.NewInt(137), big.NewInt(139), big.NewInt(149), big.NewInt(151), + big.NewInt(157), big.NewInt(163), big.NewInt(167), big.NewInt(173), big.NewInt(179), big.NewInt(181), + big.NewInt(191), big.NewInt(193), big.NewInt(197), big.NewInt(199), big.NewInt(211), big.NewInt(223), + big.NewInt(227), big.NewInt(229), big.NewInt(233), big.NewInt(239), big.NewInt(241), big.NewInt(251), + big.NewInt(257), big.NewInt(263), big.NewInt(269), big.NewInt(271), big.NewInt(277), big.NewInt(281), + big.NewInt(283), big.NewInt(293), big.NewInt(307), big.NewInt(311), big.NewInt(353), big.NewInt(359), + big.NewInt(367), big.NewInt(373), big.NewInt(379), big.NewInt(383), big.NewInt(313), big.NewInt(317), + big.NewInt(331), big.NewInt(337), big.NewInt(347), big.NewInt(349), big.NewInt(389), big.NewInt(397), + big.NewInt(401), big.NewInt(409), big.NewInt(419), big.NewInt(421), big.NewInt(431), big.NewInt(433), + big.NewInt(439), big.NewInt(443), big.NewInt(449), big.NewInt(457), big.NewInt(461), big.NewInt(463), + big.NewInt(467), big.NewInt(479), big.NewInt(487), big.NewInt(491), big.NewInt(499), big.NewInt(503), + big.NewInt(509), big.NewInt(521), big.NewInt(523), big.NewInt(541), big.NewInt(547), big.NewInt(557), + big.NewInt(563), big.NewInt(569), big.NewInt(571), big.NewInt(577), big.NewInt(587), big.NewInt(593), + big.NewInt(599), big.NewInt(601), big.NewInt(607), big.NewInt(613), big.NewInt(617), big.NewInt(619), + big.NewInt(631), big.NewInt(641), big.NewInt(643), big.NewInt(647), big.NewInt(653), big.NewInt(659), + big.NewInt(661), big.NewInt(673), big.NewInt(677), big.NewInt(683), big.NewInt(691), big.NewInt(701), + big.NewInt(709), big.NewInt(719), big.NewInt(727), big.NewInt(733), big.NewInt(739), big.NewInt(743), + big.NewInt(751), +} + +var zero = big.NewInt(0) + +func PrimeNoSmallerThan752(dividend *big.Int) bool { + quotient := big.NewInt(0) + mod := big.NewInt(0) + for _, divisor := range bigIntPrimes { + quotient.DivMod(dividend, divisor, mod) + if mod.Cmp(zero) == 0 { + return false + } + } + return true +} diff --git a/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go b/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go new file mode 100644 index 0000000000..97af7faf65 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go @@ -0,0 +1,253 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "bytes" + "encoding/asn1" + "fmt" + "reflect" +) + +type anyContent struct { + Raw asn1.RawContent +} + +type qcStatementWithInfoField struct { + Oid asn1.ObjectIdentifier + Any asn1.RawValue +} +type qcStatementWithoutInfoField struct { + Oid asn1.ObjectIdentifier +} + +type etsiBase struct { + errorInfo string + isPresent bool +} + +func (this etsiBase) GetErrorInfo() string { + return this.errorInfo +} + +func (this etsiBase) IsPresent() bool { + return this.isPresent +} + +type EtsiQcStmtIf interface { + GetErrorInfo() string + IsPresent() bool +} + +type Etsi421QualEuCert struct { + etsiBase +} + +type Etsi423QcType struct { + etsiBase + TypeOids []asn1.ObjectIdentifier +} + +type EtsiQcSscd struct { + etsiBase +} + +type EtsiMonetaryValueAlph struct { + Iso4217CurrencyCodeAlph string `asn1:"printable"` + Amount int + Exponent int +} +type EtsiMonetaryValueNum struct { + Iso4217CurrencyCodeNum int + Amount int + Exponent int +} + +type EtsiQcLimitValue struct { + etsiBase + Amount int + Exponent int + IsNum bool + CurrencyAlph string + CurrencyNum int +} + +type EtsiQcRetentionPeriod struct { + etsiBase + Period int +} +type PdsLocation struct { + Url string `asn1:"ia5"` + Language string `asn1:"printable"` +} +type EtsiQcPds struct { + etsiBase + PdsLocations []PdsLocation +} + +func AppendToStringSemicolonDelim(this *string, s string) { + if len(*this) > 0 && len(s) > 0 { + (*this) += "; " + } + (*this) += s +} + +func checkAsn1Reencoding(i interface{}, originalEncoding []byte, appendIfComparisonFails string) string { + result := "" + reencoded, marshErr := asn1.Marshal(i) + if marshErr != nil { + AppendToStringSemicolonDelim(&result, fmt.Sprintf("error reencoding ASN1 value of statementInfo field: %s", + marshErr)) + } + if !bytes.Equal(reencoded, originalEncoding) { + AppendToStringSemicolonDelim(&result, appendIfComparisonFails) + } + return result +} + +func IsAnyEtsiQcStatementPresent(extVal []byte) bool { + oidList := make([]*asn1.ObjectIdentifier, 6) + oidList[0] = &IdEtsiQcsQcCompliance + oidList[1] = &IdEtsiQcsQcLimitValue + oidList[2] = &IdEtsiQcsQcRetentionPeriod + oidList[3] = &IdEtsiQcsQcSSCD + oidList[4] = &IdEtsiQcsQcEuPDS + oidList[5] = &IdEtsiQcsQcType + for _, oid := range oidList { + r := ParseQcStatem(extVal, *oid) + if r.IsPresent() { + return true + } + } + return false +} + +//nolint:gocyclo +func ParseQcStatem(extVal []byte, sought asn1.ObjectIdentifier) EtsiQcStmtIf { + sl := make([]anyContent, 0) + rest, err := asn1.Unmarshal(extVal, &sl) + if err != nil { + return etsiBase{errorInfo: "error parsing outer SEQ", isPresent: true} + } + if len(rest) != 0 { + return etsiBase{errorInfo: "rest len of outer seq != 0", isPresent: true} + } + + for _, raw := range sl { + parseErrorString := "format error in at least one QC statement within the QC statements extension." + + " this message may appear multiple times for the same error cause." + var statem qcStatementWithInfoField + rest, err = asn1.Unmarshal(raw.Raw, &statem) + if err != nil { + var statemWithoutInfo qcStatementWithoutInfoField + + rest, err = asn1.Unmarshal(raw.Raw, &statemWithoutInfo) + if err != nil || len(rest) != 0 { + return etsiBase{errorInfo: parseErrorString, isPresent: false} + } + copy(statem.Oid, statemWithoutInfo.Oid) + if len(statem.Any.FullBytes) != 0 { + return etsiBase{errorInfo: "internal error, default optional content len is not zero"} + } + } else if 0 != len(rest) { + return etsiBase{errorInfo: parseErrorString, isPresent: false} + } + + if !statem.Oid.Equal(sought) { + continue + } + if statem.Oid.Equal(IdEtsiQcsQcCompliance) { + etsiObj := Etsi421QualEuCert{etsiBase: etsiBase{isPresent: true}} + statemWithoutInfo := qcStatementWithoutInfoField{Oid: statem.Oid} + AppendToStringSemicolonDelim(&etsiObj.errorInfo, checkAsn1Reencoding(reflect.ValueOf(statemWithoutInfo).Interface(), raw.Raw, + "invalid format of ETSI Complicance statement")) + return etsiObj + } else if statem.Oid.Equal(IdEtsiQcsQcLimitValue) { + etsiObj := EtsiQcLimitValue{etsiBase: etsiBase{isPresent: true}} + numErr := false + alphErr := false + var numeric EtsiMonetaryValueNum + var alphabetic EtsiMonetaryValueAlph + restNum, errNum := asn1.Unmarshal(statem.Any.FullBytes, &numeric) + if len(restNum) != 0 || errNum != nil { + numErr = true + } else { + etsiObj.IsNum = true + etsiObj.Amount = numeric.Amount + etsiObj.Exponent = numeric.Exponent + etsiObj.CurrencyNum = numeric.Iso4217CurrencyCodeNum + + } + if numErr { + restAlph, errAlph := asn1.Unmarshal(statem.Any.FullBytes, &alphabetic) + if len(restAlph) != 0 || errAlph != nil { + alphErr = true + } else { + etsiObj.IsNum = false + etsiObj.Amount = alphabetic.Amount + etsiObj.Exponent = alphabetic.Exponent + etsiObj.CurrencyAlph = alphabetic.Iso4217CurrencyCodeAlph + AppendToStringSemicolonDelim(&etsiObj.errorInfo, + checkAsn1Reencoding(reflect.ValueOf(alphabetic).Interface(), + statem.Any.FullBytes, "error with ASN.1 encoding, possibly a wrong ASN.1 string type was used")) + } + } + if numErr && alphErr { + etsiObj.errorInfo = "error parsing the ETSI Qc Statement statementInfo field" + } + return etsiObj + + } else if statem.Oid.Equal(IdEtsiQcsQcRetentionPeriod) { + etsiObj := EtsiQcRetentionPeriod{etsiBase: etsiBase{isPresent: true}} + rest, err := asn1.Unmarshal(statem.Any.FullBytes, &etsiObj.Period) + + if len(rest) != 0 || err != nil { + etsiObj.errorInfo = "error parsing the statementInfo field" + } + return etsiObj + } else if statem.Oid.Equal(IdEtsiQcsQcSSCD) { + etsiObj := EtsiQcSscd{etsiBase: etsiBase{isPresent: true}} + statemWithoutInfo := qcStatementWithoutInfoField{Oid: statem.Oid} + AppendToStringSemicolonDelim(&etsiObj.errorInfo, checkAsn1Reencoding(reflect.ValueOf(statemWithoutInfo).Interface(), raw.Raw, + "invalid format of ETSI SCSD statement")) + return etsiObj + } else if statem.Oid.Equal(IdEtsiQcsQcEuPDS) { + etsiObj := EtsiQcPds{etsiBase: etsiBase{isPresent: true}} + rest, err := asn1.Unmarshal(statem.Any.FullBytes, &etsiObj.PdsLocations) + if len(rest) != 0 || err != nil { + etsiObj.errorInfo = "error parsing the statementInfo field" + } else { + AppendToStringSemicolonDelim(&etsiObj.errorInfo, + checkAsn1Reencoding(reflect.ValueOf(etsiObj.PdsLocations).Interface(), statem.Any.FullBytes, + "error with ASN.1 encoding, possibly a wrong ASN.1 string type was used")) + } + return etsiObj + } else if statem.Oid.Equal(IdEtsiQcsQcType) { + var qcType Etsi423QcType + qcType.isPresent = true + rest, err := asn1.Unmarshal(statem.Any.FullBytes, &qcType.TypeOids) + if len(rest) != 0 || err != nil { + return etsiBase{errorInfo: "error parsing IdEtsiQcsQcType extension statementInfo field", isPresent: true} + } + return qcType + } else { + return etsiBase{errorInfo: "", isPresent: true} + } + + } + + return etsiBase{errorInfo: "", isPresent: false} + +} diff --git a/vendor/github.com/zmap/zlint/v3/util/rdn.go b/vendor/github.com/zmap/zlint/v3/util/rdn.go new file mode 100644 index 0000000000..cb076a91be --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/rdn.go @@ -0,0 +1,26 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import "encoding/asn1" + +type AttributeTypeAndRawValue struct { + Type asn1.ObjectIdentifier + Value asn1.RawValue +} + +type AttributeTypeAndRawValueSET []AttributeTypeAndRawValue + +type RawRDNSequence []AttributeTypeAndRawValueSET diff --git a/vendor/github.com/zmap/zlint/v3/util/time.go b/vendor/github.com/zmap/zlint/v3/util/time.go new file mode 100644 index 0000000000..ba47b2d3b8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/time.go @@ -0,0 +1,118 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "encoding/asn1" + "time" + + "github.com/zmap/zcrypto/x509" +) + +var ( + ZeroDate = time.Date(0000, time.January, 1, 0, 0, 0, 0, time.UTC) + RFC1035Date = time.Date(1987, time.January, 1, 0, 0, 0, 0, time.UTC) + RFC2459Date = time.Date(1999, time.January, 1, 0, 0, 0, 0, time.UTC) + RFC3280Date = time.Date(2002, time.April, 1, 0, 0, 0, 0, time.UTC) + RFC3490Date = time.Date(2003, time.March, 1, 0, 0, 0, 0, time.UTC) + RFC8399Date = time.Date(2018, time.May, 1, 0, 0, 0, 0, time.UTC) + RFC4325Date = time.Date(2005, time.December, 1, 0, 0, 0, 0, time.UTC) + RFC4630Date = time.Date(2006, time.August, 1, 0, 0, 0, 0, time.UTC) + RFC5280Date = time.Date(2008, time.May, 1, 0, 0, 0, 0, time.UTC) + RFC6818Date = time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC) + CABEffectiveDate = time.Date(2012, time.July, 1, 0, 0, 0, 0, time.UTC) + CABReservedIPDate = time.Date(2016, time.October, 1, 0, 0, 0, 0, time.UTC) + CABGivenNameDate = time.Date(2016, time.September, 7, 0, 0, 0, 0, time.UTC) + CABSerialNumberEntropyDate = time.Date(2016, time.September, 30, 0, 0, 0, 0, time.UTC) + CABV102Date = time.Date(2012, time.June, 8, 0, 0, 0, 0, time.UTC) + CABV113Date = time.Date(2013, time.February, 21, 0, 0, 0, 0, time.UTC) + CABV114Date = time.Date(2013, time.May, 3, 0, 0, 0, 0, time.UTC) + CABV116Date = time.Date(2013, time.July, 29, 0, 0, 0, 0, time.UTC) + CABV130Date = time.Date(2015, time.April, 16, 0, 0, 0, 0, time.UTC) + CABV131Date = time.Date(2015, time.September, 28, 0, 0, 0, 0, time.UTC) + // https://cabforum.org/wp-content/uploads/CA-Browser-Forum-EV-Guidelines-v1.7.0.pdf + CABV170Date = time.Date(2020, time.January, 31, 0, 0, 0, 0, time.UTC) + NO_SHA1 = time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC) + NoRSA1024RootDate = time.Date(2011, time.January, 1, 0, 0, 0, 0, time.UTC) + NoRSA1024Date = time.Date(2014, time.January, 1, 0, 0, 0, 0, time.UTC) + GeneralizedDate = time.Date(2050, time.January, 1, 0, 0, 0, 0, time.UTC) + NoReservedIP = time.Date(2015, time.November, 1, 0, 0, 0, 0, time.UTC) + SubCert39Month = time.Date(2016, time.July, 2, 0, 0, 0, 0, time.UTC) + SubCert825Days = time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC) + CABV148Date = time.Date(2017, time.June, 8, 0, 0, 0, 0, time.UTC) + EtsiEn319_412_5_V2_2_1_Date = time.Date(2017, time.November, 1, 0, 0, 0, 0, time.UTC) + OnionOnlyEVDate = time.Date(2015, time.May, 1, 0, 0, 0, 0, time.UTC) + CABV201Date = time.Date(2017, time.July, 28, 0, 0, 0, 0, time.UTC) + AppleCTPolicyDate = time.Date(2018, time.October, 15, 0, 0, 0, 0, time.UTC) + MozillaPolicy22Date = time.Date(2013, time.July, 26, 0, 0, 0, 0, time.UTC) + MozillaPolicy24Date = time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC) + MozillaPolicy27Date = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC) + CABFBRs_1_6_9_Date = time.Date(2020, time.March, 27, 0, 0, 0, 0, time.UTC) + AppleReducedLifetimeDate = time.Date(2020, time.September, 1, 0, 0, 0, 0, time.UTC) +) + +var ( + CABFEV_9_8_2 = CABV170Date +) + +func FindTimeType(firstDate, secondDate asn1.RawValue) (int, int) { + return firstDate.Tag, secondDate.Tag +} + +// TODO(@cpu): This function is a little bit rough around the edges (especially +// after my quick fixes for the ineffassigns) and would be a good candidate for +// clean-up/refactoring. +func GetTimes(cert *x509.Certificate) (asn1.RawValue, asn1.RawValue) { + var outSeq, firstDate, secondDate asn1.RawValue + // Unmarshal into the sequence + _, err := asn1.Unmarshal(cert.RawTBSCertificate, &outSeq) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + // Start unmarshalling the bytes + rest, err := asn1.Unmarshal(outSeq.Bytes, &outSeq) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + // This is here to account for if version is not included + if outSeq.Tag == 0 { + rest, err = asn1.Unmarshal(rest, &outSeq) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + } + rest, err = asn1.Unmarshal(rest, &outSeq) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + rest, err = asn1.Unmarshal(rest, &outSeq) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + _, err = asn1.Unmarshal(rest, &outSeq) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + // Finally at the validity date, load them into a different RawValue + rest, err = asn1.Unmarshal(outSeq.Bytes, &firstDate) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + _, err = asn1.Unmarshal(rest, &secondDate) + if err != nil { + return asn1.RawValue{}, asn1.RawValue{} + } + return firstDate, secondDate +} diff --git a/vendor/github.com/zmap/zlint/v3/zlint.go b/vendor/github.com/zmap/zlint/v3/zlint.go new file mode 100644 index 0000000000..56e1d405e1 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/zlint.go @@ -0,0 +1,62 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// Used to check parsed info from certificate for compliance + +package zlint + +import ( + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + _ "github.com/zmap/zlint/v3/lints/apple" + _ "github.com/zmap/zlint/v3/lints/cabf_br" + _ "github.com/zmap/zlint/v3/lints/cabf_ev" + _ "github.com/zmap/zlint/v3/lints/community" + _ "github.com/zmap/zlint/v3/lints/etsi" + _ "github.com/zmap/zlint/v3/lints/mozilla" + _ "github.com/zmap/zlint/v3/lints/rfc" +) + +const Version int64 = 3 + +// LintCertificate runs all registered lints on c using default options, +// producing a ResultSet. +// +// Using LintCertificate(c) is equivalent to calling LintCertificateEx(c, nil). +func LintCertificate(c *x509.Certificate) *ResultSet { + // Run all lints from the global registry + return LintCertificateEx(c, nil) +} + +// LintCertificateEx runs lints from the provided registry on c producing +// a ResultSet. Providing an explicit registry allows the caller to filter the +// lints that will be run. (See lint.Registry.Filter()) +// +// If registry is nil then the global registry of all lints is used and this +// function is equivalent to calling LintCertificate(c). +func LintCertificateEx(c *x509.Certificate, registry lint.Registry) *ResultSet { + if c == nil { + return nil + } + if registry == nil { + registry = lint.GlobalRegistry() + } + res := new(ResultSet) + res.execute(c, registry) + res.Version = Version + res.Timestamp = time.Now().Unix() + return res +} diff --git a/vendor/modules.txt b/vendor/modules.txt index ea8f96a327..d10c77d903 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -18,8 +18,8 @@ github.com/beorn7/perks/quantile # github.com/cespare/xxhash/v2 v2.1.2 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 -## explicit +# github.com/cloudflare/cfssl v1.6.4 +## explicit; go 1.18 github.com/cloudflare/cfssl/api github.com/cloudflare/cfssl/auth github.com/cloudflare/cfssl/certdb @@ -194,6 +194,9 @@ github.com/inconshreveable/mousetrap # github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 ## explicit; go 1.12 github.com/ishidawataru/sctp +# github.com/jmoiron/sqlx v1.3.3 +## explicit; go 1.10 +github.com/jmoiron/sqlx/types # github.com/matttproud/golang_protobuf_extensions v1.0.4 ## explicit; go 1.9 github.com/matttproud/golang_protobuf_extensions/pbutil @@ -306,6 +309,30 @@ github.com/stretchr/testify/assert github.com/stretchr/testify/require # github.com/tedsuo/ifrit v0.0.0-20220120221754-dd274de71113 ## explicit +# github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b +## explicit; go 1.11 +github.com/weppos/publicsuffix-go/publicsuffix +# github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc +## explicit; go 1.16 +github.com/zmap/zcrypto/dsa +github.com/zmap/zcrypto/internal/randutil +github.com/zmap/zcrypto/json +github.com/zmap/zcrypto/util +github.com/zmap/zcrypto/x509 +github.com/zmap/zcrypto/x509/ct +github.com/zmap/zcrypto/x509/pkix +# github.com/zmap/zlint/v3 v3.1.0 +## explicit; go 1.15 +github.com/zmap/zlint/v3 +github.com/zmap/zlint/v3/lint +github.com/zmap/zlint/v3/lints/apple +github.com/zmap/zlint/v3/lints/cabf_br +github.com/zmap/zlint/v3/lints/cabf_ev +github.com/zmap/zlint/v3/lints/community +github.com/zmap/zlint/v3/lints/etsi +github.com/zmap/zlint/v3/lints/mozilla +github.com/zmap/zlint/v3/lints/rfc +github.com/zmap/zlint/v3/util # go.etcd.io/bbolt v1.3.7 ## explicit; go 1.17 go.etcd.io/bbolt