forked from I2P_Developers/i2p.i2p
NetDB: Track client that requested LS
OCMOSJ: Don't send to a RAP LS
This commit is contained in:
@ -70,6 +70,7 @@ public class LeaseSet extends DatabaseEntry {
|
||||
protected final List<Lease> _leases;
|
||||
protected boolean _receivedAsPublished;
|
||||
private boolean _receivedAsReply;
|
||||
private Hash _receivedBy;
|
||||
// Store these since isCurrent() and getEarliestLeaseDate() are called frequently
|
||||
private long _firstExpiration;
|
||||
protected long _lastExpiration;
|
||||
@ -198,9 +199,30 @@ public class LeaseSet extends DatabaseEntry {
|
||||
*/
|
||||
public boolean getReceivedAsReply() { return _receivedAsReply; }
|
||||
|
||||
/** set to true @since 0.7.14 */
|
||||
/**
|
||||
* set to true
|
||||
* @since 0.7.14
|
||||
*/
|
||||
public void setReceivedAsReply() { _receivedAsReply = true; }
|
||||
|
||||
/**
|
||||
* The Hash of the local client that received this LS,
|
||||
* null if the router or unknown.
|
||||
*
|
||||
* @since 0.9.47
|
||||
*/
|
||||
public Hash getReceivedBy() { return _receivedBy; }
|
||||
|
||||
/**
|
||||
* Also sets receivedAsReply to true
|
||||
* @param localClient may be null
|
||||
* @since 0.9.47
|
||||
*/
|
||||
public void setReceivedBy(Hash localClient) {
|
||||
_receivedAsReply = true;
|
||||
_receivedBy = localClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalStateException if already signed
|
||||
*/
|
||||
|
@ -74,6 +74,17 @@ public abstract class NetworkDatabaseFacade implements Service {
|
||||
*/
|
||||
public abstract void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest);
|
||||
|
||||
/**
|
||||
* Unconditionally lookup using the client's tunnels.
|
||||
*
|
||||
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
|
||||
* @param onFindJob may be null
|
||||
* @param onFailedLookupJob may be null
|
||||
* @since 0.9.47
|
||||
*/
|
||||
public abstract void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob,
|
||||
long timeoutMs, Hash fromLocalDest);
|
||||
|
||||
/**
|
||||
* Lookup using the client's tunnels
|
||||
* Succeeds even if LS validation fails due to unsupported sig type
|
||||
|
@ -45,6 +45,8 @@ public class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest) {}
|
||||
public LeaseSet lookupLeaseSetLocally(Hash key) { return null; }
|
||||
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {}
|
||||
public void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob,
|
||||
long timeoutMs, Hash fromLocalDest) {}
|
||||
|
||||
public void lookupDestination(Hash key, Job onFinishedJob, long timeoutMs, Hash fromLocalDest) {}
|
||||
|
||||
|
@ -207,7 +207,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
_to = msg.getDestination();
|
||||
Hash toHash = _to.calculateHash();
|
||||
_hashPair = new OutboundCache.HashPair(_from.calculateHash(), toHash);
|
||||
_toString = toHash.toBase64().substring(0,4);
|
||||
_toString = toHash.toBase32();
|
||||
// we look up here rather than runJob() so we may adjust the timeout
|
||||
_leaseSet = ctx.netDb().lookupLeaseSetLocally(toHash);
|
||||
|
||||
@ -297,6 +297,23 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
SendJob success = new SendJob(getContext());
|
||||
// set in constructor
|
||||
if (_leaseSet != null) {
|
||||
if (!_leaseSet.getReceivedAsReply()) {
|
||||
boolean shouldFetch = true;
|
||||
if (_leaseSet.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
|
||||
LeaseSet2 ls2 = (LeaseSet2) _leaseSet;
|
||||
shouldFetch = !ls2.isUnpublished() || ls2.isBlindedWhenPublished();
|
||||
}
|
||||
if (shouldFetch) {
|
||||
if (_log.shouldInfo())
|
||||
_log.info(getJobId() + ": RAP LS, firing search: " + _leaseSet.getHash().toBase32());
|
||||
LookupLeaseSetFailedJob failed = new LookupLeaseSetFailedJob(getContext());
|
||||
getContext().netDb().lookupLeaseSetRemotely(_leaseSet.getHash(), success, failed,
|
||||
LS_LOOKUP_TIMEOUT, _from.calculateHash());
|
||||
} else {
|
||||
dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getJobId() + ": Send outbound client message - leaseSet found locally for " + _toString);
|
||||
if (!_leaseSet.isCurrent(Router.CLOCK_FUDGE_FACTOR / 4)) {
|
||||
@ -405,13 +422,17 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
*/
|
||||
private int getNextLease() {
|
||||
// set in runJob if found locally
|
||||
if (_leaseSet == null) {
|
||||
if (_leaseSet == null || !_leaseSet.getReceivedAsReply()) {
|
||||
_leaseSet = getContext().netDb().lookupLeaseSetLocally(_to.calculateHash());
|
||||
if (_leaseSet == null) {
|
||||
// shouldn't happen
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getJobId() + ": Lookup locally didn't find the leaseSet for " + _toString);
|
||||
return MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
||||
} else if (_leaseSet.getReceivedAsPublished()) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getJobId() + ": Only have RAP LS for " + _toString);
|
||||
return MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,8 +592,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
_log.warn("Unable to send to " + _toString + " because the sig type is unsupported");
|
||||
cause = MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Unable to send to " + _toString + " because we couldn't find their leaseSet");
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Unable to send to " + _toString + ", no LS found");
|
||||
cause = MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
||||
}
|
||||
|
||||
|
@ -116,16 +116,16 @@ class HandleFloodfillDatabaseStoreMessageJob extends JobImpl {
|
||||
} else if (match.getEarliestLeaseDate() < ls.getEarliestLeaseDate()) {
|
||||
wasNew = true;
|
||||
// If it is in our keyspace and we are talking to it
|
||||
if (match.getReceivedAsPublished())
|
||||
ls.setReceivedAsPublished(true);
|
||||
//if (match.getReceivedAsPublished())
|
||||
// ls.setReceivedAsPublished(true);
|
||||
} else if (type != DatabaseEntry.KEY_TYPE_LEASESET &&
|
||||
match.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
|
||||
LeaseSet2 ls2 = (LeaseSet2) ls;
|
||||
LeaseSet2 match2 = (LeaseSet2) match;
|
||||
if (match2.getPublished() < ls2.getPublished()) {
|
||||
wasNew = true;
|
||||
if (match.getReceivedAsPublished())
|
||||
ls.setReceivedAsPublished(true);
|
||||
//if (match.getReceivedAsPublished())
|
||||
// ls.setReceivedAsPublished(true);
|
||||
} else {
|
||||
wasNew = false;
|
||||
}
|
||||
|
@ -602,9 +602,28 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
||||
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {
|
||||
if (!_initialized) return;
|
||||
key = _blindCache.getHash(key);
|
||||
if (isNegativeCached(key))
|
||||
return;
|
||||
search(key, null, null, 20*1000, true, fromLocalDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally lookup using the client's tunnels.
|
||||
*
|
||||
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
|
||||
* @param onFindJob may be null
|
||||
* @param onFailedLookupJob may be null
|
||||
* @since 0.9.47
|
||||
*/
|
||||
public void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob,
|
||||
long timeoutMs, Hash fromLocalDest) {
|
||||
if (!_initialized) return;
|
||||
key = _blindCache.getHash(key);
|
||||
if (isNegativeCached(key))
|
||||
return;
|
||||
search(key, onFindJob, onFailedLookupJob, timeoutMs, true, fromLocalDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use lookupDestination() if you don't need the LS or don't need it validated.
|
||||
*/
|
||||
@ -936,6 +955,16 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
||||
rv = (LeaseSet)_ds.get(key);
|
||||
if ( (rv != null) && (rv.equals(leaseSet)) ) {
|
||||
// if it hasn't changed, no need to do anything
|
||||
// except copy over the flags
|
||||
Hash to = leaseSet.getReceivedBy();
|
||||
if (to != null) {
|
||||
rv.setReceivedBy(to);
|
||||
} else if (leaseSet.getReceivedAsReply()) {
|
||||
rv.setReceivedAsReply();
|
||||
}
|
||||
if (leaseSet.getReceivedAsPublished()) {
|
||||
rv.setReceivedAsPublished(true);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
} catch (ClassCastException cce) {
|
||||
|
@ -125,7 +125,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
||||
// allow DSM of our own key (used by FloodfillVerifyStoreJob)
|
||||
// or other keys (used by IterativeSearchJob)
|
||||
// as long as there's no reply token (we will never set a reply token but an attacker might)
|
||||
((LeaseSet)dsm.getEntry()).setReceivedAsReply();
|
||||
((LeaseSet)dsm.getEntry()).setReceivedBy(_client);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -155,7 +155,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
||||
return;
|
||||
}
|
||||
if (dsm.getEntry().isLeaseSet())
|
||||
((LeaseSet)dsm.getEntry()).setReceivedAsReply();
|
||||
((LeaseSet)dsm.getEntry()).setReceivedBy(_client);
|
||||
break;
|
||||
|
||||
case DatabaseSearchReplyMessage.MESSAGE_TYPE:
|
||||
@ -264,7 +264,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
||||
// Or, it's a normal LS bundled with data and a MessageStatusMessage.
|
||||
|
||||
// ... and inject it.
|
||||
((LeaseSet)dsm.getEntry()).setReceivedAsReply();
|
||||
((LeaseSet)dsm.getEntry()).setReceivedBy(_client);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Storing garlic LS down tunnel for: " + dsm.getKey() + " sent to: " +
|
||||
(_client != null ? _client.toBase32() : "router"));
|
||||
|
Reference in New Issue
Block a user