Skip to content

Commit 2175169

Browse files
committed
Use CR/LF to terminate HTTP headers and chunks
1 parent 4a1ecf0 commit 2175169

File tree

1 file changed

+57
-74
lines changed

1 file changed

+57
-74
lines changed

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java

Lines changed: 57 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -589,9 +589,8 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
589589
{
590590
EmbeddedChannel ch = new EmbeddedChannel(handler);
591591
ByteBuf buf = ch.alloc().buffer();
592-
ByteBufUtil.copy(AsciiString.of("This is not a valid HTTP line"), buf);
593-
buf.writeByte(HttpConstants.LF);
594-
buf.writeByte(HttpConstants.LF);
592+
appendAsciiLine("This is not a valid HTTP line", buf);
593+
appendCrLf(buf);
595594
ch.writeInbound(buf);
596595
ch.flushInbound();
597596
assertThat(dispatchThrowableReference.get().toString(), containsString("NOT A VALID HTTP LINE"));
@@ -602,9 +601,8 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
602601
{
603602
EmbeddedChannel ch = new EmbeddedChannel(handler);
604603
ByteBuf buf = ch.alloc().buffer();
605-
ByteBufUtil.copy(AsciiString.of("GET /this/is/a/valid/but/too/long/initial/line HTTP/1.1"), buf);
606-
buf.writeByte(HttpConstants.LF);
607-
buf.writeByte(HttpConstants.LF);
604+
appendAsciiLine("GET /this/is/a/valid/but/too/long/initial/line HTTP/1.1", buf);
605+
appendCrLf(buf);
608606
ch.writeInbound(buf);
609607
ch.flushInbound();
610608
assertThat(dispatchThrowableReference.get().toString(), containsString("HTTP line is larger than"));
@@ -615,11 +613,9 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
615613
{
616614
EmbeddedChannel ch = new EmbeddedChannel(handler);
617615
ByteBuf buf = ch.alloc().buffer();
618-
ByteBufUtil.copy(AsciiString.of("GET /url HTTP/1.1"), buf);
619-
buf.writeByte(HttpConstants.LF);
620-
ByteBufUtil.copy(AsciiString.of("Host"), buf);
621-
buf.writeByte(HttpConstants.LF);
622-
buf.writeByte(HttpConstants.LF);
616+
appendAsciiLine("GET /url HTTP/1.1", buf);
617+
appendAsciiLine("Host", buf);
618+
appendCrLf(buf);
623619
ch.writeInbound(buf);
624620
ch.flushInbound();
625621
assertThat(dispatchThrowableReference.get().toString(), containsString("No colon found"));
@@ -630,11 +626,9 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
630626
{
631627
EmbeddedChannel ch = new EmbeddedChannel(handler);
632628
ByteBuf buf = ch.alloc().buffer();
633-
ByteBufUtil.copy(AsciiString.of("GET /url HTTP/1.1"), buf);
634-
buf.writeByte(HttpConstants.LF);
635-
ByteBufUtil.copy(AsciiString.of("Host: this.looks.like.a.good.url.but.is.longer.than.permitted"), buf);
636-
buf.writeByte(HttpConstants.LF);
637-
buf.writeByte(HttpConstants.LF);
629+
appendAsciiLine("GET /url HTTP/1.1", buf);
630+
appendAsciiLine("Host: this.looks.like.a.good.url.but.is.longer.than.permitted", buf);
631+
appendCrLf(buf);
638632
ch.writeInbound(buf);
639633
ch.flushInbound();
640634
assertThat(dispatchThrowableReference.get().toString(), containsString("HTTP header is larger than"));
@@ -645,12 +639,11 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
645639
{
646640
EmbeddedChannel ch = new EmbeddedChannel(handler);
647641
ByteBuf buf = ch.alloc().buffer();
648-
ByteBufUtil.copy(AsciiString.of("GET /url HTTP/1.1"), buf);
649-
buf.writeByte(HttpConstants.LF);
642+
appendAsciiLine("GET /url HTTP/1.1", buf);
650643
ByteBufUtil.copy(AsciiString.of("Host: invalid header value"), buf);
651644
buf.writeByte(0x01);
652-
buf.writeByte(HttpConstants.LF);
653-
buf.writeByte(HttpConstants.LF);
645+
appendCrLf(buf);
646+
appendCrLf(buf);
654647
ch.writeInbound(buf);
655648
ch.flushInbound();
656649
assertThat(dispatchThrowableReference.get().toString(), containsString("Validation failed for header 'Host'"));
@@ -661,10 +654,8 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
661654
{
662655
EmbeddedChannel ch = new EmbeddedChannel(handler);
663656
ByteBuf buf = ch.alloc().buffer();
664-
ByteBufUtil.copy(AsciiString.of("GET /url HTTP/1.1"), buf);
665-
buf.writeByte(HttpConstants.LF);
666-
ByteBufUtil.copy(AsciiString.of("Host: localhost"), buf);
667-
buf.writeByte(HttpConstants.LF);
657+
appendAsciiLine("GET /url HTTP/1.1", buf);
658+
appendAsciiLine("Host: localhost", buf);
668659
ch.writeInbound(buf);
669660
ch.flushInbound();
670661
safeGet(ch.close());
@@ -718,33 +709,24 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
718709
// OPTIONS request with fixed length content written in one chunk
719710
{
720711
ByteBuf buf = ch.alloc().buffer();
721-
ByteBufUtil.copy(AsciiString.of("OPTIONS /url/whatever/fixed-length-single-chunk HTTP/1.1"), buf);
722-
buf.writeByte(HttpConstants.LF);
712+
appendAsciiLine("OPTIONS /url/whatever/fixed-length-single-chunk HTTP/1.1", buf);
723713
if (randomBoolean()) {
724-
ByteBufUtil.copy(AsciiString.of("Host: localhost"), buf);
725-
buf.writeByte(HttpConstants.LF);
714+
appendAsciiLine("Host: localhost", buf);
726715
}
727716
if (randomBoolean()) {
728-
ByteBufUtil.copy(AsciiString.of("Accept: */*"), buf);
729-
buf.writeByte(HttpConstants.LF);
717+
appendAsciiLine("Accept: */*", buf);
730718
}
731719
if (randomBoolean()) {
732-
ByteBufUtil.copy(AsciiString.of("Content-Encoding: gzip"), buf);
733-
buf.writeByte(HttpConstants.LF);
720+
appendAsciiLine("Content-Encoding: gzip", buf);
734721
}
735722
if (randomBoolean()) {
736-
ByteBufUtil.copy(
737-
AsciiString.of("Content-Type: " + randomFrom("text/plain; charset=utf-8", "application/json; charset=utf-8")),
738-
buf
739-
);
740-
buf.writeByte(HttpConstants.LF);
723+
appendAsciiLine("Content-Type: " + randomFrom("text/plain; charset=utf-8", "application/json; charset=utf-8"), buf);
741724
}
742725
String content = randomAlphaOfLengthBetween(4, 1024);
743726
// having a "Content-Length" request header is what makes it "fixed length"
744-
ByteBufUtil.copy(AsciiString.of("Content-Length: " + content.length()), buf);
745-
buf.writeByte(HttpConstants.LF);
727+
appendAsciiLine("Content-Length: " + content.length(), buf);
746728
// end of headers
747-
buf.writeByte(HttpConstants.LF);
729+
appendCrLf(buf);
748730
ByteBufUtil.copy(AsciiString.of(content), buf);
749731
// write everything in one single chunk
750732
ch.writeInbound(buf);
@@ -761,63 +743,44 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
761743
}
762744
{
763745
ByteBuf buf = ch.alloc().buffer();
764-
ByteBufUtil.copy(AsciiString.of("OPTIONS /url/whatever/chunked-transfer?encoding HTTP/1.1"), buf);
765-
buf.writeByte(HttpConstants.LF);
746+
appendAsciiLine("OPTIONS /url/whatever/chunked-transfer?encoding HTTP/1.1", buf);
766747
if (randomBoolean()) {
767-
ByteBufUtil.copy(AsciiString.of("Host: localhost"), buf);
768-
buf.writeByte(HttpConstants.LF);
748+
appendAsciiLine("Host: localhost", buf);
769749
}
770750
if (randomBoolean()) {
771-
ByteBufUtil.copy(AsciiString.of("Accept: */*"), buf);
772-
buf.writeByte(HttpConstants.LF);
751+
appendAsciiLine("Accept: */*", buf);
773752
}
774753
if (randomBoolean()) {
775-
ByteBufUtil.copy(AsciiString.of("Content-Encoding: gzip"), buf);
776-
buf.writeByte(HttpConstants.LF);
754+
appendAsciiLine("Content-Encoding: gzip", buf);
777755
}
778756
if (randomBoolean()) {
779-
ByteBufUtil.copy(
780-
AsciiString.of("Content-Type: " + randomFrom("text/plain; charset=utf-8", "application/json; charset=utf-8")),
781-
buf
782-
);
783-
buf.writeByte(HttpConstants.LF);
757+
appendAsciiLine("Content-Type: " + randomFrom("text/plain; charset=utf-8", "application/json; charset=utf-8"), buf);
784758
}
785759
// do not write a "Content-Length" header to make the request "variable length"
786760
if (randomBoolean()) {
787-
ByteBufUtil.copy(AsciiString.of("Transfer-Encoding: " + randomFrom("chunked", "gzip, chunked")), buf);
761+
appendAsciiLine("Transfer-Encoding: " + randomFrom("chunked", "gzip, chunked"), buf);
788762
} else {
789-
ByteBufUtil.copy(AsciiString.of("Transfer-Encoding: chunked"), buf);
763+
appendAsciiLine("Transfer-Encoding: chunked", buf);
790764
}
791-
buf.writeByte(HttpConstants.LF);
792-
buf.writeByte(HttpConstants.LF);
765+
// End of headers
766+
appendCrLf(buf);
793767
// maybe append some chunks as well
794768
String[] contentParts = randomArray(0, 4, String[]::new, () -> randomAlphaOfLengthBetween(1, 64));
795769
for (String content : contentParts) {
796-
ByteBufUtil.copy(AsciiString.of(Integer.toHexString(content.length())), buf);
797-
buf.writeByte(HttpConstants.CR);
798-
buf.writeByte(HttpConstants.LF);
799-
ByteBufUtil.copy(AsciiString.of(content), buf);
800-
buf.writeByte(HttpConstants.CR);
801-
buf.writeByte(HttpConstants.LF);
770+
appendAsciiLine(Integer.toHexString(content.length()), buf);
771+
appendAsciiLine(content, buf);
802772
}
803773
ch.writeInbound(buf);
804774
ch.flushInbound();
805775
ByteBuf buf2 = ch.alloc().buffer();
806776
contentParts = randomArray(1, 4, String[]::new, () -> randomAlphaOfLengthBetween(1, 64));
807777
for (String content : contentParts) {
808-
ByteBufUtil.copy(AsciiString.of(Integer.toHexString(content.length())), buf2);
809-
buf2.writeByte(HttpConstants.CR);
810-
buf2.writeByte(HttpConstants.LF);
811-
ByteBufUtil.copy(AsciiString.of(content), buf2);
812-
buf2.writeByte(HttpConstants.CR);
813-
buf2.writeByte(HttpConstants.LF);
778+
appendAsciiLine(Integer.toHexString(content.length()), buf2);
779+
appendAsciiLine(content, buf2);
814780
}
815781
// finish chunked request
816-
ByteBufUtil.copy(AsciiString.of("0"), buf2);
817-
buf2.writeByte(HttpConstants.CR);
818-
buf2.writeByte(HttpConstants.LF);
819-
buf2.writeByte(HttpConstants.CR);
820-
buf2.writeByte(HttpConstants.LF);
782+
appendAsciiLine("0", buf2);
783+
appendCrLf(buf2);
821784
ch.writeInbound(buf2);
822785
ch.flushInbound();
823786
ch.runPendingTasks();
@@ -836,4 +799,24 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
836799
}
837800
}
838801

802+
/**
803+
* Append a string as ASCII terminated by a CR/LF newline
804+
*
805+
* @param string The string to append
806+
* @param buf The buffer to append to
807+
*/
808+
private static void appendAsciiLine(String string, ByteBuf buf) {
809+
ByteBufUtil.copy(AsciiString.of(string), buf);
810+
appendCrLf(buf);
811+
}
812+
813+
/**
814+
* Append a CR/LF newline
815+
*
816+
* @param buf The buffer to append to
817+
*/
818+
private static void appendCrLf(ByteBuf buf) {
819+
buf.writeByte(HttpConstants.CR);
820+
buf.writeByte(HttpConstants.LF);
821+
}
839822
}

0 commit comments

Comments
 (0)