Merge branch 'ri-size' into 'master'

Router: Enforce consistent max RI size

See merge request i2p-hackers/i2p.i2p!168
This commit is contained in:
zzz
2024-01-02 13:33:51 +00:00
6 changed files with 28 additions and 4 deletions

View File

@@ -185,6 +185,8 @@ public class DatabaseStoreMessage extends FastI2NPMessageImpl {
// If we do delay it, getEntry() will have to check if _dbEntry is null and _byteCache
// is non-null, and then decompress.
byte decompressed[] = DataHelper.decompress(data, curIndex, compressedSize);
if (decompressed.length > RouterInfo.MAX_UNCOMPRESSED_SIZE)
throw new I2NPMessageException("RI too big: " + decompressed.length);
_dbEntry.readBytes(new ByteArrayInputStream(decompressed));
} catch (DataFormatException dfe) {
throw new I2NPMessageException("Error reading the routerInfo", dfe);

View File

@@ -87,6 +87,15 @@ public class RouterInfo extends DatabaseEntry {
public static final char CAPABILITY_HIDDEN = 'H';
private static final int MAX_ADDRESSES = 16;
/**
* All legit RIs are currently under 2KB.
* May need to be adjusted if we add a huge new enctype or sigtype.
* Enforced in DatabaseStoreMessage, the transports, and reseed.
*
* @since 0.9.62
*/
public static final int MAX_UNCOMPRESSED_SIZE = 4*1024;
/** Public string of chars which serve as bandwidth capacity markers
* NOTE: individual chars defined in Router.java
*/

View File

@@ -541,6 +541,12 @@ public class PersistentDataStore extends TransientDataStore {
* @since 0.9.58
*/
public boolean read() {
if (_routerFile.length() > RouterInfo.MAX_UNCOMPRESSED_SIZE) {
if (_log.shouldWarn())
_log.warn("RI file too big " + _routerFile.length() + ": " + _routerFile);
_routerFile.delete();
return false;
}
if (!shouldRead()) return false;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Reading " + _routerFile);

View File

@@ -24,6 +24,7 @@ import net.i2p.crypto.SU3File;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.router.RouterInfo;
import net.i2p.router.RouterClock;
import net.i2p.router.RouterContext;
import net.i2p.router.util.EventLog;
@@ -911,7 +912,7 @@ public class Reseeder {
String name = f.getName();
if (name.length() != ROUTERINFO_PREFIX.length() + 44 + ROUTERINFO_SUFFIX.length() ||
name.equals(ourB64) ||
f.length() > 10*1024 ||
f.length() > RouterInfo.MAX_UNCOMPRESSED_SIZE ||
f.lastModified() < minTime ||
!name.startsWith(ROUTERINFO_PREFIX) ||
!name.endsWith(ROUTERINFO_SUFFIX) ||

View File

@@ -117,10 +117,12 @@ class NTCP2Payload {
case BLOCK_ROUTERINFO:
int flag = payload[i] & 0xff;
if (len - 1 > RouterInfo.MAX_UNCOMPRESSED_SIZE)
throw new DataFormatException("RI too big: " + (len - 1));
RouterInfo alice = new RouterInfo();
ByteArrayInputStream bais = new ByteArrayInputStream(payload, i + 1, len - 1);
alice.readBytes(bais, true);
cb.gotRI(alice, isHandshake, (flag & 0x01) != 0 && len < 4*1024);
cb.gotRI(alice, isHandshake, (flag & 0x01) != 0 && len < 3*1024);
break;
case BLOCK_I2NP:

View File

@@ -197,16 +197,20 @@ class SSU2Payload {
if (ftot == 0)
throw new IOException("Bad fragment count for ROUTERINFO: " + ftot);
if (fnum == 0 && ftot == 1) {
RouterInfo alice = new RouterInfo();
ByteArrayInputStream bais;
if (gz) {
byte decompressed[] = DataHelper.decompress(payload, i + 2, len - 2);
if (decompressed.length > RouterInfo.MAX_UNCOMPRESSED_SIZE)
throw new DataFormatException("RI too big: " + decompressed.length);
bais = new ByteArrayInputStream(decompressed);
} else {
if (len - 2 > RouterInfo.MAX_UNCOMPRESSED_SIZE)
throw new DataFormatException("RI too big: " + (len - 2));
bais = new ByteArrayInputStream(payload, i + 2, len - 2);
}
if (bais.available() >= 4*1024)
if (bais.available() >= 3*1024)
flood = false;
RouterInfo alice = new RouterInfo();
alice.readBytes(bais, true);
cb.gotRI(alice, isHandshake, flood);
} else {