diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index 88b130f5a..36949fd36 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -95,6 +95,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { private final long _tunnelId; private final Properties _clientOptions; private final Set _sessions; + private final TunnelController _controller; public static final int PACKET_DELAY = 100; @@ -152,6 +153,16 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { this(nocli_args); } + /** + * New standard constructor in router, with back ref to tc + * @param tc may be null + * @throws IllegalArgumentException + * @since 0.9.48 + */ + public I2PTunnel(TunnelController tc) { + this(nocli_args, null, tc); + } + /** * See usage() for options * @throws IllegalArgumentException @@ -166,10 +177,21 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * @throws IllegalArgumentException */ public I2PTunnel(String[] args, ConnectionEventListener lsnr) { + this(args, lsnr, null); + } + + /** + * @param lsnr may be null + * @param tc may be null + * @throws IllegalArgumentException + * @since 0.9.48 + */ + private I2PTunnel(String[] args, ConnectionEventListener lsnr, TunnelController tc) { super(); _context = I2PAppContext.getGlobalContext(); // new I2PAppContext(); _tunnelId = __tunnelId.incrementAndGet(); _log = _context.logManager().getLog(I2PTunnel.class); + _controller = tc; // as of 0.8.4, include context properties Properties p = _context.getProperties(); _clientOptions = p; @@ -366,6 +388,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { */ public Properties getClientOptions() { return _clientOptions; } + /** + * TunnelController that constructed this, or null. + * @return controller or null + * @since 0.9.48 + */ + TunnelController getController() { return _controller; } + private void addtask(I2PTunnelTask tsk) { tsk.setTunnel(this); if (tsk.isOpen()) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java index c0b981215..0be89ea6c 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java @@ -307,12 +307,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { if (session.isOffline()) { long exp = session.getOfflineExpiration(); long remaining = exp - getTunnel().getContext().clock().now(); - if (remaining <= 0) - throw new IllegalArgumentException("Offline signature expired " + DataHelper.formatTime(exp)); + if (remaining <= 0) { + String msg = "Offline signature for tunnel expired " + DataHelper.formatTime(exp); + _log.log(Log.CRIT, msg); + throw new IllegalArgumentException(msg); + } if (remaining < 60*24*60*60*1000L) { - String msg = "Offline signature expires in " + DataHelper.formatDuration(remaining); + String msg = "Offline signature for tunnel expires in " + DataHelper.formatDuration(remaining); _log.logAlways(Log.WARN, msg); - l.log(msg); + l.log("WARNING: " + msg); } } while (session.isClosed()) { @@ -641,9 +644,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { // so sockMgr will call ConnectionManager.setAllowIncomingConnections(true) again i2pss = sockMgr.getServerSocket(); } catch (I2PException ipe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe); - open = false; + String s = "Error accepting - KILLING THE TUNNEL SERVER"; + _log.log(Log.CRIT, s, ipe); + l.log(s + ": " + ipe); + // Tell TunnelController so it will change state + TunnelController tc = getTunnel().getController(); + if (tc != null) + tc.stopTunnel(); + else + close(true); if (i2ps != null) try { i2ps.close(); } catch (IOException ioe) {} break; } catch (ConnectException ce) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java index 537ed9503..2658aae66 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java @@ -213,7 +213,7 @@ public class TunnelController implements Logging { * overwrite existing ones) */ public TunnelController(Properties config, String prefix, boolean createKey) { - _tunnel = new I2PTunnel(); + _tunnel = new I2PTunnel(this); _log = I2PAppContext.getGlobalContext().logManager().getLog(TunnelController.class); setConfig(config, prefix); _messages = new ArrayList(4); diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketLocal.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketLocal.java index 8d11601ad..3975f49e1 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketLocal.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketLocal.java @@ -7,6 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger; import net.i2p.I2PAppContext; import net.i2p.client.I2PSession; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.SessionKey; import net.i2p.data.SessionTag; @@ -235,6 +236,10 @@ class PacketLocal extends Packet implements MessageOutputStream.WriteStatus { * @since 0.9.20 moved from Packet */ public int writeSignedPacket(byte buffer[], int offset) throws IllegalStateException { + if (isFlagSet(FLAG_SIGNATURE_OFFLINE)) { + if (_transientExpires < _context.clock().now()) + throw new IllegalStateException("Offline signature expired " + DataHelper.formatTime(_transientExpires)); + } setFlag(FLAG_SIGNATURE_INCLUDED); SigningPrivateKey key = _session.getPrivateKey(); int size = writePacket(buffer, offset, key.getType().getSigLen()); diff --git a/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java b/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java index 2ff77abe3..a4a5465bd 100644 --- a/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java +++ b/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java @@ -150,8 +150,11 @@ class I2CPMessageProducer { cfg.setOptions(p); if (isOffline) { long exp = session.getOfflineExpiration(); - if (exp < _context.clock().now()) - throw new I2PSessionException("Offline signature expired " + DataHelper.formatTime(exp)); + if (exp < _context.clock().now()) { + String s = "Offline signature for tunnel expired " + DataHelper.formatTime(exp); + _log.log(Log.CRIT, s); + throw new I2PSessionException(s); + } cfg.setOfflineSignature(exp, session.getTransientSigningPublicKey(), session.getOfflineSignature()); @@ -218,7 +221,7 @@ class I2CPMessageProducer { msg.setDestination(dest); SessionId sid = session.getSessionId(); if (sid == null) { - _log.error(session.toString() + " send message w/o session", new Exception()); + _log.error(session.toString() + " cannot send message, session closed", new Exception()); return; } msg.setSessionId(sid); @@ -245,7 +248,7 @@ class I2CPMessageProducer { msg.setDestination(dest); SessionId sid = session.getSessionId(); if (sid == null) { - _log.error(session.toString() + " send message w/o session", new Exception()); + _log.error(session.toString() + " cannot send message, session closed", new Exception()); return; } msg.setSessionId(sid); @@ -412,7 +415,7 @@ class I2CPMessageProducer { msg.setLeaseSet(leaseSet); SessionId sid = session.getSessionId(); if (sid == null) { - _log.error(session.toString() + " create LS w/o session", new Exception()); + _log.error(session.toString() + " cannot create LS, session closed", new Exception()); return; } msg.setSessionId(sid); @@ -444,7 +447,7 @@ class I2CPMessageProducer { msg.setSessionConfig(cfg); SessionId sid = session.getSessionId(); if (sid == null) { - _log.error(session.toString() + " update config w/o session", new Exception()); + _log.error(session.toString() + " cannot update config, session closed", new Exception()); return; } msg.setSessionId(sid); diff --git a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java index 00f98bd47..515f4a24f 100644 --- a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java +++ b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java @@ -326,10 +326,16 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { // offline keys if (session.isOffline()) { LeaseSet2 ls2 = (LeaseSet2) leaseSet; - boolean ok = ls2.setOfflineSignature(session.getOfflineExpiration(), session.getTransientSigningPublicKey(), + long exp = session.getOfflineExpiration(); + boolean ok = ls2.setOfflineSignature(exp, session.getTransientSigningPublicKey(), session.getOfflineSignature()); if (!ok) { - session.propogateError("Bad offline signature", new Exception()); + String s; + if (exp <= _context.clock().now()) + s = "Offline signature for tunnel expired " + DataHelper.formatTime(exp); + else + s = "Bad offline signature"; + session.propogateError(s, new Exception()); session.destroySession(); } } diff --git a/core/java/src/net/i2p/data/PrivateKeyFile.java b/core/java/src/net/i2p/data/PrivateKeyFile.java index b6db55fa7..f4d122e70 100644 --- a/core/java/src/net/i2p/data/PrivateKeyFile.java +++ b/core/java/src/net/i2p/data/PrivateKeyFile.java @@ -107,7 +107,7 @@ public class PrivateKeyFile { String signername = null; String signaction = null; String certfile = null; - int days = 365; + double days = 365; int mode = 0; boolean error = false; Getopt g = new Getopt("pkf", args, "t:nuxhse:c:a:o:d:r:p:b:y:z:w:"); @@ -178,7 +178,7 @@ public class PrivateKeyFile { break; case 'd': - days = Integer.parseInt(g.getOptarg()); + days = Double.parseDouble(g.getOptarg()); break; case 'r': @@ -344,7 +344,7 @@ public class PrivateKeyFile { SigningPublicKey tSigningPubKey = (SigningPublicKey) signingKeys[0]; SigningPrivateKey tSigningPrivKey = (SigningPrivateKey) signingKeys[1]; // set expires - long expires = System.currentTimeMillis() + (days * 24*60*60*1000L); + long expires = System.currentTimeMillis() + (long) (days * 24*60*60*1000L); // sign byte[] data = new byte[4 + 2 + tSigningPubKey.length()]; DataHelper.toLong(data, 0, 4, expires / 1000); @@ -374,7 +374,7 @@ public class PrivateKeyFile { java.security.PrivateKey jpriv = SigUtil.toJavaKey(priv); if (signername == null) signername = "example.i2p"; - X509Certificate cert = SelfSignedGenerator.generate(priv, signername, days); + X509Certificate cert = SelfSignedGenerator.generate(priv, signername, (int) days); java.security.cert.Certificate[] certs = { cert }; out = new FileOutputStream(certfile); CertUtil.exportPrivateKey(jpriv, certs, out); diff --git a/history.txt b/history.txt index f7e2f03d6..bc6f18640 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,21 @@ +2020-10-29 zzz + * Tunnels: Improved logging and handling of offline signature expiration + +2020-10-28 zzz + * Tunnels: Fix tunnel tests for ECIES routers + +2020-10-27 zzz + * Util: + - DNSOverHTTPS improvements + - Fix SSLEepGet handling of previous SSL state + +2020-10-26 zzz + * Util: Fix EepGet allowCaching parameter + +2020-10-25 zzz + * Router: Quick checks of eph. key MSB before Noise DH + * Tunnels: Additional checks on ECIES BRR to catch old/buggy routers + 2020-10-23 zzz * i2ptunnel: Remove mtn tunnel (new installs only) * Tunnels: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 7ca1a3ec2..5a58b19bc 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 10; + public final static long BUILD = 11; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index 6dad9859e..7a41cb2e0 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -251,8 +251,8 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi _log.error(msg); _runner.disconnectClient(msg); } else if (in.getOfflineSignature() != null && in.getOfflineExpiration() < _context.clock().now()) { - String msg = "Offline signature expired " + DataHelper.formatTime(in.getOfflineExpiration()); - _log.error(msg); + String msg = "Offline signature for tunnel expired " + DataHelper.formatTime(in.getOfflineExpiration()); + _log.log(Log.CRIT, msg); _runner.disconnectClient(msg); } else { _log.error("Signature verification failed on a create session message:\n" + in);