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 2015/12/01 10:26:58 UTC

mina-sshd git commit: [SSHD-602] Add support for 'acl-supported' extension

Repository: mina-sshd
Updated Branches:
  refs/heads/master 9044f1b04 -> c11b57ad6


[SSHD-602] Add support for 'acl-supported' extension


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/c11b57ad
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/c11b57ad
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/c11b57ad

Branch: refs/heads/master
Commit: c11b57ad665db7910156f31738cce638f35cbb1c
Parents: 9044f1b
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Tue Dec 1 11:26:04 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Tue Dec 1 11:26:04 2015 +0200

----------------------------------------------------------------------
 .../client/subsystem/sftp/SftpFileChannel.java  |   5 +-
 .../org/apache/sshd/common/mac/BaseMac.java     |   2 +-
 .../common/subsystem/sftp/SftpConstants.java    |  13 +-
 .../sftp/extensions/AclSupportedParser.java     | 210 +++++++++++++++++++
 .../subsystem/sftp/extensions/ParserUtils.java  |   1 +
 .../apache/sshd/common/util/GenericUtils.java   |  18 ++
 .../sshd/server/subsystem/sftp/FileHandle.java  |  35 ++--
 .../server/subsystem/sftp/SftpSubsystem.java    |  88 +++++++-
 .../org/apache/sshd/PortForwardingLoadTest.java |  14 +-
 .../org/apache/sshd/PortForwardingTest.java     |  18 +-
 .../java/org/apache/sshd/agent/AgentTest.java   |   5 +-
 .../sshd/client/subsystem/sftp/SftpTest.java    |  19 +-
 .../openssh/impl/OpenSSHExtensionsTest.java     |   9 +-
 .../deprecated/UserAuthKeyboardInteractive.java |  19 +-
 14 files changed, 382 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileChannel.java
