Skip to content
Snippets Groups Projects
Commit f0c4f83e authored by Howard Chu's avatar Howard Chu
Browse files

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...)
parent dcad3d95
No related branches found
No related tags found
No related merge requests found
......@@ -138,15 +138,18 @@ ldap_pvt_str2lower LDAP_P(( char *str ));
/* tls.c */
struct ldapoptions;
struct ldap;
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_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_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 (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_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)
......
......@@ -27,6 +27,8 @@
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#elif defined( HAVE_SSL_H )
#include <ssl.h>
#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_write( Sockbuf *sb, void *buf, ber_len_t len );
static int tls_close( Sockbuf *sb );
static int tls_report_error( void );
static void tls_report_error( void );
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 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 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 );
#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;
#ifdef LDAP_R_COMPILE
......@@ -302,7 +307,7 @@ update_flags( Sockbuf *sb, SSL * ssl, int rc )
*/
int
ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg )
{
int err;
SSL *ssl;
......@@ -319,9 +324,16 @@ ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
err = SSL_connect( ssl );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
if ( err <= 0 ) {
if ( update_flags( sb, ssl, err ))
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);
ber_pvt_sb_clear_io( sb );
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 );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
if ( err <= 0 ) {
if ( update_flags( sb, ssl, err ))
return 1;
......@@ -372,14 +387,31 @@ ldap_pvt_tls_inplace ( Sockbuf *sb )
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 *
ldap_pvt_tls_get_peer( LDAP *ld )
{
return NULL;
}
const char *
ldap_pvt_tls_get_peer_issuer( LDAP *ld )
{
return NULL;
}
int
......@@ -427,9 +459,9 @@ ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
break;
case LDAP_OPT_X_TLS_CERT:
if ( lo == NULL )
arg = (void *) tls_def_ctx;
*(void **)arg = (void *) tls_def_ctx;
else
arg = lo->ldo_tls_ctx;
*(void **)arg = lo->ldo_tls_ctx;
break;
case LDAP_OPT_X_TLS_CACERTFILE:
*(char **)arg = tls_opt_cacertfile ?
......@@ -520,12 +552,12 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
}
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...
*/
if ( ldap_pvt_tls_connect( sb, ctx_arg ) < 0 ) {
if ( ldap_pvt_tls_connect( ld, sb, ctx_arg ) < 0 ) {
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 );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
update_flags(sb, (SSL *)sb->sb_iodata, ret );
#ifdef WIN32
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 );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
update_flags(sb, (SSL *)sb->sb_iodata, ret );
#ifdef WIN32
if (sb->sb_trans_needs_read)
......@@ -658,11 +696,11 @@ tls_verify_cb( int ok, X509_STORE_CTX *ctx )
if ( iname )
CRYPTO_free ( iname );
return 1;
return ok;
}
/* Inspired by ERR_print_errors in OpenSSL */
static int
static void
tls_report_error( void )
{
unsigned long l;
......@@ -693,11 +731,13 @@ tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
return tmp_rsa;
}
#if 0
static DH *
tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
{
return NULL;
}
#endif
#else
static int dummy;
......
......@@ -881,6 +881,9 @@ int connection_read(ber_socket_t s)
if ( c->c_is_tls && c->c_needs_tls_accept ) {
rc = ldap_pvt_tls_accept( c->c_sb, NULL );
if ( rc < 0 ) {
struct timeval tv;
fd_set rfd;
Debug( LDAP_DEBUG_TRACE,
"connection_read(%d): TLS accept error error=%d id=%ld, closing\n",
s, rc, c->c_connid );
......@@ -888,6 +891,21 @@ int connection_read(ber_socket_t s)
c->c_needs_tls_accept = 0;
/* connections_mutex and c_mutex are locked */
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 );
} else if ( rc == 0 ) {
c->c_needs_tls_accept = 0;
......@@ -954,7 +972,7 @@ connection_input(
Debug( LDAP_DEBUG_TRACE,
"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,
"\t*** got %ld of %lu so far\n",
(long) ( conn->c_currentber->ber_buf
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment