@Test public void testInvalidHeaderDropped() throws Exception { String url = "http://example.org/mypage.html"; String domain = "example.org"; setupProxyRequestMock(domain, url, true, -1, null, null); HttpRequest req = new HttpRequest(Uri.parse(url)).setIgnoreCache(true); String contentType = "text/html; charset=UTF-8"; HttpResponse resp = new HttpResponseBuilder() .setResponseString("Hello") .addHeader("Content-Type", contentType) .addHeader("Content-Length", "200") // Disallowed header. .addHeader(":", "someDummyValue") // Invalid header name. .create(); expect(pipeline.execute(req)).andReturn(resp); replay(); HttpResponse recorder = proxyHandler.fetch(request); verify(); assertNull(recorder.getHeader(":")); assertNull(recorder.getHeader("Content-Length")); assertEquals(recorder.getHeader("Content-Type"), contentType); }
private void expectMime(String expectedMime, String contentMime, String outputMime) throws Exception { String url = "http://example.org/file.img?" + Param.REWRITE_MIME_TYPE.getKey() + '=' + expectedMime; String domain = "example.org"; setupProxyRequestMock(domain, url, false, -1, expectedMime, null); HttpRequest req = new HttpRequest(Uri.parse(url)).setRewriteMimeType(expectedMime); HttpResponse resp = new HttpResponseBuilder() .setResponseString("Hello") .addHeader("Content-Type", contentMime) .create(); expect(pipeline.execute(req)).andReturn(resp); replay(); HttpResponse response = proxyHandler.fetch(request); verify(); assertEquals(outputMime, response.getHeader("Content-Type")); reset(); }
// ProxyHandler throws INTERNAL_SERVER_ERRORS without isRecoverable() check. @Test public void testRecoverableRewritingException() throws Exception { String url = "http://example.org/mypage.html"; String domain = "example.org"; setupProxyRequestMock(domain, url, true, -1, null, null); String contentType = "text/html; charset=UTF-8"; HttpResponse resp = new HttpResponseBuilder() .setResponseString("Hello") .addHeader("Content-Type", contentType) .create(); expect(pipeline.execute((HttpRequest) EasyMock.anyObject())).andReturn(resp); replay(); final StringBuilder stringBuilder = new StringBuilder(""); ResponseRewriter rewriter = getResponseRewriterThatThrowsExceptions(stringBuilder); ResponseRewriterRegistry rewriterRegistry = new DefaultResponseRewriterRegistry(Arrays.<ResponseRewriter>asList(rewriter), null); ProxyHandler proxyHandler = new ProxyHandler(pipeline, rewriterRegistry, true); request.setReturnOriginalContentOnError(true); HttpResponse recorder = proxyHandler.fetch(request); verify(); // Ensure that original content is returned. assertEquals(recorder.getHeader("Content-Type"), contentType); assertEquals("Hello", recorder.getResponseAsString()); assertEquals("exceptionThrown", stringBuilder.toString()); }
@Test public void testOctetSetOnNullContentType() throws Exception { String url = "http://example.org/file.evil"; String domain = "example.org"; setupNoArgsProxyRequestMock(domain, url); expectGetAndReturnHeaders(url, Maps.<String, List<String>>newHashMap()); replay(); HttpResponse response = proxyHandler.fetch(request); verify(); assertEquals("application/octet-stream", response.getHeader("Content-Type")); assertNotNull(response.getHeader("Content-Disposition")); assertTrue(rewriter.responseWasRewritten()); }
public static String getMimeType(HttpRequest request, HttpResponse original) { String mimeType = request.getRewriteMimeType(); if (mimeType == null) { mimeType = original.getHeader("Content-Type"); } return mimeType != null ? mimeType.toLowerCase() : null; }
private void assertNoContentDispositionForFlash(String contentType) throws Exception { // Some headers may be blacklisted. These are OK. String url = "http://example.org/file.evil"; String domain = "example.org"; Map<String, List<String>> headers = ImmutableMap.of("Content-Type", Arrays.asList(contentType)); setupNoArgsProxyRequestMock(domain, url); expectGetAndReturnHeaders(url, headers); replay(); HttpResponse response = proxyHandler.fetch(request); verify(); assertEquals(contentType, response.getHeader("Content-Type")); assertNull(response.getHeader("Content-Disposition")); assertTrue(rewriter.responseWasRewritten()); }
@Test public void testHeadersPreserved() throws Exception { // Some headers may be blacklisted. These are OK. String url = "http://example.org/file.evil"; String domain = "example.org"; String contentType = "text/evil; charset=UTF-8"; String magicGarbage = "fadfdfdfd"; Map<String, List<String>> headers = Maps.newHashMap(); headers.put("Content-Type", Arrays.asList(contentType)); headers.put("X-Magic-Garbage", Arrays.asList(magicGarbage)); setupNoArgsProxyRequestMock(domain, url); expectGetAndReturnHeaders(url, headers); replay(); HttpResponse response = proxyHandler.fetch(request); verify(); assertEquals(contentType, response.getHeader("Content-Type")); assertEquals(magicGarbage, response.getHeader("X-Magic-Garbage")); assertTrue(rewriter.responseWasRewritten()); }
/** * We don't actually rewrite the image we just ensure that it is in fact a valid and known image * type. */ private boolean rewriteProxiedImage( HttpRequest request, HttpResponse resp, MutableContent content) { boolean imageIsSafe = false; try { String contentType = resp.getHeader("Content-Type"); if (contentType == null || contentType.toLowerCase().startsWith("image/")) { // Unspecified or unknown image mime type. try { ImageFormat imageFormat = Sanselan.guessFormat( new ByteSourceInputStream(resp.getResponse(), request.getUri().getPath())); if (imageFormat == ImageFormat.IMAGE_FORMAT_UNKNOWN) { logger.log( Level.INFO, "Unable to sanitize unknown image type " + request.getUri().toString()); return true; } imageIsSafe = true; // Return false to indicate that no rewriting occurred return false; } catch (IOException ioe) { throw new RuntimeException(ioe); } catch (ImageReadException ire) { // Unable to read the image so its not safe logger.log( Level.INFO, "Unable to detect image type for " + request.getUri().toString() + " for sanitized content", ire); return true; } } else { return true; } } finally { if (!imageIsSafe) { content.setContent(""); } } }
/** Sanitize a CSS file. */ private boolean rewriteProxiedCss( HttpRequest request, HttpResponse response, MutableContent content, ContentRewriterFeature rewriterFeature) { String sanitized = ""; try { String contentType = response.getHeader("Content-Type"); if (contentType == null || contentType.toLowerCase().startsWith("text/")) { SanitizingProxyingLinkRewriter cssImportRewriter = sanitizingProxyingLinkRewriterFactory.create( request.getGadget(), rewriterFeature, request.getContainer(), "text/css", false, request.getIgnoreCache()); SanitizingProxyingLinkRewriter cssImageRewriter = sanitizingProxyingLinkRewriterFactory.create( request.getGadget(), rewriterFeature, request.getContainer(), "image/*", false, request.getIgnoreCache()); sanitized = cssSanitizer.sanitize( content.getContent(), request.getUri(), cssImportRewriter, cssImageRewriter); } return true; } finally { // Set sanitized content in finally to ensure it is always cleared in // the case of errors content.setContent(sanitized); } }