Merge pull request #121 from victorhahncastell/master

Verify certificate CN/SAN
main
Valery Komarov 9 years ago
commit 8517bb05ec
  1. 2
      LICENSE
  2. 2
      README.md
  3. 79
      ngx_http_auth_ldap_module.c

@ -1,7 +1,7 @@
/** /**
* Copyright (C) 2011-2013 Valery Komarov <komarov@valerka.net> * Copyright (C) 2011-2013 Valery Komarov <komarov@valerka.net>
* Copyright (C) 2013 Jiri Hruska <jirka@fud.cz> * Copyright (C) 2013 Jiri Hruska <jirka@fud.cz>
* Copyright (C) 2015 Victor Hahn Castell <victor.hahn@flexoptix.net> * Copyright (C) 2015-2016 Victor Hahn Castell <victor.hahn@flexoptix.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

@ -108,6 +108,8 @@ accepted which exposes you to possible man-in-the-middle attacks. Note that the
certificate will need to be signed by a proper CA trusted by your system if this is enabled. certificate will need to be signed by a proper CA trusted by your system if this is enabled.
See below how to trust CAs without installing them system-wide. See below how to trust CAs without installing them system-wide.
This options needs OpenSSL >= 1.0.2; it is unavailable if compiled with older versions.
## ssl_ca_file ## ssl_ca_file
expected value: file path expected value: file path

@ -1,6 +1,7 @@
/** /**
* Copyright (C) 2011-2013 Valery Komarov <komarov@valerka.net> * Copyright (C) 2011-2013 Valery Komarov <komarov@valerka.net>
* Copyright (C) 2013 Jiri Hruska <jirka@fud.cz> * Copyright (C) 2013 Jiri Hruska <jirka@fud.cz>
* Copyright (C) 2015-2016 Victor Hahn Castell <victor.hahn@flexoptix.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,6 +32,11 @@
#include <ngx_md5.h> #include <ngx_md5.h>
#include <ldap.h> #include <ldap.h>
// used for manual warnings
#define XSTR(x) STR(x)
#define STR(x) #x
#pragma GCC diagnostic warning "-Wcpp"
#ifndef LDAP_PROTO_EXT #ifndef LDAP_PROTO_EXT
/* Some OpenLDAP headers are accidentally missing ldap_init_fd() etc. */ /* Some OpenLDAP headers are accidentally missing ldap_init_fd() etc. */
@ -383,7 +389,15 @@ ngx_http_auth_ldap_ldap_server(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
} }
server->connections = i; server->connections = i;
} else if (ngx_strcmp(value[0].data, "ssl_check_cert") == 0 && ngx_strcmp(value[1].data, "on") == 0) { } else if (ngx_strcmp(value[0].data, "ssl_check_cert") == 0 && ngx_strcmp(value[1].data, "on") == 0) {
#if OPENSSL_VERSION_NUMBER >= 0x10002000
server->ssl_check_cert = 1; server->ssl_check_cert = 1;
#else
#warning "http_auth_ldap: Compiling with OpenSSL < 1.0.2, certificate verification will be unavailable. OPENSSL_VERSION_NUMBER == " XSTR(OPENSSL_VERSION_NUMBER)
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"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.02 and recompile nginx.");
#endif
} else if (ngx_strcmp(value[0].data, "ssl_ca_dir") == 0) { } else if (ngx_strcmp(value[0].data, "ssl_ca_dir") == 0) {
server->ssl_ca_dir = value[1]; server->ssl_ca_dir = value[1];
} else if (ngx_strcmp(value[0].data, "ssl_ca_file") == 0) { } else if (ngx_strcmp(value[0].data, "ssl_ca_file") == 0) {
@ -1225,30 +1239,57 @@ static void
ngx_http_auth_ldap_ssl_handshake_handler(ngx_connection_t *conn, ngx_flag_t validate) ngx_http_auth_ldap_ssl_handshake_handler(ngx_connection_t *conn, ngx_flag_t validate)
{ {
ngx_http_auth_ldap_connection_t *c; ngx_http_auth_ldap_connection_t *c;
c = conn->data; c = conn->data;
if (conn->ssl->handshaked) { if (conn->ssl->handshaked) {
// verify remote certificate #if OPENSSL_VERSION_NUMBER >= 0x10002000
X509 *cert = SSL_get_peer_certificate(conn->ssl->connection); if (validate) { // verify remote certificate if requested
long verified = SSL_get_verify_result(conn->ssl->connection); X509 *cert = SSL_get_peer_certificate(conn->ssl->connection);
long chain_verified = SSL_get_verify_result(conn->ssl->connection);
if (!validate || (cert && verified == X509_V_OK) ) { // everything fine
conn->read->handler = &ngx_http_auth_ldap_read_handler; int addr_verified;
ngx_http_auth_ldap_restore_handlers(conn); char *hostname = c->server->ludpp->lud_host;
ngx_http_auth_ldap_connection_established(c); addr_verified = X509_check_host(cert, hostname, 0, 0, 0);
return;
} else { // smells fishy if (!addr_verified) { // domain not in cert? try IP
ngx_log_error(NGX_LOG_ERR, c->log, 0, size_t len; // get IP length
"http_auth_ldap: Remote side presented invalid SSL certificate: error %l, %s", if (conn->sockaddr->sa_family == 4) len = 4;
verified, X509_verify_cert_error_string(verified)); else if (conn->sockaddr->sa_family == 6) len = 16;
ngx_http_auth_ldap_close_connection(c); else { // very unlikely indeed
return; ngx_http_auth_ldap_close_connection(c);
return;
}
addr_verified = X509_check_ip(cert, (const unsigned char*)conn->sockaddr->sa_data, len, 0);
}
// Find anything fishy?
if ( !(cert && addr_verified && chain_verified == X509_V_OK) ) {
if (!addr_verified) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"http_auth_ldap: Remote side presented invalid SSL certificate: "
"does not match address (neither server's domain nor IP in certificate's CN or SAN)");
fprintf(stderr, "DEBUG: SSL cert domain mismatch\n"); fflush(stderr);
} else {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"http_auth_ldap: Remote side presented invalid SSL certificate: error %l, %s",
chain_verified, X509_verify_cert_error_string(chain_verified));
}
ngx_http_auth_ldap_close_connection(c);
return;
}
} }
} #endif
ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_auth_ldap: SSL handshake failed"); // handshaked validation successful -- or not required in the first place
ngx_http_auth_ldap_close_connection(c); conn->read->handler = &ngx_http_auth_ldap_read_handler;
ngx_http_auth_ldap_restore_handlers(conn);
ngx_http_auth_ldap_connection_established(c);
return;
}
else { // handshake failed
ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_auth_ldap: SSL handshake failed");
ngx_http_auth_ldap_close_connection(c);
}
} }
static void static void

Loading…
Cancel
Save