diff --git a/cli/pom.xml b/cli/pom.xml index e7772b1bf228..a6623d626f42 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -72,7 +72,7 @@ org.apache.sshd sshd-core - 1.7.0 + 2.6.0 true diff --git a/cli/src/main/java/hudson/cli/PrivateKeyProvider.java b/cli/src/main/java/hudson/cli/PrivateKeyProvider.java index 579aae6e536b..1dc5444a61d8 100644 --- a/cli/src/main/java/hudson/cli/PrivateKeyProvider.java +++ b/cli/src/main/java/hudson/cli/PrivateKeyProvider.java @@ -34,14 +34,20 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.InvalidPathException; +import java.nio.file.Paths; import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; import java.security.KeyPair; +import java.security.Security; +import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Logger; +import java.util.stream.StreamSupport; import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.apache.sshd.common.util.io.resource.PathResource; import org.apache.sshd.common.util.security.SecurityUtils; /** @@ -52,7 +58,7 @@ */ public class PrivateKeyProvider { - private List privateKeys = new ArrayList<>(); + private final List privateKeys = new ArrayList<>(); /** * Get keys read so far. @@ -137,9 +143,18 @@ private static String readPemFile(File f) throws IOException{ } public static KeyPair loadKey(String pemString, String passwd) throws IOException, GeneralSecurityException { - return SecurityUtils.loadKeyPairIdentity("key", + Iterable itr = SecurityUtils.loadKeyPairIdentities(null, + new PathResource(Paths.get("key")), new ByteArrayInputStream(pemString.getBytes(UTF_8)), FilePasswordProvider.of(passwd)); + long numLoaded = itr == null ? 0 : StreamSupport.stream(itr.spliterator(), false).count(); + if (numLoaded <= 0) { + throw new InvalidKeyException("Unsupported private key file format: key"); + } + if (numLoaded != 1) { + throw new InvalidKeySpecException("Multiple private key pairs N/A: key"); + } + return itr.iterator().next(); } private static final Logger LOGGER = Logger.getLogger(PrivateKeyProvider.class.getName()); diff --git a/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java b/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java index b186263346ac..ab4b762a6ee8 100644 --- a/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java +++ b/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java @@ -7,10 +7,10 @@ import java.io.File; import java.io.IOException; -import java.lang.IllegalArgumentException; import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -81,13 +81,44 @@ public void loadKeyOpenSSH() throws IOException, GeneralSecurityException { } /** - key command: ssh-keygen -f openssh-unsupported -t rsa -b 1024 -p password - */ + key command: ssh-keygen -f openssh-unsupported -t rsa -b 1024 -m PKCS8 -p password + */ + @Test + public void loadKeyOpenSSHPKCS8() throws IOException, GeneralSecurityException { + File file = new File(this.getClass().getResource("openssh-pkcs8").getFile()); + String password = "password"; + assertKeyPairNotNull(file, password); + } + + /** + key command: ssh-keygen -f openssh-unsupported -t rsa -b 1024 -m RFC4716 -p password + */ + @Test + public void loadKeyOpenSSHRFC4716() throws IOException, GeneralSecurityException { + File file = new File(this.getClass().getResource("openssh-rfc4716").getFile()); + String password = "password"; + assertKeyPairNotNull(file, password); + } + + /** + key command: ssh-keygen -f openssh-unsupported -t rsa -b 1024 -m RFC4716 -p password + Copy pasted the same key twice + */ + @Test + public void loadKeyOpenSSHMultipleKeys() throws IOException, GeneralSecurityException { + File file = new File(this.getClass().getResource("openssh-multiple-keys").getFile()); + String password = "password"; + assertThrows(InvalidKeySpecException.class, () -> PrivateKeyProvider.loadKey(file, password)); + } + + /** + * Uses a blank file + */ @Test - public void loadKeyUnsupportedCipher() throws IOException, GeneralSecurityException { - File file = new File(this.getClass().getResource("openssh-unsuported").getFile()); + public void loadBlankKey() throws IOException, GeneralSecurityException { + File file = new File(this.getClass().getResource("blank").getFile()); String password = "password"; - assertThrows(NoSuchAlgorithmException.class, () -> PrivateKeyProvider.loadKey(file, password)); + assertThrows(InvalidKeyException.class, () -> PrivateKeyProvider.loadKey(file, password)); } /** diff --git a/cli/src/test/resources/hudson/cli/blank b/cli/src/test/resources/hudson/cli/blank new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cli/src/test/resources/hudson/cli/openssh-multiple-keys b/cli/src/test/resources/hudson/cli/openssh-multiple-keys new file mode 100644 index 000000000000..be36fb99a579 --- /dev/null +++ b/cli/src/test/resources/hudson/cli/openssh-multiple-keys @@ -0,0 +1,35 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB7+Wg6qP +jwYDqZ6ghEjcxsAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDDQX8IscJ6 +Axj5nni6lv4uh6w+CyNfsItKdLBj2KaohA7fcgpL2DrjcYo0Z9W74jbVRSW9mcCp/6Kdfl +JumpnUjpx7QBlUcnKIakpFuIHJl8HcHDLusy/R1RB1H/ShXqkHfPT3JmSbo1iwrGS4UFSq +S/KZsfKNph4x/vbyizUlPQAAAiAhHAwqGb+KrmywoeqT/QkWflUH/aRy7iZM9rYx7ROh2K +FY143YePB66yCczropqQPFn4hgf2wxSEsvMLKnBy44ruUl7w8O/mmsO993DkXmtVTHdipz +vWHZLtSFe2IB1IFAoGGcOeGFIBKQ6DfIVWPaPRFF+jmpVpn19qYpkxmp6uBq8guViXmoTV +eM/r46ipHYQ57BVopYnUQrxa13p7PZQRmrfNapfAgJpvvJxHjO9RFUeJndWNKVbCXblc24 +TTQ5EUxlLrTsRhH5ICdTSvPnm50I8yjiIZVOXNkPn8UOrj2yVaU2LDkFnbzB4EJIEtdmVb +iavgaTO/TURIS5b7oa21rVnYVacUmhZyBRgo/abu49ovvTyyNGk+MIgtmgbq8NZunBP/Te +HpaeTgZm9uMOFy7ni/S9raMYzKun8dCoNaEES/WIFBdAtw3SY2eLXYVRVKI1dk2q3swhiL +t+M81BfSzCrBzqENyrRSvbMIV0fI6Kvc8Kq5aNIPw5JIFTNYc0c8JWyxf72Is4PffyCrK7 +7qGrXiU/fys1j+LCQUg7UOLaMnYetY+JnN7Z284J59YsvFnyjoZnCJeS6Ewy6s8alLDi3k +da3VASzohO4j1mD1HWVYG/eEWMxcX5TkyxaMcXkpFkR/lEXZXMr0y+1mgICefspMsi+OSf +1xrbdd5CNbELWRD88BOuIKFhdThx9C2A65AKGpCt7UkFfNB2pCm6 +-----END OPENSSH PRIVATE KEY----- + +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB7+Wg6qP +jwYDqZ6ghEjcxsAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDDQX8IscJ6 +Axj5nni6lv4uh6w+CyNfsItKdLBj2KaohA7fcgpL2DrjcYo0Z9W74jbVRSW9mcCp/6Kdfl +JumpnUjpx7QBlUcnKIakpFuIHJl8HcHDLusy/R1RB1H/ShXqkHfPT3JmSbo1iwrGS4UFSq +S/KZsfKNph4x/vbyizUlPQAAAiAhHAwqGb+KrmywoeqT/QkWflUH/aRy7iZM9rYx7ROh2K +FY143YePB66yCczropqQPFn4hgf2wxSEsvMLKnBy44ruUl7w8O/mmsO993DkXmtVTHdipz +vWHZLtSFe2IB1IFAoGGcOeGFIBKQ6DfIVWPaPRFF+jmpVpn19qYpkxmp6uBq8guViXmoTV +eM/r46ipHYQ57BVopYnUQrxa13p7PZQRmrfNapfAgJpvvJxHjO9RFUeJndWNKVbCXblc24 +TTQ5EUxlLrTsRhH5ICdTSvPnm50I8yjiIZVOXNkPn8UOrj2yVaU2LDkFnbzB4EJIEtdmVb +iavgaTO/TURIS5b7oa21rVnYVacUmhZyBRgo/abu49ovvTyyNGk+MIgtmgbq8NZunBP/Te +HpaeTgZm9uMOFy7ni/S9raMYzKun8dCoNaEES/WIFBdAtw3SY2eLXYVRVKI1dk2q3swhiL +t+M81BfSzCrBzqENyrRSvbMIV0fI6Kvc8Kq5aNIPw5JIFTNYc0c8JWyxf72Is4PffyCrK7 +7qGrXiU/fys1j+LCQUg7UOLaMnYetY+JnN7Z284J59YsvFnyjoZnCJeS6Ewy6s8alLDi3k +da3VASzohO4j1mD1HWVYG/eEWMxcX5TkyxaMcXkpFkR/lEXZXMr0y+1mgICefspMsi+OSf +1xrbdd5CNbELWRD88BOuIKFhdThx9C2A65AKGpCt7UkFfNB2pCm6 +-----END OPENSSH PRIVATE KEY----- diff --git a/cli/src/test/resources/hudson/cli/openssh-pkcs8 b/cli/src/test/resources/hudson/cli/openssh-pkcs8 new file mode 100644 index 000000000000..9c17399c3b2e --- /dev/null +++ b/cli/src/test/resources/hudson/cli/openssh-pkcs8 @@ -0,0 +1,17 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDvGXdAqe +A3cfETZNuKc2qEAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDNj316M4aw +DJHITn0XzcGapC6+vkXOLSwD/hK8qC6cp/FPEPrOo20jxRiTrd00/M6SbfeJR+wUyZl4V5 +mz8RPKGjVFtktZ5jQJZ3QY4Jqtpc5iMxQfMXmcV0UBJaom8zc7vHSdsH2XrM+xt9Tvrob3 +wQIMjLbwj7cjcHh/1b7iywAAAiDP15QQ8FKnRgbnbRgwuOoEpAqMEt0z7l4CJE6WAQ8hCU +YyvDFs6c9LPftxa0BlS/INKC3hblqs35X24iU8XzKWTZL3ac99/AfC4Mru9NhpOme1Xdi6 +ZWpjbakqyGHeBX9ERnxcGb/hlKsWErdsMttKFgOm5WvnlOb/Rywt74zIJdq6/LTWvwjgQi +mF5yZSsJuZiFaq9fASul1gLFikhdxVPGHtI+pzDCviC2UkPdI8jVnqBEzDl7ewjZdcHykX +hZW+LxbxjKRxrFPSn8prxPqRwAbM4bWoeyh0Y1F+DUaWS9LQjMyG2eHM5RCJdjb8V3NNpH +vOFD213akcrA7X6lQFlbI5wbVgfMQ6Zo4EGlSA8f9U9fMuBhL24Opbb1d7PFaJLUnw/mJl +BlqHS2LMaTz5k/dhwVKZfaDLq6Q1RJ/0toJN6LtlQjz5DU7tmUwNmt5/CYtkjMHUQWffk9 +WQ7hPSmKiO2m07zfmwuE2Hdihbb5o2imDuBbTz129Dr5OyqhMcmAxg4GAIZBCjdlUItaAP +y9ieAVgG4gPYn1tYYa8259Gjug+v8rWzvjdRuUW21gv+quQ+yx1Q1/dErxP8m6VU6pdE7b +3TgQH+sxdXZpOksYLpuDBZ6KNdkDtQjWCCfkDCXm/4Pr5ljyu5n56YDBYyzbxq+Amsc02S +iC8i6JQjGsnvJzuGMbmrr1qE99vbRnwWJAeZsjh3U4ResfZ5mAgs +-----END OPENSSH PRIVATE KEY----- diff --git a/cli/src/test/resources/hudson/cli/openssh-rfc4716 b/cli/src/test/resources/hudson/cli/openssh-rfc4716 new file mode 100644 index 000000000000..af0075e9cc5b --- /dev/null +++ b/cli/src/test/resources/hudson/cli/openssh-rfc4716 @@ -0,0 +1,17 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB7+Wg6qP +jwYDqZ6ghEjcxsAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDDQX8IscJ6 +Axj5nni6lv4uh6w+CyNfsItKdLBj2KaohA7fcgpL2DrjcYo0Z9W74jbVRSW9mcCp/6Kdfl +JumpnUjpx7QBlUcnKIakpFuIHJl8HcHDLusy/R1RB1H/ShXqkHfPT3JmSbo1iwrGS4UFSq +S/KZsfKNph4x/vbyizUlPQAAAiAhHAwqGb+KrmywoeqT/QkWflUH/aRy7iZM9rYx7ROh2K +FY143YePB66yCczropqQPFn4hgf2wxSEsvMLKnBy44ruUl7w8O/mmsO993DkXmtVTHdipz +vWHZLtSFe2IB1IFAoGGcOeGFIBKQ6DfIVWPaPRFF+jmpVpn19qYpkxmp6uBq8guViXmoTV +eM/r46ipHYQ57BVopYnUQrxa13p7PZQRmrfNapfAgJpvvJxHjO9RFUeJndWNKVbCXblc24 +TTQ5EUxlLrTsRhH5ICdTSvPnm50I8yjiIZVOXNkPn8UOrj2yVaU2LDkFnbzB4EJIEtdmVb +iavgaTO/TURIS5b7oa21rVnYVacUmhZyBRgo/abu49ovvTyyNGk+MIgtmgbq8NZunBP/Te +HpaeTgZm9uMOFy7ni/S9raMYzKun8dCoNaEES/WIFBdAtw3SY2eLXYVRVKI1dk2q3swhiL +t+M81BfSzCrBzqENyrRSvbMIV0fI6Kvc8Kq5aNIPw5JIFTNYc0c8JWyxf72Is4PffyCrK7 +7qGrXiU/fys1j+LCQUg7UOLaMnYetY+JnN7Z284J59YsvFnyjoZnCJeS6Ewy6s8alLDi3k +da3VASzohO4j1mD1HWVYG/eEWMxcX5TkyxaMcXkpFkR/lEXZXMr0y+1mgICefspMsi+OSf +1xrbdd5CNbELWRD88BOuIKFhdThx9C2A65AKGpCt7UkFfNB2pCm6 +-----END OPENSSH PRIVATE KEY----- diff --git a/cli/src/test/resources/hudson/cli/openssh-unsuported b/cli/src/test/resources/hudson/cli/openssh-unsuported deleted file mode 100644 index 4ed6878f12c8..000000000000 --- a/cli/src/test/resources/hudson/cli/openssh-unsuported +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDIzkiSdr -mRRbRY1S2YtBacAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQCpXxUyU7MR -b4GrSMnufZb6kaBb1lHBywI7+dBNnpHyq1rpZJRi36lpxxZoaiG+inOeSBh7QPnDVvm2aN -DdT7V0PFzfZKWzxl2PRSd6EIXUsaaXuqaFcJM7rSqU1EB+9qM9JfGIqkdNKwzGdu3kdJJG -3VQQUQVtYXAOLIrApslndQAAAiDAF+/lDARNPSMcOlH6uGqfSBszQBwOf22df5yGHLbnpi -e5yslN+9Z3jFrl2XNDb8sD9e7gZtB/CbkJaDqFCqSOoW979xLLl89jJYle2L48SBbpV7i2 -0/51YYrxs4/75kJUd8uMaOBpNanyI8CBqA5IPmms1NLrSOpAbU20imQNoLUb1B8v2zNBxo -R64UyU8AkKDMwPmAHwdrM73c7eirAsuVknhg0fFjy4iCxurqz5RO0Hpjf8GHfaCh37gim/ -8f/XqwS+MlAn9KaAGi4hZJFaSuyPPVLmRTS+gleoM0zSt5J+Fvdrs/JnL/XIpf64QZafKZ -HyiZXnbJKxWhhhpslHz6QoiZ76LxwRS6bP//fsl7KWPY6IUGMD8h6JGi8o6xpsj16xIGUf -7K+c9TNcjzaO8jtC8ggaixoKdC48LdenfdaagAtBgyWQqxfxTg9ZLiQ2lrZIaF4C0aZi3+ -byeT/mzPyh6aSAsBETjHCbdy/ixi0BNbDB10LlD44J8i9yBROk7WQtM3lJL78Va4KfxSCC -dsJQPu1ABZEr1SGVqVprUaM43C/VKZk5PjXmkbAy5TCztztiWwa8HtKk4V7sH4G/ENjAtJ -w2SEybRTx0WNhD9viTSu8z+BqH1mWP2ek/orE0OWU+H6r1zSoBo9scvpUrLC2NYvcUMw+I -cDupua/5kKQgTzY+kEyRClwvziHEVe4TLZen3UMf2GM3fVC9AUC8 ------END OPENSSH PRIVATE KEY-----