changeset 308:42b15aaa7ac7 ganymed

merge
author Carl Byington <carl@five-ten-sg.com>
date Wed, 30 Jul 2014 14:21:50 -0700
parents 90e47d99ea54 (diff) 071eccdff8ea (current diff)
children cb179051f0f2
files src/ch/ethz/ssh2/transport/ClientKexManager.java src/ch/ethz/ssh2/transport/ServerKexManager.java
diffstat 2 files changed, 121 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/src/ch/ethz/ssh2/transport/ClientKexManager.java	Wed Jul 30 14:16:58 2014 -0700
+++ b/src/ch/ethz/ssh2/transport/ClientKexManager.java	Wed Jul 30 14:21:50 2014 -0700
@@ -80,7 +80,7 @@
     }
 
     public void handleFailure(final IOException failure) {
-        synchronized (accessLock) {
+        synchronized(accessLock) {
             connectionClosed = true;
             accessLock.notifyAll();
         }
@@ -89,25 +89,33 @@
     public synchronized void handleMessage(byte[] msg) throws IOException {
         PacketKexInit kip;
 
-        if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) {
+        if (msg == null) {
+            synchronized (accessLock) {
+                connectionClosed = true;
+                accessLock.notifyAll();
+                return;
+            }
+        }
+
+        if((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) {
             throw new PacketTypeException(msg[0]);
         }
 
-        if (ignore_next_kex_packet) {
+        if(ignore_next_kex_packet) {
             ignore_next_kex_packet = false;
             return;
         }
 
-        if (msg[0] == Packets.SSH_MSG_KEXINIT) {
-            if ((kxs != null) && (kxs.state != 0)) {
+        if(msg[0] == Packets.SSH_MSG_KEXINIT) {
+            if((kxs != null) && (kxs.state != 0)) {
                 throw new PacketTypeException(msg[0]);
             }
 
-            if (kxs == null) {
+            if(kxs == null) {
                 /*
                  * Ah, OK, peer wants to do KEX. Let's be nice and play
-                 * together.
-                 */
+				 * together.
+				 */
                 kxs = new KexState();
                 kxs.dhgexParameters = nextKEXdhgexParameters;
                 kip = new PacketKexInit(nextKEXcryptoWishList, rnd);
@@ -117,38 +125,42 @@
 
             kip = new PacketKexInit(msg);
             kxs.remoteKEX = kip;
+
             kxs.np = mergeKexParameters(kxs.localKEX.getKexParameters(), kxs.remoteKEX.getKexParameters());
 
-            if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) {
+            if(kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) {
                 // Guess was wrong, we need to ignore the next kex packet.
                 ignore_next_kex_packet = true;
             }
 
-            if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1")) {
-                if (kxs.dhgexParameters.getMin_group_len() == 0) {
+            if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1") ||
+                kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha256")) {
+                if(kxs.dhgexParameters.getMin_group_len() == 0) {
                     PacketKexDhGexRequestOld dhgexreq = new PacketKexDhGexRequestOld(kxs.dhgexParameters);
                     tm.sendKexMessage(dhgexreq.getPayload());
+
                 }
                 else {
                     PacketKexDhGexRequest dhgexreq = new PacketKexDhGexRequest(kxs.dhgexParameters);
                     tm.sendKexMessage(dhgexreq.getPayload());
                 }
-
+                if (kxs.np.kex_algo.endsWith("sha1")) {
+                    kxs.hashAlgo = "SHA1";
+                }
+                else {
+                    kxs.hashAlgo = "SHA-256";
+                }
                 kxs.state = 1;
                 return;
             }
 
-            if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")
-                    || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) {
-                kxs.dhx = new DhExchange();
-
-                if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) {
-                    kxs.dhx.clientInit(1, rnd);
-                }
-                else {
-                    kxs.dhx.clientInit(14, rnd);
-                }
-
+            if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")  ||
+                kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") ||
+                kxs.np.kex_algo.equals("ecdh-sha2-nistp256")          ||
+                kxs.np.kex_algo.equals("ecdh-sha2-nistp384")          ||
+                kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) {
+                kxs.dhx = GenericDhExchange.getInstance(kxs.np.kex_algo);
+                kxs.dhx.init(kxs.np.kex_algo);
                 PacketKexDHInit kp = new PacketKexDHInit(kxs.dhx.getE());
                 tm.sendKexMessage(kp.getPayload());
                 kxs.state = 1;
@@ -158,8 +170,8 @@
             throw new IllegalStateException("Unkown KEX method!");
         }
 
-        if (msg[0] == Packets.SSH_MSG_NEWKEYS) {
-            if (km == null) {
+        if(msg[0] == Packets.SSH_MSG_NEWKEYS) {
+            if(km == null) {
                 throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!");
             }
 
@@ -169,25 +181,28 @@
 
             try {
                 cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_server_to_client, false,
-                                                      km.enc_key_server_to_client, km.initial_iv_server_to_client);
+                        km.enc_key_server_to_client, km.initial_iv_server_to_client);
 
                 try {
                     mac = new MAC(kxs.np.mac_algo_server_to_client, km.integrity_key_server_to_client);
                 }
-                catch (DigestException e) {
+                catch(DigestException e) {
                     throw new IOException(e);
                 }
 
                 comp = CompressionFactory.createCompressor(kxs.np.comp_algo_server_to_client);
             }
-            catch (IllegalArgumentException e) {
+            catch(IllegalArgumentException e) {
                 throw new IOException(e.getMessage());
             }
 
             tm.changeRecvCipher(cbc, mac);
             tm.changeRecvCompression(comp);
+
             ConnectionInfo sci = new ConnectionInfo();
+
             kexCount++;
+
             sci.keyExchangeAlgorithm = kxs.np.kex_algo;
             sci.keyExchangeCounter = kexCount;
             sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server;
@@ -197,7 +212,7 @@
             sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo;
             sci.serverHostKey = kxs.remote_hostkey;
 
-            synchronized (accessLock) {
+            synchronized(accessLock) {
                 lastConnInfo = sci;
                 accessLock.notifyAll();
             }
@@ -206,12 +221,13 @@
             return;
         }
 
-        if ((kxs == null) || (kxs.state == 0)) {
+        if((kxs == null) || (kxs.state == 0)) {
             throw new IOException("Unexpected Kex submessage!");
         }
 
-        if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1")) {
-            if (kxs.state == 1) {
+        if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1") ||
+            kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha256")) {
+            if(kxs.state == 1) {
                 PacketKexDhGexGroup dhgexgrp = new PacketKexDhGexGroup(msg);
                 kxs.dhgx = new DhGroupExchange(dhgexgrp.getP(), dhgexgrp.getG());
                 kxs.dhgx.init(rnd);
@@ -221,19 +237,20 @@
                 return;
             }
 
-            if (kxs.state == 2) {
+            if(kxs.state == 2) {
                 PacketKexDhGexReply dhgexrpl = new PacketKexDhGexReply(msg);
+
                 kxs.remote_hostkey = dhgexrpl.getHostKey();
 
-                if (verifier != null) {
+                if(verifier != null) {
                     try {
-                        if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) {
+                        if(!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) {
                             throw new IOException("The server host key was not accepted by the verifier callback");
                         }
                     }
-                    catch (Exception e) {
+                    catch(Exception e) {
                         throw new IOException(
-                            "The server host key was not accepted by the verifier callback.", e);
+                                "The server host key was not accepted by the verifier callback.", e);
                     }
                 }
 
@@ -241,17 +258,15 @@
 
                 try {
                     kxs.H = kxs.dhgx.calculateH(csh.getClientString(), csh.getServerString(),
-                                                kxs.localKEX.getPayload(), kxs.remoteKEX.getPayload(), dhgexrpl.getHostKey(),
-                                                kxs.dhgexParameters);
+                            kxs.localKEX.getPayload(), kxs.remoteKEX.getPayload(), dhgexrpl.getHostKey(),
+                            kxs.dhgexParameters);
                 }
-                catch (IllegalArgumentException e) {
+                catch(IllegalArgumentException e) {
                     throw new IOException("KEX error.", e);
                 }
-
-                if (!verifySignature(dhgexrpl.getSignature(), kxs.remote_hostkey)) {
+                if(!verifySignature(dhgexrpl.getSignature(), kxs.remote_hostkey)) {
                     throw new IOException("Invalid remote host key signature");
                 }
-
                 kxs.K = kxs.dhgx.getK();
                 finishKex(true);
                 kxs.state = -1;
@@ -261,44 +276,42 @@
             throw new IllegalStateException("Illegal State in KEX Exchange!");
         }
 
-        if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")
-                || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) {
-            if (kxs.state == 1) {
+        if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")  ||
+            kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") ||
+            kxs.np.kex_algo.equals("ecdh-sha2-nistp256")          ||
+            kxs.np.kex_algo.equals("ecdh-sha2-nistp384")          ||
+            kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) {
+            if(kxs.state == 1) {
                 PacketKexDHReply dhr = new PacketKexDHReply(msg);
                 kxs.remote_hostkey = dhr.getHostKey();
 
-                if (verifier != null) {
+                if(verifier != null) {
                     try {
-                        if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) {
+                        if(!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) {
                             throw new IOException("The server host key was not accepted by the verifier callback");
                         }
                     }
-                    catch (Exception e) {
+                    catch(Exception e) {
                         throw new IOException("The server host key was not accepted by the verifier callback", e);
                     }
                 }
-
                 kxs.dhx.setF(dhr.getF());
-
                 try {
                     kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), kxs.localKEX.getPayload(),
-                                               kxs.remoteKEX.getPayload(), dhr.getHostKey());
+                            kxs.remoteKEX.getPayload(), dhr.getHostKey());
                 }
-                catch (IllegalArgumentException e) {
+                catch(IllegalArgumentException e) {
                     throw new IOException("KEX error.", e);
                 }
-
-                if (!verifySignature(dhr.getSignature(), kxs.remote_hostkey)) {
+                if(!verifySignature(dhr.getSignature(), kxs.remote_hostkey)) {
                     throw new IOException("Invalid remote host key signature");
                 }
-
                 kxs.K = kxs.dhx.getK();
                 finishKex(true);
                 kxs.state = -1;
                 return;
             }
         }
-
         throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo));
     }
 }
--- a/src/ch/ethz/ssh2/transport/ServerKexManager.java	Wed Jul 30 14:16:58 2014 -0700
+++ b/src/ch/ethz/ssh2/transport/ServerKexManager.java	Wed Jul 30 14:21:50 2014 -0700
@@ -44,7 +44,7 @@
     }
 
     public void handleFailure(final IOException failure) {
-        synchronized (accessLock) {
+        synchronized(accessLock) {
             connectionClosed = true;
             accessLock.notifyAll();
         }
@@ -53,25 +53,33 @@
     public void handleMessage(byte[] msg) throws IOException {
         PacketKexInit kip;
 
-        if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) {
+        if (msg == null) {
+            synchronized (accessLock) {
+                connectionClosed = true;
+                accessLock.notifyAll();
+                return;
+            }
+        }
+
+        if((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) {
             throw new PacketTypeException(msg[0]);
         }
 
-        if (ignore_next_kex_packet) {
+        if(ignore_next_kex_packet) {
             ignore_next_kex_packet = false;
             return;
         }
 
-        if (msg[0] == Packets.SSH_MSG_KEXINIT) {
-            if ((kxs != null) && (kxs.state != 0)) {
+        if(msg[0] == Packets.SSH_MSG_KEXINIT) {
+            if((kxs != null) && (kxs.state != 0)) {
                 throw new PacketTypeException(msg[0]);
             }
 
-            if (kxs == null) {
+            if(kxs == null) {
                 /*
                  * Ah, OK, peer wants to do KEX. Let's be nice and play
-                 * together.
-                 */
+				 * together.
+				 */
                 kxs = new KexState();
                 kxs.local_dsa_key = nextKEXdsakey;
                 kxs.local_rsa_key = nextKEXrsakey;
@@ -84,24 +92,21 @@
 
             kip = new PacketKexInit(msg);
             kxs.remoteKEX = kip;
+
             kxs.np = mergeKexParameters(kxs.remoteKEX.getKexParameters(), kxs.localKEX.getKexParameters());
 
-            if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) {
+            if(kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) {
                 // Guess was wrong, we need to ignore the next kex packet.
                 ignore_next_kex_packet = true;
             }
 
-            if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")
-                    || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) {
-                kxs.dhx = new DhExchange();
-
-                if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) {
-                    kxs.dhx.serverInit(1, rnd);
-                }
-                else {
-                    kxs.dhx.serverInit(14, rnd);
-                }
-
+            if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")  ||
+                kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") ||
+                kxs.np.kex_algo.equals("ecdh-sha2-nistp256")          ||
+                kxs.np.kex_algo.equals("ecdh-sha2-nistp384")          ||
+                kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) {
+                kxs.dhx = GenericDhExchange.getInstance(kxs.np.kex_algo);
+                kxs.dhx.init(kxs.np.kex_algo);
                 kxs.state = 1;
                 return;
             }
@@ -109,8 +114,8 @@
             throw new IllegalStateException("Unkown KEX method!");
         }
 
-        if (msg[0] == Packets.SSH_MSG_NEWKEYS) {
-            if (km == null) {
+        if(msg[0] == Packets.SSH_MSG_NEWKEYS) {
+            if(km == null) {
                 throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!");
             }
 
@@ -119,22 +124,26 @@
 
             try {
                 cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_client_to_server, false,
-                                                      km.enc_key_client_to_server, km.initial_iv_client_to_server);
+                        km.enc_key_client_to_server, km.initial_iv_client_to_server);
 
                 try {
                     mac = new MAC(kxs.np.mac_algo_client_to_server, km.integrity_key_client_to_server);
                 }
-                catch (DigestException e) {
+                catch(DigestException e) {
                     throw new IOException(e);
                 }
+
             }
-            catch (IllegalArgumentException e) {
+            catch(IllegalArgumentException e) {
                 throw new IOException(e);
             }
 
             tm.changeRecvCipher(cbc, mac);
+
             ConnectionInfo sci = new ConnectionInfo();
+
             kexCount++;
+
             sci.keyExchangeAlgorithm = kxs.np.kex_algo;
             sci.keyExchangeCounter = kexCount;
             sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server;
@@ -144,7 +153,7 @@
             sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo;
             sci.serverHostKey = kxs.remote_hostkey;
 
-            synchronized (accessLock) {
+            synchronized(accessLock) {
                 lastConnInfo = sci;
                 accessLock.notifyAll();
             }
@@ -153,38 +162,44 @@
             return;
         }
 
-        if ((kxs == null) || (kxs.state == 0)) {
+        if((kxs == null) || (kxs.state == 0)) {
             throw new IOException("Unexpected Kex submessage!");
         }
 
-        if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")
-                || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) {
-            if (kxs.state == 1) {
+        if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")  ||
+            kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") ||
+            kxs.np.kex_algo.equals("ecdh-sha2-nistp256")          ||
+            kxs.np.kex_algo.equals("ecdh-sha2-nistp384")          ||
+            kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) {
+            if(kxs.state == 1) {
                 PacketKexDHInit dhi = new PacketKexDHInit(msg);
+
                 kxs.dhx.setE(dhi.getE());
+
                 byte[] hostKey = null;
 
                 if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) {
                     hostKey = ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey)kxs.local_ec_key.getPublic());
                 }
 
-                if (kxs.np.server_host_key_algo.equals("ssh-rsa")) {
+                if(kxs.np.server_host_key_algo.equals("ssh-rsa")) {
                     hostKey = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey)kxs.local_rsa_key.getPublic());
                 }
 
-                if (kxs.np.server_host_key_algo.equals("ssh-dss")) {
+                if(kxs.np.server_host_key_algo.equals("ssh-dss")) {
                     hostKey = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey)kxs.local_dsa_key.getPublic());
                 }
 
                 try {
                     kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(),
-                                               kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey);
+                            kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey);
                 }
-                catch (IllegalArgumentException e) {
+                catch(IllegalArgumentException e) {
                     throw new IOException("KEX error.", e);
                 }
 
                 kxs.K = kxs.dhx.getK();
+
                 byte[] signature = null;
 
                 if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) {
@@ -205,10 +220,11 @@
 
                 PacketKexDHReply dhr = new PacketKexDHReply(hostKey, kxs.dhx.getF(), signature);
                 tm.sendKexMessage(dhr.getPayload());
+
                 finishKex(false);
                 kxs.state = -1;
 
-                if (authenticationStarted == false) {
+                if(authenticationStarted == false) {
                     authenticationStarted = true;
                     state.am = new ServerAuthenticationManager(state);
                 }
@@ -216,7 +232,6 @@
                 return;
             }
         }
-
         throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo));
     }
 }