Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/transport/ServerKexManager.java @ 273:91a31873c42a ganymed
start conversion from trilead to ganymed
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 18 Jul 2014 11:21:46 -0700 |
parents | |
children | b4ca341c318d |
comparison
equal
deleted
inserted
replaced
272:ce2f4e397703 | 273:91a31873c42a |
---|---|
1 /* | |
2 * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. | |
3 * Please refer to the LICENSE.txt for licensing details. | |
4 */ | |
5 package ch.ethz.ssh2.transport; | |
6 | |
7 import java.io.IOException; | |
8 import java.security.DigestException; | |
9 | |
10 import ch.ethz.ssh2.ConnectionInfo; | |
11 import ch.ethz.ssh2.PacketTypeException; | |
12 import ch.ethz.ssh2.auth.ServerAuthenticationManager; | |
13 import ch.ethz.ssh2.crypto.cipher.BlockCipher; | |
14 import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; | |
15 import ch.ethz.ssh2.crypto.dh.DhExchange; | |
16 import ch.ethz.ssh2.crypto.digest.MAC; | |
17 import ch.ethz.ssh2.packets.PacketKexDHInit; | |
18 import ch.ethz.ssh2.packets.PacketKexDHReply; | |
19 import ch.ethz.ssh2.packets.PacketKexInit; | |
20 import ch.ethz.ssh2.packets.Packets; | |
21 import ch.ethz.ssh2.server.ServerConnectionState; | |
22 import ch.ethz.ssh2.signature.DSASHA1Verify; | |
23 import ch.ethz.ssh2.signature.DSASignature; | |
24 import ch.ethz.ssh2.signature.RSASHA1Verify; | |
25 import ch.ethz.ssh2.signature.RSASignature; | |
26 | |
27 /** | |
28 * @version $Id: ServerKexManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ | |
29 */ | |
30 public class ServerKexManager extends KexManager { | |
31 | |
32 private final ServerConnectionState state; | |
33 | |
34 private boolean authenticationStarted = false; | |
35 | |
36 public ServerKexManager(ServerConnectionState state) { | |
37 super(state.tm, state.csh, state.next_cryptoWishList, state.generator); | |
38 this.state = state; | |
39 } | |
40 | |
41 @Override | |
42 public void handleFailure(final IOException failure) { | |
43 synchronized(accessLock) { | |
44 connectionClosed = true; | |
45 accessLock.notifyAll(); | |
46 } | |
47 } | |
48 | |
49 @Override | |
50 public void handleMessage(byte[] msg) throws IOException { | |
51 PacketKexInit kip; | |
52 | |
53 if((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { | |
54 throw new PacketTypeException(msg[0]); | |
55 } | |
56 | |
57 if(ignore_next_kex_packet) { | |
58 ignore_next_kex_packet = false; | |
59 return; | |
60 } | |
61 | |
62 if(msg[0] == Packets.SSH_MSG_KEXINIT) { | |
63 if((kxs != null) && (kxs.state != 0)) { | |
64 throw new PacketTypeException(msg[0]); | |
65 } | |
66 | |
67 if(kxs == null) { | |
68 /* | |
69 * Ah, OK, peer wants to do KEX. Let's be nice and play | |
70 * together. | |
71 */ | |
72 kxs = new KexState(); | |
73 kxs.local_dsa_key = nextKEXdsakey; | |
74 kxs.local_rsa_key = nextKEXrsakey; | |
75 kxs.dhgexParameters = nextKEXdhgexParameters; | |
76 kip = new PacketKexInit(nextKEXcryptoWishList, rnd); | |
77 kxs.localKEX = kip; | |
78 tm.sendKexMessage(kip.getPayload()); | |
79 } | |
80 | |
81 kip = new PacketKexInit(msg); | |
82 kxs.remoteKEX = kip; | |
83 | |
84 kxs.np = mergeKexParameters(kxs.remoteKEX.getKexParameters(), kxs.localKEX.getKexParameters()); | |
85 | |
86 if(kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { | |
87 // Guess was wrong, we need to ignore the next kex packet. | |
88 ignore_next_kex_packet = true; | |
89 } | |
90 | |
91 if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") | |
92 || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) { | |
93 kxs.dhx = new DhExchange(); | |
94 | |
95 if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) { | |
96 kxs.dhx.serverInit(1, rnd); | |
97 } | |
98 else { | |
99 kxs.dhx.serverInit(14, rnd); | |
100 } | |
101 | |
102 kxs.state = 1; | |
103 return; | |
104 } | |
105 | |
106 throw new IllegalStateException("Unkown KEX method!"); | |
107 } | |
108 | |
109 if(msg[0] == Packets.SSH_MSG_NEWKEYS) { | |
110 if(km == null) { | |
111 throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); | |
112 } | |
113 | |
114 BlockCipher cbc; | |
115 MAC mac; | |
116 | |
117 try { | |
118 cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_client_to_server, false, | |
119 km.enc_key_client_to_server, km.initial_iv_client_to_server); | |
120 | |
121 try { | |
122 mac = new MAC(kxs.np.mac_algo_client_to_server, km.integrity_key_client_to_server); | |
123 } | |
124 catch(DigestException e) { | |
125 throw new IOException(e); | |
126 } | |
127 | |
128 } | |
129 catch(IllegalArgumentException e) { | |
130 throw new IOException(e); | |
131 } | |
132 | |
133 tm.changeRecvCipher(cbc, mac); | |
134 | |
135 ConnectionInfo sci = new ConnectionInfo(); | |
136 | |
137 kexCount++; | |
138 | |
139 sci.keyExchangeAlgorithm = kxs.np.kex_algo; | |
140 sci.keyExchangeCounter = kexCount; | |
141 sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; | |
142 sci.serverToClientCryptoAlgorithm = kxs.np.enc_algo_server_to_client; | |
143 sci.clientToServerMACAlgorithm = kxs.np.mac_algo_client_to_server; | |
144 sci.serverToClientMACAlgorithm = kxs.np.mac_algo_server_to_client; | |
145 sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; | |
146 sci.serverHostKey = kxs.remote_hostkey; | |
147 | |
148 synchronized(accessLock) { | |
149 lastConnInfo = sci; | |
150 accessLock.notifyAll(); | |
151 } | |
152 | |
153 kxs = null; | |
154 return; | |
155 } | |
156 | |
157 if((kxs == null) || (kxs.state == 0)) { | |
158 throw new IOException("Unexpected Kex submessage!"); | |
159 } | |
160 | |
161 if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") | |
162 || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) { | |
163 if(kxs.state == 1) { | |
164 PacketKexDHInit dhi = new PacketKexDHInit(msg); | |
165 | |
166 kxs.dhx.setE(dhi.getE()); | |
167 | |
168 byte[] hostKey = null; | |
169 | |
170 if(kxs.np.server_host_key_algo.equals("ssh-rsa")) { | |
171 hostKey = RSASHA1Verify.encodeSSHRSAPublicKey(kxs.local_rsa_key.getPublicKey()); | |
172 } | |
173 | |
174 if(kxs.np.server_host_key_algo.equals("ssh-dss")) { | |
175 hostKey = DSASHA1Verify.encodeSSHDSAPublicKey(kxs.local_dsa_key.getPublicKey()); | |
176 } | |
177 | |
178 try { | |
179 kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), | |
180 kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey); | |
181 } | |
182 catch(IllegalArgumentException e) { | |
183 throw new IOException("KEX error.", e); | |
184 } | |
185 | |
186 kxs.K = kxs.dhx.getK(); | |
187 | |
188 byte[] signature = null; | |
189 | |
190 if(kxs.np.server_host_key_algo.equals("ssh-rsa")) { | |
191 RSASignature rs = RSASHA1Verify.generateSignature(kxs.H, kxs.local_rsa_key); | |
192 signature = RSASHA1Verify.encodeSSHRSASignature(rs); | |
193 } | |
194 | |
195 if(kxs.np.server_host_key_algo.equals("ssh-dss")) { | |
196 DSASignature ds = DSASHA1Verify.generateSignature(kxs.H, kxs.local_dsa_key, rnd); | |
197 signature = DSASHA1Verify.encodeSSHDSASignature(ds); | |
198 } | |
199 | |
200 PacketKexDHReply dhr = new PacketKexDHReply(hostKey, kxs.dhx.getF(), signature); | |
201 tm.sendKexMessage(dhr.getPayload()); | |
202 | |
203 finishKex(false); | |
204 kxs.state = -1; | |
205 | |
206 if(authenticationStarted == false) { | |
207 authenticationStarted = true; | |
208 state.am = new ServerAuthenticationManager(state); | |
209 } | |
210 | |
211 return; | |
212 } | |
213 } | |
214 throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); | |
215 } | |
216 } |