[SSHD-1097] Added capability to send peer identification via ReservedSessionMessagesHandler
diff --git a/CHANGES.md b/CHANGES.md
index 7d2b02c..5dada51 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -27,6 +27,7 @@
* [SSHD-1085](https://issues.apache.org/jira/browse/SSHD-1085) Added more notifications related to channel state change for detecting channel closing or closed earlier.
* [SSHD-1091](https://issues.apache.org/jira/browse/SSHD-1091) Renamed `sshd-contrib` top-level package in order to align naming convention.
* [SSHD-1097](https://issues.apache.org/jira/browse/SSHD-1097) Added more `SessionListener` callbacks related to the initial version and key exchange
+* [SSHD-1097](https://issues.apache.org/jira/browse/SSHD-1097) Added more capability to send peer identification via `ReservedSessionMessagesHandler`
* [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Replace log4j with logback as the slf4j logger implementation for tests
* [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added callbacks for client-side password authentication progress
* [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added callbacks for client-side public key authentication progress
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 ce8e529..3bab23a 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
@@ -356,8 +356,7 @@
clientVersion = resolveIdentificationString(CoreModuleProperties.CLIENT_IDENTIFICATION.getName());
// Note: we intentionally use an unmodifiable list in order to enforce the fact that client cannot send header lines
signalSendIdentification(clientVersion, Collections.emptyList());
-
- return sendIdentification(clientVersion);
+ return sendIdentification(clientVersion, Collections.emptyList());
}
@Override
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/ReservedSessionMessagesHandler.java b/sshd-core/src/main/java/org/apache/sshd/common/session/ReservedSessionMessagesHandler.java
index e73e5d9..ecc49f1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/ReservedSessionMessagesHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/ReservedSessionMessagesHandler.java
@@ -19,17 +19,43 @@
package org.apache.sshd.common.session;
+import java.util.List;
+
+import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.util.SshdEventListener;
import org.apache.sshd.common.util.buffer.Buffer;
/**
* Provides a way to listen and handle the {@code SSH_MSG_IGNORE} and {@code SSH_MSG_DEBUG} messages that are received
- * by a session, as well as proprietary and/or extension messages.
+ * by a session, as well as proprietary and/or extension messages and behavior.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public interface ReservedSessionMessagesHandler extends SshdEventListener {
/**
+ * Send the initial version exchange identification in and independent manner
+ *
+ * @param session The {@code Session} through which the version is exchange is being managed
+ * @param version The version line that was resolved - <B>Note:</B> since this string is part of the KEX and is
+ * <U>cached</U> in the calling session, any changes to it require updating the session's cached
+ * value.
+ * @param extraLines Extra lines to be sent - valid only for server sessions. <B>Note:/B> the handler may modify
+ * these lines and return {@code null} thus signaling the session to proceed with sending the
+ * identification
+ * @return A {@link IoWriteFuture} that can be used to wait for the data to be sent successfully. If
+ * {@code null} then the session will send the identification, otherwise it is assumed that the
+ * handler has sent it.
+ * @throws Exception
+ * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253 - section 4.2 - Protocol
+ * Version Exchange</A>
+ */
+ default IoWriteFuture sendIdentification(
+ Session session, String version, List<String> extraLines)
+ throws Exception {
+ return null;
+ }
+
+ /**
* Invoked when an {@code SSH_MSG_IGNORE} packet is received
*
* @param session The {@code Session} through which the message was received
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/ReservedSessionMessagesHandlerAdapter.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/ReservedSessionMessagesHandlerAdapter.java
index a394612..6b97b01 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/ReservedSessionMessagesHandlerAdapter.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/ReservedSessionMessagesHandlerAdapter.java
@@ -19,9 +19,13 @@
package org.apache.sshd.common.session.helpers;
+import java.util.List;
+
import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.session.ReservedSessionMessagesHandler;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.logging.AbstractLoggingBean;
@@ -41,6 +45,22 @@
}
@Override
+ public IoWriteFuture sendIdentification(Session session, String version, List<String> extraLines) throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("sendIdentification({}) version={} linesCount={}",
+ session, version, GenericUtils.size(extraLines));
+ }
+
+ if (log.isTraceEnabled() && GenericUtils.isNotEmpty(extraLines)) {
+ for (String line : extraLines) {
+ log.trace("sendIdentification({}) {}", session, line);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
public void handleIgnoreMessage(Session session, Buffer buffer) throws Exception {
handleIgnoreMessage(session, buffer.getBytes(), buffer);
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
index 7c0e74d..a5d7542 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
@@ -832,13 +832,31 @@
/**
* Send our identification.
*
- * @param ident our identification to send
- * @return {@link IoWriteFuture} that can be used to wait for notification that identification has been
- * send
- * @throws IOException If failed to send the packet
+ * @param version our identification to send
+ * @param extraLines Extra lines to send - used only by server sessions
+ * @return {@link IoWriteFuture} that can be used to wait for notification that identification has been
+ * send
+ * @throws Exception If failed to send the packet
*/
- protected IoWriteFuture sendIdentification(String ident) throws IOException {
- if (log.isDebugEnabled()) {
+ protected IoWriteFuture sendIdentification(String version, List<String> extraLines) throws Exception {
+ ReservedSessionMessagesHandler handler = getReservedSessionMessagesHandler();
+ IoWriteFuture future = (handler == null) ? null : handler.sendIdentification(this, version, extraLines);
+ boolean debugEnabled = log.isDebugEnabled();
+ if (future != null) {
+ if (debugEnabled) {
+ log.debug("sendIdentification({})[{}] sent {} lines via reserved handler",
+ this, version, GenericUtils.size(extraLines));
+ }
+
+ return future;
+ }
+
+ String ident = version;
+ if (GenericUtils.size(extraLines) > 0) {
+ ident = GenericUtils.join(extraLines, "\r\n") + "\r\n" + version;
+ }
+
+ if (debugEnabled) {
log.debug("sendIdentification({}): {}",
this, ident.replace('\r', '|').replace('\n', '|'));
}
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 d663c10..b388a6c 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
@@ -225,13 +225,7 @@
protected IoWriteFuture sendServerIdentification(List<String> headerLines) throws Exception {
serverVersion = resolveIdentificationString(CoreModuleProperties.SERVER_IDENTIFICATION.getName());
signalSendIdentification(serverVersion, headerLines);
-
- String ident = serverVersion;
- if (GenericUtils.size(headerLines) > 0) {
- ident = GenericUtils.join(headerLines, "\r\n") + "\r\n" + serverVersion;
- }
-
- return sendIdentification(ident);
+ return sendIdentification(serverVersion, headerLines);
}
@Override
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionImpl.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionImpl.java
index 9fee875..0b4a588 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionImpl.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionImpl.java
@@ -39,7 +39,7 @@
String headerConfig = CoreModuleProperties.SERVER_EXTRA_IDENTIFICATION_LINES.getOrNull(this);
String[] headers = GenericUtils.split(headerConfig, CoreModuleProperties.SERVER_EXTRA_IDENT_LINES_SEPARATOR);
- // We intentionally create a modifiable array so as to allow users to modify it via SessionListener
+ // We intentionally create a modifiable array so as to allow users to modify it via SessionListener or ReservedSessionMessagesHandler
List<String> extraLines = GenericUtils.isEmpty(headers)
? new ArrayList<>()
: new ArrayList<>(Arrays.asList(headers));