*/
#include "portable.h"
+#include "ldap_config.h"
#include <stdio.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include <ac/param.h>
+#include <ac/dirent.h>
#include "ldap-int.h"
static char *tls_opt_keyfile = NULL;
static char *tls_opt_cacertfile = NULL;
static char *tls_opt_cacertdir = NULL;
-static int tls_opt_require_cert = 0;
+static int tls_opt_require_cert = LDAP_OPT_X_TLS_DEMAND;
static char *tls_opt_ciphersuite = NULL;
static char *tls_opt_randfile = NULL;
tls_def_ctx = SSL_CTX_new( SSLv23_method() );
if ( tls_def_ctx == NULL ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_init_def_ctx: "
"TLS could not allocate default ctx (%d).\n",
- ERR_peek_error() ));
+ ERR_peek_error(), 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "TLS: could not allocate default ctx (%lu).\n",
+ "TLS: could not allocate default ctx (%lu).\n",
ERR_peek_error(),0,0);
#endif
goto error_exit;
}
+
if ( tls_opt_ciphersuite &&
- !SSL_CTX_set_cipher_list( tls_def_ctx,
- tls_opt_ciphersuite ) )
+ !SSL_CTX_set_cipher_list( tls_def_ctx, tls_opt_ciphersuite ) )
{
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_init_def_ctx: "
"TLS could not set cipher list %s.\n",
- tls_opt_ciphersuite ));
+ tls_opt_ciphersuite, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "TLS: could not set cipher list %s.\n",
- tls_opt_ciphersuite, 0, 0 );
+ "TLS: could not set cipher list %s.\n",
+ tls_opt_ciphersuite, 0, 0 );
#endif
tls_report_error();
goto error_exit;
}
+
if (tls_opt_cacertfile != NULL || tls_opt_cacertdir != NULL) {
if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
- tls_opt_cacertfile,
- tls_opt_cacertdir )
- || !SSL_CTX_set_default_verify_paths( tls_def_ctx ) )
+ tls_opt_cacertfile, tls_opt_cacertdir ) ||
+ !SSL_CTX_set_default_verify_paths( tls_def_ctx ) )
{
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
- "TLS could not load verify locations (file:`%s',dir:`%s').\n",
+ LDAP_LOG ( TRANSPORT, ERR,
+ "ldap_pvt_tls_init_def_ctx: "
+ "TLS could not load verify locations "
+ "(file:`%s',dir:`%s').\n",
tls_opt_cacertfile ? tls_opt_cacertfile : "",
- tls_opt_cacertdir ? tls_opt_cacertdir : "" ));
+ tls_opt_cacertdir ? tls_opt_cacertdir : "", 0 );
#else
Debug( LDAP_DEBUG_ANY, "TLS: "
"could not load verify locations (file:`%s',dir:`%s').\n",
tls_report_error();
goto error_exit;
}
+
calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir );
if ( !calist ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_init_def_ctx: "
"TLS could not load client CA list (file: `%s',dir:`%s')\n",
tls_opt_cacertfile ? tls_opt_cacertfile : "",
- tls_opt_cacertdir ? tls_opt_cacertdir : "" ));
+ tls_opt_cacertdir ? tls_opt_cacertdir : "", 0 );
#else
Debug( LDAP_DEBUG_ANY, "TLS: "
"could not load client CA list (file:`%s',dir:`%s').\n",
tls_report_error();
goto error_exit;
}
+
SSL_CTX_set_client_CA_list( tls_def_ctx, calist );
}
+
if ( tls_opt_keyfile &&
- !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
- tls_opt_keyfile,
- SSL_FILETYPE_PEM ) )
+ !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
+ tls_opt_keyfile, SSL_FILETYPE_PEM ) )
{
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
- "TLS could not use key file `%s'.\n", tls_opt_keyfile ));
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_init_def_ctx: "
+ "TLS could not use key file `%s'.\n", tls_opt_keyfile, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "TLS: could not use key file `%s'.\n",
- tls_opt_keyfile,0,0);
+ "TLS: could not use key file `%s'.\n",
+ tls_opt_keyfile,0,0);
#endif
tls_report_error();
goto error_exit;
}
+
if ( tls_opt_certfile &&
- !SSL_CTX_use_certificate_file( tls_def_ctx,
- tls_opt_certfile,
- SSL_FILETYPE_PEM ) )
+ !SSL_CTX_use_certificate_file( tls_def_ctx,
+ tls_opt_certfile, SSL_FILETYPE_PEM ) )
{
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
- "TLS could not use certificate `%s'.\n", tls_opt_certfile ));
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_init_def_ctx: "
+ "TLS could not use certificate `%s'.\n",
+ tls_opt_certfile, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "TLS: could not use certificate `%s'.\n",
- tls_opt_certfile,0,0);
+ "TLS: could not use certificate `%s'.\n",
+ tls_opt_certfile,0,0);
#endif
tls_report_error();
goto error_exit;
}
+
if ( ( tls_opt_certfile || tls_opt_keyfile ) &&
- !SSL_CTX_check_private_key( tls_def_ctx ) )
+ !SSL_CTX_check_private_key( tls_def_ctx ) )
{
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_init_def_ctx: "
- "TLS private key mismatch.\n" ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "ldap_pvt_tls_init_def_ctx: TLS private key mismatch.\n",
+ 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "TLS: private key mismatch.\n",
- 0,0,0);
+ "TLS: private key mismatch.\n",
+ 0,0,0);
#endif
tls_report_error();
goto error_exit;
}
+
if ( tls_opt_trace ) {
SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb );
}
+
i = SSL_VERIFY_NONE;
if ( tls_opt_require_cert ) {
i = SSL_VERIFY_PEER;
if ( tls_opt_require_cert == LDAP_OPT_X_TLS_DEMAND ||
- tls_opt_require_cert == LDAP_OPT_X_TLS_HARD ) {
+ tls_opt_require_cert == LDAP_OPT_X_TLS_HARD ) {
i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
}
+
SSL_CTX_set_verify( tls_def_ctx, i,
tls_opt_require_cert == LDAP_OPT_X_TLS_ALLOW ?
tls_verify_ok : tls_verify_cb );
ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
#endif
return 0;
+
error_exit:
if ( tls_def_ctx != NULL ) {
SSL_CTX_free( tls_def_ctx );
if ( bundle ) {
ca_list = SSL_load_client_CA_file( bundle );
}
- /*
- * FIXME: We have now to go over all files in dir, load them
- * and add every certificate there to ca_list.
- */
+#if defined(HAVE_DIRENT_H) || defined(dirent)
+ if ( dir ) {
+ DIR *dirp;
+ struct dirent *d;
+ char buf[MAXPATHLEN];
+ int l = strlen(dir), freeit = 0;
+
+ if (l > sizeof(buf))
+ goto done;
+
+ dirp = opendir( dir );
+
+ if ( !ca_list ) {
+ ca_list = sk_X509_NAME_new_null();
+ freeit = 1;
+ }
+
+ strcpy(buf, dir);
+
+ while ( dirp ) {
+ if ( ( d = readdir( dirp )) == NULL) {
+ closedir( dirp );
+ break;
+ }
+ if (l + sizeof(LDAP_DIRSEP) + NAMLEN(d) > sizeof(buf))
+ continue;
+
+ sprintf( buf+l, LDAP_DIRSEP "%s", d->d_name );
+ if ( SSL_add_file_cert_subjects_to_stack(ca_list, buf)) {
+ freeit = 0;
+ }
+ }
+ if ( freeit ) {
+ sk_X509_NAME_free( ca_list );
+ ca_list = NULL;
+ }
+ }
+#endif
+done:
return ca_list;
}
ssl = SSL_new( ctx );
if ( ssl == NULL ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "alloc_handle: "
- "TLS can't create ssl handle.\n" ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "alloc_handle: TLS can't create ssl handle.\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
#endif
sb->sb_trans_needs_read = 0;
sb->sb_trans_needs_write = 0;
- if (err == SSL_ERROR_WANT_READ)
- {
- sb->sb_trans_needs_read = 1;
- return 1;
- } else if (err == SSL_ERROR_WANT_WRITE)
- {
- sb->sb_trans_needs_write = 1;
- return 1;
- } else if (err == SSL_ERROR_WANT_CONNECT)
- {
- return 1;
+
+ if (err == SSL_ERROR_WANT_READ) {
+ sb->sb_trans_needs_read = 1;
+ return 1;
+
+ } else if (err == SSL_ERROR_WANT_WRITE) {
+ sb->sb_trans_needs_write = 1;
+ return 1;
+
+ } else if (err == SSL_ERROR_WANT_CONNECT) {
+ return 1;
}
return 0;
}
assert( sbiod != NULL );
p = LBER_MALLOC( sizeof( *p ) );
- if ( p == NULL )
+ if ( p == NULL ) {
return -1;
+ }
p->ssl = (SSL *)arg;
p->sbiod = sbiod;
if (err == SSL_ERROR_WANT_WRITE ) {
sbiod->sbiod_sb->sb_trans_needs_write = 1;
errno = EWOULDBLOCK;
- }
- else
+
+ } else {
sbiod->sbiod_sb->sb_trans_needs_write = 0;
+ }
return ret;
}
static int
sb_tls_bio_destroy( BIO *b )
{
- if ( b == NULL )
- return 0;
+ if ( b == NULL ) return 0;
b->ptr = NULL; /* sb_tls_remove() will free it */
b->init = 0;
struct tls_data *p;
int ret;
- if ( buf == NULL || len <= 0 )
- return 0;
+ if ( buf == NULL || len <= 0 ) return 0;
p = (struct tls_data *)b->ptr;
- if ( p == NULL || p->sbiod == NULL )
+ if ( p == NULL || p->sbiod == NULL ) {
return 0;
+ }
ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
BIO_clear_retry_flags( b );
- if ( ret < 0 && errno == EWOULDBLOCK )
+ if ( ret < 0 && errno == EWOULDBLOCK ) {
BIO_set_retry_read( b );
+ }
return ret;
}
struct tls_data *p;
int ret;
- if ( buf == NULL || len <= 0 )
- return 0;
+ if ( buf == NULL || len <= 0 ) return 0;
p = (struct tls_data *)b->ptr;
- if ( p == NULL || p->sbiod == NULL )
+ if ( p == NULL || p->sbiod == NULL ) {
return 0;
+ }
ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
BIO_clear_retry_flags( b );
- if ( ret < 0 && errno == EWOULDBLOCK )
+ if ( ret < 0 && errno == EWOULDBLOCK ) {
BIO_set_retry_write( b );
+ }
return ret;
}
#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));
}
+
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_int_tls_connect: "
- "TLS can't connect.\n" ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "ldap_int_tls_connect: TLS can't connect.\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
#endif
+
ber_sockbuf_remove_io( sb, &sb_tls_sbio,
LBER_SBIOD_LEVEL_TRANSPORT );
#ifdef LDAP_DEBUG
if ( HAS_TLS( sb ) ) {
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
+
} else {
ssl = alloc_handle( ctx_arg );
- if ( ssl == NULL )
- return -1;
+ if ( ssl == NULL ) return -1;
+
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
errno = WSAGetLastError();
#endif
if ( err <= 0 ) {
- if ( update_flags( sb, ssl, err ))
- return 1;
+ if ( update_flags( sb, ssl, err )) return 1;
+
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_accept: "
- "TLS can't accept.\n" ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "ldap_pvt_tls_accept: TLS can't accept.\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
#endif
+
tls_report_error();
ber_sockbuf_remove_io( sb, &sb_tls_sbio,
LBER_SBIOD_LEVEL_TRANSPORT );
int
ldap_pvt_tls_inplace ( Sockbuf *sb )
{
- if ( HAS_TLS( sb ) )
- return(1);
- return(0);
+ return HAS_TLS( sb ) ? 1 : 0;
}
void *
int
ldap_pvt_tls_get_strength( void *s )
{
- SSL_CIPHER *c;
+ SSL_CIPHER *c;
- c = SSL_get_current_cipher((SSL *)s);
- return SSL_CIPHER_get_bits(c, NULL);
+ c = SSL_get_current_cipher((SSL *)s);
+ return SSL_CIPHER_get_bits(c, NULL);
}
-static X509 *
-tls_get_cert( SSL *s )
-{
- /* If peer cert was bad, treat as if no cert was given */
- if (SSL_get_verify_result(s)) {
- /* If we can send an alert, do so */
- if (SSL_version(s) != SSL2_VERSION) {
- ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_BAD_CERTIFICATE);
- }
- return NULL;
- }
- return SSL_get_peer_certificate(s);
-}
-
-char *
-ldap_pvt_tls_get_peer( void *s )
+int
+ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )
{
- X509 *x;
- X509_NAME *xn;
- char buf[2048], *p;
+ X509 *x;
+ X509_NAME *xn;
+ int rc;
+ x = SSL_get_certificate((SSL *)s);
- x = tls_get_cert((SSL *)s);
+ if (!x) return LDAP_INVALID_CREDENTIALS;
+
+ xn = X509_get_subject_name(x);
+ rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags );
+ X509_free(x);
+ return rc;
+}
- if (!x)
- return NULL;
-
- xn = X509_get_subject_name(x);
- p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
- X509_free(x);
- return p;
+static X509 *
+tls_get_cert( SSL *s )
+{
+ /* If peer cert was bad, treat as if no cert was given */
+ if (SSL_get_verify_result(s)) {
+ /* If we can send an alert, do so */
+ if (SSL_version(s) != SSL2_VERSION) {
+ ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_BAD_CERTIFICATE);
+ }
+ return NULL;
+ }
+ return SSL_get_peer_certificate(s);
}
-char *
-ldap_pvt_tls_get_peer_dn( void *s )
+int
+ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )
{
X509 *x;
X509_NAME *xn;
- char buf[2048], *p, *dn;
+ int rc;
x = tls_get_cert((SSL *)s);
- if (!x) return NULL;
-
+ if (!x) return LDAP_INVALID_CREDENTIALS;
+
xn = X509_get_subject_name(x);
- p = X509_NAME_oneline(xn, buf, sizeof(buf));
-
- dn = ldap_dcedn2dn( p );
-
+ rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags);
X509_free(x);
- return dn;
+ return rc;
}
char *
int ret;
x = tls_get_cert((SSL *)s);
-
- if (!x)
- return NULL;
+ if (!x) return NULL;
xn = X509_get_subject_name(x);
}
int
-ldap_pvt_tls_check_hostname( void *s, const char *name_in )
+ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
{
- int i, ret = LDAP_LOCAL_ERROR;
- X509 *x;
+ int i, ret = LDAP_LOCAL_ERROR;
+ X509 *x;
const char *name;
if( ldap_int_hostname &&
name = name_in;
}
- x = tls_get_cert((SSL *)s);
- if (!x)
- {
+ x = tls_get_cert((SSL *)s);
+ if (!x) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_check_hostname: "
- "TLS unable to get peer certificate.\n" ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "ldap_pvt_tls_check_hostname: "
+ "TLS unable to get peer certificate.\n" , 0, 0, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "TLS: unable to get peer certificate.\n",
- 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: unable to get peer certificate.\n",
+ 0, 0, 0 );
#endif
- return ret;
- }
-
- i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
- if (i >= 0)
- {
- X509_EXTENSION *ex;
- STACK_OF(GENERAL_NAME) *alt;
+ /* If this was a fatal condition, things would have
+ * aborted long before now.
+ */
+ return LDAP_SUCCESS;
+ }
- ex = X509_get_ext(x, i);
- alt = X509V3_EXT_d2i(ex);
- if (alt)
- {
- int n, len1, len2 = 0;
- char *domain;
- GENERAL_NAME *gn;
- X509V3_EXT_METHOD *method;
-
- len1 = strlen(name);
- n = sk_GENERAL_NAME_num(alt);
- domain = strchr(name, '.');
- if (domain)
- len2 = len1 - (domain-name);
- for (i=0; i<n; i++)
- {
- gn = sk_GENERAL_NAME_value(alt, i);
- if (gn->type == GEN_DNS)
- {
- char *sn = ASN1_STRING_data(gn->d.ia5);
- int sl = ASN1_STRING_length(gn->d.ia5);
+ i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
+ if (i >= 0) {
+ X509_EXTENSION *ex;
+ STACK_OF(GENERAL_NAME) *alt;
+
+ ex = X509_get_ext(x, i);
+ alt = X509V3_EXT_d2i(ex);
+ if (alt) {
+ int n, len1, len2 = 0;
+ char *domain;
+ GENERAL_NAME *gn;
+
+ len1 = strlen(name);
+ n = sk_GENERAL_NAME_num(alt);
+ domain = strchr(name, '.');
+ if (domain) {
+ len2 = len1 - (domain-name);
+ }
+ for (i=0; i<n; i++) {
+ gn = sk_GENERAL_NAME_value(alt, i);
+ if (gn->type == GEN_DNS) {
+ char *sn = ASN1_STRING_data(gn->d.ia5);
+ int sl = ASN1_STRING_length(gn->d.ia5);
+
+ /* Is this an exact match? */
+ if ((len1 == sl) && !strncasecmp(name, sn, len1)) {
+ break;
+ }
+
+ /* Is this a wildcard match? */
+ if ((*sn == '*') && domain && (len2 == sl-1) &&
+ !strncasecmp(domain, sn+1, len2))
+ {
+ break;
+ }
- /* Is this an exact match? */
- if ((len1 == sl) && !strncasecmp(name, sn, len1))
- break;
+#if 0
+ /* Is this a RFC 2549 style wildcard match? */
+ if ((*sn == '.') && domain && (len2 == sl) &&
+ !strncasecmp(domain, sn, len2))
+ {
+ break;
+ }
+#endif
+ }
+ }
- /* Is this a wildcard match? */
- if ((*sn == '*') && domain && (len2 == sl-1) &&
- !strncasecmp(domain, sn+1, len2))
- break;
+ GENERAL_NAMES_free(alt);
+ if (i < n) { /* Found a match */
+ ret = LDAP_SUCCESS;
+ }
}
- }
- method = X509V3_EXT_get(ex);
- method->ext_free(alt);
- if (i < n) /* Found a match */
- ret = LDAP_SUCCESS;
}
- }
- if (ret != LDAP_SUCCESS)
- {
- X509_NAME *xn;
- char buf[2048];
+ if (ret != LDAP_SUCCESS) {
+ X509_NAME *xn;
+ char buf[2048];
- xn = X509_get_subject_name(x);
+ xn = X509_get_subject_name(x);
- if (X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf))
- == -1)
- {
+ if( X509_NAME_get_text_by_NID( xn, NID_commonName,
+ buf, sizeof(buf)) == -1)
+ {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_check_hostname: "
- "TLS unable to get common name from peer certificate.\n" ));
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_check_hostname: "
+ "TLS unable to get common name from peer certificate.\n",
+ 0, 0, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "TLS: unable to get common name from peer certificate.\n",
- 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: unable to get common name from peer certificate.\n",
+ 0, 0, 0 );
#endif
- } else if (strcasecmp(name, buf))
- {
+ ld->ld_error = LDAP_STRDUP("TLS: unable to get CN from peer certificate");
+
+ } else if (strcasecmp(name, buf)) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "ldap_pvt_tls_check_hostname: "
- "TLS hostname (%s) does not match "
- "common name in certificate (%s).\n", name, buf ));
+ LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_check_hostname: "
+ "TLS hostname (%s) does not match "
+ "common name in certificate (%s).\n", name, buf, 0 );
#else
- Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
- "common name in certificate (%s).\n",
- name, buf, 0 );
+ Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
+ "common name in certificate (%s).\n",
+ name, buf, 0 );
#endif
- ret = LDAP_CONNECT_ERROR;
- } else
- {
- ret = LDAP_SUCCESS;
+ ret = LDAP_CONNECT_ERROR;
+ ld->ld_error = LDAP_STRDUP("TLS: hostname does not match CN in peer certificate");
+
+ } else {
+ ret = LDAP_SUCCESS;
+ }
}
- }
- X509_free(x);
- return ret;
+ X509_free(x);
+ return ret;
}
const char *
ldap_pvt_tls_get_peer_issuer( void *s )
{
-#if 0 /* currently unused; see ldap_pvt_tls_get_peer() if needed */
- X509 *x;
- X509_NAME *xn;
- char buf[2048], *p;
-
- x = SSL_get_peer_certificate((SSL *)s);
-
- if (!x)
- return NULL;
-
- xn = X509_get_issuer_name(x);
- p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
- X509_free(x);
- return p;
+#if 0 /* currently unused; see ldap_pvt_tls_get_peer_dn() if needed */
+ X509 *x;
+ X509_NAME *xn;
+ char buf[2048], *p;
+
+ x = SSL_get_peer_certificate((SSL *)s);
+
+ if (!x) return NULL;
+
+ xn = X509_get_issuer_name(x);
+ p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
+ X509_free(x);
+ return p;
#else
- return NULL;
+ return NULL;
#endif
}
case LDAP_OPT_X_TLS_REQUIRE_CERT:
case LDAP_OPT_X_TLS:
i = -1;
- if ( strcasecmp( arg, "never" ) == 0 )
+ if ( strcasecmp( arg, "never" ) == 0 ) {
i = LDAP_OPT_X_TLS_NEVER ;
- if ( strcasecmp( arg, "demand" ) == 0 )
+
+ } else if ( strcasecmp( arg, "demand" ) == 0 ) {
i = LDAP_OPT_X_TLS_DEMAND ;
- if ( strcasecmp( arg, "allow" ) == 0 )
+
+ } else if ( strcasecmp( arg, "allow" ) == 0 ) {
i = LDAP_OPT_X_TLS_ALLOW ;
- if ( strcasecmp( arg, "try" ) == 0 )
+
+ } else if ( strcasecmp( arg, "try" ) == 0 ) {
i = LDAP_OPT_X_TLS_TRY ;
- if ( ( strcasecmp( arg, "hard" ) == 0 ) ||
- ( strcasecmp( arg, "on" ) == 0 ) ||
- ( strcasecmp( arg, "yes" ) == 0) ||
- ( strcasecmp( arg, "true" ) == 0 ) )
+
+ } else if ( ( strcasecmp( arg, "hard" ) == 0 ) ||
+ ( strcasecmp( arg, "on" ) == 0 ) ||
+ ( strcasecmp( arg, "yes" ) == 0) ||
+ ( strcasecmp( arg, "true" ) == 0 ) )
+ {
i = LDAP_OPT_X_TLS_HARD ;
+ }
if (i >= 0) {
return ldap_pvt_tls_set_option( ld, option, &i );
*(int *)arg = lo->ldo_tls_mode;
break;
case LDAP_OPT_X_TLS_CTX:
- if ( ld == NULL )
+ if ( ld == NULL ) {
*(void **)arg = (void *) tls_def_ctx;
- else
+ } else {
*(void **)arg = ld->ld_defconn->lconn_tls_ctx;
+ }
break;
case LDAP_OPT_X_TLS_CACERTFILE:
*(char **)arg = tls_opt_cacertfile ?
/*
* compare host with name(s) in certificate
*/
- ld->ld_errno = ldap_pvt_tls_check_hostname( ssl, host );
+ ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host );
if (ld->ld_errno != LDAP_SUCCESS) {
return ld->ld_errno;
}
* set SASL properties to TLS ssf and authid
*/
{
- const char *authid;
+ struct berval authid = { 0, NULL };
ber_len_t ssf;
/* we need to let SASL know */
ssf = ldap_pvt_tls_get_strength( ssl );
- authid = ldap_pvt_tls_get_peer( ssl );
+ /* failure is OK, we just can't use SASL EXTERNAL */
+ (void) ldap_pvt_tls_get_my_dn( ssl, &authid, NULL, 0 );
- (void) ldap_int_sasl_external( ld, conn, authid, ssf );
+ (void) ldap_int_sasl_external( ld, conn, authid.bv_val, ssf );
+ LDAP_FREE( authid.bv_val );
}
return LDAP_SUCCESS;
op = "undefined";
}
- if ( where & SSL_CB_LOOP ) {
+ if ( where & SSL_CB_LOOP ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_DETAIL1, "tls_info_cb: "
- "TLS trace: %s:%s\n", op, SSL_state_string_long( ssl ) ));
+ LDAP_LOG ( TRANSPORT, DETAIL1, "tls_info_cb: "
+ "TLS trace: %s:%s\n", op, SSL_state_string_long( ssl ), 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "TLS trace: %s:%s\n",
- op, SSL_state_string_long( ssl ), 0 );
+ "TLS trace: %s:%s\n",
+ op, SSL_state_string_long( ssl ), 0 );
#endif
+
} else if ( where & SSL_CB_ALERT ) {
- op = ( where & SSL_CB_READ ) ? "read" : "write";
+ op = ( where & SSL_CB_READ ) ? "read" : "write";
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_DETAIL1, "tls_info_cb: "
- "TLS trace: SSL3 alert %s:%s:%s\n", op,
- SSL_alert_type_string_long( ret ),
- SSL_alert_desc_string_long( ret) ));
+ LDAP_LOG ( TRANSPORT, DETAIL1,
+ "tls_info_cb: TLS trace: SSL3 alert %s:%s:%s\n",
+ op, SSL_alert_type_string_long( ret ),
+ SSL_alert_desc_string_long( ret) );
#else
Debug( LDAP_DEBUG_TRACE,
- "TLS trace: SSL3 alert %s:%s:%s\n",
- op,
- SSL_alert_type_string_long( ret ),
- SSL_alert_desc_string_long( ret) );
+ "TLS trace: SSL3 alert %s:%s:%s\n",
+ op,
+ SSL_alert_type_string_long( ret ),
+ SSL_alert_desc_string_long( ret) );
#endif
+
} else if ( where & SSL_CB_EXIT ) {
- if ( ret == 0 ) {
+ if ( ret == 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "tls_info_cb: "
- "TLS trace: %s:failed in %s\n", op, SSL_state_string_long( ssl ) ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "tls_info_cb: TLS trace: %s:failed in %s\n",
+ op, SSL_state_string_long( ssl ), 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "TLS trace: %s:failed in %s\n",
- op, SSL_state_string_long( ssl ), 0 );
+ "TLS trace: %s:failed in %s\n",
+ op, SSL_state_string_long( ssl ), 0 );
#endif
- } else if ( ret < 0 ) {
+ } else if ( ret < 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "tls_info_cb: "
- "TLS trace: %s:error in %s\n", op, SSL_state_string_long( ssl ) ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "tls_info_cb: TLS trace: %s:error in %s\n",
+ op, SSL_state_string_long( ssl ), 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "TLS trace: %s:error in %s\n",
- op, SSL_state_string_long( ssl ), 0 );
+ "TLS trace: %s:error in %s\n",
+ op, SSL_state_string_long( ssl ), 0 );
#endif
}
}
sname = X509_NAME_oneline( subject, NULL, 0 );
iname = X509_NAME_oneline( issuer, NULL, 0 );
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR, "tls_verify_cb"
- "TLS certificate verification: depth: %d, err: %d: "
- "subject: %s, issuer: %s\n", errdepth, errnum,
- sname ? sname : "-unknown-", iname ? iname : "-unknown-" ));
+ LDAP_LOG( TRANSPORT, ERR,
+ "TLS certificate verification: depth: %d, err: %d, subject: %s,",
+ errdepth, errnum,
+ sname ? sname : "-unknown-" );
+ LDAP_LOG( TRANSPORT, ERR, " issuer: %s\n", iname ? iname : "-unknown-", 0, 0 );
+ if ( !ok ) {
+ LDAP_LOG ( TRANSPORT, ERR,
+ "TLS certificate verification: Error, %s\n",
+ X509_verify_cert_error_string(errnum), 0, 0 );
+ }
#else
Debug( LDAP_DEBUG_TRACE,
- "TLS certificate verification: depth: %d, err: %d, subject: %s,",
- errdepth, errnum,
- sname ? sname : "-unknown-" );
+ "TLS certificate verification: depth: %d, err: %d, subject: %s,",
+ errdepth, errnum,
+ sname ? sname : "-unknown-" );
Debug( LDAP_DEBUG_TRACE, " issuer: %s\n", iname ? iname : "-unknown-", 0, 0 );
+ if ( !ok ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS certificate verification: Error, %s\n",
+ X509_verify_cert_error_string(errnum), 0, 0 );
+ }
#endif
if ( sname )
CRYPTO_free ( sname );
static void
tls_report_error( void )
{
- unsigned long l;
- char buf[200];
- const char *file;
- int line;
+ unsigned long l;
+ char buf[200];
+ const char *file;
+ int line;
- while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
+ while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR,
- "tls_report_error: TLS %s %s:%d\n",
- ERR_error_string( l, buf ), file, line ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "tls_report_error: TLS %s %s:%d\n",
+ ERR_error_string( l, buf ), file, line );
#else
- Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
- ERR_error_string( l, buf ), file, line );
+ Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
+ ERR_error_string( l, buf ), file, line );
#endif
- }
+ }
}
static RSA *
if ( !tmp_rsa ) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_ERR,
- "tls_tmp_rsa_cb: TLS Failed to generate temporary %d-bit %s RSA key\n",
- key_length, is_export ? "export" : "domestic" ));
+ LDAP_LOG ( TRANSPORT, ERR,
+ "tls_tmp_rsa_cb: TLS Failed to generate temporary %d-bit %s "
+ "RSA key\n", key_length, is_export ? "export" : "domestic", 0 );
#else
Debug( LDAP_DEBUG_ANY,
"TLS: Failed to generate temporary %d-bit %s RSA key\n",
if (randfile == NULL) {
/* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd.
* If $HOME is not set or buffer too small to hold the pathname,
- * an error occurs. - From RAND_file_name() man page.
+ * an error occurs. - From RAND_file_name() man page.
* The fact is that when $HOME is NULL, .rnd is used.
*/
randfile = RAND_file_name( buffer, sizeof( buffer ) );
if (randfile == NULL) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_DETAIL1,
+ LDAP_LOG ( TRANSPORT, DETAIL1,
"tls_seed_PRNG: TLS Use configuration file or "
- "$RANDFILE to define seed PRNG\n" ));
+ "$RANDFILE to define seed PRNG\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"TLS: Use configuration file or $RANDFILE to define seed PRNG\n",
if (RAND_status() == 0) {
#ifdef NEW_LOGGING
- LDAP_LOG (( "tls", LDAP_LEVEL_DETAIL1,
- "tls_seed_PRNG: TLS PRNG not been seeded with enough data\n" ));
+ LDAP_LOG ( TRANSPORT, DETAIL1,
+ "tls_seed_PRNG: TLS PRNG not been seeded with enough data\n",
+ 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"TLS: PRNG not been seeded with enough data\n",