index b656582..7220623 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileChannel.java
@@ -40,12 +40,11 @@ import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.sshd.common.PropertyResolverUtils;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.io.IoUtils;
 
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FX_LOCK_CONFLICT;
-
 public class SftpFileChannel extends FileChannel {
     public static final String COPY_BUFSIZE_PROP = "sftp-channel-copy-buf-size";
     public static final int DEFAULT_TRANSFER_BUFFER_SIZE = IoUtils.DEFAULT_COPY_SIZE;
@@ -322,7 +321,7 @@ public class SftpFileChannel extends FileChannel {
         try {
             sftp.lock(handle, position, size, 0);
         } catch (SftpException e) {
-            if (e.getStatus() == SSH_FX_LOCK_CONFLICT) {
+            if (e.getStatus() == SftpConstants.SSH_FX_LOCK_CONFLICT) {
                 throw new OverlappingFileLockException();
             }
             throw e;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/common/mac/BaseMac.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/BaseMac.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/BaseMac.java
index 76e09e8..5c9fc82 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/BaseMac.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/mac/BaseMac.java
@@ -108,7 +108,7 @@ public class BaseMac implements Mac {
     @Override
     public String toString() {
         return getClass().getSimpleName() + "[" + getAlgorithm() + "] - "
-             + getBlockSize() + "/" + getDefaultBlockSize() + " bits";
+             + " block=" + getBlockSize() + "/" + getDefaultBlockSize() + " bytes";
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
index ff7a081..21a7486 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
@@ -20,7 +20,6 @@ package org.apache.sshd.common.subsystem.sftp;
 
 import java.lang.reflect.Field;
 import java.util.Map;
-
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.Predicate;
 import org.apache.sshd.common.util.logging.LoggingUtils;
@@ -243,16 +242,28 @@ public final class SftpConstants {
     public static final String EXT_TEXT_SEEK = "text-seek";
     public static final String EXT_VERSION_SELECT = "version-select";
     public static final String EXT_COPY_FILE = "copy-file";
+
     public static final String EXT_MD5_HASH = "md5-hash";
     public static final String EXT_MD5_HASH_HANDLE = "md5-hash-handle";
     public static final int MD5_QUICK_HASH_SIZE = 2048;
+
     public static final String EXT_CHECK_FILE_HANDLE = "check-file-handle";
     public static final String EXT_CHECK_FILE_NAME = "check-file-name";
     public static final int MIN_CHKFILE_BLOCKSIZE = 256;
+
     public static final String EXT_CHECK_FILE = "check-file";
     public static final String EXT_COPY_DATA = "copy-data";
     public static final String EXT_SPACE_AVAILABLE = "space-available";
 
+    // see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-11 section 5.4
+    public static final String EXT_ACL_SUPPORTED = "acl-supported";
+    public static final int SSH_ACL_CAP_ALLOW = 0x00000001;
+    public static final int SSH_ACL_CAP_DENY = 0x00000002;
+    public static final int SSH_ACL_CAP_AUDIT = 0x00000004;
+    public static final int SSH_ACL_CAP_ALARM = 0x00000008;
+    public static final int SSH_ACL_CAP_INHERIT_ACCESS = 0x00000010;
+    public static final int SSH_ACL_CAP_INHERIT_AUDIT_ALARM = 0x00000020;
+
     private SftpConstants() {
         throw new UnsupportedOperationException("No instance");
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/AclSupportedParser.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/AclSupportedParser.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/AclSupportedParser.java
new file mode 100644
index 0000000..3859892
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/AclSupportedParser.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.subsystem.sftp.extensions;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.subsystem.sftp.extensions.AclSupportedParser.AclCapabilities;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+import org.apache.sshd.common.util.logging.LoggingUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class AclSupportedParser extends AbstractParser<AclCapabilities> {
+    /**
+     * The &quot;acl-supported&quot; information as per
+     * <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-11">DRAFT 11 - section 5.4</A>
+     *
+     * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+     */
+    public static class AclCapabilities implements Serializable, Cloneable {
+        private static final long serialVersionUID = -3118426327336468237L;
+        private int capabilities;
+
+        public AclCapabilities() {
+            this(0);
+        }
+
+        public AclCapabilities(int capabilities) {
+            this.capabilities = capabilities;
+        }
+
+        public int getCapabilities() {
+            return capabilities;
+        }
+
+        public void setCapabilities(int capabilities) {
+            this.capabilities = capabilities;
+        }
+
+        @Override
+        public int hashCode() {
+            return getCapabilities();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) {
+                return false;
+            }
+            if (obj == this) {
+                return true;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+
+            return ((AclCapabilities) obj).getCapabilities() == getCapabilities();
+        }
+
+        @Override
+        public AclCapabilities clone() {
+            try {
+                return getClass().cast(super.clone());
+            } catch (CloneNotSupportedException e) {
+                throw new RuntimeException("Failed to clone " + toString() + ": " + e.getMessage(), e);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return Objects.toString(decodeAclCapabilities(getCapabilities()));
+        }
+
+        private static class LazyAclCapabilityNameHolder {
+            private static final String ACL_CAP_NAME_PREFIX = "SSH_ACL_CAP_";
+            private static final Map<Integer, String> ACL_VALUES_MAP = LoggingUtils.generateMnemonicMap(SftpConstants.class, ACL_CAP_NAME_PREFIX);
+            private static final Map<String, Integer> ACL_NAMES_MAP =
+                    Collections.unmodifiableMap(GenericUtils.flipMap(ACL_VALUES_MAP, GenericUtils.<Integer>caseInsensitiveMap(), false));
+        }
+
+        @SuppressWarnings("synthetic-access")
+        public static Map<String, Integer> getAclCapabilityNamesMap() {
+            return LazyAclCapabilityNameHolder.ACL_NAMES_MAP;
+        }
+
+        /**
+         * @param name The ACL capability name - may be without the &quot;SSH_ACL_CAP_xxx&quot; prefix.
+         * Ignored if {@code null}/empty
+         * @return The matching {@link Integer} value - or {@code null} if no match found
+         */
+        public static Integer getAclCapabilityValue(String name) {
+            if (GenericUtils.isEmpty(name)) {
+                return null;
+            }
+
+            name = name.toUpperCase();
+            if (!name.startsWith(LazyAclCapabilityNameHolder.ACL_CAP_NAME_PREFIX)) {
+                name += LazyAclCapabilityNameHolder.ACL_CAP_NAME_PREFIX;
+            }
+
+            Map<String, Integer> map = getAclCapabilityNamesMap();
+            return map.get(name);
+        }
+
+        @SuppressWarnings("synthetic-access")
+        public static Map<Integer, String> getAclCapabilityValuesMap() {
+            return LazyAclCapabilityNameHolder.ACL_VALUES_MAP;
+        }
+
+        public static String getAclCapabilityName(int aclCapValue) {
+            Map<Integer, String> map = getAclCapabilityValuesMap();
+            String name = map.get(aclCapValue);
+            if (GenericUtils.isEmpty(name)) {
+                return Integer.toString(aclCapValue);
+            } else {
+                return name;
+            }
+        }
+
+        public static Set<String> decodeAclCapabilities(int mask) {
+            if (mask == 0) {
+                return Collections.emptySet();
+            }
+
+            Set<String> caps = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+            Map<Integer, String> map = getAclCapabilityValuesMap();
+            for (Map.Entry<Integer, String> ae : map.entrySet()) {
+                Integer value = ae.getKey();
+                String name = ae.getValue();
+                if ((mask & value.intValue()) != 0) {
+                    caps.add(name);
+                }
+            }
+
+            return caps;
+        }
+
+        public static int constructAclCapabilities(Collection<Integer> maskValues) {
+            if (GenericUtils.isEmpty(maskValues)) {
+                return 0;
+            }
+
+            int mask = 0;
+            for (Integer v : maskValues) {
+                mask |= v.intValue();
+            }
+
+            return mask;
+        }
+
+        public static Set<Integer> deconstructAclCapabilities(int mask) {
+            if (mask == 0) {
+                return Collections.emptySet();
+            }
+
+            Map<Integer, String> map = getAclCapabilityValuesMap();
+            Set<Integer> caps = new HashSet<Integer>(map.size());
+            for (Integer v : map.keySet()) {
+                if ((mask & v.intValue()) != 0) {
+                    caps.add(v);
+                }
+            }
+
+            return caps;
+        }
+    }
+
+    public static final AclSupportedParser INSTANCE = new AclSupportedParser();
+
+    public AclSupportedParser() {
+        super(SftpConstants.EXT_ACL_SUPPORTED);
+    }
+
+    @Override
+    public AclCapabilities parse(byte[] input, int offset, int len) {
+        return parse(new ByteArrayBuffer(input, offset, len));
+    }
+
+    public AclCapabilities parse(Buffer buffer) {
+        return new AclCapabilities(buffer.getInt());
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
index 7e16784..243d299 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/extensions/ParserUtils.java
@@ -52,6 +52,7 @@ public final class ParserUtils {
                             VersionsParser.INSTANCE,
                             SupportedParser.INSTANCE,
                             Supported2Parser.INSTANCE,
+                            AclSupportedParser.INSTANCE,
                             // OpenSSH extensions
                             PosixRenameExtensionParser.INSTANCE,
                             StatVfsExtensionParser.INSTANCE,

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index 13fc270..ed5593e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -330,6 +330,24 @@ public final class GenericUtils {
         return CASE_INSENSITIVE_MAP_FACTORY;
     }
 
+    public static <K, V> Map<V, K> flipMap(Map<? extends K, ? extends V> map, Factory<? extends Map<V, K>> mapCreator, boolean allowDuplicates) {
+        if (isEmpty(map)) {
+            return Collections.emptyMap();
+        }
+
+        Map<V, K> result = ValidateUtils.checkNotNull(mapCreator.create(), "No map created");
+        for (Map.Entry<? extends K, ? extends V> ee : map.entrySet()) {
+            K key = ee.getKey();
+            V value = ee.getValue();
+            K prev = result.put(value, key);
+            if ((prev != null) && (!allowDuplicates)) {
+                ValidateUtils.throwIllegalArgumentException("Multiple values for key=%s: current=%s, previous=%s", value, key, prev);
+            }
+        }
+
+        return result;
+    }
+
     @SafeVarargs
     public static <K, V> Map<K, V> mapValues(
             Transformer<? super V, ? extends K> keyMapper, Factory<? extends Map<K, V>> mapCreator, V ... values) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
index bd54bdf..faed6a0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
@@ -33,19 +33,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_APPEND_DATA;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_READ_ATTRIBUTES;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_READ_DATA;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_WRITE_ATTRIBUTES;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_WRITE_DATA;
-
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_ACCESS_DISPOSITION;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_APPEND_DATA;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_CREATE_NEW;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_CREATE_TRUNCATE;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_OPEN_EXISTING;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_OPEN_OR_CREATE;
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_TRUNCATE_EXISTING;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -62,31 +51,31 @@ public class FileHandle extends Handle {
         this.access = access;
 
         Set<OpenOption> options = new HashSet<>();
-        if (((access & ACE4_READ_DATA) != 0) || ((access & ACE4_READ_ATTRIBUTES) != 0)) {
+        if (((access & SftpConstants.ACE4_READ_DATA) != 0) || ((access & SftpConstants.ACE4_READ_ATTRIBUTES) != 0)) {
             options.add(StandardOpenOption.READ);
         }
-        if (((access & ACE4_WRITE_DATA) != 0) || ((access & ACE4_WRITE_ATTRIBUTES) != 0)) {
+        if (((access & SftpConstants.ACE4_WRITE_DATA) != 0) || ((access & SftpConstants.ACE4_WRITE_ATTRIBUTES) != 0)) {
             options.add(StandardOpenOption.WRITE);
         }
-        switch (flags & SSH_FXF_ACCESS_DISPOSITION) {
-            case SSH_FXF_CREATE_NEW:
+        switch (flags & SftpConstants.SSH_FXF_ACCESS_DISPOSITION) {
+            case SftpConstants.SSH_FXF_CREATE_NEW:
                 options.add(StandardOpenOption.CREATE_NEW);
                 break;
-            case SSH_FXF_CREATE_TRUNCATE:
+            case SftpConstants.SSH_FXF_CREATE_TRUNCATE:
                 options.add(StandardOpenOption.CREATE);
                 options.add(StandardOpenOption.TRUNCATE_EXISTING);
                 break;
-            case SSH_FXF_OPEN_EXISTING:
+            case SftpConstants.SSH_FXF_OPEN_EXISTING:
                 break;
-            case SSH_FXF_OPEN_OR_CREATE:
+            case SftpConstants.SSH_FXF_OPEN_OR_CREATE:
                 options.add(StandardOpenOption.CREATE);
                 break;
-            case SSH_FXF_TRUNCATE_EXISTING:
+            case SftpConstants.SSH_FXF_TRUNCATE_EXISTING:
                 options.add(StandardOpenOption.TRUNCATE_EXISTING);
                 break;
             default:    // ignored
         }
-        if ((flags & SSH_FXF_APPEND_DATA) != 0) {
+        if ((flags & SftpConstants.SSH_FXF_APPEND_DATA) != 0) {
             options.add(StandardOpenOption.APPEND);
         }
         FileAttribute<?>[] attributes = new FileAttribute<?>[attrs.size()];
@@ -126,7 +115,7 @@ public class FileHandle extends Handle {
     }
 
     public boolean isOpenAppend() {
-        return ACE4_APPEND_DATA == (getAccessMask() & ACE4_APPEND_DATA);
+        return SftpConstants.ACE4_APPEND_DATA == (getAccessMask() & SftpConstants.ACE4_APPEND_DATA);
     }
 
     public int read(byte[] data, long offset) throws IOException {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index fca8f5c..8449f5c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -59,6 +59,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -86,6 +87,7 @@ import org.apache.sshd.common.file.FileSystemAware;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.subsystem.sftp.SftpHelper;
+import org.apache.sshd.common.subsystem.sftp.extensions.AclSupportedParser;
 import org.apache.sshd.common.subsystem.sftp.extensions.SpaceAvailableExtensionInfo;
 import org.apache.sshd.common.subsystem.sftp.extensions.openssh.AbstractOpenSSHExtensionParser.OpenSSHExtension;
 import org.apache.sshd.common.subsystem.sftp.extensions.openssh.FsyncExtensionParser;
@@ -228,6 +230,19 @@ public class SftpSubsystem
     public static final List<String> DEFAULT_UNIX_VIEW = Collections.singletonList("unix:*");
 
     /**
+     * Comma separate list of {@code SSH_ACL_CAP_xxx} names - where name can be without
+     * the prefix. If not defined then {@link #DEFAULT_ACL_SUPPORTED_MASK} is used
+     */
+    public static final String ACL_SUPPORTED_MASK_PROP = "sftp-acl-supported-mask";
+    public static final Set<Integer> DEFAULT_ACL_SUPPORTED_MASK =
+            Collections.unmodifiableSet(
+                    new HashSet<Integer>(Arrays.asList(
+                            SftpConstants.SSH_ACL_CAP_ALLOW,
+                            SftpConstants.SSH_ACL_CAP_DENY,
+                            SftpConstants.SSH_ACL_CAP_AUDIT,
+                            SftpConstants.SSH_ACL_CAP_ALARM)));
+
+    /**
      * A {@link Map} of {@link FileInfoExtractor}s to be used to complete
      * attributes that are deemed important enough to warrant an extra
      * effort if not accessible via the file system attributes views
@@ -2198,13 +2213,7 @@ public class SftpSubsystem
         appendNewlineExtension(buffer, IoUtils.EOL);
         appendVendorIdExtension(buffer, VersionProperties.getVersionProperties());
         appendOpenSSHExtensions(buffer);
-
-        /* TODO updateAvailableExtensions(extensions, appendAclSupportedExtension(...)
-            buffer.putString("acl-supported");
-            buffer.putInt(4);
-            // capabilities
-            buffer.putInt(0);
-        */
+        appendAclSupportedExtension(buffer);
 
         Map<String, OptionalFeature> extensions = getSupportedClientExtensions();
         int numExtensions = GenericUtils.size(extensions);
@@ -2227,8 +2236,56 @@ public class SftpSubsystem
         appendSupported2Extension(buffer, extras);
     }
 
+    protected int appendAclSupportedExtension(Buffer buffer) {
+        ServerSession session = getServerSession();
+        Collection<Integer> maskValues = resolveAclSupportedCapabilities(session);
+        int mask = AclSupportedParser.AclCapabilities.constructAclCapabilities(maskValues);
+        if (mask != 0) {
+            if (log.isTraceEnabled()) {
+                log.trace("appendAclSupportedExtension({}) capabilities={}",
+                          session, AclSupportedParser.AclCapabilities.decodeAclCapabilities(mask));
+            }
+
+            buffer.putString(SftpConstants.EXT_ACL_SUPPORTED);
+
+            // placeholder for length
+            int lenPos = buffer.wpos();
+            buffer.putInt(0);
+            buffer.putInt(mask);
+            BufferUtils.updateLengthPlaceholder(buffer, lenPos);
+        }
+
+        return mask;
+    }
+
+    protected Collection<Integer> resolveAclSupportedCapabilities(ServerSession session) {
+        String override = PropertyResolverUtils.getString(session, ACL_SUPPORTED_MASK_PROP);
+        if (override == null) {
+            return DEFAULT_ACL_SUPPORTED_MASK;
+        }
+
+        // empty means not supported
+        if (log.isDebugEnabled()) {
+            log.debug("resolveAclSupportedCapabilities({}) override='{}'", session, override);
+        }
+
+        if (override.length() == 0) {
+            return Collections.emptySet();
+        }
+
+        String[] names = GenericUtils.split(override, ',');
+        Set<Integer> maskValues = new HashSet<Integer>(names.length);
+        for (String n : names) {
+            Integer v = ValidateUtils.checkNotNull(
+                    AclSupportedParser.AclCapabilities.getAclCapabilityValue(n), "Unknown ACL capability: %s", n);
+            maskValues.add(v);
+        }
+
+        return maskValues;
+    }
+
     protected List<OpenSSHExtension> appendOpenSSHExtensions(Buffer buffer) {
-        List<OpenSSHExtension> extList = resolveOpenSSHExtensions();
+        List<OpenSSHExtension> extList = resolveOpenSSHExtensions(getServerSession());
         if (GenericUtils.isEmpty(extList)) {
             return extList;
         }
@@ -2241,12 +2298,16 @@ public class SftpSubsystem
         return extList;
     }
 
-    protected List<OpenSSHExtension> resolveOpenSSHExtensions() {
-        String value = PropertyResolverUtils.getString(getServerSession(), OPENSSH_EXTENSIONS_PROP);
+    protected List<OpenSSHExtension> resolveOpenSSHExtensions(ServerSession session) {
+        String value = PropertyResolverUtils.getString(session, OPENSSH_EXTENSIONS_PROP);
         if (value == null) {    // No override
             return DEFAULT_OPEN_SSH_EXTENSIONS;
         }
 
+        if (log.isDebugEnabled()) {
+            log.debug("resolveOpenSSHExtensions({}) override='{}'", session, value);
+        }
+
         String[] pairs = GenericUtils.split(value, ',');
         int numExts = GenericUtils.length(pairs);
         if (numExts <= 0) {     // User does not want to report ANY extensions
@@ -2271,11 +2332,16 @@ public class SftpSubsystem
     }
 
     protected Map<String, OptionalFeature> getSupportedClientExtensions() {
-        String value = PropertyResolverUtils.getString(getServerSession(), CLIENT_EXTENSIONS_PROP);
+        ServerSession session = getServerSession();
+        String value = PropertyResolverUtils.getString(session, CLIENT_EXTENSIONS_PROP);
         if (value == null) {
             return DEFAULT_SUPPORTED_CLIENT_EXTENSIONS;
         }
 
+        if (log.isDebugEnabled()) {
+            log.debug("getSupportedClientExtensions({}) override='{}'", session, value);
+        }
+
         if (value.length() <= 0) {  // means don't report any extensions
             return Collections.emptyMap();
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java b/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
index 8939797..d5720a9 100644
--- a/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
@@ -18,8 +18,6 @@
  */
 package org.apache.sshd;
 
-import static org.apache.sshd.util.test.Utils.getFreePort;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -37,9 +35,6 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
 import org.apache.commons.httpclient.HostConfiguration;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpVersion;
@@ -55,6 +50,7 @@ import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
+import org.apache.sshd.util.test.Utils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
@@ -63,6 +59,10 @@ import org.junit.runners.MethodSorters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
 /**
  * Port forwarding tests
  */
@@ -223,7 +223,7 @@ public class PortForwardingLoadTest extends BaseTestSupport {
             ss.setReuseAddress(true);
             ss.bind(new InetSocketAddress((InetAddress) null, 0));
             int forwardedPort = ss.getLocalPort();
-            int sinkPort = getFreePort();
+            int sinkPort = Utils.getFreePort();
             session.setPortForwardingR(sinkPort, TEST_LOCALHOST, forwardedPort);
             final boolean started[] = new boolean[1];
             started[0] = false;
@@ -344,7 +344,7 @@ public class PortForwardingLoadTest extends BaseTestSupport {
         Session session = createSession();
         try {
             final int forwardedPort1 = session.setPortForwardingL(0, host, port);
-            final int forwardedPort2 = getFreePort();
+            final int forwardedPort2 = Utils.getFreePort();
             session.setPortForwardingR(forwardedPort2, TEST_LOCALHOST, forwardedPort1);
             System.err.println("URL: http://localhost:" + forwardedPort2);
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java b/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
index 6380390..490f884 100644
--- a/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
@@ -18,8 +18,6 @@
  */
 package org.apache.sshd;
 
-import static org.apache.sshd.util.test.Utils.getFreePort;
-
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
@@ -38,9 +36,6 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.TimeUnit;
 
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
 import org.apache.mina.core.buffer.IoBuffer;
 import org.apache.mina.core.service.IoAcceptor;
 import org.apache.mina.core.service.IoHandlerAdapter;
@@ -64,6 +59,7 @@ import org.apache.sshd.server.global.TcpipForwardHandler;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
+import org.apache.sshd.util.test.Utils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
@@ -71,6 +67,10 @@ import org.junit.Test;
 import org.junit.runners.MethodSorters;
 import org.slf4j.LoggerFactory;
 
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
 /**
  * Port forwarding tests
  */
@@ -196,7 +196,7 @@ public class PortForwardingTest extends BaseTestSupport {
     public void testRemoteForwarding() throws Exception {
         Session session = createSession();
         try {
-            int forwardedPort = getFreePort();
+            int forwardedPort = Utils.getFreePort();
             session.setPortForwardingR(forwardedPort, TEST_LOCALHOST, echoPort);
             waitForForwardingRequest(TcpipForwardHandler.REQUEST, TimeUnit.SECONDS.toMillis(5L));
 
@@ -227,7 +227,7 @@ public class PortForwardingTest extends BaseTestSupport {
     public void testRemoteForwardingSecondTimeInSameSession() throws Exception {
         Session session = createSession();
         try {
-            int forwardedPort = getFreePort();
+            int forwardedPort = Utils.getFreePort();
             session.setPortForwardingR(forwardedPort, TEST_LOCALHOST, echoPort);
             waitForForwardingRequest(TcpipForwardHandler.REQUEST, TimeUnit.SECONDS.toMillis(5L));
 
@@ -323,7 +323,7 @@ public class PortForwardingTest extends BaseTestSupport {
     public void testLocalForwarding() throws Exception {
         Session session = createSession();
         try {
-            int forwardedPort = getFreePort();
+            int forwardedPort = Utils.getFreePort();
             session.setPortForwardingL(forwardedPort, TEST_LOCALHOST, echoPort);
 
             try (Socket s = new Socket(TEST_LOCALHOST, forwardedPort);
@@ -455,7 +455,7 @@ public class PortForwardingTest extends BaseTestSupport {
         Session session = createSession();
         try {
             // 1. Create a Port Forward
-            int forwardedPort = getFreePort();
+            int forwardedPort = Utils.getFreePort();
             session.setPortForwardingR(forwardedPort, TEST_LOCALHOST, echoPort);
             waitForForwardingRequest(TcpipForwardHandler.REQUEST, TimeUnit.SECONDS.toMillis(5L));
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
index e0f8d79..fbdc82b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
@@ -18,8 +18,6 @@
  */
 package org.apache.sshd.agent;
 
-import static org.apache.sshd.util.test.Utils.createTestKeyPairProvider;
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -46,6 +44,7 @@ import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.EchoShell;
 import org.apache.sshd.util.test.EchoShellFactory;
+import org.apache.sshd.util.test.Utils;
 import org.junit.Assume;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -102,7 +101,7 @@ public class AgentTest extends BaseTestSupport {
         ProxyAgentFactory agentFactory = new ProxyAgentFactory();
         LocalAgentFactory localAgentFactory = new LocalAgentFactory();
         String username = getCurrentTestName();
-        KeyPair pair = createTestKeyPairProvider("dsaprivkey.pem").loadKey(KeyPairProvider.SSH_DSS);
+        KeyPair pair = Utils.createTestKeyPairProvider("dsaprivkey.pem").loadKey(KeyPairProvider.SSH_DSS);
         localAgentFactory.getAgent().addIdentity(pair, username);
 
         try (SshServer sshd1 = setupTestServer()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index a5a096d..9274c5b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -39,6 +39,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeSet;
 import java.util.Vector;
 import java.util.concurrent.TimeUnit;
@@ -61,6 +62,7 @@ import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.subsystem.sftp.extensions.AclSupportedParser.AclCapabilities;
 import org.apache.sshd.common.subsystem.sftp.extensions.ParserUtils;
 import org.apache.sshd.common.subsystem.sftp.extensions.Supported2Parser.Supported2;
 import org.apache.sshd.common.subsystem.sftp.extensions.SupportedParser.Supported;
@@ -931,7 +933,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
                     Map<String, byte[]> extensions = sftp.getServerExtensions();
                     for (String name : new String[]{
                             SftpConstants.EXT_NEWLINE, SftpConstants.EXT_VERSIONS,
-                            SftpConstants.EXT_VENDOR_ID,
+                            SftpConstants.EXT_VENDOR_ID, SftpConstants.EXT_ACL_SUPPORTED,
                             SftpConstants.EXT_SUPPORTED, SftpConstants.EXT_SUPPORTED2
                     }) {
                         assertTrue("Missing extension=" + name, extensions.containsKey(name));
@@ -946,6 +948,14 @@ public class SftpTest extends AbstractSftpClientTestSupport {
                             assertSupportedExtensions(extName, ((Supported) extValue).extensionNames);
                         } else if (SftpConstants.EXT_SUPPORTED2.equalsIgnoreCase(extName)) {
                             assertSupportedExtensions(extName, ((Supported2) extValue).extensionNames);
+                        } else if (SftpConstants.EXT_ACL_SUPPORTED.equalsIgnoreCase(extName)) {
+                            assertSupportedAclCapabilities((AclCapabilities) extValue);
+                        }
+                    }
+
+                    for (String extName : extensions.keySet()) {
+                        if (!data.containsKey(extName)) {
+                            outputDebugMessage("No parser for extension=%s", extName);
                         }
                     }
 
@@ -998,6 +1008,13 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         }
     }
 
+    private static void assertSupportedAclCapabilities(AclCapabilities caps) {
+        Set<Integer> actual = AclCapabilities.deconstructAclCapabilities(caps.getCapabilities());
+        assertEquals("Mismatched ACL capabilities count", SftpSubsystem.DEFAULT_ACL_SUPPORTED_MASK.size(), actual.size());
+        assertTrue("Missing capabilities - expected=" + SftpSubsystem.DEFAULT_ACL_SUPPORTED_MASK + ", actual=" + actual,
+                   actual.containsAll(SftpSubsystem.DEFAULT_ACL_SUPPORTED_MASK));
+    }
+
     @Test
     public void testSftpVersionSelector() throws Exception {
         final AtomicInteger selected = new AtomicInteger(-1);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
index 18b5ec3..10c5b5b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
@@ -50,6 +50,7 @@ import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.server.Command;
+import org.apache.sshd.server.session.ServerSession;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.Utils;
@@ -59,8 +60,6 @@ import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
 
-import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_EXTENDED_REPLY;
-
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
@@ -141,8 +140,8 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
             public Command create() {
                 return new SftpSubsystem(getExecutorService(), isShutdownOnExit(), getUnsupportedAttributePolicy()) {
                     @Override
-                    protected List<OpenSSHExtension> resolveOpenSSHExtensions() {
-                        List<OpenSSHExtension> original = super.resolveOpenSSHExtensions();
+                    protected List<OpenSSHExtension> resolveOpenSSHExtensions(ServerSession session) {
+                        List<OpenSSHExtension> original = super.resolveOpenSSHExtensions(session);
                         int numOriginal = GenericUtils.size(original);
                         List<OpenSSHExtension> result = new ArrayList<OpenSSHExtension>(numOriginal + 2);
                         if (numOriginal > 0) {
@@ -166,7 +165,7 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
                             }
 
                             buffer.clear();
-                            buffer.putByte((byte) SSH_FXP_EXTENDED_REPLY);
+                            buffer.putByte((byte) SftpConstants.SSH_FXP_EXTENDED_REPLY);
                             buffer.putInt(id);
                             OpenSSHStatExtensionInfo.encode(buffer, expected);
                             send(buffer);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c11b57ad/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
index 0732e06..9201607 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthKeyboardInteractive.java
@@ -25,10 +25,6 @@ import org.apache.sshd.client.auth.UserInteraction;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.util.buffer.Buffer;
-import static org.apache.sshd.common.SshConstants.SSH_MSG_USERAUTH_FAILURE;
-import static org.apache.sshd.common.SshConstants.SSH_MSG_USERAUTH_INFO_REQUEST;
-import static org.apache.sshd.common.SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE;
-import static org.apache.sshd.common.SshConstants.SSH_MSG_USERAUTH_SUCCESS;
 
 /**
  * Userauth with keyboard-interactive method.
@@ -62,12 +58,14 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
         } else {
             int cmd = buffer.getUByte();
             switch (cmd) {
-                case SSH_MSG_USERAUTH_INFO_REQUEST:
-                    log.debug("Received SSH_MSG_USERAUTH_INFO_REQUEST");
+                case SshConstants.SSH_MSG_USERAUTH_INFO_REQUEST: {
                     String name = buffer.getString();
                     String instruction = buffer.getString();
                     String language_tag = buffer.getString();
-                    log.info("Received {} {} {}", new Object[]{name, instruction, language_tag});
+                    if (log.isDebugEnabled()) {
+                        log.debug("next({}) Received SSH_MSG_USERAUTH_INFO_REQUEST - name={}, instruction={}, lang={}",
+                                 session, name, instruction, language_tag);
+                    }
                     int num = buffer.getInt();
                     String[] prompt = new String[num];
                     boolean[] echo = new boolean[num];
@@ -93,17 +91,18 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
                         return Result.Failure;
                     }
 
-                    buffer = session.createBuffer(SSH_MSG_USERAUTH_INFO_RESPONSE);
+                    buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE);
                     buffer.putInt(rep.length);
                     for (String r : rep) {
                         buffer.putString(r);
                     }
                     session.writePacket(buffer);
                     return Result.Continued;
-                case SSH_MSG_USERAUTH_SUCCESS:
+                }
+                case SshConstants.SSH_MSG_USERAUTH_SUCCESS:
                     log.debug("Received SSH_MSG_USERAUTH_SUCCESS");
                     return Result.Success;
-                case SSH_MSG_USERAUTH_FAILURE:
+                case SshConstants.SSH_MSG_USERAUTH_FAILURE:
                     {
                         String methods = buffer.getString();
                         boolean partial = buffer.getBoolean();