mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
libldap/tls.c: change tls_verify_cb to no longer ignore verification errors.
This means a ldaps connection may drop before any LDAP protocol exchange occurs (due to expired cert, unrecognized CAs, etc.). Change ldap_pvt_tls_connect to copy any TLS error string to ld_error upon connection failure, otherwise client just sees "can't contact LDAP server." slapd/connection.c: add flush/delay when SSL_accept fails, to allow any TLS alerts we generated to propagate back to the client. (Which will then be picked up by ldap_pvt_tls_connect on the client...)
This commit is contained in:
parent
dcad3d9569
commit
f0c4f83ea2
3 changed files with 73 additions and 12 deletions
|
|
@ -138,15 +138,18 @@ ldap_pvt_str2lower LDAP_P(( char *str ));
|
||||||
|
|
||||||
/* tls.c */
|
/* tls.c */
|
||||||
struct ldapoptions;
|
struct ldapoptions;
|
||||||
|
struct ldap;
|
||||||
|
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_init LDAP_P(( void ));
|
LIBLDAP_F (int) ldap_pvt_tls_init LDAP_P(( void ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg ));
|
LIBLDAP_F (int) ldap_pvt_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_connect LDAP_P(( Sockbuf *sb, void *ctx_arg ));
|
LIBLDAP_F (int) ldap_pvt_tls_connect LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg ));
|
LIBLDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
|
LIBLDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
|
LIBLDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg ));
|
||||||
|
LIBLDAP_F (void *) ldap_pvt_tls_sb_handle LDAP_P(( Sockbuf *sb ));
|
||||||
|
LIBLDAP_F (void *) ldap_pvt_tls_get_handle LDAP_P(( struct ldap *ld ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb ));
|
LIBLDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb ));
|
||||||
LIBLDAP_F (int) ldap_pvt_tls_start LDAP_P(( Sockbuf *sb, void *ctx_arg ));
|
LIBLDAP_F (int) ldap_pvt_tls_start LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg ));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UTF-8 (in utf-8.c)
|
* UTF-8 (in utf-8.c)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_SSL_H
|
#ifdef HAVE_OPENSSL_SSL_H
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
#elif defined( HAVE_SSL_H )
|
#elif defined( HAVE_SSL_H )
|
||||||
#include <ssl.h>
|
#include <ssl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -46,7 +48,7 @@ static int tls_remove( Sockbuf *sb );
|
||||||
static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
|
static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
|
||||||
static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
|
static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
|
||||||
static int tls_close( Sockbuf *sb );
|
static int tls_close( Sockbuf *sb );
|
||||||
static int tls_report_error( void );
|
static void tls_report_error( void );
|
||||||
|
|
||||||
static Sockbuf_IO tls_io=
|
static Sockbuf_IO tls_io=
|
||||||
{
|
{
|
||||||
|
|
@ -60,9 +62,12 @@ static Sockbuf_IO tls_io=
|
||||||
static void tls_info_cb( SSL *ssl, int where, int ret );
|
static void tls_info_cb( SSL *ssl, int where, int ret );
|
||||||
static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
|
static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
|
||||||
static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
|
static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
|
||||||
static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
|
|
||||||
static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
|
static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
|
||||||
|
|
||||||
|
#if 0 /* Currently this is not used by anyone */
|
||||||
|
static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
|
||||||
|
#endif
|
||||||
|
|
||||||
static SSL_CTX *tls_def_ctx = NULL;
|
static SSL_CTX *tls_def_ctx = NULL;
|
||||||
|
|
||||||
#ifdef LDAP_R_COMPILE
|
#ifdef LDAP_R_COMPILE
|
||||||
|
|
@ -302,7 +307,7 @@ update_flags( Sockbuf *sb, SSL * ssl, int rc )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
|
ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg )
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
|
@ -319,9 +324,16 @@ ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
|
||||||
|
|
||||||
err = SSL_connect( ssl );
|
err = SSL_connect( ssl );
|
||||||
|
|
||||||
|
#ifdef HAVE_WINSOCK
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
#endif
|
||||||
if ( err <= 0 ) {
|
if ( err <= 0 ) {
|
||||||
if ( update_flags( sb, ssl, err ))
|
if ( update_flags( sb, ssl, err ))
|
||||||
return 1;
|
return 1;
|
||||||
|
if ((err = ERR_peek_error())) {
|
||||||
|
char buf[256];
|
||||||
|
ld->ld_error = ldap_strdup(ERR_error_string(err, buf));
|
||||||
|
}
|
||||||
Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
|
Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
|
||||||
ber_pvt_sb_clear_io( sb );
|
ber_pvt_sb_clear_io( sb );
|
||||||
ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
|
ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
|
||||||
|
|
@ -352,6 +364,9 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
|
||||||
|
|
||||||
err = SSL_accept( ssl );
|
err = SSL_accept( ssl );
|
||||||
|
|
||||||
|
#ifdef HAVE_WINSOCK
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
#endif
|
||||||
if ( err <= 0 ) {
|
if ( err <= 0 ) {
|
||||||
if ( update_flags( sb, ssl, err ))
|
if ( update_flags( sb, ssl, err ))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -372,14 +387,31 @@ ldap_pvt_tls_inplace ( Sockbuf *sb )
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
ldap_pvt_tls_sb_handle( Sockbuf *sb )
|
||||||
|
{
|
||||||
|
if (HAS_TLS( sb ))
|
||||||
|
return sb->sb_iodata;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
ldap_pvt_tls_get_handle( LDAP *ld )
|
||||||
|
{
|
||||||
|
return ldap_pvt_tls_sb_handle(&ld->ld_sb);
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ldap_pvt_tls_get_peer( LDAP *ld )
|
ldap_pvt_tls_get_peer( LDAP *ld )
|
||||||
{
|
{
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ldap_pvt_tls_get_peer_issuer( LDAP *ld )
|
ldap_pvt_tls_get_peer_issuer( LDAP *ld )
|
||||||
{
|
{
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -427,9 +459,9 @@ ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
|
||||||
break;
|
break;
|
||||||
case LDAP_OPT_X_TLS_CERT:
|
case LDAP_OPT_X_TLS_CERT:
|
||||||
if ( lo == NULL )
|
if ( lo == NULL )
|
||||||
arg = (void *) tls_def_ctx;
|
*(void **)arg = (void *) tls_def_ctx;
|
||||||
else
|
else
|
||||||
arg = lo->ldo_tls_ctx;
|
*(void **)arg = lo->ldo_tls_ctx;
|
||||||
break;
|
break;
|
||||||
case LDAP_OPT_X_TLS_CACERTFILE:
|
case LDAP_OPT_X_TLS_CACERTFILE:
|
||||||
*(char **)arg = tls_opt_cacertfile ?
|
*(char **)arg = tls_opt_cacertfile ?
|
||||||
|
|
@ -520,12 +552,12 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ldap_pvt_tls_start ( Sockbuf *sb, void *ctx_arg )
|
ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Fortunately, the lib uses blocking io...
|
* Fortunately, the lib uses blocking io...
|
||||||
*/
|
*/
|
||||||
if ( ldap_pvt_tls_connect( sb, ctx_arg ) < 0 ) {
|
if ( ldap_pvt_tls_connect( ld, sb, ctx_arg ) < 0 ) {
|
||||||
return LDAP_CONNECT_ERROR;
|
return LDAP_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -556,6 +588,9 @@ tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
|
||||||
{
|
{
|
||||||
int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
|
int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
|
||||||
|
|
||||||
|
#ifdef HAVE_WINSOCK
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
#endif
|
||||||
update_flags(sb, (SSL *)sb->sb_iodata, ret );
|
update_flags(sb, (SSL *)sb->sb_iodata, ret );
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (sb->sb_trans_needs_write)
|
if (sb->sb_trans_needs_write)
|
||||||
|
|
@ -569,6 +604,9 @@ tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
|
||||||
{
|
{
|
||||||
int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
|
int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
|
||||||
|
|
||||||
|
#ifdef HAVE_WINSOCK
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
#endif
|
||||||
update_flags(sb, (SSL *)sb->sb_iodata, ret );
|
update_flags(sb, (SSL *)sb->sb_iodata, ret );
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (sb->sb_trans_needs_read)
|
if (sb->sb_trans_needs_read)
|
||||||
|
|
@ -658,11 +696,11 @@ tls_verify_cb( int ok, X509_STORE_CTX *ctx )
|
||||||
if ( iname )
|
if ( iname )
|
||||||
CRYPTO_free ( iname );
|
CRYPTO_free ( iname );
|
||||||
|
|
||||||
return 1;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inspired by ERR_print_errors in OpenSSL */
|
/* Inspired by ERR_print_errors in OpenSSL */
|
||||||
static int
|
static void
|
||||||
tls_report_error( void )
|
tls_report_error( void )
|
||||||
{
|
{
|
||||||
unsigned long l;
|
unsigned long l;
|
||||||
|
|
@ -693,11 +731,13 @@ tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
|
||||||
return tmp_rsa;
|
return tmp_rsa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static DH *
|
static DH *
|
||||||
tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
|
tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static int dummy;
|
static int dummy;
|
||||||
|
|
|
||||||
|
|
@ -881,6 +881,9 @@ int connection_read(ber_socket_t s)
|
||||||
if ( c->c_is_tls && c->c_needs_tls_accept ) {
|
if ( c->c_is_tls && c->c_needs_tls_accept ) {
|
||||||
rc = ldap_pvt_tls_accept( c->c_sb, NULL );
|
rc = ldap_pvt_tls_accept( c->c_sb, NULL );
|
||||||
if ( rc < 0 ) {
|
if ( rc < 0 ) {
|
||||||
|
struct timeval tv;
|
||||||
|
fd_set rfd;
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
"connection_read(%d): TLS accept error error=%d id=%ld, closing\n",
|
"connection_read(%d): TLS accept error error=%d id=%ld, closing\n",
|
||||||
s, rc, c->c_connid );
|
s, rc, c->c_connid );
|
||||||
|
|
@ -888,6 +891,21 @@ int connection_read(ber_socket_t s)
|
||||||
c->c_needs_tls_accept = 0;
|
c->c_needs_tls_accept = 0;
|
||||||
/* connections_mutex and c_mutex are locked */
|
/* connections_mutex and c_mutex are locked */
|
||||||
connection_closing( c );
|
connection_closing( c );
|
||||||
|
|
||||||
|
/* Drain input before close, to allow SSL error codes
|
||||||
|
* to propagate to client. */
|
||||||
|
FD_ZERO(&rfd);
|
||||||
|
FD_SET(s, &rfd);
|
||||||
|
ber_pvt_sb_set_readahead(c->c_sb, 0);
|
||||||
|
for (rc=1; rc>0;)
|
||||||
|
{
|
||||||
|
char buf[4096];
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
rc = select(s+1, &rfd, NULL, NULL, &tv);
|
||||||
|
if (rc == 1)
|
||||||
|
rc = ber_pvt_sb_read(c->c_sb, buf, sizeof(buf));
|
||||||
|
}
|
||||||
connection_close( c );
|
connection_close( c );
|
||||||
} else if ( rc == 0 ) {
|
} else if ( rc == 0 ) {
|
||||||
c->c_needs_tls_accept = 0;
|
c->c_needs_tls_accept = 0;
|
||||||
|
|
@ -954,7 +972,7 @@ connection_input(
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
"ber_get_next on fd %d failed errno=%d (%s)\n",
|
"ber_get_next on fd %d failed errno=%d (%s)\n",
|
||||||
ber_pvt_sb_get_desc( conn->c_sb ), err, STRERROR(err) );
|
ber_pvt_sb_get_desc( conn->c_sb ), err, sock_errstr(err) );
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
"\t*** got %ld of %lu so far\n",
|
"\t*** got %ld of %lu so far\n",
|
||||||
(long) ( conn->c_currentber->ber_buf
|
(long) ( conn->c_currentber->ber_buf
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue