2 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5 * tls.c - Handle tls/ssl using SSLeay or OpenSSL.
16 #include <ac/socket.h>
17 #include <ac/string.h>
19 #include <ac/unistd.h>
24 #include <ldap_pvt_thread.h>
27 #ifdef HAVE_OPENSSL_SSL_H
28 #include <openssl/ssl.h>
29 #elif defined( HAVE_SSL_H )
33 static char *tls_opt_certfile = NULL;
34 static char *tls_opt_keyfile = NULL;
35 static char *tls_opt_cacertfile = NULL;
36 static char *tls_opt_cacertdir = NULL;
37 static int tls_opt_require_cert = 0;
38 static char *tls_opt_ciphersuite = NULL;
40 #define HAS_TLS( sb ) ((sb)->sb_io==&tls_io)
42 static int tls_setup( Sockbuf *sb, void *arg );
43 static int tls_remove( Sockbuf *sb );
44 static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
45 static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
46 static int tls_close( Sockbuf *sb );
47 static int tls_report_error( void );
49 static Sockbuf_IO tls_io=
58 static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
60 static SSL_CTX *tls_def_ctx = NULL;
64 * provide mutexes for the SSLeay library.
66 static ldap_pvt_thread_mutex_t tls_mutexes[CRYPTO_NUM_LOCKS];
68 static void tls_locking_cb( int mode, int type, const char *file, int line )
70 if ( mode & CRYPTO_LOCK ) {
71 ldap_pvt_thread_mutex_lock( tls_mutexes+type );
73 ldap_pvt_thread_mutex_unlock( tls_mutexes+type );
78 * an extra mutex for the default ctx.
81 static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
83 static void tls_init_threads( void )
87 for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
88 ldap_pvt_thread_mutex_init( tls_mutexes+i );
90 CRYPTO_set_locking_callback( tls_locking_cb );
91 /* FIXME: the thread id should be added somehow... */
93 ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
95 #endif /* LDAP_R_COMPILE */
98 * Initialize tls system. Should be called only once.
101 ldap_pvt_tls_init( void )
103 static int tls_initialized = 0;
105 if ( tls_initialized )
107 #ifdef LDAP_R_COMPILE
110 SSL_load_error_strings();
111 SSLeay_add_ssl_algorithms();
116 * initialize the default context
119 ldap_pvt_tls_init_def_ctx( void )
121 #ifdef LDAP_R_COMPILE
122 ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
124 if ( tls_def_ctx == NULL ) {
125 tls_def_ctx = SSL_CTX_new( SSLv23_method() );
126 if ( tls_def_ctx == NULL ) {
127 Debug( LDAP_DEBUG_ANY,
128 "TLS: could not allocate default ctx.\n",0,0,0);
131 if ( tls_opt_ciphersuite &&
132 !SSL_CTX_set_cipher_list( tls_def_ctx,
133 tls_opt_ciphersuite ) ) {
134 Debug( LDAP_DEBUG_ANY,
135 "TLS: could not set cipher list %s.\n",
136 tls_opt_ciphersuite, 0, 0 );
140 if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
142 tls_opt_cacertdir ) ||
143 !SSL_CTX_set_default_verify_paths( tls_def_ctx ) ) {
144 Debug( LDAP_DEBUG_ANY,
145 "TLS: could not load verify locations (file:`%s',dir:`%s').\n",
146 tls_opt_cacertfile,tls_opt_cacertdir,0);
150 if ( tls_opt_keyfile &&
151 !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
153 SSL_FILETYPE_PEM ) ) {
154 Debug( LDAP_DEBUG_ANY,
155 "TLS: could not use key file `%s'.\n",
156 tls_opt_keyfile,0,0);
160 if ( tls_opt_certfile &&
161 !SSL_CTX_use_certificate_file( tls_def_ctx,
163 SSL_FILETYPE_PEM ) ) {
164 Debug( LDAP_DEBUG_ANY,
165 "TLS: could not use certificate `%s'.\n",
166 tls_opt_certfile,0,0);
170 if ( ( tls_opt_certfile || tls_opt_keyfile ) &&
171 !SSL_CTX_check_private_key( tls_def_ctx ) ) {
172 Debug( LDAP_DEBUG_ANY,
173 "TLS: private key mismatch.\n",
178 SSL_CTX_set_verify( tls_def_ctx, (tls_opt_require_cert) ?
179 (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) :
180 SSL_VERIFY_PEER, tls_verify_cb );
182 #ifdef LDAP_R_COMPILE
183 ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
187 #ifdef LDAP_R_COMPILE
188 ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
194 alloc_handle( Sockbuf *sb, void *ctx_arg )
201 ctx = (SSL_CTX *) ctx_arg;
203 if ( ldap_pvt_tls_init_def_ctx() < 0 )
208 ssl = SSL_new( ctx );
210 Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
215 SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) );
220 update_flags( Sockbuf *sb, SSL * ssl )
222 sb->sb_trans_needs_read = SSL_want_read(ssl) ? 1 : 0;
223 sb->sb_trans_needs_write = SSL_want_write(ssl) ? 1 : 0;
227 * Call this to do a TLS connect on a sockbuf. ctx_arg can be
228 * a SSL_CTX * or NULL, in which case the default ctx is used.
232 * 0 - Success. Connection is ready for communication.
233 * <0 - Error. Can't create a TLS stream.
234 * >0 - Partial success.
235 * Do a select (using information from lber_pvt_sb_needs_{read,write}
240 ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
245 if ( HAS_TLS( sb ) ) {
246 ssl = (SSL *) sb->sb_iodata;
248 ssl = alloc_handle( sb, ctx_arg );
251 ber_pvt_sb_clear_io( sb );
252 ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
255 err = SSL_connect( ssl );
260 (errno==EWOULDBLOCK) ||
266 update_flags( sb, ssl );
269 Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
270 ber_pvt_sb_clear_io( sb );
271 ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
278 * Call this to do a TLS accept on a sockbuf.
279 * Everything else is the same as with tls_connect.
282 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
287 if ( HAS_TLS( sb ) ) {
288 ssl = (SSL *) sb->sb_iodata;
290 ssl = alloc_handle( sb, ctx_arg );
293 ber_pvt_sb_clear_io( sb );
294 ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
297 err = SSL_accept( ssl );
300 if ( !SSL_want_nothing( ssl ) ) {
301 update_flags( sb, ssl );
304 Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
306 ber_pvt_sb_clear_io( sb );
307 ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
314 ldap_pvt_tls_get_peer( LDAP *ld )
319 ldap_pvt_tls_get_peer_issuer( LDAP *ld )
324 ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
329 case LDAP_OPT_X_TLS_CACERTFILE:
330 case LDAP_OPT_X_TLS_CACERTDIR:
331 case LDAP_OPT_X_TLS_CERTFILE:
332 case LDAP_OPT_X_TLS_KEYFILE:
333 return ldap_pvt_tls_set_option( NULL, option, (void *) arg );
334 case LDAP_OPT_X_TLS_REQUIRE_CERT:
335 i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
336 ( strcasecmp( arg, "yes" ) == 0) ||
337 ( strcasecmp( arg, "true" ) == 0 ) );
338 return ldap_pvt_tls_set_option( NULL, option, (void *) &i );
340 if ( strcasecmp( arg, "never" ) == 0 )
341 return ldap_pvt_tls_set_option( lo, option,
342 LDAP_OPT_X_TLS_NEVER );
343 if ( strcasecmp( arg, "demand" ) == 0 )
344 return ldap_pvt_tls_set_option( lo, option,
345 LDAP_OPT_X_TLS_DEMAND );
346 if ( strcasecmp( arg, "allow" ) == 0 )
347 return ldap_pvt_tls_set_option( lo, option,
348 LDAP_OPT_X_TLS_ALLOW );
349 if ( strcasecmp( arg, "try" ) == 0 )
350 return ldap_pvt_tls_set_option( lo, option,
351 LDAP_OPT_X_TLS_TRY );
352 if ( strcasecmp( arg, "hard" ) == 0 )
353 return ldap_pvt_tls_set_option( lo, option,
354 LDAP_OPT_X_TLS_HARD );
362 ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
366 *(int *)arg = lo->ldo_tls_mode;
368 case LDAP_OPT_X_TLS_CERT:
370 arg = (void *) tls_def_ctx;
372 arg = lo->ldo_tls_ctx;
374 case LDAP_OPT_X_TLS_CACERTFILE:
375 *(char **)arg = tls_opt_cacertfile ?
376 strdup( tls_opt_cacertfile ) : NULL;
378 case LDAP_OPT_X_TLS_CACERTDIR:
379 *(char **)arg = tls_opt_cacertdir ?
380 strdup( tls_opt_cacertdir ) : NULL;
382 case LDAP_OPT_X_TLS_CERTFILE:
383 *(char **)arg = tls_opt_certfile ?
384 strdup( tls_opt_certfile ) : NULL;
386 case LDAP_OPT_X_TLS_KEYFILE:
387 *(char **)arg = tls_opt_keyfile ?
388 strdup( tls_opt_keyfile ) : NULL;
390 case LDAP_OPT_X_TLS_REQUIRE_CERT:
391 *(int *)arg = tls_opt_require_cert;
400 ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
404 switch( *(int *) arg ) {
405 case LDAP_OPT_X_TLS_NEVER:
406 case LDAP_OPT_X_TLS_DEMAND:
407 case LDAP_OPT_X_TLS_ALLOW:
408 case LDAP_OPT_X_TLS_TRY:
409 case LDAP_OPT_X_TLS_HARD:
410 lo->ldo_tls_mode = *(int *)arg;
416 case LDAP_OPT_X_TLS_CERT:
418 tls_def_ctx = (SSL_CTX *) arg;
420 lo->ldo_tls_ctx = arg;
426 case LDAP_OPT_X_TLS_CACERTFILE:
427 if ( tls_opt_cacertfile ) free( tls_opt_cacertfile );
428 tls_opt_cacertfile = arg ? strdup( (char *) arg ) : NULL;
430 case LDAP_OPT_X_TLS_CACERTDIR:
431 if ( tls_opt_cacertdir ) free( tls_opt_cacertdir );
432 tls_opt_cacertdir = arg ? strdup( (char *) arg ) : NULL;
434 case LDAP_OPT_X_TLS_CERTFILE:
435 if ( tls_opt_certfile ) free( tls_opt_certfile );
436 tls_opt_certfile = arg ? strdup( (char *) arg ) : NULL;
438 case LDAP_OPT_X_TLS_KEYFILE:
439 if ( tls_opt_keyfile ) free( tls_opt_keyfile );
440 tls_opt_keyfile = arg ? strdup( (char *) arg ) : NULL;
442 case LDAP_OPT_X_TLS_REQUIRE_CERT:
443 tls_opt_require_cert = * (int *) arg;
445 case LDAP_OPT_X_TLS_CIPHER_SUITE:
446 if ( tls_opt_ciphersuite ) free( tls_opt_ciphersuite );
447 tls_opt_ciphersuite = arg ? strdup( (char *) arg ) : NULL;
456 tls_setup( Sockbuf *sb, void *arg )
463 tls_remove( Sockbuf *sb )
465 SSL_free( (SSL *) sb->sb_iodata );
470 tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
472 int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
474 update_flags(sb, (SSL *)sb->sb_iodata );
479 tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
481 int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
483 update_flags(sb, (SSL *)sb->sb_iodata );
488 tls_close( Sockbuf *sb )
490 tcp_close( ber_pvt_sb_get_desc( sb ) );
495 tls_verify_cb( int ok, X509_STORE_CTX *ctx )
500 /* Inspired by ERR_print_errors in OpenSSL */
502 tls_report_error( void )
509 while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
510 Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
511 ERR_error_string( l, buf ), file, line );