Capture server key before returning from callback 18/81918/5
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 6 May 2019 20:56:54 +0000 (22:56 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 7 May 2019 07:10:41 +0000 (09:10 +0200)
The key exchange structure is torn down immediately after
KeyEstablished callback returns, hence we need to capture
the server key before returning.

JIRA: NETCONF-614
Change-Id: Iebe69fe374a766f1502325cb610eed8dadb5f099
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
netconf/callhome-protocol/src/main/java/org/opendaylight/netconf/callhome/protocol/NetconfCallHomeServer.java
netconf/callhome-protocol/src/test/java/org/opendaylight/netconf/callhome/protocol/NetconfCallHomeServerTest.java
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallhomeStatusReporter.java

index c519d2bb7b30ab504880a30099ae78d2fb4cf931..47ee60eeccf93e7aad2f2087417a73b5f887cba8 100644 (file)
@@ -18,12 +18,10 @@ import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
 import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.client.session.ClientSessionImpl;
 import org.apache.sshd.client.session.SessionFactory;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoServiceFactory;
-import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.session.SessionListener;
 import org.apache.sshd.netty.NettyIoServiceFactory;
@@ -119,6 +117,8 @@ public class NetconfCallHomeServer implements AutoCloseable, ServerKeyVerifier {
     }
 
     private SshFutureListener<AuthFuture> newAuthSshFutureListener(final ClientSession session) {
+        final PublicKey serverKey = session.getKex().getServerKey();
+
         return new SshFutureListener<AuthFuture>() {
             @Override
             public void operationComplete(final AuthFuture authFuture) {
@@ -137,13 +137,8 @@ public class NetconfCallHomeServer implements AutoCloseable, ServerKeyVerifier {
             }
 
             private void onFailure(final Throwable throwable) {
-                ClientSessionImpl impl = (ClientSessionImpl) session;
                 LOG.error("Authorize failed for session {}", session, throwable);
-
-                KeyExchange kex = impl.getKex();
-                PublicKey key = kex.getServerKey();
-                recorder.reportFailedAuth(key);
-
+                recorder.reportFailedAuth(serverKey);
                 session.close(true);
             }
 
index 27b829e0ef5d8eacce9a1e782cfea27b14d7a5ec..e400f5e66f35ab6755919aae8f53b0a0d2206b89 100644 (file)
@@ -33,6 +33,7 @@ import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoServiceFactory;
+import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.session.SessionListener;
 import org.junit.AfterClass;
@@ -114,6 +115,12 @@ public class NetconfCallHomeServerTest {
             CallHomeSessionContext mockContext = mock(CallHomeSessionContext.class);
             doNothing().when(mockContext).openNetconfChannel();
             doReturn(mockContext).when(mockSession).getAttribute(any(Session.AttributeKey.class));
+
+            final KeyExchange kex = mock(KeyExchange.class);
+            doReturn(kex).when(mockSession).getKex();
+            final PublicKey serverKey = mock(PublicKey.class);
+            doReturn(serverKey).when(kex).getServerKey();
+
             SessionListener listener = instance.createSessionListener();
             doReturn(mockAuthFuture).when(mockContext).authorize();
             // when
index 1f819ae0a34ffa3f0cf5a32597ed9c72d1be6c86..7bff5acd4a661b7c8b02ad07e83a5b8b18ef279b 100644 (file)
@@ -303,6 +303,10 @@ class CallhomeStatusReporter implements DataTreeChangeListener<Node>, StatusReco
 
         for (Device device : getDevicesAsList()) {
             String keyString = device.getSshHostKey();
+            if (keyString == null) {
+                LOG.info("Whitelist device {} does not have a host key, skipping it", device.getUniqueId());
+                continue;
+            }
 
             try {
                 PublicKey pubKey = decoder.decodePublicKey(keyString);