diff --git a/src/main/java/net/schmizz/sshj/Config.java b/src/main/java/net/schmizz/sshj/Config.java
index 7e77ec0f..a0b156e7 100644
--- a/src/main/java/net/schmizz/sshj/Config.java
+++ b/src/main/java/net/schmizz/sshj/Config.java
@@ -155,4 +155,24 @@ public interface Config {
* @param keepAliveProvider keep-alive provider
*/
void setKeepAliveProvider(KeepAliveProvider keepAliveProvider);
+
+ /**
+ * Gets whether the client should first wait for a received server ident, before sending the client ident.
+ *
+ * NB: This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
+ *
+ * The default value is set to false.
+ *
+ * @return Whether to first wait for the server ident.
+ */
+ boolean isWaitForServerIdentBeforeSendingClientIdent();
+
+ /**
+ * Sets whether the SSH client should wait for a received server ident, before sending the client ident.
+ *
+ * NB: This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
+
+ * @param waitForServerIdentBeforeSendingClientIdent Whether to wait for the server ident.
+ */
+ void setWaitForServerIdentBeforeSendingClientIdent(boolean waitForServerIdentBeforeSendingClientIdent);
}
diff --git a/src/main/java/net/schmizz/sshj/ConfigImpl.java b/src/main/java/net/schmizz/sshj/ConfigImpl.java
index d15384ec..9fb253f7 100644
--- a/src/main/java/net/schmizz/sshj/ConfigImpl.java
+++ b/src/main/java/net/schmizz/sshj/ConfigImpl.java
@@ -44,6 +44,8 @@ public class ConfigImpl
private List> signatureFactories;
private List> fileKeyProviderFactories;
+ private boolean waitForServerIdentBeforeSendingClientIdent = false;
+
@Override
public List> getCipherFactories() {
return cipherFactories;
@@ -157,4 +159,14 @@ public class ConfigImpl
public void setKeepAliveProvider(KeepAliveProvider keepAliveProvider) {
this.keepAliveProvider = keepAliveProvider;
}
-}
\ No newline at end of file
+
+ @Override
+ public boolean isWaitForServerIdentBeforeSendingClientIdent() {
+ return waitForServerIdentBeforeSendingClientIdent;
+ }
+
+ @Override
+ public void setWaitForServerIdentBeforeSendingClientIdent(boolean waitForServerIdentBeforeSendingClientIdent) {
+ this.waitForServerIdentBeforeSendingClientIdent = waitForServerIdentBeforeSendingClientIdent;
+ }
+}
diff --git a/src/main/java/net/schmizz/sshj/transport/TransportImpl.java b/src/main/java/net/schmizz/sshj/transport/TransportImpl.java
index 80b2b01f..c2e790ce 100644
--- a/src/main/java/net/schmizz/sshj/transport/TransportImpl.java
+++ b/src/main/java/net/schmizz/sshj/transport/TransportImpl.java
@@ -152,19 +152,15 @@ public final class TransportImpl
try {
- log.info("Client identity string: {}", clientID);
- connInfo.out.write((clientID + "\r\n").getBytes(IOUtils.UTF8));
- connInfo.out.flush();
-
- // Read server's ID
- final Buffer.PlainBuffer buf = new Buffer.PlainBuffer();
- while ((serverID = readIdentification(buf)).isEmpty()) {
- int b = connInfo.in.read();
- if (b == -1)
- throw new TransportException("Server closed connection during identification exchange");
- buf.putByte((byte) b);
+ if (config.isWaitForServerIdentBeforeSendingClientIdent()) {
+ receiveServerIdent();
+ sendClientIdent();
+ } else {
+ sendClientIdent();
+ receiveServerIdent();
}
+
log.info("Server identity string: {}", serverID);
} catch (IOException e) {
@@ -174,6 +170,26 @@ public final class TransportImpl
reader.start();
}
+ private void receiveServerIdent() throws IOException {
+ final Buffer.PlainBuffer buf = new Buffer.PlainBuffer();
+ while ((serverID = readIdentification(buf)).isEmpty()) {
+ int b = connInfo.in.read();
+ if (b == -1)
+ throw new TransportException("Server closed connection during identification exchange");
+ buf.putByte((byte) b);
+ }
+ }
+
+ /**
+ * Receive the server identification string.
+ * @throws IOException If there was an error writing to the outputstream.
+ */
+ private void sendClientIdent() throws IOException {
+ log.info("Client identity string: {}", clientID);
+ connInfo.out.write((clientID + "\r\n").getBytes(IOUtils.UTF8));
+ connInfo.out.flush();
+ }
+
/**
* Reads the identification string from the SSH server. This is the very first string that is sent upon connection
* by the server. It takes the form of, e.g. "SSH-2.0-OpenSSH_ver".