Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/ServerConnection.java @ 298:ab3a99f11a36 ganymed
add ecdsa key support everywhere
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 29 Jul 2014 18:01:08 -0700 |
parents | d2ee20d9dff1 |
children | 349847b2e318 |
comparison
equal
deleted
inserted
replaced
297:c1f929cb3dd0 | 298:ab3a99f11a36 |
---|---|
69 * @see #connect(int) | 69 * @see #connect(int) |
70 * | 70 * |
71 * @param s The socket | 71 * @param s The socket |
72 * @param dsa_key The DSA hostkey, may be <code>NULL</code> | 72 * @param dsa_key The DSA hostkey, may be <code>NULL</code> |
73 * @param rsa_key The RSA hostkey, may be <code>NULL</code> | 73 * @param rsa_key The RSA hostkey, may be <code>NULL</code> |
74 */ | 74 * @param ec_key The EC hostkey, may be <code>NULL</code> |
75 public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key) | 75 */ |
76 public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) | |
76 { | 77 { |
77 state.s = s; | 78 state.s = s; |
78 state.softwareversion = softwareversion; | 79 state.softwareversion = softwareversion; |
79 state.next_dsa_key = dsa_key; | 80 state.next_dsa_key = dsa_key; |
80 state.next_rsa_key = rsa_key; | 81 state.next_rsa_key = rsa_key; |
81 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key); | 82 state.next_ec_key = ec_key; |
83 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | |
82 } | 84 } |
83 | 85 |
84 /** | 86 /** |
85 * Establish the connection and block until the first handshake has completed. | 87 * Establish the connection and block until the first handshake has completed. |
86 * <p> | 88 * <p> |
98 } | 100 } |
99 | 101 |
100 /** | 102 /** |
101 * Establish the connection and block until the first handshake has completed. | 103 * Establish the connection and block until the first handshake has completed. |
102 * <p> | 104 * <p> |
103 * Note 1: either a DSA or a RSA (or both) hostkey must be set before calling this method. | 105 * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. |
104 * <p> | 106 * <p> |
105 * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) | 107 * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) |
106 * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). | 108 * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). |
107 * | 109 * |
108 * @see #setPEMHostKey(char[], String) | 110 * @see #setPEMHostKey(char[], String) |
124 throw new IllegalStateException("The callback for authentication events has not been set."); | 126 throw new IllegalStateException("The callback for authentication events has not been set."); |
125 | 127 |
126 if (state.tm != null) | 128 if (state.tm != null) |
127 throw new IllegalStateException("The initial handshake has already been started."); | 129 throw new IllegalStateException("The initial handshake has already been started."); |
128 | 130 |
129 if ((state.next_dsa_key == null) && (state.next_rsa_key == null)) | 131 if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) |
130 throw new IllegalStateException("Neither a RSA nor a DSA host key has been specified!"); | 132 throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); |
131 | 133 |
132 state.tm = new ServerTransportManager(state.s); | 134 state.tm = new ServerTransportManager(state.s); |
133 } | 135 } |
134 | 136 |
135 state.tm.connect(state); | 137 state.tm.connect(state); |
169 { | 171 { |
170 if (state.tm == null) | 172 if (state.tm == null) |
171 throw new IllegalStateException( | 173 throw new IllegalStateException( |
172 "Cannot force another key exchange, you need to start the key exchange first."); | 174 "Cannot force another key exchange, you need to start the key exchange first."); |
173 | 175 |
174 state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key); | 176 state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
175 } | 177 } |
176 } | 178 } |
177 | 179 |
178 /** | 180 /** |
179 * Returns a {@link ConnectionInfo} object containing the details of | 181 * Returns a {@link ConnectionInfo} object containing the details of |
197 | 199 |
198 return state.tm.getConnectionInfo(1); | 200 return state.tm.getConnectionInfo(1); |
199 } | 201 } |
200 | 202 |
201 /** | 203 /** |
202 * Change the current DSA hostkey. Either a DSA or RSA private key must be set for a successful handshake with | 204 * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with |
203 * the client. | 205 * the client. |
204 * <p> | 206 * <p> |
205 * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will | 207 * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will |
206 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the | 208 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the |
207 * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. | 209 * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. |
214 { | 216 { |
215 if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) | 217 if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) |
216 throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); | 218 throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); |
217 | 219 |
218 state.next_dsa_key = dsa_hostkey; | 220 state.next_dsa_key = dsa_hostkey; |
219 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key); | 221 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
220 } | 222 } |
221 } | 223 } |
222 | 224 |
223 /** | 225 /** |
224 * Change the current RSA hostkey. Either a DSA or RSA private key must be set for a successful handshake with | 226 * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with |
225 * the client. | 227 * the client. |
226 * <p> | 228 * <p> |
227 * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will | 229 * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will |
228 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the | 230 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the |
229 * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. | 231 * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. |
236 { | 238 { |
237 if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) | 239 if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) |
238 throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); | 240 throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); |
239 | 241 |
240 state.next_rsa_key = rsa_hostkey; | 242 state.next_rsa_key = rsa_hostkey; |
241 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key); | 243 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
244 } | |
245 } | |
246 | |
247 /** | |
248 * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with | |
249 * the client. | |
250 * <p> | |
251 * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will | |
252 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the | |
253 * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. | |
254 * | |
255 * @param rsa_hostkey | |
256 */ | |
257 public synchronized void setEcHostKey(KeyPair ec_hostkey) | |
258 { | |
259 synchronized (state) | |
260 { | |
261 if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) | |
262 throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); | |
263 | |
264 state.next_ec_key = ec_hostkey; | |
265 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | |
242 } | 266 } |
243 } | 267 } |
244 | 268 |
245 /** | 269 /** |
246 * Utility method that loads a PEM based hostkey (either RSA or DSA based) and | 270 * Utility method that loads a PEM based hostkey (either RSA or DSA based) and |
256 PrivateKey key = pair.getPrivate(); | 280 PrivateKey key = pair.getPrivate(); |
257 | 281 |
258 if (key instanceof DSAPrivateKey) setDsaHostKey(pair); | 282 if (key instanceof DSAPrivateKey) setDsaHostKey(pair); |
259 | 283 |
260 if (key instanceof RSAPrivateKey) setRsaHostKey(pair); | 284 if (key instanceof RSAPrivateKey) setRsaHostKey(pair); |
285 | |
286 if (key instanceof ECPrivateKey) setEcHostKey(pair); | |
261 } | 287 } |
262 | 288 |
263 /** | 289 /** |
264 * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and | 290 * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and |
265 * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. | 291 * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. |
290 fr.close(); | 316 fr.close(); |
291 | 317 |
292 setPEMHostKey(cw.toCharArray(), password); | 318 setPEMHostKey(cw.toCharArray(), password); |
293 } | 319 } |
294 | 320 |
295 private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key) | 321 private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) |
296 { | 322 { |
297 if ((next_dsa_key != null) && (next_rsa_key != null)) | 323 List<String> algos = new ArrayList<string>(); |
298 next_cryptoWishList.serverHostKeyAlgorithms = new String[] { "ssh-rsa", "ssh-dss" }; | 324 if (next_dsa_key != null) algos.add("ssh-dss"); |
299 else if (next_dsa_key != null) | 325 if (next_rsa_key != null) algos.add("ssh-rsa"); |
300 next_cryptoWishList.serverHostKeyAlgorithms = new String[] { "ssh-dss" }; | 326 if (next_ec_key != null) algos.add("ssh-ec"); |
301 else if (next_rsa_key != null) | 327 next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; |
302 next_cryptoWishList.serverHostKeyAlgorithms = new String[] { "ssh-rsa" }; | 328 algos.toArray(next_cryptoWishList.serverHostKeyAlgorithms); |
303 else | |
304 next_cryptoWishList.serverHostKeyAlgorithms = new String[0]; | |
305 } | 329 } |
306 | 330 |
307 /** | 331 /** |
308 * Callback interface with methods that will be called upon events | 332 * Callback interface with methods that will be called upon events |
309 * generated by the client (e.g., client opens a new Session which results in a <code>ServerSession</code>). | 333 * generated by the client (e.g., client opens a new Session which results in a <code>ServerSession</code>). |