Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1c9c914
tls: Add support for matching against OtherName SAN type
arulthileeban Jun 1, 2024
d1f167f
tls: OtherName refactoring
arulthileeban Jun 1, 2024
7d9fa67
Merge branch 'envoyproxy:main' into other_name_san
arulthileeban Jun 1, 2024
c95587b
tls: Add tests and certs for OtherName SAN Validation
arulthileeban Jun 1, 2024
3aa7618
tls: Add docs for OtherName SAN matching
arulthileeban Jun 2, 2024
27107f3
tls: Add UPN to spelling dictionary
arulthileeban Jun 2, 2024
fa8c908
jwt_authn: Remove PANIC for invalid oid
arulthileeban Jun 3, 2024
8be3f1b
tls: Modify tests for othername SAN
arulthileeban Jun 4, 2024
5004b55
tls: add logic to handle different othername type inputs from certs
arulthileeban Jun 5, 2024
543aa7e
tls: Add Othername SAN value match docs and value failure test
arulthileeban Jun 6, 2024
20a5d9f
Merge branch 'main' into other_name_san
arulthileeban Jun 7, 2024
0318aa4
tls: add othername tests for various types
arulthileeban Jun 8, 2024
dfb8a23
tls: add test/doc for null othername type
arulthileeban Jun 8, 2024
80e6037
tls: Modify handling of OtherName SAN value extraction
arulthileeban Jun 15, 2024
bef4d58
tls: fix switch - fall through on condition failure
arulthileeban Jun 17, 2024
2d9bfb7
tls: split string case handling + tests
arulthileeban Jun 19, 2024
d800848
tls: change variable str to tmp_str for diff string types
arulthileeban Jun 21, 2024
70a5cb9
minor fix
arulthileeban Jun 21, 2024
ded0296
tls: add comments for tests
arulthileeban Jun 25, 2024
90a980e
Merge branch 'main' into other_name_san
arulthileeban Jun 27, 2024
d3c7937
add spelling fix
arulthileeban Jun 27, 2024
b1de297
add bmpstring change
arulthileeban Jun 27, 2024
06d4848
add bmpstring test+code
arulthileeban Jun 27, 2024
c773c79
bmpstring spelling fix
arulthileeban Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions api/envoy/extensions/transport_sockets/tls/v3/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,29 @@ message SubjectAltNameMatcher {
DNS = 2;
URI = 3;
IP_ADDRESS = 4;
OTHER_NAME = 5;
}

// Specification of type of SAN. Note that the default enum value is an invalid choice.
SanType san_type = 1 [(validate.rules).enum = {defined_only: true not_in: 0}];

// Matcher for SAN value.
//
// The string matching for OTHER_NAME SAN values depends on their ASN.1 type:
//
// * OBJECT: Validated against its dotted numeric notation (e.g., "1.2.3.4")
// * BOOLEAN: Validated against strings "true" or "false"
// * INTEGER/ENUMERATED: Validated against a string containing the integer value
// * NULL: Validated against an empty string
// * Other types: Validated directly against the string value
type.matcher.v3.StringMatcher matcher = 2 [(validate.rules).message = {required: true}];

// OID Value which is required if OTHER_NAME SAN type is used.
// For example, UPN OID is 1.3.6.1.4.1.311.20.2.3
// (Reference: http://oid-info.com/get/1.3.6.1.4.1.311.20.2.3).
//
// If set for SAN types other than OTHER_NAME, it will be ignored.
string oid = 3;
Comment thread
arulthileeban marked this conversation as resolved.
}

// [#next-free-field: 18]
Expand Down
6 changes: 6 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ new_features:
change: |
Added :ref:`bypass_overload_manager <envoy_v3_api_field_config.listener.v3.Listener.bypass_overload_manager>`
to bypass the overload manager for a listener. When set to true, the listener will not be subject to overload protection.
- area: tls
change: |
added support to match against ``OtherName`` SAN Type under :ref:`match_typed_subject_alt_names
<envoy_v3_api_field_extensions.transport_sockets.tls.v3.CertificateValidationContext.match_typed_subject_alt_names>`.
An additional field ``oid`` is added to :ref:`SubjectAltNameMatcher
<envoy_v3_api_msg_extensions.transport_sockets.tls.v3.SubjectAltNameMatcher>` to support this change.

