mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 23:30:55 +03:00
Add extra logging in OpenSSHKnownHosts and extra test
This commit is contained in:
@@ -85,7 +85,7 @@ class ECDSAVariationsAdapter {
|
|||||||
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
|
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
|
||||||
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
|
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
|
||||||
ECPoint p = new ECPoint(bigX, bigY);
|
ECPoint p = new ECPoint(bigX, bigY);
|
||||||
ECPublicKeySpec publicKeySpec = new java.security.spec.ECPublicKeySpec(p, ecCurveSpec);
|
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(p, ecCurveSpec);
|
||||||
|
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
||||||
return keyFactory.generatePublic(publicKeySpec);
|
return keyFactory.generatePublic(publicKeySpec);
|
||||||
|
|||||||
@@ -197,6 +197,12 @@ final class KeyExchanger
|
|||||||
if (hkv.verify(transport.getRemoteHost(), transport.getRemotePort(), key))
|
if (hkv.verify(transport.getRemoteHost(), transport.getRemotePort(), key))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
log.error("Disconnecting because none of the configured Host key verifiers ({}) could verify '{}' host key with fingerprint {} for {}:{}",
|
||||||
|
hostVerifiers,
|
||||||
|
KeyType.fromKey(key),
|
||||||
|
SecurityUtils.getFingerprint(key),
|
||||||
|
transport.getRemoteHost(),
|
||||||
|
transport.getRemotePort());
|
||||||
|
|
||||||
throw new TransportException(DisconnectReason.HOST_KEY_NOT_VERIFIABLE,
|
throw new TransportException(DisconnectReason.HOST_KEY_NOT_VERIFIABLE,
|
||||||
"Could not verify `" + KeyType.fromKey(key)
|
"Could not verify `" + KeyType.fromKey(key)
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ public class OpenSSHKnownHosts
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean verify(PublicKey key) throws IOException {
|
public boolean verify(PublicKey key) throws IOException {
|
||||||
return key.equals(this.key) && marker != Marker.REVOKED;
|
return getKeyString(key).equals(getKeyString(this.key)) && marker != Marker.REVOKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLine() {
|
public String getLine() {
|
||||||
@@ -350,12 +350,12 @@ public class OpenSSHKnownHosts
|
|||||||
|
|
||||||
line.append(getHostPart());
|
line.append(getHostPart());
|
||||||
line.append(" ").append(type.toString());
|
line.append(" ").append(type.toString());
|
||||||
line.append(" ").append(getKeyString());
|
line.append(" ").append(getKeyString(key));
|
||||||
return line.toString();
|
return line.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKeyString() {
|
private String getKeyString(PublicKey pk) {
|
||||||
final Buffer.PlainBuffer buf = new Buffer.PlainBuffer().putPublicKey(key);
|
final Buffer.PlainBuffer buf = new Buffer.PlainBuffer().putPublicKey(pk);
|
||||||
return Base64.encodeBytes(buf.array(), buf.rpos(), buf.available());
|
return Base64.encodeBytes(buf.array(), buf.rpos(), buf.available());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C)2009 - SSHJ Contributors
|
||||||
|
*
|
||||||
|
* Licensed 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 com.hierynomus.sshj.transport.verification
|
||||||
|
|
||||||
|
import net.schmizz.sshj.common.KeyType
|
||||||
|
import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts
|
||||||
|
import net.schmizz.sshj.util.KeyUtil
|
||||||
|
import org.junit.Ignore
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.Unroll
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException
|
||||||
|
import java.security.PublicKey
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat
|
||||||
|
|
||||||
|
class OpenSSHKnownHostsSpec extends Specification {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TemporaryFolder temp = new TemporaryFolder();
|
||||||
|
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "should add comment lines"() {
|
||||||
|
given:
|
||||||
|
def file = writeKnownHosts(contents)
|
||||||
|
|
||||||
|
when:
|
||||||
|
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(file)
|
||||||
|
|
||||||
|
then:
|
||||||
|
openSSHKnownHosts.entries().size() == 1
|
||||||
|
openSSHKnownHosts.entries()[0] instanceof OpenSSHKnownHosts.CommentEntry
|
||||||
|
|
||||||
|
where:
|
||||||
|
contents << ["", "# this is a comment"]
|
||||||
|
}
|
||||||
|
|
||||||
|
def "should parse and verify plain host entry with RSA key"() {
|
||||||
|
given:
|
||||||
|
def f = writeKnownHosts("schmizz.net,69.163.155.180 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6P9Hlwdahh250jGZYKg2snRq2j2lFJVdKSHyxqbJiVy9VX9gTkN3K2MD48qyrYLYOyGs3vTttyUk+cK++JMzURWsrP4piby7LpeOT+3Iq8CQNj4gXZdcH9w15Vuk2qS11at6IsQPVHpKD9HGg9//EFUccI/4w06k4XXLm/IxOGUwj6I2AeWmEOL3aDi+fe07TTosSdLUD6INtR0cyKsg0zC7Da24ixoShT8Oy3x2MpR7CY3PQ1pUVmvPkr79VeA+4qV9F1JM09WdboAMZgWQZ+XrbtuBlGsyhpUHSCQOya+kOJ+bYryS+U7A+6nmTW3C9FX4FgFqTF89UHOC7V0zZQ==")
|
||||||
|
final PublicKey key = KeyUtil
|
||||||
|
.newRSAPublicKey(
|
||||||
|
"e8ff4797075a861db9d2319960a836b2746ada3da514955d2921f2c6a6c9895cbd557f604e43772b6303e3cab2ad82d83b21acdef4edb72524f9c2bef893335115acacfe2989bcbb2e978e4fedc8abc090363e205d975c1fdc35e55ba4daa4b5d5ab7a22c40f547a4a0fd1c683dfff10551c708ff8c34ea4e175cb9bf2313865308fa23601e5a610e2f76838be7ded3b4d3a2c49d2d40fa20db51d1cc8ab20d330bb0dadb88b1a12853f0ecb7c7632947b098dcf435a54566bcf92befd55e03ee2a57d17524cd3d59d6e800c66059067e5eb6edb81946b3286950748240ec9afa4389f9b62bc92f94ec0fba9e64d6dc2f455f816016a4c5f3d507382ed5d3365",
|
||||||
|
"23");
|
||||||
|
|
||||||
|
when:
|
||||||
|
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(f)
|
||||||
|
|
||||||
|
then:
|
||||||
|
openSSHKnownHosts.verify("schmizz.net", 22, key)
|
||||||
|
openSSHKnownHosts.verify("69.163.155.180", 22, key)
|
||||||
|
!openSSHKnownHosts.verify("69.163.155.18", 22, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
def "should parse and verify hashed host entry"() {
|
||||||
|
given:
|
||||||
|
def f = writeKnownHosts("|1|F1E1KeoE/eEWhi10WpGv4OdiO6Y=|3988QV0VE8wmZL7suNrYQLITLCg= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6P9Hlwdahh250jGZYKg2snRq2j2lFJVdKSHyxqbJiVy9VX9gTkN3K2MD48qyrYLYOyGs3vTttyUk+cK++JMzURWsrP4piby7LpeOT+3Iq8CQNj4gXZdcH9w15Vuk2qS11at6IsQPVHpKD9HGg9//EFUccI/4w06k4XXLm/IxOGUwj6I2AeWmEOL3aDi+fe07TTosSdLUD6INtR0cyKsg0zC7Da24ixoShT8Oy3x2MpR7CY3PQ1pUVmvPkr79VeA+4qV9F1JM09WdboAMZgWQZ+XrbtuBlGsyhpUHSCQOya+kOJ+bYryS+U7A+6nmTW3C9FX4FgFqTF89UHOC7V0zZQ==");
|
||||||
|
final PublicKey key = KeyUtil
|
||||||
|
.newRSAPublicKey(
|
||||||
|
"e8ff4797075a861db9d2319960a836b2746ada3da514955d2921f2c6a6c9895cbd557f604e43772b6303e3cab2ad82d83b21acdef4edb72524f9c2bef893335115acacfe2989bcbb2e978e4fedc8abc090363e205d975c1fdc35e55ba4daa4b5d5ab7a22c40f547a4a0fd1c683dfff10551c708ff8c34ea4e175cb9bf2313865308fa23601e5a610e2f76838be7ded3b4d3a2c49d2d40fa20db51d1cc8ab20d330bb0dadb88b1a12853f0ecb7c7632947b098dcf435a54566bcf92befd55e03ee2a57d17524cd3d59d6e800c66059067e5eb6edb81946b3286950748240ec9afa4389f9b62bc92f94ec0fba9e64d6dc2f455f816016a4c5f3d507382ed5d3365",
|
||||||
|
"23");
|
||||||
|
|
||||||
|
when:
|
||||||
|
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(f)
|
||||||
|
|
||||||
|
then:
|
||||||
|
openSSHKnownHosts.verify("192.168.1.61", 22, key)
|
||||||
|
!openSSHKnownHosts.verify("192.168.1.2", 22, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
def "should parse and verify v1 host entry"() {
|
||||||
|
given:
|
||||||
|
def f = writeKnownHosts("test.com,1.1.1.1 2048 35 22017496617994656680820635966392838863613340434802393112245951008866692373218840197754553998457793202561151141246686162285550121243768846314646395880632789308110750881198697743542374668273149584280424505890648953477691795864456749782348425425954366277600319096366690719901119774784695056100331902394094537054256611668966698242432417382422091372756244612839068092471592121759862971414741954991375710930168229171638843329213652899594987626853020377726482288618521941129157643483558764875338089684351824791983007780922947554898825663693324944982594850256042689880090306493029526546183035567296830604572253312294059766327")
|
||||||
|
def key = KeyUtil.newRSAPublicKey("ae6983ed63a33afc69fe0b88b4ba14393120a0b66e1460916a8390ff109139cd14f4e1701ab5c5feeb479441fe2091d04c0ba7d3fa1756b80ed103657ab53b5d7daa38af22f59f9cbfc16892d4ef1f8fd3ae49663c295be1f568a160d54328fbc2c0598f48d32296b1b9942336234952c440cda1bfac904e3391db98e52f9b1de229adc18fc34a9a569717aa9a5b1145e73b8a8394354028d02054ca760243fb8fc1575490607dd098e698e02b5d8bdf22d55ec958245222ef4c65b8836b9f13674a2d2895a587bfd4423b4eeb6d3ef98451640e3d63d2fc6a761ffd34446abab028494caf36d67ffd65298d69f19f2d90bae4c207b671db563a08f1bb9bf237",
|
||||||
|
"23")
|
||||||
|
when:
|
||||||
|
OpenSSHKnownHosts knownHosts = new OpenSSHKnownHosts(f)
|
||||||
|
|
||||||
|
then:
|
||||||
|
knownHosts.verify("test.com", 22, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
def "should ignore malformed line"() {
|
||||||
|
given:
|
||||||
|
def f = writeKnownHosts("M36Lo+Ik5ukNugvvoNFlpnyiHMmtKxt3FpyEfYuryXjNqMNWHn/ARVnpUIl5jRLTB7WBzyLYMG7X5nuoFL9zYqKGtHxChbDunxMVbspw5WXI9VN+qxcLwmITmpEvI9ApyS/Ox2ZyN7zw==")
|
||||||
|
|
||||||
|
when:
|
||||||
|
OpenSSHKnownHosts knownHosts = new OpenSSHKnownHosts(f)
|
||||||
|
|
||||||
|
then:
|
||||||
|
knownHosts.entries().size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
File writeKnownHosts(String line)
|
||||||
|
throws IOException {
|
||||||
|
File known_hosts = temp.newFile("known_hosts");
|
||||||
|
FileWriter fileWriter = new FileWriter(known_hosts);
|
||||||
|
BufferedWriter writer = new BufferedWriter(fileWriter);
|
||||||
|
writer.write(line);
|
||||||
|
writer.write("\r\n");
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
return known_hosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C)2009 - SSHJ Contributors
|
|
||||||
*
|
|
||||||
* Licensed 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 net.schmizz.sshj.transport.verification;
|
|
||||||
|
|
||||||
import net.schmizz.sshj.util.KeyUtil;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.rules.TemporaryFolder;
|
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.PublicKey;
|
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
public class OpenSSHKnownHostsTest {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public TemporaryFolder temp = new TemporaryFolder();
|
|
||||||
|
|
||||||
public File writeKnownHosts(String line)
|
|
||||||
throws IOException {
|
|
||||||
File known_hosts = temp.newFile("known_hosts");
|
|
||||||
FileWriter fileWriter = new FileWriter(known_hosts);
|
|
||||||
BufferedWriter writer = new BufferedWriter(fileWriter);
|
|
||||||
writer.write(line);
|
|
||||||
writer.write("\r\n");
|
|
||||||
writer.flush();
|
|
||||||
writer.close();
|
|
||||||
return known_hosts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shouldAddCommentForEmptyLine()
|
|
||||||
throws IOException {
|
|
||||||
File file = writeKnownHosts("");
|
|
||||||
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(file);
|
|
||||||
assertThat(openSSHKnownHosts.entries().size(), equalTo(1));
|
|
||||||
assertThat(openSSHKnownHosts.entries().get(0), instanceOf(OpenSSHKnownHosts.CommentEntry.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shouldAddCommentForCommentLine()
|
|
||||||
throws IOException {
|
|
||||||
File file = writeKnownHosts("# this is a comment");
|
|
||||||
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(file);
|
|
||||||
assertThat(openSSHKnownHosts.entries().size(), equalTo(1));
|
|
||||||
assertThat(openSSHKnownHosts.entries().get(0), instanceOf(OpenSSHKnownHosts.CommentEntry.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSchmizzEntry()
|
|
||||||
throws IOException, GeneralSecurityException {
|
|
||||||
OpenSSHKnownHosts kh = new OpenSSHKnownHosts(new File("src/test/resources/known_hosts"));
|
|
||||||
final PublicKey key = KeyUtil
|
|
||||||
.newRSAPublicKey(
|
|
||||||
"e8ff4797075a861db9d2319960a836b2746ada3da514955d2921f2c6a6c9895cbd557f604e43772b6303e3cab2ad82d83b21acdef4edb72524f9c2bef893335115acacfe2989bcbb2e978e4fedc8abc090363e205d975c1fdc35e55ba4daa4b5d5ab7a22c40f547a4a0fd1c683dfff10551c708ff8c34ea4e175cb9bf2313865308fa23601e5a610e2f76838be7ded3b4d3a2c49d2d40fa20db51d1cc8ab20d330bb0dadb88b1a12853f0ecb7c7632947b098dcf435a54566bcf92befd55e03ee2a57d17524cd3d59d6e800c66059067e5eb6edb81946b3286950748240ec9afa4389f9b62bc92f94ec0fba9e64d6dc2f455f816016a4c5f3d507382ed5d3365",
|
|
||||||
"23");
|
|
||||||
|
|
||||||
assertTrue(kh.verify("schmizz.net", 22, key));
|
|
||||||
assertTrue(kh.verify("69.163.155.180", 22, key));
|
|
||||||
assertFalse(kh.verify("69.163.155.18", 22, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testVerifyIndexError() throws Exception {
|
|
||||||
final OpenSSHKnownHosts v = new OpenSSHKnownHosts(new File("src/test/resources/known_hosts.invalid"));
|
|
||||||
assertTrue(v.entries().isEmpty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
schmizz.net,69.163.155.180 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6P9Hlwdahh250jGZYKg2snRq2j2lFJVdKSHyxqbJiVy9VX9gTkN3K2MD48qyrYLYOyGs3vTttyUk+cK++JMzURWsrP4piby7LpeOT+3Iq8CQNj4gXZdcH9w15Vuk2qS11at6IsQPVHpKD9HGg9//EFUccI/4w06k4XXLm/IxOGUwj6I2AeWmEOL3aDi+fe07TTosSdLUD6INtR0cyKsg0zC7Da24ixoShT8Oy3x2MpR7CY3PQ1pUVmvPkr79VeA+4qV9F1JM09WdboAMZgWQZ+XrbtuBlGsyhpUHSCQOya+kOJ+bYryS+U7A+6nmTW3C9FX4FgFqTF89UHOC7V0zZQ==
|
|
||||||
# Above we have a plain line, Below we have a hashed line, Last is a v1 line, This is a garbage line.
|
|
||||||
|1|dy7xSefq6NmJms6AzANG3w45W28=|SSCTlHs4pZbc2uaRoPvjyEAHE1g= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAu64GJcCkdtckPGt8uKTyhG1ShT1Np1kh10eE49imQ4Nh9Y/IrSPzDtYUAazQ88ABc2NffuOKkdn2qtUwZ1ulfcdNfN3oTim3BiVHqa041pKG0L+onQe8Bo+CaG5KBLy/C24eNGM9EcfQvDQOnq1eD3lnR/l8fFckldzjfxZgar0yT9Bb3pwp50oN+1wSEINJEHOgMIW8kZBQmyNr/B+b7yX+Y1s1vuYIP/i4WimCVmkdi9G87Ga8w7GxKalRD2QOG6Xms2YWRQDN6M/MOn4tda3EKolbWkctEWcQf/PcVJffTH4Wv5f0RjVyrQv4ha4FZcNAv6RkRd9WkiCsiTKioQ==
|
|
||||||
test.com,1.1.1.1 2048 35 22017496617994656680820635966392838863613340434802393112245951008866692373218840197754553998457793202561151141246686162285550121243768846314646395880632789308110750881198697743542374668273149584280424505890648953477691795864456749782348425425954366277600319096366690719901119774784695056100331902394094537054256611668966698242432417382422091372756244612839068092471592121759862971414741954991375710930168229171638843329213652899594987626853020377726482288618521941129157643483558764875338089684351824791983007780922947554898825663693324944982594850256042689880090306493029526546183035567296830604572253312294059766327
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
M36Lo+Ik5ukNugvvoNFlpnyiHMmtKxt3FpyEfYuryXjNqMNWHn/ARVnpUIl5jRLTB7WBzyLYMG7X5nuoFL9zYqKGtHxChbDunxMVbspw5WXI9VN+qxcLwmITmpEvI9ApyS/Ox2ZyN7zw==
|
|
||||||
Reference in New Issue
Block a user