Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow parsing of nonstandard country name and jurisdiction country name #6641

Merged
merged 1 commit into from Nov 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/development/test-vectors.rst
Expand Up @@ -444,6 +444,9 @@ Custom X.509 Vectors
version.
* ``invalid-sct-length.der`` - A certificate with an SCT with an internal
length greater than the amount of data.
* ``bad_country.pem`` - A certificate with country name and jurisdiction
country name values in its subject and issuer distinguished names which
are longer than 2 characters.

Custom X.509 Request Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
17 changes: 15 additions & 2 deletions src/cryptography/x509/name.py
Expand Up @@ -3,6 +3,7 @@
# for complete details.

import typing
import warnings

from cryptography import utils
from cryptography.hazmat.bindings._rust import (
Expand Down Expand Up @@ -79,7 +80,12 @@ def _escape_dn_value(val: str) -> str:

class NameAttribute(object):
def __init__(
self, oid: ObjectIdentifier, value: str, _type=_SENTINEL
self,
oid: ObjectIdentifier,
value: str,
_type=_SENTINEL,
*,
_validate=True,
) -> None:
if not isinstance(oid, ObjectIdentifier):
raise TypeError(
Expand All @@ -93,10 +99,17 @@ def __init__(
oid == NameOID.COUNTRY_NAME
or oid == NameOID.JURISDICTION_COUNTRY_NAME
):
if len(value.encode("utf8")) != 2:
c_len = len(value.encode("utf8"))
if c_len != 2 and _validate is True:
raise ValueError(
"Country name must be a 2 character country code"
)
elif c_len != 2:
warnings.warn(
"Country names should be two characters, but the "
"attribute is {} characters in length.".format(c_len),
stacklevel=2,
)

# The appropriate ASN1 string type varies by OID and is defined across
# multiple RFCs including 2459, 3280, and 5280. In general UTF8String
Expand Down
4 changes: 3 additions & 1 deletion src/rust/src/x509/common.rs
Expand Up @@ -5,6 +5,7 @@
use crate::asn1::PyAsn1Error;
use crate::x509;
use chrono::{Datelike, TimeZone, Timelike};
use pyo3::types::IntoPyDict;
use pyo3::ToPyObject;
use std::collections::HashSet;
use std::convert::TryInto;
Expand Down Expand Up @@ -382,8 +383,9 @@ fn parse_name_attribute(
_ => std::str::from_utf8(attribute.value.data())
.map_err(|_| asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue))?,
};
let kwargs = [("_validate", false)].into_py_dict(py);
Ok(x509_module
.call_method1("NameAttribute", (oid, py_data, py_tag))?
.call_method("NameAttribute", (oid, py_data, py_tag), Some(kwargs))?
.to_object(py))
}

Expand Down
22 changes: 22 additions & 0 deletions tests/x509/test_x509.py
Expand Up @@ -747,6 +747,28 @@ def test_negative_serial_number(self, backend):
with pytest.warns(utils.DeprecatedIn36):
assert cert.serial_number == -18008675309

def test_country_jurisdiction_country_too_long(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "bad_country.pem"),
x509.load_pem_x509_certificate,
backend,
)
with pytest.warns(UserWarning):
assert (
cert.subject.get_attributes_for_oid(x509.NameOID.COUNTRY_NAME)[
0
].value
== "too long"
)

with pytest.warns(UserWarning):
assert (
cert.subject.get_attributes_for_oid(
x509.NameOID.JURISDICTION_COUNTRY_NAME
)[0].value
== "also too long"
)

def test_alternate_rsa_with_sha1_oid(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "alternate-rsa-sha1-oid.der"),
Expand Down
18 changes: 18 additions & 0 deletions vectors/cryptography_vectors/x509/custom/bad_country.pem
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC4DCCAcigAwIBAgICAwkwDQYJKoZIhvcNAQENBQAwMzERMA8GA1UEBhMIdG9v
IGxvbmcxHjAcBgsrBgEEAYI3PAIBAxMNYWxzbyB0b28gbG9uZzAeFw0wMjAxMDEx
MjAxMDBaFw0zMDEyMzEwODMwMDBaMDMxETAPBgNVBAYTCHRvbyBsb25nMR4wHAYL
KwYBBAGCNzwCAQMTDWFsc28gdG9vIGxvbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDBevx+d0dMqlqoMDYVij/797UhaFG6IjDl1qv8wcbP71npI+oT
MLxZO3OAKrYIpuSjMGUjoxFrpao5ZhRRdOE7bEnpt4Bi5EnXLvsQ/UnpH6CLltBR
54Lp9avFtab3mEgnrbjnPaAPIrLv3Nt26rRu2tmO1lZidD/cbA4zal0M26p9wp5T
Y14kyHpbLEIVloBjzetoqXK6u8Hjz/APuagONypNDCySDR6M7jM85HDcLoFFrbBb
8pruHSTxQejMeEmJxYf8b7rNl58/IWPB1ymbNlvHL/4oSOlnrtHkjcxRWzpQ7U3g
T9BThGyhCiI7EMyEHMgP3r7kTzEUwT6IavWDAgMBAAEwDQYJKoZIhvcNAQENBQAD
ggEBALEK2PhqEfqH6/q3M7Guq9E/GuB0qAlqBkZNqIzX8WdRuMKRCnE2I0TDFtbp
jGrhqYcugOB12HeOWT3iSg491KDphsWGFR+La7zZkFKdSf3Cc/ktw6lOgu66CQxI
Bfgp0O4yGexKYkeW1C/gQVoAzczelykfSFthG+BJsX4OGsb6g98y6fsOnHfx7s2t
UkPMYUgom3fhs/J4RhRTKHAOiPBTKg91qGRcGr4TjqCRmiWVw1hFJL0p4vZopnS8
VX/OrLRnNsj+VxoSIksoEUuxNdUuN4lw14IDZFUEw9CErnyisX2DEozjrg6jca8n
gdJuDRk4TlNl/CpgNraJcu47pME=
-----END CERTIFICATE-----