Send and check target destination in first streaming SYN packet

This commit is contained in:
idk
2023-03-13 01:30:17 +00:00
parent ed513b6c15
commit 38666d2449
2 changed files with 34 additions and 0 deletions

View File

@ -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());

View File

@ -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);