BUG/MEDIUM: mux-h2: make sure we don't emit TE headers with anything but "trailers"

While the H2 parser properly checks for the absence of anything but
"trailers" in the TE header field, we forget to check this when sending
the request to an H2 server. The problem is that an H2->H2 conversion
may keep "gzip" and fail on the next stage.

This patch makes sure that we only send "TE: trailers" if the TE header
contains the "trailers" token, otherwise it's dropped.

This fixes issue #464 and should be backported till 1.9.

(cherry picked from commit bb2c4ae06566b8a8789caca4c48524aeb88cbc1b)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit e22b3fb31968569194b1f848fadb4ca01f4dfc73)
[wt: adjusted context]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 50b7b7a..beaf79c 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -4889,19 +4889,32 @@
 
 	/* encode all headers, stop at empty name */
 	for (hdr = 0; hdr < sizeof(list)/sizeof(list[0]); hdr++) {
+		struct ist n = list[hdr].n;
+		struct ist v = list[hdr].v;
+
 		/* these ones do not exist in H2 and must be dropped. */
-		if (isteq(list[hdr].n, ist("connection")) ||
-		    isteq(list[hdr].n, ist("host")) ||
-		    isteq(list[hdr].n, ist("proxy-connection")) ||
-		    isteq(list[hdr].n, ist("keep-alive")) ||
-		    isteq(list[hdr].n, ist("upgrade")) ||
-		    isteq(list[hdr].n, ist("transfer-encoding")))
+		if (isteq(n, ist("connection")) ||
+		    isteq(n, ist("host")) ||
+		    isteq(n, ist("proxy-connection")) ||
+		    isteq(n, ist("keep-alive")) ||
+		    isteq(n, ist("upgrade")) ||
+		    isteq(n, ist("transfer-encoding")))
 			continue;
 
-		if (isteq(list[hdr].n, ist("")))
+		if (isteq(n, ist("te"))) {
+			/* "te" may only be sent with "trailers" if this value
+			 * is present, otherwise it must be deleted.
+			 */
+			v = istist(v, ist("trailers"));
+			if (!v.ptr || (v.len > 8 && v.ptr[8] != ','))
+				continue;
+			v = ist("trailers");
+		}
+
+		if (isteq(n, ist("")))
 			break; // end
 
-		if (!hpack_encode_header(&outbuf, list[hdr].n, list[hdr].v)) {
+		if (!hpack_encode_header(&outbuf, n, v)) {
 			/* output full */
 			if (b_space_wraps(mbuf))
 				goto realign_again;