]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls.c
Parsing and printing of extensions in schema definitions.
[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 ) ((sb)->sb_io==&tls_io)
45
46 static int tls_setup( Sockbuf *sb, void *arg );
47 static int tls_remove( Sockbuf *sb );
48 static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
49 static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
50 static int tls_close( Sockbuf *sb );
51 static void tls_report_error( void );
52
53 static Sockbuf_IO tls_io=
54 {
55    tls_setup,
56    tls_remove,
57    tls_read,
58    tls_write,
59    tls_close
60 };
61
62 static void tls_info_cb( SSL *ssl, int where, int ret );
63 static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
64 static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
65 static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
66
67 #if 0   /* Currently this is not used by anyone */
68 static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
69 #endif
70
71 static SSL_CTX *tls_def_ctx = NULL;
72
73 #ifdef LDAP_R_COMPILE
74 /*
75  * provide mutexes for the SSLeay library.
76  */
77 static ldap_pvt_thread_mutex_t  tls_mutexes[CRYPTO_NUM_LOCKS];
78
79 static void tls_locking_cb( int mode, int type, const char *file, int line )
80 {
81         if ( mode & CRYPTO_LOCK ) {
82                 ldap_pvt_thread_mutex_lock( tls_mutexes+type );
83         } else {
84                 ldap_pvt_thread_mutex_unlock( tls_mutexes+type );
85         }
86 }
87
88 /*
89  * an extra mutex for the default ctx.
90  */
91
92 static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
93
94 static void tls_init_threads( void )
95 {
96         int i;
97
98         for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
99                 ldap_pvt_thread_mutex_init( tls_mutexes+i );
100         }
101         CRYPTO_set_locking_callback( tls_locking_cb );
102         /* FIXME: the thread id should be added somehow... */
103
104         ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
105 }
106 #endif /* LDAP_R_COMPILE */
107
108 /*
109  * Initialize tls system. Should be called only once.
110  */
111 int
112 ldap_pvt_tls_init( void )
113 {
114         static int tls_initialized = 0;
115
116         if ( tls_initialized )
117                 return 0;
118         tls_initialized = 1;
119 #ifdef LDAP_R_COMPILE
120         tls_init_threads();
121 #endif
122         SSL_load_error_strings();
123         SSLeay_add_ssl_algorithms();
124         /* FIXME: mod_ssl does this */
125         X509V3_add_standard_extensions();
126         return 0;
127 }
128
129 /*
130  * initialize the default context
131  */
132 int
133 ldap_pvt_tls_init_def_ctx( void )
134 {
135         STACK_OF(X509_NAME) *calist;
136
137 #ifdef LDAP_R_COMPILE
138         ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
139 #endif
140         if ( tls_def_ctx == NULL ) {
141                 tls_def_ctx = SSL_CTX_new( SSLv23_method() );
142                 if ( tls_def_ctx == NULL ) {
143                         Debug( LDAP_DEBUG_ANY,
144                                "TLS: could not allocate default ctx.\n",0,0,0);
145                         goto error_exit;
146                 }
147                 if ( tls_opt_ciphersuite &&
148                      !SSL_CTX_set_cipher_list( tls_def_ctx,
149                         tls_opt_ciphersuite ) ) {
150                         Debug( LDAP_DEBUG_ANY,
151                                "TLS: could not set cipher list %s.\n",
152                                tls_opt_ciphersuite, 0, 0 );
153                         tls_report_error();
154                         goto error_exit;
155                 }
156                 if (tls_opt_cacertfile != NULL || tls_opt_cacertdir != NULL) {
157                         if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
158                                                              tls_opt_cacertfile,
159                                                              tls_opt_cacertdir )
160                              || !SSL_CTX_set_default_verify_paths( tls_def_ctx ) )
161                         {
162                                 Debug( LDAP_DEBUG_ANY,
163                         "TLS: could not load verify locations (file:`%s',dir:`%s').\n",
164                                        tls_opt_cacertfile,tls_opt_cacertdir,0);
165                                 tls_report_error();
166                                 goto error_exit;
167                         }
168                         calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir );
169                         if ( !calist ) {
170                                 Debug( LDAP_DEBUG_ANY,
171                         "TLS: could not load client CA list (file:`%s',dir:`%s').\n",
172                                        tls_opt_cacertfile,tls_opt_cacertdir,0);
173                                 tls_report_error();
174                                 goto error_exit;
175                         }
176                         SSL_CTX_set_client_CA_list( tls_def_ctx, calist );
177                 }
178                 if ( tls_opt_keyfile &&
179                      !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
180                                                    tls_opt_keyfile,
181                                                    SSL_FILETYPE_PEM ) ) {
182                         Debug( LDAP_DEBUG_ANY,
183                                "TLS: could not use key file `%s'.\n",
184                                tls_opt_keyfile,0,0);
185                         tls_report_error();
186                         goto error_exit;
187                 }
188                 if ( tls_opt_certfile &&
189                      !SSL_CTX_use_certificate_file( tls_def_ctx,
190                                                     tls_opt_certfile,
191                                                     SSL_FILETYPE_PEM ) ) {
192                         Debug( LDAP_DEBUG_ANY,
193                                "TLS: could not use certificate `%s'.\n",
194                                tls_opt_certfile,0,0);
195                         tls_report_error();
196                         goto error_exit;
197                 }
198                 if ( ( tls_opt_certfile || tls_opt_keyfile ) &&
199                      !SSL_CTX_check_private_key( tls_def_ctx ) ) {
200                         Debug( LDAP_DEBUG_ANY,
201                                "TLS: private key mismatch.\n",
202                                0,0,0);
203                         tls_report_error();
204                         goto error_exit;
205                 }
206                 if ( tls_opt_trace ) {
207                         SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb );
208                 }
209                 SSL_CTX_set_verify( tls_def_ctx, (tls_opt_require_cert) ?
210                         (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) :
211                         SSL_VERIFY_PEER, tls_verify_cb );
212                 SSL_CTX_set_tmp_rsa_callback( tls_def_ctx, tls_tmp_rsa_cb );
213                 /* SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); */
214         }
215 #ifdef LDAP_R_COMPILE
216         ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
217 #endif
218         return 0;
219 error_exit:
220         if ( tls_def_ctx != NULL ) {
221                 SSL_CTX_free( tls_def_ctx );
222                 tls_def_ctx = NULL;
223         }
224 #ifdef LDAP_R_COMPILE
225         ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
226 #endif
227         return -1;
228 }
229
230 static STACK_OF(X509_NAME) *
231 get_ca_list( char * bundle, char * dir )
232 {
233         STACK_OF(X509_NAME) *ca_list = NULL;
234
235         if ( bundle ) {
236                 ca_list = SSL_load_client_CA_file( bundle );
237         }
238         /*
239          * FIXME: We have now to go over all files in dir, load them
240          * and add every certificate there to ca_list.
241          */
242         return ca_list;
243 }
244
245 static SSL *
246 alloc_handle( Sockbuf *sb, void *ctx_arg )
247 {
248         int     err;
249         SSL_CTX *ctx;
250         SSL     *ssl;
251
252         if ( ctx_arg ) {
253                 ctx = (SSL_CTX *) ctx_arg;
254         } else {
255                 if ( ldap_pvt_tls_init_def_ctx() < 0 )
256                         return NULL;
257                 ctx = tls_def_ctx;
258         }
259
260         ssl = SSL_new( ctx );
261         if ( ssl == NULL ) {
262                 Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
263                 return NULL;
264         }
265
266         if ( tls_opt_trace ) {
267                 SSL_set_info_callback( ssl, tls_info_cb );
268         }
269         sb->sb_iodata = ssl;
270         SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) );
271         return ssl;
272 }
273
274 static int
275 update_flags( Sockbuf *sb, SSL * ssl, int rc )
276 {
277         int err = SSL_get_error(ssl, rc);
278
279         sb->sb_trans_needs_read  = 0;
280         sb->sb_trans_needs_write = 0;
281         if (err == SSL_ERROR_WANT_READ)
282         {
283             sb->sb_trans_needs_read  = 1;
284             return 1;
285         } else if (err == SSL_ERROR_WANT_WRITE)
286         {
287             sb->sb_trans_needs_write = 1;
288             return 1;
289         } else if (err == SSL_ERROR_WANT_CONNECT)
290         {
291             return 1;
292         }
293         return 0;
294 }
295
296 /*
297  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
298  * a SSL_CTX * or NULL, in which case the default ctx is used.
299  *
300  * Return value:
301  *
302  *  0 - Success. Connection is ready for communication.
303  * <0 - Error. Can't create a TLS stream.
304  * >0 - Partial success.
305  *        Do a select (using information from lber_pvt_sb_needs_{read,write}
306  *              and call again.
307  */
308
309 int
310 ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg )
311 {
312         int     err;
313         SSL     *ssl;
314
315         if ( HAS_TLS( sb ) ) {
316                 ssl = (SSL *) sb->sb_iodata;
317         } else {
318                 ssl = alloc_handle( sb, ctx_arg );
319                 if ( ssl == NULL )
320                         return -1;
321                 ber_pvt_sb_clear_io( sb );
322                 ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
323         }
324
325         err = SSL_connect( ssl );
326
327 #ifdef HAVE_WINSOCK
328         errno = WSAGetLastError();
329 #endif
330         if ( err <= 0 ) {
331                 if ( update_flags( sb, ssl, err ))
332                         return 1;
333                 if ((err = ERR_peek_error())) {
334                         char buf[256];
335                         ld->ld_error = ldap_strdup(ERR_error_string(err, buf));
336                 }
337                 Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
338                 ber_pvt_sb_clear_io( sb );
339                 ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
340                 return -1;
341         }
342         return 0;
343 }
344
345 /*
346  * Call this to do a TLS accept on a sockbuf.
347  * Everything else is the same as with tls_connect.
348  */
349 int
350 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
351 {
352         int     err;
353         SSL     *ssl;
354
355         if ( HAS_TLS( sb ) ) {
356                 ssl = (SSL *) sb->sb_iodata;
357         } else {
358                 ssl = alloc_handle( sb, ctx_arg );
359                 if ( ssl == NULL )
360                         return -1;
361                 ber_pvt_sb_clear_io( sb );
362                 ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
363         }
364
365         err = SSL_accept( ssl );
366
367 #ifdef HAVE_WINSOCK
368         errno = WSAGetLastError();
369 #endif
370         if ( err <= 0 ) {
371                 if ( update_flags( sb, ssl, err ))
372                         return 1;
373                 Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
374                 tls_report_error();
375                 ber_pvt_sb_clear_io( sb );
376                 ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
377                 return -1;
378         }
379         return 0;
380 }
381
382 int
383 ldap_pvt_tls_inplace ( Sockbuf *sb )
384 {
385         if ( HAS_TLS( sb ) )
386                 return(1);
387         return(0);
388 }
389
390 void *
391 ldap_pvt_tls_sb_handle( Sockbuf *sb )
392 {
393         if (HAS_TLS( sb ))
394                 return sb->sb_iodata;
395         else
396                 return NULL;
397 }
398
399 void *
400 ldap_pvt_tls_get_handle( LDAP *ld )
401 {
402         return ldap_pvt_tls_sb_handle(&ld->ld_sb);
403 }
404
405 const char *
406 ldap_pvt_tls_get_peer( LDAP *ld )
407 {
408     return NULL;
409 }
410
411 const char *
412 ldap_pvt_tls_get_peer_issuer( LDAP *ld )
413 {
414     return NULL;
415 }
416
417 int
418 ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
419 {
420         int i;
421
422         switch( option ) {
423         case LDAP_OPT_X_TLS_CACERTFILE:
424         case LDAP_OPT_X_TLS_CACERTDIR:
425         case LDAP_OPT_X_TLS_CERTFILE:
426         case LDAP_OPT_X_TLS_KEYFILE:
427                 return ldap_pvt_tls_set_option( NULL, option, (void *) arg );
428         case LDAP_OPT_X_TLS_REQUIRE_CERT:
429                 i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
430                       ( strcasecmp( arg, "yes" ) == 0) ||
431                       ( strcasecmp( arg, "true" ) == 0 ) );
432                 return ldap_pvt_tls_set_option( NULL, option, (void *) &i );
433         case LDAP_OPT_X_TLS:
434                 i = -1;
435                 if ( strcasecmp( arg, "never" ) == 0 )
436                         i = LDAP_OPT_X_TLS_NEVER ;
437                 if ( strcasecmp( arg, "demand" ) == 0 )
438                         i = LDAP_OPT_X_TLS_DEMAND ;
439                 if ( strcasecmp( arg, "allow" ) == 0 )
440                         i = LDAP_OPT_X_TLS_ALLOW ;
441                 if ( strcasecmp( arg, "try" ) == 0 )
442                         i = LDAP_OPT_X_TLS_TRY ;
443                 if ( strcasecmp( arg, "hard" ) == 0 )
444                         i = LDAP_OPT_X_TLS_HARD ;
445                 if (i >= 0)
446                         return ldap_pvt_tls_set_option( lo, option, &i );
447                 return -1;
448         default:
449                 return -1;
450         }
451 }
452
453 int
454 ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
455 {
456         switch( option ) {
457         case LDAP_OPT_X_TLS:
458                 *(int *)arg = lo->ldo_tls_mode;
459                 break;
460         case LDAP_OPT_X_TLS_CERT:
461                 if ( lo == NULL )
462                         *(void **)arg = (void *) tls_def_ctx;
463                 else
464                         *(void **)arg = lo->ldo_tls_ctx;
465                 break;
466         case LDAP_OPT_X_TLS_CACERTFILE:
467                 *(char **)arg = tls_opt_cacertfile ?
468                         LDAP_STRDUP( tls_opt_cacertfile ) : NULL;
469                 break;
470         case LDAP_OPT_X_TLS_CACERTDIR:
471                 *(char **)arg = tls_opt_cacertdir ?
472                         LDAP_STRDUP( tls_opt_cacertdir ) : NULL;
473                 break;
474         case LDAP_OPT_X_TLS_CERTFILE:
475                 *(char **)arg = tls_opt_certfile ?
476                         LDAP_STRDUP( tls_opt_certfile ) : NULL;
477                 break;
478         case LDAP_OPT_X_TLS_KEYFILE:
479                 *(char **)arg = tls_opt_keyfile ?
480                         LDAP_STRDUP( tls_opt_keyfile ) : NULL;
481                 break;
482         case LDAP_OPT_X_TLS_REQUIRE_CERT:
483                 *(int *)arg = tls_opt_require_cert;
484                 break;
485         default:
486                 return -1;
487         }
488         return 0;
489 }
490
491 int
492 ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
493 {
494         switch( option ) {
495         case LDAP_OPT_X_TLS:
496                 switch( *(int *) arg ) {
497                 case LDAP_OPT_X_TLS_NEVER:
498                 case LDAP_OPT_X_TLS_DEMAND:
499                 case LDAP_OPT_X_TLS_ALLOW:
500                 case LDAP_OPT_X_TLS_TRY:
501                 case LDAP_OPT_X_TLS_HARD:
502                         if (lo != NULL) {
503                                 lo->ldo_tls_mode = *(int *)arg;
504                         }
505
506                         return 0;
507                 }
508                 return -1;
509
510         case LDAP_OPT_X_TLS_CERT:
511                 if ( lo == NULL ) {
512                         tls_def_ctx = (SSL_CTX *) arg;
513
514                 } else {
515                         lo->ldo_tls_ctx = arg;
516                 }
517                 return 0;
518         }
519
520         if ( lo != NULL ) {
521                 return -1;
522         }
523
524         switch( option ) {
525         case LDAP_OPT_X_TLS_CACERTFILE:
526                 if ( tls_opt_cacertfile ) free( tls_opt_cacertfile );
527                 tls_opt_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
528                 break;
529         case LDAP_OPT_X_TLS_CACERTDIR:
530                 if ( tls_opt_cacertdir ) free( tls_opt_cacertdir );
531                 tls_opt_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
532                 break;
533         case LDAP_OPT_X_TLS_CERTFILE:
534                 if ( tls_opt_certfile ) free( tls_opt_certfile );
535                 tls_opt_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
536                 break;
537         case LDAP_OPT_X_TLS_KEYFILE:
538                 if ( tls_opt_keyfile ) free( tls_opt_keyfile );
539                 tls_opt_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
540                 break;
541         case LDAP_OPT_X_TLS_REQUIRE_CERT:
542                 tls_opt_require_cert = * (int *) arg;
543                 break;
544         case LDAP_OPT_X_TLS_CIPHER_SUITE:
545                 if ( tls_opt_ciphersuite ) free( tls_opt_ciphersuite );
546                 tls_opt_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
547                 break;
548         default:
549                 return -1;
550         }
551         return 0;
552 }
553
554 int
555 ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg )
556 {
557         /*
558          * Fortunately, the lib uses blocking io...
559          */
560         if ( ldap_pvt_tls_connect( ld, sb, ctx_arg ) < 0 ) {
561                 return LDAP_CONNECT_ERROR;
562         }
563
564         /* FIXME: hostname of server must be compared with name in
565          * certificate....
566          */
567
568         return LDAP_SUCCESS;
569 }
570
571
572 static int
573 tls_setup( Sockbuf *sb, void *arg )
574 {
575         sb->sb_iodata = arg;
576         return 0;
577 }
578
579 static int
580 tls_remove( Sockbuf *sb )
581 {
582         SSL_free( (SSL *) sb->sb_iodata );
583         return 0;
584 }
585
586 static ber_slen_t
587 tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
588 {
589         int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
590
591 #ifdef HAVE_WINSOCK
592         errno = WSAGetLastError();
593 #endif
594         update_flags(sb, (SSL *)sb->sb_iodata, ret );
595 #ifdef WIN32
596         if (sb->sb_trans_needs_write)
597                 errno = EWOULDBLOCK;
598 #endif
599         return ret;
600 }
601
602 static ber_slen_t
603 tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
604 {
605         int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
606
607 #ifdef HAVE_WINSOCK
608         errno = WSAGetLastError();
609 #endif
610         update_flags(sb, (SSL *)sb->sb_iodata, ret );
611 #ifdef WIN32
612         if (sb->sb_trans_needs_read)
613                 errno = EWOULDBLOCK;
614 #endif
615         return ret;
616 }
617
618 static int
619 tls_close( Sockbuf *sb )
620 {
621         tcp_close( ber_pvt_sb_get_desc( sb ) );
622         return 0;
623 }
624
625 /* Derived from openssl/apps/s_cb.c */
626 static void
627 tls_info_cb( SSL *ssl, int where, int ret )
628 {
629         int w;
630         char *op;
631
632         w = where & ~SSL_ST_MASK;
633         if ( w & SSL_ST_CONNECT ) {
634                 op = "SSL_connect";
635         } else if ( w & SSL_ST_ACCEPT ) {
636                 op = "SSL_accept";
637         } else {
638                 op = "undefined";
639         }
640
641         if ( where & SSL_CB_LOOP ) {
642                 Debug( LDAP_DEBUG_TRACE,
643                        "TLS trace: %s:%s\n",
644                        op, SSL_state_string_long( ssl ), 0 );
645         } else if ( where & SSL_CB_ALERT ) {
646                 op = ( where & SSL_CB_READ ) ? "read" : "write";
647                 Debug( LDAP_DEBUG_TRACE,
648                        "TLS trace: SSL3 alert %s:%s:%s\n",
649                        op,
650                        SSL_alert_type_string_long( ret ),
651                        SSL_alert_desc_string_long( ret) );
652         } else if ( where & SSL_CB_EXIT ) {
653                 if ( ret == 0 ) {
654                         Debug( LDAP_DEBUG_TRACE,
655                                "TLS trace: %s:failed in %s\n",
656                                op, SSL_state_string_long( ssl ), 0 );
657                 } else if ( ret < 0 ) {
658                         Debug( LDAP_DEBUG_TRACE,
659                                "TLS trace: %s:error in %s\n",
660                                op, SSL_state_string_long( ssl ), 0 );
661                 }
662         }
663 }
664
665 static int
666 tls_verify_cb( int ok, X509_STORE_CTX *ctx )
667 {
668         X509 *cert;
669         int errnum;
670         int errdepth;
671         X509_NAME *subject;
672         X509_NAME *issuer;
673         char *sname;
674         char *iname;
675
676         cert = X509_STORE_CTX_get_current_cert( ctx );
677         errnum = X509_STORE_CTX_get_error( ctx );
678         errdepth = X509_STORE_CTX_get_error_depth( ctx );
679
680         /*
681          * X509_get_*_name return pointers to the internal copies of
682          * those things requested.  So do not free them.
683          */
684         subject = X509_get_subject_name( cert );
685         issuer = X509_get_issuer_name( cert );
686         /* X509_NAME_oneline, if passed a NULL buf, allocate memomry */
687         sname = X509_NAME_oneline( subject, NULL, 0 );
688         iname = X509_NAME_oneline( issuer, NULL, 0 );
689         Debug( LDAP_DEBUG_TRACE,
690                "TLS certificate verification: depth: %d, subject: %s, issuer: %s\n",
691                errdepth,
692                sname ? sname : "-unknown-",
693                iname ? iname : "-unknown-" );
694         if ( sname )
695                 CRYPTO_free ( sname );
696         if ( iname )
697                 CRYPTO_free ( iname );
698
699         return ok;
700 }
701
702 /* Inspired by ERR_print_errors in OpenSSL */
703 static void
704 tls_report_error( void )
705 {
706         unsigned long l;
707         char buf[200];
708         const char *file;
709         int line;
710
711         while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
712                         Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
713                                ERR_error_string( l, buf ), file, line );
714         }
715 }
716
717 static RSA *
718 tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
719 {
720         RSA *tmp_rsa;
721
722         /* FIXME:  Pregenerate the key on startup */
723         /* FIXME:  Who frees the key? */
724         tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL );
725
726         if ( !tmp_rsa ) {
727                 Debug( LDAP_DEBUG_ANY, "TLS: Failed to generate temporary %d-bit %s RSA key\n",
728                        key_length, is_export ? "export" : "domestic", 0 );
729                 return NULL;
730         }
731         return tmp_rsa;
732 }
733
734 #if 0
735 static DH *
736 tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
737 {
738         return NULL;
739 }
740 #endif
741
742 #else
743 static int dummy;
744 #endif