Blame SOURCES/freeradius-correct-receiving-multiple-packets.patch

a7bcdb
diff --git a/src/main/tls_listen.c b/src/main/tls_listen.c
a7bcdb
index 32cf564..45e7641 100644
a7bcdb
--- a/src/main/tls_listen.c
a7bcdb
+++ b/src/main/tls_listen.c
a7bcdb
@@ -189,6 +189,18 @@ static int tls_socket_recv(rad_listen_t *listener)
a7bcdb
 
a7bcdb
 	RDEBUG3("Reading from socket %d", request->packet->sockfd);
a7bcdb
 	PTHREAD_MUTEX_LOCK(&sock->mutex);
a7bcdb
+
a7bcdb
+	/*
a7bcdb
+	 *	If there is pending application data, as set up by
a7bcdb
+	 *	SSL_peek(), read that before reading more data from
a7bcdb
+	 *	the socket.
a7bcdb
+	 */
a7bcdb
+	if (SSL_pending(sock->ssn->ssl)) {
a7bcdb
+		RDEBUG3("Reading pending buffered data");
a7bcdb
+		sock->ssn->dirty_in.used = 0;
a7bcdb
+		goto get_application_data;
a7bcdb
+	}
a7bcdb
+
a7bcdb
 	rcode = read(request->packet->sockfd,
a7bcdb
 		     sock->ssn->dirty_in.data,
a7bcdb
 		     sizeof(sock->ssn->dirty_in.data));
a7bcdb
@@ -250,6 +262,7 @@ static int tls_socket_recv(rad_listen_t *listener)
a7bcdb
 	/*
a7bcdb
 	 *	Try to get application data.
a7bcdb
 	 */
a7bcdb
+get_application_data:
a7bcdb
 	status = tls_application_data(sock->ssn, request);
a7bcdb
 	RDEBUG("Application data status %d", status);
a7bcdb
 
a7bcdb
@@ -333,9 +346,11 @@ int dual_tls_recv(rad_listen_t *listener)
a7bcdb
 	RAD_REQUEST_FUNP fun = NULL;
a7bcdb
 	listen_socket_t *sock = listener->data;
a7bcdb
 	RADCLIENT	*client = sock->client;
a7bcdb
+	BIO		*rbio;
a7bcdb
 
a7bcdb
 	if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0;
a7bcdb
 
a7bcdb
+redo:
a7bcdb
 	if (!tls_socket_recv(listener)) {
a7bcdb
 		return 0;
a7bcdb
 	}
a7bcdb
@@ -403,6 +418,26 @@ int dual_tls_recv(rad_listen_t *listener)
a7bcdb
 		return 0;
a7bcdb
 	}
a7bcdb
 
a7bcdb
+	/*
a7bcdb
+	 *	Check for more application data.
a7bcdb
+	 *
a7bcdb
+	 *	If there is pending SSL data, "peek" at the
a7bcdb
+	 *	application data.  If we get at least one byte of
a7bcdb
+	 *	application data, go back to tls_socket_recv().
a7bcdb
+	 *	SSL_peek() will set SSL_pending(), and
a7bcdb
+	 *	tls_socket_recv() will read another packet.
a7bcdb
+	 */
a7bcdb
+	rbio = SSL_get_rbio(sock->ssn->ssl);
a7bcdb
+	if (BIO_ctrl_pending(rbio)) {
a7bcdb
+		char buf[1];
a7bcdb
+		int peek = SSL_peek(sock->ssn->ssl, buf, 1);
a7bcdb
+
a7bcdb
+		if (peek > 0) {
a7bcdb
+			DEBUG("more TLS records after dual_tls_recv");
a7bcdb
+			goto redo;
a7bcdb
+		}
a7bcdb
+	}
a7bcdb
+
a7bcdb
 	return 1;
a7bcdb
 }
a7bcdb