1- /* Copyright (c) 2000, 2011 , Oracle and/or its affiliates. All rights reserved.
1+ /* Copyright (c) 2000, 2013 , Oracle and/or its affiliates. All rights reserved.
22
33 This program is free software; you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
@@ -106,18 +106,24 @@ static void ssl_set_sys_error(int ssl_error)
106106
107107
108108/**
109- Indicate whether a SSL I/O operation must be retried later.
109+ This function does two things:
110+ - it indicates whether a SSL I/O operation must be retried later;
111+ - it clears the OpenSSL error queue, thus the next OpenSSL-operation can be
112+ performed even after failed OpenSSL-call.
110113
111114 @param vio VIO object representing a SSL connection.
112115 @param ret Value returned by a SSL I/O function.
113- @param event[out] The type of I/O event to wait/retry.
116+ @param event[out] The type of I/O event to wait/retry.
117+ @param ssl_errno_holder[out] The SSL error code.
114118
115119 @return Whether a SSL I/O operation should be deferred.
116120 @retval TRUE Temporary failure, retry operation.
117121 @retval FALSE Indeterminate failure.
118122*/
119123
120- static my_bool ssl_should_retry (Vio * vio , int ret , enum enum_vio_io_event * event )
124+ static my_bool ssl_should_retry (Vio * vio , int ret ,
125+ enum enum_vio_io_event * event ,
126+ unsigned long * ssl_errno_holder )
121127{
122128 int ssl_error ;
123129 SSL * ssl = vio -> ssl_arg ;
@@ -136,14 +142,22 @@ static my_bool ssl_should_retry(Vio *vio, int ret, enum enum_vio_io_event *event
136142 * event = VIO_IO_EVENT_WRITE ;
137143 break ;
138144 default :
139- #ifndef DBUG_OFF
145+ #ifndef DBUG_OFF /* Debug build */
146+ /* Note: the OpenSSL error queue gets cleared in report_errors(). */
140147 report_errors (ssl );
148+ #else /* Release build */
149+ # ifndef HAVE_YASSL
150+ /* OpenSSL: clear the error queue. */
151+ ERR_clear_error ();
152+ # endif
141153#endif
142154 should_retry = FALSE;
143155 ssl_set_sys_error (ssl_error );
144156 break ;
145157 }
146158
159+ * ssl_errno_holder = ssl_error ;
160+
147161 return should_retry ;
148162}
149163
@@ -152,14 +166,30 @@ size_t vio_ssl_read(Vio *vio, uchar *buf, size_t size)
152166{
153167 int ret ;
154168 SSL * ssl = vio -> ssl_arg ;
169+ unsigned long ssl_errno_not_used ;
170+
155171 DBUG_ENTER ("vio_ssl_read" );
156172
157- while (( ret = SSL_read ( ssl , buf , size )) < 0 )
173+ while (1 )
158174 {
159175 enum enum_vio_io_event event ;
160176
177+ #ifndef HAVE_YASSL
178+ /*
179+ OpenSSL: check that the SSL thread's error queue is cleared. Otherwise
180+ SSL_read() returns an error from the error queue, when SSL_read() failed
181+ because it would block.
182+ */
183+ DBUG_ASSERT (ERR_peek_error () == 0 );
184+ #endif
185+
186+ ret = SSL_read (ssl , buf , size );
187+
188+ if (ret >= 0 )
189+ break ;
190+
161191 /* Process the SSL I/O error. */
162- if (!ssl_should_retry (vio , ret , & event ))
192+ if (!ssl_should_retry (vio , ret , & event , & ssl_errno_not_used ))
163193 break ;
164194
165195 /* Attempt to wait for an I/O event. */
@@ -175,14 +205,30 @@ size_t vio_ssl_write(Vio *vio, const uchar *buf, size_t size)
175205{
176206 int ret ;
177207 SSL * ssl = vio -> ssl_arg ;
208+ unsigned long ssl_errno_not_used ;
209+
178210 DBUG_ENTER ("vio_ssl_write" );
179211
180- while (( ret = SSL_write ( ssl , buf , size )) < 0 )
212+ while (1 )
181213 {
182214 enum enum_vio_io_event event ;
183215
216+ #ifndef HAVE_YASSL
217+ /*
218+ OpenSSL: check that the SSL thread's error queue is cleared. Otherwise
219+ SSL_write() returns an error from the error queue, when SSL_write() failed
220+ because it would block.
221+ */
222+ DBUG_ASSERT (ERR_peek_error () == 0 );
223+ #endif
224+
225+ ret = SSL_write (ssl , buf , size );
226+
227+ if (ret >= 0 )
228+ break ;
229+
184230 /* Process the SSL I/O error. */
185- if (!ssl_should_retry (vio , ret , & event ))
231+ if (!ssl_should_retry (vio , ret , & event , & ssl_errno_not_used ))
186232 break ;
187233
188234 /* Attempt to wait for an I/O event. */
@@ -277,23 +323,40 @@ typedef int (*ssl_handshake_func_t)(SSL*);
277323 @param vio VIO object representing a SSL connection.
278324 @param ssl SSL structure for the connection.
279325 @param func SSL handshake handler.
326+ @param ssl_errno_holder[out] The SSL error code.
280327
281328 @return Return value is 1 on success.
282329*/
283330
284- static int ssl_handshake_loop (Vio * vio , SSL * ssl , ssl_handshake_func_t func )
331+ static int ssl_handshake_loop (Vio * vio , SSL * ssl ,
332+ ssl_handshake_func_t func ,
333+ unsigned long * ssl_errno_holder )
285334{
286335 int ret ;
287336
288337 vio -> ssl_arg = ssl ;
289338
290339 /* Initiate the SSL handshake. */
291- while (( ret = func ( ssl )) < 1 )
340+ while (1 )
292341 {
293342 enum enum_vio_io_event event ;
294343
344+ #ifndef HAVE_YASSL
345+ /*
346+ OpenSSL: check that the SSL thread's error queue is cleared. Otherwise
347+ SSL-handshake-function returns an error from the error queue, when the
348+ function failed because it would block.
349+ */
350+ DBUG_ASSERT (ERR_peek_error () == 0 );
351+ #endif
352+
353+ ret = func (ssl );
354+
355+ if (ret >= 1 )
356+ break ;
357+
295358 /* Process the SSL I/O error. */
296- if (!ssl_should_retry (vio , ret , & event ))
359+ if (!ssl_should_retry (vio , ret , & event , ssl_errno_holder ))
297360 break ;
298361
299362 /* Wait for I/O so that the handshake can proceed. */
@@ -308,7 +371,8 @@ static int ssl_handshake_loop(Vio *vio, SSL *ssl, ssl_handshake_func_t func)
308371
309372
310373static int ssl_do (struct st_VioSSLFd * ptr , Vio * vio , long timeout ,
311- ssl_handshake_func_t func , unsigned long * errptr )
374+ ssl_handshake_func_t func ,
375+ unsigned long * ssl_errno_holder )
312376{
313377 int r ;
314378 SSL * ssl ;
@@ -320,7 +384,7 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
320384 if (!(ssl = SSL_new (ptr -> ssl_context )))
321385 {
322386 DBUG_PRINT ("error" , ("SSL_new failure" ));
323- * errptr = ERR_get_error ();
387+ * ssl_errno_holder = ERR_get_error ();
324388 DBUG_RETURN (1 );
325389 }
326390 DBUG_PRINT ("info" , ("ssl: 0x%lx timeout: %ld" , (long ) ssl , timeout ));
@@ -345,10 +409,9 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
345409 yaSSL_transport_set_send_function (ssl , yassl_send );
346410#endif
347411
348- if ((r = ssl_handshake_loop (vio , ssl , func )) < 1 )
412+ if ((r = ssl_handshake_loop (vio , ssl , func , ssl_errno_holder )) < 1 )
349413 {
350414 DBUG_PRINT ("error" , ("SSL_connect/accept failure" ));
351- * errptr = SSL_get_error (ssl , r );
352415 SSL_free (ssl );
353416 DBUG_RETURN (1 );
354417 }
@@ -395,17 +458,19 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
395458}
396459
397460
398- int sslaccept (struct st_VioSSLFd * ptr , Vio * vio , long timeout , unsigned long * errptr )
461+ int sslaccept (struct st_VioSSLFd * ptr , Vio * vio , long timeout ,
462+ unsigned long * ssl_errno_holder )
399463{
400464 DBUG_ENTER ("sslaccept" );
401- DBUG_RETURN (ssl_do (ptr , vio , timeout , SSL_accept , errptr ));
465+ DBUG_RETURN (ssl_do (ptr , vio , timeout , SSL_accept , ssl_errno_holder ));
402466}
403467
404468
405- int sslconnect (struct st_VioSSLFd * ptr , Vio * vio , long timeout , unsigned long * errptr )
469+ int sslconnect (struct st_VioSSLFd * ptr , Vio * vio , long timeout ,
470+ unsigned long * ssl_errno_holder )
406471{
407472 DBUG_ENTER ("sslconnect" );
408- DBUG_RETURN (ssl_do (ptr , vio , timeout , SSL_connect , errptr ));
473+ DBUG_RETURN (ssl_do (ptr , vio , timeout , SSL_connect , ssl_errno_holder ));
409474}
410475
411476
0 commit comments