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