I2CP: Basic router-side handling of meta LS2

Improve error handling of LS2 params client-side
Methods to remember blinded key in LS2
This commit is contained in:
zzz
2019-01-10 13:39:18 +00:00
parent 8cd7e7de65
commit 0d330caf9a
4 changed files with 73 additions and 31 deletions

View File

@@ -103,6 +103,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
return true;
} catch (NumberFormatException nfe) {
session.propogateError("Bad LS2 type", nfe);
session.destroySession();
return true;
}
}
@@ -124,6 +125,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
leaseSet = new MetaLeaseSet();
} else {
session.propogateError("Unsupported LS2 type", new Exception());
session.destroySession();
return;
}
} else {
@@ -284,7 +286,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
session.getOfflineSignature());
if (!ok) {
session.propogateError("Bad offline signature", new Exception());
// TODO just let the router handle it for now
session.destroySession();
}
}
try {
@@ -306,6 +308,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
_log.debug("Created and signed LeaseSet: " + leaseSet);
} catch (DataFormatException dfe) {
session.propogateError("Error signing the leaseSet", dfe);
session.destroySession();
} catch (I2PSessionException ise) {
if (session.isClosed()) {
// race, closed while signing leaseset

View File

@@ -50,6 +50,7 @@ class RequestVariableLeaseSetMessageHandler extends RequestLeaseSetMessageHandle
leaseSet = new MetaLeaseSet();
} else {
session.propogateError("Unsupported LS2 type", new Exception());
session.destroySession();
return;
}
} else {

View File

@@ -39,6 +39,8 @@ public class LeaseSet2 extends LeaseSet {
protected Properties _options;
// only used if more than one key, otherwise null
private List<PublicKey> _encryptionKeys;
// If this leaseset was formerly blinded, the blinded hash, so we can find it again
private Hash _blindedHash;
private static final int FLAG_OFFLINE_KEYS = 1;
private static final int FLAG_UNPUBLISHED = 2;
@@ -182,6 +184,21 @@ public class LeaseSet2 extends LeaseSet {
return ctx.dsa().verifySignature(_offlineSignature, data, 0, data.length, getSigningPublicKey());
}
/**
* Set this on creation if known
*/
public void setBlindedHash(Hash bh) {
_blindedHash = bh;
}
/**
* The orignal blinded hash, where this came from.
* @return null if unknown or not previously blinded
*/
public Hash getBlindedHash() {
return _blindedHash;
}
///// overrides below here

View File

@@ -13,9 +13,11 @@ import java.util.Properties;
import net.i2p.CoreVersion;
import net.i2p.crypto.SigType;
import net.i2p.data.DatabaseEntry;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
import net.i2p.data.Payload;
import net.i2p.data.PublicKey;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
@@ -266,6 +268,14 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
}
}
props.putAll(inProps);
if ("7".equals(props.getProperty("i2cp.leaseSetType"))) {
// Prevent tunnel builds for Meta LS
// more TODO
props.setProperty("inbound.length", "0");
props.setProperty("outbound.length", "0");
props.setProperty("inbound.lengthVariance", "0");
props.setProperty("outbound.lengthVariance", "0");
}
cfg.setOptions(props);
// this sets the session id
int status = _runner.sessionEstablished(cfg);
@@ -469,10 +479,19 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
/** override for testing */
protected void handleCreateLeaseSet(CreateLeaseSetMessage message) {
if ( (message.getLeaseSet() == null) || (message.getPrivateKey() == null) || (message.getSigningPrivateKey() == null) ) {
LeaseSet ls = message.getLeaseSet();
if (ls == null) {
if (_log.shouldLog(Log.ERROR))
_log.error("Null lease set granted: " + message);
_runner.disconnectClient("Invalid CreateLeaseSetMessage");
_runner.disconnectClient("Invalid CreateLeaseSetMessage - null LS");
return;
}
int type = ls.getType();
if (type != DatabaseEntry.KEY_TYPE_META_LS2 &&
(message.getPrivateKey() == null || message.getSigningPrivateKey() == null)) {
if (_log.shouldLog(Log.ERROR))
_log.error("Null private keys: " + message);
_runner.disconnectClient("Invalid CreateLeaseSetMessage - null private keys");
return;
}
SessionId id = message.getSessionId();
@@ -486,42 +505,44 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
return;
}
Destination dest = cfg.getDestination();
Destination ndest = message.getLeaseSet().getDestination();
Destination ndest = ls.getDestination();
if (!dest.equals(ndest)) {
if (_log.shouldLog(Log.ERROR))
_log.error("Different destination in LS");
_runner.disconnectClient("Different destination in LS");
return;
}
LeaseSetKeys keys = _context.keyManager().getKeys(dest);
if (keys == null ||
!message.getPrivateKey().equals(keys.getDecryptionKey())) {
// Verify and register crypto keys if new or if changed
// Private crypto key should never change, and if it does,
// one of the checks below will fail
PublicKey pk;
try {
pk = message.getPrivateKey().toPublic();
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.ERROR))
_log.error("Bad private key in LS");
_runner.disconnectClient("Bad private key in LS");
return;
if (type != DatabaseEntry.KEY_TYPE_META_LS2) {
LeaseSetKeys keys = _context.keyManager().getKeys(dest);
if (keys == null ||
!message.getPrivateKey().equals(keys.getDecryptionKey())) {
// Verify and register crypto keys if new or if changed
// Private crypto key should never change, and if it does,
// one of the checks below will fail
PublicKey pk;
try {
pk = message.getPrivateKey().toPublic();
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.ERROR))
_log.error("Bad private key in LS");
_runner.disconnectClient("Bad private key in LS");
return;
}
if (!pk.equals(ls.getEncryptionKey())) {
if (_log.shouldLog(Log.ERROR))
_log.error("Private/public crypto key mismatch in LS");
_runner.disconnectClient("Private/public crypto key mismatch in LS");
return;
}
// just register new SPK, don't verify, unused
_context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey());
} else if (!message.getSigningPrivateKey().equals(keys.getRevocationKey())) {
// just register new SPK, don't verify, unused
_context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey());
}
if (!pk.equals(message.getLeaseSet().getEncryptionKey())) {
if (_log.shouldLog(Log.ERROR))
_log.error("Private/public crypto key mismatch in LS");
_runner.disconnectClient("Private/public crypto key mismatch in LS");
return;
}
// just register new SPK, don't verify, unused
_context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey());
} else if (!message.getSigningPrivateKey().equals(keys.getRevocationKey())) {
// just register new SPK, don't verify, unused
_context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey());
}
try {
_context.netDb().publish(message.getLeaseSet());
_context.netDb().publish(ls);
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.ERROR))
_log.error("Invalid leaseset from client", iae);
@@ -532,7 +553,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
_log.info("New lease set granted for destination " + dest);
// leaseSetCreated takes care of all the LeaseRequestState stuff (including firing any jobs)
_runner.leaseSetCreated(message.getLeaseSet());
_runner.leaseSetCreated(ls);
}
/** override for testing */