forked from I2P_Developers/i2p.i2p
SSU2: Fixes part 2
Add method to put additional blocks in data messages Send and handle termination blocks
This commit is contained in:
@@ -775,6 +775,9 @@ class EstablishmentManager {
|
||||
|
||||
/**
|
||||
* Got a SessionDestroy on an established conn
|
||||
*
|
||||
* SSU 1 or 2
|
||||
*
|
||||
* @since 0.8.1
|
||||
*/
|
||||
void receiveSessionDestroy(RemoteHostId from, PeerState state) {
|
||||
@@ -785,6 +788,9 @@ class EstablishmentManager {
|
||||
|
||||
/**
|
||||
* Got a SessionDestroy during outbound establish
|
||||
*
|
||||
* SSU 1 or 2
|
||||
*
|
||||
* @since 0.8.1
|
||||
*/
|
||||
void receiveSessionDestroy(RemoteHostId from, OutboundEstablishState state) {
|
||||
@@ -800,6 +806,9 @@ class EstablishmentManager {
|
||||
* TODO - PacketHandler won't look up inbound establishes
|
||||
* As this packet was essentially unauthenticated (i.e. intro key, not session key)
|
||||
* we just log it as it could be spoofed.
|
||||
*
|
||||
* SSU 1 or 2
|
||||
*
|
||||
* @since 0.8.1
|
||||
*/
|
||||
void receiveSessionDestroy(RemoteHostId from) {
|
||||
|
||||
@@ -144,6 +144,10 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
_sendHeaderEncryptKey2 = SSU2Util.hkdf(_context, _handshakeState.getChainingKey(), "SessCreateHeader");
|
||||
_currentState = InboundState.IB_STATE_REQUEST_RECEIVED;
|
||||
}
|
||||
if (_currentState == InboundState.IB_STATE_FAILED) {
|
||||
// termination block received
|
||||
throw new GeneralSecurityException("Termination block in Session/Token Request");
|
||||
}
|
||||
if (_timeReceived == 0)
|
||||
throw new GeneralSecurityException("No DateTime block in Session/Token Request");
|
||||
long skew = _establishBegin - _timeReceived;
|
||||
@@ -308,7 +312,11 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
}
|
||||
|
||||
public void gotTermination(int reason, long count) {
|
||||
throw new IllegalStateException("Termination in Handshake");
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Got TERMINATION block, reason: " + reason + " count: " + count);
|
||||
// this sets the state to FAILED
|
||||
fail();
|
||||
_transport.getEstablisher().receiveSessionDestroy(_remoteHostId);
|
||||
}
|
||||
|
||||
public void gotUnknown(int type, int len) {
|
||||
@@ -418,6 +426,11 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
_log.debug("State after sess req: " + _handshakeState);
|
||||
_timeReceived = 0;
|
||||
processPayload(data, off + LONG_HEADER_SIZE, len - (LONG_HEADER_SIZE + KEY_LEN + MAC_LEN), true);
|
||||
packetReceived();
|
||||
if (_currentState == InboundState.IB_STATE_FAILED) {
|
||||
// termination block received
|
||||
throw new GeneralSecurityException("Termination block in Session Request");
|
||||
}
|
||||
if (_timeReceived == 0)
|
||||
throw new GeneralSecurityException("No DateTime block in Session Request");
|
||||
long skew = _establishBegin - _timeReceived;
|
||||
@@ -426,8 +439,6 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
_sendHeaderEncryptKey2 = SSU2Util.hkdf(_context, _handshakeState.getChainingKey(), "SessCreateHeader");
|
||||
_currentState = InboundState.IB_STATE_REQUEST_RECEIVED;
|
||||
_rtt = (int) ( _context.clock().now() - _lastSend );
|
||||
|
||||
packetReceived();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,6 +474,11 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("State after sess conf: " + _handshakeState);
|
||||
processPayload(data, off + SHORT_HEADER_SIZE, len - (SHORT_HEADER_SIZE + KEY_LEN + MAC_LEN + MAC_LEN), false);
|
||||
packetReceived();
|
||||
if (_currentState == InboundState.IB_STATE_FAILED) {
|
||||
// termination block received
|
||||
throw new GeneralSecurityException("Termination block in Session Confirmed");
|
||||
}
|
||||
_sessCrForReTX = null;
|
||||
|
||||
if (_receivedConfirmedIdentity == null)
|
||||
@@ -471,7 +487,6 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
// createPeerState() called from gotRI()
|
||||
|
||||
_currentState = InboundState.IB_STATE_CONFIRMED_COMPLETELY;
|
||||
packetReceived();
|
||||
return _pstate;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,11 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
}
|
||||
|
||||
public void gotTermination(int reason, long count) {
|
||||
throw new IllegalStateException("Termination in Sess Created");
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Got TERMINATION block, reason: " + reason + " count: " + count);
|
||||
// this sets the state to FAILED
|
||||
fail();
|
||||
_transport.getEstablisher().receiveSessionDestroy(_remoteHostId, this);
|
||||
}
|
||||
|
||||
public void gotUnknown(int type, int len) {
|
||||
@@ -323,6 +327,11 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
_log.debug("Retry error", gse);
|
||||
throw gse;
|
||||
}
|
||||
packetReceived();
|
||||
if (_currentState == OutboundState.OB_STATE_VALIDATION_FAILED) {
|
||||
// termination block received
|
||||
return;
|
||||
}
|
||||
if (_timeReceived == 0)
|
||||
throw new GeneralSecurityException("No DateTime block in Session/Token Request");
|
||||
long skew = _establishBegin - _timeReceived;
|
||||
@@ -330,7 +339,6 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
throw new GeneralSecurityException("Skew exceeded in Session/Token Request: " + skew);
|
||||
createNewState(_routerAddress);
|
||||
_currentState = OutboundState.OB_STATE_RETRY_RECEIVED;
|
||||
packetReceived();
|
||||
}
|
||||
|
||||
public synchronized void receiveSessionCreated(UDPPacket packet) throws GeneralSecurityException {
|
||||
@@ -371,6 +379,11 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
_log.debug("State after sess cr: " + _handshakeState);
|
||||
_timeReceived = 0;
|
||||
processPayload(data, off + LONG_HEADER_SIZE, len - (LONG_HEADER_SIZE + KEY_LEN + MAC_LEN), true);
|
||||
packetReceived();
|
||||
if (_currentState == OutboundState.OB_STATE_VALIDATION_FAILED) {
|
||||
// termination block received
|
||||
return;
|
||||
}
|
||||
if (_timeReceived == 0)
|
||||
throw new GeneralSecurityException("No DateTime block in Session/Token Request");
|
||||
long skew = _establishBegin - _timeReceived;
|
||||
@@ -384,7 +397,6 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
if (_requestSentCount == 1) {
|
||||
_rtt = (int) (_context.clock().now() - _requestSentTime);
|
||||
}
|
||||
packetReceived();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -133,6 +133,15 @@ class PacketBuilder2 {
|
||||
*
|
||||
*/
|
||||
public UDPPacket buildPacket(List<Fragment> fragments, PeerState2 peer) {
|
||||
return buildPacket(fragments, null, peer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiple fragments and optional other blocks.
|
||||
*
|
||||
* @param otherBlocks may be null or empty
|
||||
*/
|
||||
public UDPPacket buildPacket(List<Fragment> fragments, List<Block> otherBlocks, PeerState2 peer) {
|
||||
// calculate data size
|
||||
int numFragments = fragments.size();
|
||||
int dataSize = 0;
|
||||
@@ -172,7 +181,10 @@ class PacketBuilder2 {
|
||||
|
||||
// ok, now for the body...
|
||||
// +2 for acks and padding
|
||||
List<Block> blocks = new ArrayList<Block>(fragments.size() + 2);
|
||||
int bcnt = fragments.size() + 2;
|
||||
if (otherBlocks != null)
|
||||
bcnt += otherBlocks.size();
|
||||
List<Block> blocks = new ArrayList<Block>(bcnt);
|
||||
int sizeWritten = 0;
|
||||
|
||||
// add the acks
|
||||
@@ -207,6 +219,17 @@ class PacketBuilder2 {
|
||||
off += sz;
|
||||
sizeWritten += sz;
|
||||
}
|
||||
|
||||
// now the other blocks, if any
|
||||
if (otherBlocks != null) {
|
||||
for (Block block : otherBlocks) {
|
||||
blocks.add(block);
|
||||
int sz = block.getTotalLength();
|
||||
off += sz;
|
||||
sizeWritten += sz;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME
|
||||
Block block = getPadding(sizeWritten, currentMTU);
|
||||
if (block != null) {
|
||||
@@ -280,6 +303,15 @@ class PacketBuilder2 {
|
||||
public UDPPacket buildACK(PeerState2 peer) {
|
||||
return buildPacket(Collections.emptyList(), peer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a data packet with a termination block.
|
||||
* This will also include acks and padding.
|
||||
*/
|
||||
public UDPPacket buildSessionDestroyPacket(int reason, PeerState2 peer) {
|
||||
Block block = new SSU2Payload.TerminationBlock(reason, peer.getReceivedMessages().getHighestSet());
|
||||
return buildPacket(Collections.emptyList(), Collections.singletonList(block), peer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new SessionRequest packet for the given peer, encrypting it
|
||||
|
||||
@@ -350,8 +350,9 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
}
|
||||
|
||||
public void gotTermination(int reason, long count) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got TERMINATION block, reason: " + reason + " count: " + count);
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Got TERMINATION block, reason: " + reason + " count: " + count);
|
||||
_transport.getEstablisher().receiveSessionDestroy(_remoteHostId, this);
|
||||
}
|
||||
|
||||
public void gotUnknown(int type, int len) {
|
||||
|
||||
@@ -2126,10 +2126,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
* @since 0.8.9
|
||||
*/
|
||||
void sendDestroy(PeerState peer) {
|
||||
// peer must be fully established
|
||||
if (peer.getCurrentCipherKey() == null)
|
||||
return;
|
||||
UDPPacket pkt = _packetBuilder.buildSessionDestroyPacket(peer);
|
||||
UDPPacket pkt;
|
||||
if (peer.getVersion() == 1) {
|
||||
// peer must be fully established
|
||||
if (peer.getCurrentCipherKey() == null)
|
||||
return;
|
||||
pkt = _packetBuilder.buildSessionDestroyPacket(peer);
|
||||
} else {
|
||||
// unspecified reason
|
||||
pkt = _packetBuilder2.buildSessionDestroyPacket(0, (PeerState2) peer);
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Sending destroy to : " + peer);
|
||||
send(pkt);
|
||||
|
||||
Reference in New Issue
Block a user