home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / src / tls.c < prev    next >
C/C++ Source or Header  |  2001-11-13  |  28KB  |  1,316 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/libldap/tls.c,v 1.8.2.26 2001/09/18 16:09:34 kurt Exp $ */
  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. #include <stdio.h>
  12.  
  13. #include <ac/stdlib.h>
  14. #include <ac/errno.h>
  15. #include <ac/socket.h>
  16. #include <ac/string.h>
  17. #include <ac/time.h>
  18. #include <ac/unistd.h>
  19. #include <ac/param.h>
  20.  
  21. #include "ldap-int.h"
  22.  
  23. #ifdef HAVE_TLS
  24.  
  25. #ifdef LDAP_R_COMPILE
  26. #include <ldap_pvt_thread.h>
  27. #endif
  28.  
  29. #ifdef HAVE_OPENSSL_SSL_H
  30. #include <openssl/ssl.h>
  31. #include <openssl/x509v3.h>
  32. #include <openssl/err.h>
  33. #include <openssl/rand.h>
  34. #elif defined( HAVE_SSL_H )
  35. #include <ssl.h>
  36. #endif
  37.  
  38. static int  tls_opt_trace = 1;
  39. static char *tls_opt_certfile = NULL;
  40. static char *tls_opt_keyfile = NULL;
  41. static char *tls_opt_cacertfile = NULL;
  42. static char *tls_opt_cacertdir = NULL;
  43. static int  tls_opt_require_cert = 0;
  44. static char *tls_opt_ciphersuite = NULL;
  45. static char *tls_opt_randfile = NULL;
  46.  
  47. #define HAS_TLS( sb )    ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
  48.                 (void *)&ldap_pvt_sockbuf_io_tls )
  49.  
  50. static void tls_report_error( void );
  51.  
  52. static void tls_info_cb( SSL *ssl, int where, int ret );
  53. static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
  54. static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
  55. static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
  56.  
  57. #if 0    /* Currently this is not used by anyone */
  58. static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
  59. #endif
  60.  
  61. static SSL_CTX *tls_def_ctx = NULL;
  62.  
  63. static int tls_seed_PRNG( const char *randfile );
  64.  
  65. #ifdef LDAP_R_COMPILE
  66. /*
  67.  * provide mutexes for the SSLeay library.
  68.  */
  69. static ldap_pvt_thread_mutex_t    tls_mutexes[CRYPTO_NUM_LOCKS];
  70.  
  71. static void tls_locking_cb( int mode, int type, const char *file, int line )
  72. {
  73.     if ( mode & CRYPTO_LOCK ) {
  74.         ldap_pvt_thread_mutex_lock( &tls_mutexes[type] );
  75.     } else {
  76.         ldap_pvt_thread_mutex_unlock( &tls_mutexes[type] );
  77.     }
  78. }
  79.  
  80. /*
  81.  * an extra mutex for the default ctx.
  82.  */
  83.  
  84. static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
  85.  
  86. static void tls_init_threads( void )
  87. {
  88.     int i;
  89.  
  90.     for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
  91.         ldap_pvt_thread_mutex_init( &tls_mutexes[i] );
  92.     }
  93.     CRYPTO_set_locking_callback( tls_locking_cb );
  94.     /* FIXME: the thread id should be added somehow... */
  95.  
  96.     ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
  97. }
  98. #endif /* LDAP_R_COMPILE */
  99.  
  100. /*
  101.  * Initialize TLS subsystem. Should be called only once.
  102.  */
  103. int
  104. ldap_pvt_tls_init( void )
  105. {
  106.     static int tls_initialized = 0;
  107.  
  108.     if ( tls_initialized ) return 0;
  109.     tls_initialized = 1;
  110.  
  111.     (void) tls_seed_PRNG( tls_opt_randfile );
  112.  
  113. #ifdef LDAP_R_COMPILE
  114.     tls_init_threads();
  115. #endif
  116.  
  117.     SSL_load_error_strings();
  118.     SSLeay_add_ssl_algorithms();
  119.  
  120.     /* FIXME: mod_ssl does this */
  121.     X509V3_add_standard_extensions();
  122.     return 0;
  123. }
  124.  
  125. /*
  126.  * initialize the default context
  127.  */
  128. int
  129. ldap_pvt_tls_init_def_ctx( void )
  130. {
  131.     STACK_OF(X509_NAME) *calist;
  132.  
  133. #ifdef LDAP_R_COMPILE
  134.     ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
  135. #endif
  136.     if ( tls_def_ctx == NULL ) {
  137.         tls_def_ctx = SSL_CTX_new( SSLv23_method() );
  138.         if ( tls_def_ctx == NULL ) {
  139.             Debug( LDAP_DEBUG_ANY,
  140.                "TLS: could not allocate default ctx (%d).\n",
  141.                 ERR_peek_error(),0,0);
  142.             goto error_exit;
  143.         }
  144.         if ( tls_opt_ciphersuite &&
  145.              !SSL_CTX_set_cipher_list( tls_def_ctx,
  146.             tls_opt_ciphersuite ) ) {
  147.             Debug( LDAP_DEBUG_ANY,
  148.                    "TLS: could not set cipher list %s.\n",
  149.                    tls_opt_ciphersuite, 0, 0 );
  150.             tls_report_error();
  151.             goto error_exit;
  152.         }
  153.         if (tls_opt_cacertfile != NULL || tls_opt_cacertdir != NULL) {
  154.             if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
  155.                                  tls_opt_cacertfile,
  156.                                  tls_opt_cacertdir )
  157.                  || !SSL_CTX_set_default_verify_paths( tls_def_ctx ) )
  158.             {
  159.                 Debug( LDAP_DEBUG_ANY,
  160.              "TLS: could not load verify locations (file:`%s',dir:`%s').\n",
  161.                        tls_opt_cacertfile,tls_opt_cacertdir,0);
  162.                 tls_report_error();
  163.                 goto error_exit;
  164.             }
  165.             calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir );
  166.             if ( !calist ) {
  167.                 Debug( LDAP_DEBUG_ANY,
  168.              "TLS: could not load client CA list (file:`%s',dir:`%s').\n",
  169.                        tls_opt_cacertfile,tls_opt_cacertdir,0);
  170.                 tls_report_error();
  171.                 goto error_exit;
  172.             }
  173.             SSL_CTX_set_client_CA_list( tls_def_ctx, calist );
  174.         }
  175.         if ( tls_opt_keyfile &&
  176.              !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
  177.                            tls_opt_keyfile,
  178.                            SSL_FILETYPE_PEM ) ) {
  179.             Debug( LDAP_DEBUG_ANY,
  180.                    "TLS: could not use key file `%s'.\n",
  181.                    tls_opt_keyfile,0,0);
  182.             tls_report_error();
  183.             goto error_exit;
  184.         }
  185.         if ( tls_opt_certfile &&
  186.              !SSL_CTX_use_certificate_file( tls_def_ctx,
  187.                             tls_opt_certfile,
  188.                             SSL_FILETYPE_PEM ) ) {
  189.             Debug( LDAP_DEBUG_ANY,
  190.                    "TLS: could not use certificate `%s'.\n",
  191.                    tls_opt_certfile,0,0);
  192.             tls_report_error();
  193.             goto error_exit;
  194.         }
  195.         if ( ( tls_opt_certfile || tls_opt_keyfile ) &&
  196.              !SSL_CTX_check_private_key( tls_def_ctx ) ) {
  197.             Debug( LDAP_DEBUG_ANY,
  198.                    "TLS: private key mismatch.\n",
  199.                    0,0,0);
  200.             tls_report_error();
  201.             goto error_exit;
  202.         }
  203.         if ( tls_opt_trace ) {
  204.             SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb );
  205.         }
  206.         SSL_CTX_set_verify( tls_def_ctx,
  207.             tls_opt_require_cert ?
  208.             (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) :
  209.             SSL_VERIFY_NONE,
  210.             tls_verify_cb );
  211.         SSL_CTX_set_tmp_rsa_callback( tls_def_ctx, tls_tmp_rsa_cb );
  212.         /* SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); */
  213.     }
  214. #ifdef LDAP_R_COMPILE
  215.     ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
  216. #endif
  217.     return 0;
  218. error_exit:
  219.     if ( tls_def_ctx != NULL ) {
  220.         SSL_CTX_free( tls_def_ctx );
  221.         tls_def_ctx = NULL;
  222.     }
  223. #ifdef LDAP_R_COMPILE
  224.     ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
  225. #endif
  226.     return -1;
  227. }
  228.  
  229. static STACK_OF(X509_NAME) *
  230. get_ca_list( char * bundle, char * dir )
  231. {
  232.     STACK_OF(X509_NAME) *ca_list = NULL;
  233.  
  234.     if ( bundle ) {
  235.         ca_list = SSL_load_client_CA_file( bundle );
  236.     }
  237.     /*
  238.      * FIXME: We have now to go over all files in dir, load them
  239.      * and add every certificate there to ca_list.
  240.      */
  241.     return ca_list;
  242. }
  243.  
  244. static SSL *
  245. alloc_handle( void *ctx_arg )
  246. {
  247.     SSL_CTX    *ctx;
  248.     SSL    *ssl;
  249.  
  250.     if ( ctx_arg ) {
  251.         ctx = (SSL_CTX *) ctx_arg;
  252.     } else {
  253.         if ( ldap_pvt_tls_init_def_ctx() < 0 ) return NULL;
  254.         ctx = tls_def_ctx;
  255.     }
  256.  
  257.     ssl = SSL_new( ctx );
  258.     if ( ssl == NULL ) {
  259.         Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
  260.         return NULL;
  261.     }
  262.     return ssl;
  263. }
  264.  
  265. static int
  266. update_flags( Sockbuf *sb, SSL * ssl, int rc )
  267. {
  268.     int err = SSL_get_error(ssl, rc);
  269.  
  270.     sb->sb_trans_needs_read  = 0;
  271.     sb->sb_trans_needs_write = 0;
  272.     if (err == SSL_ERROR_WANT_READ)
  273.     {
  274.         sb->sb_trans_needs_read  = 1;
  275.         return 1;
  276.     } else if (err == SSL_ERROR_WANT_WRITE)
  277.     {
  278.         sb->sb_trans_needs_write = 1;
  279.         return 1;
  280.     } else if (err == SSL_ERROR_WANT_CONNECT)
  281.     {
  282.         return 1;
  283.     }
  284.     return 0;
  285. }
  286.  
  287. /*
  288.  * TLS support for LBER Sockbufs
  289.  */
  290.  
  291. struct tls_data {
  292.     SSL            *ssl;
  293.     Sockbuf_IO_Desc        *sbiod;
  294. };
  295.  
  296. extern BIO_METHOD ldap_pvt_sb_bio_method;
  297.  
  298. static int
  299. sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
  300. {
  301.     struct tls_data        *p;
  302.     BIO            *bio;
  303.  
  304.     assert( sbiod != NULL );
  305.  
  306.     p = LBER_MALLOC( sizeof( *p ) );
  307.     if ( p == NULL )
  308.         return -1;
  309.     
  310.     p->ssl = (SSL *)arg;
  311.     p->sbiod = sbiod;
  312.     bio = BIO_new( &ldap_pvt_sb_bio_method );
  313.     bio->ptr = (void *)p;
  314.     SSL_set_bio( p->ssl, bio, bio );
  315.     sbiod->sbiod_pvt = p;
  316.     return 0;
  317. }
  318.  
  319. static int
  320. sb_tls_remove( Sockbuf_IO_Desc *sbiod )
  321. {
  322.     struct tls_data        *p;
  323.     
  324.     assert( sbiod != NULL );
  325.     assert( sbiod->sbiod_pvt != NULL );
  326.  
  327.     p = (struct tls_data *)sbiod->sbiod_pvt;
  328.     SSL_free( p->ssl );
  329.     LBER_FREE( sbiod->sbiod_pvt );
  330.     sbiod->sbiod_pvt = NULL;
  331.     return 0;
  332. }
  333.  
  334. static int
  335. sb_tls_close( Sockbuf_IO_Desc *sbiod )
  336. {
  337.     struct tls_data        *p;
  338.     
  339.     assert( sbiod != NULL );
  340.     assert( sbiod->sbiod_pvt != NULL );
  341.  
  342.     p = (struct tls_data *)sbiod->sbiod_pvt;
  343.     SSL_shutdown( p->ssl );
  344.     return 0;
  345. }
  346.  
  347. static int
  348. sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
  349. {
  350.     struct tls_data        *p;
  351.     
  352.     assert( sbiod != NULL );
  353.     assert( sbiod->sbiod_pvt != NULL );
  354.  
  355.     p = (struct tls_data *)sbiod->sbiod_pvt;
  356.     
  357.     if ( opt == LBER_SB_OPT_GET_SSL ) {
  358.         *((SSL **)arg) = p->ssl;
  359.         return 1;
  360.  
  361.     } else if ( opt == LBER_SB_OPT_DATA_READY ) {
  362.         if( SSL_pending( p->ssl ) > 0 ) {
  363.             return 1;
  364.         }
  365.     }
  366.     
  367.     return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
  368. }
  369.  
  370. static ber_slen_t
  371. sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
  372. {
  373.     struct tls_data        *p;
  374.     ber_slen_t        ret;
  375.     int            err;
  376.  
  377.     assert( sbiod != NULL );
  378.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  379.  
  380.     p = (struct tls_data *)sbiod->sbiod_pvt;
  381.  
  382.     ret = SSL_read( p->ssl, (char *)buf, len );
  383. #ifdef HAVE_WINSOCK
  384.     errno = WSAGetLastError();
  385. #endif
  386. #ifdef __OS2__
  387.     errno = sock_errno();
  388. #endif
  389.     err = SSL_get_error( p->ssl, ret );
  390.     if (err == SSL_ERROR_WANT_READ ) {
  391.         sbiod->sbiod_sb->sb_trans_needs_read = 1;
  392. #if defined(WIN32) || defined(__OS2__)
  393.         errno = EWOULDBLOCK;
  394. #endif
  395.     }
  396.     else
  397.         sbiod->sbiod_sb->sb_trans_needs_read = 0;
  398.     return ret;
  399. }
  400.  
  401. static ber_slen_t
  402. sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
  403. {
  404.     struct tls_data        *p;
  405.     ber_slen_t        ret;
  406.     int            err;
  407.  
  408.     assert( sbiod != NULL );
  409.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  410.  
  411.     p = (struct tls_data *)sbiod->sbiod_pvt;
  412.  
  413.     ret = SSL_write( p->ssl, (char *)buf, len );
  414. #ifdef HAVE_WINSOCK
  415.     errno = WSAGetLastError();
  416. #endif
  417. #ifdef __OS2__
  418.     errno = sock_errno();
  419. #endif
  420.     err = SSL_get_error( p->ssl, ret );
  421.     if (err == SSL_ERROR_WANT_WRITE ) {
  422.         sbiod->sbiod_sb->sb_trans_needs_write = 1;
  423. #if defined(WIN32) || defined(__OS2__)
  424.         errno = EWOULDBLOCK;
  425. #endif
  426.     }
  427.     else
  428.         sbiod->sbiod_sb->sb_trans_needs_write = 0;
  429.     return ret;
  430. }
  431.  
  432. Sockbuf_IO ldap_pvt_sockbuf_io_tls =
  433. {
  434.     sb_tls_setup,        /* sbi_setup */
  435.     sb_tls_remove,        /* sbi_remove */
  436.     sb_tls_ctrl,        /* sbi_ctrl */
  437.     sb_tls_read,        /* sbi_read */
  438.     sb_tls_write,        /* sbi_write */
  439.     sb_tls_close        /* sbi_close */
  440. };
  441.  
  442. static int
  443. sb_tls_bio_create( BIO *b ) {
  444.     b->init = 1;
  445.     b->num = 0;
  446.     b->ptr = NULL;
  447.     b->flags = 0;
  448.     return 1;
  449. }
  450.  
  451. static int
  452. sb_tls_bio_destroy( BIO *b )
  453. {
  454.     if ( b == NULL )
  455.         return 0;
  456.  
  457.     b->ptr = NULL;        /* sb_tls_remove() will free it */
  458.     b->init = 0;
  459.     b->flags = 0;
  460.     return 1;
  461. }
  462.  
  463. static int
  464. sb_tls_bio_read( BIO *b, char *buf, int len )
  465. {
  466.     struct tls_data        *p;
  467.     int            ret;
  468.         
  469.     if ( buf == NULL || len <= 0 )
  470.         return 0;
  471.  
  472.     p = (struct tls_data *)b->ptr;
  473.  
  474.     if ( p == NULL || p->sbiod == NULL )
  475.         return 0;
  476.  
  477.     ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
  478.  
  479.     BIO_clear_retry_flags( b );
  480.     if ( ret < 0 && errno == EWOULDBLOCK )
  481.         BIO_set_retry_read( b );
  482.  
  483.     return ret;
  484. }
  485.  
  486. static int
  487. sb_tls_bio_write( BIO *b, const char *buf, int len )
  488. {
  489.     struct tls_data        *p;
  490.     int            ret;
  491.     
  492.     if ( buf == NULL || len <= 0 )
  493.         return 0;
  494.     
  495.     p = (struct tls_data *)b->ptr;
  496.  
  497.     if ( p == NULL || p->sbiod == NULL )
  498.         return 0;
  499.  
  500.     ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
  501.  
  502.     BIO_clear_retry_flags( b );
  503.     if ( ret < 0 && errno == EWOULDBLOCK )
  504.         BIO_set_retry_write( b );
  505.  
  506.     return ret;
  507. }
  508.  
  509. static long
  510. sb_tls_bio_ctrl( BIO *b, int cmd, long num, void *ptr )
  511. {
  512.     if ( cmd == BIO_CTRL_FLUSH ) {
  513.         /* The OpenSSL library needs this */
  514.         return 1;
  515.     }
  516.     return 0;
  517. }
  518.  
  519. static int
  520. sb_tls_bio_gets( BIO *b, char *buf, int len )
  521. {
  522.     return -1;
  523. }
  524.  
  525. static int
  526. sb_tls_bio_puts( BIO *b, const char *str )
  527. {
  528.     return sb_tls_bio_write( b, str, strlen( str ) );
  529. }
  530.     
  531. BIO_METHOD ldap_pvt_sb_bio_method =
  532. {
  533.     ( 100 | 0x400 ),        /* it's a source/sink BIO */
  534.     "sockbuf glue",
  535.     sb_tls_bio_write,
  536.     sb_tls_bio_read,
  537.     sb_tls_bio_puts,
  538.     sb_tls_bio_gets,
  539.     sb_tls_bio_ctrl,
  540.     sb_tls_bio_create,
  541.     sb_tls_bio_destroy
  542. };
  543.  
  544. /*
  545.  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
  546.  * a SSL_CTX * or NULL, in which case the default ctx is used.
  547.  *
  548.  * Return value:
  549.  *
  550.  *  0 - Success. Connection is ready for communication.
  551.  * <0 - Error. Can't create a TLS stream.
  552.  * >0 - Partial success.
  553.  *      Do a select (using information from lber_pvt_sb_needs_{read,write}
  554.  *        and call again.
  555.  */
  556.  
  557. static int
  558. ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
  559. {
  560.     Sockbuf *sb = conn->lconn_sb;
  561.     int    err;
  562.     SSL    *ssl;
  563.  
  564.     if ( HAS_TLS( sb ) ) {
  565.         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
  566.  
  567.     } else {
  568.         void *ctx = ld->ld_defconn
  569.             ? ld->ld_defconn->lconn_tls_ctx : NULL;
  570.  
  571.         ssl = alloc_handle( ctx );
  572.  
  573.         if ( ssl == NULL ) return -1;
  574.  
  575. #ifdef LDAP_DEBUG
  576.         ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
  577.             LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
  578. #endif
  579.         ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
  580.             LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
  581.  
  582.         if( ctx == NULL ) {
  583.             conn->lconn_tls_ctx = tls_def_ctx;
  584.         }
  585.     }
  586.  
  587.     err = SSL_connect( ssl );
  588.  
  589. #ifdef HAVE_WINSOCK
  590.     errno = WSAGetLastError();
  591. #endif
  592. #ifdef __OS2__
  593.     errno = sock_errno();
  594. #endif
  595.     if ( err <= 0 ) {
  596.         if ( update_flags( sb, ssl, err )) {
  597.             return 1;
  598.         }
  599.         if ((err = ERR_peek_error())) {
  600.             char buf[256];
  601.             ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf));
  602.         }
  603.         Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
  604.         ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
  605.             LBER_SBIOD_LEVEL_TRANSPORT );
  606. #ifdef LDAP_DEBUG
  607.         ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
  608.             LBER_SBIOD_LEVEL_TRANSPORT );
  609. #endif
  610.         return -1;
  611.     }
  612.  
  613.     return 0;
  614. }
  615.  
  616. /*
  617.  * Call this to do a TLS accept on a sockbuf.
  618.  * Everything else is the same as with tls_connect.
  619.  */
  620. int
  621. ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
  622. {
  623.     int    err;
  624.     SSL    *ssl;
  625.  
  626.     if ( HAS_TLS( sb ) ) {
  627.         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
  628.     } else {
  629.         ssl = alloc_handle( ctx_arg );
  630.         if ( ssl == NULL )
  631.             return -1;
  632. #ifdef LDAP_DEBUG
  633.         ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
  634.             LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
  635. #endif
  636.         ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
  637.             LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
  638.     }
  639.  
  640.     err = SSL_accept( ssl );
  641.  
  642. #ifdef HAVE_WINSOCK
  643.     errno = WSAGetLastError();
  644. #endif
  645. #ifdef __OS2__
  646.     errno = sock_errno();
  647. #endif
  648.     if ( err <= 0 ) {
  649.         if ( update_flags( sb, ssl, err ))
  650.             return 1;
  651.         Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
  652.         tls_report_error();
  653.         ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
  654.             LBER_SBIOD_LEVEL_TRANSPORT );
  655. #ifdef LDAP_DEBUG
  656.         ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
  657.             LBER_SBIOD_LEVEL_TRANSPORT );
  658. #endif
  659.         return -1;
  660.     }
  661.  
  662.     return 0;
  663. }
  664.  
  665. int
  666. ldap_pvt_tls_inplace ( Sockbuf *sb )
  667. {
  668.     if ( HAS_TLS( sb ) )
  669.         return(1);
  670.     return(0);
  671. }
  672.  
  673. void *
  674. ldap_pvt_tls_sb_ctx( Sockbuf *sb )
  675. {
  676.     void            *p;
  677.     
  678.     if (HAS_TLS( sb )) {
  679.         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p );
  680.         return p;
  681.     }
  682.  
  683.     return NULL;
  684. }
  685.  
  686. int
  687. ldap_pvt_tls_get_strength( void *s )
  688. {
  689.     SSL_CIPHER *c;
  690.  
  691.     c = SSL_get_current_cipher((SSL *)s);
  692.     return SSL_CIPHER_get_bits(c, NULL);
  693. }
  694.  
  695.  
  696. char *
  697. ldap_pvt_tls_get_peer( void *s )
  698. {
  699.     X509 *x;
  700.     X509_NAME *xn;
  701.     char buf[2048], *p;
  702.  
  703.     x = SSL_get_peer_certificate((SSL *)s);
  704.  
  705.     if (!x)
  706.         return NULL;
  707.     
  708.     xn = X509_get_subject_name(x);
  709.     p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
  710.     X509_free(x);
  711.     return p;
  712. }
  713.  
  714. char *
  715. ldap_pvt_tls_get_peer_dn( void *s )
  716. {
  717.     X509 *x;
  718.     X509_NAME *xn;
  719.     char buf[2048], *p, *dn;
  720.  
  721.     x = SSL_get_peer_certificate((SSL *)s);
  722.  
  723.     if (!x) return NULL;
  724.     
  725.     xn = X509_get_subject_name(x);
  726.     p = X509_NAME_oneline(xn, buf, sizeof(buf));
  727.  
  728.     dn = ldap_dcedn2dn( p );
  729.  
  730.     X509_free(x);
  731.     return dn;
  732. }
  733.  
  734. char *
  735. ldap_pvt_tls_get_peer_hostname( void *s )
  736. {
  737.     X509 *x;
  738.     X509_NAME *xn;
  739.     char buf[2048], *p;
  740.     int ret;
  741.  
  742.     x = SSL_get_peer_certificate((SSL *)s);
  743.  
  744.     if (!x)
  745.         return NULL;
  746.     
  747.     xn = X509_get_subject_name(x);
  748.  
  749.     ret = X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf));
  750.     if( ret == -1 ) {
  751.         X509_free(x);
  752.         return NULL;
  753.     }
  754.  
  755.     p = LDAP_STRDUP(buf);
  756.     X509_free(x);
  757.     return p;
  758. }
  759.  
  760. int
  761. ldap_pvt_tls_check_hostname( void *s, char *name )
  762. {
  763.     int i, ret = LDAP_LOCAL_ERROR;
  764.     X509 *x;
  765.  
  766.     x = SSL_get_peer_certificate((SSL *)s);
  767.     if (!x)
  768.     {
  769.     Debug( LDAP_DEBUG_ANY,
  770.         "TLS: unable to get peer certificate.\n",
  771.         0, 0, 0 );
  772.     return ret;
  773.     }
  774.  
  775.     i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
  776.     if (i >= 0)
  777.     {
  778.     X509_EXTENSION *ex;
  779.     STACK_OF(GENERAL_NAME) *alt;
  780.  
  781.     ex = X509_get_ext(x, i);
  782.     alt = X509V3_EXT_d2i(ex);
  783.     if (alt)
  784.     {
  785.         int n, len1, len2;
  786.         char *domain;
  787.         GENERAL_NAME *gn;
  788.         X509V3_EXT_METHOD *method;
  789.  
  790.         len1 = strlen(name);
  791.         n = sk_GENERAL_NAME_num(alt);
  792.         domain = strchr(name, '.');
  793.         if (domain)
  794.             len2 = len1 - (domain-name);
  795.         for (i=0; i<n; i++)
  796.         {
  797.         gn = sk_GENERAL_NAME_value(alt, i);
  798.         if (gn->type == GEN_DNS)
  799.         {
  800.             char *sn = ASN1_STRING_data(gn->d.ia5);
  801.             int sl = ASN1_STRING_length(gn->d.ia5);
  802.  
  803.             /* Is this an exact match? */
  804.             if ((len1 == sl) && !strncasecmp(name, sn, len1))
  805.             break;
  806.  
  807.             /* Is this a wildcard match? */
  808.             if ((*sn == '*') && domain && (len2 == sl-1) &&
  809.                 !strncasecmp(domain, sn+1, len2))
  810.             break;
  811.         }
  812.         }
  813.         method = X509V3_EXT_get(ex);
  814.         method->ext_free(alt);
  815.         if (i < n)    /* Found a match */
  816.         ret = LDAP_SUCCESS;
  817.     }
  818.     }
  819.  
  820.     if (ret != LDAP_SUCCESS)
  821.     {
  822.     X509_NAME *xn;
  823.     char buf[2048];
  824.  
  825.     xn = X509_get_subject_name(x);
  826.  
  827.     if (X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf))
  828.         == -1)
  829.     {
  830.         Debug( LDAP_DEBUG_ANY,
  831.             "TLS: unable to get common name from peer certificate.\n",
  832.             0, 0, 0 );
  833.     } else if (strcasecmp(name, buf))
  834.     {
  835.         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
  836.             "common name in certificate (%s).\n", 
  837.             name, buf, 0 );
  838.         ret =  LDAP_CONNECT_ERROR;
  839.     } else
  840.     {
  841.         ret = LDAP_SUCCESS;
  842.     }
  843.     }
  844.     X509_free(x);
  845.     return ret;
  846. }
  847.  
  848. const char *
  849. ldap_pvt_tls_get_peer_issuer( void *s )
  850. {
  851. #if 0    /* currently unused; see ldap_pvt_tls_get_peer() if needed */
  852.     X509 *x;
  853.     X509_NAME *xn;
  854.     char buf[2048], *p;
  855.  
  856.     x = SSL_get_peer_certificate((SSL *)s);
  857.  
  858.     if (!x)
  859.         return NULL;
  860.     
  861.     xn = X509_get_issuer_name(x);
  862.     p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf)));
  863.     X509_free(x);
  864.     return p;
  865. #else
  866.     return NULL;
  867. #endif
  868. }
  869.  
  870. int
  871. ldap_int_tls_config( LDAP *ld, int option, const char *arg )
  872. {
  873.     int i;
  874.  
  875.     switch( option ) {
  876.     case LDAP_OPT_X_TLS_CACERTFILE:
  877.     case LDAP_OPT_X_TLS_CACERTDIR:
  878.     case LDAP_OPT_X_TLS_CERTFILE:
  879.     case LDAP_OPT_X_TLS_KEYFILE:
  880.     case LDAP_OPT_X_TLS_RANDOM_FILE:
  881.         return ldap_pvt_tls_set_option( ld, option, (void *) arg );
  882.  
  883.     case LDAP_OPT_X_TLS_REQUIRE_CERT:
  884.         i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
  885.               ( strcasecmp( arg, "yes" ) == 0) ||
  886.               ( strcasecmp( arg, "true" ) == 0 ) );
  887.         return ldap_pvt_tls_set_option( ld, option, (void *) &i );
  888.  
  889.     case LDAP_OPT_X_TLS:
  890.         i = -1;
  891.         if ( strcasecmp( arg, "never" ) == 0 )
  892.             i = LDAP_OPT_X_TLS_NEVER ;
  893.         if ( strcasecmp( arg, "demand" ) == 0 )
  894.             i = LDAP_OPT_X_TLS_DEMAND ;
  895.         if ( strcasecmp( arg, "allow" ) == 0 )
  896.             i = LDAP_OPT_X_TLS_ALLOW ;
  897.         if ( strcasecmp( arg, "try" ) == 0 )
  898.             i = LDAP_OPT_X_TLS_TRY ;
  899.         if ( strcasecmp( arg, "hard" ) == 0 )
  900.             i = LDAP_OPT_X_TLS_HARD ;
  901.  
  902.         if (i >= 0) {
  903.             return ldap_pvt_tls_set_option( ld, option, &i );
  904.         }
  905.         return -1;
  906.     }
  907.  
  908.     return -1;
  909. }
  910.  
  911. int
  912. ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
  913. {
  914.     struct ldapoptions *lo;
  915.  
  916.     if( ld != NULL ) {
  917.         assert( LDAP_VALID( ld ) );
  918.  
  919.         if( !LDAP_VALID( ld ) ) {
  920.             return LDAP_OPT_ERROR;
  921.         }
  922.  
  923.         lo = &ld->ld_options;
  924.  
  925.     } else {
  926.         /* Get pointer to global option structure */
  927.         lo = LDAP_INT_GLOBAL_OPT();   
  928.         if ( lo == NULL ) {
  929.             return LDAP_NO_MEMORY;
  930.         }
  931.     }
  932.  
  933.     switch( option ) {
  934.     case LDAP_OPT_X_TLS:
  935.         *(int *)arg = lo->ldo_tls_mode;
  936.         break;
  937.     case LDAP_OPT_X_TLS_CTX:
  938.         if ( ld == NULL )
  939.             *(void **)arg = (void *) tls_def_ctx;
  940.         else
  941.             *(void **)arg = ld->ld_defconn->lconn_tls_ctx;
  942.         break;
  943.     case LDAP_OPT_X_TLS_CACERTFILE:
  944.         *(char **)arg = tls_opt_cacertfile ?
  945.             LDAP_STRDUP( tls_opt_cacertfile ) : NULL;
  946.         break;
  947.     case LDAP_OPT_X_TLS_CACERTDIR:
  948.         *(char **)arg = tls_opt_cacertdir ?
  949.             LDAP_STRDUP( tls_opt_cacertdir ) : NULL;
  950.         break;
  951.     case LDAP_OPT_X_TLS_CERTFILE:
  952.         *(char **)arg = tls_opt_certfile ?
  953.             LDAP_STRDUP( tls_opt_certfile ) : NULL;
  954.         break;
  955.     case LDAP_OPT_X_TLS_KEYFILE:
  956.         *(char **)arg = tls_opt_keyfile ?
  957.             LDAP_STRDUP( tls_opt_keyfile ) : NULL;
  958.         break;
  959.     case LDAP_OPT_X_TLS_REQUIRE_CERT:
  960.         *(int *)arg = tls_opt_require_cert;
  961.         break;
  962.     case LDAP_OPT_X_TLS_RANDOM_FILE:
  963.         *(char **)arg = tls_opt_randfile;
  964.         break;
  965.     default:
  966.         return -1;
  967.     }
  968.     return 0;
  969. }
  970.  
  971. int
  972. ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
  973. {
  974.     struct ldapoptions *lo;
  975.  
  976.     if( ld != NULL ) {
  977.         assert( LDAP_VALID( ld ) );
  978.  
  979.         if( !LDAP_VALID( ld ) ) {
  980.             return LDAP_OPT_ERROR;
  981.         }
  982.  
  983.         lo = &ld->ld_options;
  984.  
  985.     } else {
  986.         /* Get pointer to global option structure */
  987.         lo = LDAP_INT_GLOBAL_OPT();   
  988.         if ( lo == NULL ) {
  989.             return LDAP_NO_MEMORY;
  990.         }
  991.     }
  992.  
  993.     switch( option ) {
  994.     case LDAP_OPT_X_TLS:
  995.         switch( *(int *) arg ) {
  996.         case LDAP_OPT_X_TLS_NEVER:
  997.         case LDAP_OPT_X_TLS_DEMAND:
  998.         case LDAP_OPT_X_TLS_ALLOW:
  999.         case LDAP_OPT_X_TLS_TRY:
  1000.         case LDAP_OPT_X_TLS_HARD:
  1001.             if (lo != NULL) {
  1002.                 lo->ldo_tls_mode = *(int *)arg;
  1003.             }
  1004.  
  1005.             return 0;
  1006.         }
  1007.         return -1;
  1008.  
  1009.     case LDAP_OPT_X_TLS_CTX:
  1010.         if ( ld == NULL ) {
  1011.             tls_def_ctx = (SSL_CTX *) arg;
  1012.  
  1013.         } else {
  1014.             ld->ld_defconn->lconn_tls_ctx = arg;
  1015.         }
  1016.         return 0;
  1017.     }
  1018.  
  1019.     if ( ld != NULL ) {
  1020.         return -1;
  1021.     }
  1022.  
  1023.     switch( option ) {
  1024.     case LDAP_OPT_X_TLS_CACERTFILE:
  1025.         if ( tls_opt_cacertfile ) LDAP_FREE( tls_opt_cacertfile );
  1026.         tls_opt_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
  1027.         break;
  1028.     case LDAP_OPT_X_TLS_CACERTDIR:
  1029.         if ( tls_opt_cacertdir ) LDAP_FREE( tls_opt_cacertdir );
  1030.         tls_opt_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
  1031.         break;
  1032.     case LDAP_OPT_X_TLS_CERTFILE:
  1033.         if ( tls_opt_certfile ) LDAP_FREE( tls_opt_certfile );
  1034.         tls_opt_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
  1035.         break;
  1036.     case LDAP_OPT_X_TLS_KEYFILE:
  1037.         if ( tls_opt_keyfile ) LDAP_FREE( tls_opt_keyfile );
  1038.         tls_opt_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
  1039.         break;
  1040.     case LDAP_OPT_X_TLS_REQUIRE_CERT:
  1041.         tls_opt_require_cert = * (int *) arg;
  1042.         break;
  1043.     case LDAP_OPT_X_TLS_CIPHER_SUITE:
  1044.         if ( tls_opt_ciphersuite ) LDAP_FREE( tls_opt_ciphersuite );
  1045.         tls_opt_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
  1046.         break;
  1047.     case LDAP_OPT_X_TLS_RANDOM_FILE:
  1048.         if (tls_opt_randfile ) LDAP_FREE (tls_opt_randfile );
  1049.         tls_opt_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
  1050.         break;
  1051.     default:
  1052.         return -1;
  1053.     }
  1054.     return 0;
  1055. }
  1056.  
  1057. int
  1058. ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
  1059. {
  1060.     Sockbuf *sb = conn->lconn_sb;
  1061.     char *host;
  1062.     void *ssl;
  1063.  
  1064.     if( srv ) {
  1065.         host = srv->lud_host;
  1066.     } else {
  1067.          host = conn->lconn_server->lud_host;
  1068.     }
  1069.  
  1070.     /* avoid NULL host */
  1071.     if( host == NULL ) host = "localhost";
  1072.  
  1073.     (void) ldap_pvt_tls_init();
  1074.  
  1075.     /*
  1076.      * Fortunately, the lib uses blocking io...
  1077.      */
  1078.     if ( ldap_int_tls_connect( ld, conn ) < 0 ) {
  1079.         ld->ld_errno = LDAP_CONNECT_ERROR;
  1080.         return (ld->ld_errno);
  1081.     }
  1082.  
  1083.     ssl = (void *) ldap_pvt_tls_sb_ctx( sb );
  1084.     assert( ssl != NULL );
  1085.  
  1086.     /* 
  1087.      * compare host with name(s) in certificate
  1088.      */
  1089.  
  1090.     ld->ld_errno = ldap_pvt_tls_check_hostname( ssl, host );
  1091.     if (ld->ld_errno != LDAP_SUCCESS) {
  1092.         return ld->ld_errno;
  1093.     }
  1094.  
  1095.     /*
  1096.      * set SASL properties to TLS ssf and authid
  1097.      */
  1098.     {
  1099.         const char *authid;
  1100.         ber_len_t ssf;
  1101.  
  1102.         /* we need to let SASL know */
  1103.         ssf = ldap_pvt_tls_get_strength( ssl );
  1104.         authid = ldap_pvt_tls_get_peer( ssl );
  1105.  
  1106.         (void) ldap_int_sasl_external( ld, conn, authid, ssf );
  1107.     }
  1108.  
  1109.     return LDAP_SUCCESS;
  1110. }
  1111.  
  1112. /* Derived from openssl/apps/s_cb.c */
  1113. static void
  1114. tls_info_cb( SSL *ssl, int where, int ret )
  1115. {
  1116.     int w;
  1117.     char *op;
  1118.  
  1119.     w = where & ~SSL_ST_MASK;
  1120.     if ( w & SSL_ST_CONNECT ) {
  1121.         op = "SSL_connect";
  1122.     } else if ( w & SSL_ST_ACCEPT ) {
  1123.         op = "SSL_accept";
  1124.     } else {
  1125.         op = "undefined";
  1126.     }
  1127.  
  1128.         if ( where & SSL_CB_LOOP ) {
  1129.         Debug( LDAP_DEBUG_TRACE,
  1130.                "TLS trace: %s:%s\n",
  1131.                op, SSL_state_string_long( ssl ), 0 );
  1132.     } else if ( where & SSL_CB_ALERT ) {
  1133.                 op = ( where & SSL_CB_READ ) ? "read" : "write";
  1134.         Debug( LDAP_DEBUG_TRACE,
  1135.                "TLS trace: SSL3 alert %s:%s:%s\n",
  1136.                op,
  1137.                SSL_alert_type_string_long( ret ),
  1138.                SSL_alert_desc_string_long( ret) );
  1139.     } else if ( where & SSL_CB_EXIT ) {
  1140.                 if ( ret == 0 ) {
  1141.             Debug( LDAP_DEBUG_TRACE,
  1142.                    "TLS trace: %s:failed in %s\n",
  1143.                    op, SSL_state_string_long( ssl ), 0 );
  1144.                 } else if ( ret < 0 ) {
  1145.             Debug( LDAP_DEBUG_TRACE,
  1146.                    "TLS trace: %s:error in %s\n",
  1147.                    op, SSL_state_string_long( ssl ), 0 );
  1148.         }
  1149.     }
  1150. }
  1151.  
  1152. static int
  1153. tls_verify_cb( int ok, X509_STORE_CTX *ctx )
  1154. {
  1155.     X509 *cert;
  1156.     int errnum;
  1157.     int errdepth;
  1158.     X509_NAME *subject;
  1159.     X509_NAME *issuer;
  1160.     char *sname;
  1161.     char *iname;
  1162.  
  1163.     cert = X509_STORE_CTX_get_current_cert( ctx );
  1164.     errnum = X509_STORE_CTX_get_error( ctx );
  1165.     errdepth = X509_STORE_CTX_get_error_depth( ctx );
  1166.  
  1167.     /*
  1168.      * X509_get_*_name return pointers to the internal copies of
  1169.      * those things requested.  So do not free them.
  1170.      */
  1171.     subject = X509_get_subject_name( cert );
  1172.     issuer = X509_get_issuer_name( cert );
  1173.     /* X509_NAME_oneline, if passed a NULL buf, allocate memomry */
  1174.     sname = X509_NAME_oneline( subject, NULL, 0 );
  1175.     iname = X509_NAME_oneline( issuer, NULL, 0 );
  1176.     Debug( LDAP_DEBUG_TRACE,
  1177.            "TLS certificate verification: depth: %d, subject: %s, issuer: %s\n",
  1178.            errdepth,
  1179.            sname ? sname : "-unknown-",
  1180.            iname ? iname : "-unknown-" );
  1181.     if ( sname )
  1182.         CRYPTO_free ( sname );
  1183.     if ( iname )
  1184.         CRYPTO_free ( iname );
  1185.  
  1186.     return ok;
  1187. }
  1188.  
  1189. /* Inspired by ERR_print_errors in OpenSSL */
  1190. static void
  1191. tls_report_error( void )
  1192. {
  1193.         unsigned long l;
  1194.         char buf[200];
  1195.         const char *file;
  1196.         int line;
  1197.  
  1198.         while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
  1199.             Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
  1200.                    ERR_error_string( l, buf ), file, line );
  1201.         }
  1202. }
  1203.  
  1204. static RSA *
  1205. tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
  1206. {
  1207.     RSA *tmp_rsa;
  1208.  
  1209.     /* FIXME:  Pregenerate the key on startup */
  1210.     /* FIXME:  Who frees the key? */
  1211.     tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL );
  1212.  
  1213.     if ( !tmp_rsa ) {
  1214.         Debug( LDAP_DEBUG_ANY,
  1215.             "TLS: Failed to generate temporary %d-bit %s RSA key\n",
  1216.             key_length, is_export ? "export" : "domestic", 0 );
  1217.         return NULL;
  1218.     }
  1219.     return tmp_rsa;
  1220. }
  1221.  
  1222. static int
  1223. tls_seed_PRNG( const char *randfile )
  1224. {
  1225. #ifndef URANDOM_DEVICE
  1226.     /* no /dev/urandom (or equiv) */
  1227.     long total=0;
  1228.     char buffer[MAXPATHLEN];
  1229.  
  1230.     if (randfile == NULL) {
  1231.         /* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd.
  1232.          * If $HOME is not set or buffer too small to hold the pathname,
  1233.          * an error occurs.    - From RAND_file_name() man page.
  1234.          * The fact is that when $HOME is NULL, .rnd is used.
  1235.          */
  1236.         randfile = RAND_file_name( buffer, sizeof( buffer ) );
  1237.  
  1238.     } else if (RAND_egd(randfile) > 0) {
  1239.         /* EGD socket */
  1240.         return 0;
  1241.     }
  1242.  
  1243.     if (randfile == NULL) {
  1244.         Debug( LDAP_DEBUG_ANY,
  1245.             "TLS: Use configuration file or $RANDFILE to define seed PRNG\n",
  1246.             0, 0, 0);
  1247.         return -1;
  1248.     }
  1249.  
  1250.     total = RAND_load_file(randfile, -1);
  1251.  
  1252.     if (RAND_status() == 0) {
  1253.         Debug( LDAP_DEBUG_ANY,
  1254.             "TLS: PRNG not been seeded with enough data\n",
  1255.             0, 0, 0);
  1256.         return -1;
  1257.     }
  1258.  
  1259.     /* assume if there was enough bits to seed that it's okay
  1260.      * to write derived bits to the file
  1261.      */
  1262.     RAND_write_file(randfile);
  1263.  
  1264. #endif
  1265.  
  1266.     return 0;
  1267. }
  1268.  
  1269. #if 0
  1270. static DH *
  1271. tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
  1272. {
  1273.     return NULL;
  1274. }
  1275. #endif
  1276. #endif
  1277.  
  1278. int
  1279. ldap_start_tls_s ( LDAP *ld,
  1280.     LDAPControl **serverctrls,
  1281.     LDAPControl **clientctrls )
  1282. {
  1283.     int rc;
  1284.  
  1285. #ifdef HAVE_TLS
  1286.     char *rspoid = NULL;
  1287.     struct berval *rspdata = NULL;
  1288.  
  1289.     /* XXYYZ: this initiates operation only on default connection! */
  1290.  
  1291.     if ( ldap_pvt_tls_inplace( ld->ld_sb ) != 0 ) {
  1292.         return LDAP_LOCAL_ERROR;
  1293.     }
  1294.  
  1295.     rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS,
  1296.         NULL, serverctrls, clientctrls, &rspoid, &rspdata );
  1297.     if ( rc != LDAP_SUCCESS ) {
  1298.         return rc;
  1299.     }
  1300.  
  1301.     if ( rspoid != NULL ) {
  1302.         LDAP_FREE(rspoid);
  1303.     }
  1304.  
  1305.     if ( rspdata != NULL ) {
  1306.         ber_bvfree( rspdata );
  1307.     }
  1308.  
  1309.     rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL );
  1310. #else
  1311.     rc = LDAP_NOT_SUPPORTED;
  1312. #endif
  1313.     return rc;
  1314. }
  1315.  
  1316.