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 2021/01/02 07:14:54 UTC

[mina-sshd] 15/15: [SSHD-1114] Added HostBasedAuthenticationReporter#signalAuthenticationExhausted

This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit f4aa59fd93aa8a17a7853cc397607aec081e73b9
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri Jan 1 08:38:10 2021 +0200

    [SSHD-1114] Added HostBasedAuthenticationReporter#signalAuthenticationExhausted
---
 docs/client-setup.md                               |  6 +++---
 .../hostbased/HostBasedAuthenticationReporter.java | 18 ++++++++++++++++
 .../client/auth/hostbased/UserAuthHostBased.java   | 25 +++++++++++++---------
 .../sshd/client/auth/pubkey/UserAuthPublicKey.java |  3 +--
 4 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/docs/client-setup.md b/docs/client-setup.md
index 7f71922..0fc059e 100644
--- a/docs/client-setup.md
+++ b/docs/client-setup.md
@@ -100,9 +100,9 @@ This interface is required for full support of `keyboard-interactive` authentica
 The client can handle a simple password request from the server, but if more complex challenge-response interaction is required, then this interface must be
 provided - including support for `SSH_MSG_USERAUTH_PASSWD_CHANGEREQ` as described in [RFC 4252 section 8](https://tools.ietf.org/html/rfc4252#section-8).
 
-While RFC-4256 support is the primary purpose of this interface, it can also be used to retrieve the server's welcome banner as described
-in [RFC 4252 section 5.4](https://tools.ietf.org/html/rfc4252#section-5.4) as well as its initial identification string as described
-in [RFC 4253 section 4.2](https://tools.ietf.org/html/rfc4253#section-4.2).
+While ]RFC-4256](https://tools.ietf.org/html/rfc4256) support is the primary purpose of this interface, it can also be used to retrieve the server's
+welcome banner as described in [RFC 4252 section 5.4](https://tools.ietf.org/html/rfc4252#section-5.4) as well as its initial identification string
+as described in [RFC 4253 section 4.2](https://tools.ietf.org/html/rfc4253#section-4.2).
 
 In this context, regardless of whether such interaction is configured, the default implementation for the client side contains code
 that attempts to auto-detect a password prompt. If it detects it, then it attempts to use one of the registered passwords (if any) as
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/HostBasedAuthenticationReporter.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/HostBasedAuthenticationReporter.java
index 18c2193..749b5bc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/HostBasedAuthenticationReporter.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/HostBasedAuthenticationReporter.java
@@ -49,6 +49,24 @@ public interface HostBasedAuthenticationReporter {
     }
 
     /**
+     * Signals end of host based attempts and optionally switching to other authentication methods. <B>Note:</B> neither
+     * {@link #signalAuthenticationSuccess(ClientSession, String, KeyPair, String, String) signalAuthenticationSuccess}
+     * nor {@link #signalAuthenticationFailure(ClientSession, String, KeyPair, String, String, boolean, List)
+     * signalAuthenticationFailure} are invoked.
+     *
+     * @param  session   The {@link ClientSession}
+     * @param  service   The requesting service name
+     * @param  hostname  The host name value sent to the server
+     * @param  username  The username value sent to the server
+     * @throws Exception If failed to handle the callback - <B>Note:</B> may cause session close
+     */
+    default void signalAuthenticationExhausted(
+            ClientSession session, String service, String hostname, String username)
+            throws Exception {
+        // ignored
+    }
+
+    /**
      * @param  session   The {@link ClientSession}
      * @param  service   The requesting service name
      * @param  identity  The {@link KeyPair} identity being attempted
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/UserAuthHostBased.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/UserAuthHostBased.java
index 5c18b5f..2e9ded2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/UserAuthHostBased.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/hostbased/UserAuthHostBased.java
@@ -96,15 +96,22 @@ public class UserAuthHostBased extends AbstractUserAuth implements SignatureFact
     protected boolean sendAuthDataRequest(ClientSession session, String service) throws Exception {
         String name = getName();
         boolean debugEnabled = log.isDebugEnabled();
-        if ((keys == null) || (!keys.hasNext())) {
+        String clientUsername = resolveClientUsername(session);
+        String clientHostname = resolveClientHostname(session);
+        HostBasedAuthenticationReporter reporter = session.getHostBasedAuthenticationReporter();
+        keyInfo = ((keys != null) && keys.hasNext()) ? keys.next() : null;
+        if (keyInfo == null) {
             if (debugEnabled) {
                 log.debug("sendAuthDataRequest({})[{}][{}] no more keys to send", session, service, name);
             }
 
+            if (reporter != null) {
+                reporter.signalAuthenticationExhausted(session, service, clientUsername, clientHostname);
+            }
+
             return false;
         }
 
-        keyInfo = keys.next();
         KeyPair kp = keyInfo.getKey();
         PublicKey pub = kp.getPublic();
         String keyType = KeyUtils.getKeyType(pub);
@@ -124,8 +131,6 @@ public class UserAuthHostBased extends AbstractUserAuth implements SignatureFact
 
         byte[] id = session.getSessionId();
         String username = session.getUsername();
-        String clientUsername = resolveClientUsername();
-        String clientHostname = resolveClientHostname();
         if (debugEnabled) {
             log.debug("sendAuthDataRequest({})[{}][{}] client={}@{}",
                     session, service, name, clientUsername, clientHostname);
@@ -164,7 +169,6 @@ public class UserAuthHostBased extends AbstractUserAuth implements SignatureFact
         byte[] signature = appendSignature(
                 session, service, keyType, pub, keyBytes,
                 clientHostname, clientUsername, verifier, buffer);
-        HostBasedAuthenticationReporter reporter = session.getHostBasedAuthenticationReporter();
         if (reporter != null) {
             reporter.signalAuthenticationAttempt(
                     session, service, kp, clientHostname, clientUsername, signature);
@@ -231,8 +235,8 @@ public class UserAuthHostBased extends AbstractUserAuth implements SignatureFact
         HostBasedAuthenticationReporter reporter = session.getHostBasedAuthenticationReporter();
         if (reporter != null) {
             reporter.signalAuthenticationSuccess(
-                    session, service, (keyInfo == null) ? null : keyInfo.getKey(), resolveClientHostname(),
-                    resolveClientUsername());
+                    session, service, (keyInfo == null) ? null : keyInfo.getKey(),
+                    resolveClientHostname(session), resolveClientUsername(session));
         }
     }
 
@@ -244,16 +248,17 @@ public class UserAuthHostBased extends AbstractUserAuth implements SignatureFact
         if (reporter != null) {
             reporter.signalAuthenticationFailure(
                     session, service, (keyInfo == null) ? null : keyInfo.getKey(),
-                    resolveClientHostname(), resolveClientUsername(), partial, serverMethods);
+                    resolveClientHostname(session), resolveClientUsername(session),
+                    partial, serverMethods);
         }
     }
 
-    protected String resolveClientUsername() {
+    protected String resolveClientUsername(ClientSession session) {
         String value = getClientUsername();
         return GenericUtils.isEmpty(value) ? OsUtils.getCurrentUser() : value;
     }
 
-    protected String resolveClientHostname() {
+    protected String resolveClientHostname(ClientSession session) {
         String value = getClientHostname();
         if (GenericUtils.isEmpty(value)) {
             value = SshdSocketAddress.toAddressString(
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java
index 26ee56d..f55fc4e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java
@@ -101,12 +101,12 @@ public class UserAuthPublicKey extends AbstractUserAuth implements SignatureFact
             throw new RuntimeSshException(e);
         }
 
+        PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter();
         if (current == null) {
             if (debugEnabled) {
                 log.debug("resolveAttemptedPublicKeyIdentity({})[{}] no more keys to send", session, service);
             }
 
-            PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter();
             if (reporter != null) {
                 reporter.signalAuthenticationExhausted(session, service);
             }
@@ -145,7 +145,6 @@ public class UserAuthPublicKey extends AbstractUserAuth implements SignatureFact
                     session, service, name, algo, KeyUtils.getFingerPrint(pubKey));
         }
 
-        PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter();
         if (reporter != null) {
             reporter.signalAuthenticationAttempt(session, service, keyPair, algo);
         }