1 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
15 
16 /*
17   Note that we can't have assertion on file descriptors;  The reason for
18   this is that during mysql shutdown, another thread can close a file
19   we are working on.  In this case we should just return read errors from
20   the file descriptior.
21 */
22 
23 #include "vio_priv.h"
24 
25 #ifdef HAVE_OPENSSL
26 
27 #ifndef DBUG_OFF
28 
29 static void
report_errors(SSL * ssl)30 report_errors(SSL* ssl)
31 {
32   unsigned long	l;
33   const char *file;
34   const char *data;
35   int line, flags;
36   char buf[512];
37 
38   DBUG_ENTER("report_errors");
39 
40   while ((l= ERR_get_error_line_data(&file,&line,&data,&flags)))
41   {
42     DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
43 			 file,line,(flags&ERR_TXT_STRING)?data:"")) ;
44   }
45 
46   if (ssl)
47     DBUG_PRINT("error", ("error: %s",
48                          ERR_error_string(SSL_get_error(ssl, l), buf)));
49 
50   DBUG_PRINT("info", ("socket_errno: %d", socket_errno));
51   DBUG_VOID_RETURN;
52 }
53 
54 #endif
55 
56 
vio_ssl_read(Vio * vio,uchar * buf,size_t size)57 size_t vio_ssl_read(Vio *vio, uchar* buf, size_t size)
58 {
59   size_t r;
60   DBUG_ENTER("vio_ssl_read");
61   DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u  ssl: 0x%lx",
62 		       vio->sd, (long) buf, (uint) size, (long) vio->ssl_arg));
63 
64   r= SSL_read((SSL*) vio->ssl_arg, buf, size);
65 #ifndef DBUG_OFF
66   if (r == (size_t) -1)
67     report_errors((SSL*) vio->ssl_arg);
68 #endif
69   DBUG_PRINT("exit", ("%u", (uint) r));
70   DBUG_RETURN(r);
71 }
72 
73 
vio_ssl_write(Vio * vio,const uchar * buf,size_t size)74 size_t vio_ssl_write(Vio *vio, const uchar* buf, size_t size)
75 {
76   size_t r;
77   DBUG_ENTER("vio_ssl_write");
78   DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd,
79                        (long) buf, (uint) size));
80 
81   r= SSL_write((SSL*) vio->ssl_arg, buf, size);
82 #ifndef DBUG_OFF
83   if (r == (size_t) -1)
84     report_errors((SSL*) vio->ssl_arg);
85 #endif
86   DBUG_PRINT("exit", ("%u", (uint) r));
87   DBUG_RETURN(r);
88 }
89 
90 
vio_ssl_close(Vio * vio)91 int vio_ssl_close(Vio *vio)
92 {
93   int r= 0;
94   SSL *ssl= (SSL*)vio->ssl_arg;
95   DBUG_ENTER("vio_ssl_close");
96 
97   if (ssl)
98   {
99     /*
100     THE SSL standard says that SSL sockets must send and receive a close_notify
101     alert on socket shutdown to avoid truncation attacks. However, this can
102     cause problems since we often hold a lock during shutdown and this IO can
103     take an unbounded amount of time to complete. Since our packets are self
104     describing with length, we aren't vunerable to these attacks. Therefore,
105     we just shutdown by closing the socket (quiet shutdown).
106     */
107     SSL_set_quiet_shutdown(ssl, 1);
108 
109     switch ((r= SSL_shutdown(ssl))) {
110     case 1:
111       /* Shutdown successful */
112       break;
113     case 0:
114       /*
115         Shutdown not yet finished - since the socket is going to
116         be closed there is no need to call SSL_shutdown() a second
117         time to wait for the other side to respond
118       */
119       break;
120     default: /* Shutdown failed */
121       DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d",
122                                SSL_get_error(ssl, r)));
123       break;
124     }
125   }
126   DBUG_RETURN(vio_close(vio));
127 }
128 
129 
vio_ssl_delete(Vio * vio)130 void vio_ssl_delete(Vio *vio)
131 {
132   if (!vio)
133     return; /* It must be safe to delete null pointer */
134 
135   if (vio->type == VIO_TYPE_SSL)
136     vio_ssl_close(vio); /* Still open, close connection first */
137 
138   if (vio->ssl_arg)
139   {
140     SSL_free((SSL*) vio->ssl_arg);
141     vio->ssl_arg= 0;
142   }
143 
144   vio_delete(vio);
145 }
146 
147 
ssl_do(struct st_VioSSLFd * ptr,Vio * vio,long timeout,int (* connect_accept_func)(SSL *),unsigned long * errptr)148 static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
149                   int (*connect_accept_func)(SSL*), unsigned long *errptr)
150 {
151   int r;
152   SSL *ssl;
153   my_bool unused;
154   my_bool was_blocking;
155   /* Declared here to make compiler happy */
156 #if !defined(HAVE_YASSL) && !defined(DBUG_OFF)
157   int j, n;
158 #endif
159 
160   DBUG_ENTER("ssl_do");
161   DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d  ctx: 0x%lx",
162                        (long) ptr, vio->sd, (long) ptr->ssl_context));
163 
164   /* Set socket to blocking if not already set */
165   vio_blocking(vio, 1, &was_blocking);
166 
167   if (!(ssl= SSL_new(ptr->ssl_context)))
168   {
169     DBUG_PRINT("error", ("SSL_new failure"));
170     *errptr= ERR_get_error();
171     vio_blocking(vio, was_blocking, &unused);
172     DBUG_RETURN(1);
173   }
174   DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
175   SSL_clear(ssl);
176   SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
177   SSL_set_fd(ssl, vio->sd);
178 #if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION)
179   SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); /* OpenSSL >= 1.0 only */
180 #elif OPENSSL_VERSION_NUMBER >= 0x00908000L /* workaround for OpenSSL 0.9.8 */
181   sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
182 #endif
183 
184 #if !defined(HAVE_YASSL) && !defined(DBUG_OFF)
185   {
186     STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
187     ssl_comp_methods = SSL_COMP_get_compression_methods();
188     n= sk_SSL_COMP_num(ssl_comp_methods);
189     DBUG_PRINT("info", ("Available compression methods:\n"));
190     if (n == 0)
191       DBUG_PRINT("info", ("NONE\n"));
192     else
193       for (j = 0; j < n; j++)
194       {
195         SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
196         DBUG_PRINT("info", ("  %d: %s\n", c->id, c->name));
197       }
198   }
199 #endif
200 
201   if ((r= connect_accept_func(ssl)) < 1)
202   {
203     DBUG_PRINT("error", ("SSL_connect/accept failure"));
204     *errptr= SSL_get_error(ssl, r);
205     SSL_free(ssl);
206     vio_blocking(vio, was_blocking, &unused);
207     DBUG_RETURN(1);
208   }
209 
210   /*
211     Connection succeeded. Install new function handlers,
212     change type, set sd to the fd used when connecting
213     and set pointer to the SSL structure
214   */
215   vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0);
216   vio->ssl_arg= (void*)ssl;
217 
218 #ifndef DBUG_OFF
219   {
220     /* Print some info about the peer */
221     X509 *cert;
222     char buf[512];
223 
224     DBUG_PRINT("info",("SSL connection succeeded"));
225     DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl)));
226 
227     if ((cert= SSL_get_peer_certificate (ssl)))
228     {
229       DBUG_PRINT("info",("Peer certificate:"));
230       X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
231       DBUG_PRINT("info",("\t subject: '%s'", buf));
232       X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
233       DBUG_PRINT("info",("\t issuer: '%s'", buf));
234       X509_free(cert);
235     }
236     else
237       DBUG_PRINT("info",("Peer does not have certificate."));
238 
239     if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
240     {
241       DBUG_PRINT("info",("shared_ciphers: '%s'", buf));
242     }
243     else
244       DBUG_PRINT("info",("no shared ciphers!"));
245   }
246 #endif
247 
248   DBUG_RETURN(0);
249 }
250 
251 
sslaccept(struct st_VioSSLFd * ptr,Vio * vio,long timeout,unsigned long * errptr)252 int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *errptr)
253 {
254   DBUG_ENTER("sslaccept");
255   DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept, errptr));
256 }
257 
258 
sslconnect(struct st_VioSSLFd * ptr,Vio * vio,long timeout,unsigned long * errptr)259 int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *errptr)
260 {
261   DBUG_ENTER("sslconnect");
262   DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect, errptr));
263 }
264 
265 
vio_ssl_blocking(Vio * vio,my_bool set_blocking_mode,my_bool * old_mode)266 int vio_ssl_blocking(Vio *vio __attribute__((unused)),
267 		     my_bool set_blocking_mode,
268 		     my_bool *old_mode)
269 {
270   /* Mode is always blocking */
271   *old_mode= 1;
272   /* Return error if we try to change to non_blocking mode */
273   return (set_blocking_mode ? 0 : 1);
274 }
275 
vio_ssl_has_data(Vio * vio)276 my_bool vio_ssl_has_data(Vio *vio)
277 {
278   return SSL_pending(vio->ssl_arg) > 0 ? TRUE : FALSE;
279 }
280 
281 #endif /* HAVE_OPENSSL */
282