]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls.c
ITS#537: lber io rewrite from Gambor Gombas.
[openldap] / libraries / libldap / tls.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  *
6  * tls.c - Handle tls/ssl using SSLeay or OpenSSL.
7  */
8
9 #include "portable.h"
10
11 #ifdef HAVE_TLS
12
13 #include <stdio.h>
14
15 #include <ac/stdlib.h>
16 #include <ac/errno.h>
17 #include <ac/socket.h>
18 #include <ac/string.h>
19 #include <ac/time.h>
20 #include <ac/unistd.h>
21
22 #include "ldap-int.h"
23
24 #ifdef LDAP_R_COMPILE
25 #include <ldap_pvt_thread.h>
26 #endif
27
28 #ifdef HAVE_OPENSSL_SSL_H
29 #include <openssl/ssl.h>
30 #include <openssl/x509v3.h>
31 #include <openssl/err.h>
32 #elif defined( HAVE_SSL_H )
33 #include <ssl.h>
34 #endif
35
36 static int  tls_opt_trace = 1;
37 static char *tls_opt_certfile = NULL;
38 static char *tls_opt_keyfile = NULL;
39 static char *tls_opt_cacertfile = NULL;
40 static char *tls_opt_cacertdir = NULL;
41 static int  tls_opt_require_cert = 0;
42 static char *tls_opt_ciphersuite = NULL;
43
44 #define HAS_TLS( sb )   ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
45                                 (void *)&ldap_pvt_sockbuf_io_tls )
46
47 static void tls_report_error( void );
48
49 static void tls_info_cb( SSL *ssl, int where, int ret );
50 static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
51 static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
52 static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
53
54 #if 0   /* Currently this is not used by anyone */
55 static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
56 #endif
57
58 static SSL_CTX *tls_def_ctx = NULL;
59
60 #ifdef LDAP_R_COMPILE
61 /*
62  * provide mutexes for the SSLeay library.
63  */
64 static ldap_pvt_thread_mutex_t  tls_mutexes[CRYPTO_NUM_LOCKS];
65
66 static void tls_locking_cb( int mode, int type, const char *file, int line )
67 {
68         if ( mode & CRYPTO_LOCK ) {
69                 ldap_pvt_thread_mutex_lock( tls_mutexes+type );
70         } else {
71                 ldap_pvt_thread_mutex_unlock( tls_mutexes+type );
72         }
73 }
74
75 /*
76  * an extra mutex for the default ctx.
77  */
78
79 static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
80
81 static void tls_init_threads( void )
82 {
83         int i;
84
85         for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
86                 ldap_pvt_thread_mutex_init( tls_mutexes+i );
87         }
88         CRYPTO_set_locking_callback( tls_locking_cb );
89         /* FIXME: the thread id should be added somehow... */
90
91         ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
92 }
93 #endif /* LDAP_R_COMPILE */
94
95 /*
96  * Initialize tls system. Should be called only once.
97  */
98 int
99 ldap_pvt_tls_init( void )
100 {
101         static int tls_initialized = 0;
102
103         if ( tls_initialized )
104                 return 0;
105         tls_initialized = 1;
106 #ifdef LDAP_R_COMPILE
107         tls_init_threads();
108 #endif
109         SSL_load_error_strings();
110         SSLeay_add_ssl_algorithms();
111         /* FIXME: mod_ssl does this */
112         X509V3_add_standard_extensions();
113         return 0;
114 }
115
116 /*
117  * initialize the default context
118  */
119 int
120 ldap_pvt_tls_init_def_ctx( void )
121 {
122         STACK_OF(X509_NAME) *calist;
123
124 #ifdef LDAP_R_COMPILE
125         ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
126 #endif
127         if ( tls_def_ctx == NULL ) {
128                 tls_def_ctx = SSL_CTX_new( SSLv23_method() );
129                 if ( tls_def_ctx == NULL ) {
130                         Debug( LDAP_DEBUG_ANY,
131                                "TLS: could not allocate default ctx.\n",0,0,0);
132                         goto error_exit;
133                 }
134                 if ( tls_opt_ciphersuite &&
135                      !SSL_CTX_set_cipher_list( tls_def_ctx,
136                         tls_opt_ciphersuite ) ) {
137                         Debug( LDAP_DEBUG_ANY,
138                                "TLS: could not set cipher list %s.\n",
139                                tls_opt_ciphersuite, 0, 0 );
140                         tls_report_error();
141                         goto error_exit;
142                 }
143                 if (tls_opt_cacertfile != NULL || tls_opt_cacertdir != NULL) {
144                         if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
145                                                              tls_opt_cacertfile,
146                                                              tls_opt_cacertdir )
147                              || !SSL_CTX_set_default_verify_paths( tls_def_ctx ) )
148                         {
149                                 Debug( LDAP_DEBUG_ANY,
150                         "TLS: could not load verify locations (file:`%s',dir:`%s').\n",
151                                        tls_opt_cacertfile,tls_opt_cacertdir,0);
152                                 tls_report_error();
153                                 goto error_exit;
154                         }
155                         calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir );
156                         if ( !calist ) {
157                                 Debug( LDAP_DEBUG_ANY,
158                         "TLS: could not load client CA list (file:`%s',dir:`%s').\n",
159                                        tls_opt_cacertfile,tls_opt_cacertdir,0);
160                                 tls_report_error();
161                                 goto error_exit;
162                         }
163                         SSL_CTX_set_client_CA_list( tls_def_ctx, calist );
164                 }
165                 if ( tls_opt_keyfile &&
166                      !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
167                                                    tls_opt_keyfile,
168                                                    SSL_FILETYPE_PEM ) ) {
169                         Debug( LDAP_DEBUG_ANY,
170                                "TLS: could not use key file `%s'.\n",
171                                tls_opt_keyfile,0,0);
172                         tls_report_error();
173                         goto error_exit;
174                 }
175                 if ( tls_opt_certfile &&
176                      !SSL_CTX_use_certificate_file( tls_def_ctx,
177                                                     tls_opt_certfile,
178                                                     SSL_FILETYPE_PEM ) ) {
179                         Debug( LDAP_DEBUG_ANY,
180                                "TLS: could not use certificate `%s'.\n",
181                                tls_opt_certfile,0,0);
182                         tls_report_error();
183                         goto error_exit;
184                 }
185                 if ( ( tls_opt_certfile || tls_opt_keyfile ) &&
186                      !SSL_CTX_check_private_key( tls_def_ctx ) ) {
187                         Debug( LDAP_DEBUG_ANY,
188                                "TLS: private key mismatch.\n",
189                                0,0,0);
190                         tls_report_error();
191                         goto error_exit;
192                 }
193                 if ( tls_opt_trace ) {
194                         SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb );
195                 }
196                 SSL_CTX_set_verify( tls_def_ctx, (tls_opt_require_cert) ?
197                         (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) :
198                         SSL_VERIFY_PEER, tls_verify_cb );
199                 SSL_CTX_set_tmp_rsa_callback( tls_def_ctx, tls_tmp_rsa_cb );
200                 /* SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); */
201         }
202 #ifdef LDAP_R_COMPILE
203         ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
204 #endif
205         return 0;
206 error_exit:
207         if ( tls_def_ctx != NULL ) {
208                 SSL_CTX_free( tls_def_ctx );
209                 tls_def_ctx = NULL;
210         }
211 #ifdef LDAP_R_COMPILE
212         ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
213 #endif
214         return -1;
215 }
216
217 static STACK_OF(X509_NAME) *
218 get_ca_list( char * bundle, char * dir )
219 {
220         STACK_OF(X509_NAME) *ca_list = NULL;
221
222         if ( bundle ) {
223                 ca_list = SSL_load_client_CA_file( bundle );
224         }
225         /*
226          * FIXME: We have now to go over all files in dir, load them
227          * and add every certificate there to ca_list.
228          */
229         return ca_list;
230 }
231
232 static SSL *
233 alloc_handle( void *ctx_arg )
234 {
235         SSL_CTX *ctx;
236         SSL     *ssl;
237
238         if ( ctx_arg ) {
239                 ctx = (SSL_CTX *) ctx_arg;
240         } else {
241                 if ( ldap_pvt_tls_init_def_ctx() < 0 )
242                         return NULL;
243                 ctx = tls_def_ctx;
244         }
245
246         ssl = SSL_new( ctx );
247         if ( ssl == NULL ) {
248                 Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
249                 return NULL;
250         }
251
252         if ( tls_opt_trace ) {
253                 SSL_set_info_callback( ssl, tls_info_cb );
254         }
255         return ssl;
256 }
257
258 static int
259 update_flags( Sockbuf *sb, SSL * ssl, int rc )
260 {
261         int err = SSL_get_error(ssl, rc);
262
263         sb->sb_trans_needs_read  = 0;
264         sb->sb_trans_needs_write = 0;
265         if (err == SSL_ERROR_WANT_READ)
266         {
267             sb->sb_trans_needs_read  = 1;
268             return 1;
269         } else if (err == SSL_ERROR_WANT_WRITE)
270         {
271             sb->sb_trans_needs_write = 1;
272             return 1;
273         } else if (err == SSL_ERROR_WANT_CONNECT)
274         {
275             return 1;
276         }
277         return 0;
278 }
279
280 /*
281  * TLS support for LBER Sockbufs
282  */
283
284 struct tls_data {
285         SSL                     *ssl;
286         Sockbuf_IO_Desc         *sbiod;
287 };
288
289 extern BIO_METHOD ldap_pvt_sb_bio_method;
290
291 static int
292 sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
293 {
294         struct tls_data         *p;
295         BIO                     *bio;
296
297         assert( sbiod != NULL );
298
299         p = LBER_MALLOC( sizeof( *p ) );
300         if ( p == NULL )
301                 return -1;
302         
303         p->ssl = (SSL *)arg;
304         p->sbiod = sbiod;
305         bio = BIO_new( &ldap_pvt_sb_bio_method );
306         bio->ptr = (void *)p;
307         SSL_set_bio( p->ssl, bio, bio );
308         sbiod->sbiod_pvt = p;
309         return 0;
310 }
311
312 static int
313 sb_tls_remove( Sockbuf_IO_Desc *sbiod )
314 {
315         struct tls_data         *p;
316         
317         assert( sbiod != NULL );
318         assert( sbiod->sbiod_pvt != NULL );
319
320         p = (struct tls_data *)sbiod->sbiod_pvt;
321         SSL_free( p->ssl );
322         LBER_FREE( sbiod->sbiod_pvt );
323         sbiod->sbiod_pvt = NULL;
324         return 0;
325 }
326
327 static int
328 sb_tls_close( Sockbuf_IO_Desc *sbiod )
329 {
330         struct tls_data         *p;
331         
332         assert( sbiod != NULL );
333         assert( sbiod->sbiod_pvt != NULL );
334
335         p = (struct tls_data *)sbiod->sbiod_pvt;
336         SSL_shutdown( p->ssl );
337         return 0;
338 }
339
340 static int
341 sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
342 {
343         struct tls_data         *p;
344         
345         assert( sbiod != NULL );
346         assert( sbiod->sbiod_pvt != NULL );
347
348         p = (struct tls_data *)sbiod->sbiod_pvt;
349         
350         if ( opt == LBER_SB_OPT_GET_SSL ) {
351                 *((SSL **)arg) = p->ssl;
352                 return 1;
353         }
354         
355         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
356 }
357
358 static ber_slen_t
359 sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
360 {
361         struct tls_data         *p;
362         ber_slen_t              ret;
363         int                     err;
364
365         assert( sbiod != NULL );
366         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
367
368         p = (struct tls_data *)sbiod->sbiod_pvt;
369
370         ret = SSL_read( p->ssl, (char *)buf, len );
371 #ifdef HAVE_WINSOCK
372         errno = WSAGetLastError();
373 #endif
374         err = SSL_get_error( p->ssl, ret );
375         if (err == SSL_ERROR_WANT_READ ) {
376                 sbiod->sbiod_sb->sb_trans_needs_read = 1;
377 #ifdef WIN32
378                 errno = EWOULDBLOCK;
379 #endif
380         }
381         else
382                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
383         return ret;
384 }
385
386 static ber_slen_t
387 sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
388 {
389         struct tls_data         *p;
390         ber_slen_t              ret;
391         int                     err;
392
393         assert( sbiod != NULL );
394         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
395
396         p = (struct tls_data *)sbiod->sbiod_pvt;
397
398         ret = SSL_write( p->ssl, (char *)buf, len );
399 #ifdef HAVE_WINSOCK
400         errno = WSAGetLastError();
401 #endif
402         err = SSL_get_error( p->ssl, ret );
403         if (err == SSL_ERROR_WANT_WRITE ) {
404                 sbiod->sbiod_sb->sb_trans_needs_write = 1;
405 #ifdef WIN32
406                 errno = EWOULDBLOCK;
407 #endif
408         }
409         else
410                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
411         return ret;
412 }
413
414 Sockbuf_IO ldap_pvt_sockbuf_io_tls =
415 {
416         sb_tls_setup,           /* sbi_setup */
417         sb_tls_remove,          /* sbi_remove */
418         sb_tls_ctrl,            /* sbi_ctrl */
419         sb_tls_read,            /* sbi_read */
420         sb_tls_write,           /* sbi_write */
421         sb_tls_close            /* sbi_close */
422 };
423
424 static int
425 sb_tls_bio_create( BIO *b ) {
426         b->init = 1;
427         b->num = 0;
428         b->ptr = NULL;
429         b->flags = 0;
430         return 1;
431 }
432
433 static int
434 sb_tls_bio_destroy( BIO *b )
435 {
436         if ( b == NULL )
437                 return 0;
438
439         b->ptr = NULL;          /* sb_tls_remove() will free it */
440         b->init = 0;
441         b->flags = 0;
442         return 1;
443 }
444
445 static int
446 sb_tls_bio_read( BIO *b, char *buf, int len )
447 {
448         struct tls_data         *p;
449         int                     ret;
450                 
451         if ( buf == NULL || len <= 0 )
452                 return 0;
453
454         p = (struct tls_data *)b->ptr;
455
456         if ( p == NULL || p->sbiod == NULL )
457                 return 0;
458
459         ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
460
461         BIO_clear_retry_flags( b );
462         if ( ret < 0 && errno == EWOULDBLOCK )
463                 BIO_set_retry_read( b );
464
465         return ret;
466 }
467
468 static int
469 sb_tls_bio_write( BIO *b, char *buf, int len )
470 {
471         struct tls_data         *p;
472         int                     ret;
473         
474         if ( buf == NULL || len <= 0 )
475                 return 0;
476         
477         p = (struct tls_data *)b->ptr;
478
479         if ( p == NULL || p->sbiod == NULL )
480                 return 0;
481
482         ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, buf, len );
483
484         BIO_clear_retry_flags( b );
485         if ( ret < 0 && errno == EWOULDBLOCK )
486                 BIO_set_retry_write( b );
487
488         return ret;
489 }
490
491 static long
492 sb_tls_bio_ctrl( BIO *b, int cmd, long num, char *ptr )
493 {
494         if ( cmd == BIO_CTRL_FLUSH ) {
495                 /* The OpenSSL library needs this */
496                 return 1;
497         }
498         return 0;
499 }
500
501 static int
502 sb_tls_bio_gets( BIO *b, char *buf, int len )
503 {
504         return -1;
505 }
506
507 static int
508 sb_tls_bio_puts( BIO *b, char *str )
509 {
510         return sb_tls_bio_write( b, str, strlen( str ) );
511 }
512         
513 BIO_METHOD ldap_pvt_sb_bio_method =
514 {
515         ( 100 | 0x400 ),                /* it's a source/sink BIO */
516         "sockbuf glue",
517         sb_tls_bio_write,
518         sb_tls_bio_read,
519         sb_tls_bio_puts,
520         sb_tls_bio_gets,
521         sb_tls_bio_ctrl,
522         sb_tls_bio_create,
523         sb_tls_bio_destroy
524 };
525
526 /*
527  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
528  * a SSL_CTX * or NULL, in which case the default ctx is used.
529  *
530  * Return value:
531  *
532  *  0 - Success. Connection is ready for communication.
533  * <0 - Error. Can't create a TLS stream.
534  * >0 - Partial success.
535  *        Do a select (using information from lber_pvt_sb_needs_{read,write}
536  *              and call again.
537  */
538
539 int
540 ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg )
541 {
542         int     err;
543         SSL     *ssl;
544
545         if ( HAS_TLS( sb ) ) {
546                 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
547         } else {
548                 ssl = alloc_handle( ctx_arg );
549                 if ( ssl == NULL )
550                         return -1;
551 #ifdef LDAP_DEBUG
552                 ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
553                         LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
554 #endif
555                 ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
556                         LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
557         }
558
559         err = SSL_connect( ssl );
560
561 #ifdef HAVE_WINSOCK
562         errno = WSAGetLastError();
563 #endif
564         if ( err <= 0 ) {
565                 if ( update_flags( sb, ssl, err ))
566                         return 1;
567                 if ((err = ERR_peek_error())) {
568                         char buf[256];
569                         ld->ld_error = ldap_strdup(ERR_error_string(err, buf));
570                 }
571                 Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
572                 ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
573                         LBER_SBIOD_LEVEL_TRANSPORT );
574 #ifdef LDAP_DEBUG
575                 ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
576                         LBER_SBIOD_LEVEL_TRANSPORT );
577 #endif
578                 return -1;
579         }
580         return 0;
581 }
582
583 /*
584  * Call this to do a TLS accept on a sockbuf.
585  * Everything else is the same as with tls_connect.
586  */
587 int
588 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
589 {
590         int     err;
591         SSL     *ssl;
592
593         if ( HAS_TLS( sb ) ) {
594                 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
595         } else {
596                 ssl = alloc_handle( ctx_arg );
597                 if ( ssl == NULL )
598                         return -1;
599 #ifdef LDAP_DEBUG
600                 ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
601                         LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
602 #endif
603                 ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
604                         LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
605         }
606
607         err = SSL_accept( ssl );
608
609 #ifdef HAVE_WINSOCK
610         errno = WSAGetLastError();
611 #endif
612         if ( err <= 0 ) {
613                 if ( update_flags( sb, ssl, err ))
614                         return 1;
615                 Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
616                 tls_report_error();
617                 ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
618                         LBER_SBIOD_LEVEL_TRANSPORT );
619 #ifdef LDAP_DEBUG
620                 ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
621                         LBER_SBIOD_LEVEL_TRANSPORT );
622 #endif
623                 return -1;
624         }
625         return 0;
626 }
627
628 int
629 ldap_pvt_tls_inplace ( Sockbuf *sb )
630 {
631         if ( HAS_TLS( sb ) )
632                 return(1);
633         return(0);
634 }
635
636 void *
637 ldap_pvt_tls_sb_handle( Sockbuf *sb )
638 {
639         void                    *p;
640         
641         if (HAS_TLS( sb )) {
642                 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p );
643                 return p;
644         }
645                 return NULL;
646 }
647
648 void *
649 ldap_pvt_tls_get_handle( LDAP *ld )
650 {
651         return ldap_pvt_tls_sb_handle( ld->ld_sb );
652 }
653
654 const char *
655 ldap_pvt_tls_get_peer( LDAP *ld )
656 {
657     return NULL;
658 }
659
660 const char *
661 ldap_pvt_tls_get_peer_issuer( LDAP *ld )
662 {
663     return NULL;
664 }
665
666 int
667 ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
668 {
669         int i;
670
671         switch( option ) {
672         case LDAP_OPT_X_TLS_CACERTFILE:
673         case LDAP_OPT_X_TLS_CACERTDIR:
674         case LDAP_OPT_X_TLS_CERTFILE:
675         case LDAP_OPT_X_TLS_KEYFILE:
676                 return ldap_pvt_tls_set_option( NULL, option, (void *) arg );
677         case LDAP_OPT_X_TLS_REQUIRE_CERT:
678                 i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
679                       ( strcasecmp( arg, "yes" ) == 0) ||
680                       ( strcasecmp( arg, "true" ) == 0 ) );
681                 return ldap_pvt_tls_set_option( NULL, option, (void *) &i );
682         case LDAP_OPT_X_TLS:
683                 i = -1;
684                 if ( strcasecmp( arg, "never" ) == 0 )
685                         i = LDAP_OPT_X_TLS_NEVER ;
686                 if ( strcasecmp( arg, "demand" ) == 0 )
687                         i = LDAP_OPT_X_TLS_DEMAND ;
688                 if ( strcasecmp( arg, "allow" ) == 0 )
689                         i = LDAP_OPT_X_TLS_ALLOW ;
690                 if ( strcasecmp( arg, "try" ) == 0 )
691                         i = LDAP_OPT_X_TLS_TRY ;
692                 if ( strcasecmp( arg, "hard" ) == 0 )
693                         i = LDAP_OPT_X_TLS_HARD ;
694                 if (i >= 0)
695                         return ldap_pvt_tls_set_option( lo, option, &i );
696                 return -1;
697         default:
698                 return -1;
699         }
700 }
701
702 int
703 ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
704 {
705         switch( option ) {
706         case LDAP_OPT_X_TLS:
707                 *(int *)arg = lo->ldo_tls_mode;
708                 break;
709         case LDAP_OPT_X_TLS_CERT:
710                 if ( lo == NULL )
711                         *(void **)arg = (void *) tls_def_ctx;
712                 else
713                         *(void **)arg = lo->ldo_tls_ctx;
714                 break;
715         case LDAP_OPT_X_TLS_CACERTFILE:
716                 *(char **)arg = tls_opt_cacertfile ?
717                         LDAP_STRDUP( tls_opt_cacertfile ) : NULL;
718                 break;
719         case LDAP_OPT_X_TLS_CACERTDIR:
720                 *(char **)arg = tls_opt_cacertdir ?
721                         LDAP_STRDUP( tls_opt_cacertdir ) : NULL;
722                 break;
723         case LDAP_OPT_X_TLS_CERTFILE:
724                 *(char **)arg = tls_opt_certfile ?
725                         LDAP_STRDUP( tls_opt_certfile ) : NULL;
726                 break;
727         case LDAP_OPT_X_TLS_KEYFILE:
728                 *(char **)arg = tls_opt_keyfile ?
729                         LDAP_STRDUP( tls_opt_keyfile ) : NULL;
730                 break;
731         case LDAP_OPT_X_TLS_REQUIRE_CERT:
732                 *(int *)arg = tls_opt_require_cert;
733                 break;
734         default:
735                 return -1;
736         }
737         return 0;
738 }
739
740 int
741 ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
742 {
743         switch( option ) {
744         case LDAP_OPT_X_TLS:
745                 switch( *(int *) arg ) {
746                 case LDAP_OPT_X_TLS_NEVER:
747                 case LDAP_OPT_X_TLS_DEMAND:
748                 case LDAP_OPT_X_TLS_ALLOW:
749                 case LDAP_OPT_X_TLS_TRY:
750                 case LDAP_OPT_X_TLS_HARD:
751                         if (lo != NULL) {
752                                 lo->ldo_tls_mode = *(int *)arg;
753                         }
754
755                         return 0;
756                 }
757                 return -1;
758
759         case LDAP_OPT_X_TLS_CERT:
760                 if ( lo == NULL ) {
761                         tls_def_ctx = (SSL_CTX *) arg;
762
763                 } else {
764                         lo->ldo_tls_ctx = arg;
765                 }
766                 return 0;
767         }
768
769         if ( lo != NULL ) {
770                 return -1;
771         }
772
773         switch( option ) {
774         case LDAP_OPT_X_TLS_CACERTFILE:
775                 if ( tls_opt_cacertfile ) free( tls_opt_cacertfile );
776                 tls_opt_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
777                 break;
778         case LDAP_OPT_X_TLS_CACERTDIR:
779                 if ( tls_opt_cacertdir ) free( tls_opt_cacertdir );
780                 tls_opt_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
781                 break;
782         case LDAP_OPT_X_TLS_CERTFILE:
783                 if ( tls_opt_certfile ) free( tls_opt_certfile );
784                 tls_opt_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
785                 break;
786         case LDAP_OPT_X_TLS_KEYFILE:
787                 if ( tls_opt_keyfile ) free( tls_opt_keyfile );
788                 tls_opt_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
789                 break;
790         case LDAP_OPT_X_TLS_REQUIRE_CERT:
791                 tls_opt_require_cert = * (int *) arg;
792                 break;
793         case LDAP_OPT_X_TLS_CIPHER_SUITE:
794                 if ( tls_opt_ciphersuite ) free( tls_opt_ciphersuite );
795                 tls_opt_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
796                 break;
797         default:
798                 return -1;
799         }
800         return 0;
801 }
802
803 int
804 ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg )
805 {
806         /*
807          * Fortunately, the lib uses blocking io...
808          */
809         if ( ldap_pvt_tls_connect( ld, sb, ctx_arg ) < 0 ) {
810                 return LDAP_CONNECT_ERROR;
811         }
812
813         /* FIXME: hostname of server must be compared with name in
814          * certificate....
815          */
816
817         return LDAP_SUCCESS;
818 }
819
820 /* Derived from openssl/apps/s_cb.c */
821 static void
822 tls_info_cb( SSL *ssl, int where, int ret )
823 {
824         int w;
825         char *op;
826
827         w = where & ~SSL_ST_MASK;
828         if ( w & SSL_ST_CONNECT ) {
829                 op = "SSL_connect";
830         } else if ( w & SSL_ST_ACCEPT ) {
831                 op = "SSL_accept";
832         } else {
833                 op = "undefined";
834         }
835
836         if ( where & SSL_CB_LOOP ) {
837                 Debug( LDAP_DEBUG_TRACE,
838                        "TLS trace: %s:%s\n",
839                        op, SSL_state_string_long( ssl ), 0 );
840         } else if ( where & SSL_CB_ALERT ) {
841                 op = ( where & SSL_CB_READ ) ? "read" : "write";
842                 Debug( LDAP_DEBUG_TRACE,
843                        "TLS trace: SSL3 alert %s:%s:%s\n",
844                        op,
845                        SSL_alert_type_string_long( ret ),
846                        SSL_alert_desc_string_long( ret) );
847         } else if ( where & SSL_CB_EXIT ) {
848                 if ( ret == 0 ) {
849                         Debug( LDAP_DEBUG_TRACE,
850                                "TLS trace: %s:failed in %s\n",
851                                op, SSL_state_string_long( ssl ), 0 );
852                 } else if ( ret < 0 ) {
853                         Debug( LDAP_DEBUG_TRACE,
854                                "TLS trace: %s:error in %s\n",
855                                op, SSL_state_string_long( ssl ), 0 );
856                 }
857         }
858 }
859
860 static int
861 tls_verify_cb( int ok, X509_STORE_CTX *ctx )
862 {
863         X509 *cert;
864         int errnum;
865         int errdepth;
866         X509_NAME *subject;
867         X509_NAME *issuer;
868         char *sname;
869         char *iname;
870
871         cert = X509_STORE_CTX_get_current_cert( ctx );
872         errnum = X509_STORE_CTX_get_error( ctx );
873         errdepth = X509_STORE_CTX_get_error_depth( ctx );
874
875         /*
876          * X509_get_*_name return pointers to the internal copies of
877          * those things requested.  So do not free them.
878          */
879         subject = X509_get_subject_name( cert );
880         issuer = X509_get_issuer_name( cert );
881         /* X509_NAME_oneline, if passed a NULL buf, allocate memomry */
882         sname = X509_NAME_oneline( subject, NULL, 0 );
883         iname = X509_NAME_oneline( issuer, NULL, 0 );
884         Debug( LDAP_DEBUG_TRACE,
885                "TLS certificate verification: depth: %d, subject: %s, issuer: %s\n",
886                errdepth,
887                sname ? sname : "-unknown-",
888                iname ? iname : "-unknown-" );
889         if ( sname )
890                 CRYPTO_free ( sname );
891         if ( iname )
892                 CRYPTO_free ( iname );
893
894         return ok;
895 }
896
897 /* Inspired by ERR_print_errors in OpenSSL */
898 static void
899 tls_report_error( void )
900 {
901         unsigned long l;
902         char buf[200];
903         const char *file;
904         int line;
905
906         while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
907                         Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
908                                ERR_error_string( l, buf ), file, line );
909         }
910 }
911
912 static RSA *
913 tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
914 {
915         RSA *tmp_rsa;
916
917         /* FIXME:  Pregenerate the key on startup */
918         /* FIXME:  Who frees the key? */
919         tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL );
920
921         if ( !tmp_rsa ) {
922                 Debug( LDAP_DEBUG_ANY, "TLS: Failed to generate temporary %d-bit %s RSA key\n",
923                        key_length, is_export ? "export" : "domestic", 0 );
924                 return NULL;
925         }
926         return tmp_rsa;
927 }
928
929 #if 0
930 static DH *
931 tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
932 {
933         return NULL;
934 }
935 #endif
936
937 #else
938 static int dummy;
939 #endif