From bf206cada35873b2d3ac2dd8cdff3a575a3919fb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 29 May 2008 20:36:18 +0300 Subject: [PATCH] Changed TLS server to use OpenSSL SSL_accept() instead of SSL_read() 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 | 39 ++++++++++++++++++++++++++++++++++----- src/eap_server/eap_tls.c | 5 +++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index e83bf9162..f5b1b9847 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -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); diff --git a/src/eap_server/eap_tls.c b/src/eap_server/eap_tls.c index e5f1931e6..1b168c582 100644 --- a/src/eap_server/eap_tls.c +++ b/src/eap_server/eap_tls.c @@ -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); }