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"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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! */
|
||||
@Override
|
||||
protected byte[] getBytes() {
|
||||
|
@ -28,6 +28,7 @@ import net.i2p.client.I2PClient;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.data.DatabaseEntry;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.EncryptedLeaseSet;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.Payload;
|
||||
@ -99,6 +100,7 @@ class ClientConnectionRunner {
|
||||
/** For inbound traffic. true if i2cp.fastReceive = "true"; @since 0.9.4 */
|
||||
private boolean _dontSendMSMOnReceive;
|
||||
private final AtomicInteger _messageId; // messageId counter
|
||||
private Hash _encryptedLSHash;
|
||||
|
||||
// Was 32767 since the beginning (04-2004).
|
||||
// But it's 4 bytes in the I2CP spec and stored as a long in MessageID....
|
||||
@ -125,7 +127,10 @@ class ClientConnectionRunner {
|
||||
SessionConfig config;
|
||||
LeaseRequestState leaseRequest;
|
||||
Rerequest rerequestTimer;
|
||||
/** possibly decrypted */
|
||||
LeaseSet currentLeaseSet;
|
||||
/** only if encrypted */
|
||||
LeaseSet currentEncryptedLeaseSet;
|
||||
|
||||
SessionParams(Destination d, boolean isPrimary) {
|
||||
dest = d;
|
||||
@ -199,11 +204,17 @@ class ClientConnectionRunner {
|
||||
_acceptedPending.clear();
|
||||
if (_sessionKeyManager != null)
|
||||
_sessionKeyManager.shutdown();
|
||||
if (_encryptedLSHash != null)
|
||||
_manager.unregisterEncryptedDestination(this, _encryptedLSHash);
|
||||
_manager.unregisterConnection(this);
|
||||
// netdb may be null in unit tests
|
||||
if (_context.netDb() != null) {
|
||||
for (SessionParams sp : _sessions.values()) {
|
||||
LeaseSet ls = sp.currentLeaseSet;
|
||||
if (ls != null)
|
||||
_context.netDb().unpublish(ls);
|
||||
// unpublish encrypted LS also
|
||||
ls = sp.currentEncryptedLeaseSet;
|
||||
if (ls != null)
|
||||
_context.netDb().unpublish(ls);
|
||||
if (!sp.isPrimary)
|
||||
@ -431,6 +442,10 @@ class ClientConnectionRunner {
|
||||
// Tell client manger
|
||||
_manager.unregisterSession(id, sp.dest);
|
||||
LeaseSet ls = sp.currentLeaseSet;
|
||||
if (ls != null)
|
||||
_context.netDb().unpublish(ls);
|
||||
// unpublish encrypted LS also
|
||||
ls = sp.currentEncryptedLeaseSet;
|
||||
if (ls != null)
|
||||
_context.netDb().unpublish(ls);
|
||||
isPrimary = sp.isPrimary;
|
||||
@ -446,6 +461,10 @@ class ClientConnectionRunner {
|
||||
_log.info("Destroying remaining client subsession " + sp.sessionId);
|
||||
_manager.unregisterSession(sp.sessionId, sp.dest);
|
||||
LeaseSet ls = sp.currentLeaseSet;
|
||||
if (ls != null)
|
||||
_context.netDb().unpublish(ls);
|
||||
// unpublish encrypted LS also
|
||||
ls = sp.currentEncryptedLeaseSet;
|
||||
if (ls != null)
|
||||
_context.netDb().unpublish(ls);
|
||||
_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
|
||||
* 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) {
|
||||
Hash h = ls.getDestination().calculateHash();
|
||||
@ -596,6 +617,11 @@ class ClientConnectionRunner {
|
||||
return;
|
||||
LeaseRequestState state;
|
||||
synchronized (this) {
|
||||
if (ls.getType() == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
|
||||
EncryptedLeaseSet encls = (EncryptedLeaseSet) ls;
|
||||
sp.currentEncryptedLeaseSet = encls;
|
||||
ls = encls.getDecryptedLeaseSet();
|
||||
}
|
||||
sp.currentLeaseSet = ls;
|
||||
state = sp.leaseRequest;
|
||||
if (state == null) {
|
||||
@ -616,6 +642,30 @@ class ClientConnectionRunner {
|
||||
_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.
|
||||
* 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.
|
||||
* Side effect: Sets the session ID of the runner.
|
||||
@ -328,6 +342,31 @@ class ClientManager {
|
||||
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.
|
||||
* @return null on failure
|
||||
|
@ -632,6 +632,17 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
}
|
||||
}
|
||||
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())
|
||||
_log.debug("Publishing: " + ls);
|
||||
_context.netDb().publish(ls);
|
||||
@ -652,13 +663,8 @@ 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)
|
||||
if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
|
||||
EncryptedLeaseSet encls = (EncryptedLeaseSet) ls;
|
||||
_runner.leaseSetCreated(encls.getDecryptedLeaseSet());
|
||||
} else {
|
||||
_runner.leaseSetCreated(ls);
|
||||
}
|
||||
}
|
||||
|
||||
/** override for testing */
|
||||
protected void handleDestLookup(DestLookupMessage message) {
|
||||
|
@ -1200,7 +1200,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
||||
|
||||
public void unpublish(LeaseSet localLeaseSet) {
|
||||
if (!_initialized) return;
|
||||
Hash h = localLeaseSet.getDestination().calculateHash();
|
||||
Hash h = localLeaseSet.getHash();
|
||||
DatabaseEntry data = _ds.remove(h);
|
||||
|
||||
if (data == null) {
|
||||
|
Reference in New Issue
Block a user