MINOR: ssl: Handle sending early data to server.

This adds a new keyword on the "server" line, "allow-0rtt", if set, we'll try
to send early data to the server, as long as the client sent early data, as
in case the server rejects the early data, we no longer have them, and can't
resend them, so the only option we have is to send back a 425, and we need
to be sure the client knows how to interpret it correctly.
diff --git a/src/backend.c b/src/backend.c
index 9dbbd91..ca064b6 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1038,7 +1038,7 @@
  */
 int connect_server(struct stream *s)
 {
-	struct connection *cli_conn;
+	struct connection *cli_conn = NULL;
 	struct connection *srv_conn;
 	struct conn_stream *srv_cs;
 	struct conn_stream *old_cs;
@@ -1180,10 +1180,11 @@
 
 		/* process the case where the server requires the PROXY protocol to be sent */
 		srv_conn->send_proxy_ofs = 0;
+		cli_conn = objt_conn(strm_orig(s));
+
 		if (srv && srv->pp_opts) {
 			srv_conn->flags |= CO_FL_PRIVATE;
 			srv_conn->send_proxy_ofs = 1; /* must compute size */
-			cli_conn = objt_conn(strm_orig(s));
 			if (cli_conn)
 				conn_get_to_addr(cli_conn);
 		}
@@ -1208,6 +1209,15 @@
 
 	err = si_connect(&s->si[1]);
 
+	if (!reuse && cli_conn && srv &&
+	    (srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) &&
+		    (cli_conn->flags & CO_FL_EARLY_DATA) &&
+		    !channel_is_empty(si_oc(&s->si[1])) &&
+		    srv_conn->flags & CO_FL_SSL_WAIT_HS) {
+		srv_conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
+		srv_conn->flags |= CO_FL_EARLY_SSL_HS;
+	}
+
 	if (err != SF_ERR_NONE)
 		return err;
 
diff --git a/src/proto_http.c b/src/proto_http.c
index bfce2cf..0573179 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5147,6 +5147,17 @@
 			channel_auto_close(rep);
 			rep->analysers &= AN_RES_FLT_END;
 			txn->status = 502;
+
+			/* Check to see if the server refused the early data.
+			 * If so, just send a 425
+			 */
+			if (objt_cs(s->si[1].end)) {
+				struct connection *conn = objt_cs(s->si[1].end)->conn;
+
+				if (conn->err_code == CO_ER_SSL_EARLY_FAILED)
+					txn->status = 425;
+			}
+
 			s->si[1].flags |= SI_FL_NOLINGER;
 			channel_truncate(rep);
 			http_reply_and_close(s, txn->status, http_error_message(s));
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index abb09d0..72d9b8a 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -5210,6 +5210,22 @@
 			goto out_error;
 		}
 	}
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+	else {
+		/*
+		 * If the server refused the early data, we have to send a
+		 * 425 to the client, as we no longer have the data to sent
+		 * them again.
+		 */
+		if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
+			if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
+				conn->err_code = CO_ER_SSL_EARLY_FAILED;
+				goto out_error;
+			}
+		}
+	}
+#endif
+
 
 reneg_ok:
 
@@ -5328,7 +5344,8 @@
 
 			ret = SSL_read_early_data(conn->xprt_ctx,
 			    bi_end(buf), try, &read_length);
-			if (read_length > 0)
+			if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
+			    read_length > 0)
 				conn->flags |= CO_FL_EARLY_DATA;
 			if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
 			    ret == SSL_READ_EARLY_DATA_FINISH) {
@@ -5465,16 +5482,34 @@
 			if (conn->tmp_early_data == -1)
 				conn->tmp_early_data = 0;
 
-			max_early = SSL_get_max_early_data(conn->xprt_ctx);
+			if (objt_listener(conn->target))
+				max_early = SSL_get_max_early_data(conn->xprt_ctx);
+			else {
+				if (SSL_get0_session(conn->xprt_ctx))
+					max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
+				else
+					max_early = 0;
+			}
+
 			if (try + conn->tmp_early_data > max_early) {
 				try -= (try + conn->tmp_early_data) - max_early;
-				if (try <= 0)
+				if (try <= 0) {
+					if (objt_server(conn->target)) {
+						conn->flags &= ~CO_FL_EARLY_SSL_HS;
+						conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
+					}
 					break;
+				}
 			}
 			ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
 			if (ret == 1) {
 				ret = written_data;
 				conn->tmp_early_data += ret;
+				if (objt_server(conn->target)) {
+					conn->flags &= ~CO_FL_EARLY_SSL_HS;
+					conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
+				}
+
 			}
 
 		} else
@@ -5600,6 +5635,13 @@
  */
 static void ssl_sock_shutw(struct connection *conn, int clean)
 {
+	/* If we're done with the connection before we did the handshake
+	 * force the handshake anyway, so that the session is in a consistent
+	 * state
+	 */
+	if (conn->flags & CO_FL_EARLY_SSL_HS)
+		SSL_do_handshake(conn->xprt_ctx);
+
 	if (conn->flags & CO_FL_HANDSHAKE)
 		return;
 	if (!clean)
@@ -7705,6 +7747,13 @@
 	return 0;
 }
 
+/* parse the "allow-0rtt" server keyword */
+static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+	newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
+	return 0;
+}
+
 /* parse the "no-ssl-reuse" server keyword */
 static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
 {
@@ -8558,6 +8607,7 @@
  * not enabled.
  */
 static struct srv_kw_list srv_kws = { "SSL", { }, {
+	{ "allow-0rtt",              srv_parse_allow_0rtt,         0, 1 }, /* Allow using early data on this server */
 	{ "ca-file",                 srv_parse_ca_file,            1, 1 }, /* set CAfile to process verify server cert */
 	{ "check-sni",               srv_parse_check_sni,          1, 1 }, /* set SNI */
 	{ "check-ssl",               srv_parse_check_ssl,          0, 1 }, /* enable SSL for health checks */