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/02 14:46:09 UTC

mina-sshd git commit: [SSHD-606] Windows strict permissions key file check always fails due to owner mismatch

Repository: mina-sshd
Updated Branches:
  refs/heads/master 23ac5e3bd -> 484b793e4


[SSHD-606] Windows strict permissions key file check always fails due to owner mismatch


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

Branch: refs/heads/master
Commit: 484b793e40095bf5348a1629e08224fe20c68fb6
Parents: 23ac5e3
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Wed Dec 2 15:45:57 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Wed Dec 2 15:45:57 2015 +0200

----------------------------------------------------------------------
 .../org/apache/sshd/common/util/io/IoUtils.java | 19 ++++-
 .../sshd/common/config/keys/KeyUtilsTest.java   | 43 +++++++++++
 .../util/io/ModifiableFileWatcherTest.java      | 79 ++++++++++++++++++++
 3 files changed, 139 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/484b793e/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
index f8e692c..981725f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
@@ -262,13 +262,28 @@ public final class IoUtils {
      *
      * @param path  The {@link Path}
      * @param options The {@link LinkOption}s to use when querying the owner
-     * @return Owner of the file or null if unsupported
+     * @return Owner of the file or null if unsupported. <B>Note:</B> for
+     * <I>Windows</I> it strips any prepended domain or group name
      * @throws IOException If failed to access the file system
+     * @see Files#getOwner(Path, LinkOption...)
      */
     public static String getFileOwner(Path path, LinkOption... options) throws IOException {
         try {
             UserPrincipal principal = Files.getOwner(path, options);
-            return (principal == null) ? null : principal.getName();
+            String owner = (principal == null) ? null : principal.getName();
+            if (GenericUtils.isEmpty(owner)) {
+                return owner;
+            }
+
+            // Windows owner sometime has the domain and/or group prepended to it
+            if (OsUtils.isWin32()) {
+                int pos = owner.lastIndexOf('\\');
+                if (pos > 0) {
+                    return owner.substring(pos + 1);
+                }
+            }
+
+            return owner;
         } catch (UnsupportedOperationException e) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/484b793e/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
index bda03a4..03af665 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
@@ -19,11 +19,19 @@
 
 package org.apache.sshd.common.config.keys;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFilePermission;
 import java.security.DigestException;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.security.PrivateKey;
 import java.security.PublicKey;
+import java.util.Collection;
+import java.util.Date;
 
 import org.apache.sshd.common.cipher.ECCurves;
 import org.apache.sshd.common.digest.BaseDigest;
@@ -32,7 +40,10 @@ import org.apache.sshd.common.digest.Digest;
 import org.apache.sshd.common.digest.DigestFactory;
 import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.OsUtils;
+import org.apache.sshd.common.util.Pair;
 import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.junit.Assume;
 import org.junit.FixMethodOrder;
@@ -179,6 +190,38 @@ public class KeyUtilsTest extends BaseTestSupport {
         }
     }
 
+    @Test   // see SSHD-606
+    public void testValidateStrictKeyFilePermissions() throws IOException {
+        Path file = getTempTargetRelativeFile(getClass().getSimpleName(), getCurrentTestName());
+        outputDebugMessage("%s deletion result=%s", file, Files.deleteIfExists(file));
+        assertNull("Unexpected violation for non-existent file: " + file, KeyUtils.validateStrictKeyFilePermissions(file));
+
+        assertHierarchyTargetFolderExists(file.getParent());
+        try (OutputStream output = Files.newOutputStream(file)) {
+            output.write((getClass().getName() + "#" + getCurrentTestName() + "@" + new Date(System.currentTimeMillis())).getBytes(StandardCharsets.UTF_8));
+        }
+
+        Collection<PosixFilePermission> perms = IoUtils.getPermissions(file);
+        if (GenericUtils.isEmpty(perms)) {
+            assertNull("Unexpected violation for no permissions file: " + file, KeyUtils.validateStrictKeyFilePermissions(file));
+        } else if (OsUtils.isUNIX()) {
+            Pair<String, Object> violation = null;
+            for (PosixFilePermission p : KeyUtils.STRICTLY_PROHIBITED_FILE_PERMISSION) {
+                if (perms.contains(p)) {
+                    violation = KeyUtils.validateStrictKeyFilePermissions(file);
+                    assertNotNull("Unexpected success for permission=" + p + " of file " + file + " permissions=" + perms, violation);
+                    break;
+                }
+            }
+
+            if (violation == null) {    // we expect a failure since the parent does not have the necessary permissions
+                assertNotNull("Unexpected UNIX success for file " + file + " permissions=" + perms, KeyUtils.validateStrictKeyFilePermissions(file));
+            }
+        } else {
+            assertNull("Unexpected Windows violation for file " + file + " permissions=" + perms, KeyUtils.validateStrictKeyFilePermissions(file));
+        }
+    }
+
     private static KeyPair generateKeyPair(String keyType, int keySize) throws GeneralSecurityException {
         try {
             System.out.println("generateKeyPair(" + keyType + ")[" + keySize + "]");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/484b793e/sshd-core/src/test/java/org/apache/sshd/common/util/io/ModifiableFileWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/io/ModifiableFileWatcherTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/io/ModifiableFileWatcherTest.java
new file mode 100644
index 0000000..4caa791
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/util/io/ModifiableFileWatcherTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.util.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Collection;
+import java.util.Date;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.OsUtils;
+import org.apache.sshd.common.util.Pair;
+import org.apache.sshd.util.test.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ModifiableFileWatcherTest extends BaseTestSupport {
+    public ModifiableFileWatcherTest() {
+        super();
+    }
+
+    @Test   // see SSHD-606
+    public void testValidateStrictConfigFilePermissions() throws IOException {
+        Path file = getTempTargetRelativeFile(getClass().getSimpleName(), getCurrentTestName());
+        outputDebugMessage("%s deletion result=%s", file, Files.deleteIfExists(file));
+        assertNull("Unexpected violation for non-existent file: " + file, ModifiableFileWatcher.validateStrictConfigFilePermissions(file));
+
+        assertHierarchyTargetFolderExists(file.getParent());
+        try (OutputStream output = Files.newOutputStream(file)) {
+            output.write((getClass().getName() + "#" + getCurrentTestName() + "@" + new Date(System.currentTimeMillis())).getBytes(StandardCharsets.UTF_8));
+        }
+
+        Collection<PosixFilePermission> perms = IoUtils.getPermissions(file);
+        if (GenericUtils.isEmpty(perms)) {
+            assertNull("Unexpected violation for no permissions file: " + file, ModifiableFileWatcher.validateStrictConfigFilePermissions(file));
+        } else if (OsUtils.isUNIX()) {
+            Pair<String, Object> violation = null;
+            for (PosixFilePermission p : ModifiableFileWatcher.STRICTLY_PROHIBITED_FILE_PERMISSION) {
+                if (perms.contains(p)) {
+                    violation = ModifiableFileWatcher.validateStrictConfigFilePermissions(file);
+                    assertNotNull("Unexpected success for permission=" + p + " of file " + file + " permissions=" + perms, violation);
+                    break;
+                }
+            }
+
+            if (violation == null) {    // we do not expected a failure if no permissions have been violated
+                assertNull("Unexpected UNIX violation for file " + file + " permissions=" + perms, ModifiableFileWatcher.validateStrictConfigFilePermissions(file));
+            }
+        } else {
+            assertNull("Unexpected Windows violation for file " + file + " permissions=" + perms, ModifiableFileWatcher.validateStrictConfigFilePermissions(file));
+        }
+    }
+}