diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java index 49bb72bd91a1f1c9de9220978eba7f2403b041d0..fbe1e905a39580d91b3846433518712db5733987 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java @@ -95,7 +95,7 @@ class SAMHandlerFactory { return null; } - if (Boolean.valueOf(i2cpProps.getProperty(SAMBridge.PROP_AUTH))) { + if (Boolean.parseBoolean(i2cpProps.getProperty(SAMBridge.PROP_AUTH))) { String user = props.getProperty("USER"); String pw = props.getProperty("PASSWORD"); if (user == null || pw == null) diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index 01ed1f211e8beeec86c7d6aa92882e3908c4e7e7..eb5ff9f64e6ed13231ce653f9ac1f32c3455d450 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -837,7 +837,7 @@ class SAMv3Handler extends SAMv1Handler _log.debug("No parameters specified in STREAM CONNECT message"); return false; } - boolean verbose = props.getProperty("SILENT","false").equals("false"); + boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT")); String dest = props.getProperty("DESTINATION"); if (dest == null) { @@ -877,7 +877,7 @@ class SAMv3Handler extends SAMv1Handler return false ; } - protected boolean execStreamForwardIncoming( Properties props ) { + private boolean execStreamForwardIncoming( Properties props ) { try { try { streamForwardingSocket = true ; @@ -894,9 +894,9 @@ class SAMv3Handler extends SAMv1Handler 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 { notifyStreamResult(verbose, "OK", null); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java index d927c6f3c2f5d03448a74008d7d46dadab21b41f..3bd98e71c774101f7316ba5e9661436d8643b4f9 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java @@ -11,9 +11,16 @@ package net.i2p.sam; import java.io.IOException; import java.io.InterruptedIOException; import java.net.ConnectException; +import java.net.InetSocketAddress; import java.net.NoRouteToHostException; +import java.net.SocketTimeoutException; +import java.security.GeneralSecurityException; 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.client.streaming.I2PServerSocket; 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.Destination; import net.i2p.util.I2PAppThread; +import net.i2p.util.I2PSSLSocketFactory; import net.i2p.util.Log; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -41,6 +49,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi private final Object socketServerLock = new Object(); private I2PServerSocket socketServer; + private static I2PSSLSocketFactory _sslSocketFactory; private final String nick ; @@ -91,7 +100,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi throws I2PException, ConnectException, NoRouteToHostException, DataFormatException, InterruptedIOException, IOException { - boolean verbose = (props.getProperty("SILENT", "false").equals("false")); + boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT")); Destination d = SAMUtils.getDest(dest); 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 { 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() ; @@ -223,7 +235,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi if (_log.shouldLog(Log.DEBUG)) _log.debug("no host specified. Taken from the client socket : " + host +':'+port); } - + boolean isSSL = Boolean.parseBoolean(props.getProperty("SSL")); synchronized( this.socketServerLock ) { @@ -235,23 +247,28 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi 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(); } + /** + * Forward sockets from I2P to the host/port provided + */ private static class SocketForwarder implements Runnable { private final String host; private final int port; 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.port = port ; this.session = session ; this.verbose = verbose ; this.sendPorts = sendPorts; + this.isSSL = isSSL; } public void run() @@ -259,24 +276,62 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi while (session.getSocketServer()!=null) { // wait and accept a connection from I2P side - I2PSocket i2ps = null ; + I2PSocket i2ps; try { i2ps = session.getSocketServer().accept(); - } catch (Exception e) {} - - if (i2ps==null) { - continue ; - } + if (i2ps == null) + continue; + } catch (SocketTimeoutException ste) { + 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 - java.net.InetSocketAddress addr = new java.net.InetSocketAddress(host,port); - SocketChannel clientServerSock = null ; + SocketChannel clientServerSock; try { - clientServerSock = SocketChannel.open(addr) ; - } - catch ( IOException e ) { - continue ; + if (isSSL) { + I2PAppContext ctx = I2PAppContext.getGlobalContext(); + synchronized(SAMv3StreamSession.class) { + 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