You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2018/10/12 11:09:26 UTC

svn commit: r1843651 - /tomcat/native/trunk/native/src/sslnetwork.c

Author: rjung
Date: Fri Oct 12 11:09:26 2018
New Revision: 1843651

URL: http://svn.apache.org/viewvc?rev=1843651&view=rev
Log:
Refactor after r1843514 to share common code
between PHA and reneg case.

Modified:
    tomcat/native/trunk/native/src/sslnetwork.c

Modified: tomcat/native/trunk/native/src/sslnetwork.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslnetwork.c?rev=1843651&r1=1843650&r2=1843651&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslnetwork.c (original)
+++ tomcat/native/trunk/native/src/sslnetwork.c Fri Oct 12 11:09:26 2018
@@ -616,15 +616,69 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, atta
     return APR_SUCCESS;
 }
 
+static int ssl_do_renegotiate(tcn_ssl_conn_t *con, int use_pha)
+{
+    int retVal;
+    int error = 0;
+    char peekbuf[1];
+    apr_interval_time_t timeout;
+
+    apr_socket_timeout_get(con->sock, &timeout);
+
+    /* Trigger reading of the certs from the client.
+     * Peeking 0 bytes actually works.
+     * Before TLS 1.3 this will result in a renegotiation.
+     * for TLS 1.3 in PHA.
+     * See: http://marc.info/?t=145493359200002&r=1&w=2
+     *
+     * This will normally return SSL_ERROR_WANT_READ whether the renegotiation
+     * has been completed or not. Afterwards, need to determine if I/O needs to
+     * be triggered or not.
+     */
+    retVal = SSL_peek(con->ssl, peekbuf, 0);
+    if (retVal < 1) {
+        error = SSL_get_error(con->ssl, retVal);
+    }
+
+    // If the certs have not been received, then need to wait for I/O
+    while ((use_pha && con->pha_state == PHA_STARTED) || (!use_pha && SSL_renegotiate_pending(con->ssl))) {
+        // SSL_ERROR_WANT_READ is expected. Anything else is an error.
+        if (error == SSL_ERROR_WANT_READ) {
+            retVal = wait_for_io_or_timeout(con, error, timeout);
+            /*
+             * Since this is blocking I/O, anything other than APR_SUCCESS is an
+             * error.
+             */
+            if (retVal != APR_SUCCESS) {
+                con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
+                return retVal;
+            }
+        } else {
+            return APR_EGENERAL;
+        }
+
+        // Re-try SSL_peek after I/O
+        retVal = SSL_peek(con->ssl, peekbuf, 0);
+        if (retVal < 1) {
+            error = SSL_get_error(con->ssl, retVal);
+        } else {
+            /*
+             * Reset error to handle case where SSL_Peek returns 0 but
+             * the pha resp. renegotiation state has not changed.
+             * This will trigger an error to be returned.
+             */
+            error = 0;
+        }
+    }
+    return APR_SUCCESS;
+}
+
 TCN_IMPLEMENT_CALL(jint, SSLSocket, renegotiate)(TCN_STDARGS,
                                                  jlong sock)
 {
     tcn_socket_t *s   = J2P(sock, tcn_socket_t *);
     tcn_ssl_conn_t *con;
     int retVal;
-    int error = 0;
-    char peekbuf[1];
-    apr_interval_time_t timeout;
 #if defined(SSL_OP_NO_TLSv1_3)
     const SSL_SESSION *session;
 #endif
@@ -632,7 +686,6 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, rene
     UNREFERENCED_STDARGS;
     TCN_ASSERT(sock != 0);
     con = (tcn_ssl_conn_t *)s->opaque;
-    apr_socket_timeout_get(con->sock, &timeout);
 
 #if defined(SSL_OP_NO_TLSv1_3)
     session  = SSL_get_session(con->ssl);
@@ -651,43 +704,11 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, rene
         if (retVal <= 0) {
             return APR_EGENERAL;
         }
-
-        // Trigger reading of the certs from the client
-        retVal = SSL_peek(con->ssl, peekbuf, 0);
-        if (retVal < 1) {
-            error = SSL_get_error(con->ssl, retVal);
+        retVal = ssl_do_renegotiate(con, 1);
+        if (retVal != APR_SUCCESS) {
+            return retVal;
         }
 
-        // If the certs have not been received, then need to wait for I/O
-        while (con->pha_state == PHA_STARTED) {
-            // SSL_ERROR_WANT_READ is expected. Anything else is an error.
-            if (error == SSL_ERROR_WANT_READ) {
-                retVal = wait_for_io_or_timeout(con, error, timeout);
-                /*
-                 * Since this is blocking I/O, anything other than APR_SUCCESS is an
-                 * error.
-                 */
-                if (retVal != APR_SUCCESS) {
-                    con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
-                    return retVal;
-                }
-            } else {
-                return APR_EGENERAL;
-            }
-
-            // Re-try SSL_peek after I/O
-            retVal = SSL_peek(con->ssl, peekbuf, 0);
-            if (retVal < 1) {
-                error = SSL_get_error(con->ssl, retVal);
-            } else {
-                /*
-                 * Reset error to handle case where SSL_Peek returns 0 but
-                 * con->pha_state has not changed. This will trigger an error
-                 * to be returned.
-                 */
-                error = 0;
-            }
-        }
     } else {
 #endif
         // TLS 1.2 and earlier renegotiation
@@ -702,49 +723,9 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, rene
         if (retVal <= 0) {
             return APR_EGENERAL;
         }
-
-        /* Need to trigger the renegotiation handshake by reading.
-         * Peeking 0 bytes actually works.
-         * See: http://marc.info/?t=145493359200002&r=1&w=2
-         *
-         * This will normally return SSL_ERROR_WANT_READ whether the renegotiation
-         * has been completed or not. Afterwards, need to determine if I/O needs to
-         * be triggered or not.
-         */
-        retVal = SSL_peek(con->ssl, peekbuf, 0);
-        if (retVal < 1) {
-            error = SSL_get_error(con->ssl, retVal);
-        }
-
-        // If the renegotiation is still pending, then I/O needs to be triggered
-        while (SSL_renegotiate_pending(con->ssl)) {
-            // SSL_ERROR_WANT_READ is expected. Anything else is an error.
-            if (error == SSL_ERROR_WANT_READ) {
-                retVal = wait_for_io_or_timeout(con, error, timeout);
-                /*
-                 * Since this is blocking I/O, anything other than APR_SUCCESS is an
-                 * error.
-                 */
-                if (retVal != APR_SUCCESS) {
-                    con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
-                    return retVal;
-                }
-            } else {
-                return APR_EGENERAL;
-            }
-
-            // Re-try SSL_peek after I/O
-            retVal = SSL_peek(con->ssl, peekbuf, 0);
-            if (retVal < 1) {
-                error = SSL_get_error(con->ssl, retVal);
-            } else {
-                /*
-                 * Reset error to handle case where SSL_Peek returns 0 but
-                 * SSL_renegotiate_pending returns true. This will trigger an error
-                 * to be returned.
-                 */
-                error = 0;
-            }
+        retVal = ssl_do_renegotiate(con, 0);
+        if (retVal != APR_SUCCESS) {
+            return retVal;
         }
 
         con->reneg_state = RENEG_REJECT;



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org