mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / vio / viossl.c
blob9d863853ac452314f069a5dc69b61a7ccfcdd7a1
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
20 the file descriptior.
23 #include "vio_priv.h"
25 #ifdef HAVE_OPENSSL
27 #ifdef __NETWARE__
29 /* yaSSL already uses BSD sockets */
30 #ifndef HAVE_YASSL
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)
39 int result= -1;
40 BIO_METHOD *BIO_s_bsdsocket();
41 BIO *bio;
43 if ((bio= BIO_new(BIO_s_bsdsocket())))
45 result= BIO_set_fd(bio, fd, BIO_NOCLOSE);
46 SSL_set_bio(s, bio, bio);
48 return result;
51 #define SSL_set_fd(A, B) SSL_set_fd_bsd((A), (B))
53 #endif /* HAVE_YASSL */
54 #endif /* __NETWARE__ */
57 static void
58 report_errors(SSL* ssl)
60 unsigned long l;
61 const char *file;
62 const char *data;
63 int line, flags;
64 #ifndef DBUG_OFF
65 char buf[512];
66 #endif
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:"")) ;
76 if (ssl)
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));
81 DBUG_VOID_RETURN;
85 size_t vio_ssl_read(Vio *vio, uchar* buf, size_t size)
87 size_t r;
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);
93 #ifndef DBUG_OFF
94 if (r == (size_t) -1)
95 report_errors((SSL*) vio->ssl_arg);
96 #endif
97 DBUG_PRINT("exit", ("%u", (uint) r));
98 DBUG_RETURN(r);
102 size_t vio_ssl_write(Vio *vio, const uchar* buf, size_t size)
104 size_t r;
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);
110 #ifndef DBUG_OFF
111 if (r == (size_t) -1)
112 report_errors((SSL*) vio->ssl_arg);
113 #endif
114 DBUG_PRINT("exit", ("%u", (uint) r));
115 DBUG_RETURN(r);
119 int vio_ssl_close(Vio *vio)
121 int r= 0;
122 SSL *ssl= (SSL*)vio->ssl_arg;
123 DBUG_ENTER("vio_ssl_close");
125 if (ssl)
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))) {
138 case 1:
139 /* Shutdown successful */
140 break;
141 case 0:
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
147 break;
148 default: /* Shutdown failed */
149 DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d",
150 SSL_get_error(ssl, r)));
151 break;
154 DBUG_RETURN(vio_close(vio));
158 void vio_ssl_delete(Vio *vio)
160 if (!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 */
166 if (vio->ssl_arg)
168 SSL_free((SSL*) vio->ssl_arg);
169 vio->ssl_arg= 0;
172 vio_delete(vio);
176 static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
177 int (*connect_accept_func)(SSL*))
179 SSL *ssl;
180 my_bool unused;
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"));
193 report_errors(ssl);
194 vio_blocking(vio, was_blocking, &unused);
195 DBUG_RETURN(1);
197 DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
198 SSL_clear(ssl);
199 SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
200 SSL_set_fd(ssl, vio->sd);
201 #ifndef HAVE_YASSL
202 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
203 #endif
205 if (connect_accept_func(ssl) < 1)
207 DBUG_PRINT("error", ("SSL_connect/accept failure"));
208 report_errors(ssl);
209 SSL_free(ssl);
210 vio_blocking(vio, was_blocking, &unused);
211 DBUG_RETURN(1);
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;
222 #ifndef DBUG_OFF
224 /* Print some info about the peer */
225 X509 *cert;
226 char buf[512];
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));
238 X509_free(cert);
240 else
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));
247 else
248 DBUG_PRINT("info",("no shared ciphers!"));
250 #endif
252 DBUG_RETURN(0);
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,
272 my_bool *old_mode)
274 /* Mode is always blocking */
275 *old_mode= 1;
276 /* Return error if we try to change to non_blocking mode */
277 return (set_blocking_mode ? 0 : 1);
282 #endif /* HAVE_OPENSSL */