From da893452ea8c1be7bde450e864c3ee2d04e84222 Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 4 Feb 2017 21:18:00 +0000 Subject: [PATCH] HTTP proxies: Pass through relative referer URIs, convert same-origin absolute referer URIs to relative (ticket #1862) --- .../i2p/i2ptunnel/I2PTunnelHTTPClient.java | 35 ++++++++++++++---- .../i2p/i2ptunnel/I2PTunnelHTTPServer.java | 36 ++++++++++++------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 754dbee76..6a7c0cf4a 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -400,6 +400,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn String authorization = null; int remotePort = 0; String referer = null; + URI origRequestURI = null; while((line = reader.readLine(method)) != null) { line = line.trim(); if(_log.shouldLog(Log.DEBUG)) { @@ -476,7 +477,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // to be the outgoing URI (with http:// if going to outproxy, otherwise without) URI requestURI; try { - requestURI = new URI(request); + origRequestURI = requestURI = new URI(request); if(requestURI.getRawUserInfo() != null || requestURI.getRawFragment() != null) { // these should never be sent to the proxy in the request line if(_log.shouldLog(Log.WARN)) { @@ -937,11 +938,33 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // save for address helper form below referer = line.substring(9); if (!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_REFERER))) { - // Shouldn't we be more specific, like accepting in-site referers ? - //line = "Referer: i2p"; - line = null; - continue; // completely strip the line - } + try { + // Either strip or rewrite the referer line + URI refererURI = new URI(referer); + String refererHost = refererURI.getHost(); + if (refererHost != null) { + String origHost = origRequestURI.getHost(); + if (!refererHost.equals(origHost) || + refererURI.getPort() != origRequestURI.getPort() || + !DataHelper.eq(refererURI.getScheme(), origRequestURI.getScheme())) { + line = null; + continue; // completely strip the line if everything doesn't match + } + // Strip to a relative URI, to hide the original host name + StringBuilder buf = new StringBuilder(); + buf.append("Referer: "); + String refererPath = refererURI.getRawPath(); + buf.append(refererPath != null ? refererPath : "/"); + String refererQuery = refererURI.getRawQuery(); + if (refererQuery != null) + buf.append('?').append(refererQuery); + line = buf.toString(); + } // else relative URI, leave in + } catch (URISyntaxException use) { + line = null; + continue; // completely strip the line + } + } // else allow } else if(lowercaseLine.startsWith("via: ") && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_VIA))) { //line = "Via: i2p"; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java index 693624ae4..49b7360d0 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java @@ -387,19 +387,29 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { return; } - if (Boolean.parseBoolean(opts.getProperty(OPT_REJECT_REFERER)) && - headers.containsKey("Referer")) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Refusing access from: " + - Base32.encode(peerHash.getData()) + ".b32.i2p" + - " with Referer: " + headers.get("Referer").get(0)); - try { - socket.getOutputStream().write(ERR_INPROXY.getBytes("UTF-8")); - } catch (IOException ioe) {} - try { - socket.close(); - } catch (IOException ioe) {} - return; + if (Boolean.parseBoolean(opts.getProperty(OPT_REJECT_REFERER))) { + // reject absolute URIs only + List h = headers.get("Referer"); + if (h != null) { + String referer = h.get(0); + if (referer.length() > 9) { + // "Referer: " + referer = referer.substring(9); + if (referer.startsWith("http://") || referer.startsWith("https://")) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Refusing access from: " + + Base32.encode(peerHash.getData()) + ".b32.i2p" + + " with Referer: " + referer); + try { + socket.getOutputStream().write(ERR_INPROXY.getBytes("UTF-8")); + } catch (IOException ioe) {} + try { + socket.close(); + } catch (IOException ioe) {} + return; + } + } + } } if (Boolean.parseBoolean(opts.getProperty(OPT_REJECT_USER_AGENTS)) &&