I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Unverified Commit 4ef4ae4d authored by zzz's avatar zzz
Browse files

Streaming: Refactor sig checking

Save sig OK status in Packet
Fix spot where byte array cache was not used
Do not send NACK 0 for retransmitted SYNs
Remove 1-byte DataHelper.toLong() calls
parent ac50eefe
No related branches found
No related tags found
No related merge requests found
......@@ -16,6 +16,7 @@ import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
import net.i2p.util.ByteCache;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.ConvertToHash;
import net.i2p.util.LHMCache;
......@@ -54,6 +55,7 @@ class ConnectionManager {
/** since 0.9, each manager instantiates its own timer */
private final SimpleTimer2 _timer;
private final Map<Long, Object> _recentlyClosed;
private final ByteCache _cache = ByteCache.getInstance(32, 4*1024);
private static final Object DUMMY = new Object();
/** cache of the property to detect changes */
......@@ -84,6 +86,8 @@ class ConnectionManager {
/**
* Manage all conns for this session
*
* @param session the primary session, packets may come in on subsessions also
*/
public ConnectionManager(I2PAppContext context,
I2PSession session,
......@@ -237,6 +241,21 @@ class ConnectionManager {
* or if the connection was rejected
*/
public Connection receiveConnection(Packet synPacket) {
Destination from = synPacket.getOptionalFrom();
if (from == null) {
if (_log.shouldWarn())
_log.warn("SYN w/o FROM: " + synPacket);
return null;
}
ByteArray ba = _cache.acquire();
boolean sigOk = synPacket.verifySignature(_context, ba.getData());
_cache.release(ba);
if (!sigOk) {
if (_log.shouldWarn())
_log.warn("Received unsigned / forged SYN apparently from " + from.toBase32() + ": " + synPacket);
return null;
}
boolean reject = false;
int retryAfter = 0;
......@@ -261,9 +280,6 @@ class ConnectionManager {
_context.statManager().addRateData("stream.receiveActive", 1);
if (reject) {
Destination from = synPacket.getOptionalFrom();
if (from == null)
return null;
String resp = _defaultOptions.getLimitAction();
if ("drop".equals(resp)) {
// always drop
......
......@@ -285,6 +285,7 @@ class ConnectionPacketHandler {
if (isSYN && (packet.getSendStreamId() <= 0) ) {
// don't honor the ACK 0 in SYN packets received when the other side
// has obviously not seen our messages
// and ignore NACKs
fastAck = false;
} else {
fastAck = ack(con, packet.getAckThrough(), packet.getNacks(), packet, isNew, choke);
......@@ -650,8 +651,9 @@ class ConnectionPacketHandler {
packet.isFlagSet(Packet.FLAG_SYNCHRONIZE | Packet.FLAG_CLOSE | Packet.FLAG_SIGNATURE_INCLUDED)) {
// we need a valid signature
SigningPublicKey spk = con.getRemoteSPK();
// inbound SYNs are now verifed in ConnectionManager; Packet caches the result
ByteArray ba = _cache.acquire();
boolean sigOk = packet.verifySignature(_context, spk, null);
boolean sigOk = packet.verifySignature(_context, spk, ba.getData());
_cache.release(ba);
if (!sigOk) {
throw new I2PException("Received unsigned / forged packet: " + packet);
......
......@@ -214,9 +214,14 @@ class MessageInputStream extends InputStream {
* Adds the ack-through and nack fields to a packet we are building for transmission
*/
public void updateAcks(PacketLocal packet) {
synchronized (_dataLock) {
packet.setAckThrough(_highestBlockId);
packet.setNacks(locked_getNacks());
if (packet.getSendStreamId() > 0 || !packet.isFlagSet(Packet.FLAG_SYNCHRONIZE)) {
synchronized (_dataLock) {
packet.setAckThrough(_highestBlockId);
packet.setNacks(locked_getNacks());
}
} else {
// do not send NACK 0 for retransmitted SYNs
packet.setAckThrough(-1);
}
}
......
......@@ -79,6 +79,7 @@ class Packet {
private int _resendDelay;
private int _flags;
private ByteArray _payload;
private boolean _sigVerified;
// the next four are set only if the flags say so
protected Signature _optionSignature;
protected Destination _optionFrom;
......@@ -466,18 +467,15 @@ class Packet {
cur += 4;
if (_nacks != null) {
// if max win is ever > 255, limit to 255
DataHelper.toLong(buffer, cur, 1, _nacks.length);
cur++;
buffer[cur++] = (byte) _nacks.length;
for (int i = 0; i < _nacks.length; i++) {
DataHelper.toLong(buffer, cur, 4, _nacks[i]);
cur += 4;
}
} else {
DataHelper.toLong(buffer, cur, 1, 0);
cur++;
buffer[cur++] = 0;
}
DataHelper.toLong(buffer, cur, 1, _resendDelay > 0 ? _resendDelay : 0);
cur++;
buffer[cur++] = _resendDelay > 0 ? ((byte) _resendDelay) : 0;
DataHelper.toLong(buffer, cur, 2, _flags);
cur += 2;
......@@ -782,6 +780,8 @@ class Packet {
* false otherwise.
*/
public boolean verifySignature(I2PAppContext ctx, SigningPublicKey altSPK, byte buffer[]) {
if (_sigVerified)
return true;
if (!isFlagSet(FLAG_SIGNATURE_INCLUDED)) return false;
if (_optionSignature == null) return false;
SigningPublicKey spk = _optionFrom != null ? _optionFrom.getSigningPublicKey() : altSPK;
......@@ -852,7 +852,9 @@ class Packet {
l.warn("Signature failed on " + toString(), iae);
ok = false;
}
if (!ok) {
if (ok) {
_sigVerified = true;
} else {
Log l = ctx.logManager().getLog(Packet.class);
if (l.shouldLog(Log.WARN))
l.warn("Signature failed on " + toString() + " using SPK " + spk);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment