]> git.sur5r.net Git - openldap/commitdiff
libldap/tls.c: change tls_verify_cb to no longer ignore verification errors.
authorHoward Chu <hyc@openldap.org>
Wed, 10 May 2000 17:07:09 +0000 (17:07 +0000)
committerHoward Chu <hyc@openldap.org>
Wed, 10 May 2000 17:07:09 +0000 (17:07 +0000)
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...)

include/ldap_pvt.h
libraries/libldap/tls.c
servers/slapd/connection.c

index 6164c0574363a99aef3a3f64c8f2aaddc0ce87f3..b4da5008b7ab723d317e3c09bc90bb5edc8609a9 100644 (file)
@@ -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)
index d1d786a541053b4efc99376c3ec76589e996dc3b..71bd5c8c77cd926d96bb9f2c6a33a14dbb8070fd 100644 (file)
@@ -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;
index 4afec31af05172e5a550843c30ac6d89361e09d1..2c6847a8532d9642d3203dcffd3a6eb9c14d94bc 100644 (file)
@@ -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