deprecated:
- area: tracing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ CertificateValidationContextConfigImpl::getSubjectAltNameMatchers(
}
// Handle deprecated string type san matchers without san type specified, by
// creating a matcher for each supported type.
// Note: This does not handle otherName type
for (const envoy::type::matcher::v3::StringMatcher& matcher : config.match_subject_alt_names()) {
static constexpr std::array<
envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::SanType, 4>
Expand Down
16 changes: 15 additions & 1 deletion source/common/tls/cert_validator/san_matcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ bool StringSanMatcher::match(const GENERAL_NAME* general_name) const {
if (general_name->type != general_name_type_) {
return false;
}
if (general_name->type == GEN_OTHERNAME) {
if (OBJ_cmp(general_name->d.otherName->type_id, general_name_oid_.get())) {
return false;
}
}
// For DNS SAN, if the StringMatcher type is exact, we have to follow DNS matching semantics.
const std::string san = Utility::generalNameAsString(general_name);
return general_name->type == GEN_DNS &&
Expand All @@ -32,7 +37,7 @@ SanMatcherPtr createStringSanMatcher(
Server::Configuration::CommonFactoryContext& context) {
// Verify that a new san type has not been added.
static_assert(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::SanType_MAX ==
4);
5);

switch (matcher.san_type()) {
PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
Expand All @@ -44,6 +49,15 @@ SanMatcherPtr createStringSanMatcher(
return SanMatcherPtr{std::make_unique<StringSanMatcher>(GEN_URI, matcher.matcher(), context)};
case envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::IP_ADDRESS:
return SanMatcherPtr{std::make_unique<StringSanMatcher>(GEN_IPADD, matcher.matcher(), context)};
case envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::OTHER_NAME: {
// Invalid/Empty OID returns a nullptr from OBJ_txt2obj
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj(matcher.oid().c_str(), 0));
if (oid == nullptr) {
return nullptr;
}
return SanMatcherPtr{std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher.matcher(),
context, std::move(oid))};
Comment thread
arulthileeban marked this conversation as resolved.
}
case envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::SAN_TYPE_UNSPECIFIED:
PANIC("unhandled value");
}
Expand Down
7 changes: 5 additions & 2 deletions source/common/tls/cert_validator/san_matcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ class StringSanMatcher : public SanMatcher {
bool match(const GENERAL_NAME* general_name) const override;
~StringSanMatcher() override = default;
StringSanMatcher(int general_name_type, envoy::type::matcher::v3::StringMatcher matcher,
Server::Configuration::CommonFactoryContext& context)
: general_name_type_(general_name_type), matcher_(matcher, context) {}
Server::Configuration::CommonFactoryContext& context,
bssl::UniquePtr<ASN1_OBJECT>&& general_name_oid = nullptr)
: general_name_type_(general_name_type), matcher_(matcher, context),
general_name_oid_(std::move(general_name_oid)) {}

private:
const int general_name_type_;
const Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher> matcher_;
bssl::UniquePtr<ASN1_OBJECT> general_name_oid_;
};

SanMatcherPtr createStringSanMatcher(
Expand Down
30 changes: 30 additions & 0 deletions source/common/tls/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,36 @@ std::string Utility::generalNameAsString(const GENERAL_NAME* general_name) {
}
break;
}
case GEN_OTHERNAME:
ASN1_TYPE* value = general_name->d.otherName->value;
if (value == nullptr) {
break;
}
switch (value->type) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the matcher specify the expected type to avoid any potential bypass of the checks, similar to the change made in #18628? Or is that overkill here? cc @yanavlasov @pradeepcrao .

@arulthileeban arulthileeban Jun 21, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yanavlasov @pradeepcrao friendly ping for any thoughts here. There is admittedly room for bypass, but I'm not sure if the principle to create a distinction between DNS/IP/EMAIL/URI applies here between data types. Happy to make any changes if required.

@arulthileeban arulthileeban Jun 25, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a follow up, I checked the RFC for this. Nothing is clearly stated about the OtherName semantics in the SAN subsection - pretty much that the OID speaks for the type and the value speaks for the name. The name constraints subsection and the above section however go into detail as to what is expected of a DNS, URI, IP, EMAIL SAN and the format and semantics it should take and when certificates should be rejected. Adding #18628 helps us conform to that. Having an DNS SAN with value "google.com" matched against a IP expectation should fail since IP SAN would be expected to have certain semantics along with the fact that those types are individually distinguished. For othername SAN, they just specify this:

