1 /* Copyright (c) 2000-2008 MySQL AB
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.
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.
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
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
29 /* yaSSL already uses BSD sockets */
33 The default OpenSSL implementation on NetWare uses WinSock.
34 This code allows us to use the BSD sockets.
37 static int SSL_set_fd_bsd(SSL
*s
, int fd
)
40 BIO_METHOD
*BIO_s_bsdsocket();
43 if ((bio
= BIO_new(BIO_s_bsdsocket())))
45 result
= BIO_set_fd(bio
, fd
, BIO_NOCLOSE
);
46 SSL_set_bio(s
, bio
, bio
);
51 #define SSL_set_fd(A, B) SSL_set_fd_bsd((A), (B))
53 #endif /* HAVE_YASSL */
54 #endif /* __NETWARE__ */
58 report_errors(SSL
* ssl
)
68 DBUG_ENTER("report_errors");
70 while ((l
= ERR_get_error_line_data(&file
,&line
,&data
,&flags
)))
72 DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l
,buf
),
73 file
,line
,(flags
&ERR_TXT_STRING
)?data
:"")) ;
77 DBUG_PRINT("error", ("error: %s",
78 ERR_error_string(SSL_get_error(ssl
, l
), buf
)));
80 DBUG_PRINT("info", ("socket_errno: %d", socket_errno
));
85 size_t vio_ssl_read(Vio
*vio
, uchar
* buf
, size_t size
)
88 DBUG_ENTER("vio_ssl_read");
89 DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u ssl: 0x%lx",
90 vio
->sd
, (long) buf
, (uint
) size
, (long) vio
->ssl_arg
));
92 r
= SSL_read((SSL
*) vio
->ssl_arg
, buf
, size
);
95 report_errors((SSL
*) vio
->ssl_arg
);
97 DBUG_PRINT("exit", ("%u", (uint
) r
));
102 size_t vio_ssl_write(Vio
*vio
, const uchar
* buf
, size_t size
)
105 DBUG_ENTER("vio_ssl_write");
106 DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio
->sd
,
107 (long) buf
, (uint
) size
));
109 r
= SSL_write((SSL
*) vio
->ssl_arg
, buf
, size
);
111 if (r
== (size_t) -1)
112 report_errors((SSL
*) vio
->ssl_arg
);
114 DBUG_PRINT("exit", ("%u", (uint
) r
));
119 int vio_ssl_close(Vio
*vio
)
122 SSL
*ssl
= (SSL
*)vio
->ssl_arg
;
123 DBUG_ENTER("vio_ssl_close");
128 THE SSL standard says that SSL sockets must send and receive a close_notify
129 alert on socket shutdown to avoid truncation attacks. However, this can
130 cause problems since we often hold a lock during shutdown and this IO can
131 take an unbounded amount of time to complete. Since our packets are self
132 describing with length, we aren't vunerable to these attacks. Therefore,
133 we just shutdown by closing the socket (quiet shutdown).
135 SSL_set_quiet_shutdown(ssl
, 1);
137 switch ((r
= SSL_shutdown(ssl
))) {
139 /* Shutdown successful */
143 Shutdown not yet finished - since the socket is going to
144 be closed there is no need to call SSL_shutdown() a second
145 time to wait for the other side to respond
148 default: /* Shutdown failed */
149 DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d",
150 SSL_get_error(ssl
, r
)));
154 DBUG_RETURN(vio_close(vio
));
158 void vio_ssl_delete(Vio
*vio
)
161 return; /* It must be safe to delete null pointer */
163 if (vio
->type
== VIO_TYPE_SSL
)
164 vio_ssl_close(vio
); /* Still open, close connection first */
168 SSL_free((SSL
*) vio
->ssl_arg
);
176 static int ssl_do(struct st_VioSSLFd
*ptr
, Vio
*vio
, long timeout
,
177 int (*connect_accept_func
)(SSL
*))
181 my_bool was_blocking
;
183 DBUG_ENTER("ssl_do");
184 DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx",
185 (long) ptr
, vio
->sd
, (long) ptr
->ssl_context
));
187 /* Set socket to blocking if not already set */
188 vio_blocking(vio
, 1, &was_blocking
);
190 if (!(ssl
= SSL_new(ptr
->ssl_context
)))
192 DBUG_PRINT("error", ("SSL_new failure"));
194 vio_blocking(vio
, was_blocking
, &unused
);
197 DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl
, timeout
));
199 SSL_SESSION_set_timeout(SSL_get_session(ssl
), timeout
);
200 SSL_set_fd(ssl
, vio
->sd
);
202 SSL_set_options(ssl
, SSL_OP_NO_COMPRESSION
);
205 if (connect_accept_func(ssl
) < 1)
207 DBUG_PRINT("error", ("SSL_connect/accept failure"));
210 vio_blocking(vio
, was_blocking
, &unused
);
215 Connection succeeded. Install new function handlers,
216 change type, set sd to the fd used when connecting
217 and set pointer to the SSL structure
219 vio_reset(vio
, VIO_TYPE_SSL
, SSL_get_fd(ssl
), 0, 0);
220 vio
->ssl_arg
= (void*)ssl
;
224 /* Print some info about the peer */
228 DBUG_PRINT("info",("SSL connection succeeded"));
229 DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl
)));
231 if ((cert
= SSL_get_peer_certificate (ssl
)))
233 DBUG_PRINT("info",("Peer certificate:"));
234 X509_NAME_oneline(X509_get_subject_name(cert
), buf
, sizeof(buf
));
235 DBUG_PRINT("info",("\t subject: '%s'", buf
));
236 X509_NAME_oneline(X509_get_issuer_name(cert
), buf
, sizeof(buf
));
237 DBUG_PRINT("info",("\t issuer: '%s'", buf
));
241 DBUG_PRINT("info",("Peer does not have certificate."));
243 if (SSL_get_shared_ciphers(ssl
, buf
, sizeof(buf
)))
245 DBUG_PRINT("info",("shared_ciphers: '%s'", buf
));
248 DBUG_PRINT("info",("no shared ciphers!"));
256 int sslaccept(struct st_VioSSLFd
*ptr
, Vio
*vio
, long timeout
)
258 DBUG_ENTER("sslaccept");
259 DBUG_RETURN(ssl_do(ptr
, vio
, timeout
, SSL_accept
));
263 int sslconnect(struct st_VioSSLFd
*ptr
, Vio
*vio
, long timeout
)
265 DBUG_ENTER("sslconnect");
266 DBUG_RETURN(ssl_do(ptr
, vio
, timeout
, SSL_connect
));
270 int vio_ssl_blocking(Vio
*vio
__attribute__((unused
)),
271 my_bool set_blocking_mode
,
274 /* Mode is always blocking */
276 /* Return error if we try to change to non_blocking mode */
277 return (set_blocking_mode
? 0 : 1);
282 #endif /* HAVE_OPENSSL */