From 1f7fdff64a9d39ccdd3a5ff3be780cacf2628941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Sun, 19 Dec 2021 18:23:01 +0000 Subject: [PATCH] tls: fix handling of x509 subject and issuer When subject and verifier are represented as strings, escape special characters (such as '+') to guarantee unambiguity. Previously, different distinguished names could result in the same string when encoded. In particular, inserting a '+' in a single-value Relative Distinguished Name (e.g., L or OU) would produce a string that is indistinguishable from a multi-value Relative Distinguished Name. Third-party code that correctly interprets the generated string representation as a multi-value Relative Distinguished Name could then be vulnerable to an injection attack, e.g., when an attacker includes a single-value RDN with type OU and value 'HR + CN=example.com', the string representation produced by unpatched versions of Node.js would be 'OU=HR + CN=example.com', which represents a multi-value RDN. Node.js itself is not vulnerable to this attack because the current implementation that parses such strings into objects does not handle '+' at all. This oversight leads to incorrect results, but at the same time appears to prevent injection attacks (as described above). With this change, the JavaScript objects representing the subject and issuer Relative Distinguished Names are constructed in C++ directly, instead of (incorrectly) encoding them as strings and then (incorrectly) decoding the strings in JavaScript. This addresses CVE-2021-44533. Co-authored-by: Akshay K CVE-ID: CVE-2021-44533 Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/303 PR-URL: https://github.com/nodejs-private/node-private/pull/300 Reviewed-By: Michael Dawson Reviewed-By: Rich Trott --- lib/_tls_common.js | 6 +- src/crypto/crypto_common.cc | 128 ++++++++++++++++-- src/crypto/crypto_common.h | 3 +- src/crypto/crypto_x509.cc | 2 +- test/fixtures/x509-escaping/create-certs.js | 141 ++++++++++++++++++++ test/fixtures/x509-escaping/subj-0-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-1-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-2-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-3-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-4-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-5-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-6-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-7-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-8-cert.pem | 28 ++++ test/fixtures/x509-escaping/subj-9-cert.pem | 28 ++++ test/parallel/test-x509-escaping.js | 109 +++++++++++++++ 16 files changed, 656 insertions(+), 13 deletions(-) create mode 100644 test/fixtures/x509-escaping/subj-0-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-1-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-2-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-3-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-4-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-5-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-6-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-7-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-8-cert.pem create mode 100644 test/fixtures/x509-escaping/subj-9-cert.pem diff --git a/lib/_tls_common.js b/lib/_tls_common.js index cb3f08bf28793e..533fbe7fd256e3 100644 --- a/lib/_tls_common.js +++ b/lib/_tls_common.js @@ -126,11 +126,13 @@ function translatePeerCertificate(c) { if (!c) return null; - if (c.issuer != null) c.issuer = parseCertString(c.issuer); + // TODO(tniessen): can we remove parseCertString without breaking anything? + if (typeof c.issuer === 'string') c.issuer = parseCertString(c.issuer); if (c.issuerCertificate != null && c.issuerCertificate !== c) { c.issuerCertificate = translatePeerCertificate(c.issuerCertificate); } - if (c.subject != null) c.subject = parseCertString(c.subject); + // TODO(tniessen): can we remove parseCertString without breaking anything? + if (typeof c.subject === 'string') c.subject = parseCertString(c.subject); if (c.infoAccess != null) { const info = c.infoAccess; c.infoAccess = ObjectCreate(null); diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc index 02ed01ad7563cd..4be308fb655017 100644 --- a/src/crypto/crypto_common.cc +++ b/src/crypto/crypto_common.cc @@ -42,6 +42,7 @@ using v8::Value; namespace crypto { static constexpr int X509_NAME_FLAGS = + ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_UTF8_CONVERT | XN_FLAG_SEP_MULTILINE | @@ -964,6 +965,93 @@ MaybeLocal GetSubject( return ToV8Value(env, bio); } +template +static MaybeLocal GetX509NameObject(Environment* env, X509* cert) { + X509_NAME* name = get_name(cert); + CHECK_NOT_NULL(name); + + int cnt = X509_NAME_entry_count(name); + CHECK_GE(cnt, 0); + + Local result = + Object::New(env->isolate(), Null(env->isolate()), nullptr, nullptr, 0); + if (result.IsEmpty()) { + return MaybeLocal(); + } + + for (int i = 0; i < cnt; i++) { + X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); + CHECK_NOT_NULL(entry); + + // We intentionally ignore the value of X509_NAME_ENTRY_set because the + // representation as an object does not allow grouping entries into sets + // anyway, and multi-value RDNs are rare, i.e., the vast majority of + // Relative Distinguished Names contains a single type-value pair only. + const ASN1_OBJECT* type = X509_NAME_ENTRY_get_object(entry); + const ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry); + + // If OpenSSL knows the type, use the short name of the type as the key, and + // the numeric representation of the type's OID otherwise. + int type_nid = OBJ_obj2nid(type); + char type_buf[80]; + const char* type_str; + if (type_nid != NID_undef) { + type_str = OBJ_nid2sn(type_nid); + CHECK_NOT_NULL(type_str); + } else { + OBJ_obj2txt(type_buf, sizeof(type_buf), type, true); + type_str = type_buf; + } + + Local v8_name; + if (!String::NewFromUtf8(env->isolate(), type_str).ToLocal(&v8_name)) { + return MaybeLocal(); + } + + // The previous implementation used X509_NAME_print_ex, which escapes some + // characters in the value. The old implementation did not decode/unescape + // values correctly though, leading to ambiguous and incorrect + // representations. The new implementation only converts to Unicode and does + // not escape anything. + unsigned char* value_str; + int value_str_size = ASN1_STRING_to_UTF8(&value_str, value); + if (value_str_size < 0) { + return Undefined(env->isolate()); + } + + Local v8_value; + if (!String::NewFromUtf8(env->isolate(), + reinterpret_cast(value_str), + NewStringType::kNormal, + value_str_size).ToLocal(&v8_value)) { + OPENSSL_free(value_str); + return MaybeLocal(); + } + + OPENSSL_free(value_str); + + // For backward compatibility, we only create arrays if multiple values + // exist for the same key. That is not great but there is not much we can + // change here without breaking things. Note that this creates nested data + // structures, yet still does not allow representing Distinguished Names + // accurately. + if (result->HasOwnProperty(env->context(), v8_name).ToChecked()) { + Local accum = + result->Get(env->context(), v8_name).ToLocalChecked(); + if (!accum->IsArray()) { + accum = Array::New(env->isolate(), &accum, 1); + result->Set(env->context(), v8_name, accum).Check(); + } + Local array = accum.As(); + array->Set(env->context(), array->Length(), v8_value).Check(); + } else { + result->Set(env->context(), v8_name, v8_value).Check(); + } + } + + return result; +} + MaybeLocal GetCipherName(Environment* env, const SSLPointer& ssl) { return GetCipherName(env, SSL_get_current_cipher(ssl.get())); } @@ -1194,22 +1282,44 @@ MaybeLocal GetPeerCert( return result; } -MaybeLocal X509ToObject(Environment* env, X509* cert) { +MaybeLocal X509ToObject( + Environment* env, + X509* cert, + bool names_as_string) { EscapableHandleScope scope(env->isolate()); Local context = env->context(); Local info = Object::New(env->isolate()); BIOPointer bio(BIO_new(BIO_s_mem())); + if (names_as_string) { + // TODO(tniessen): this branch should not have to exist. It is only here + // because toLegacyObject() does not actually return a legacy object, and + // instead represents subject and issuer as strings. + if (!Set(context, + info, + env->subject_string(), + GetSubject(env, bio, cert)) || + !Set(context, + info, + env->issuer_string(), + GetIssuerString(env, bio, cert))) { + return MaybeLocal(); + } + } else { + if (!Set(context, + info, + env->subject_string(), + GetX509NameObject(env, cert)) || + !Set(context, + info, + env->issuer_string(), + GetX509NameObject(env, cert))) { + return MaybeLocal(); + } + } + if (!Set(context, - info, - env->subject_string(), - GetSubject(env, bio, cert)) || - !Set(context, - info, - env->issuer_string(), - GetIssuerString(env, bio, cert)) || - !Set(context, info, env->subjectaltname_string(), GetSubjectAltNameString(env, bio, cert)) || diff --git a/src/crypto/crypto_common.h b/src/crypto/crypto_common.h index b916c4c7eb6126..2e7ea236b40184 100644 --- a/src/crypto/crypto_common.h +++ b/src/crypto/crypto_common.h @@ -116,7 +116,8 @@ v8::MaybeLocal ECPointToBuffer( v8::MaybeLocal X509ToObject( Environment* env, - X509* cert); + X509* cert, + bool names_as_string = false); v8::MaybeLocal GetValidTo( Environment* env, diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc index 8ad453680bf998..7c299620dfeeb9 100644 --- a/src/crypto/crypto_x509.cc +++ b/src/crypto/crypto_x509.cc @@ -470,7 +470,7 @@ void X509Certificate::ToLegacy(const FunctionCallbackInfo& args) { X509Certificate* cert; ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); Local ret; - if (X509ToObject(env, cert->get()).ToLocal(&ret)) + if (X509ToObject(env, cert->get(), true).ToLocal(&ret)) args.GetReturnValue().Set(ret); } diff --git a/test/fixtures/x509-escaping/create-certs.js b/test/fixtures/x509-escaping/create-certs.js index b84547e1d0aef9..abb01756be56c0 100644 --- a/test/fixtures/x509-escaping/create-certs.js +++ b/test/fixtures/x509-escaping/create-certs.js @@ -500,3 +500,144 @@ for (let i = 0; i < infoAccessExtensions.length; i++) { }); writeFileSync(`./info-${i}-cert.pem`, `${pem}\n`); } + +const subjects = [ + [ + [ + { type: oid.localityName, value: UTF8String.encode('Somewhere') } + ], + [ + { type: oid.commonName, value: UTF8String.encode('evil.example.com') } + ] + ], + [ + [ + { + type: oid.localityName, + value: UTF8String.encode('Somewhere\0evil.example.com'), + } + ] + ], + [ + [ + { + type: oid.localityName, + value: UTF8String.encode('Somewhere\nCN=evil.example.com') + } + ] + ], + [ + [ + { + type: oid.localityName, + value: UTF8String.encode('Somewhere, CN = evil.example.com') + } + ] + ], + [ + [ + { + type: oid.localityName, + value: UTF8String.encode('Somewhere/CN=evil.example.com') + } + ] + ], + [ + [ + { + type: oid.localityName, + value: UTF8String.encode('M\u00fcnchen\\\nCN=evil.example.com') + } + ] + ], + [ + [ + { type: oid.localityName, value: UTF8String.encode('Somewhere') }, + { type: oid.commonName, value: UTF8String.encode('evil.example.com') }, + ] + ], + [ + [ + { + type: oid.localityName, + value: UTF8String.encode('Somewhere + CN=evil.example.com'), + } + ] + ], + [ + [ + { type: oid.localityName, value: UTF8String.encode('L1') }, + { type: oid.localityName, value: UTF8String.encode('L2') }, + ], + [ + { type: oid.localityName, value: UTF8String.encode('L3') }, + ] + ], + [ + [ + { type: oid.localityName, value: UTF8String.encode('L1') }, + ], + [ + { type: oid.localityName, value: UTF8String.encode('L2') }, + ], + [ + { type: oid.localityName, value: UTF8String.encode('L3') }, + ], + ], +]; + +for (let i = 0; i < subjects.length; i++) { + const tbs = { + version: 'v3', + serialNumber: new BN('01', 16), + signature: { + algorithm: oid.sha256WithRSAEncryption, + parameters: null_ + }, + issuer: { + type: 'rdnSequence', + value: subjects[i] + }, + validity: { + notBefore: { type: 'utcTime', value: now }, + notAfter: { type: 'utcTime', value: now + days * 86400000 } + }, + subject: { + type: 'rdnSequence', + value: subjects[i] + }, + subjectPublicKeyInfo: { + algorithm: { + algorithm: oid.rsaEncryption, + parameters: null_ + }, + subjectPublicKey: { + unused: 0, + data: publicKey + } + } + }; + + // Self-sign the certificate. + const tbsDer = rfc5280.TBSCertificate.encode(tbs, 'der'); + const signature = crypto.createSign(digest).update(tbsDer).sign(privateKey); + + // Construct the signed certificate. + const cert = { + tbsCertificate: tbs, + signatureAlgorithm: { + algorithm: oid.sha256WithRSAEncryption, + parameters: null_ + }, + signature: { + unused: 0, + data: signature + } + }; + + // Store the signed certificate. + const pem = rfc5280.Certificate.encode(cert, 'pem', { + label: 'CERTIFICATE' + }); + writeFileSync(`./subj-${i}-cert.pem`, `${pem}\n`); +} diff --git a/test/fixtures/x509-escaping/subj-0-cert.pem b/test/fixtures/x509-escaping/subj-0-cert.pem new file mode 100644 index 00000000000000..ae853c893125be --- /dev/null +++ b/test/fixtures/x509-escaping/subj-0-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE1zCCAr+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAvMRIwEAYDVQQHDAlTb21l +d2hlcmUxGTAXBgNVBAMMEGV2aWwuZXhhbXBsZS5jb20wHhcNMjExMjIwMTQ1NzM1 +WhcNMzExMjE4MTQ1NzM1WjAvMRIwEAYDVQQHDAlTb21ld2hlcmUxGTAXBgNVBAMM +EGV2aWwuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCxEWd00u9E9T/ko6WcCKjhZ7tjnfVylnA7M0EHOwvdivgD46eAb1omsonLagiV +rZrG7EpYuMhtz+g3Yv1d0nvFvv8ge9UIdnN8EDTDzLpJ3KbNqHURraiXuBDqa3rd +Y4JBakCcuYHl1bj1OTew7xl1FWc1je04rBTQGTFIRdmJZYyc9bIw9WkY6msod0w1 +PDcLhZS3emh/eYaL4zAQWrVhQfWzf4rZzFaI/a5n0o75aUkTuvxDDQ51V2d6WkSU +3KbOnf2JW+QJXfzsNOeiYA9AnfY59evr4GEeG8VZdGuUG39uDCIWmAUT8elhXXqV +q+NdBqc6VUNLDJbqCmMx/Ecp48EHO6X5uXm0xViZIVPNIzqiiRhVt4nFfwPQZrTg +aq2+tD7/zD1yED4O1FhlDl5twH2N7+oG06HsEluQdLPrj7IedpneGVKMs078Ddov +7j6icYv/RZHVetDlrzDDHjLJWwxyAWzdGdkhtMGPd6B9i4TtF/PU3J3nbpLn5XfE +BFu4jJ+w+5Wvk5a60gF1ERy/OLBM/e8sro2sEBIpp1tN1wJVBZOtTIi4VVDhwDRQ +Uiwb2d1Re7GQ7+mcz5D/01qxW6S+w0IKrpwJUjR3mpa0OU98KfKVJkeyeEBLkEhD +dnGTDqZ9E/ickGosrW2gAAYKgzXk725dpxTdpLEosfDbpwIDAQABMA0GCSqGSIb3 +DQEBCwUAA4ICAQAnszSuVqfEmpjf2VMvk9TUuiop0tejHP+hB30IURJqA9K51edx +IRszXXU4Sj8uHT88RpKxgDm/GcfEA0l2rWZ6Mal6pmUyjteJJPMVA6fgeNM8XvtJ +eoxi2wm8FzxXJrPK7fOMG5/fLb7ENUZYFRHVFJ+Gk290DP7x81Gzb5tcsolrVqW+ +TZdV2aBZya28NjgXncjinIlD61I6LzoQbDInab5nEPKMRuRTXMLfbAypXrPAbsfz ++Z6ZKhfNEo0/5cI4iG8MQXM1HgbFCkWOTPPeR53lo+1f9dN3IZ+1PYUjkOJzuxUZ +HIA+Dy+S1ocfK582LqohexhjeC5AL74rJJcgns9ORxz2GN1buIRTzi9XL2egp7cd ++XgZ3phpY4mIM0bH+DJ7eIqkM17WkEwJ3vazu7tEmIldc06Pmt2vFEcQB3T0bsw7 +lBZdwSEkqTb+IexaQerSyztuxKc2DhOLTqZfVPCd2LWhasNSHzGmanI3vmBy98MN +LZzo7+G1BDMyMsl3DwEiwOGYARXJklU1LxCj6nVCTymNToLXtF2xHcZuK94Pqol9 +n8zMCUYNOr7USWA25GwfpN65UHN7YXsOl9XIMWl+iVA5QepAI9sL0n3CyFW0ZXgn +DsZkfikYa+xhQSUANV4zDx1X8FxZmT0Op/+mhkvwL1+YKUHJy3WdXrIFgw== +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-1-cert.pem b/test/fixtures/x509-escaping/subj-1-cert.pem new file mode 100644 index 00000000000000..3e193e25c2cf2a --- /dev/null +++ b/test/fixtures/x509-escaping/subj-1-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQHDBpTb21l +d2hlcmUAZXZpbC5leGFtcGxlLmNvbTAeFw0yMTEyMjAxNDU3MzVaFw0zMTEyMTgx +NDU3MzVaMCUxIzAhBgNVBAcMGlNvbWV3aGVyZQBldmlsLmV4YW1wbGUuY29tMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsRFndNLvRPU/5KOlnAio4We7 +Y531cpZwOzNBBzsL3Yr4A+OngG9aJrKJy2oIla2axuxKWLjIbc/oN2L9XdJ7xb7/ +IHvVCHZzfBA0w8y6Sdymzah1Ea2ol7gQ6mt63WOCQWpAnLmB5dW49Tk3sO8ZdRVn +NY3tOKwU0BkxSEXZiWWMnPWyMPVpGOprKHdMNTw3C4WUt3pof3mGi+MwEFq1YUH1 +s3+K2cxWiP2uZ9KO+WlJE7r8Qw0OdVdnelpElNymzp39iVvkCV387DTnomAPQJ32 +OfXr6+BhHhvFWXRrlBt/bgwiFpgFE/HpYV16lavjXQanOlVDSwyW6gpjMfxHKePB +Bzul+bl5tMVYmSFTzSM6ookYVbeJxX8D0Ga04GqtvrQ+/8w9chA+DtRYZQ5ebcB9 +je/qBtOh7BJbkHSz64+yHnaZ3hlSjLNO/A3aL+4+onGL/0WR1XrQ5a8wwx4yyVsM +cgFs3RnZIbTBj3egfYuE7Rfz1Nyd526S5+V3xARbuIyfsPuVr5OWutIBdREcvziw +TP3vLK6NrBASKadbTdcCVQWTrUyIuFVQ4cA0UFIsG9ndUXuxkO/pnM+Q/9NasVuk +vsNCCq6cCVI0d5qWtDlPfCnylSZHsnhAS5BIQ3Zxkw6mfRP4nJBqLK1toAAGCoM1 +5O9uXacU3aSxKLHw26cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAmjKOoKxLwPY4 +e65pYTUSBctPZ2juW5uNs8UvH5O32OC9RhENJBIIKn3B9Z/wkexR2zcvaQmJObLW +6mkR7O0tNgsXVYJFzLRBfjM/nyP6nafiCUekmoh9Kojq6x5IQQgEsK+Uw123kkoI +w/h3hBYBq8+CFPnYtBLZBVVFMNGaATXrYJPCcjVrtAHYxIWaDN2R+1DWLRIV72sF +hu4xGz0kmUbzforl/FA3gdgM7mwfZMF4+EoQZi5mShdWnyfzAHIbtahnA4lPNtx9 +vBqYIZ/a2ITsXmWc2KGs/rRG+SDLzg+H1Xudvu/y2d1ULpZQfT6bg6Ro855FiU9h +TyHHQGGqlC9/DjHy//wERsFEJZh5/j21LGyalEjgfOYtzPkjZlIweYr8LlHTrauo +/gWihriaaWAkD+2fwQ09CUHdvOG6yoT+j/E50FsekfqV3tKMwoZoph6dF1TWQg32 +JXV0akpd5ff1cca8sZgJfUksDfSkrwG7fl3tje30vQTlvNrhu2MCKFGQwyXed3qg +86lx+sTZjxMYvqWWysKTx8aIJ95XAK2jJ2OEVI2X6cdgoAp6aMkycbttik4hDoPJ +eAWaZo2UFs2MGoUbX9m4RzPqPuBHNFqoV6yRyS1K/3KWyxVVvamZY0Qgzmoi4coB +hRlTO6GDkF7u1YQ7eZi7pP7U8OcklfE= +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-2-cert.pem b/test/fixtures/x509-escaping/subj-2-cert.pem new file mode 100644 index 00000000000000..e6a23dccddbd51 --- /dev/null +++ b/test/fixtures/x509-escaping/subj-2-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEyTCCArGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQHDB1Tb21l +d2hlcmUKQ049ZXZpbC5leGFtcGxlLmNvbTAeFw0yMTEyMjAxNDU3MzVaFw0zMTEy +MTgxNDU3MzVaMCgxJjAkBgNVBAcMHVNvbWV3aGVyZQpDTj1ldmlsLmV4YW1wbGUu +Y29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsRFndNLvRPU/5KOl +nAio4We7Y531cpZwOzNBBzsL3Yr4A+OngG9aJrKJy2oIla2axuxKWLjIbc/oN2L9 +XdJ7xb7/IHvVCHZzfBA0w8y6Sdymzah1Ea2ol7gQ6mt63WOCQWpAnLmB5dW49Tk3 +sO8ZdRVnNY3tOKwU0BkxSEXZiWWMnPWyMPVpGOprKHdMNTw3C4WUt3pof3mGi+Mw +EFq1YUH1s3+K2cxWiP2uZ9KO+WlJE7r8Qw0OdVdnelpElNymzp39iVvkCV387DTn +omAPQJ32OfXr6+BhHhvFWXRrlBt/bgwiFpgFE/HpYV16lavjXQanOlVDSwyW6gpj +MfxHKePBBzul+bl5tMVYmSFTzSM6ookYVbeJxX8D0Ga04GqtvrQ+/8w9chA+DtRY +ZQ5ebcB9je/qBtOh7BJbkHSz64+yHnaZ3hlSjLNO/A3aL+4+onGL/0WR1XrQ5a8w +wx4yyVsMcgFs3RnZIbTBj3egfYuE7Rfz1Nyd526S5+V3xARbuIyfsPuVr5OWutIB +dREcvziwTP3vLK6NrBASKadbTdcCVQWTrUyIuFVQ4cA0UFIsG9ndUXuxkO/pnM+Q +/9NasVukvsNCCq6cCVI0d5qWtDlPfCnylSZHsnhAS5BIQ3Zxkw6mfRP4nJBqLK1t +oAAGCoM15O9uXacU3aSxKLHw26cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAEMEW +EElTS/lgeoWvTruGEqmpwS86NE+j+Ws+VnUXnjo2RSqs4tSICkBzJsi4g/WHNa5V +TzD42MOmyQTUGaJ96Cpq8VmL8pE0mYKo1wXsi8WonDgaw0Eup6v9ga5kHPfKJBvV +dqEP+upiAbYXxlISj+xgOVW5WBJ3tBic1Iyg/oOKlHwXYA0IKc1MOLlvh0EdVqj7 +2cYodO7nuAmeFLpf5RDtGTNMWt/whoqv+vUb5iy2pDdDNMJdoa0hT/L4E+ibl0ZA +7W/RKkcXJ0RlZMA7rYGjQ2/lasHvMniHlfLZd2UtChVgs8hY/b1PCLubyiz1peCj +Q8Y4VoveePnxfovTPvcvMxPbNiCLPJtsPhWq1KPbOyBpKBc/mJ6I5DmszQB16Jb2 +fq6RfrrXjC1C+vYN4KCUGPbS+J4eZ0a04C4OdSGED02YSOpLIBnfNRMDyXZQ6Hhd +sZSvyOAD3UhugEloCV9cnFKVglbXaW3k97xeYg/86udVPrgiAEn7u3Lsr9U1wZ2x +wFgE4js1IzeIvIZOk9wDQHPolUiPaZUvMZXfM7+i9X9qX9AgtUAxnO0y0U9zXrUB +Xjdtfddb4XAHdrPnuBkCb/75JeQ4JroP3t59iY0SFuQ0TH9YkOJULrw7oTqqmLo+ +PAFMiK1/kbmpVsT92k2WLjPgrAXe+lslQPwXBNM= +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-3-cert.pem b/test/fixtures/x509-escaping/subj-3-cert.pem new file mode 100644 index 00000000000000..48bee70c9b2620 --- /dev/null +++ b/test/fixtures/x509-escaping/subj-3-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzzCCAregAwIBAgIBATANBgkqhkiG9w0BAQsFADArMSkwJwYDVQQHDCBTb21l +d2hlcmUsIENOID0gZXZpbC5leGFtcGxlLmNvbTAeFw0yMTEyMjAxNDU3MzVaFw0z +MTEyMTgxNDU3MzVaMCsxKTAnBgNVBAcMIFNvbWV3aGVyZSwgQ04gPSBldmlsLmV4 +YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsRFndNLv +RPU/5KOlnAio4We7Y531cpZwOzNBBzsL3Yr4A+OngG9aJrKJy2oIla2axuxKWLjI +bc/oN2L9XdJ7xb7/IHvVCHZzfBA0w8y6Sdymzah1Ea2ol7gQ6mt63WOCQWpAnLmB +5dW49Tk3sO8ZdRVnNY3tOKwU0BkxSEXZiWWMnPWyMPVpGOprKHdMNTw3C4WUt3po +f3mGi+MwEFq1YUH1s3+K2cxWiP2uZ9KO+WlJE7r8Qw0OdVdnelpElNymzp39iVvk +CV387DTnomAPQJ32OfXr6+BhHhvFWXRrlBt/bgwiFpgFE/HpYV16lavjXQanOlVD +SwyW6gpjMfxHKePBBzul+bl5tMVYmSFTzSM6ookYVbeJxX8D0Ga04GqtvrQ+/8w9 +chA+DtRYZQ5ebcB9je/qBtOh7BJbkHSz64+yHnaZ3hlSjLNO/A3aL+4+onGL/0WR +1XrQ5a8wwx4yyVsMcgFs3RnZIbTBj3egfYuE7Rfz1Nyd526S5+V3xARbuIyfsPuV +r5OWutIBdREcvziwTP3vLK6NrBASKadbTdcCVQWTrUyIuFVQ4cA0UFIsG9ndUXux +kO/pnM+Q/9NasVukvsNCCq6cCVI0d5qWtDlPfCnylSZHsnhAS5BIQ3Zxkw6mfRP4 +nJBqLK1toAAGCoM15O9uXacU3aSxKLHw26cCAwEAATANBgkqhkiG9w0BAQsFAAOC +AgEAFvcwnV5K6KH4jvYFUccZDEVZ2WFuZsqJVD5N4nX5KgHmnSzyDYgHRRZ4oGiN +eTgi+3B6S5TPRTMLUaO7hnFxilnfr3HlhsQhGVh+Qb+ovyL1evsrCu8CzmmFMJs1 +bHm/ct/HzDfNgrx7HEZbrpesNjka05UWhIewA/64IkSMFoGbrjb35WINpcHQNgvQ +X5YnUTk3U+DyDHGeRvZ9dsYBXnK7Q+s6lbS1Bvl3G65SZq9fxqtxLnwloP5ms62j +r7OLdQ/IDYFu0v/HKkA9Ms/NJyKtoPUXYyiP0qQPq2A9lDRW07goCaR7WApmU4Sr +uYQVAPCFbEJGQtjUVUrmEdlEuNaiaMM7+iB5WEXaQ8M8gRX+4U7lbk7HsRSsHlDn +9/1sAOxrWAnCffoYSrUwruD8SKVCTBlkYs5pPSIkfz/yzwNq5u6ebe5ATJBjIv+H +N4nflcrY18oMAz694f+94RUFat/5wX+WsnNT4Av+bVz6Gv5nbGJGXurUArrne5F9 +G+ESYu2KuGIRhxrOrBIvZapv9lITlBm9t8kChBbR9YZC4dD0+lu72h4xH3iXeeBl +MFmP1mk8zxuIwH6H/bM70B5NAHEw4U5guthnRU5YSK5EpvXhNl/JqdSp8xskfYCM +62dhRqgQNL0HZxKJO61bn3XBvVKLPNpCqBD5KQsI0R4wevM= +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-4-cert.pem b/test/fixtures/x509-escaping/subj-4-cert.pem new file mode 100644 index 00000000000000..c23922d99190ae --- /dev/null +++ b/test/fixtures/x509-escaping/subj-4-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEyTCCArGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQHDB1Tb21l +d2hlcmUvQ049ZXZpbC5leGFtcGxlLmNvbTAeFw0yMTEyMjAxNDU3MzVaFw0zMTEy +MTgxNDU3MzVaMCgxJjAkBgNVBAcMHVNvbWV3aGVyZS9DTj1ldmlsLmV4YW1wbGUu +Y29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsRFndNLvRPU/5KOl +nAio4We7Y531cpZwOzNBBzsL3Yr4A+OngG9aJrKJy2oIla2axuxKWLjIbc/oN2L9 +XdJ7xb7/IHvVCHZzfBA0w8y6Sdymzah1Ea2ol7gQ6mt63WOCQWpAnLmB5dW49Tk3 +sO8ZdRVnNY3tOKwU0BkxSEXZiWWMnPWyMPVpGOprKHdMNTw3C4WUt3pof3mGi+Mw +EFq1YUH1s3+K2cxWiP2uZ9KO+WlJE7r8Qw0OdVdnelpElNymzp39iVvkCV387DTn +omAPQJ32OfXr6+BhHhvFWXRrlBt/bgwiFpgFE/HpYV16lavjXQanOlVDSwyW6gpj +MfxHKePBBzul+bl5tMVYmSFTzSM6ookYVbeJxX8D0Ga04GqtvrQ+/8w9chA+DtRY +ZQ5ebcB9je/qBtOh7BJbkHSz64+yHnaZ3hlSjLNO/A3aL+4+onGL/0WR1XrQ5a8w +wx4yyVsMcgFs3RnZIbTBj3egfYuE7Rfz1Nyd526S5+V3xARbuIyfsPuVr5OWutIB +dREcvziwTP3vLK6NrBASKadbTdcCVQWTrUyIuFVQ4cA0UFIsG9ndUXuxkO/pnM+Q +/9NasVukvsNCCq6cCVI0d5qWtDlPfCnylSZHsnhAS5BIQ3Zxkw6mfRP4nJBqLK1t +oAAGCoM15O9uXacU3aSxKLHw26cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAQD16 +wSsZodV3hk98VYDyXBuQdzrlF1zXm5n7Dx+ONGw62d3FRRaegbkwBfvUf7P+ZfR/ +qUFZQwWKYZ+hYos/gIvYuBRJSSg8nrGrHkp+AXIxQ6ZmgVAat3OnLdzG+k0Cras6 +vzRrEohL3JnXCBVZ+4MMnNrZFhGzQ9rHGJtrarkZ5NQMhH8VbfdtuKDpwS8O9mtI +MqoNTIViocqtBem8ZD5z+m9A5UT8DMKwL+gjDQQ3j/flfmAq5bcqZkkIrJol3mrp +4Ol1Hc4/tVMa1wsnEtYGWEOfBJqANY3m5IiEBHIyeP67NR68fdlZ+XFpdHNl5/LV +XwjGquv0jSE3CbKR1ez5sefn1fmCWVZi5mZV6O8jpT7Ztu1XL8jOxTxtCMKE6cCC +xgEL2HFG4JWeA/z5ZXT8U+4Bfiu1GXBMxF5LJc89DORTBRIWMR1IHca+nOb2zHNF +v4QOfqLKF+ko5D/ie9Xg1s49l6lI8NReg9NRRp2sc90Zxc0Pqz7wdNH2SMUC/+gR +kWhz77OhACeXpcRQVy0Bi64l5Or+05ZB2piK6OemcFUKIybKjxUbzuwZdrqj0vK6 +Tw1nemA1BCH8X+b1rz6kDKPycBAEdtMoRSFzbtZbdjBR1g0PLGeYn8rL2gsLMpaN +1XTCTb7BAAy0Ky4cpMduD+uYGbma9V4ER3RLdL8= +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-5-cert.pem b/test/fixtures/x509-escaping/subj-5-cert.pem new file mode 100644 index 00000000000000..6c1c87e2ce9b73 --- /dev/null +++ b/test/fixtures/x509-escaping/subj-5-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEyTCCArGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQHDB1Nw7xu +Y2hlblwKQ049ZXZpbC5leGFtcGxlLmNvbTAeFw0yMTEyMjAxNDU3MzVaFw0zMTEy +MTgxNDU3MzVaMCgxJjAkBgNVBAcMHU3DvG5jaGVuXApDTj1ldmlsLmV4YW1wbGUu +Y29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsRFndNLvRPU/5KOl +nAio4We7Y531cpZwOzNBBzsL3Yr4A+OngG9aJrKJy2oIla2axuxKWLjIbc/oN2L9 +XdJ7xb7/IHvVCHZzfBA0w8y6Sdymzah1Ea2ol7gQ6mt63WOCQWpAnLmB5dW49Tk3 +sO8ZdRVnNY3tOKwU0BkxSEXZiWWMnPWyMPVpGOprKHdMNTw3C4WUt3pof3mGi+Mw +EFq1YUH1s3+K2cxWiP2uZ9KO+WlJE7r8Qw0OdVdnelpElNymzp39iVvkCV387DTn +omAPQJ32OfXr6+BhHhvFWXRrlBt/bgwiFpgFE/HpYV16lavjXQanOlVDSwyW6gpj +MfxHKePBBzul+bl5tMVYmSFTzSM6ookYVbeJxX8D0Ga04GqtvrQ+/8w9chA+DtRY +ZQ5ebcB9je/qBtOh7BJbkHSz64+yHnaZ3hlSjLNO/A3aL+4+onGL/0WR1XrQ5a8w +wx4yyVsMcgFs3RnZIbTBj3egfYuE7Rfz1Nyd526S5+V3xARbuIyfsPuVr5OWutIB +dREcvziwTP3vLK6NrBASKadbTdcCVQWTrUyIuFVQ4cA0UFIsG9ndUXuxkO/pnM+Q +/9NasVukvsNCCq6cCVI0d5qWtDlPfCnylSZHsnhAS5BIQ3Zxkw6mfRP4nJBqLK1t +oAAGCoM15O9uXacU3aSxKLHw26cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAipRw +3Q8C0CUYTQJlYTAdmATrboUFATpex+ZFhQgQPPWs/tUvf8zWU+DdDjFjrLNCY+ew +FaURBnNQ92AE3LVDayu3Jh6TMoHKMAnPOERaiMuHDoKr/T4JVk2vWSBck6aYbokl +7W7/ucMTVyPS9tLiuIwyJ+0dta+ucQSjIZj2RtCzsOtxdbUqt/7iTJrl8EjZGGbH +FTKSbFBY2mR9oFKhoyCaVV0Alw1//napqdzu93gNqZx3cXskA0T63GxyhjhVpFq8 +d1ILGB3yKAiIzc5epNKx8ZPSUddx7zK0FAXRtBGHcOTES3+kTljkxmXAFDGTrMk0 +fsWgKfDDkDEGaUHL43524HLnPUoQASdQ9Uk5r7TDkl/kATv5w+HpWKdd3sxcSH8m +UeUFCFdJbcOyqKfF7jz8kCe08Xt2sEW5tKZb4xWjI+mm01PCNeyCsaAw4OlSDUEm +63fCsXY/b+i0hOxdd/eusoq3B76ngOEGaEJ8jOvpxeyHuet9kDet5M48aQRE9S9x +HJWLL+80mFt4yiRHPUob/WP+4L7EnBjmiVBevEO0sptYLqymdRuCy4Ub4/QIQnNW +kFasltzL/WEe1TzpTNziqOk1jEHA06D5Euwy/mI+S0Y0uvFOYC+tVkspsCNikrTu +Fj0Lqyg5tqQJM3msSEfJvaJhUydaeIZp1Cr535Y= +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-6-cert.pem b/test/fixtures/x509-escaping/subj-6-cert.pem new file mode 100644 index 00000000000000..82912d7c269f69 --- /dev/null +++ b/test/fixtures/x509-escaping/subj-6-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE0zCCArugAwIBAgIBATANBgkqhkiG9w0BAQsFADAtMSswEAYDVQQHDAlTb21l +d2hlcmUwFwYDVQQDDBBldmlsLmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoX +DTMxMTIxODE0NTczNVowLTErMBAGA1UEBwwJU29tZXdoZXJlMBcGA1UEAwwQZXZp +bC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALER +Z3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4BvWiayictqCJWtmsbs +Sli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGtqJe4EOpret1jgkFq +QJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1aRjqayh3TDU8NwuF +lLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMNDnVXZ3paRJTcps6d +/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaYBRPx6WFdepWr410G +pzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3icV/A9BmtOBqrb60 +Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4ZUoyzTvwN2i/uPqJx +i/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tcnedukufld8QEW7iM +n7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61MiLhVUOHANFBSLBvZ +3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUmR7J4QEuQSEN2cZMO +pn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAEwDQYJKoZIhvcNAQEL +BQADggIBAAdRC4tmZb5tukc4pIdnzRyrzNq3uefQNLcrZpZaCKAWvey+AFOZw88N +nnjUT0A3bXA2YJPKQtRaSJG+UBH3xgRNOM0ttvKYqmzZDt/ygzxRlTMt80AVVyMG +P06D5UUZHEX6aUchS/noDI5jewZy23jINEAzQv8B72r8WjV/LwjbJ1IoBg08gJhO +QQCfeDaJ0sAQCL1tdlwiS6Q3N6rkC3jLzBHCzXP0FN5OF5rxr6nlfHiTOuhTdodR +p/UrLVADdvpXq6SegbTvZ7/KwNWzzAmOEx2MAHFQKh46S1+RHQE3L7SV9dqV2XCe +OxfBPPXTy+AiceKhVL0+jhdI/VWIdhTHSCeFuzrGbrLQwWLCDZ5AZjS/JaBXuVGl +WILzz3ZG6ekdqMY/qG8weDEFv49f03MGWoX27uhkz4qtumLzrXEspzL7GwUfnDZo +zyF9Jo9vJVNmiz/N2DnUd0X5hdHUsjnN8vPN+3u5kkvfXTgT9wUrMgzECu/tyC92 +GAX0MqY6lKJwTT+pxkZPUNGMbP8c3BuO9NVGPUeOA+/4sgsws+V0TDF7umNk2nq3 +vCuS+QFZXAR4Ns2xgIOMH8XQjRZ4qSp3HsFNehOqSQrFvcgjMLo0RcgiwgReUMl+ +Pnhjk+V4ttEIUe3UswaRHD9moG4sgCfFk/bafwCvdKonD6mBETMa +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-7-cert.pem b/test/fixtures/x509-escaping/subj-7-cert.pem new file mode 100644 index 00000000000000..fd645da96540be --- /dev/null +++ b/test/fixtures/x509-escaping/subj-7-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzTCCArWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAqMSgwJgYDVQQHDB9Tb21l +d2hlcmUgKyBDTj1ldmlsLmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMx +MTIxODE0NTczNVowKjEoMCYGA1UEBwwfU29tZXdoZXJlICsgQ049ZXZpbC5leGFt +cGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALERZ3TS70T1 +P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4BvWiayictqCJWtmsbsSli4yG3P +6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGtqJe4EOpret1jgkFqQJy5geXV +uPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1aRjqayh3TDU8NwuFlLd6aH95 +hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMNDnVXZ3paRJTcps6d/Ylb5Ald +/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaYBRPx6WFdepWr410GpzpVQ0sM +luoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3icV/A9BmtOBqrb60Pv/MPXIQ +Pg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4ZUoyzTvwN2i/uPqJxi/9FkdV6 +0OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tcnedukufld8QEW7iMn7D7la+T +lrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61MiLhVUOHANFBSLBvZ3VF7sZDv +6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUmR7J4QEuQSEN2cZMOpn0T+JyQ +aiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAEwDQYJKoZIhvcNAQELBQADggIB +AAG8vjV7c4B4yKO2BDhufVjkmzot97SPf4qR0qJATAV+Iifm5D2YL/dr36kyvTiK +JoPU/0vztcnh5X75YzvEtD4xh5zg3FQdAEpGx4zZkNXkJt2syz3V3DFG9Te4GH3n +/a39z4yn2J2MG2uXj+TTSJR23ICAgqNkj4EtrwvOouAqLCR/yZuYaUM6ZPmEYrHM +5wwiMCheDgMUYvFhTIKAwalnQitCGQCFr5WvTHU/0oVn498miZEU5LPAIiuhIQoA +UI/tro47evU/Nli8WY9UImLbcWkbIS7MogtWhjDQXd80G3sX+9DpVO43S2Cf4shB +yXl49bvqITMXdurSQrNKbfQ5aLDmKno4Qjs9wZMmi2xhIKczuB4bdtQDsC0/LiSr +oydiSP9uxYatT6SedzgkypTOL/5qtuh14Z7aRio5s4WrIDDJ1RVlWJGffq4hF+j/ +cu5OHo4cyvN42+bnyYzAWpOE7h8Nmi0D14zvm1FE3FKVSlBZzScBBungVdJkchAP +4JleXVqfH5skLgMiYCa3qocfUEfeKTCVXJUxaPIvBILtcOYzx75B0izsVlsd/dr+ +DqoIKN9aMGyuKR0QZtmW97eCxaH6Dm7lVuym56hiQrT3J0PL2iU+LU1R9UfLE/pL +RjUWW/gbxxNq8dbFybiUM7Sj+6tWuVvLygA04lMeDIDq +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-8-cert.pem b/test/fixtures/x509-escaping/subj-8-cert.pem new file mode 100644 index 00000000000000..edd4b460b13ba8 --- /dev/null +++ b/test/fixtures/x509-escaping/subj-8-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMRYwCQYDVQQHDAJMMTAJ +BgNVBAcMAkwyMQswCQYDVQQHDAJMMzAeFw0yMTEyMjAxNDU3MzVaFw0zMTEyMTgx +NDU3MzVaMCUxFjAJBgNVBAcMAkwxMAkGA1UEBwwCTDIxCzAJBgNVBAcMAkwzMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsRFndNLvRPU/5KOlnAio4We7 +Y531cpZwOzNBBzsL3Yr4A+OngG9aJrKJy2oIla2axuxKWLjIbc/oN2L9XdJ7xb7/ +IHvVCHZzfBA0w8y6Sdymzah1Ea2ol7gQ6mt63WOCQWpAnLmB5dW49Tk3sO8ZdRVn +NY3tOKwU0BkxSEXZiWWMnPWyMPVpGOprKHdMNTw3C4WUt3pof3mGi+MwEFq1YUH1 +s3+K2cxWiP2uZ9KO+WlJE7r8Qw0OdVdnelpElNymzp39iVvkCV387DTnomAPQJ32 +OfXr6+BhHhvFWXRrlBt/bgwiFpgFE/HpYV16lavjXQanOlVDSwyW6gpjMfxHKePB +Bzul+bl5tMVYmSFTzSM6ookYVbeJxX8D0Ga04GqtvrQ+/8w9chA+DtRYZQ5ebcB9 +je/qBtOh7BJbkHSz64+yHnaZ3hlSjLNO/A3aL+4+onGL/0WR1XrQ5a8wwx4yyVsM +cgFs3RnZIbTBj3egfYuE7Rfz1Nyd526S5+V3xARbuIyfsPuVr5OWutIBdREcvziw +TP3vLK6NrBASKadbTdcCVQWTrUyIuFVQ4cA0UFIsG9ndUXuxkO/pnM+Q/9NasVuk +vsNCCq6cCVI0d5qWtDlPfCnylSZHsnhAS5BIQ3Zxkw6mfRP4nJBqLK1toAAGCoM1 +5O9uXacU3aSxKLHw26cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAGNhY0vKd8Os9 +75+HHQH03BugatuIykpSu+tj8OYr2/7VLT76qUaKdkAZV0m9TiS8MitHZieEbig3 +EozQtYrTZQbiFjiV8FudPsmAXZxcz1TdE25mZykWe24FmZNdeMQmoVRZYbg3gb/M +sTEDbnV3DoW6X8LWMlitaBpisxg/LqHakATvj6Otvts8RFhI1c/JFx8THuY14Fj1 +sJ8eFdwebPK35V4ZNtH8bevVo9MvnUS290fF1WDC1dnjZ1zYqHT7sPoGbCFF4kne +TF2Ef12BgUNtgJKnXeEV5Gull4iOQS8qTkWCIm8jbz1+9ap8nqVcGn60bkwiMmgz +hNyBW7c31MvEfedfCwFma/uV1yMB2nGwX47TMnTTjwc5b2I/lOrFOfeh2JD9QVZF +XFKRsVXqCwa3aLc1fc93M9kEHzKWzGgMjYvJzZEGsoqTil22NmQXIG7jKjLth7zF +4Sc/qBDXsLaqUaWQveZ9U6suFYr9u2X7h3KkciFtsZPFK+AZGO07z/4nWEeo4frV +RyltN38BmJxwBSxNEZFBiMJ9AEmg2EhgBXJbEhN9XCwpW2EEp+M09AfcebzKjJ+h +3Q7AWlTPawz/PQzzunZzNMkq7/6Y/dIFg/Ak8RIPkMVb3xE9oD0wMWigyiK05UUI +832NnZXih3qq15MfVS4eTSeKrNcFt3c= +-----END CERTIFICATE----- diff --git a/test/fixtures/x509-escaping/subj-9-cert.pem b/test/fixtures/x509-escaping/subj-9-cert.pem new file mode 100644 index 00000000000000..5490e2ea3e5aed --- /dev/null +++ b/test/fixtures/x509-escaping/subj-9-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExzCCAq+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQHDAJMMTEL +MAkGA1UEBwwCTDIxCzAJBgNVBAcMAkwzMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIx +ODE0NTczNVowJzELMAkGA1UEBwwCTDExCzAJBgNVBAcMAkwyMQswCQYDVQQHDAJM +MzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALERZ3TS70T1P+SjpZwI +qOFnu2Od9XKWcDszQQc7C92K+APjp4BvWiayictqCJWtmsbsSli4yG3P6Ddi/V3S +e8W+/yB71Qh2c3wQNMPMukncps2odRGtqJe4EOpret1jgkFqQJy5geXVuPU5N7Dv +GXUVZzWN7TisFNAZMUhF2YlljJz1sjD1aRjqayh3TDU8NwuFlLd6aH95hovjMBBa +tWFB9bN/itnMVoj9rmfSjvlpSRO6/EMNDnVXZ3paRJTcps6d/Ylb5Ald/Ow056Jg +D0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaYBRPx6WFdepWr410GpzpVQ0sMluoKYzH8 +RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUO +Xm3AfY3v6gbToewSW5B0s+uPsh52md4ZUoyzTvwN2i/uPqJxi/9FkdV60OWvMMMe +MslbDHIBbN0Z2SG0wY93oH2LhO0X89Tcnedukufld8QEW7iMn7D7la+TlrrSAXUR +HL84sEz97yyujawQEimnW03XAlUFk61MiLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/T +WrFbpL7DQgqunAlSNHealrQ5T3wp8pUmR7J4QEuQSEN2cZMOpn0T+JyQaiytbaAA +BgqDNeTvbl2nFN2ksSix8NunAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAEeFRIyV +5PdD7Xipg3byNhcCH6I8gADM+Ipnxic93COfQrWCKd/lnsJzxml7VhyANScUTx44 +wkYs+kW9Xi/tEViVwrsFzlTB3YwaAYPiGNtr98B4JBUfLneHSh8IUeeMUnBeLt4O +eqo3ts38hCfY3B3E2FtV9nRBKu91ZwE+pInWftdTJ6pIkltr+t9kPbVFW72hYfQJ +rdtyzIiSkTnJElcvNcWtsqEmTMLewgZz/bjbZkQh/LXQDT7oepZBZ5Qb4F8kwytb +wGC/OFoByWyXYfuPWKb2obdnbb5xa1vg8rLVdVgY25q+VeNItBB/FSzf0Pnxd9od +jVVtzvby57A0IT7XpTu8RFAkuWmZp4FO5kDyXLNgsd6md/qeqcO5V7dY6MSKeIXw +nMYTBWuxOZPMw2RnxjcfkEdN/5sDuYHnzuizkH+OiwPPfs2qa4EETaxo5xxmTcy+ +pDh0GEOIgyazpJnncgG1k1ABOcHevRaCpm8NuXexkfpAHEORNfOflRkJDICXSUxv +5o2VjOhqj8gRqLvpGBW3hCxVM/Of2Fzdye0ldoDhzcW0WxjzmcjcC5EEEVSapwok +K5+ZvVFjqW2j619UICFf95tCtB025AzWWwVVQ9rlnCWL0MOrOwe66vYERG2MUYAD +jcB7FUOjXh2+3Gkh1PzXiXCQatDLhIVt9Vus +-----END CERTIFICATE----- diff --git a/test/parallel/test-x509-escaping.js b/test/parallel/test-x509-escaping.js index 5970f243471037..ba11dde79b0821 100644 --- a/test/parallel/test-x509-escaping.js +++ b/test/parallel/test-x509-escaping.js @@ -247,6 +247,115 @@ const { hasOpenSSL3 } = common; } } +// Test escaping rules for the subject field. +{ + const expectedSubjects = [ + { + text: 'L=Somewhere\nCN=evil.example.com', + legacy: { + L: 'Somewhere', + CN: 'evil.example.com', + }, + }, + { + text: 'L=Somewhere\\00evil.example.com', + legacy: { + L: 'Somewhere\0evil.example.com', + }, + }, + { + text: 'L=Somewhere\\0ACN=evil.example.com', + legacy: { + L: 'Somewhere\nCN=evil.example.com' + }, + }, + { + text: 'L=Somewhere\\, CN = evil.example.com', + legacy: { + L: 'Somewhere, CN = evil.example.com' + }, + }, + { + text: 'L=Somewhere/CN=evil.example.com', + legacy: { + L: 'Somewhere/CN=evil.example.com' + }, + }, + { + text: 'L=München\\\\\\0ACN=evil.example.com', + legacy: { + L: 'München\\\nCN=evil.example.com' + } + }, + { + text: 'L=Somewhere + CN=evil.example.com', + legacy: { + L: 'Somewhere', + CN: 'evil.example.com', + } + }, + { + text: 'L=Somewhere \\+ CN=evil.example.com', + legacy: { + L: 'Somewhere + CN=evil.example.com' + } + }, + // Observe that the legacy representation cannot properly distinguish + // between multi-value RDNs and multiple single-value RDNs. + { + text: 'L=L1 + L=L2\nL=L3', + legacy: { + L: ['L1', 'L2', 'L3'] + }, + }, + { + text: 'L=L1\nL=L2\nL=L3', + legacy: { + L: ['L1', 'L2', 'L3'] + }, + }, + ]; + + const serverKey = fixtures.readSync('x509-escaping/server-key.pem', 'utf8'); + + for (let i = 0; i < expectedSubjects.length; i++) { + const pem = fixtures.readSync(`x509-escaping/subj-${i}-cert.pem`, 'utf8'); + const expected = expectedSubjects[i]; + + // Test the subject property of the X509Certificate API. + const cert = new X509Certificate(pem); + assert.strictEqual(cert.subject, expected.text); + // The issuer MUST be the same as the subject since the cert is self-signed. + assert.strictEqual(cert.issuer, expected.text); + + // Test that the certificate obtained by checkServerIdentity has the correct + // subject property. + const server = tls.createServer({ + key: serverKey, + cert: pem, + }, common.mustCall((conn) => { + conn.destroy(); + server.close(); + })).listen(common.mustCall(() => { + const { port } = server.address(); + tls.connect(port, { + ca: pem, + servername: 'example.com', + checkServerIdentity: (hostname, peerCert) => { + assert.strictEqual(hostname, 'example.com'); + const expectedObject = Object.assign(Object.create(null), + expected.legacy); + assert.deepStrictEqual(peerCert.subject, expectedObject); + // The issuer MUST be the same as the subject since the cert is + // self-signed. Otherwise, OpenSSL would have already rejected the + // certificate while connecting to the TLS server. + assert.deepStrictEqual(peerCert.issuer, expectedObject); + }, + }, common.mustCall()); + })); + } +} + // The internal parsing logic must match the JSON specification exactly. { // This list is partially based on V8's own JSON tests.