diff --git a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java index 7f76a2919..138b40e8c 100644 --- a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java +++ b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java @@ -103,6 +103,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { return true; } catch (NumberFormatException nfe) { session.propogateError("Bad LS2 type", nfe); + session.destroySession(); return true; } } @@ -124,6 +125,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { leaseSet = new MetaLeaseSet(); } else { session.propogateError("Unsupported LS2 type", new Exception()); + session.destroySession(); return; } } else { @@ -284,7 +286,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { session.getOfflineSignature()); if (!ok) { session.propogateError("Bad offline signature", new Exception()); - // TODO just let the router handle it for now + session.destroySession(); } } try { @@ -306,6 +308,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { _log.debug("Created and signed LeaseSet: " + leaseSet); } catch (DataFormatException dfe) { session.propogateError("Error signing the leaseSet", dfe); + session.destroySession(); } catch (I2PSessionException ise) { if (session.isClosed()) { // race, closed while signing leaseset diff --git a/core/java/src/net/i2p/client/impl/RequestVariableLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/impl/RequestVariableLeaseSetMessageHandler.java index c7fe69259..282ac7d50 100644 --- a/core/java/src/net/i2p/client/impl/RequestVariableLeaseSetMessageHandler.java +++ b/core/java/src/net/i2p/client/impl/RequestVariableLeaseSetMessageHandler.java @@ -50,6 +50,7 @@ class RequestVariableLeaseSetMessageHandler extends RequestLeaseSetMessageHandle leaseSet = new MetaLeaseSet(); } else { session.propogateError("Unsupported LS2 type", new Exception()); + session.destroySession(); return; } } else { diff --git a/core/java/src/net/i2p/data/LeaseSet2.java b/core/java/src/net/i2p/data/LeaseSet2.java index 353c05906..e65a85f19 100644 --- a/core/java/src/net/i2p/data/LeaseSet2.java +++ b/core/java/src/net/i2p/data/LeaseSet2.java @@ -39,6 +39,8 @@ public class LeaseSet2 extends LeaseSet { protected Properties _options; // only used if more than one key, otherwise null private List _encryptionKeys; + // If this leaseset was formerly blinded, the blinded hash, so we can find it again + private Hash _blindedHash; private static final int FLAG_OFFLINE_KEYS = 1; private static final int FLAG_UNPUBLISHED = 2; @@ -182,6 +184,21 @@ public class LeaseSet2 extends LeaseSet { return ctx.dsa().verifySignature(_offlineSignature, data, 0, data.length, getSigningPublicKey()); } + /** + * Set this on creation if known + */ + public void setBlindedHash(Hash bh) { + _blindedHash = bh; + } + + /** + * The orignal blinded hash, where this came from. + * @return null if unknown or not previously blinded + */ + public Hash getBlindedHash() { + return _blindedHash; + } + ///// overrides below here diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index 76836e315..12e73e6c4 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -13,9 +13,11 @@ import java.util.Properties; import net.i2p.CoreVersion; import net.i2p.crypto.SigType; +import net.i2p.data.DatabaseEntry; import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.Hash; +import net.i2p.data.LeaseSet; import net.i2p.data.Payload; import net.i2p.data.PublicKey; import net.i2p.data.i2cp.BandwidthLimitsMessage; @@ -266,6 +268,14 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi } } props.putAll(inProps); + if ("7".equals(props.getProperty("i2cp.leaseSetType"))) { + // Prevent tunnel builds for Meta LS + // more TODO + props.setProperty("inbound.length", "0"); + props.setProperty("outbound.length", "0"); + props.setProperty("inbound.lengthVariance", "0"); + props.setProperty("outbound.lengthVariance", "0"); + } cfg.setOptions(props); // this sets the session id int status = _runner.sessionEstablished(cfg); @@ -469,10 +479,19 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi /** override for testing */ protected void handleCreateLeaseSet(CreateLeaseSetMessage message) { - if ( (message.getLeaseSet() == null) || (message.getPrivateKey() == null) || (message.getSigningPrivateKey() == null) ) { + LeaseSet ls = message.getLeaseSet(); + if (ls == null) { if (_log.shouldLog(Log.ERROR)) _log.error("Null lease set granted: " + message); - _runner.disconnectClient("Invalid CreateLeaseSetMessage"); + _runner.disconnectClient("Invalid CreateLeaseSetMessage - null LS"); + return; + } + int type = ls.getType(); + if (type != DatabaseEntry.KEY_TYPE_META_LS2 && + (message.getPrivateKey() == null || message.getSigningPrivateKey() == null)) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Null private keys: " + message); + _runner.disconnectClient("Invalid CreateLeaseSetMessage - null private keys"); return; } SessionId id = message.getSessionId(); @@ -486,42 +505,44 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi return; } Destination dest = cfg.getDestination(); - Destination ndest = message.getLeaseSet().getDestination(); + Destination ndest = ls.getDestination(); if (!dest.equals(ndest)) { if (_log.shouldLog(Log.ERROR)) _log.error("Different destination in LS"); _runner.disconnectClient("Different destination in LS"); return; } - LeaseSetKeys keys = _context.keyManager().getKeys(dest); - if (keys == null || - !message.getPrivateKey().equals(keys.getDecryptionKey())) { - // Verify and register crypto keys if new or if changed - // Private crypto key should never change, and if it does, - // one of the checks below will fail - PublicKey pk; - try { - pk = message.getPrivateKey().toPublic(); - } catch (IllegalArgumentException iae) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Bad private key in LS"); - _runner.disconnectClient("Bad private key in LS"); - return; + if (type != DatabaseEntry.KEY_TYPE_META_LS2) { + LeaseSetKeys keys = _context.keyManager().getKeys(dest); + if (keys == null || + !message.getPrivateKey().equals(keys.getDecryptionKey())) { + // Verify and register crypto keys if new or if changed + // Private crypto key should never change, and if it does, + // one of the checks below will fail + PublicKey pk; + try { + pk = message.getPrivateKey().toPublic(); + } catch (IllegalArgumentException iae) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Bad private key in LS"); + _runner.disconnectClient("Bad private key in LS"); + return; + } + if (!pk.equals(ls.getEncryptionKey())) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Private/public crypto key mismatch in LS"); + _runner.disconnectClient("Private/public crypto key mismatch in LS"); + return; + } + // just register new SPK, don't verify, unused + _context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey()); + } else if (!message.getSigningPrivateKey().equals(keys.getRevocationKey())) { + // just register new SPK, don't verify, unused + _context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey()); } - if (!pk.equals(message.getLeaseSet().getEncryptionKey())) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Private/public crypto key mismatch in LS"); - _runner.disconnectClient("Private/public crypto key mismatch in LS"); - return; - } - // just register new SPK, don't verify, unused - _context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey()); - } else if (!message.getSigningPrivateKey().equals(keys.getRevocationKey())) { - // just register new SPK, don't verify, unused - _context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey()); } try { - _context.netDb().publish(message.getLeaseSet()); + _context.netDb().publish(ls); } catch (IllegalArgumentException iae) { if (_log.shouldLog(Log.ERROR)) _log.error("Invalid leaseset from client", iae); @@ -532,7 +553,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi _log.info("New lease set granted for destination " + dest); // leaseSetCreated takes care of all the LeaseRequestState stuff (including firing any jobs) - _runner.leaseSetCreated(message.getLeaseSet()); + _runner.leaseSetCreated(ls); } /** override for testing */