You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2010/09/22 16:44:14 UTC

svn commit: r999991 - in /mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd: ./ client/ client/channel/ client/kex/ client/session/ common/ server/kex/

Author: gnodet
Date: Wed Sep 22 14:44:14 2010
New Revision: 999991

URL: http://svn.apache.org/viewvc?rev=999991&view=rev
Log:
[SSHD-92] Server key verification
Patch provided by Justin SB

Added:
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/AcceptAllServerKeyVerifier.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/DelegatingServerKeyVerifier.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/RequiredServerKeyVerifier.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/ServerKeyVerifier.java
Modified:
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientChannel.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/SshClient.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/KeyExchange.java
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientChannel.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientChannel.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientChannel.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientChannel.java Wed Sep 22 14:44:14 2010
@@ -57,4 +57,5 @@ public interface ClientChannel {
 
     CloseFuture close(boolean immediately);
 
+    Integer getExitStatus();
 }

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientSession.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientSession.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/ClientSession.java Wed Sep 22 14:44:14 2010
@@ -20,7 +20,7 @@ package org.apache.sshd;
 
 import java.io.IOException;
 import java.security.KeyPair;
-import java.security.PublicKey;
+import java.util.Map;
 
 import org.apache.sshd.client.channel.ChannelExec;
 import org.apache.sshd.client.channel.ChannelSession;
@@ -76,4 +76,5 @@ public interface ClientSession {
 
     CloseFuture close(boolean immediately);
 
+    Map<Object, Object> getMetadataMap();
 }

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/SshClient.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/SshClient.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/SshClient.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/SshClient.java Wed Sep 22 14:44:14 2010
@@ -32,6 +32,7 @@ import org.apache.mina.core.future.IoFut
 import org.apache.mina.core.service.IoConnector;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.apache.sshd.agent.ChannelAgentForwarding;
+import org.apache.sshd.client.ServerKeyVerifier;
 import org.apache.sshd.client.SessionFactory;
 import org.apache.sshd.client.channel.ChannelShell;
 import org.apache.sshd.client.future.ConnectFuture;
@@ -111,6 +112,8 @@ public class SshClient extends AbstractF
     protected IoConnector connector;
     protected SessionFactory sessionFactory;
 
+    private ServerKeyVerifier serverKeyVerifier;
+
     public SshClient() {
     }
 
@@ -392,4 +395,12 @@ public class SshClient extends AbstractF
         }
     }
 
+    public ServerKeyVerifier getServerKeyVerifier() {
+        return serverKeyVerifier;
+    }
+
+    public void setServerKeyVerifier(ServerKeyVerifier serverKeyVerifier) {
+        this.serverKeyVerifier = serverKeyVerifier;
+    }
+
 }

Added: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/AcceptAllServerKeyVerifier.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/AcceptAllServerKeyVerifier.java?rev=999991&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/AcceptAllServerKeyVerifier.java (added)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/AcceptAllServerKeyVerifier.java Wed Sep 22 14:44:14 2010
@@ -0,0 +1,25 @@
+package org.apache.sshd.client;
+
+import java.net.SocketAddress;
+
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.common.util.BufferUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A ServerKeyVerifier that accepts all server keys.
+ */
+public class AcceptAllServerKeyVerifier implements ServerKeyVerifier {
+	protected final Logger log = LoggerFactory.getLogger(getClass());
+
+	public static final ServerKeyVerifier INSTANCE = new AcceptAllServerKeyVerifier();
+
+	private AcceptAllServerKeyVerifier() {
+	}
+
+	public boolean verifyServerKey(ClientSession sshClientSession, SocketAddress remoteAddress, byte[] serverKey) {
+		log.trace("Accepting key for " + remoteAddress + " key=" + BufferUtils.printHex(serverKey));
+		return true;
+	}
+}

Added: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/DelegatingServerKeyVerifier.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/DelegatingServerKeyVerifier.java?rev=999991&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/DelegatingServerKeyVerifier.java (added)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/DelegatingServerKeyVerifier.java Wed Sep 22 14:44:14 2010
@@ -0,0 +1,29 @@
+package org.apache.sshd.client;
+
+import java.net.SocketAddress;
+import java.util.Map;
+
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.common.util.BufferUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * A ServerKeyVerifier that delegates verification to the ServerKeyVerifier found in the ClientSession metadata
+ * The ServerKeyVerifier can be specified at the SshClient level, which may have connections to multiple hosts.
+ * This technique lets each connection have its own ServerKeyVerifier.
+ */
+public class DelegatingServerKeyVerifier implements ServerKeyVerifier {
+	protected final Logger log = LoggerFactory.getLogger(getClass());
+
+	public boolean verifyServerKey(ClientSession sshClientSession, SocketAddress remoteAddress, byte[] serverKey) {
+		Map<Object, Object> metadataMap = sshClientSession.getMetadataMap();
+		Object verifier = metadataMap.get(ServerKeyVerifier.class);
+		if (verifier == null) {
+			log.trace("No verifier found in ClientSession metadata; accepting server key");
+			return true;
+		}
+		// We throw if it's not a ServerKeyVerifier...
+		return ((ServerKeyVerifier) verifier).verifyServerKey(sshClientSession, remoteAddress, serverKey);
+	}
+}

