Skip to content

Commit 265e9d2

Browse files
committed
Add extra logging in OpenSSHKnownHosts and extra test
1 parent 0b65526 commit 265e9d2

File tree

8 files changed

+137
-98
lines changed

8 files changed

+137
-98
lines changed

src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static PublicKey readPubKeyFromBuffer(Buffer<?> buf, String variation) throws Ge
8585
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
8686
ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
8787
ECPoint p = new ECPoint(bigX, bigY);
88-
ECPublicKeySpec publicKeySpec = new java.security.spec.ECPublicKeySpec(p, ecCurveSpec);
88+
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(p, ecCurveSpec);
8989

9090
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
9191
return keyFactory.generatePublic(publicKeySpec);

src/main/java/net/schmizz/sshj/transport/KeyExchanger.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ private synchronized void verifyHost(PublicKey key)
197197
if (hkv.verify(transport.getRemoteHost(), transport.getRemotePort(), key))
198198
return;
199199
}
200+
log.error("Disconnecting because none of the configured Host key verifiers ({}) could verify '{}' host key with fingerprint {} for {}:{}",
201+
hostVerifiers,
202+
KeyType.fromKey(key),
203+
SecurityUtils.getFingerprint(key),
204+
transport.getRemoteHost(),
205+
transport.getRemotePort());
200206

