diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionDataReceiver.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionDataReceiver.java index 8be32b7da..89a8f82ec 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionDataReceiver.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionDataReceiver.java @@ -2,6 +2,7 @@ package net.i2p.client.streaming.impl; import net.i2p.I2PAppContext; import net.i2p.data.ByteArray; +import net.i2p.data.DataHelper; import net.i2p.util.Log; /** @@ -205,6 +206,14 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver { packet.setFlag(Packet.FLAG_SYNCHRONIZE); packet.setOptionalFrom(); packet.setOptionalMaxSize(_connection.getOptions().getMaxMessageSize()); + if (!_connection.isInbound()) { + byte[] h = _connection.getRemotePeer().calculateHash().getData(); + long[] fakeNacks = new long[8]; + for (int i = 0; i < 8; i++) { + fakeNacks[i] = DataHelper.fromLong(h, i << 2, 4); + } + packet.setNacks(fakeNacks); + } } packet.setLocalPort(_connection.getLocalPort()); packet.setRemotePort(_connection.getPort()); diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionManager.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionManager.java index fbb6703cb..e68b16e91 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionManager.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/ConnectionManager.java @@ -250,6 +250,31 @@ class ConnectionManager { ByteArray ba = _cache.acquire(); boolean sigOk = synPacket.verifySignature(_context, ba.getData()); _cache.release(ba); + if (sigOk) { + long[] nacks = synPacket.getNacks(); + if (nacks != null && nacks.length == 8) { + // we use the packet's session because it may be a subsession + Hash hash = synPacket.getSession().getMyDestination().calculateHash(); + byte[] h = hash.getData(); + for (int i = 0; i < 8; i++) { + if (nacks[i] != DataHelper.fromLong(h, i << 2, 4)) { + if (_log.shouldWarn()) { + // glue it back together for logging only + byte[] g = new byte[32]; + for (int j = 0; j < 8; j++) { + DataHelper.toLong(g, j << 2, 4, nacks[j]); + } + Hash ghash = new Hash(g); + _log.warn("Sig passed but hash failed, expected: " + hash.toBase32() + " got: " + ghash.toBase32()); + } + sigOk = false; + break; + } + } + if (sigOk && _log.shouldWarn()) + _log.warn("Validated SYN NACKS from: " + from.toBase32()); + } + } if (!sigOk) { if (_log.shouldWarn()) _log.warn("Received unsigned / forged SYN apparently from " + from.toBase32() + ": " + synPacket);