/* 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)
#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
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=
{
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
*/
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;
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 );
err = SSL_accept( ssl );
+#ifdef HAVE_WINSOCK
+ errno = WSAGetLastError();
+#endif
if ( err <= 0 ) {
if ( update_flags( sb, ssl, err ))
return 1;
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
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 ?
}
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;
}
{
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)
{
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)
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;
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;
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 );
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;
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