201207
throw new TransportException(DisconnectReason.HOST_KEY_NOT_VERIFIABLE,
202208
"Could not verify `" + KeyType.fromKey(key)

src/main/java/net/schmizz/sshj/transport/verification/OpenSSHKnownHosts.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public boolean appliesTo(KeyType type, String host) throws IOException {
340340

341341
@Override
342342
public boolean verify(PublicKey key) throws IOException {
343-
return key.equals(this.key) && marker != Marker.REVOKED;
343+
return getKeyString(key).equals(getKeyString(this.key)) && marker != Marker.REVOKED;
344344
}
345345

346346
public String getLine() {
@@ -350,12 +350,12 @@ public String getLine() {
350350

351351
line.append(getHostPart());
352352
line.append(" ").append(type.toString());
353-
line.append(" ").append(getKeyString());
353+
line.append(" ").append(getKeyString(key));
354354
return line.toString();
355355
}
356356

357-
private String getKeyString() {
358-
final Buffer.PlainBuffer buf = new Buffer.PlainBuffer().putPublicKey(key);
357+
private String getKeyString(PublicKey pk) {
358+
final Buffer.PlainBuffer buf = new Buffer.PlainBuffer().putPublicKey(pk);
359359
return Base64.encodeBytes(buf.array(), buf.rpos(), buf.available());
360360
}
361361

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright (C)2009 - SSHJ Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.hierynomus.sshj.transport.verification
17+
18+
import net.schmizz.sshj.common.KeyType
19+
import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts
20+
import net.schmizz.sshj.util.KeyUtil
21+
import org.junit.Ignore
22+
import org.junit.Rule
23+
import org.junit.Test
24+
import org.junit.rules.TemporaryFolder
25+
import spock.lang.Specification
26+
import spock.lang.Unroll
27+
28+
import java.security.GeneralSecurityException
29+
import java.security.PublicKey
30+
31+
import static org.hamcrest.CoreMatchers.equalTo
32+
import static org.hamcrest.CoreMatchers.instanceOf
33+
import static org.hamcrest.MatcherAssert.assertThat
34+
35+
class OpenSSHKnownHostsSpec extends Specification {
36+
37+
@Rule
38+
public TemporaryFolder temp = new TemporaryFolder();
39+
40+
41+
@Unroll
42+
def "should add comment lines"() {
43+
given:
44+
def file = writeKnownHosts(contents)
45+
46+
when:
47+
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(file)
48+
49+
then:
50+
openSSHKnownHosts.entries().size() == 1
51+
openSSHKnownHosts.entries()[0] instanceof OpenSSHKnownHosts.CommentEntry
52+
53+
where:
54+
contents << ["", "# this is a comment"]
55+
}
56+
57+
def "should parse and verify plain host entry with RSA key"() {
58+
given:
59+
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==")
60+
final PublicKey key = KeyUtil
61+
.newRSAPublicKey(
62+
"e8ff4797075a861db9d2319960a836b2746ada3da514955d2921f2c6a6c9895cbd557f604e43772b6303e3cab2ad82d83b21acdef4edb72524f9c2bef893335115acacfe2989bcbb2e978e4fedc8abc090363e205d975c1fdc35e55ba4daa4b5d5ab7a22c40f547a4a0fd1c683dfff10551c708ff8c34ea4e175cb9bf2313865308fa23601e5a610e2f76838be7ded3b4d3a2c49d2d40fa20db51d1cc8ab20d330bb0dadb88b1a12853f0ecb7c7632947b098dcf435a54566bcf92befd55e03ee2a57d17524cd3d59d6e800c66059067e5eb6edb81946b3286950748240ec9afa4389f9b62bc92f94ec0fba9e64d6dc2f455f816016a4c5f3d507382ed5d3365",
63+
"23");
64+
65+
when:
66+
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(f)
67+
68+
then:
69+
openSSHKnownHosts.verify("schmizz.net", 22, key)
70+
openSSHKnownHosts.verify("69.163.155.180", 22, key)
71+
!openSSHKnownHosts.verify("69.163.155.18", 22, key)
72+
}
73+
74+
def "should parse and verify hashed host entry"() {
75+
given:
76+
def f = writeKnownHosts("|1|F1E1KeoE/eEWhi10WpGv4OdiO6Y=|3988QV0VE8wmZL7suNrYQLITLCg= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6P9Hlwdahh250jGZYKg2snRq2j2lFJVdKSHyxqbJiVy9VX9gTkN3K2MD48qyrYLYOyGs3vTttyUk+cK++JMzURWsrP4piby7LpeOT+3Iq8CQNj4gXZdcH9w15Vuk2qS11at6IsQPVHpKD9HGg9//EFUccI/4w06k4XXLm/IxOGUwj6I2AeWmEOL3aDi+fe07TTosSdLUD6INtR0cyKsg0zC7Da24ixoShT8Oy3x2MpR7CY3PQ1pUVmvPkr79VeA+4qV9F1JM09WdboAMZgWQZ+XrbtuBlGsyhpUHSCQOya+kOJ+bYryS+U7A+6nmTW3C9FX4FgFqTF89UHOC7V0zZQ==");
77+
final PublicKey key = KeyUtil
78+
.newRSAPublicKey(
79+
"e8ff4797075a861db9d2319960a836b2746ada3da514955d2921f2c6a6c9895cbd557f604e43772b6303e3cab2ad82d83b21acdef4edb72524f9c2bef893335115acacfe2989bcbb2e978e4fedc8abc090363e205d975c1fdc35e55ba4daa4b5d5ab7a22c40f547a4a0fd1c683dfff10551c708ff8c34ea4e175cb9bf2313865308fa23601e5a610e2f76838be7ded3b4d3a2c49d2d40fa20db51d1cc8ab20d330bb0dadb88b1a12853f0ecb7c7632947b098dcf435a54566bcf92befd55e03ee2a57d17524cd3d59d6e800c66059067e5eb6edb81946b3286950748240ec9afa4389f9b62bc92f94ec0fba9e64d6dc2f455f816016a4c5f3d507382ed5d3365",
80+
"23");
81+
82+
when:
83+
OpenSSHKnownHosts openSSHKnownHosts = new OpenSSHKnownHosts(f)
84+
85+
then:
86+
openSSHKnownHosts.verify("192.168.1.61", 22, key)
87+
!openSSHKnownHosts.verify("192.168.1.2", 22, key)
88+
}
89+
90+
def "should parse and verify v1 host entry"() {
91+
given:
92+
def f = writeKnownHosts("test.com,1.1.1.1 2048 35 22017496617994656680820635966392838863613340434802393112245951008866692373218840197754553998457793202561151141246686162285550121243768846314646395880632789308110750881198697743542374668273149584280424505890648953477691795864456749782348425425954366277600319096366690719901119774784695056100331902394094537054256611668966698242432417382422091372756244612839068092471592121759862971414741954991375710930168229171638843329213652899594987626853020377726482288618521941129157643483558764875338089684351824791983007780922947554898825663693324944982594850256042689880090306493029526546183035567296830604572253312294059766327")
93+
def key = KeyUtil.newRSAPublicKey("ae6983ed63a33afc69fe0b88b4ba14393120a0b66e1460916a8390ff109139cd14f4e1701ab5c5feeb479441fe2091d04c0ba7d3fa1756b80ed103657ab53b5d7daa38af22f59f9cbfc16892d4ef1f8fd3ae49663c295be1f568a160d54328fbc2c0598f48d32296b1b9942336234952c440cda1bfac904e3391db98e52f9b1de229adc18fc34a9a569717aa9a5b1145e73b8a8394354028d02054ca760243fb8fc1575490607dd098e698e02b5d8bdf22d55ec958245222ef4c65b8836b9f13674a2d2895a587bfd4423b4eeb6d3ef98451640e3d63d2fc6a761ffd34446abab028494caf36d67ffd65298d69f19f2d90bae4c207b671db563a08f1bb9bf237",
94+
"23")
95+
when:
96+
OpenSSHKnownHosts knownHosts = new OpenSSHKnownHosts(f)
97+
98+
then:
99+
knownHosts.verify("test.com", 22, key)
100+
}
101+
102+
def "should ignore malformed line"() {
103+
given:
104+
def f = writeKnownHosts("M36Lo+Ik5ukNugvvoNFlpnyiHMmtKxt3FpyEfYuryXjNqMNWHn/ARVnpUIl5jRLTB7WBzyLYMG7X5nuoFL9zYqKGtHxChbDunxMVbspw5WXI9VN+qxcLwmITmpEvI9ApyS/Ox2ZyN7zw==")
105+
106+
when:
107+
OpenSSHKnownHosts knownHosts = new OpenSSHKnownHosts(f)
108+
109+
then:
110+
knownHosts.entries().size() == 0
111+
}
112+
113+
File writeKnownHosts(String line)
114+
throws IOException {
115+
File known_hosts = temp.newFile("known_hosts");
116+
FileWriter fileWriter = new FileWriter(known_hosts);
117+
BufferedWriter writer = new BufferedWriter(fileWriter);
118+
writer.write(line);
119+
writer.write("\r\n");
120+
writer.flush();
121+
writer.close();
122+
return known_hosts;
123+
}
124+
125+
126+
}

src/test/java/net/schmizz/sshj/transport/verification/OpenSSHKnownHostsTest.java

Lines changed: 0 additions & 88 deletions
This file was deleted.

src/test/resources/known_hosts

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/test/resources/known_hosts.invalid

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)