ssl.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:19k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2. Note that this code interfaces with with the OpenSSL
  4.  * libraries, so please read LICENSE where I give explicit permission to link
  5.  * against the OpenSSL libraries.
  6.  * Author: Chris Evans
  7.  * ssl.c
  8.  *
  9.  * Routines to handle a SSL/TLS-based implementation of RFC 2228, i.e.
  10.  * encryption.
  11.  */
  12. #include "ssl.h"
  13. #include "session.h"
  14. #include "ftpcodes.h"
  15. #include "ftpcmdio.h"
  16. #include "defs.h"
  17. #include "str.h"
  18. #include "sysutil.h"
  19. #include "tunables.h"
  20. #include "utility.h"
  21. #include "builddefs.h"
  22. #include "logging.h"
  23. #ifdef VSF_BUILD_SSL
  24. #include <openssl/ssl.h>
  25. #include <openssl/err.h>
  26. #include <openssl/rand.h>
  27. #include <openssl/bio.h>
  28. #include <errno.h>
  29. #include <limits.h>
  30. static char* get_ssl_error();
  31. static SSL* get_ssl(struct vsf_session* p_sess, int fd);
  32. static int ssl_session_init(struct vsf_session* p_sess);
  33. static void setup_bio_callbacks();
  34. static long bio_callback(
  35.   BIO* p_bio, int oper, const char* p_arg, int argi, long argl, long retval);
  36. static int ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx);
  37. static int ssl_cert_digest(
  38.   SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str);
  39. static void maybe_log_shutdown_state(struct vsf_session* p_sess);
  40. static void maybe_log_ssl_error_state(struct vsf_session* p_sess, int ret);
  41. static int ssl_read_common(struct vsf_session* p_sess,
  42.                            SSL* p_ssl,
  43.                            char* p_buf,
  44.                            unsigned int len,
  45.                            int (*p_ssl_func)(SSL*, void*, int));
  46. static int ssl_inited;
  47. static struct mystr debug_str;
  48. void
  49. ssl_init(struct vsf_session* p_sess)
  50. {
  51.   if (!ssl_inited)
  52.   {
  53.     SSL_CTX* p_ctx;
  54.     long options;
  55.     int verify_option = 0;
  56.     SSL_library_init();
  57.     p_ctx = SSL_CTX_new(SSLv23_server_method());
  58.     if (p_ctx == NULL)
  59.     {
  60.       die("SSL: could not allocate SSL context");
  61.     }
  62.     options = SSL_OP_ALL;
  63.     if (!tunable_sslv2)
  64.     {
  65.       options |= SSL_OP_NO_SSLv2;
  66.     }
  67.     if (!tunable_sslv3)
  68.     {
  69.       options |= SSL_OP_NO_SSLv3;
  70.     }
  71.     if (!tunable_tlsv1)
  72.     {
  73.       options |= SSL_OP_NO_TLSv1;
  74.     }
  75.     SSL_CTX_set_options(p_ctx, options);
  76.     if (tunable_rsa_cert_file)
  77.     {
  78.       const char* p_key = tunable_rsa_private_key_file;
  79.       if (!p_key)
  80.       {
  81.         p_key = tunable_rsa_cert_file;
  82.       }
  83.       if (SSL_CTX_use_certificate_chain_file(p_ctx, tunable_rsa_cert_file) != 1)
  84.       {
  85.         die("SSL: cannot load RSA certificate");
  86.       }
  87.       if (SSL_CTX_use_PrivateKey_file(p_ctx, p_key, X509_FILETYPE_PEM) != 1)
  88.       {
  89.         die("SSL: cannot load RSA private key");
  90.       }
  91.     }
  92.     if (tunable_dsa_cert_file)
  93.     {
  94.       const char* p_key = tunable_dsa_private_key_file;
  95.       if (!p_key)
  96.       {
  97.         p_key = tunable_dsa_cert_file;
  98.       }
  99.       if (SSL_CTX_use_certificate_chain_file(p_ctx, tunable_dsa_cert_file) != 1)
  100.       {
  101.         die("SSL: cannot load DSA certificate");
  102.       }
  103.       if (SSL_CTX_use_PrivateKey_file(p_ctx, p_key, X509_FILETYPE_PEM) != 1)
  104.       {
  105.         die("SSL: cannot load DSA private key");
  106.       }
  107.     }
  108.     if (tunable_ssl_ciphers &&
  109.         SSL_CTX_set_cipher_list(p_ctx, tunable_ssl_ciphers) != 1)
  110.     {
  111.       die("SSL: could not set cipher list");
  112.     }
  113.     if (RAND_status() != 1)
  114.     {
  115.       die("SSL: RNG is not seeded");
  116.     }
  117.     if (tunable_ssl_request_cert)
  118.     {
  119.       verify_option |= SSL_VERIFY_PEER;
  120.     }
  121.     if (tunable_require_cert)
  122.     {
  123.       verify_option |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  124.     }
  125.     if (verify_option)
  126.     {
  127.       SSL_CTX_set_verify(p_ctx, verify_option, ssl_verify_callback);
  128.       if (tunable_ca_certs_file)
  129.       {
  130.         STACK_OF(X509_NAME)* p_names;
  131.         if (!SSL_CTX_load_verify_locations(p_ctx, tunable_ca_certs_file, NULL))
  132.         {
  133.           die("SSL: could not load verify file");
  134.         }
  135.         p_names = SSL_load_client_CA_file(tunable_ca_certs_file);
  136.         if (!p_names)
  137.         {
  138.           die("SSL: could not load client certs file");
  139.         }
  140.         SSL_CTX_set_client_CA_list(p_ctx, p_names);
  141.       }
  142.     }
  143.     {
  144.       static const char* p_ctx_id = "vsftpd";
  145.       SSL_CTX_set_session_id_context(p_ctx, (void*) p_ctx_id,
  146.                                      vsf_sysutil_strlen(p_ctx_id));
  147.     }
  148.     if (tunable_require_ssl_reuse)
  149.     {
  150.       /* Ensure cached session doesn't expire */
  151.       SSL_CTX_set_timeout(p_ctx, INT_MAX);
  152.     }
  153.     p_sess->p_ssl_ctx = p_ctx;
  154.     ssl_inited = 1;
  155.   }
  156. }
  157. void
  158. ssl_control_handshake(struct vsf_session* p_sess)
  159. {
  160.   if (!ssl_session_init(p_sess))
  161.   {
  162.     struct mystr err_str = INIT_MYSTR;
  163.     str_alloc_text(&err_str, "Negotiation failed: ");
  164.     /* Technically, we shouldn't leak such detailed error messages. */
  165.     str_append_text(&err_str, get_ssl_error());
  166.     vsf_cmdio_write_str(p_sess, FTP_TLS_FAIL, &err_str);
  167.     vsf_sysutil_exit(0);
  168.   }
  169.   p_sess->control_use_ssl = 1;
  170. }
  171. void
  172. handle_auth(struct vsf_session* p_sess)
  173. {
  174.   str_upper(&p_sess->ftp_arg_str);
  175.   if (str_equal_text(&p_sess->ftp_arg_str, "TLS") ||
  176.       str_equal_text(&p_sess->ftp_arg_str, "TLS-C") ||
  177.       str_equal_text(&p_sess->ftp_arg_str, "SSL") ||
  178.       str_equal_text(&p_sess->ftp_arg_str, "TLS-P"))
  179.   {
  180.     vsf_cmdio_write(p_sess, FTP_AUTHOK, "Proceed with negotiation.");
  181.     ssl_control_handshake(p_sess);
  182.     if (str_equal_text(&p_sess->ftp_arg_str, "SSL") ||
  183.         str_equal_text(&p_sess->ftp_arg_str, "TLS-P"))
  184.     {
  185.       p_sess->data_use_ssl = 1;
  186.     }
  187.   }
  188.   else
  189.   {
  190.     vsf_cmdio_write(p_sess, FTP_BADAUTH, "Unknown AUTH type.");
  191.   }
  192. }
  193. void
  194. handle_pbsz(struct vsf_session* p_sess)
  195. {
  196.   if (!p_sess->control_use_ssl)
  197.   {
  198.     vsf_cmdio_write(p_sess, FTP_BADPBSZ, "PBSZ needs a secure connection.");
  199.   }
  200.   else
  201.   {
  202.     vsf_cmdio_write(p_sess, FTP_PBSZOK, "PBSZ set to 0.");
  203.   }
  204. }
  205. void
  206. handle_prot(struct vsf_session* p_sess)
  207. {
  208.   str_upper(&p_sess->ftp_arg_str);
  209.   if (!p_sess->control_use_ssl)
  210.   {
  211.     vsf_cmdio_write(p_sess, FTP_BADPROT, "PROT needs a secure connection.");
  212.   }
  213.   else if (str_equal_text(&p_sess->ftp_arg_str, "C"))
  214.   {
  215.     p_sess->data_use_ssl = 0;
  216.     vsf_cmdio_write(p_sess, FTP_PROTOK, "PROT now Clear.");
  217.   }
  218.   else if (str_equal_text(&p_sess->ftp_arg_str, "P"))
  219.   {
  220.     p_sess->data_use_ssl = 1;
  221.     vsf_cmdio_write(p_sess, FTP_PROTOK, "PROT now Private.");
  222.   }
  223.   else if (str_equal_text(&p_sess->ftp_arg_str, "S") ||
  224.            str_equal_text(&p_sess->ftp_arg_str, "E"))
  225.   {
  226.     vsf_cmdio_write(p_sess, FTP_NOHANDLEPROT, "PROT not supported.");
  227.   }
  228.   else
  229.   {
  230.     vsf_cmdio_write(p_sess, FTP_NOSUCHPROT, "PROT not recognized.");
  231.   }
  232. }
  233. int
  234. ssl_read(struct vsf_session* p_sess, void* p_ssl, char* p_buf, unsigned int len)
  235. {
  236.   return ssl_read_common(p_sess, (SSL*) p_ssl, p_buf, len, SSL_read);
  237. }
  238. int
  239. ssl_peek(struct vsf_session* p_sess, void* p_ssl, char* p_buf, unsigned int len)
  240. {
  241.   return ssl_read_common(p_sess, (SSL*) p_ssl, p_buf, len, SSL_peek);
  242. }
  243. static int
  244. ssl_read_common(struct vsf_session* p_sess,
  245.                 SSL* p_void_ssl,
  246.                 char* p_buf,
  247.                 unsigned int len,
  248.                 int (*p_ssl_func)(SSL*, void*, int))
  249. {
  250.   int retval;
  251.   int err;
  252.   SSL* p_ssl = (SSL*) p_void_ssl;
  253.   do
  254.   {
  255.     retval = (*p_ssl_func)(p_ssl, p_buf, len);
  256.     err = SSL_get_error(p_ssl, retval);
  257.   }
  258.   while (retval < 0 && (err == SSL_ERROR_WANT_READ ||
  259.                         err == SSL_ERROR_WANT_WRITE));
  260.   /* If we hit an EOF, make sure it was from the peer, not injected by the
  261.    * attacker.
  262.    */
  263.   if (retval == 0 && SSL_get_shutdown(p_ssl) != SSL_RECEIVED_SHUTDOWN)
  264.   {
  265.     str_alloc_text(&debug_str, "Connection terminated without SSL shutdown "
  266.                                "- buggy client?");
  267.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  268.     if (tunable_strict_ssl_read_eof)
  269.     {
  270.       return -1;
  271.     }
  272.   }
  273.   return retval;
  274. }
  275. int
  276. ssl_write(void* p_ssl, const char* p_buf, unsigned int len)
  277. {
  278.   int retval;
  279.   int err;
  280.   do
  281.   {
  282.     retval = SSL_write((SSL*) p_ssl, p_buf, len);
  283.     err = SSL_get_error((SSL*) p_ssl, retval);
  284.   }
  285.   while (retval < 0 && (err == SSL_ERROR_WANT_READ ||
  286.                         err == SSL_ERROR_WANT_WRITE));
  287.   return retval;
  288. }
  289. int
  290. ssl_write_str(void* p_ssl, const struct mystr* p_str)
  291. {
  292.   unsigned int len = str_getlen(p_str);
  293.   int ret = SSL_write((SSL*) p_ssl, str_getbuf(p_str), len);
  294.   if ((unsigned int) ret != len)
  295.   {
  296.     return -1;
  297.   }
  298.   return 0;
  299. }
  300. int
  301. ssl_read_into_str(struct vsf_session* p_sess, void* p_ssl, struct mystr* p_str)
  302. {
  303.   unsigned int len = str_getlen(p_str);
  304.   int ret = ssl_read(p_sess, p_ssl, (char*) str_getbuf(p_str), len);
  305.   if (ret >= 0)
  306.   {
  307.     str_trunc(p_str, (unsigned int) ret);
  308.   }
  309.   else
  310.   {
  311.     str_empty(p_str);
  312.   }
  313.   return ret;
  314. }
  315. static void
  316. maybe_log_shutdown_state(struct vsf_session* p_sess)
  317. {
  318.   if (tunable_debug_ssl)
  319.   {
  320.     int ret = SSL_get_shutdown(p_sess->p_data_ssl);
  321.     str_alloc_text(&debug_str, "SSL shutdown state is: ");
  322.     if (ret == 0)
  323.     {
  324.       str_append_text(&debug_str, "NONE");
  325.     }
  326.     else if (ret == SSL_SENT_SHUTDOWN)
  327.     {
  328.       str_append_text(&debug_str, "SSL_SENT_SHUTDOWN");
  329.     }
  330.     else if (ret == SSL_RECEIVED_SHUTDOWN)
  331.     {
  332.       str_append_text(&debug_str, "SSL_RECEIVED_SHUTDOWN");
  333.     }
  334.     else
  335.     {
  336.       str_append_ulong(&debug_str, ret);
  337.     }
  338.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  339.   }
  340. }
  341. static void
  342. maybe_log_ssl_error_state(struct vsf_session* p_sess, int ret)
  343. {
  344.   if (tunable_debug_ssl)
  345.   {
  346.     str_alloc_text(&debug_str, "SSL ret: ");
  347.     str_append_ulong(&debug_str, ret);
  348.     str_append_text(&debug_str, ", SSL error: ");
  349.     str_append_text(&debug_str, get_ssl_error());
  350.     str_append_text(&debug_str, ", errno: ");
  351.     str_append_ulong(&debug_str, errno);
  352.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  353.   }
  354. }
  355. int
  356. ssl_data_close(struct vsf_session* p_sess)
  357. {
  358.   int success = 1;
  359.   SSL* p_ssl = p_sess->p_data_ssl;
  360.   if (p_ssl)
  361.   {
  362.     int ret;
  363.     maybe_log_shutdown_state(p_sess);
  364.     /* This is a mess. Ideally, when we're the sender, we'd like to get to the
  365.      * SSL_RECEIVED_SHUTDOWN state to get a cryptographic guarantee that the
  366.      * peer received all the data and shut the connection down cleanly. It
  367.      * doesn't matter hugely apart from logging, but it's a nagging detail.
  368.      * Unfortunately, no FTP client I found was able to get sends into that
  369.      * state, so the best we can do is issue SSL_shutdown but not check the
  370.      * errors / returns. At least this enables the receiver to be sure of the
  371.      * integrity of the send in terms of unwanted truncation.
  372.      */
  373.     ret = SSL_shutdown(p_ssl);
  374.     maybe_log_shutdown_state(p_sess);
  375.     if (ret == 0)
  376.     {
  377.       ret = SSL_shutdown(p_ssl);
  378.       maybe_log_shutdown_state(p_sess);
  379.       if (ret != 1)
  380.       {
  381.         if (tunable_strict_ssl_write_shutdown)
  382.         {
  383.           success = 0;
  384.         }
  385.         maybe_log_shutdown_state(p_sess);
  386.         maybe_log_ssl_error_state(p_sess, ret);
  387.       }
  388.     }
  389.     else if (ret < 0)
  390.     {
  391.       if (tunable_strict_ssl_write_shutdown)
  392.       {
  393.         success = 0;
  394.       }
  395.       maybe_log_ssl_error_state(p_sess, ret);
  396.     }
  397.     SSL_free(p_ssl);
  398.     p_sess->p_data_ssl = NULL;
  399.   }
  400.   return success;
  401. }
  402. int
  403. ssl_accept(struct vsf_session* p_sess, int fd)
  404. {
  405.   /* SECURITY: data SSL connections don't have any auth on them as part of the
  406.    * protocol. If a client sends an unfortunately optional client cert then
  407.    * we can check for a match between the control and data connections.
  408.    */
  409.   SSL* p_ssl;
  410.   int reused;
  411.   if (p_sess->p_data_ssl != NULL)
  412.   {
  413.     die("p_data_ssl should be NULL.");
  414.   }
  415.   p_ssl = get_ssl(p_sess, fd);
  416.   if (p_ssl == NULL)
  417.   {
  418.     return 0;
  419.   }
  420.   p_sess->p_data_ssl = p_ssl;
  421.   setup_bio_callbacks(p_ssl);
  422.   reused = SSL_session_reused(p_ssl);
  423.   if (tunable_require_ssl_reuse && !reused)
  424.   {
  425.     str_alloc_text(&debug_str, "No SSL session reuse on data channel.");
  426.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  427.     ssl_data_close(p_sess);
  428.     return 0;
  429.   }
  430.   if (str_getlen(&p_sess->control_cert_digest) > 0)
  431.   {
  432.     static struct mystr data_cert_digest;
  433.     if (!ssl_cert_digest(p_ssl, p_sess, &data_cert_digest))
  434.     {
  435.       str_alloc_text(&debug_str, "Missing cert on data channel.");
  436.       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  437.       ssl_data_close(p_sess);
  438.       return 0;
  439.     }
  440.     if (str_strcmp(&p_sess->control_cert_digest, &data_cert_digest))
  441.     {
  442.       str_alloc_text(&debug_str, "DIFFERENT cert on data channel.");
  443.       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  444.       ssl_data_close(p_sess);
  445.       return 0;
  446.     }
  447.     if (tunable_debug_ssl)
  448.     {
  449.       str_alloc_text(&debug_str, "Matching cert on data channel.");
  450.       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  451.     }
  452.   }
  453.   return 1;
  454. }
  455. void
  456. ssl_comm_channel_init(struct vsf_session* p_sess)
  457. {
  458.   if (p_sess->ssl_consumer_fd != -1)
  459.   {
  460.     bug("ssl_consumer_fd active");
  461.   }
  462.   if (p_sess->ssl_slave_fd != -1)
  463.   {
  464.     bug("ssl_slave_fd active");
  465.   }
  466.   const struct vsf_sysutil_socketpair_retval retval =
  467.     vsf_sysutil_unix_stream_socketpair();
  468.   p_sess->ssl_consumer_fd = retval.socket_one;
  469.   p_sess->ssl_slave_fd = retval.socket_two;
  470. }
  471. void
  472. ssl_comm_channel_set_consumer_context(struct vsf_session* p_sess)
  473. {
  474.   if (p_sess->ssl_slave_fd == -1)
  475.   {
  476.     bug("ssl_slave_fd already closed");
  477.   }
  478.   vsf_sysutil_close(p_sess->ssl_slave_fd);
  479.   p_sess->ssl_slave_fd = -1;
  480. }
  481. void
  482. ssl_comm_channel_set_producer_context(struct vsf_session* p_sess)
  483. {
  484.   if (p_sess->ssl_consumer_fd == -1)
  485.   {
  486.     bug("ssl_consumer_fd already closed");
  487.   }
  488.   vsf_sysutil_close(p_sess->ssl_consumer_fd);
  489.   p_sess->ssl_consumer_fd = -1;
  490. }
  491. static SSL*
  492. get_ssl(struct vsf_session* p_sess, int fd)
  493. {
  494.   SSL* p_ssl = SSL_new(p_sess->p_ssl_ctx);
  495.   if (p_ssl == NULL)
  496.   {
  497.     if (tunable_debug_ssl)
  498.     {
  499.       str_alloc_text(&debug_str, "SSL_new failed");
  500.       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  501.     }
  502.     return NULL;
  503.   }
  504.   if (!SSL_set_fd(p_ssl, fd))
  505.   {
  506.     if (tunable_debug_ssl)
  507.     {
  508.       str_alloc_text(&debug_str, "SSL_set_fd failed");
  509.       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  510.     }
  511.     SSL_free(p_ssl);
  512.     return NULL;
  513.   }
  514.   if (SSL_accept(p_ssl) != 1)
  515.   {
  516.     const char* p_err = get_ssl_error();
  517.     if (tunable_debug_ssl)
  518.     {
  519.       str_alloc_text(&debug_str, "SSL_accept failed: ");
  520.       str_append_text(&debug_str, p_err);
  521.       vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  522.     }
  523.     /* The RFC is quite clear that we can just close the control channel
  524.      * here.
  525.      */
  526.     die(p_err);
  527.   }
  528.   if (tunable_debug_ssl)
  529.   {
  530.     const char* p_ssl_version = SSL_get_cipher_version(p_ssl);
  531.     SSL_CIPHER* p_ssl_cipher = SSL_get_current_cipher(p_ssl);
  532.     const char* p_cipher_name = SSL_CIPHER_get_name(p_ssl_cipher);
  533.     X509* p_ssl_cert = SSL_get_peer_certificate(p_ssl);
  534.     int reused = SSL_session_reused(p_ssl);
  535.     str_alloc_text(&debug_str, "SSL version: ");
  536.     str_append_text(&debug_str, p_ssl_version);
  537.     str_append_text(&debug_str, ", SSL cipher: ");
  538.     str_append_text(&debug_str, p_cipher_name);
  539.     if (reused)
  540.     {
  541.       str_append_text(&debug_str, ", reused");
  542.     }
  543.     else
  544.     {
  545.       str_append_text(&debug_str, ", not reused");
  546.     }
  547.     if (p_ssl_cert != NULL)
  548.     {
  549.       str_append_text(&debug_str, ", CERT PRESENTED");
  550.       X509_free(p_ssl_cert);
  551.     }
  552.     else
  553.     {
  554.       str_append_text(&debug_str, ", no cert");
  555.     }
  556.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  557.   }
  558.   return p_ssl;
  559. }
  560. static int
  561. ssl_session_init(struct vsf_session* p_sess)
  562. {
  563.   SSL* p_ssl = get_ssl(p_sess, VSFTP_COMMAND_FD);
  564.   if (p_ssl == NULL)
  565.   {
  566.     return 0;
  567.   }
  568.   p_sess->p_control_ssl = p_ssl;
  569.   (void) ssl_cert_digest(p_ssl, p_sess, &p_sess->control_cert_digest);
  570.   setup_bio_callbacks(p_ssl);
  571.   return 1;
  572. }
  573. static int
  574. ssl_cert_digest(SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str)
  575. {
  576.   X509* p_cert = SSL_get_peer_certificate(p_ssl);
  577.   unsigned int num_bytes = 0;
  578.   if (p_cert == NULL)
  579.   {
  580.     return 0;
  581.   }
  582.   str_reserve(p_str, EVP_MAX_MD_SIZE);
  583.   str_empty(p_str);
  584.   str_rpad(p_str, EVP_MAX_MD_SIZE);
  585.   if (!X509_digest(p_cert, EVP_sha256(), (unsigned char*) str_getbuf(p_str),
  586.                    &num_bytes))
  587.   {
  588.     die("X509_digest failed");
  589.   }
  590.   X509_free(p_cert);
  591.   if (tunable_debug_ssl)
  592.   {
  593.     unsigned int i;
  594.     str_alloc_text(&debug_str, "Cert digest:");
  595.     for (i = 0; i < num_bytes; ++i)
  596.     { 
  597.       str_append_char(&debug_str, ' ');
  598.       str_append_ulong(
  599.         &debug_str, (unsigned long) (unsigned char) str_get_char_at(p_str, i));
  600.     }
  601.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  602.   }
  603.   str_trunc(p_str, num_bytes);
  604.   return 1;
  605. }
  606. static char*
  607. get_ssl_error()
  608. {
  609.   SSL_load_error_strings();
  610.   return ERR_error_string(ERR_get_error(), NULL);
  611. }
  612. static void setup_bio_callbacks(SSL* p_ssl)
  613. {
  614.   BIO* p_bio = SSL_get_rbio(p_ssl);
  615.   BIO_set_callback(p_bio, bio_callback);
  616.   p_bio = SSL_get_wbio(p_ssl);
  617.   BIO_set_callback(p_bio, bio_callback);
  618. }
  619. static long
  620. bio_callback(
  621.   BIO* p_bio, int oper, const char* p_arg, int argi, long argl, long ret)
  622. {
  623.   int retval = 0;
  624.   int fd = 0;
  625.   (void) p_arg;
  626.   (void) argi;
  627.   (void) argl;
  628.   if (oper == (BIO_CB_READ | BIO_CB_RETURN) ||
  629.       oper == (BIO_CB_WRITE | BIO_CB_RETURN))
  630.   {
  631.     retval = (int) ret;
  632.     fd = BIO_get_fd(p_bio, NULL);
  633.   }
  634.   vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
  635.   return ret;
  636. }
  637. static int
  638. ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx)
  639. {
  640.   (void) p_ctx;
  641.   if (tunable_validate_cert)
  642.   {
  643.     return verify_ok;
  644.   }
  645.   return 1;
  646. }
  647. void
  648. ssl_add_entropy(struct vsf_session* p_sess)
  649. {
  650.   /* Although each child does seem to have its different pool of entropy, I
  651.    * don't trust the interaction of OpenSSL's opaque RAND API and fork(). So
  652.    * throw a bit more in (only works on systems with /dev/urandom for now).
  653.    */
  654.   int ret = RAND_load_file("/dev/urandom", 16);
  655.   if (ret != 16)
  656.   {
  657.     str_alloc_text(&debug_str, "Couldn't add extra OpenSSL entropy: ");
  658.     str_append_ulong(&debug_str, (unsigned long) ret);
  659.     vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
  660.   }
  661. }
  662. #else /* VSF_BUILD_SSL */
  663. void
  664. ssl_init(struct vsf_session* p_sess)
  665. {
  666.   (void) p_sess;
  667.   die("SSL: ssl_enable is set but SSL support not compiled in");
  668. }
  669. void
  670. ssl_control_handshake(struct vsf_session* p_sess)
  671. {
  672.   (void) p_sess;
  673. }
  674. void
  675. handle_auth(struct vsf_session* p_sess)
  676. {
  677.   (void) p_sess;
  678. }
  679. void
  680. handle_pbsz(struct vsf_session* p_sess)
  681. {
  682.   (void) p_sess;
  683. }
  684. void
  685. handle_prot(struct vsf_session* p_sess)
  686. {
  687.   (void) p_sess;
  688. }
  689. int
  690. ssl_read(struct vsf_session* p_sess, void* p_ssl, char* p_buf, unsigned int len)
  691. {
  692.   (void) p_sess;
  693.   (void) p_ssl;
  694.   (void) p_buf;
  695.   (void) len;
  696.   return -1;
  697. }
  698. int
  699. ssl_peek(struct vsf_session* p_sess, void* p_ssl, char* p_buf, unsigned int len)
  700. {
  701.   (void) p_sess;
  702.   (void) p_ssl;
  703.   (void) p_buf;
  704.   (void) len;
  705.   return -1;
  706. }
  707. int
  708. ssl_write(void* p_ssl, const char* p_buf, unsigned int len)
  709. {
  710.   (void) p_ssl;
  711.   (void) p_buf;
  712.   (void) len;
  713.   return -1;
  714. }
  715. int
  716. ssl_write_str(void* p_ssl, const struct mystr* p_str)
  717. {
  718.   (void) p_ssl;
  719.   (void) p_str;
  720.   return -1;
  721. }
  722. int
  723. ssl_accept(struct vsf_session* p_sess, int fd)
  724. {
  725.   (void) p_sess;
  726.   (void) fd;
  727.   return -1;
  728. }
  729. int
  730. ssl_data_close(struct vsf_session* p_sess)
  731. {
  732.   (void) p_sess;
  733.   return 1;
  734. }
  735. void
  736. ssl_comm_channel_init(struct vsf_session* p_sess)
  737. {
  738.   (void) p_sess;
  739. }
  740. void
  741. ssl_comm_channel_set_consumer_context(struct vsf_session* p_sess)
  742. {
  743.   (void) p_sess;
  744. }
  745. void
  746. ssl_comm_channel_set_producer_context(struct vsf_session* p_sess)
  747. {
  748.   (void) p_sess;
  749. }
  750. void
  751. ssl_add_entropy(struct vsf_session* p_sess)
  752. {
  753.   (void) p_sess;
  754. }
  755. int
  756. ssl_read_into_str(struct vsf_session* p_sess, void* p_ssl, struct mystr* p_str)
  757. {
  758.   (void) p_sess;
  759.   (void) p_ssl;
  760.   (void) p_str;
  761.   return -1;
  762. }
  763. #endif /* VSF_BUILD_SSL */