Skip to content

Commit

Permalink
allow parsing of nonstandard country name and jurisdiction country na…
Browse files Browse the repository at this point in the history
…me (#6641)

The spec requires both of these to be exactly two characters to
correspond with ISO country codes. Reality is sometimes messier, so this
allows parsing (but not encoding) of this invalid data. Parsing will
raise a UserWarning if incorrect lengths are detected.
  • Loading branch information
reaperhulk committed Nov 21, 2021
1 parent 2b22df1 commit 5bd0c10
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
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-----

0 comments on commit 5bd0c10

Please sign in to comment.