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 2019/02/25 05:44:40 UTC

[mina-sshd] 03/03: [SSHD-870] Added unit tests to cover GPG2 keyring

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 00f2106d65be7724181b915641f4f1da3acba561
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Mon Feb 25 07:42:56 2019 +0200

    [SSHD-870] Added unit tests to cover GPG2 keyring
---
 .../keys/loader/openpgp/PGPPublicRingWatcher.java  |  47 +++++++++++++++------
 .../loader/openpgp/PGPPublicRingWatcherTest.java   |  25 +++++++----
 .../1F11118D536D856BDCE47D450C4AE71509F195FF.rev   |  32 ++++++++++++++
 .../30F6173E98A6D0AF0C72CF8C0F1C452CAE49CA29.key   | Bin 0 -> 1158 bytes
 .../D1DEB8CA8D7DB9DCA3A2F6D02891F4B771628949.key   | Bin 0 -> 1158 bytes
 .../src/test/resources/kbx2ring/pubring.kbx        | Bin 0 -> 1482 bytes
 .../src/test/resources/kbx2ring/trustdb.gpg        | Bin 0 -> 1240 bytes
 7 files changed, 82 insertions(+), 22 deletions(-)

diff --git a/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcher.java b/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcher.java
index 8d33af9..a8d121c 100644
--- a/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcher.java
+++ b/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcher.java
@@ -21,12 +21,14 @@ package org.apache.sshd.common.config.keys.loader.openpgp;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.security.GeneralSecurityException;
 import java.security.KeyFactory;
 import java.security.PublicKey;
 import java.security.spec.KeySpec;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -57,16 +59,18 @@ public class PGPPublicRingWatcher extends ModifiableFileWatcher implements PGPAu
     /**
      * @see <A HREF="https://www.gnupg.org/faq/whats-new-in-2.1.html#nosecring">Removal of the secret keyring</A>
      */
-    public static final String DEFAULT_PUBLIC_RING_FILENAME = "pubring.gpg";
+    public static final String GPG_V1_PUBLIC_RING_FILENAME = "pubring.gpg";
+    public static final String GPG_V2_PUBLIC_RING_FILENAME = "pubring.kbx";
+
+    /** V1 and V2 known public ring file names in <U>order</U> of preference */
+    public static final List<String> PUBLIC_RING_FILES =
+        Collections.unmodifiableList(
+            Arrays.asList(GPG_V2_PUBLIC_RING_FILENAME, GPG_V1_PUBLIC_RING_FILENAME));
 
     /** Holds a {@link Map} whose key=the fingerprint (case <U>insensitive</U>), value=the associated {@link PublicKey} */
     protected final AtomicReference<NavigableMap<String, PublicKey>> ringKeys =
         new AtomicReference<>(Collections.emptyNavigableMap());
 
-    public PGPPublicRingWatcher() {
-        this(getDefaultPublicRingFilePath());
-    }
-
     public PGPPublicRingWatcher(Path file) {
         super(file);
     }
@@ -249,16 +253,33 @@ public class PGPPublicRingWatcher extends ModifiableFileWatcher implements PGPAu
         return SecurityUtils.getKeyFactory(algorithm);
     }
 
