Changed TLS server to use OpenSSL SSL_accept() instead of SSL_read()
authorJouni Malinen <j@w1.fi>
Thu, 29 May 2008 17:36:18 +0000 (20:36 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 29 May 2008 17:36:18 +0000 (20:36 +0300)
The server handshake processing was still using SSL_read() to get OpenSSL
to perform the handshake. While this works for most cases, it caused some
issues for re-authentication. This is now changed to use SSL_accept() which
is more approriate here since we know that the handshake is still going on
and there will not be any tunneled data available. This resolves some of
the re-authentication issues and makes it possible for the server to notice
if TLS processing fails (SSL_read() did not return an error in many of
these cases while SSL_accept() does).

Set session id context to a unique value in order to avoid fatal errors
when client tries session resumption (SSL_set_session_id_context() must be
called for that to work), but disable session resumption with the unique
value for the time being since not all server side code is ready for it yet
(e.g., EAP-TTLS needs special Phase 2 processing when using abbreviated
handshake).

Changed EAP-TLS server not to call TLS library when processing the final
ACK (empty data) from the client in order to avoid starting a new TLS
handshake with SSL_accept().

src/crypto/tls_openssl.c
src/eap_server/eap_tls.c

index e83bf91..f5b1b98 100644 (file)
@@ -1282,6 +1282,8 @@ static int tls_connection_set_subject_match(struct tls_connection *conn,
 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
                              int verify_peer)
 {
+       static int counter = 0;
+
        if (conn == NULL)
                return -1;
 
@@ -1295,6 +1297,19 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
 
        SSL_set_accept_state(conn->ssl);
 
+       /*
+        * Set session id context in order to avoid fatal errors when client
+        * tries to resume a session. However, set the context to a unique
+        * value in order to effectively disable session resumption for now
+        * since not all areas of the server code are ready for it (e.g.,
+        * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS
+        * handshake).
+        */
+       counter++;
+       SSL_set_session_id_context(conn->ssl,
+                                  (const unsigned char *) &counter,
+                                  sizeof(counter));
+
        return 0;
 }
 
@@ -2101,8 +2116,11 @@ u8 * tls_connection_server_handshake(void *ssl_ctx,
 {
        int res;
        u8 *out_data;
-       char buf[10];
 
+       /*
+        * Give TLS handshake data from the client (if available) to OpenSSL
+        * for processing.
+        */
        if (in_data &&
            BIO_write(conn->ssl_in, in_data, in_len) < 0) {
                tls_show_errors(MSG_INFO, __func__,
@@ -2110,12 +2128,23 @@ u8 * tls_connection_server_handshake(void *ssl_ctx,
                return NULL;
        }
 
-       res = SSL_read(conn->ssl, buf, sizeof(buf));
-       if (res >= 0) {
-               wpa_printf(MSG_DEBUG, "SSL: Unexpected data from SSL_read "
-                          "(res=%d)", res);
+       /* Initiate TLS handshake or continue the existing handshake */
+       res = SSL_accept(conn->ssl);
+       if (res != 1) {
+               int err = SSL_get_error(conn->ssl, res);
+               if (err == SSL_ERROR_WANT_READ)
+                       wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want "
+                                  "more data");
+               else if (err == SSL_ERROR_WANT_WRITE)
+                       wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to "
+                                  "write");
+               else {
+                       tls_show_errors(MSG_INFO, __func__, "SSL_accept");
+                       return NULL;
+               }
        }
 
+       /* Get the TLS handshake data to be sent to the client */
        res = BIO_ctrl_pending(conn->ssl_out);
        wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
        out_data = os_malloc(res == 0 ? 1 : res);
index e5f1931..1b168c5 100644 (file)
@@ -159,6 +159,11 @@ static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
                                const struct wpabuf *respData)
 {
        struct eap_tls_data *data = priv;
+       if (data->state == SUCCESS && wpabuf_len(data->ssl.in_buf) == 0) {
+               wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
+                          "handshake message");
+               return;
+       }
        if (eap_server_tls_phase1(sm, &data->ssl) < 0)
                eap_tls_state(data, FAILURE);
 }