netty5/codec-http2/src/test/java/io/netty/handler/codec/http2/InOrderHttp2Headers.java
Julien Hoarau 3e6b54bb59 Fix failing h2spec tests 8.1.2.1 related to pseudo-headers validation
Motivation:

According to the spec:
All pseudo-header fields MUST appear in the header block before regular
header fields. Any request or response that contains a pseudo-header
field that appears in a header block after
a regular header field MUST be treated as malformed (Section 8.1.2.6).

Pseudo-header fields are only valid in the context in which they are defined.
Pseudo-header fields defined for requests MUST NOT appear in responses;
pseudo-header fields defined for responses MUST NOT appear in requests.
Pseudo-header fields MUST NOT appear in trailers.
Endpoints MUST treat a request or response that contains undefined or
invalid pseudo-header fields as malformed (Section 8.1.2.6).

Clients MUST NOT accept a malformed response. Note that these requirements
are intended to protect against several types of common attacks against HTTP;
they are deliberately strict because being permissive can expose
implementations to these vulnerabilities.

Modifications:

- Introduce validation in HPackDecoder

Result:

- Requests with unknown pseudo-field headers are rejected
- Requests with containing response specific pseudo-headers are rejected
- Requests where pseudo-header appear after regular header are rejected
- h2spec 8.1.2.1 pass
2018-01-29 19:42:56 -08:00

105 lines
2.9 KiB
Java

/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.http2;
import io.netty.handler.codec.CharSequenceValueConverter;
import io.netty.handler.codec.DefaultHeaders;
import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
/**
* Http2Headers implementation that preserves headers insertion order.
*/
public class InOrderHttp2Headers
extends DefaultHeaders<CharSequence, CharSequence, Http2Headers> implements Http2Headers {
InOrderHttp2Headers() {
super(CharSequenceValueConverter.INSTANCE);
}
@Override
public boolean equals(Object o) {
return o instanceof Http2Headers && equals((Http2Headers) o, CASE_SENSITIVE_HASHER);
}
@Override
public int hashCode() {
return hashCode(CASE_SENSITIVE_HASHER);
}
@Override
public Http2Headers method(CharSequence value) {
set(PseudoHeaderName.METHOD.value(), value);
return this;
}
@Override
public Http2Headers scheme(CharSequence value) {
set(PseudoHeaderName.SCHEME.value(), value);
return this;
}
@Override
public Http2Headers authority(CharSequence value) {
set(PseudoHeaderName.AUTHORITY.value(), value);
return this;
}
@Override
public Http2Headers path(CharSequence value) {
set(PseudoHeaderName.PATH.value(), value);
return this;
}
@Override
public Http2Headers status(CharSequence value) {
set(PseudoHeaderName.STATUS.value(), value);
return this;
}
@Override
public CharSequence method() {
return get(PseudoHeaderName.METHOD.value());
}
@Override
public CharSequence scheme() {
return get(PseudoHeaderName.SCHEME.value());
}
@Override
public CharSequence authority() {
return get(PseudoHeaderName.AUTHORITY.value());
}
@Override
public CharSequence path() {
return get(PseudoHeaderName.PATH.value());
}
@Override
public CharSequence status() {
return get(PseudoHeaderName.STATUS.value());
}
@Override
public boolean contains(CharSequence name, CharSequence value, boolean caseInsensitive) {
return contains(name, value, caseInsensitive ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER);
}
}