I2CP: Prevent loopback messages to same session (i2pd Github #2005)

This commit is contained in:
zzz
2024-01-15 10:35:29 +00:00
parent ba39f58800
commit f337c1b3c9
7 changed files with 34 additions and 31 deletions

View File

@@ -117,6 +117,9 @@ public class I2PSocketException extends SocketException {
case MessageStatusMessage.STATUS_SEND_FAILURE_META_LEASESET:
return "Meta lease set";
case MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK:
return "local loopback denied, set i2cp.disableLoopback=true to test sending to yourself through tunnels";
case SendMessageStatusListener.STATUS_CANCELLED:
return _x("Local destination shutdown");

View File

@@ -324,6 +324,7 @@ class PacketQueue implements SendMessageStatusListener, Closeable {
case MessageStatusMessage.STATUS_SEND_FAILURE_DESTINATION:
case MessageStatusMessage.STATUS_SEND_FAILURE_BAD_LEASESET:
case MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED_LEASESET:
case MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK:
case SendMessageStatusListener.STATUS_CANCELLED:
if (con.getHighestAckedThrough() >= 0) {
// a retxed SYN succeeded before the first SYN failed

View File

@@ -157,6 +157,7 @@ class MessageState {
case MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED_LEASESET:
case MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET:
case MessageStatusMessage.STATUS_SEND_FAILURE_META_LEASESET:
case MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK:
case SendMessageStatusListener.STATUS_CANCELLED:
// does not trump success
if (_state != State.SUCCESS)

View File

@@ -189,6 +189,13 @@ public class MessageStatusMessage extends I2CPMessageImpl {
*/
public final static int STATUS_SEND_FAILURE_META_LEASESET = 22;
/**
* Message was attempted to be sent to the same Destination.
* This is a guaranteed failure.
* @since 0.9.62
*/
public final static int STATUS_SEND_FAILURE_LOOPBACK = 23;
// NOTE:
// Add any new status codes to handlers in:
// net.i2p.client.impl.MessageState

View File

@@ -806,7 +806,7 @@ class ClientConnectionRunner {
// the following blocks as described above
Destination fromDest = getDestination(message.getSessionId());
if (fromDest != null)
_manager.distributeMessage(fromDest, dest, payload,
_manager.distributeMessage(this, fromDest, dest, payload,
id, message.getNonce(), expiration, flags);
// else log error?
//long timeToDistribute = _context.clock().now() - beforeDistribute;

View File

@@ -451,11 +451,13 @@ class ClientManager {
/**
* Distribute message to a local or remote destination.
*
* @param sender non-null
* @param msgId the router's ID for this message
* @param messageNonce the client's ID for this message
* @param flags ignored for local
*/
void distributeMessage(Destination fromDest, Destination toDest, Payload payload,
void distributeMessage(ClientConnectionRunner sender, Destination fromDest, Destination toDest, Payload payload,
MessageId msgId, long messageNonce, long expiration, int flags) {
ClientConnectionRunner runner;
if (_ctx.getBooleanProperty(PROP_DISABLE_LOOPBACK)) {
@@ -467,22 +469,19 @@ class ClientManager {
if (runner != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Message " + msgId + " is targeting a local destination. distribute it as such");
ClientConnectionRunner sender = getRunner(fromDest);
if (sender == null) {
// sender went away
return;
if (runner != sender) {
// run this inline so we don't clog up the job queue
Job j = new DistributeLocal(toDest, runner, sender, fromDest, payload, msgId, messageNonce);
//_ctx.jobQueue().addJob(j);
j.runJob();
} else {
if (_log.shouldWarn())
_log.warn("Loopback attempt from client " + fromDest.getHash());
int rc = MessageStatusMessage.STATUS_SEND_FAILURE_LOOPBACK;
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
}
// run this inline so we don't clog up the job queue
Job j = new DistributeLocal(toDest, runner, sender, fromDest, payload, msgId, messageNonce);
//_ctx.jobQueue().addJob(j);
j.runJob();
} else if (!_metaDests.isEmpty() && _metaDests.contains(toDest)) {
// meta dests don't have runners but are local, and you can't send to them
ClientConnectionRunner sender = getRunner(fromDest);
if (sender == null) {
// sender went away
return;
}
int rc = MessageStatusMessage.STATUS_SEND_FAILURE_BAD_LEASESET;
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
} else {

View File

@@ -56,19 +56,16 @@ class LocalClientManager extends ClientManager {
* @param flags ignored for local
*/
@Override
void distributeMessage(Destination fromDest, Destination toDest, Payload payload,
void distributeMessage(ClientConnectionRunner sender, Destination fromDest, Destination toDest, Payload payload,
MessageId msgId, long messageNonce, long expiration, int flags) {
// check if there is a runner for it
ClientConnectionRunner sender = getRunner(fromDest);
ClientConnectionRunner runner = getRunner(toDest);
if (runner != null) {
if (dropX1000 > 0) {
if (100 * 1000 * _ctx.random().nextFloat() < dropX1000) {
System.out.println("Message " + msgId + " DROPPED randomly");
if (sender != null) {
// pretend success
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
}
// pretend success
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
}
}
if (latency > 0 || jitter > 0) {
@@ -83,15 +80,12 @@ class LocalClientManager extends ClientManager {
}
}
boolean ok = runner.receiveMessage(toDest, fromDest, payload);
if (sender != null) {
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
}
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
} else {
// remote. ignore.
System.out.println("Message " + msgId + " is targeting a REMOTE destination - DROPPED");
if (sender != null)
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_FAILURE);
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_FAILURE);
}
}
@@ -113,10 +107,8 @@ class LocalClientManager extends ClientManager {
public void timeReached() {
boolean ok = r.receiveMessage(td, fd, pl);
if (s != null) {
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
s.updateMessageDeliveryStatus(fd, id, nonce, rc);
}
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
s.updateMessageDeliveryStatus(fd, id, nonce, rc);
}
}