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/include/types/connection.h b/include/types/connection.h
index beb0b71..eb67455 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -226,6 +226,7 @@
 	CO_ER_SSL_HANDSHAKE_HB, /* SSL error during handshake with heartbeat present */
 	CO_ER_SSL_KILLED_HB,    /* Stopped a TLSv1 heartbeat attack (CVE-2014-0160) */
 	CO_ER_SSL_NO_TARGET,    /* unknown target (not client nor server) */
+	CO_ER_SSL_EARLY_FAILED, /* Server refused early data */
 };
 
 /* source address settings for outgoing connections */
diff --git a/include/types/server.h b/include/types/server.h
index 4a31934..76225f7 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -167,6 +167,7 @@
 #define SRV_SSL_O_NONE         0x0000
 #define SRV_SSL_O_NO_TLS_TICKETS 0x0100 /* disable session resumption tickets */
 #define SRV_SSL_O_NO_REUSE     0x200  /* disable session reuse */
+#define SRV_SSL_O_EARLY_DATA   0x400  /* Allow using early data */
 #endif
 
 struct pid_list {
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 */