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