V3 Stream Session: SSL for STREAM FORWARD

better exception handling
boolean cleanups
This commit is contained in:
zzz
2015-06-27 14:31:55 +00:00
parent 9b2d416154
commit 194f20e18c
3 changed files with 78 additions and 23 deletions

View File

@ -95,7 +95,7 @@ class SAMHandlerFactory {
return null; return null;
} }
if (Boolean.valueOf(i2cpProps.getProperty(SAMBridge.PROP_AUTH))) { if (Boolean.parseBoolean(i2cpProps.getProperty(SAMBridge.PROP_AUTH))) {
String user = props.getProperty("USER"); String user = props.getProperty("USER");
String pw = props.getProperty("PASSWORD"); String pw = props.getProperty("PASSWORD");
if (user == null || pw == null) if (user == null || pw == null)

View File

@ -837,7 +837,7 @@ class SAMv3Handler extends SAMv1Handler
_log.debug("No parameters specified in STREAM CONNECT message"); _log.debug("No parameters specified in STREAM CONNECT message");
return false; return false;
} }
boolean verbose = props.getProperty("SILENT","false").equals("false"); boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT"));
String dest = props.getProperty("DESTINATION"); String dest = props.getProperty("DESTINATION");
if (dest == null) { if (dest == null) {
@ -877,7 +877,7 @@ class SAMv3Handler extends SAMv1Handler
return false ; return false ;
} }
protected boolean execStreamForwardIncoming( Properties props ) { private boolean execStreamForwardIncoming( Properties props ) {
try { try {
try { try {
streamForwardingSocket = true ; streamForwardingSocket = true ;
@ -894,9 +894,9 @@ class SAMv3Handler extends SAMv1Handler
return false ; return false ;
} }
protected boolean execStreamAccept( Properties props ) private boolean execStreamAccept( Properties props )
{ {
boolean verbose = props.getProperty( "SILENT", "false").equals("false"); boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT"));
try { try {
try { try {
notifyStreamResult(verbose, "OK", null); notifyStreamResult(verbose, "OK", null);

View File

@ -11,9 +11,16 @@ package net.i2p.sam;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException; import java.net.NoRouteToHostException;
import java.net.SocketTimeoutException;
import java.security.GeneralSecurityException;
import java.util.Properties; import java.util.Properties;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import net.i2p.I2PAppContext;
import net.i2p.I2PException; import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocket;
@ -21,6 +28,7 @@ import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.I2PSSLSocketFactory;
import net.i2p.util.Log; import net.i2p.util.Log;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
@ -41,6 +49,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi
private final Object socketServerLock = new Object(); private final Object socketServerLock = new Object();
private I2PServerSocket socketServer; private I2PServerSocket socketServer;
private static I2PSSLSocketFactory _sslSocketFactory;
private final String nick ; private final String nick ;
@ -91,7 +100,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi
throws I2PException, ConnectException, NoRouteToHostException, throws I2PException, ConnectException, NoRouteToHostException,
DataFormatException, InterruptedIOException, IOException { DataFormatException, InterruptedIOException, IOException {
boolean verbose = (props.getProperty("SILENT", "false").equals("false")); boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT"));
Destination d = SAMUtils.getDest(dest); Destination d = SAMUtils.getDest(dest);
I2PSocketOptions opts = socketMgr.buildOptions(props); I2PSocketOptions opts = socketMgr.buildOptions(props);
@ -202,10 +211,13 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi
} }
/**
* Forward sockets from I2P to the host/port provided
*/
public void startForwardingIncoming(Properties props, boolean sendPorts) throws SAMException, InterruptedIOException public void startForwardingIncoming(Properties props, boolean sendPorts) throws SAMException, InterruptedIOException
{ {
SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
boolean verbose = props.getProperty("SILENT", "false").equals("false"); boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT"));
if ( rec==null ) throw new InterruptedIOException() ; if ( rec==null ) throw new InterruptedIOException() ;
@ -223,7 +235,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("no host specified. Taken from the client socket : " + host +':'+port); _log.debug("no host specified. Taken from the client socket : " + host +':'+port);
} }
boolean isSSL = Boolean.parseBoolean(props.getProperty("SSL"));
synchronized( this.socketServerLock ) synchronized( this.socketServerLock )
{ {
@ -235,23 +247,28 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi
this.socketServer = this.socketMgr.getServerSocket(); this.socketServer = this.socketMgr.getServerSocket();
} }
SocketForwarder forwarder = new SocketForwarder(host, port, this, verbose, sendPorts); SocketForwarder forwarder = new SocketForwarder(host, port, isSSL, this, verbose, sendPorts);
(new Thread(rec.getThreadGroup(), forwarder, "SAMV3StreamForwarder")).start(); (new Thread(rec.getThreadGroup(), forwarder, "SAMV3StreamForwarder")).start();
} }
/**
* Forward sockets from I2P to the host/port provided
*/
private static class SocketForwarder implements Runnable private static class SocketForwarder implements Runnable
{ {
private final String host; private final String host;
private final int port; private final int port;
private final SAMv3StreamSession session; private final SAMv3StreamSession session;
private final boolean verbose, sendPorts; private final boolean isSSL, verbose, sendPorts;
SocketForwarder(String host, int port, SAMv3StreamSession session, boolean verbose, boolean sendPorts) { SocketForwarder(String host, int port, boolean isSSL,
SAMv3StreamSession session, boolean verbose, boolean sendPorts) {
this.host = host ; this.host = host ;
this.port = port ; this.port = port ;
this.session = session ; this.session = session ;
this.verbose = verbose ; this.verbose = verbose ;
this.sendPorts = sendPorts; this.sendPorts = sendPorts;
this.isSSL = isSSL;
} }
public void run() public void run()
@ -259,24 +276,62 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi
while (session.getSocketServer()!=null) { while (session.getSocketServer()!=null) {
// wait and accept a connection from I2P side // wait and accept a connection from I2P side
I2PSocket i2ps = null ; I2PSocket i2ps;
try { try {
i2ps = session.getSocketServer().accept(); i2ps = session.getSocketServer().accept();
} catch (Exception e) {} if (i2ps == null)
continue;
if (i2ps==null) { } catch (SocketTimeoutException ste) {
continue ; continue;
} } catch (ConnectException ce) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3StreamSession.class);
if (log.shouldLog(Log.WARN))
log.warn("Error accepting", ce);
try { Thread.sleep(50); } catch (InterruptedException ie) {}
continue;
} catch (I2PException ipe) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3StreamSession.class);
if (log.shouldLog(Log.WARN))
log.warn("Error accepting", ipe);
break;
}
// open a socket towards client // open a socket towards client
java.net.InetSocketAddress addr = new java.net.InetSocketAddress(host,port);
SocketChannel clientServerSock = null ; SocketChannel clientServerSock;
try { try {
clientServerSock = SocketChannel.open(addr) ; if (isSSL) {
} I2PAppContext ctx = I2PAppContext.getGlobalContext();
catch ( IOException e ) { synchronized(SAMv3StreamSession.class) {
continue ; if (_sslSocketFactory == null) {
try {
_sslSocketFactory = new I2PSSLSocketFactory(
ctx, true, "certificates/sam");
} catch (GeneralSecurityException gse) {
Log log = ctx.logManager().getLog(SAMv3StreamSession.class);
log.error("SSL error", gse);
try {
i2ps.close();
} catch (IOException ee) {}
throw new RuntimeException("SSL error", gse);
}
}
}
SSLSocket sock = (SSLSocket) _sslSocketFactory.createSocket(host, port);
I2PSSLSocketFactory.verifyHostname(ctx, sock, host);
clientServerSock = new SSLSocketChannel(sock);
} else {
InetSocketAddress addr = new InetSocketAddress(host, port);
clientServerSock = SocketChannel.open(addr) ;
}
} catch (IOException ioe) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3StreamSession.class);
if (log.shouldLog(Log.WARN))
log.warn("Error forwarding", ioe);
try {
i2ps.close();
} catch (IOException ee) {}
continue;
} }
// build pipes between both sockets // build pipes between both sockets