You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/04/10 16:48:01 UTC
mina-sshd git commit: [SSHD-813] Execute KEX related session code
under synchronization lock
Repository: mina-sshd
Updated Branches:
refs/heads/master 3c9efa8a5 -> 11f85a5ac
[SSHD-813] Execute KEX related session code under synchronization lock
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/11f85a5a
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/11f85a5a
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/11f85a5a
Branch: refs/heads/master
Commit: 11f85a5ac6f4bba93cadf780f02c80a5e66b2cd0
Parents: 3c9efa8
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Sat Apr 7 17:21:18 2018 +0300
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Tue Apr 10 19:51:19 2018 +0300
----------------------------------------------------------------------
.../client/session/AbstractClientSession.java | 11 ++-
.../org/apache/sshd/common/NamedFactory.java | 12 +--
.../common/session/helpers/AbstractSession.java | 82 ++++++++++++++++----
.../server/session/AbstractServerSession.java | 4 +-
4 files changed, 84 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/11f85a5a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
index 1d84d28..6a1a15d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
@@ -471,13 +471,13 @@ public abstract class AbstractClientSession extends AbstractSession implements C
@Override
protected void setKexSeed(byte... seed) {
- i_c = ValidateUtils.checkNotNullAndNotEmpty(seed, "No KEX seed");
+ setClientKexData(seed);
}
@Override
protected void receiveKexInit(Map<KexProposalOption, String> proposal, byte[] seed) throws IOException {
mergeProposals(serverProposal, proposal);
- i_s = seed;
+ setServerKexData(seed);
}
@Override
@@ -550,8 +550,11 @@ public abstract class AbstractClientSession extends AbstractSession implements C
proposal.put(KexProposalOption.C2SENC, BuiltinCiphers.Constants.NONE);
proposal.put(KexProposalOption.S2CENC, BuiltinCiphers.Constants.NONE);
- byte[] seed = sendKexInit(proposal);
- setKexSeed(seed);
+ byte[] seed;
+ synchronized (kexState) {
+ seed = sendKexInit(proposal);
+ setKexSeed(seed);
+ }
}
return Objects.requireNonNull(kexFutureHolder.get(), "No current KEX future");
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/11f85a5a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
index 9e4f612..5386447 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
@@ -40,7 +40,7 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
* @param <T> type of object to create
* @return a newly created object or {@code null} if the factory is not in the list
*/
- static <T> T create(Collection<? extends NamedFactory<T>> factories, String name) {
+ static <T> T create(Collection<? extends NamedFactory<? extends T>> factories, String name) {
NamedFactory<? extends T> f = NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, factories);
if (f != null) {
return f.create();
@@ -52,15 +52,15 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
static <S extends OptionalFeature, T, E extends NamedFactory<T>> List<NamedFactory<T>> setUpTransformedFactories(
boolean ignoreUnsupported, Collection<? extends S> preferred, Function<? super S, ? extends E> xform) {
return preferred.stream()
- .filter(f -> ignoreUnsupported || f.isSupported())
- .map(xform)
- .collect(Collectors.toList());
+ .filter(f -> ignoreUnsupported || f.isSupported())
+ .map(xform)
+ .collect(Collectors.toList());
}
static <T, E extends NamedFactory<T> & OptionalFeature> List<NamedFactory<T>> setUpBuiltinFactories(
boolean ignoreUnsupported, Collection<? extends E> preferred) {
return preferred.stream()
- .filter(f -> ignoreUnsupported || f.isSupported())
- .collect(Collectors.toList());
+ .filter(f -> ignoreUnsupported || f.isSupported())
+ .collect(Collectors.toList());
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/11f85a5a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
index 5ca2192..b947e3a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
@@ -160,8 +160,6 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
protected final Map<KexProposalOption, String> serverProposal = new EnumMap<>(KexProposalOption.class);
protected final Map<KexProposalOption, String> clientProposal = new EnumMap<>(KexProposalOption.class);
protected final Map<KexProposalOption, String> negotiationResult = new EnumMap<>(KexProposalOption.class);
- protected byte[] i_c; // the payload of the client's SSH_MSG_KEXINIT
- protected byte[] i_s; // the payload of the factoryManager's SSH_MSG_KEXINIT
protected KeyExchange kex;
protected Boolean firstKexPacketFollows;
protected final AtomicReference<KexState> kexState = new AtomicReference<>(KexState.UNKNOWN);
@@ -247,6 +245,9 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
private ChannelStreamPacketWriterResolver channelStreamPacketWriterResolver;
private UnknownChannelReferenceHandler unknownChannelReferenceHandler;
+ private byte[] clientKexData; // the payload of the client's SSH_MSG_KEXINIT
+ private byte[] serverKexData; // the payload of the factoryManager's SSH_MSG_KEXINIT
+
/**
* Create a new session.
*
@@ -780,6 +781,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
log.debug("handleServiceRequest({}) SSH_MSG_SERVICE_REQUEST '{}'", this, serviceName);
}
validateKexState(SshConstants.SSH_MSG_SERVICE_REQUEST, KexState.DONE);
+
try {
startService(serviceName);
} catch (Throwable e) {
@@ -821,6 +823,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
log.debug("handleKexInit({}) SSH_MSG_KEXINIT", this);
}
receiveKexInit(buffer);
+
if (kexState.compareAndSet(KexState.DONE, KexState.RUN)) {
sendKexInit();
} else if (!kexState.compareAndSet(KexState.INIT, KexState.RUN)) {
@@ -829,10 +832,21 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
Map<KexProposalOption, String> result = negotiate();
String kexAlgorithm = result.get(KexProposalOption.ALGORITHMS);
- kex = ValidateUtils.checkNotNull(NamedFactory.create(getKeyExchangeFactories(), kexAlgorithm),
+ Collection<? extends NamedFactory<KeyExchange>> kexFactories = getKeyExchangeFactories();
+ kex = ValidateUtils.checkNotNull(NamedFactory.create(kexFactories, kexAlgorithm),
"Unknown negotiated KEX algorithm: %s",
kexAlgorithm);
- kex.init(this, serverVersion.getBytes(StandardCharsets.UTF_8), clientVersion.getBytes(StandardCharsets.UTF_8), i_s, i_c);
+
+ byte[] v_s = serverVersion.getBytes(StandardCharsets.UTF_8);
+ byte[] v_c = clientVersion.getBytes(StandardCharsets.UTF_8);
+ byte[] i_s;
+ byte[] i_c;
+ synchronized (kexState) {
+ i_s = getServerKexData();
+ i_c = getClientKexData();
+ }
+ kex.init(this, v_s, v_c, i_s, i_c);
+
signalSessionEvent(SessionListener.Event.KexCompleted);
}
@@ -855,6 +869,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
}
signalSessionEvent(SessionListener.Event.KeyEstablished);
+
Collection<? extends Map.Entry<? extends SshFutureListener<IoWriteFuture>, IoWriteFuture>> pendingWrites;
synchronized (pendingPackets) {
pendingWrites = sendPendingPackets(pendingPackets);
@@ -1085,7 +1100,8 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
public IoWriteFuture writePacket(Buffer buffer) throws IOException {
// While exchanging key, queue high level packets
if (!KexState.DONE.equals(kexState.get())) {
- byte cmd = buffer.array()[buffer.rpos()];
+ byte[] bufData = buffer.array();
+ byte cmd = bufData[buffer.rpos()];
if (cmd > SshConstants.SSH_MSG_KEX_LAST) {
String cmdName = SshConstants.getCommandMessageName(cmd & 0xFF);
synchronized (pendingPackets) {
@@ -1179,7 +1195,8 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
}
synchronized (random) {
- ignorePacketsCount.set(calculateNextIgnorePacketCount(random, ignorePacketsFrequency, ignorePacketsVariance));
+ count = calculateNextIgnorePacketCount(random, ignorePacketsFrequency, ignorePacketsVariance);
+ ignorePacketsCount.set(count);
return ignorePacketDataLength + random.random(ignorePacketDataLength);
}
}
@@ -2583,17 +2600,46 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
}
Map<KexProposalOption, String> proposal = createProposal(resolvedAlgorithms);
- byte[] seed = sendKexInit(proposal);
+ byte[] seed;
+ synchronized (kexState) {
+ seed = sendKexInit(proposal);
+ setKexSeed(seed);
+ }
+
if (log.isTraceEnabled()) {
log.trace("sendKexInit({}) proposal={} seed: {}", this, proposal, BufferUtils.toHex(':', seed));
}
- setKexSeed(seed);
return seed;
}
+ protected byte[] getClientKexData() {
+ synchronized (kexState) {
+ return (clientKexData == null) ? null : clientKexData.clone();
+ }
+ }
+
+ protected void setClientKexData(byte[] data) {
+ ValidateUtils.checkNotNullAndNotEmpty(data, "No client KEX seed");
+ synchronized (kexState) {
+ clientKexData = data.clone();
+ }
+ }
+
+ protected byte[] getServerKexData() {
+ synchronized (kexState) {
+ return (serverKexData == null) ? null : serverKexData.clone();
+ }
+ }
+
+ protected void setServerKexData(byte[] data) {
+ ValidateUtils.checkNotNullAndNotEmpty(data, "No server KEX seed");
+ synchronized (kexState) {
+ serverKexData = data.clone();
+ }
+ }
+
/**
- * @param seed The result of the KEXINIT handshake - required for correct
- * session key establishment
+ * @param seed The result of the KEXINIT handshake - required for correct session key establishment
*/
protected abstract void setKexSeed(byte... seed);
@@ -2622,10 +2668,20 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
*/
protected abstract void checkKeys() throws IOException;
- protected void receiveKexInit(Buffer buffer) throws IOException {
+ protected byte[] receiveKexInit(Buffer buffer) throws IOException {
Map<KexProposalOption, String> proposal = new EnumMap<>(KexProposalOption.class);
- byte[] seed = receiveKexInit(buffer, proposal);
- receiveKexInit(proposal, seed);
+
+ byte[] seed;
+ synchronized (kexState) {
+ seed = receiveKexInit(buffer, proposal);
+ receiveKexInit(proposal, seed);
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace("receiveKexInit({}) proposal={} seed: {}", this, proposal, BufferUtils.toHex(':', seed));
+ }
+
+ return seed;
}
protected abstract void receiveKexInit(Map<KexProposalOption, String> proposal, byte[] seed) throws IOException;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/11f85a5a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
index d73d38e..07937df 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
@@ -236,7 +236,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
@Override
protected void setKexSeed(byte... seed) {
- i_s = ValidateUtils.checkNotNullAndNotEmpty(seed, "No KEX seed");
+ setServerKexData(seed);
}
@Override
@@ -379,7 +379,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
@Override
protected void receiveKexInit(Map<KexProposalOption, String> proposal, byte[] seed) throws IOException {
mergeProposals(clientProposal, proposal);
- i_c = seed;
+ setClientKexData(seed);
}
@Override