Added: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/RequiredServerKeyVerifier.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/RequiredServerKeyVerifier.java?rev=999991&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/RequiredServerKeyVerifier.java (added)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/RequiredServerKeyVerifier.java Wed Sep 22 14:44:14 2010
@@ -0,0 +1,32 @@
+package org.apache.sshd.client;
+
+import java.net.SocketAddress;
+import java.util.Arrays;
+
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.common.util.BufferUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A ServerKeyVerifier that accepts one server key (specified in the constructor)
+ *
+ */
+public class RequiredServerKeyVerifier implements ServerKeyVerifier {
+	protected final Logger log = LoggerFactory.getLogger(getClass());
+	final byte[] requiredKey;
+
+	public RequiredServerKeyVerifier(byte[] requiredKey) {
+		super();
+		this.requiredKey = requiredKey;
+	}
+
+	public boolean verifyServerKey(ClientSession sshClientSession, SocketAddress remoteAddress, byte[] serverKey) {
+		if (Arrays.equals(requiredKey, serverKey)) {
+			return true;
+		}
+
+		log.info("Server at " + remoteAddress + " presented wrong key: " + BufferUtils.printHex(serverKey));
+		return false;
+	}
+}

Added: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/ServerKeyVerifier.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/ServerKeyVerifier.java?rev=999991&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/ServerKeyVerifier.java (added)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/ServerKeyVerifier.java Wed Sep 22 14:44:14 2010
@@ -0,0 +1,9 @@
+package org.apache.sshd.client;
+
+import java.net.SocketAddress;
+
+import org.apache.sshd.ClientSession;
+
+public interface ServerKeyVerifier {
+    boolean verifyServerKey(ClientSession sshClientSession, SocketAddress remoteAddress, byte[] serverKey);
+}

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java Wed Sep 22 14:44:14 2010
@@ -243,4 +243,8 @@ public abstract class AbstractClientChan
         }
         // TODO: handle other channel requests
     }
+
+    public Integer getExitStatus() {
+        return exitStatus;
+    }
 }

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java Wed Sep 22 14:44:14 2010
@@ -59,6 +59,8 @@ public abstract class AbstractDHGClient 
     private byte[] K;
     private byte[] H;
 
+    private byte[] serverKey;
+
     public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
         if (!(s instanceof ClientSessionImpl)) {
             throw new IllegalStateException("Using a client side KeyExchange on a server");
@@ -91,13 +93,13 @@ public abstract class AbstractDHGClient 
 
         log.info("Received SSH_MSG_KEXDH_REPLY");
         
-        byte[] K_S = buffer.getBytes();
+        serverKey = buffer.getBytes();
         f = buffer.getMPIntAsBytes();
         byte[] sig = buffer.getBytes();
         dh.setF(f);
         K = dh.getK();
 
-        buffer = new Buffer(K_S);
+        buffer = new Buffer(serverKey);
         PublicKey key = buffer.getRawPublicKey();
         String keyAlg = (key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS;
 
@@ -106,7 +108,7 @@ public abstract class AbstractDHGClient 
         buffer.putString(V_S);
         buffer.putString(I_C);
         buffer.putString(I_S);
-        buffer.putString(K_S);
+        buffer.putString(serverKey);
         buffer.putMPInt(e);
         buffer.putMPInt(f);
         buffer.putMPInt(K);
@@ -135,4 +137,8 @@ public abstract class AbstractDHGClient 
         return K;
     }
 
+    public byte[] getServerKey() {
+        return serverKey;
+    }
+
 }

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java Wed Sep 22 14:44:14 2010
@@ -19,11 +19,16 @@
 package org.apache.sshd.client.session;
 
 import java.io.IOException;
+import java.net.SocketAddress;
 import java.security.KeyPair;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.mina.core.session.IoSession;
 import org.apache.sshd.ClientChannel;
 import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.ServerKeyVerifier;
 import org.apache.sshd.client.UserAuth;
 import org.apache.sshd.client.auth.UserAuthAgent;
 import org.apache.sshd.client.auth.UserAuthPassword;
@@ -57,6 +62,11 @@ public class ClientSessionImpl extends A
     private UserAuth userAuth;
     private AuthFuture authFuture;
 
+    /**
+     * For clients to store their own metadata
+     */
+    private Map<Object, Object> metadataMap = new HashMap<Object, Object>();
+
     public ClientSessionImpl(FactoryManager client, IoSession session) throws Exception {
         super(client, session);
         log.info("Session created...");
@@ -390,8 +400,15 @@ public class ClientSessionImpl extends A
         I_S = receiveKexInit(buffer, serverProposal);
     }
 
-    private void checkHost() throws Exception {
-        // TODO: check host fingerprint
+    private void checkHost() throws SshException {
+        ServerKeyVerifier serverKeyVerifier = ((SshClient) getFactoryManager()).getServerKeyVerifier();
+
+        if (serverKeyVerifier != null) {
+            SocketAddress remoteAddress = ioSession.getRemoteAddress();
+
+            if (!serverKeyVerifier.verifyServerKey(this, remoteAddress, kex.getServerKey()))
+                throw new SshException("Server key did not validate");
+        }
     }
 
     private void sendAuthRequest() throws Exception {
@@ -463,4 +480,8 @@ public class ClientSessionImpl extends A
         });
     }
 
+	public Map<Object, Object> getMetadataMap() {
+		return metadataMap;
+	}
+
 }

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/KeyExchange.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/KeyExchange.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/KeyExchange.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/KeyExchange.java Wed Sep 22 14:44:14 2010
@@ -70,4 +70,8 @@ public interface KeyExchange {
      */
     byte[] getK();
 
-}
\ No newline at end of file
+    /**
+     * Retrieves the server's key
+     */
+    byte[] getServerKey();
+}

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java?rev=999991&r1=999990&r2=999991&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java Wed Sep 22 14:44:14 2010
@@ -145,4 +145,8 @@ public abstract class AbstractDHGServer 
         return K;
     }
 
+    public byte[] getServerKey() {
+        throw new UnsupportedOperationException();
+    }
+
 }