From f1a277c4d782601ca8a2039437b8b20a3a4e660b Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 6 Jun 2020 18:44:49 +0000 Subject: [PATCH] I2CP, i2ptunnel: Check for expired offline signature client-side Better error message on the router side --- .../java/src/net/i2p/i2ptunnel/I2PTunnelServer.java | 11 +++++++++-- .../src/net/i2p/client/impl/I2CPMessageProducer.java | 6 +++++- .../i2p/router/client/ClientMessageEventListener.java | 6 +++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java index e5d850399..b974177ba 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java @@ -43,6 +43,7 @@ import net.i2p.client.streaming.IncomingConnectionFilter; import net.i2p.client.streaming.StatefulConnectionFilter; import net.i2p.crypto.SigType; import net.i2p.data.Base64; +import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.util.EventDispatcher; import net.i2p.util.I2PAppThread; @@ -302,9 +303,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { */ private void connectManager() { int retries = 0; - while (sockMgr.getSession().isClosed()) { + I2PSession session = sockMgr.getSession(); + if (session.isOffline()) { + long exp = session.getOfflineExpiration(); + if (exp < getTunnel().getContext().clock().now()) + throw new IllegalArgumentException("Offline signature expired " + DataHelper.formatTime(exp)); + } + while (session.isClosed()) { try { - sockMgr.getSession().connect(); + session.connect(); // Now connect the subsessions, if any List subs = sockMgr.getSubsessions(); if (!subs.isEmpty()) { diff --git a/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java b/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java index c43696c90..2ff77abe3 100644 --- a/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java +++ b/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java @@ -23,6 +23,7 @@ import net.i2p.client.I2PSessionException; import net.i2p.client.SendMessageOptions; import net.i2p.data.DatabaseEntry; import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.LeaseSet; import net.i2p.data.Payload; @@ -148,7 +149,10 @@ class I2CPMessageProducer { } cfg.setOptions(p); if (isOffline) { - cfg.setOfflineSignature(session.getOfflineExpiration(), + long exp = session.getOfflineExpiration(); + if (exp < _context.clock().now()) + throw new I2PSessionException("Offline signature expired " + DataHelper.formatTime(exp)); + cfg.setOfflineSignature(exp, session.getTransientSigningPublicKey(), session.getOfflineSignature()); } diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index b344035a3..6dad9859e 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -250,8 +250,12 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi msg += DataHelper.formatDuration(0 - skew) + " in the future"; _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); + _runner.disconnectClient(msg); } else { - _log.error("Signature verification failed on a create session message"); + _log.error("Signature verification failed on a create session message:\n" + in); _runner.disconnectClient("Invalid signature on CreateSessionMessage"); } return;