-
Notifications
You must be signed in to change notification settings - Fork 851
Ensure that ca override does not get lost #7219
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
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 |
|---|---|---|
|
|
@@ -924,6 +924,8 @@ void | |
| SSLNetVConnection::clear() | ||
| { | ||
| _serverName.reset(); | ||
| _ca_cert_file.reset(); | ||
|
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. Need a |
||
| _ca_cert_dir.reset(); | ||
|
|
||
| if (ssl != nullptr) { | ||
| SSL_free(ssl); | ||
|
|
@@ -1921,3 +1923,20 @@ SSLNetVConnection::set_server_name(std::string_view name) | |
| _serverName.reset(n); | ||
| } | ||
| } | ||
|
|
||
| void | ||
| SSLNetVConnection::set_ca_cert_file(std::string_view file, std::string_view dir) | ||
| { | ||
| if (file.size()) { | ||
| char *n = new char[file.size() + 1]; | ||
| std::memcpy(n, file.data(), file.size()); | ||
| n[file.size()] = '\0'; | ||
| _ca_cert_file.reset(n); | ||
| } | ||
| if (dir.size()) { | ||
| char *n = new char[dir.size() + 1]; | ||
| std::memcpy(n, dir.data(), dir.size()); | ||
| n[dir.size()] = '\0'; | ||
| _ca_cert_dir.reset(n); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -300,6 +300,8 @@ set_context_cert(SSL *ssl) | |
| // Reset the ticket callback if needed | ||
| SSL_CTX_set_tlsext_ticket_key_cb(ctx.get(), ssl_callback_session_ticket); | ||
| #endif | ||
| // After replacing the SSL_CTX, make sure the overriden ca_cert_file is still set | ||
| setClientCertCACerts(ssl, netvc->get_ca_cert_file(), netvc->get_ca_cert_dir()); | ||
| } else { | ||
| found = false; | ||
| } | ||
|
|
@@ -1146,19 +1148,25 @@ setClientCertLevel(SSL *ssl, uint8_t certLevel) | |
| } | ||
|
|
||
| void | ||
| setClientCertCACerts(SSL *ssl, X509_STORE *ca_certs) | ||
| setClientCertCACerts(SSL *ssl, const char *file, const char *dir) | ||
| { | ||
| if ((file != nullptr && file[0] != '\0') || (dir != nullptr && dir[0] != '\0')) { | ||
| #if defined(SSL_set1_verify_cert_store) | ||
| // The set0 version will take ownership of the X509_STORE object | ||
| X509_STORE *ctx = X509_STORE_new(); | ||
| if (X509_STORE_load_locations(ctx, file && file[0] != '\0' ? file : nullptr, dir && dir[0] != '\0' ? dir : nullptr)) { | ||
| SSL_set0_verify_cert_store(ssl, ctx); | ||
| } | ||
|
|
||
| // It is necessasry to use set1 and not set0 here. SSL_free() calls ssl_cert_free(), which calls | ||
| // X509_STORE_free() on the ca_certs store. Hard to see how set0 could ever actually be useful, in | ||
| // what scenario would SSL objects never be freed? | ||
| // | ||
| SSL_set1_verify_cert_store(ssl, ca_certs); | ||
|
|
||
| // SSL_set_client_CA_list takes ownership of the STACK_OF(X509) structure | ||
| // So we load it each time to pass into the SSL object | ||
| if (file != nullptr && file[0] != '\0') { | ||
| SSL_set_client_CA_list(ssl, SSL_load_client_CA_file(file)); | ||
| } | ||
|
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'm really lost with all this. Doesn't this just set the names of the CAs that are sent to the client, not the CA certs used to validate? How is this relevant to Vinith's (or my) test, where the curl command only has a single cert it can send in any case? Seems like there should be a way to avoid having to read a disk file on every single TLS handshake.
Member
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. True. I added this when debugging the issue. Based on the documentation, it seemed like there were cases when the client would only look for appropriate intermediates if this was set. Since we set this in the SSL_CTX case, I added it here. Turns out it didn't fix the issue (at least not alone). The ssl->cert->verify_store rewriting was the main problem. |
||
| #else | ||
| ink_assert(!"Configuration checking should prevent reaching this code"); | ||
| ink_assert(!"Configuration checking should prevent reaching this code"); | ||
| #endif | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
||
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.
These are needed because the SNI config can disappear during a transaction, destroying the original source, correct?