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();
+ }
+
}