-    private static final class LazyDefaultPublicRingPathHolder {
-        private static final Path PATH = PGPUtils.getDefaultPgpFolderPath().resolve(DEFAULT_PUBLIC_RING_FILENAME);
+    public static Path detectDefaultPublicRingFilePath() {
+        return detectDefaultPublicRingFilePath(PGPUtils.getDefaultPgpFolderPath());
+    }
+
+    /**
+     * Checks if either the {@value #GPG_V1_PUBLIC_RING_FILENAME} or {@value #GPG_V2_PUBLIC_RING_FILENAME}
+     * exist as a <U>regular</U> file and can be read. <B>Note:</B> it attempts the V2 file first.
+     *
+     * @param dir The directory to look into
+     * @return The resolved {@link Path} - {@code null} if none of the files exists.
+     */
+    public static Path detectDefaultPublicRingFilePath(Path dir) {
+        for (String name : PUBLIC_RING_FILES) {
+            Path file = dir.resolve(name);
+            if (!Files.exists(file)) {
+                continue;
+            }
+            if (!Files.isRegularFile(file)) {
+                continue;
+            }
+            if (!Files.isReadable(file)) {
+                continue;
+            }
 
-        private LazyDefaultPublicRingPathHolder() {
-            throw new UnsupportedOperationException("No instance");
+            return file;
         }
-    }
 
-    @SuppressWarnings("synthetic-access")
-    public static Path getDefaultPublicRingFilePath() {
-        return LazyDefaultPublicRingPathHolder.PATH;
+        return null;
     }
 }
diff --git a/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcherTest.java b/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcherTest.java
index c4aef51..b3ace53 100644
--- a/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcherTest.java
+++ b/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPPublicRingWatcherTest.java
@@ -19,7 +19,6 @@
 
 package org.apache.sshd.common.config.keys.loader.openpgp;
 
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.security.PublicKey;
 import java.util.Map;
@@ -36,8 +35,6 @@ import org.junit.Test;
 import org.junit.runners.MethodSorters;
 
 /**
- * TODO Add javadoc
- *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -48,8 +45,8 @@ public class PGPPublicRingWatcherTest extends JUnitTestSupport {
 
     @Test
     public void testDefaultRingPath() {
-        Path path = PGPPublicRingWatcher.getDefaultPublicRingFilePath();
-        Assume.assumeTrue("File does not exist: " + path, Files.exists(path));
+        Path path = PGPPublicRingWatcher.detectDefaultPublicRingFilePath();
+        Assume.assumeTrue("No default ring detected", path != null);
 
         try {
             testPublicRingWatcher(path);
@@ -60,10 +57,19 @@ public class PGPPublicRingWatcherTest extends JUnitTestSupport {
     }
 
     @Test
-    public void testResourcesKeyPath() throws Exception {
+    public void testV1ResourcesKeyPath() throws Exception {
         Path dir = CommonTestSupportUtils.resolve(
             detectSourcesFolder(), TEST_SUBFOLDER, RESOURCES_SUBFOLDER, "keyring");
-        Path file = dir.resolve(PGPPublicRingWatcher.DEFAULT_PUBLIC_RING_FILENAME);
+        Path file = dir.resolve(PGPPublicRingWatcher.GPG_V1_PUBLIC_RING_FILENAME);
+        Map<String, PublicKey> keys = testPublicRingWatcher(file);
+        assertFalse("No keys extracted", GenericUtils.isEmpty(keys));
+    }
+
+    @Test
+    public void testV2ResourcesKeyPath() throws Exception {
+        Path dir = CommonTestSupportUtils.resolve(
+            detectSourcesFolder(), TEST_SUBFOLDER, RESOURCES_SUBFOLDER, "kbx2ring");
+        Path file = dir.resolve(PGPPublicRingWatcher.GPG_V2_PUBLIC_RING_FILENAME);
         Map<String, PublicKey> keys = testPublicRingWatcher(file);
         assertFalse("No keys extracted", GenericUtils.isEmpty(keys));
     }
@@ -78,8 +84,9 @@ public class PGPPublicRingWatcherTest extends JUnitTestSupport {
             for (Map.Entry<String, PublicKey> ke : keys.entrySet()) {
                 String fp = ke.getKey();
                 PublicKey k = ke.getValue();
-                outputDebugMessage("%s: %s %s %s",
-                    getCurrentTestName(), fp, KeyUtils.getKeyType(k), KeyUtils.getFingerPrint(k));
+                outputDebugMessage("%s: %s %s[%d] %s",
+                    getCurrentTestName(), fp, KeyUtils.getKeyType(k),
+                    KeyUtils.getKeySize(k), KeyUtils.getFingerPrint(k));
             }
         }
 
diff --git a/sshd-openpgp/src/test/resources/kbx2ring/openpgp-revocs.d/1F11118D536D856BDCE47D450C4AE71509F195FF.rev b/sshd-openpgp/src/test/resources/kbx2ring/openpgp-revocs.d/1F11118D536D856BDCE47D450C4AE71509F195FF.rev
new file mode 100644
index 0000000..0130917
--- /dev/null
+++ b/sshd-openpgp/src/test/resources/kbx2ring/openpgp-revocs.d/1F11118D536D856BDCE47D450C4AE71509F195FF.rev
@@ -0,0 +1,32 @@
+This is a revocation certificate for the OpenPGP key:
+
+pub   rsa2048 2019-02-25 [S]
+      1F11118D536D856BDCE47D450C4AE71509F195FF
+uid          Apache MINA SSHD (Apache MINA SSHD RSA kbx) <de...@mina.apache.org>
+
+A revocation certificate is a kind of "kill switch" to publicly
+declare that a key shall not anymore be used.  It is not possible
+to retract such a revocation certificate once it has been published.
+
+Use it to revoke this key in case of a compromise or loss of
+the secret key.  However, if the secret key is still accessible,
+it is better to generate a new revocation certificate and give
+a reason for the revocation.  For details see the description of
+of the gpg command "--generate-revocation" in the GnuPG manual.
+
+To avoid an accidental use of this file, a colon has been inserted
+before the 5 dashes below.  Remove this colon with a text editor
+before importing and publishing this revocation certificate.
+
+:-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: This is a revocation certificate
+
+iQE2BCABCAAgFiEEHxERjVNthWvc5H1FDErnFQnxlf8FAlxzePoCHQAACgkQDErn
+FQnxlf//1gf/YQz/tbAkEkYStxWJDBBsSRp40Z+tMlk6wHe+YIfqzwi5aOfO4gIO
+aS5QgqBuiALFnjsFaeNlm4liUtRp2ztYkYSRHQqfDb4iGhjFLU74a9sr++luv/uI
+ZdSgmVD0DjSwo3zqrNRWvvGTdOAr3Jswwt5Qw9m9pIjLN+7USi3J7nJXMnPW22TV
+iAi6pUQvCH2PNyZthkl5z2tkNQN7Ib/gOjbEX8l7bOCr5xO3UqDMMzn3Gz8pQE08
+3U0tNe81nDBm/124icD9QPoVKxCJ8ZILA1rq6xg9l+fCPDxWgxYdPJx/Ies+0TxP
+wZouY8LyW5WHyZEl+FbzrlccrYbjqJ+Ung==
+=Rsk+
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/sshd-openpgp/src/test/resources/kbx2ring/private-keys-v1.d/30F6173E98A6D0AF0C72CF8C0F1C452CAE49CA29.key b/sshd-openpgp/src/test/resources/kbx2ring/private-keys-v1.d/30F6173E98A6D0AF0C72CF8C0F1C452CAE49CA29.key
new file mode 100644
index 0000000..36b4358
Binary files /dev/null and b/sshd-openpgp/src/test/resources/kbx2ring/private-keys-v1.d/30F6173E98A6D0AF0C72CF8C0F1C452CAE49CA29.key differ
diff --git a/sshd-openpgp/src/test/resources/kbx2ring/private-keys-v1.d/D1DEB8CA8D7DB9DCA3A2F6D02891F4B771628949.key b/sshd-openpgp/src/test/resources/kbx2ring/private-keys-v1.d/D1DEB8CA8D7DB9DCA3A2F6D02891F4B771628949.key
new file mode 100644
index 0000000..0585bc4
Binary files /dev/null and b/sshd-openpgp/src/test/resources/kbx2ring/private-keys-v1.d/D1DEB8CA8D7DB9DCA3A2F6D02891F4B771628949.key differ
diff --git a/sshd-openpgp/src/test/resources/kbx2ring/pubring.kbx b/sshd-openpgp/src/test/resources/kbx2ring/pubring.kbx
new file mode 100644
index 0000000..8c7c0fc
Binary files /dev/null and b/sshd-openpgp/src/test/resources/kbx2ring/pubring.kbx differ
diff --git a/sshd-openpgp/src/test/resources/kbx2ring/trustdb.gpg b/sshd-openpgp/src/test/resources/kbx2ring/trustdb.gpg
new file mode 100644
index 0000000..3749f5f
Binary files /dev/null and b/sshd-openpgp/src/test/resources/kbx2ring/trustdb.gpg differ