The syntax and semantics for name constraints for otherName, ediPartyName, and registeredID are not defined by this specification, however, syntax and semantics for name constraints for other name forms may be specified in other documents.

Considering we have an OID matching which is probably what should define type here, it might just be enough based on my understanding of RFC.

On a side note, I also noticed another RFC which tries to define semantics very specific to an usecase, but nothing generic.

case V_ASN1_NULL:
break;
case V_ASN1_BOOLEAN:
san = value->value.boolean ? "true" : "false";
break;
case V_ASN1_ENUMERATED:
san = std::to_string(ASN1_ENUMERATED_get(value->value.enumerated));
Comment thread
arulthileeban marked this conversation as resolved.
Outdated
break;
case V_ASN1_INTEGER:
san = std::to_string(ASN1_INTEGER_get(value->value.integer));
Comment thread
arulthileeban marked this conversation as resolved.
Outdated
break;
case V_ASN1_OBJECT: {
char tmp_obj[256]; // OID Max length
if (OBJ_obj2txt(tmp_obj, 256, value->value.object, 1) < 0) {
Comment thread
arulthileeban marked this conversation as resolved.
Outdated
break;
}
san.assign(tmp_obj);
break;
Comment thread
arulthileeban marked this conversation as resolved.
}
default:
Comment thread
arulthileeban marked this conversation as resolved.
str = value->value.asn1_string;
san.assign(reinterpret_cast<const char*>(ASN1_STRING_data(str)), ASN1_STRING_length(str));
break;
Comment thread
arulthileeban marked this conversation as resolved.
}
}
return san;
}
Expand Down
128 changes: 128 additions & 0 deletions test/common/tls/cert_validator/default_validator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,134 @@ TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameDNSMatched) {
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
matcher.MergeFrom(TestUtility::createRegexMatcher(R"raw([^.]*\.example.com)raw"));
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 0));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameBooleanTypeMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_multiple_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.5.5.7.8.7", 0));
matcher.MergeFrom(TestUtility::createExactMatcher("true"));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameEnumeratedTypeMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_multiple_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.4.1.311.20.2.1", 0));
matcher.MergeFrom(TestUtility::createExactMatcher("5"));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameIntegerTypeMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_multiple_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.5.5.7.8.3", 0));
matcher.MergeFrom(TestUtility::createExactMatcher("5464"));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameObjectTypeMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_multiple_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.5.2.2", 0));
matcher.MergeFrom(TestUtility::createExactMatcher("1.3.6.1.4.1.311.20.2.3"));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameNullTypeMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_multiple_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 0));
matcher.MergeFrom(TestUtility::createExactMatcher(""));
Comment thread
arulthileeban marked this conversation as resolved.
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameDnsAndOtherNameMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_dns_and_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
matcher.MergeFrom(TestUtility::createRegexMatcher(R"raw([^.]*\.example.com)raw"));
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 0));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(
SanMatcherPtr{std::make_unique<StringSanMatcher>(GEN_DNS, matcher, context)});
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_TRUE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameIncorrectOidMatched) {
Comment thread
arulthileeban marked this conversation as resolved.
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
matcher.MergeFrom(TestUtility::createRegexMatcher(R"raw([^.]*\.example.com)raw"));
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.4.1.311.20.2.2", 0));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_FALSE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameOtherNameIncorrectValueMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

bssl::UniquePtr<X509> cert = readCertFromFile(TestEnvironment::substitute(
"{{ test_rundir }}/test/common/tls/test_data/san_othername_cert.pem"));
envoy::type::matcher::v3::StringMatcher matcher;
matcher.MergeFrom(TestUtility::createRegexMatcher(R"raw([^.]*\.example.net)raw"));
bssl::UniquePtr<ASN1_OBJECT> oid(OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 0));
std::vector<SanMatcherPtr> subject_alt_name_matchers;
subject_alt_name_matchers.push_back(SanMatcherPtr{
std::make_unique<StringSanMatcher>(GEN_OTHERNAME, matcher, context, std::move(oid))});
EXPECT_FALSE(DefaultCertValidator::matchSubjectAltName(cert.get(), subject_alt_name_matchers));
}

