You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2023/03/17 02:11:18 UTC

[james-project] branch master updated: [FIX] Prevent sending invalid content type upon downloads

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

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new b2e2070771 [FIX] Prevent sending invalid content type upon downloads
b2e2070771 is described below

commit b2e2070771310b2d27173436a5ba8ebca6a3d54c
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Mar 15 15:49:49 2023 +0700

    [FIX] Prevent sending invalid content type upon downloads
---
 .../org/apache/james/jmap/http/DownloadRoutes.java | 10 +++++++++-
 .../apache/james/jmap/routes/DownloadRoutes.scala  | 23 ++++++++++++++--------
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java
index d5b09cfe4d..9c55521dd9 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java
@@ -67,6 +67,7 @@ import com.google.common.base.CharMatcher;
 import com.google.common.collect.ImmutableList;
 
 import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http.HttpHeaderValidationUtil;
 import io.netty.handler.codec.http.HttpMethod;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
@@ -226,7 +227,7 @@ public class DownloadRoutes implements JMAPRoutes {
     private Mono<Void> downloadBlob(Optional<String> optionalName, HttpServerResponse response, long blobSize, ContentType blobContentType, InputStream stream) {
         return addContentDispositionHeader(optionalName, response)
             .header("Content-Length", String.valueOf(blobSize))
-            .header(CONTENT_TYPE, blobContentType.asString())
+            .header(CONTENT_TYPE, sanitizeHeaderValue(blobContentType.asString()))
             .status(OK)
             .send(ReactorUtils.toChunks(stream, BUFFER_SIZE)
                 .map(Unpooled::wrappedBuffer)
@@ -234,6 +235,13 @@ public class DownloadRoutes implements JMAPRoutes {
             .then();
     }
 
+    public String sanitizeHeaderValue(String s) {
+        if (HttpHeaderValidationUtil.validateValidHeaderValue(s) == -1) {
+            return s;
+        }
+        return "application/octet-stream";
+    }
+
     private HttpServerResponse addContentDispositionHeader(Optional<String> optionalName, HttpServerResponse resp) {
         return optionalName.map(name -> addContentDispositionHeaderRegardingEncoding(name, resp))
             .orElse(resp);
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/DownloadRoutes.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/DownloadRoutes.scala
index 63317105da..8b3446bd55 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/DownloadRoutes.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/DownloadRoutes.scala
@@ -18,13 +18,19 @@
  ****************************************************************/
 package org.apache.james.jmap.routes
 
+import java.io.InputStream
+import java.nio.charset.StandardCharsets
+import java.util.stream
+import java.util.stream.Stream
+
 import com.google.common.base.CharMatcher
 import eu.timepit.refined.numeric.NonNegative
 import eu.timepit.refined.refineV
 import io.netty.buffer.Unpooled
 import io.netty.handler.codec.http.HttpHeaderNames.{CONTENT_LENGTH, CONTENT_TYPE}
 import io.netty.handler.codec.http.HttpResponseStatus._
-import io.netty.handler.codec.http.{HttpMethod, HttpResponseStatus, QueryStringDecoder}
+import io.netty.handler.codec.http.{HttpHeaderValidationUtil, HttpMethod, HttpResponseStatus, QueryStringDecoder}
+import javax.inject.{Inject, Named}
 import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream
 import org.apache.james.jmap.HttpConstants.JSON_CONTENT_TYPE
 import org.apache.james.jmap.api.model.Size.{Size, sanitizeSize}
@@ -54,12 +60,6 @@ import reactor.core.publisher.Mono
 import reactor.core.scala.publisher.SMono
 import reactor.core.scheduler.Schedulers
 import reactor.netty.http.server.{HttpServerRequest, HttpServerResponse}
-import java.io.InputStream
-import java.nio.charset.StandardCharsets
-import java.util.stream
-import java.util.stream.Stream
-
-import javax.inject.{Inject, Named}
 
 import scala.compat.java8.FunctionConverters._
 import scala.jdk.CollectionConverters._
@@ -312,7 +312,7 @@ class DownloadRoutes @Inject()(@Named(InjectionKeys.RFC_8621) val authenticator:
       (stream: InputStream) => addContentDispositionHeader(optionalName)
         .compose(addContentLengthHeader(blob.size))
         .apply(response)
-        .header(CONTENT_TYPE, blobContentType.asString)
+        .header(CONTENT_TYPE, sanitizeHeaderValue(blobContentType.asString))
         .status(OK)
         .send(ReactorUtils.toChunks(stream, BUFFER_SIZE)
           .map(Unpooled.wrappedBuffer(_))
@@ -325,6 +325,13 @@ class DownloadRoutes @Inject()(@Named(InjectionKeys.RFC_8621) val authenticator:
     resp => optionalName.map(addContentDispositionHeaderRegardingEncoding(_, resp))
       .getOrElse(resp)
 
+  private def sanitizeHeaderValue(s: String): String =
+    if (HttpHeaderValidationUtil.validateValidHeaderValue(s) == -1) {
+      s
+    } else {
+      "application/octet-stream"
+    }
+
   private def addContentLengthHeader(sizeTry: Try[Size]): HttpServerResponse => HttpServerResponse =
     resp => sizeTry
       .map(size => resp.header("Content-Length", size.value.toString))


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org