forked from I2P_Developers/i2p.i2p
SSU2: Allow termination in retry
Handle skew reason in termination, possibly ban peer Adjust clock at startup when terminated with skew reason Don't send immediate termination to a too-close address Javadoc fixes Log tweaks
This commit is contained in:
@@ -822,6 +822,8 @@ class EstablishmentManager {
|
||||
}
|
||||
// very basic validation that this is probably in response to a good packet.
|
||||
// we don't bother to decrypt the packet, even if it's only a token request
|
||||
if (_transport.isTooClose(to.getIP()))
|
||||
return;
|
||||
DatagramPacket pkt = fromPacket.getPacket();
|
||||
int off = pkt.getOffset();
|
||||
int len = pkt.getLength();
|
||||
|
||||
@@ -823,8 +823,8 @@ class IntroductionManager {
|
||||
RouterInfo aliceRI = null;
|
||||
int rcode;
|
||||
if (charlie == null) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Relay tag not found " + tag + " from " + alice);
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Relay tag not found " + tag + " from " + alice);
|
||||
rcode = SSU2Util.RELAY_REJECT_BOB_NO_TAG;
|
||||
} else if (charlie.getVersion() != 2) {
|
||||
if (_log.shouldWarn())
|
||||
|
||||
@@ -27,6 +27,7 @@ import net.i2p.data.router.RouterIdentity;
|
||||
import net.i2p.data.router.RouterInfo;
|
||||
import net.i2p.router.RouterContext;
|
||||
import static net.i2p.router.transport.udp.SSU2Util.*;
|
||||
import net.i2p.time.BuildTime;
|
||||
import net.i2p.util.Addresses;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
@@ -262,7 +263,7 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Processed " + blocks + " blocks on " + this);
|
||||
} catch (Exception e) {
|
||||
throw new GeneralSecurityException("Session Created payload error", e);
|
||||
throw new GeneralSecurityException("Retry or Session Created payload error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,13 +347,39 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
// this sets the state to FAILED
|
||||
fail();
|
||||
_transport.getEstablisher().receiveSessionDestroy(_remoteHostId, this);
|
||||
Hash bob = _remotePeer.calculateHash();
|
||||
if (reason == REASON_BANNED) {
|
||||
_context.banlist().banlistRouter(_remotePeer.calculateHash(), "They banned us", null, null, _context.clock().now() + 2*60*60*1000);
|
||||
_context.banlist().banlistRouter(bob, "They banned us", null, null, _context.clock().now() + 2*60*60*1000);
|
||||
} else if (reason == REASON_MSG1) {
|
||||
// this is like a short ban
|
||||
_context.banlist().banlistRouter(_remotePeer.calculateHash(), "They banned us", null, null, _context.clock().now() + 20*60*1000);
|
||||
_context.banlist().banlistRouter(bob, "They banned us", null, null, _context.clock().now() + 20*60*1000);
|
||||
} else if (reason == REASON_SKEW) {
|
||||
long sendOn = _timeReceived;
|
||||
long recvOn = _establishBegin;
|
||||
// Positive when we are ahead of them
|
||||
long skew = recvOn - sendOn;
|
||||
String skewString = DataHelper.formatDuration(Math.abs(skew));
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Failed, clock skew " + skewString + " on " + this);
|
||||
if (sendOn == 0) {
|
||||
// no datetime block
|
||||
} else if (sendOn < BuildTime.getEarliestTime() || sendOn > BuildTime.getLatestTime()) {
|
||||
// his problem
|
||||
_context.banlist().banlistRouter(skewString, bob, _x("Excessive clock skew: {0}"));
|
||||
} else {
|
||||
boolean skewOK = skew < PacketHandler.MAX_SKEW && skew > (0 - PacketHandler.MAX_SKEW);
|
||||
if (skewOK && !_context.clock().getUpdatedSuccessfully()) {
|
||||
// adjust the clock one time in desperation
|
||||
_context.clock().setOffset(0 - skew, true);
|
||||
if (skew != 0)
|
||||
_log.logAlways(Log.WARN, "NTP failure, UDP adjusting clock by " + skewString);
|
||||
} else {
|
||||
_context.banlist().banlistRouter(skewString, bob, _x("Excessive clock skew: {0}"));
|
||||
}
|
||||
}
|
||||
_context.statManager().addRateData("udp.destroyedInvalidSkew", skew);
|
||||
}
|
||||
// TODO handle other cases - skew?
|
||||
// TODO handle other cases
|
||||
}
|
||||
|
||||
public void gotPathChallenge(RemoteHostId from, byte[] data) {
|
||||
@@ -782,4 +809,15 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
' ' + _currentState +
|
||||
(_introducers != null ? (" Introducers: " + _introducers.toString()) : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a string for extraction by xgettext and translation.
|
||||
* Use this only in static initializers.
|
||||
* It does not translate!
|
||||
* @return s
|
||||
* @since 0.9.57
|
||||
*/
|
||||
private static final String _x(String s) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class PacketHandler {
|
||||
* There's no use making it any larger, as messages will just be thrown out there.
|
||||
*/
|
||||
private static final long GRACE_PERIOD = Router.CLOCK_FUDGE_FACTOR + 30*1000;
|
||||
private static final long MAX_SKEW = 90*24*60*60*1000L;
|
||||
static final long MAX_SKEW = 90*24*60*60*1000L;
|
||||
|
||||
private enum AuthType { NONE, INTRO, BOBINTRO, SESSION }
|
||||
|
||||
@@ -897,8 +897,13 @@ class PacketHandler {
|
||||
header.getType() != SSU2Util.SESSION_REQUEST_FLAG_BYTE ||
|
||||
header.getVersion() != 2 ||
|
||||
header.getNetID() != _networkID) {
|
||||
if (_log.shouldWarn())
|
||||
if (_log.shouldWarn()) {
|
||||
if (header == null) {
|
||||
// packet too short, possibly token-request-after-retry? let's see...
|
||||
header = SSU2Header.trialDecryptLongHeader(packet, k1, k2);
|
||||
}
|
||||
_log.warn("Failed decrypt Session Request after Retry: " + header + " on " + state);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (header.getSrcConnID() != state.getSendConnID()) {
|
||||
@@ -1025,8 +1030,8 @@ class PacketHandler {
|
||||
header.getType() != SSU2Util.RETRY_FLAG_BYTE ||
|
||||
header.getVersion() != 2 ||
|
||||
header.getNetID() != _networkID) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Does not decrypt as Session Created or Retry: " + header + " on " + state);
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Does not decrypt as Session Created or Retry: " + header + " on " + state);
|
||||
return false;
|
||||
}
|
||||
type = SSU2Util.RETRY_FLAG_BYTE;
|
||||
|
||||
@@ -355,8 +355,6 @@ class SSU2Payload {
|
||||
break;
|
||||
|
||||
case BLOCK_TERMINATION:
|
||||
if (isHandshake)
|
||||
throw new IOException("Illegal block in handshake: " + type);
|
||||
if (len < 9)
|
||||
throw new IOException("Bad length for TERMINATION: " + len);
|
||||
long last = DataHelper.fromLong8(payload, i);
|
||||
|
||||
@@ -99,7 +99,7 @@ final class SSU2Util {
|
||||
public static final int DATA_HEADER_SIZE = SHORT_HEADER_SIZE;
|
||||
|
||||
/**
|
||||
* The message types, 0-10, as bytes
|
||||
* The message types, 0-11, as bytes
|
||||
*/
|
||||
public static final byte SESSION_REQUEST_FLAG_BYTE = UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST;
|
||||
public static final byte SESSION_CREATED_FLAG_BYTE = UDPPacket.PAYLOAD_TYPE_SESSION_CREATED;
|
||||
@@ -110,6 +110,7 @@ final class SSU2Util {
|
||||
public static final byte TOKEN_REQUEST_FLAG_BYTE = 10;
|
||||
public static final byte HOLE_PUNCH_FLAG_BYTE = 11;
|
||||
|
||||
// HKDF infos
|
||||
public static final String INFO_CREATED = "SessCreateHeader";
|
||||
public static final String INFO_CONFIRMED = "SessionConfirmed";
|
||||
public static final String INFO_DATA = "HKDFSSU2DataKeys";
|
||||
@@ -118,10 +119,12 @@ final class SSU2Util {
|
||||
public static final byte[] ZEROKEY = new byte[KEY_LEN];
|
||||
|
||||
// relay and peer test
|
||||
// Signature prologues
|
||||
public static final byte[] RELAY_REQUEST_PROLOGUE = DataHelper.getASCII("RelayRequestData");
|
||||
public static final byte[] RELAY_RESPONSE_PROLOGUE = DataHelper.getASCII("RelayAgreementOK");
|
||||
public static final byte[] PEER_TEST_PROLOGUE = DataHelper.getASCII("PeerTestValidate");
|
||||
|
||||
// test status codes
|
||||
public static final int TEST_ACCEPT = 0;
|
||||
public static final int TEST_REJECT_BOB_UNSPEC = 1;
|
||||
public static final int TEST_REJECT_BOB_NO_CHARLIE = 2;
|
||||
@@ -136,6 +139,7 @@ final class SSU2Util {
|
||||
public static final int TEST_REJECT_CHARLIE_BANNED = 69;
|
||||
public static final int TEST_REJECT_CHARLIE_UNKNOWN_ALICE = 70;
|
||||
|
||||
// relay status codes
|
||||
public static final int RELAY_ACCEPT = 0;
|
||||
public static final int RELAY_REJECT_BOB_UNSPEC = 1;
|
||||
public static final int RELAY_REJECT_BOB_BANNED_CHARLIE = 2;
|
||||
|
||||
Reference in New Issue
Block a user