-
Notifications
You must be signed in to change notification settings - Fork 5.3k
ssl: support wildcard matching for verify_subject_alt_name #1298
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
Changes from all commits
3ed769d
bef14f1
e4b97c7
ad7d440
c878f8b
9347913
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -200,7 +200,7 @@ bool ContextImpl::verifySubjectAltName(X509* cert, | |
| ASN1_STRING* str = altname->d.dNSName; | ||
| char* dns_name = reinterpret_cast<char*>(ASN1_STRING_data(str)); | ||
| for (auto& config_san : subject_alt_names) { | ||
| if (dNSNameMatch(config_san, dns_name)) { | ||
| if (dNSNameMatch(config_san, dns_name, static_cast<size_t>(ASN1_STRING_length(str)))) { | ||
| verified = true; | ||
| break; | ||
| } | ||
|
|
@@ -209,7 +209,7 @@ bool ContextImpl::verifySubjectAltName(X509* cert, | |
| ASN1_STRING* str = altname->d.uniformResourceIdentifier; | ||
| char* crt_san = reinterpret_cast<char*>(ASN1_STRING_data(str)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It just occurred to me that there is and then we could compare strings only if Sorry for not catching this yesterday!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll fix this along with the problem mentioned below.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a side question though, if we use
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is correct. Optimally, You would just pass char* and length to the function, then still use strncmp (or compare if you can). At this point though let's just get something working that everyone agrees with. :)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cool, I'll stick to the current way then
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...it is. Feel free to ignore this. Alternatively, you could use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right. I'll pass |
||
| for (auto& config_san : subject_alt_names) { | ||
| if (config_san.compare(crt_san) == 0) { | ||
| if (uriMatch(config_san, crt_san, static_cast<size_t>(ASN1_STRING_length(str)))) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||
| verified = true; | ||
| break; | ||
| } | ||
|
|
@@ -223,20 +223,29 @@ bool ContextImpl::verifySubjectAltName(X509* cert, | |
| return verified; | ||
| } | ||
|
|
||
| bool ContextImpl::dNSNameMatch(const std::string& dNSName, const char* pattern) { | ||
| if (dNSName == pattern) { | ||
| return true; | ||
| bool ContextImpl::dNSNameMatch(const std::string& dns_pattern, const char* dns, size_t dns_len) { | ||
| size_t pattern_len = dns_pattern.length(); | ||
| if (pattern_len > 1 && dns_pattern.substr(0, 2) == "*.") { | ||
| if (dns_len >= pattern_len) { | ||
| size_t off = dns_len - pattern_len + 1; | ||
| return dns_pattern.compare(1, pattern_len - 1, dns + off, pattern_len - 1) == 0; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| size_t pattern_len = strlen(pattern); | ||
| if (pattern_len > 1 && pattern[0] == '*' && pattern[1] == '.') { | ||
| if (dNSName.length() > pattern_len - 1) { | ||
| size_t off = dNSName.length() - pattern_len + 1; | ||
| return dNSName.compare(off, pattern_len - 1, pattern + 1) == 0; | ||
| return dns_pattern == dns; | ||
| } | ||
|
|
||
| bool ContextImpl::uriMatch(const std::string& uri_pattern, const char* uri, size_t uri_len) { | ||
| size_t pattern_len = uri_pattern.length(); | ||
| if (pattern_len > 1 && uri_pattern.substr(pattern_len - 2) == "/*") { | ||
| if (uri_len >= pattern_len) { | ||
| return uri_pattern.compare(0, pattern_len - 1, uri, pattern_len - 1) == 0; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| return false; | ||
| return uri_pattern == uri; | ||
| } | ||
|
|
||
| bool ContextImpl::verifyCertificateHash(X509* cert, const std::vector<uint8_t>& expected_hash) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,18 @@ | ||
| -----BEGIN CERTIFICATE----- | ||
| MIIC3zCCAkigAwIBAgIJAIP3FexxDZw/MA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV | ||
| MIIC3zCCAkigAwIBAgIJAOqvogwSzSGmMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV | ||
| BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp | ||
| c2NvMQ0wCwYDVQQKEwRMeWZ0MRkwFwYDVQQLExBMeWZ0IEVuZ2luZWVyaW5nMRkw | ||
| FwYDVQQDExBUZXN0IFVwc3RyZWFtIENBMB4XDTE3MDcwOTAxMzkzMloXDTE5MDcw | ||
| OTAxMzkzMlowfzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAU | ||
| FwYDVQQDExBUZXN0IFVwc3RyZWFtIENBMB4XDTE3MDcyNzE3NTcxNFoXDTE5MDcy | ||
| NzE3NTcxNFowfzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAU | ||
| BgNVBAcTDVNhbiBGcmFuY2lzY28xDTALBgNVBAoTBEx5ZnQxGTAXBgNVBAsTEEx5 | ||
| ZnQgRW5naW5lZXJpbmcxGTAXBgNVBAMTEFRlc3QgVXBzdHJlYW0gQ0EwgZ8wDQYJ | ||
| KoZIhvcNAQEBBQADgY0AMIGJAoGBANbxYY3hK35w0cSDReeoEJtqoegs+v3wo3B7 | ||
| Uaki2AWXcdQK4kEyz1zesRcwUgT3gTqNdQJ+WiN0UtZpEgqvNDvSRYj1ONLIrnP7 | ||
| en1Uc2ld5KHjzZfSUnlDSlHURGad2N/V9fsT8HUUrAFSNnyRRmA54zuuQP8cQBLl | ||
| YXgisaADAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG | ||
| MB0GA1UdDgQWBBQ3dX2uHV9GclTYCEwe0vUNWBQwaTAfBgNVHSMEGDAWgBQ3dX2u | ||
| HV9GclTYCEwe0vUNWBQwaTANBgkqhkiG9w0BAQsFAAOBgQB6tJ+WGcHcAwc148ca | ||
| +TtjxKB1GI6LoQusMXmF5tZlFi/Prk8+pHqcNZdFeNxYSIQnZvIQijTHUFKrBfbn | ||
| 1KGxrivXNGQj1/ivAAofzduLHK0k8g8koejwyM5aqkMXUucGHyp28+75D5paTnEZ | ||
| v+yOm2g0grB52deXB97mj5yYlQ== | ||
| HV9GclTYCEwe0vUNWBQwaTANBgkqhkiG9w0BAQsFAAOBgQBEuF8bxTKs/ZxjKCkV | ||
| vL/1VFl//Y0iXpYl7D+fH6R1/jC0FQ5x1esvJkmS4vVqWCkpz+u8PFi4LhgIIx5V | ||
| 6IhP4fvJtBaGkSE7Ct8zFL2mZX4198Bm+XbuUXvdehOAs6GX3XIVI+Pcu7ioaXPP | ||
| MTFQHMB4XlhWsUudCZ7VVln5Ew== | ||
| -----END CERTIFICATE----- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,19 @@ | ||
| -----BEGIN CERTIFICATE----- | ||
| MIIDFjCCAn+gAwIBAgIJAIEoeL+knpI0MA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV | ||
| MIIDGDCCAoGgAwIBAgIJAJPDaoHAmb5AMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV | ||
| BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp | ||
| c2NvMQ0wCwYDVQQKEwRMeWZ0MRkwFwYDVQQLExBMeWZ0IEVuZ2luZWVyaW5nMRkw | ||
| FwYDVQQDExBUZXN0IFVwc3RyZWFtIENBMB4XDTE3MDcwOTAxMzkzMloXDTE5MDcw | ||
| OTAxMzkzMlowgYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYw | ||
| FwYDVQQDExBUZXN0IFVwc3RyZWFtIENBMB4XDTE3MDcyNzE3NTcxNFoXDTE5MDcy | ||
| NzE3NTcxNFowgYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYw | ||
| FAYDVQQHEw1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKEwRMeWZ0MRkwFwYDVQQLExBM | ||
| eWZ0IEVuZ2luZWVyaW5nMR0wGwYDVQQDExRUZXN0IFVwc3RyZWFtIFNlcnZlcjCB | ||
| nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu7BZ855UTUGLBbSIG7NbmOHnit0k | ||
| qhVaS7qf56wuGybRyoS82vUKKF+HG84DJZGjPCCzr9sjgPuDI2ebWf28YScS/K/v | ||
| VVVk4mdJcpL8LSKF9j2wWjD1fk/soLAfeMgs3GvXBXk1GsJ+PzCr6jKJ+EqghKpV | ||
| 3snf6/leRi0gBrMCAwEAAaOBlDCBkTAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIF | ||
| 4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwFQYDVR0RBA4wDIIKKi5s | ||
| eWZ0LmNvbTAdBgNVHQ4EFgQUL4L/GnkQef+2KrADZK0zecZe84MwHwYDVR0jBBgw | ||
| FoAUN3V9rh1fRnJU2AhMHtL1DVgUMGkwDQYJKoZIhvcNAQELBQADgYEAvE6Hoguo | ||
| ImLP3WPBzW5WuvWwheG2QOlCEo9gP3V/C4ptAr92znG4Jrsp72S86LFdFYR+ZKgK | ||
| 4QRwtoPyVIb6cGK+N70TE/21Z3jWuA5gvezKT3XnGy+RhPSapLAjjafuvYsVUPv9 | ||
| aGPmBCsMiipz9dWjLxVTF9nUNZeRLnxbLSk= | ||
| 3snf6/leRi0gBrMCAwEAAaOBljCBkzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIF | ||
| 4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwFwYDVR0RBBAwDoIMZm9v | ||
| Lmx5ZnQuY29tMB0GA1UdDgQWBBQvgv8aeRB5/7YqsANkrTN5xl7zgzAfBgNVHSME | ||
| GDAWgBQ3dX2uHV9GclTYCEwe0vUNWBQwaTANBgkqhkiG9w0BAQsFAAOBgQAHX0fA | ||
| YGUQrS5/+k+lnmcJo6j0dSwGZAjemIjbFUXqMPOK72G4vveZKGJvYQ5bLXiRdc5I | ||
| XKcxpdF1h9DNnVUdCJtb4UEHds1s167uACX/fLW8IhWiN+V6scI4oBzS0fe4qKn6 | ||
| MhcCbQFkIVgCFBesM30elX8yPHIYTSBeeA/OgQ== | ||
| -----END CERTIFICATE----- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,7 +99,7 @@ | |
| "connect_timeout_ms": 5000, | ||
| "ssl_context": { | ||
| "ca_cert_file": "{{ test_rundir }}/test/config/integration/certs/upstreamcacert.pem", | ||
| "verify_subject_alt_name": [ "foo.lyft.com" ] | ||
| "verify_subject_alt_name": [ "*.lyft.com" ] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer if you add new test cases, so that we have both exact match and wildcard covered.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think unit tests already cover both cases. The purpose of integration tests should just be making sure that the overall flow works?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree, especially when most of the verification and SAN extraction is actually happening in 3rd-party library, which isn't involved at all in those unit tests.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW, I disagree also. Please keep the existing test and add a new one. Changing this code almost always breaks something / someone so the more coverage we have the better. (Hence why we are now at like 60 comments on a tiny PR). |
||
| }, | ||
| "type": "static", | ||
| "lb_type": "round_robin", | ||
|
|
@@ -110,7 +110,7 @@ | |
| "connect_timeout_ms": 5000, | ||
| "ssl_context": { | ||
| "ca_cert_file": "{{ test_rundir }}/test/config/integration/certs/upstreamcacert.pem", | ||
| "verify_subject_alt_name": [ "foo.lyft.com" ] | ||
| "verify_subject_alt_name": [ "*.lyft.com" ] | ||
| }, | ||
| "type": "strict_dns", | ||
| "lb_type": "round_robin", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably want to save this to a local variable before the
forloop.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid extra calls to
ASN1_STRING_length()(since I don't think it will get inlined) and dereference ofstr.