viossl.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Note that we can't have assertion on file descriptors;  The reason for
  15.   this is that during mysql shutdown, another thread can close a file
  16.   we are working on.  In this case we should just return read errors from
  17.   the file descriptior.
  18. */
  19. #include "vio_priv.h"
  20. #ifdef HAVE_OPENSSL
  21. #ifdef __NETWARE__
  22. /*
  23.   The default OpenSSL implementation on NetWare uses WinSock.
  24.   This code allows us to use the BSD sockets.
  25. */
  26. static int SSL_set_fd_bsd(SSL *s, int fd)
  27. {
  28.   int result= -1;
  29.   BIO_METHOD *BIO_s_bsdsocket();
  30.   BIO *bio;
  31.   if ((bio= BIO_new(BIO_s_bsdsocket())))
  32.   {
  33.     result= BIO_set_fd(bio, fd, BIO_NOCLOSE);
  34.     SSL_set_bio(s, bio, bio);
  35.   }
  36.   return result;
  37. }
  38. #define SSL_set_fd(A, B)  SSL_set_fd_bsd((A), (B))
  39. #endif /* __NETWARE__ */
  40. static void
  41. report_errors()
  42. {
  43.   unsigned long l;
  44.   const char* file;
  45.   const char* data;
  46.   int line,flags;
  47.   DBUG_ENTER("report_errors");
  48.   while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)))
  49.   {
  50.     char buf[512];
  51.     DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%sn", ERR_error_string(l,buf),
  52.  file,line,(flags&ERR_TXT_STRING)?data:"")) ;
  53.   }
  54.   DBUG_PRINT("info", ("errno: %d", socket_errno));
  55.   DBUG_VOID_RETURN;
  56. }
  57. int vio_ssl_errno(Vio *vio __attribute__((unused)))
  58. {
  59.   return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
  60. }
  61. int vio_ssl_read(Vio * vio, gptr buf, int size)
  62. {
  63.   int r;
  64.   DBUG_ENTER("vio_ssl_read");
  65.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d, ssl_=%p",
  66.        vio->sd, buf, size, vio->ssl_arg));
  67.   if ((r= SSL_read((SSL*) vio->ssl_arg, buf, size)) < 0)
  68.   {
  69.     int err= SSL_get_error((SSL*) vio->ssl_arg, r);
  70.     DBUG_PRINT("error",("SSL_read(): %d  SSL_get_error(): %d", r, err));
  71.     report_errors();
  72.   }
  73.   DBUG_PRINT("exit", ("%d", r));
  74.   DBUG_RETURN(r);
  75. }
  76. int vio_ssl_write(Vio * vio, const gptr buf, int size)
  77. {
  78.   int r;
  79.   DBUG_ENTER("vio_ssl_write");
  80.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  81.   if ((r= SSL_write((SSL*) vio->ssl_arg, buf, size)) < 0)
  82.     report_errors();
  83.   DBUG_PRINT("exit", ("%d", r));
  84.   DBUG_RETURN(r);
  85. }
  86. int vio_ssl_fastsend(Vio * vio __attribute__((unused)))
  87. {
  88.   int r=0;
  89.   DBUG_ENTER("vio_ssl_fastsend");
  90. #if defined(IPTOS_THROUGHPUT) && !defined(__EMX__)
  91.   {
  92.     int tos= IPTOS_THROUGHPUT;
  93.     r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
  94.   }
  95. #endif                                    /* IPTOS_THROUGHPUT && !__EMX__ */
  96.   if (!r)
  97.   {
  98. #ifdef __WIN__
  99.     BOOL nodelay= 1;
  100.     r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay,
  101.                   sizeof(nodelay));
  102. #else
  103.     int nodelay= 1;
  104.     r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,
  105.                   sizeof(nodelay));
  106. #endif                                          /* __WIN__ */
  107.   }
  108.   if (r)
  109.   {
  110.     DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
  111.     r= -1;
  112.   }
  113.   DBUG_PRINT("exit", ("%d", r));
  114.   DBUG_RETURN(r);
  115. }
  116. int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive)
  117. {
  118.   int r=0;
  119.   DBUG_ENTER("vio_ssl_keepalive");
  120.   DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
  121.        set_keep_alive));
  122.   if (vio->type != VIO_TYPE_NAMEDPIPE)
  123.   {
  124.     uint opt = (set_keep_alive) ? 1 : 0;
  125.     r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
  126.   sizeof(opt));
  127.   }
  128.   DBUG_RETURN(r);
  129. }
  130. my_bool
  131. vio_ssl_should_retry(Vio * vio __attribute__((unused)))
  132. {
  133.   int en = socket_errno;
  134.   return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
  135.   en == SOCKET_EWOULDBLOCK);
  136. }
  137. my_bool
  138. vio_ssl_was_interrupted(Vio *vio __attribute__((unused)))
  139. {
  140.   int en= socket_errno;
  141.   return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
  142.   en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
  143. }
  144. int vio_ssl_close(Vio * vio)
  145. {
  146.   int r;
  147.   DBUG_ENTER("vio_ssl_close");
  148.   r=0;
  149.   if ((SSL*) vio->ssl_arg)
  150.   {
  151.     r = SSL_shutdown((SSL*) vio->ssl_arg);
  152.     SSL_free((SSL*) vio->ssl_arg);
  153.     vio->ssl_arg= 0;
  154.   }
  155.   if (vio->sd >= 0)
  156.   {
  157.     if (shutdown(vio->sd, 2))
  158.       r= -1;
  159.     if (closesocket(vio->sd))
  160.       r= -1;
  161.   }
  162.   if (r)
  163.   {
  164.     DBUG_PRINT("error", ("close() failed, error: %d",socket_errno));
  165.     report_errors();
  166.     /* FIXME: error handling (not critical for MySQL) */
  167.   }
  168.   vio->type= VIO_CLOSED;
  169.   vio->sd=   -1;
  170.   DBUG_RETURN(r);
  171. }
  172. const char *vio_ssl_description(Vio * vio)
  173. {
  174.   return vio->desc;
  175. }
  176. enum enum_vio_type vio_ssl_type(Vio* vio)
  177. {
  178.   return vio->type;
  179. }
  180. my_socket vio_ssl_fd(Vio* vio)
  181. {
  182.   return vio->sd;
  183. }
  184. my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
  185. {
  186.   DBUG_ENTER("vio_ssl_peer_addr");
  187.   DBUG_PRINT("enter", ("sd=%d", vio->sd));
  188.   if (vio->localhost)
  189.   {
  190.     strmov(buf,"127.0.0.1");
  191.     *port=0;
  192.   }
  193.   else
  194.   {
  195.     size_socket addrLen = sizeof(struct sockaddr);
  196.     if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
  197.     &addrLen) != 0)
  198.     {
  199.       DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno));
  200.       DBUG_RETURN(1);
  201.     }
  202. #ifdef TO_BE_FIXED
  203.     my_inet_ntoa(vio->remote.sin_addr,buf);
  204.     *port= 0;
  205. #else
  206.     strmov(buf, "unknown");
  207.     *port= 0;
  208. #endif
  209.   }
  210.   DBUG_PRINT("exit", ("addr=%s", buf));
  211.   DBUG_RETURN(0);
  212. }
  213. void vio_ssl_in_addr(Vio *vio, struct in_addr *in)
  214. {
  215.   DBUG_ENTER("vio_ssl_in_addr");
  216.   if (vio->localhost)
  217.     bzero((char*) in, sizeof(*in));
  218.   else
  219.     *in=vio->remote.sin_addr;
  220.   DBUG_VOID_RETURN;
  221. }
  222. /*
  223.   TODO: Add documentation
  224. */
  225. int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
  226. {
  227.   char *str;
  228.   char buf[1024];
  229.   X509* client_cert;
  230.   my_bool unused;
  231.   my_bool net_blocking;
  232.   enum enum_vio_type old_type;  
  233.   DBUG_ENTER("sslaccept");
  234.   DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr));
  235.   old_type= vio->type;
  236.   net_blocking = vio_is_blocking(vio);
  237.   vio_blocking(vio, 1, &unused); /* Must be called before reset */
  238.   vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
  239.   vio->ssl_arg= 0;
  240.   if (!(vio->ssl_arg= (void*) SSL_new(ptr->ssl_context)))
  241.   {
  242.     DBUG_PRINT("error", ("SSL_new failure"));
  243.     report_errors();
  244.     vio_reset(vio, old_type,vio->sd,0,FALSE);
  245.     vio_blocking(vio, net_blocking, &unused);
  246.     DBUG_RETURN(1);
  247.   }
  248.   DBUG_PRINT("info", ("ssl_=%p  timeout=%ld",(SSL*) vio->ssl_arg, timeout));
  249.   SSL_clear((SSL*) vio->ssl_arg);
  250.   SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout);
  251.   SSL_set_fd((SSL*) vio->ssl_arg,vio->sd);
  252.   SSL_set_accept_state((SSL*) vio->ssl_arg);
  253.   if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1)
  254.   {
  255.     DBUG_PRINT("error", ("SSL_do_handshake failure"));
  256.     report_errors();
  257.     SSL_free((SSL*) vio->ssl_arg);
  258.     vio->ssl_arg= 0;
  259.     vio_reset(vio, old_type,vio->sd,0,FALSE);
  260.     vio_blocking(vio, net_blocking, &unused);
  261.     DBUG_RETURN(1);
  262.   }
  263. #ifndef DBUG_OFF
  264.   DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
  265.      ,SSL_get_cipher_name((SSL*) vio->ssl_arg)));
  266.   client_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg);
  267.   if (client_cert != NULL)
  268.   {
  269.     DBUG_PRINT("info",("Client certificate:"));
  270.     str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
  271.     DBUG_PRINT("info",("t subject: %s", str));
  272.     free (str);
  273.     str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);
  274.     DBUG_PRINT("info",("t issuer: %s", str));
  275.     free (str);
  276.     X509_free (client_cert);
  277.   }
  278.   else
  279.     DBUG_PRINT("info",("Client does not have certificate."));
  280.   str=SSL_get_shared_ciphers((SSL*) vio->ssl_arg, buf, sizeof(buf));
  281.   if (str)
  282.   {
  283.     DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str));
  284.   }
  285.   else
  286.   {
  287.     DBUG_PRINT("info",("no shared ciphers!"));
  288.   }
  289. #endif
  290.   DBUG_RETURN(0);
  291. }
  292. int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
  293. {
  294.   char *str;
  295.   X509*    server_cert;
  296.   my_bool unused;
  297.   my_bool net_blocking;
  298.   enum enum_vio_type old_type;  
  299.   DBUG_ENTER("sslconnect");
  300.   DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context));
  301.   old_type= vio->type;
  302.   net_blocking = vio_is_blocking(vio);
  303.   vio_blocking(vio, 1, &unused); /* Must be called before reset */
  304.   vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
  305.   vio->ssl_arg= 0;
  306.   if (!(vio->ssl_arg = SSL_new(ptr->ssl_context)))
  307.   {
  308.     DBUG_PRINT("error", ("SSL_new failure"));
  309.     report_errors();
  310.     vio_reset(vio, old_type,vio->sd,0,FALSE);
  311.     vio_blocking(vio, net_blocking, &unused);    
  312.     DBUG_RETURN(1);
  313.   }
  314.   DBUG_PRINT("info", ("ssl_=%p  timeout=%ld",(SSL*) vio->ssl_arg, timeout));
  315.   SSL_clear((SSL*) vio->ssl_arg);
  316.   SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout);
  317.   SSL_set_fd ((SSL*) vio->ssl_arg, vio->sd);
  318.   SSL_set_connect_state((SSL*) vio->ssl_arg);
  319.   if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1)
  320.   {
  321.     DBUG_PRINT("error", ("SSL_do_handshake failure"));
  322.     report_errors();
  323.     SSL_free((SSL*) vio->ssl_arg);
  324.     vio->ssl_arg= 0;
  325.     vio_reset(vio, old_type,vio->sd,0,FALSE);
  326.     vio_blocking(vio, net_blocking, &unused);
  327.     DBUG_RETURN(1);
  328.   }  
  329. #ifndef DBUG_OFF
  330.   DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
  331.      ,SSL_get_cipher_name((SSL*) vio->ssl_arg)));
  332.   server_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg);
  333.   if (server_cert != NULL)
  334.   {
  335.     DBUG_PRINT("info",("Server certificate:"));
  336.     str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0);
  337.     DBUG_PRINT("info",("t subject: %s", str));
  338.     free(str);
  339.     str = X509_NAME_oneline (X509_get_issuer_name  (server_cert), 0, 0);
  340.     DBUG_PRINT("info",("t issuer: %s", str));
  341.     free(str);
  342.     /*
  343.       We could do all sorts of certificate verification stuff here before
  344.       deallocating the certificate.
  345.     */
  346.     X509_free (server_cert);
  347.   }
  348.   else
  349.     DBUG_PRINT("info",("Server does not have certificate."));
  350. #endif
  351.   DBUG_RETURN(0);
  352. }
  353. int vio_ssl_blocking(Vio * vio __attribute__((unused)),
  354.      my_bool set_blocking_mode,
  355.      my_bool *old_mode)
  356. {
  357.   /* Return error if we try to change to non_blocking mode */
  358.   *old_mode=1; /* Mode is always blocking */
  359.   return set_blocking_mode ? 0 : 1;
  360. }
  361. void vio_ssl_timeout(Vio *vio __attribute__((unused)),
  362.      uint which __attribute__((unused)),
  363.                      uint timeout __attribute__((unused)))
  364. {
  365. #ifdef __WIN__
  366.   ulong wait_timeout= (ulong) timeout * 1000;
  367.   (void) setsockopt(vio->sd, SOL_SOCKET,
  368. which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout,
  369.         sizeof(wait_timeout));
  370. #endif /* __WIN__ */
  371. }
  372. #endif /* HAVE_OPENSSL */