TEST(DefaultCertValidatorTest, TestMatchSubjectAltNameIncorrectTypeMatched) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;

Expand Down
15 changes: 15 additions & 0 deletions test/common/tls/cert_validator/san_matcher_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ TEST(SanMatcherConfigTest, TestValidSanType) {
envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher san_matcher;
san_matcher.mutable_matcher()->set_exact("foo.example");
san_matcher.set_san_type(san_type);
if (san_type ==
envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::OTHER_NAME) {
san_matcher.set_oid("1.3.6.1.4.1.311.20.2.3"); // Set dummy OID
}
if (san_type == envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::
SAN_TYPE_UNSPECIFIED) {
EXPECT_DEATH(createStringSanMatcher(san_matcher, context), "unhandled value");
Expand All @@ -42,6 +46,17 @@ TEST(SanMatcherConfigTest, TestValidSanType) {
}
}

// Verify that setting Invalid OID for OtherName SAN results in a panic.
TEST(SanMatcherConfigTest, TestInvalidOidOtherNameSanType) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;
envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher san_matcher;
san_matcher.mutable_matcher()->set_exact("foo.example");
san_matcher.set_oid("1.3.6.1.4.1.311.20.2.ffff");
san_matcher.set_san_type(
envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::OTHER_NAME);
EXPECT_EQ(createStringSanMatcher(san_matcher, context), nullptr);
}

TEST(SanMatcherConfigTest, UnspecifiedSanType) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;
envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher san_matcher;
Expand Down
6 changes: 6 additions & 0 deletions test/common/tls/test_data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ There are 15 identities:
- **SAN With URI**: It has the certificate *san_uri_cert.pem*, which is signed
by the **CA** using the config *san_uri_cert.cfg*. The certificate has SAN
field of URI type. *san_uri_key.pem* is its private key.
- **SAN With OtherName**: It has the certificate *san_othername_cert.pem*, which is signed
by the **CA** using the config *san_othername_cert.cfg*. The certificate has SAN
field of OtherName(UPN) type. *san_othername_key.pem* is its private key.
- **SAN With OtherName and DNS**: It has the certificate *san_othername_cert.pem*, which is signed
by the **CA** using the config *san_dns_and_othername_cert.cfg*. The certificate has two SAN
fields, one DNS and one OtherName(UPN) type. *san_dns_and_othername_key.pem* is its private key.
- **Password-protected**: The password-protected certificate *password_protected_cert.pem*,
using the config *san_uri_cert.cfg*. *password_protected_key.pem* is
its private key encrypted using the password supplied in *password_protected_password.txt*.
Expand Down
12 changes: 12 additions & 0 deletions test/common/tls/test_data/certs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,18 @@ generate_x509_cert san_uri ca
generate_rsa_key san_ip
generate_x509_cert san_ip ca

# Generate san_othername_cert.pem.
generate_rsa_key san_othername
generate_x509_cert san_othername ca

# Generate san_dns_and_othername_cert.pem.
generate_rsa_key san_multiple_othername
generate_x509_cert san_multiple_othername ca

# Generate san_dns_and_othername_cert.pem.
generate_rsa_key san_dns_and_othername
generate_x509_cert san_dns_and_othername ca

# Concatenate san_ip_cert.pem and Test Intermediate CA (intermediate_ca_cert.pem) to create valid certificate chain.
cat san_ip_cert.pem intermediate_ca_cert.pem > san_ip_chain.pem

Expand Down
37 changes: 37 additions & 0 deletions test/common/tls/test_data/san_dns_and_othername_cert.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
countryName = US
countryName_default = US
stateOrProvinceName = California
stateOrProvinceName_default = California
localityName = San Francisco
localityName_default = San Francisco
organizationName = Lyft
organizationName_default = Lyft
organizationalUnitName = Lyft Engineering
organizationalUnitName_default = Lyft Engineering
commonName = Test Server
commonName_default = Test Server
commonName_max = 64

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alt_names
subjectKeyIdentifier = hash

[v3_ca]
basicConstraints = critical, CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alt_names
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always

[alt_names]
DNS.1 = server1.example.com
otherName.1 = 1.3.6.1.4.1.311.20.2.3;UTF8:server1.example.com
Loading