typedef tls_ctx *(TI_ctx_new)(struct ldapoptions *lo);
typedef void (TI_ctx_ref)(tls_ctx *ctx);
typedef void (TI_ctx_free)(tls_ctx *ctx);
-typedef int (TI_ctx_init)(struct ldapoptions *lo, struct ldaptls *lt, int is_server);
+#define ERRBUFSIZE 256
+typedef int (TI_ctx_init)(struct ldapoptions *lo, struct ldaptls *lt, int is_server, char *errmsg);
typedef tls_session *(TI_session_new)(tls_ctx *ctx, int is_server);
typedef int (TI_session_connect)(LDAP *ld, tls_session *s, const char *name_in);
* initialize a new TLS context
*/
static int
-ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
+ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server, char *errmsg )
{
int rc = 0;
tls_impl *ti = tls_imp;
goto error_exit;
}
- rc = ti->ti_ctx_init( lo, <s, is_server );
+ rc = ti->ti_ctx_init( lo, <s, is_server, errmsg );
error_exit:
if ( rc < 0 && lo->ldo_tls_ctx != NULL ) {
ldap_pvt_tls_init_def_ctx( int is_server )
{
struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
+ char errmsg[ERRBUFSIZE];
int rc;
+ errmsg[0] = 0;
LDAP_MUTEX_LOCK( &tls_def_ctx_mutex );
- rc = ldap_int_tls_init_ctx( lo, is_server );
+ rc = ldap_int_tls_init_ctx( lo, is_server, errmsg );
LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex );
+ if ( rc ) {
+ Debug1( LDAP_DEBUG_ANY,"TLS: init_def_ctx: %s.\n", errmsg );
+ }
return rc;
}
if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile );
lo->ldo_tls_randfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL;
break;
- case LDAP_OPT_X_TLS_NEWCTX:
+ case LDAP_OPT_X_TLS_NEWCTX: {
+ int rc;
+ char errmsg[ERRBUFSIZE];
if ( !arg ) return -1;
if ( lo->ldo_tls_ctx )
ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
lo->ldo_tls_ctx = NULL;
- return ldap_int_tls_init_ctx( lo, *(int *)arg );
+ errmsg[0] = 0;
+ rc = ldap_int_tls_init_ctx( lo, *(int *)arg, errmsg );
+ if ( rc && errmsg[0] ) {
+ if ( ld->ld_error )
+ LDAP_FREE( ld->ld_error );
+ ld->ld_error = LDAP_STRDUP( errmsg );
+ }
+ return rc;
+ }
case LDAP_OPT_X_TLS_CACERT:
if ( lo->ldo_tls_cacert.bv_val )
LDAP_FREE( lo->ldo_tls_cacert.bv_val );
* initialize a new TLS context
*/
static int
-tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
+tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server, char *errmsg )
{
tlsg_ctx *ctx = lo->ldo_tls_ctx;
int rc;
"TLS: warning: no certificate found in CA certificate directory `%s'.\n",
lt->lt_cacertdir );
/* only warn, no return */
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
}
}
"TLS: warning: no certificate loaded from CA certificate file `%s'.\n",
lo->ldo_tls_cacertfile );
/* only warn, no return */
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
}
}
"TLS: could not use CA certificate: %s (%d)\n",
gnutls_strerror( rc ),
rc );
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
return -1;
}
}
unsigned int max = VERIFY_DEPTH;
rc = gnutls_x509_privkey_init( &key );
- if ( rc ) return -1;
+ if ( rc ) {
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
+ return -1;
+ }
/* OpenSSL builds the cert chain for us, but GnuTLS
* expects it to be present in the certfile. If it's
"TLS: could not use private key: %s (%d)\n",
gnutls_strerror( rc ),
rc );
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
return rc;
}
"TLS: could not use certificate: %s (%d)\n",
gnutls_strerror( rc ),
rc );
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
return rc;
}
"TLS: could not use certificate with key: %s (%d)\n",
gnutls_strerror( rc ),
rc );
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
return -1;
}
} else if (( lo->ldo_tls_certfile || lo->ldo_tls_keyfile )) {
ctx->cred,
lt->lt_crlfile,
GNUTLS_X509_FMT_PEM );
- if ( rc < 0 ) return -1;
+ if ( rc < 0 ) {
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
+ return -1;
+ }
rc = 0;
}
rc = gnutls_dh_params_import_pkcs3( ctx->dh_params, &buf,
GNUTLS_X509_FMT_PEM );
LDAP_FREE( buf.data );
- if ( rc ) return -1;
+ if ( rc ) {
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
+ return -1;
+ }
gnutls_certificate_set_dh_params( ctx->cred, ctx->dh_params );
}
static int tlso_opt_trace = 1;
-static void tlso_report_error( void );
+static void tlso_report_error( char *errmsg );
static void tlso_info_cb( const SSL *ssl, int where, int ret );
static int tlso_verify_cb( int ok, X509_STORE_CTX *ctx );
* initialize a new TLS context
*/
static int
-tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
+tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server, char *errmsg )
{
tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx;
int i;
Debug1( LDAP_DEBUG_ANY,
"TLS: could not set cipher list %s.\n",
lo->ldo_tls_ciphersuite );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
}
if ( !SSL_CTX_set_default_verify_paths( ctx ) ) {
Debug0( LDAP_DEBUG_ANY, "TLS: "
"could not use default certificate paths" );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
} else {
if ( !X509_STORE_add_cert( store, cert )) {
Debug0( LDAP_DEBUG_ANY, "TLS: "
"could not use CA certificate" );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
}
"could not load verify locations (file:`%s',dir:`%s').\n",
lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "" );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
"could not load client CA list (file:`%s',dir:`%s').\n",
lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "" );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
if ( !SSL_CTX_use_certificate( ctx, cert )) {
Debug0( LDAP_DEBUG_ANY,
"TLS: could not use certificate.\n" );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
X509_free( cert );
Debug1( LDAP_DEBUG_ANY,
"TLS: could not use certificate file `%s'.\n",
lo->ldo_tls_certfile );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
{
Debug0( LDAP_DEBUG_ANY,
"TLS: could not use private key.\n" );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
EVP_PKEY_free( pkey );
Debug1( LDAP_DEBUG_ANY,
"TLS: could not use key file `%s'.\n",
lo->ldo_tls_keyfile );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
Debug1( LDAP_DEBUG_ANY,
"TLS: could not use DH parameters file `%s'.\n",
lo->ldo_tls_dhfile );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
if (!( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) {
Debug1( LDAP_DEBUG_ANY,
"TLS: could not read DH parameters file `%s'.\n",
lo->ldo_tls_dhfile );
- tlso_report_error();
+ tlso_report_error( errmsg );
BIO_free( bio );
return -1;
}
Debug1( LDAP_DEBUG_ANY,
"TLS: could not set EC name `%s'.\n",
lo->ldo_tls_ecname );
- tlso_report_error();
+ tlso_report_error( errmsg );
return -1;
}
/*
/* Inspired by ERR_print_errors in OpenSSL */
static void
-tlso_report_error( void )
+tlso_report_error( char *errmsg )
{
unsigned long l;
- char buf[200];
+ char buf[ERRBUFSIZE];
const char *file;
int line;
while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
- ERR_error_string_n( l, buf, sizeof( buf ) );
+ ERR_error_string_n( l, buf, ERRBUFSIZE );
+ if ( !*errmsg )
+ strcpy(errmsg, buf );
#ifdef HAVE_EBCDIC
if ( file ) {
file = LDAP_STRDUP( file );
#ifdef HAVE_TLS
rc = bindconf_tls_set( sb, ld );
if ( rc ) {
+ char *errmsg = NULL;
+ ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &errmsg );
Debug( LDAP_DEBUG_ANY,
"slap_client_connect: "
- "URI=%s TLS context initialization failed (%d)\n",
- sb->sb_uri.bv_val, rc );
+ "URI=%s TLS context initialization failed (%d) %s\n",
+ sb->sb_uri.bv_val, rc, errmsg ? errmsg : "" );
+ ldap_memfree( errmsg );
goto done;
}
#endif
ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
load_extop( &slap_EXOP_START_TLS, 0, starttls_extop );
} else if ( rc != LDAP_NOT_SUPPORTED ) {
+ char *errmsg = NULL;
+ ldap_get_option( slap_tls_ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &errmsg );
Debug( LDAP_DEBUG_ANY,
- "main: TLS init def ctx failed: %d\n",
- rc );
+ "main: TLS init def ctx failed: %d %s\n",
+ rc, errmsg ? errmsg : "" );
+ ldap_memfree( errmsg );
rc = 1;
SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
goto destroy;