forked from I2P_Developers/i2p.i2p
I2CP, NetDB: More encrypted LS2 fixes (WIP)
Marked encrypted LS hash as local Fix isCurrent() on encrypted LS Fix unpublish of encrypted LS
This commit is contained in:
@ -281,6 +281,21 @@ public class LeaseSet2 extends LeaseSet {
|
|||||||
log.warn("Don't set revocation key in ls2", new Exception("I did it"));
|
log.warn("Don't set revocation key in ls2", new Exception("I did it"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the leaseset is currently valid, at least within a given
|
||||||
|
* fudge factor.
|
||||||
|
* Overridden to use the expiration time instead of the last expiration.
|
||||||
|
*
|
||||||
|
* @param fudge milliseconds fudge factor to allow between the current time
|
||||||
|
* @return true if there are current leases, false otherwise
|
||||||
|
* @since 0.9.39
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isCurrent(long fudge) {
|
||||||
|
long now = Clock.getInstance().now();
|
||||||
|
return _expires > now - fudge;
|
||||||
|
}
|
||||||
|
|
||||||
/** without sig! */
|
/** without sig! */
|
||||||
@Override
|
@Override
|
||||||
protected byte[] getBytes() {
|
protected byte[] getBytes() {
|
||||||
|
@ -28,6 +28,7 @@ import net.i2p.client.I2PClient;
|
|||||||
import net.i2p.crypto.SessionKeyManager;
|
import net.i2p.crypto.SessionKeyManager;
|
||||||
import net.i2p.data.DatabaseEntry;
|
import net.i2p.data.DatabaseEntry;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
|
import net.i2p.data.EncryptedLeaseSet;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.data.LeaseSet;
|
import net.i2p.data.LeaseSet;
|
||||||
import net.i2p.data.Payload;
|
import net.i2p.data.Payload;
|
||||||
@ -99,6 +100,7 @@ class ClientConnectionRunner {
|
|||||||
/** For inbound traffic. true if i2cp.fastReceive = "true"; @since 0.9.4 */
|
/** For inbound traffic. true if i2cp.fastReceive = "true"; @since 0.9.4 */
|
||||||
private boolean _dontSendMSMOnReceive;
|
private boolean _dontSendMSMOnReceive;
|
||||||
private final AtomicInteger _messageId; // messageId counter
|
private final AtomicInteger _messageId; // messageId counter
|
||||||
|
private Hash _encryptedLSHash;
|
||||||
|
|
||||||
// Was 32767 since the beginning (04-2004).
|
// Was 32767 since the beginning (04-2004).
|
||||||
// But it's 4 bytes in the I2CP spec and stored as a long in MessageID....
|
// But it's 4 bytes in the I2CP spec and stored as a long in MessageID....
|
||||||
@ -125,7 +127,10 @@ class ClientConnectionRunner {
|
|||||||
SessionConfig config;
|
SessionConfig config;
|
||||||
LeaseRequestState leaseRequest;
|
LeaseRequestState leaseRequest;
|
||||||
Rerequest rerequestTimer;
|
Rerequest rerequestTimer;
|
||||||
|
/** possibly decrypted */
|
||||||
LeaseSet currentLeaseSet;
|
LeaseSet currentLeaseSet;
|
||||||
|
/** only if encrypted */
|
||||||
|
LeaseSet currentEncryptedLeaseSet;
|
||||||
|
|
||||||
SessionParams(Destination d, boolean isPrimary) {
|
SessionParams(Destination d, boolean isPrimary) {
|
||||||
dest = d;
|
dest = d;
|
||||||
@ -199,11 +204,17 @@ class ClientConnectionRunner {
|
|||||||
_acceptedPending.clear();
|
_acceptedPending.clear();
|
||||||
if (_sessionKeyManager != null)
|
if (_sessionKeyManager != null)
|
||||||
_sessionKeyManager.shutdown();
|
_sessionKeyManager.shutdown();
|
||||||
|
if (_encryptedLSHash != null)
|
||||||
|
_manager.unregisterEncryptedDestination(this, _encryptedLSHash);
|
||||||
_manager.unregisterConnection(this);
|
_manager.unregisterConnection(this);
|
||||||
// netdb may be null in unit tests
|
// netdb may be null in unit tests
|
||||||
if (_context.netDb() != null) {
|
if (_context.netDb() != null) {
|
||||||
for (SessionParams sp : _sessions.values()) {
|
for (SessionParams sp : _sessions.values()) {
|
||||||
LeaseSet ls = sp.currentLeaseSet;
|
LeaseSet ls = sp.currentLeaseSet;
|
||||||
|
if (ls != null)
|
||||||
|
_context.netDb().unpublish(ls);
|
||||||
|
// unpublish encrypted LS also
|
||||||
|
ls = sp.currentEncryptedLeaseSet;
|
||||||
if (ls != null)
|
if (ls != null)
|
||||||
_context.netDb().unpublish(ls);
|
_context.netDb().unpublish(ls);
|
||||||
if (!sp.isPrimary)
|
if (!sp.isPrimary)
|
||||||
@ -431,6 +442,10 @@ class ClientConnectionRunner {
|
|||||||
// Tell client manger
|
// Tell client manger
|
||||||
_manager.unregisterSession(id, sp.dest);
|
_manager.unregisterSession(id, sp.dest);
|
||||||
LeaseSet ls = sp.currentLeaseSet;
|
LeaseSet ls = sp.currentLeaseSet;
|
||||||
|
if (ls != null)
|
||||||
|
_context.netDb().unpublish(ls);
|
||||||
|
// unpublish encrypted LS also
|
||||||
|
ls = sp.currentEncryptedLeaseSet;
|
||||||
if (ls != null)
|
if (ls != null)
|
||||||
_context.netDb().unpublish(ls);
|
_context.netDb().unpublish(ls);
|
||||||
isPrimary = sp.isPrimary;
|
isPrimary = sp.isPrimary;
|
||||||
@ -446,6 +461,10 @@ class ClientConnectionRunner {
|
|||||||
_log.info("Destroying remaining client subsession " + sp.sessionId);
|
_log.info("Destroying remaining client subsession " + sp.sessionId);
|
||||||
_manager.unregisterSession(sp.sessionId, sp.dest);
|
_manager.unregisterSession(sp.sessionId, sp.dest);
|
||||||
LeaseSet ls = sp.currentLeaseSet;
|
LeaseSet ls = sp.currentLeaseSet;
|
||||||
|
if (ls != null)
|
||||||
|
_context.netDb().unpublish(ls);
|
||||||
|
// unpublish encrypted LS also
|
||||||
|
ls = sp.currentEncryptedLeaseSet;
|
||||||
if (ls != null)
|
if (ls != null)
|
||||||
_context.netDb().unpublish(ls);
|
_context.netDb().unpublish(ls);
|
||||||
_context.tunnelManager().removeAlias(sp.dest);
|
_context.tunnelManager().removeAlias(sp.dest);
|
||||||
@ -588,6 +607,8 @@ class ClientConnectionRunner {
|
|||||||
/**
|
/**
|
||||||
* called after a new leaseSet is granted by the client, the NetworkDb has been
|
* called after a new leaseSet is granted by the client, the NetworkDb has been
|
||||||
* updated. This takes care of all the LeaseRequestState stuff (including firing any jobs)
|
* updated. This takes care of all the LeaseRequestState stuff (including firing any jobs)
|
||||||
|
*
|
||||||
|
* @param ls, if encrypted, the encrypted LS, not the decrypted one
|
||||||
*/
|
*/
|
||||||
void leaseSetCreated(LeaseSet ls) {
|
void leaseSetCreated(LeaseSet ls) {
|
||||||
Hash h = ls.getDestination().calculateHash();
|
Hash h = ls.getDestination().calculateHash();
|
||||||
@ -596,6 +617,11 @@ class ClientConnectionRunner {
|
|||||||
return;
|
return;
|
||||||
LeaseRequestState state;
|
LeaseRequestState state;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
if (ls.getType() == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
|
||||||
|
EncryptedLeaseSet encls = (EncryptedLeaseSet) ls;
|
||||||
|
sp.currentEncryptedLeaseSet = encls;
|
||||||
|
ls = encls.getDecryptedLeaseSet();
|
||||||
|
}
|
||||||
sp.currentLeaseSet = ls;
|
sp.currentLeaseSet = ls;
|
||||||
state = sp.leaseRequest;
|
state = sp.leaseRequest;
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
@ -616,6 +642,30 @@ class ClientConnectionRunner {
|
|||||||
_context.jobQueue().addJob(state.getOnGranted());
|
_context.jobQueue().addJob(state.getOnGranted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after destinationEstablished(),
|
||||||
|
* when an encrypted leaseset is created, so we know it's local.
|
||||||
|
* Add to the clients list. Check for a dup hash.
|
||||||
|
* Caller must call runner.disconnectClient() on failure.
|
||||||
|
*
|
||||||
|
* @param hash the location of the encrypted LS, will change every day
|
||||||
|
* @return success, false on dup
|
||||||
|
* @since 0.9.39
|
||||||
|
*/
|
||||||
|
public boolean registerEncryptedLS(Hash hash) {
|
||||||
|
boolean rv = true;
|
||||||
|
synchronized(this) {
|
||||||
|
if (!hash.equals(_encryptedLSHash)) {
|
||||||
|
if (_encryptedLSHash != null)
|
||||||
|
_manager.unregisterEncryptedDestination(this, _encryptedLSHash);
|
||||||
|
rv = _manager.registerEncryptedDestination(this, hash);
|
||||||
|
if (rv)
|
||||||
|
_encryptedLSHash = hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a DisconnectMessage and log with level Log.ERROR.
|
* Send a DisconnectMessage and log with level Log.ERROR.
|
||||||
* This is always bad.
|
* This is always bad.
|
||||||
|
@ -288,6 +288,20 @@ class ClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the hash for the encrypted LS.
|
||||||
|
* Call before unregisterConnection, or when the hash changes.
|
||||||
|
*
|
||||||
|
* @since 0.9.39
|
||||||
|
*/
|
||||||
|
public void unregisterEncryptedDestination(ClientConnectionRunner runner, Hash hash) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Unregistering encrypted LS " + hash.toBase32());
|
||||||
|
synchronized (_runners) {
|
||||||
|
_runnersByHash.remove(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add to the clients list. Check for a dup destination.
|
* Add to the clients list. Check for a dup destination.
|
||||||
* Side effect: Sets the session ID of the runner.
|
* Side effect: Sets the session ID of the runner.
|
||||||
@ -328,6 +342,31 @@ class ClientManager {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after destinationEstablished(),
|
||||||
|
* when an encrypted leaseset is created, so we know it's local.
|
||||||
|
* Add to the clients list. Check for a dup hash.
|
||||||
|
* Caller must call runner.disconnectClient() on failure.
|
||||||
|
*
|
||||||
|
* @param hash the location of the encrypted LS, will change every day
|
||||||
|
* @return success, false on dup
|
||||||
|
* @since 0.9.39
|
||||||
|
*/
|
||||||
|
public boolean registerEncryptedDestination(ClientConnectionRunner runner, Hash hash) {
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("New encrypted LS " + hash.toBase32());
|
||||||
|
|
||||||
|
boolean rv;
|
||||||
|
synchronized (_runners) {
|
||||||
|
rv = !_runnersByHash.containsKey(hash);
|
||||||
|
if (rv)
|
||||||
|
_runnersByHash.put(hash, runner);
|
||||||
|
}
|
||||||
|
if (!rv)
|
||||||
|
_log.error("Encrypted dest collision " + hash.toBase32());
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new random, unused sessionId. Caller must synch on _runners.
|
* Generate a new random, unused sessionId. Caller must synch on _runners.
|
||||||
* @return null on failure
|
* @return null on failure
|
||||||
|
@ -632,6 +632,17 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
|
||||||
|
// so the client manager knows it's a local hash
|
||||||
|
// we could put this in runner.leaseSetCreated(), but
|
||||||
|
// need to set it before calling publish()
|
||||||
|
Hash newHash = ls.getHash();
|
||||||
|
boolean ok = _runner.registerEncryptedLS(newHash);
|
||||||
|
if (!ok) {
|
||||||
|
_runner.disconnectClient("Duplicate hash of encrypted LS2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Publishing: " + ls);
|
_log.debug("Publishing: " + ls);
|
||||||
_context.netDb().publish(ls);
|
_context.netDb().publish(ls);
|
||||||
@ -652,12 +663,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
|||||||
_log.info("New lease set granted for destination " + dest);
|
_log.info("New lease set granted for destination " + dest);
|
||||||
|
|
||||||
// leaseSetCreated takes care of all the LeaseRequestState stuff (including firing any jobs)
|
// leaseSetCreated takes care of all the LeaseRequestState stuff (including firing any jobs)
|
||||||
if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
|
_runner.leaseSetCreated(ls);
|
||||||
EncryptedLeaseSet encls = (EncryptedLeaseSet) ls;
|
|
||||||
_runner.leaseSetCreated(encls.getDecryptedLeaseSet());
|
|
||||||
} else {
|
|
||||||
_runner.leaseSetCreated(ls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** override for testing */
|
/** override for testing */
|
||||||
|
@ -1200,7 +1200,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
|
|
||||||
public void unpublish(LeaseSet localLeaseSet) {
|
public void unpublish(LeaseSet localLeaseSet) {
|
||||||
if (!_initialized) return;
|
if (!_initialized) return;
|
||||||
Hash h = localLeaseSet.getDestination().calculateHash();
|
Hash h = localLeaseSet.getHash();
|
||||||
DatabaseEntry data = _ds.remove(h);
|
DatabaseEntry data = _ds.remove(h);
|
||||||
|
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
|
Reference in New Issue
Block a user