You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2023/12/13 08:23:51 UTC

(httpcomponents-core) 24/37: HTTPCORE-756: reject HTTPS requests received over insecure (non-TLS) connection per RFC 9110 section 7.4

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 353b7aaac75266e7ca827aaebb3cf071c74eca0e
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Tue Oct 3 11:57:00 2023 +0200

    HTTPCORE-756: reject HTTPS requests received over insecure (non-TLS) connection per RFC 9110 section 7.4
---
 .../hc/core5/http/protocol/RequestConformance.java |  4 +++
 .../http/protocol/TestStandardInterceptors.java    | 29 ++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConformance.java b/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConformance.java
index b81b4cc8b..adbf30e9b 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConformance.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConformance.java
@@ -35,6 +35,7 @@ import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpRequestInterceptor;
+import org.apache.hc.core5.http.MisdirectedRequestException;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.net.URIAuthority;
@@ -74,6 +75,9 @@ public class RequestConformance implements HttpRequestInterceptor {
                 throw new ProtocolException("Request host is empty");
             }
         }
+        if (URIScheme.HTTPS.same(request.getScheme()) && context.getAttribute(HttpCoreContext.SSL_SESSION) == null) {
+            throw new MisdirectedRequestException("HTTPS request over non-secure connection");
+        }
     }
 
 }
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java b/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java
index c17620f18..62c19ed7c 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java
@@ -29,6 +29,8 @@ package org.apache.hc.core5.http.protocol;
 
 import java.nio.charset.StandardCharsets;
 
+import javax.net.ssl.SSLSession;
+
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.Header;
@@ -38,6 +40,7 @@ import org.apache.hc.core5.http.HttpRequestInterceptor;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.Method;
+import org.apache.hc.core5.http.MisdirectedRequestException;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.io.entity.BasicHttpEntity;
 import org.apache.hc.core5.http.io.entity.EmptyInputStream;
@@ -49,6 +52,7 @@ import org.apache.hc.core5.http.message.BasicHeader;
 import org.apache.hc.core5.net.URIAuthority;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
 
 public class TestStandardInterceptors {
 
@@ -1056,6 +1060,31 @@ public class TestStandardInterceptors {
                 interceptor.process(request, request.getEntity(), context));
     }
 
+    @Test
+    public void testRequestConformanceHttps() throws Exception {
+        final HttpContext context = new BasicHttpContext(null);
+        context.setAttribute(HttpCoreContext.SSL_SESSION, Mockito.mock(SSLSession.class));
+        final BasicClassicHttpRequest request = new BasicClassicHttpRequest(Method.GET, "/");
+        request.setScheme("https");
+        request.setAuthority(new URIAuthority("somehost", 8888));
+        request.setPath("/path");
+        final RequestConformance interceptor = new RequestConformance();
+        interceptor.process(request, request.getEntity(), context);
+    }
+
+    @Test
+    public void testRequestConformanceHttpsInsecureConnection() throws Exception {
+        final HttpContext context = new BasicHttpContext(null);
+        context.setAttribute(HttpCoreContext.SSL_SESSION, null);
+        final BasicClassicHttpRequest request = new BasicClassicHttpRequest(Method.GET, "/");
+        request.setScheme("https");
+        request.setAuthority(new URIAuthority("somehost", 8888));
+        request.setPath("/path");
+        final RequestConformance interceptor = new RequestConformance();
+        Assertions.assertThrows(MisdirectedRequestException.class, () ->
+                interceptor.process(request, request.getEntity(), context));
+    }
+
     @Test
     public void testResponseConformanceNoContent() throws Exception {
         final HttpContext context = new BasicHttpContext(null);