1/* Copyright (c) 2000, 2013, 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#include "my_context.h"
25#include <mysql_async.h>
26
27#ifdef HAVE_OPENSSL
28
29#ifdef HAVE_YASSL
30/*
31 yassl seem to be different here, SSL_get_error() value can be
32 directly passed to ERR_error_string(), and these errors don't go
33 into ERR_get_error() stack.
34 in openssl, apparently, SSL_get_error() values live in a different
35 namespace, one needs to use ERR_get_error() as an argument
36 for ERR_error_string().
37*/
38#define SSL_errno(X,Y) SSL_get_error(X,Y)
39#else
40#define SSL_errno(X,Y) ERR_get_error()
41#endif
42
43/**
44 Obtain the equivalent system error status for the last SSL I/O operation.
45
46 @param ssl_error The result code of the failed TLS/SSL I/O operation.
47*/
48
49static void ssl_set_sys_error(int ssl_error)
50{
51 int error= 0;
52
53 switch (ssl_error)
54 {
55 case SSL_ERROR_ZERO_RETURN:
56 error= SOCKET_ECONNRESET;
57 break;
58 case SSL_ERROR_WANT_READ:
59 case SSL_ERROR_WANT_WRITE:
60#ifdef SSL_ERROR_WANT_CONNECT
61 case SSL_ERROR_WANT_CONNECT:
62#endif
63#ifdef SSL_ERROR_WANT_ACCEPT
64 case SSL_ERROR_WANT_ACCEPT:
65#endif
66 error= SOCKET_EWOULDBLOCK;
67 break;
68 case SSL_ERROR_SSL:
69 /* Protocol error. */
70#ifdef EPROTO
71 error= EPROTO;
72#else
73 error= SOCKET_ECONNRESET;
74#endif
75 break;
76 case SSL_ERROR_SYSCALL:
77 case SSL_ERROR_NONE:
78 default:
79 break;
80 };
81
82 /* Set error status to a equivalent of the SSL error. */
83 if (error)
84 {
85#ifdef _WIN32
86 WSASetLastError(error);
87#else
88 errno= error;
89#endif
90 }
91}
92
93
94/**
95 Indicate whether a SSL I/O operation must be retried later.
96
97 @param vio VIO object representing a SSL connection.
98 @param ret Value returned by a SSL I/O function.
99 @param event[out] The type of I/O event to wait/retry.
100
101 @return Whether a SSL I/O operation should be deferred.
102 @retval TRUE Temporary failure, retry operation.
103 @retval FALSE Indeterminate failure.
104*/
105
106static my_bool ssl_should_retry(Vio *vio, int ret, enum enum_vio_io_event *event)
107{
108 int ssl_error;
109 SSL *ssl= vio->ssl_arg;
110 my_bool should_retry= TRUE;
111
112 /* Retrieve the result for the SSL I/O operation. */
113 ssl_error= SSL_get_error(ssl, ret);
114
115 /* Retrieve the result for the SSL I/O operation. */
116 switch (ssl_error)
117 {
118 case SSL_ERROR_WANT_READ:
119 *event= VIO_IO_EVENT_READ;
120 break;
121 case SSL_ERROR_WANT_WRITE:
122 *event= VIO_IO_EVENT_WRITE;
123 break;
124 default:
125 should_retry= FALSE;
126 ssl_set_sys_error(ssl_error);
127 break;
128 }
129
130 return should_retry;
131}
132
133
134size_t vio_ssl_read(Vio *vio, uchar *buf, size_t size)
135{
136 int ret;
137 SSL *ssl= vio->ssl_arg;
138 DBUG_ENTER("vio_ssl_read");
139 DBUG_PRINT("enter", ("sd: %d buf: %p size: %zu ssl: %p",
140 (int)mysql_socket_getfd(vio->mysql_socket), buf, size,
141 vio->ssl_arg));
142
143 if (vio->async_context && vio->async_context->active)
144 ret= my_ssl_read_async(vio->async_context, (SSL *)vio->ssl_arg, buf, (int)size);
145 else
146 {
147 while ((ret= SSL_read(ssl, buf, (int)size)) < 0)
148 {
149 enum enum_vio_io_event event;
150
151 /* Process the SSL I/O error. */
152 if (!ssl_should_retry(vio, ret, &event))
153 break;
154 /* Attempt to wait for an I/O event. */
155 if (vio_socket_io_wait(vio, event))
156 break;
157 }
158 }
159
160 DBUG_PRINT("exit", ("%d", (int) ret));
161 DBUG_RETURN(ret < 0 ? -1 : ret);
162
163}
164
165
166size_t vio_ssl_write(Vio *vio, const uchar *buf, size_t size)
167{
168 int ret;
169 SSL *ssl= vio->ssl_arg;
170 DBUG_ENTER("vio_ssl_write");
171 DBUG_PRINT("enter", ("sd: %d buf: %p size: %zu",
172 (int)mysql_socket_getfd(vio->mysql_socket),
173 buf, size));
174
175 if (vio->async_context && vio->async_context->active)
176 ret= my_ssl_write_async(vio->async_context, (SSL *)vio->ssl_arg, buf,
177 (int)size);
178 else
179 {
180 while ((ret= SSL_write(ssl, buf, (int)size)) < 0)
181 {
182 enum enum_vio_io_event event;
183
184 /* Process the SSL I/O error. */
185 if (!ssl_should_retry(vio, ret, &event))
186 break;
187
188 /* Attempt to wait for an I/O event. */
189 if (vio_socket_io_wait(vio, event))
190 break;
191 }
192 }
193
194 DBUG_RETURN(ret < 0 ? -1 : ret);
195}
196
197#ifdef HAVE_YASSL
198
199/* Emulate a blocking recv() call with vio_read(). */
200static long yassl_recv(void *ptr, void *buf, size_t len,
201 int flag __attribute__((unused)))
202{
203 return (long)vio_read(ptr, buf, len);
204}
205
206
207/* Emulate a blocking send() call with vio_write(). */
208static long yassl_send(void *ptr, const void *buf, size_t len,
209 int flag __attribute__((unused)))
210{
211 return (long)vio_write(ptr, buf, len);
212}
213
214#endif
215
216int vio_ssl_close(Vio *vio)
217{
218 int r= 0;
219 SSL *ssl= (SSL*)vio->ssl_arg;
220 DBUG_ENTER("vio_ssl_close");
221
222 if (ssl)
223 {
224 /*
225 THE SSL standard says that SSL sockets must send and receive a close_notify
226 alert on socket shutdown to avoid truncation attacks. However, this can
227 cause problems since we often hold a lock during shutdown and this IO can
228 take an unbounded amount of time to complete. Since our packets are self
229 describing with length, we aren't vunerable to these attacks. Therefore,
230 we just shutdown by closing the socket (quiet shutdown).
231 */
232 SSL_set_quiet_shutdown(ssl, 1);
233
234 switch ((r= SSL_shutdown(ssl))) {
235 case 1:
236 /* Shutdown successful */
237 break;
238 case 0:
239 /*
240 Shutdown not yet finished - since the socket is going to
241 be closed there is no need to call SSL_shutdown() a second
242 time to wait for the other side to respond
243 */
244 break;
245 default: /* Shutdown failed */
246 DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d",
247 SSL_get_error(ssl, r)));
248 break;
249 }
250 }
251 DBUG_RETURN(vio_close(vio));
252}
253
254
255void vio_ssl_delete(Vio *vio)
256{
257 if (!vio)
258 return; /* It must be safe to delete null pointer */
259
260 if (vio->type == VIO_TYPE_SSL)
261 vio_ssl_close(vio); /* Still open, close connection first */
262
263 if (vio->ssl_arg)
264 {
265 SSL_free((SSL*) vio->ssl_arg);
266 vio->ssl_arg= 0;
267 }
268
269 vio_delete(vio);
270}
271
272
273/** SSL handshake handler. */
274typedef int (*ssl_handshake_func_t)(SSL*);
275
276
277/**
278 Loop and wait until a SSL handshake is completed.
279
280 @param vio VIO object representing a SSL connection.
281 @param ssl SSL structure for the connection.
282 @param func SSL handshake handler.
283
284 @return Return value is 1 on success.
285*/
286
287static int ssl_handshake_loop(Vio *vio, SSL *ssl, ssl_handshake_func_t func)
288{
289 int ret;
290
291 vio->ssl_arg= ssl;
292
293 /* Initiate the SSL handshake. */
294 while ((ret= func(ssl)) < 1)
295 {
296 enum enum_vio_io_event event;
297
298 /* Process the SSL I/O error. */
299 if (!ssl_should_retry(vio, ret, &event))
300 break;
301
302 /* Wait for I/O so that the handshake can proceed. */
303 if (vio_socket_io_wait(vio, event))
304 break;
305 }
306
307 vio->ssl_arg= NULL;
308
309 return ret;
310}
311
312
313static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
314 ssl_handshake_func_t func, unsigned long *errptr)
315{
316 int r;
317 SSL *ssl;
318 my_bool unused;
319 my_bool was_blocking;
320 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
321 DBUG_ENTER("ssl_do");
322 DBUG_PRINT("enter", ("ptr: %p, sd: %d ctx: %p",
323 ptr, (int)sd, ptr->ssl_context));
324
325 /* Set socket to blocking if not already set */
326 vio_blocking(vio, 1, &was_blocking);
327
328 if (!(ssl= SSL_new(ptr->ssl_context)))
329 {
330 DBUG_PRINT("error", ("SSL_new failure"));
331 *errptr= ERR_get_error();
332 vio_blocking(vio, was_blocking, &unused);
333 DBUG_RETURN(1);
334 }
335 DBUG_PRINT("info", ("ssl: %p timeout: %ld", ssl, timeout));
336 SSL_clear(ssl);
337 SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
338 SSL_set_fd(ssl, sd);
339
340 /*
341 Since yaSSL does not support non-blocking send operations, use
342 special transport functions that properly handles non-blocking
343 sockets. These functions emulate the behavior of blocking I/O
344 operations by waiting for I/O to become available.
345 */
346#ifdef HAVE_YASSL
347 /* Set first argument of the transport functions. */
348 yaSSL_transport_set_ptr(ssl, vio);
349 /* Set functions to use in order to send and receive data. */
350 yaSSL_transport_set_recv_function(ssl, yassl_recv);
351 yaSSL_transport_set_send_function(ssl, yassl_send);
352#endif
353
354#if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION)
355 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
356#endif
357
358 if ((r= ssl_handshake_loop(vio, ssl, func)) < 1)
359 {
360 DBUG_PRINT("error", ("SSL_connect/accept failure"));
361 *errptr= SSL_errno(ssl, r);
362 SSL_free(ssl);
363 vio_blocking(vio, was_blocking, &unused);
364 DBUG_RETURN(1);
365 }
366
367 /*
368 Connection succeeded. Install new function handlers,
369 change type, set sd to the fd used when connecting
370 and set pointer to the SSL structure
371 */
372 if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0))
373 {
374 vio_blocking(vio, was_blocking, &unused);
375 DBUG_RETURN(1);
376 }
377
378#ifndef DBUG_OFF
379 {
380 /* Print some info about the peer */
381 X509 *cert;
382 char buf[512];
383
384 DBUG_PRINT("info",("SSL connection succeeded"));
385 DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl)));
386
387 if ((cert= SSL_get_peer_certificate (ssl)))
388 {
389 DBUG_PRINT("info",("Peer certificate:"));
390 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
391 DBUG_PRINT("info",("\t subject: '%s'", buf));
392 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
393 DBUG_PRINT("info",("\t issuer: '%s'", buf));
394 X509_free(cert);
395 }
396 else
397 DBUG_PRINT("info",("Peer does not have certificate."));
398
399 if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
400 {
401 DBUG_PRINT("info",("shared_ciphers: '%s'", buf));
402 }
403 else
404 DBUG_PRINT("info",("no shared ciphers!"));
405 }
406#endif
407
408 DBUG_RETURN(0);
409}
410
411
412int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *errptr)
413{
414 DBUG_ENTER("sslaccept");
415 DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept, errptr));
416}
417
418
419int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *errptr)
420{
421 DBUG_ENTER("sslconnect");
422 DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect, errptr));
423}
424
425
426int vio_ssl_blocking(Vio *vio __attribute__((unused)),
427 my_bool set_blocking_mode,
428 my_bool *old_mode)
429{
430 /* Mode is always blocking */
431 *old_mode= 1;
432 /* Return error if we try to change to non_blocking mode */
433 return (set_blocking_mode ? 0 : 1);
434}
435
436my_bool vio_ssl_has_data(Vio *vio)
437{
438 return SSL_pending(vio->ssl_arg) > 0 ? TRUE : FALSE;
439}
440
441#endif /* HAVE_OPENSSL */
442