Skip to content
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

fix segfault in ngx_http_auth_ldap_ssl_handshake_handler and add "chain" option for ssl_check_cert #237

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

mmguero
Copy link

@mmguero mmguero commented May 5, 2020

This pull request addresses two things relating to ngx_http_auth_ldap_ssl_handshake_handler:

  1. Fixes segmentation fault in ngx_http_auth_ldap_ssl_handshake_handler with ssl_check_cert and ssl_ca_dir #236 by not assuming conn->sockaddr is non-NULL. Instead, it tries to get it from conn->sockaddr, c->conn.sockaddr, and finally c->server->parsed_url.sockaddr.sockaddr, in that order:
struct sockaddr *conn_sockaddr = NULL;
if (conn->sockaddr != NULL) conn_sockaddr = conn->sockaddr;
else if (c->conn.sockaddr != NULL) conn_sockaddr = c->conn.sockaddr;
else conn_sockaddr = &c->server->parsed_url.sockaddr.sockaddr;

Additionally, it uses the correct AF_INET and AF_INET6 constants for checking sa_family for IPv4 vs. IPv6, rather than the incorrect 4 and 6 integer literals.

  1. ssl_check_cert now accepts chain in addition to on and off:
  • on - full certificate verification in ngx_http_auth_ldap_ssl_handshake_handler, meaning checking the certificate chain with SSL_get_verify_result and X509_check_host or X509_check_ip (same as previous on behavior; full can also be used to mean the same thing as on)
  • off - no certificate verification (same as previous off behavior)
  • chain - perform certificate chain verification with SSL_get_verify_result, but don't do host/IP verification (i.e., don't call X509_check_host or X509_check_ip)

This should not break backwards compatibility. I've been testing it in conjunction with an issue in my project (idaholab/Malcolm#128) and it addresses my needs. I've left the checks in place for OPENSSL_VERSION_NUMBER to leave the warnings in place if compiled with too old a version of openssl.

Let me know if you've got any issues or questions.

mmguero added 6 commits April 20, 2020 14:54
This reverts commit bf64cf2, reversing
changes made to f022103.

This change isn't right -- it an LDAP setup when `group_attribute_is_dn
on` is enabled, which is what this section of code
(kvspb@bf64cf2#diff-c05c0daefb48996cbf510b81002b49bcR2230)
is conditionally targeting.  This original PR kvspb#199 changed the underlying
LDAP query (eg `user_val`) from looking up the user's DN as a group
attribute in LDAP (eg set via the `group_attribute` directive in nginx)
to looking up the _group's_ DN, which isn't right and won't work.

This PR reverts the previous change to make this work correctly again.

Fwiw, the originally-referenced issue kvspb#180 seems to be a completely
different issue, relating to escaping and parentheses.
…on) or chain (verify cert chain but not hostname/IP)
…l_handshake_handler with ssl_check_cert and ssl_ca_dir
Copy link
Author

@mmguero mmguero left a comment

Choose a reason for hiding this comment

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

I've outlined all of the code changes for the PR, let me know if you have any concerns or questions.

@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/

#include <sys/socket.h>
Copy link
Author

Choose a reason for hiding this comment

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

Added sys/socket.h for AF_INET and AF_INET6 later in ngx_http_auth_ldap_ssl_handshake_handler

#define SSL_CERT_VERIFY_OFF 0
#define SSL_CERT_VERIFY_FULL 1
#define SSL_CERT_VERIFY_CHAIN 2

Copy link
Author

Choose a reason for hiding this comment

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

These constants are used as possible values for ngx_http_auth_ldap_server_t.ssl_check_cert to indicate off, on/full and chain verification as described in the PR body.

"http_auth_ldap: 'ssl_cert_check': cannot verify remote certificate's domain name because "
"your version of OpenSSL is too old. "
"Please install OpenSSL >= 1.0.2 and recompile nginx.");
#endif
Copy link
Author

Choose a reason for hiding this comment

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

Leave directives for checking OPENSSL_VERSION_NUMBER in place. If ssl_check_cert is specified, on and full indicate full certificate checking (chain and host/IP), chain indicates checking certificate chain only but not host/IP, and anything else means off (don't verify the certificate).

else { // very unlikely indeed
ngx_http_auth_ldap_close_connection(c);
return;
if (c->server->ssl_check_cert == SSL_CERT_VERIFY_CHAIN) {
Copy link
Author

Choose a reason for hiding this comment

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

handle chain (SSL_CERT_VERIFY_CHAIN) case: we've already called SSL_get_verify_result and got chain_verified assigned, which will be checked below. Set addr_verified to 1 (success) so it will get ignored in the checks later. Don't call X509_check_host or X509_check_ip.

if (!addr_verified) { // domain not in cert? try IP
size_t len; // get IP length

struct sockaddr *conn_sockaddr = NULL;
Copy link
Author

Choose a reason for hiding this comment

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

This next few lines of code was what was causing the segfault in kvspb/nginx-auth-ldap/#236. conn->sockaddr was always NULL for me. So check a few places that (I think) should have the value we need and use one of them, if set. If there's anywhere my logic might be wrong, it would be here, in assuming the values of these sockaddr structs represent the same thing. But I think it's right.


if (conn_sockaddr->sa_family == AF_INET) len = 4;
else if (conn_sockaddr->sa_family == AF_INET6) len = 16;
else { // very unlikely indeed
Copy link
Author

Choose a reason for hiding this comment

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

We are now checking AF_INET and AF_INET6 rather than just 4 and 6, which wouldn't have ever been correct anyway.

ngx_http_auth_ldap_close_connection(c);
return;
}
addr_verified = X509_check_ip(cert, (const unsigned char*)conn_sockaddr->sa_data, len, 0);
Copy link
Author

Choose a reason for hiding this comment

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

See the comment above where I assign conn_sockaddr

update counter (this is always reset in
ngx_http_auth_ldap_connect() for a successful ldap
connection
c->server->max_down_retries_count < c->server->max_down_retries) {
Copy link
Author

Choose a reason for hiding this comment

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

this is just my editor stripping trailing spaces

@@ -1542,7 +1566,7 @@ ngx_http_auth_ldap_read_handler(ngx_event_t *rev)
// timer call to this read handler again
ngx_http_auth_ldap_reconnect_handler(rev);
return;
}
}
Copy link
Author

Choose a reason for hiding this comment

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

this is just my editor stripping trailing spaces

davidjb added a commit to jcu-eresearch/nginx-dynamic-modules that referenced this pull request Nov 19, 2020
This patches in kvspb/nginx-auth-ldap#237 to
handle segfaults produced by failure to make SSL connections to LDAP
servers.
@mmguero
Copy link
Author

mmguero commented Jul 13, 2022

ping... project still active?

Ericbla added a commit to Ericbla/nginx-auth-ldap that referenced this pull request Jul 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

segmentation fault in ngx_http_auth_ldap_ssl_handshake_handler with ssl_check_cert and ssl_ca_dir
1 participant