diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java index 32a17568cf16ccb5b412858bcc8366e21fb6e18f..a7dd7b13e678b62a703b8f931bdd6e63f786b52b 100644 --- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java +++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java @@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger; import net.i2p.client.I2PClient; import net.i2p.crypto.SessionKeyManager; import net.i2p.data.DatabaseEntry; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.EncryptedLeaseSet; import net.i2p.data.Hash; @@ -47,6 +48,8 @@ import net.i2p.router.Job; import net.i2p.router.JobImpl; import net.i2p.router.RouterContext; import net.i2p.router.crypto.TransientSessionKeyManager; +import net.i2p.router.crypto.ratchet.RatchetSKM; +import net.i2p.router.crypto.ratchet.MuxedSKM; import net.i2p.util.ConcurrentHashSet; import net.i2p.util.I2PThread; import net.i2p.util.Log; @@ -287,7 +290,10 @@ class ClientConnectionRunner { return _clientVersion; } - /** current client's sessionkeymanager */ + /** + * The current client's SessionKeyManager. + * As of 0.9.44, returned implementation varies based on supported encryption types. + */ public SessionKeyManager getSessionKeyManager() { return _sessionKeyManager; } /** @@ -544,8 +550,10 @@ class ClientConnectionRunner { if (!isPrimary) { // all encryption keys must be the same for (SessionParams sp : _sessions.values()) { - if (!dest.getPublicKey().equals(sp.dest.getPublicKey())) + if (!dest.getPublicKey().equals(sp.dest.getPublicKey())) { + _log.error("LS pubkey mismatch"); return SessionStatusMessage.STATUS_INVALID; + } } } SessionParams sp = new SessionParams(dest, isPrimary); @@ -560,10 +568,15 @@ class ClientConnectionRunner { _dontSendMSM = "none".equals(opts.getProperty(I2PClient.PROP_RELIABILITY, "").toLowerCase(Locale.US)); _dontSendMSMOnReceive = Boolean.parseBoolean(opts.getProperty(I2PClient.PROP_FAST_RECEIVE)); } + + // Set up the // per-destination session key manager to prevent rather easy correlation + // based on the specified encryption types in the config if (isPrimary && _sessionKeyManager == null) { int tags = TransientSessionKeyManager.DEFAULT_TAGS; int thresh = TransientSessionKeyManager.LOW_THRESHOLD; + boolean hasElg = false; + boolean hasEC = false; if (opts != null) { String ptags = opts.getProperty(PROP_TAGS); if (ptags != null) { @@ -573,8 +586,37 @@ class ClientConnectionRunner { if (pthresh != null) { try { thresh = Integer.parseInt(pthresh); } catch (NumberFormatException nfe) {} } + String senc = opts.getProperty("i2cp.leaseSetEncType"); + if (senc != null) { + String[] senca = DataHelper.split(senc, ","); + for (String sencaa : senca) { + if (sencaa.equals("0")) + hasElg = true; + else if (sencaa.equals("4")) + hasEC = true; + } + } else { + hasElg = true; + } + } else { + hasElg = true; + } + if (hasElg) { + if (hasEC) { + TransientSessionKeyManager tskm = new TransientSessionKeyManager(_context, tags, thresh); + RatchetSKM rskm = new RatchetSKM(_context); + _sessionKeyManager = new MuxedSKM(tskm, rskm); + } else { + _sessionKeyManager = new TransientSessionKeyManager(_context, tags, thresh); + } + } else { + if (hasEC) { + _sessionKeyManager = new RatchetSKM(_context); + } else { + _log.error("No supported encryption types in i2cp.leaseSetEncType for " + dest.toBase32()); + return SessionStatusMessage.STATUS_INVALID; + } } - _sessionKeyManager = new TransientSessionKeyManager(_context, tags, thresh); } return _manager.destinationEstablished(this, dest); } @@ -877,8 +919,8 @@ class ClientConnectionRunner { if (! current.getLease(i).getGateway().equals(set.getLease(i).getGateway())) break; if (i == leases - 1) { - if (_log.shouldLog(Log.INFO)) - _log.info("Requested leaseSet hasn't changed"); + if (_log.shouldDebug()) + _log.debug("Requested leaseSet hasn't changed"); if (onCreateJob != null) _context.jobQueue().addJob(onCreateJob); return; // no change