SOCKS: Fix NPE on lookup failure in SOCKS 4a

Remove duplicate lookups in SOCKS 5
Log tweaks
Streaming, i2ptunnel: Catch null destination in connect() calls
Synchronize Connection.setRemotePeer(); remove _remotePeerSet field
This commit is contained in:
zzz
2016-04-13 13:40:46 +00:00
parent 094cf14d4a
commit 5a2975ba65
9 changed files with 63 additions and 23 deletions

View File

@ -626,7 +626,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* adding it to the list of connections actually managed by this * adding it to the list of connections actually managed by this
* tunnel. * tunnel.
* *
* @param dest The destination to connect to * @param dest The destination to connect to, non-null
* @return a new I2PSocket * @return a new I2PSocket
*/ */
public I2PSocket createI2PSocket(Destination dest) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException { public I2PSocket createI2PSocket(Destination dest) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException {
@ -638,7 +638,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* adding it to the list of connections actually managed by this * adding it to the list of connections actually managed by this
* tunnel. * tunnel.
* *
* @param dest The destination to connect to * @param dest The destination to connect to, non-null
* @param port The destination port to connect to 0 - 65535 * @param port The destination port to connect to 0 - 65535
* @return a new I2PSocket * @return a new I2PSocket
* @since 0.9.9 * @since 0.9.9
@ -656,7 +656,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* adding it to the list of connections actually managed by this * adding it to the list of connections actually managed by this
* tunnel. * tunnel.
* *
* @param dest The destination to connect to * @param dest The destination to connect to, non-null
* @param opt Option to be used to open when opening the socket * @param opt Option to be used to open when opening the socket
* @return a new I2PSocket * @return a new I2PSocket
* *
@ -666,6 +666,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* @throws I2PException if there is some other I2P-related problem * @throws I2PException if there is some other I2P-related problem
*/ */
public I2PSocket createI2PSocket(Destination dest, I2PSocketOptions opt) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException { public I2PSocket createI2PSocket(Destination dest, I2PSocketOptions opt) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException {
if (dest == null)
throw new NullPointerException();
I2PSocket i2ps; I2PSocket i2ps;
verifySocketManager(); verifySocketManager();

View File

@ -22,6 +22,7 @@ import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions; import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.HexDump; import net.i2p.util.HexDump;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -212,14 +213,22 @@ public class SOCKS4aServer extends SOCKSServer {
try { try {
if (connHostName.toLowerCase(Locale.US).endsWith(".i2p") || if (connHostName.toLowerCase(Locale.US).endsWith(".i2p") ||
connHostName.toLowerCase(Locale.US).endsWith(".onion")) { connHostName.toLowerCase(Locale.US).endsWith(".onion")) {
_log.debug("connecting to " + connHostName + "..."); // Let's not do a new Dest for every request, huh?
// Let's not due a new Dest for every request, huh?
//I2PSocketManager sm = I2PSocketManagerFactory.createManager(); //I2PSocketManager sm = I2PSocketManagerFactory.createManager();
//destSock = sm.connect(I2PTunnel.destFromName(connHostName), null); //destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(connHostName);
if (dest == null) {
try {
sendRequestReply(Reply.CONNECTION_REFUSED, InetAddress.getByName("127.0.0.1"), 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Host not found");
}
if (_log.shouldDebug())
_log.debug("connecting to " + connHostName + "...");
Properties overrides = new Properties(); Properties overrides = new Properties();
I2PSocketOptions sktOpts = t.buildOptions(overrides); I2PSocketOptions sktOpts = t.buildOptions(overrides);
sktOpts.setPort(connPort); sktOpts.setPort(connPort);
destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName), sktOpts); destSock = t.createI2PSocket(dest, sktOpts);
} else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) { } else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
String err = "No localhost accesses allowed through the Socks Proxy"; String err = "No localhost accesses allowed through the Socks Proxy";
_log.error(err); _log.error(err);
@ -249,10 +258,18 @@ public class SOCKS4aServer extends SOCKSServer {
} }
int p = I2PAppContext.getGlobalContext().random().nextInt(proxies.size()); int p = I2PAppContext.getGlobalContext().random().nextInt(proxies.size());
String proxy = proxies.get(p); String proxy = proxies.get(p);
_log.debug("connecting to port " + connPort + " proxy " + proxy + " for " + connHostName + "..."); Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(proxy);
if (dest == null) {
try {
sendRequestReply(Reply.CONNECTION_REFUSED, InetAddress.getByName("127.0.0.1"), 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Outproxy not found");
}
if (_log.shouldDebug())
_log.debug("connecting to port " + connPort + " proxy " + proxy + " for " + connHostName + "...");
// this isn't going to work, these need to be socks outproxies so we need // this isn't going to work, these need to be socks outproxies so we need
// to do a socks session to them? // to do a socks session to them?
destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy)); destSock = t.createI2PSocket(dest);
} }
confirmConnection(); confirmConnection();
_log.debug("connection confirmed - exchanging data..."); _log.debug("connection confirmed - exchanging data...");

View File

@ -363,8 +363,7 @@ public class SOCKS5Server extends SOCKSServer {
try { try {
if (connHostName.toLowerCase(Locale.US).endsWith(".i2p")) { if (connHostName.toLowerCase(Locale.US).endsWith(".i2p")) {
_log.debug("connecting to " + connHostName + "..."); // Let's not do a new Dest for every request, huh?
// Let's not due a new Dest for every request, huh?
//I2PSocketManager sm = I2PSocketManagerFactory.createManager(); //I2PSocketManager sm = I2PSocketManagerFactory.createManager();
//destSock = sm.connect(I2PTunnel.destFromName(connHostName), null); //destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(connHostName); Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(connHostName);
@ -374,10 +373,12 @@ public class SOCKS5Server extends SOCKSServer {
} catch (IOException ioe) {} } catch (IOException ioe) {}
throw new SOCKSException("Host not found"); throw new SOCKSException("Host not found");
} }
if (_log.shouldDebug())
_log.debug("connecting to " + connHostName + "...");
Properties overrides = new Properties(); Properties overrides = new Properties();
I2PSocketOptions sktOpts = t.buildOptions(overrides); I2PSocketOptions sktOpts = t.buildOptions(overrides);
sktOpts.setPort(connPort); sktOpts.setPort(connPort);
destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName), sktOpts); destSock = t.createI2PSocket(dest, sktOpts);
} else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) { } else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
String err = "No localhost accesses allowed through the Socks Proxy"; String err = "No localhost accesses allowed through the Socks Proxy";
_log.error(err); _log.error(err);
@ -468,7 +469,7 @@ public class SOCKS5Server extends SOCKSServer {
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(proxy); Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(proxy);
if (dest == null) if (dest == null)
throw new SOCKSException("Outproxy not found"); throw new SOCKSException("Outproxy not found");
I2PSocket destSock = tun.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy), proxyOpts); I2PSocket destSock = tun.createI2PSocket(dest, proxyOpts);
DataOutputStream out = null; DataOutputStream out = null;
DataInputStream in = null; DataInputStream in = null;
try { try {

View File

@ -826,15 +826,22 @@ class Connection {
_timer.addEvent(event, msToWait); _timer.addEvent(event, msToWait);
} }
private boolean _remotePeerSet = false;
/** who are we talking with /** who are we talking with
* @return peer Destination * @return peer Destination or null if unset
*/
public synchronized Destination getRemotePeer() { return _remotePeer; }
/**
* @param peer non-null
*/ */
public Destination getRemotePeer() { return _remotePeer; }
public void setRemotePeer(Destination peer) { public void setRemotePeer(Destination peer) {
if (_remotePeerSet) throw new RuntimeException("Remote peer already set [" + _remotePeer + ", " + peer + "]"); if (peer == null)
_remotePeerSet = true; throw new NullPointerException();
_remotePeer = peer; synchronized(this) {
if (_remotePeer != null)
throw new RuntimeException("Remote peer already set [" + _remotePeer + ", " + peer + "]");
_remotePeer = peer;
}
// now that we know who the other end is, get the rtt etc. from the cache // now that we know who the other end is, get the rtt etc. from the cache
_connectionManager.updateOptsFromShare(this); _connectionManager.updateOptsFromShare(this);
} }
@ -1220,7 +1227,7 @@ class Connection {
buf.append(" from "); buf.append(" from ");
else else
buf.append(" to "); buf.append(" to ");
if (_remotePeerSet) if (_remotePeer != null)
buf.append(_remotePeer.calculateHash().toBase64().substring(0,4)); buf.append(_remotePeer.calculateHash().toBase64().substring(0,4));
else else
buf.append("unknown"); buf.append("unknown");

View File

@ -395,12 +395,14 @@ class ConnectionManager {
* Build a new connection to the given peer. This blocks if there is no * Build a new connection to the given peer. This blocks if there is no
* connection delay, otherwise it returns immediately. * connection delay, otherwise it returns immediately.
* *
* @param peer Destination to contact * @param peer Destination to contact, non-null
* @param opts Connection's options * @param opts Connection's options
* @param session generally the session from the constructor, but could be a subsession * @param session generally the session from the constructor, but could be a subsession
* @return new connection, or null if we have exceeded our limit * @return new connection, or null if we have exceeded our limit
*/ */
public Connection connect(Destination peer, ConnectionOptions opts, I2PSession session) { public Connection connect(Destination peer, ConnectionOptions opts, I2PSession session) {
if (peer == null)
throw new NullPointerException();
Connection con = null; Connection con = null;
long expiration = _context.clock().now(); long expiration = _context.clock().now();
long tmout = opts.getConnectTimeout(); long tmout = opts.getConnectTimeout();

View File

@ -479,7 +479,13 @@ class ConnectionPacketHandler {
if (con.getSendStreamId() <= 0) { if (con.getSendStreamId() <= 0) {
if (packet.isFlagSet(Packet.FLAG_SYNCHRONIZE)) { if (packet.isFlagSet(Packet.FLAG_SYNCHRONIZE)) {
con.setSendStreamId(packet.getReceiveStreamId()); con.setSendStreamId(packet.getReceiveStreamId());
con.setRemotePeer(packet.getOptionalFrom()); Destination dest = packet.getOptionalFrom();
if (dest == null) {
if (_log.shouldWarn())
_log.warn("SYN Packet without FROM");
return false;
}
con.setRemotePeer(dest);
return true; return true;
} else { } else {
// neither RST nor SYN and we dont have the stream id yet? // neither RST nor SYN and we dont have the stream id yet?

View File

@ -524,6 +524,8 @@ public class I2PSocketManagerFull implements I2PSocketManager {
*/ */
public I2PSocket connect(Destination peer, I2PSocketOptions options) public I2PSocket connect(Destination peer, I2PSocketOptions options)
throws I2PException, NoRouteToHostException { throws I2PException, NoRouteToHostException {
if (peer == null)
throw new NullPointerException();
if (options == null) if (options == null)
options = _defaultOptions; options = _defaultOptions;
ConnectionOptions opts = null; ConnectionOptions opts = null;

View File

@ -1,3 +1,6 @@
2016-04-13 zzz
* SOCKS: Fix NPE on lookup failure in SOCKS 4a
2016-04-07 zzz 2016-04-07 zzz
* Debian builds: * Debian builds:
- Prep for depending on tomcat packages - Prep for depending on tomcat packages

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 1; public final static long BUILD = 2;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";