Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/ServerConnection.java @ 308:42b15aaa7ac7 ganymed
merge
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 30 Jul 2014 14:21:50 -0700 |
parents | 071eccdff8ea |
children | c19b24adf6c9 |
comparison
equal
deleted
inserted
replaced
306:90e47d99ea54 | 308:42b15aaa7ac7 |
---|---|
27 * A server-side SSH-2 connection. | 27 * A server-side SSH-2 connection. |
28 * | 28 * |
29 * @author Christian | 29 * @author Christian |
30 * | 30 * |
31 */ | 31 */ |
32 public class ServerConnection | 32 public class ServerConnection { |
33 { | 33 /** |
34 /** | 34 * The softwareversion presented to the SSH-2 client. |
35 * The softwareversion presented to the SSH-2 client. | 35 */ |
36 */ | 36 private String softwareversion = String.format("Ganymed_SSHD_%s", Version.getSpecification()); |
37 private String softwareversion = String.format("Ganymed_SSHD_%s", Version.getSpecification()); | 37 |
38 | 38 private final ServerConnectionState state = new ServerConnectionState(this); |
39 private final ServerConnectionState state = new ServerConnectionState(this); | 39 |
40 | 40 /** |
41 /** | 41 * Creates a new <code>ServerConnection</code> that will communicate |
42 * Creates a new <code>ServerConnection</code> that will communicate | 42 * with the client over the given <code>Socket</code>. |
43 * with the client over the given <code>Socket</code>. | 43 * <p> |
44 * <p> | 44 * Note: you need to call {@link #connect()} or {@link #connect(int)} to |
45 * Note: you need to call {@link #connect()} or {@link #connect(int)} to | 45 * perform the initial handshake and establish the encrypted communication. |
46 * perform the initial handshake and establish the encrypted communication. | 46 * |
47 * | 47 * @see #connect(int) |
48 * @see #connect(int) | 48 * |
49 * | 49 * @param s The socket |
50 * @param s The socket | 50 */ |
51 */ | 51 public ServerConnection(Socket s) { |
52 public ServerConnection(Socket s) | 52 this(s, null, null, null); |
53 { | 53 } |
54 this(s, null, null, null); | |
55 } | |
56 | 54 |
57 public ServerConnection(Socket s, String softwareversion) { | 55 public ServerConnection(Socket s, String softwareversion) { |
58 this(s, null, null, null); | 56 this(s, null, null, null); |
59 this.softwareversion = softwareversion; | 57 this.softwareversion = softwareversion; |
60 } | 58 } |
61 | 59 |
62 /** | 60 /** |
63 * Creates a new <code>ServerConnection</code> that will communicate | 61 * Creates a new <code>ServerConnection</code> that will communicate |
64 * with the client over the given <code>Socket</code>. | 62 * with the client over the given <code>Socket</code>. |
65 * <p> | 63 * <p> |
66 * Note: you need to call {@link #connect()} or {@link #connect(int)} to | 64 * Note: you need to call {@link #connect()} or {@link #connect(int)} to |
67 * perform the initial handshake and establish the encrypted communication. | 65 * perform the initial handshake and establish the encrypted communication. |
68 * <p> | 66 * <p> |
69 * Please read the javadoc for the {@link #connect(int)} method. | 67 * Please read the javadoc for the {@link #connect(int)} method. |
70 * | 68 * |
71 * @see #connect(int) | 69 * @see #connect(int) |
72 * | 70 * |
73 * @param s The socket | 71 * @param s The socket |
74 * @param dsa_key The DSA hostkey, may be <code>NULL</code> | 72 * @param dsa_key The DSA hostkey, may be <code>NULL</code> |
75 * @param rsa_key The RSA hostkey, may be <code>NULL</code> | 73 * @param rsa_key The RSA hostkey, may be <code>NULL</code> |
76 * @param ec_key The EC hostkey, may be <code>NULL</code> | 74 * @param ec_key The EC hostkey, may be <code>NULL</code> |
77 */ | 75 */ |
78 public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) | 76 public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) { |
79 { | 77 state.s = s; |
80 state.s = s; | 78 state.softwareversion = softwareversion; |
81 state.softwareversion = softwareversion; | 79 state.next_dsa_key = dsa_key; |
82 state.next_dsa_key = dsa_key; | 80 state.next_rsa_key = rsa_key; |
83 state.next_rsa_key = rsa_key; | 81 state.next_ec_key = ec_key; |
84 state.next_ec_key = ec_key; | 82 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
85 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | 83 } |
86 } | 84 |
87 | 85 /** |
88 /** | 86 * Establish the connection and block until the first handshake has completed. |
89 * Establish the connection and block until the first handshake has completed. | 87 * <p> |
90 * <p> | 88 * Note: this is a wrapper that calls <code>connect(0)</code> (i.e., connect with no timeout). |
91 * Note: this is a wrapper that calls <code>connect(0)</code> (i.e., connect with no timeout). | 89 * <p> |
92 * <p> | 90 * Please read the javadoc for the {@link #connect(int)} method. |
93 * Please read the javadoc for the {@link #connect(int)} method. | 91 * |
94 * | 92 * @see #connect(int) |
95 * @see #connect(int) | 93 * |
96 * | 94 * @throws IOException |
97 * @throws IOException | 95 */ |
98 */ | 96 |
99 public synchronized void connect() throws IOException | 97 public synchronized void connect() throws IOException { |
100 { | 98 connect(0); |
101 connect(0); | 99 } |
102 } | 100 |
103 | 101 /** |
104 /** | 102 * Establish the connection and block until the first handshake has completed. |
105 * Establish the connection and block until the first handshake has completed. | 103 * <p> |
106 * <p> | 104 * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. |
107 * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. | 105 * <p> |
108 * <p> | 106 * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) |
109 * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) | 107 * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). |
110 * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). | 108 * |
111 * | 109 * @see #setPEMHostKey(char[], String) |
112 * @see #setPEMHostKey(char[], String) | 110 * @see #setPEMHostKey(File, String) |
113 * @see #setPEMHostKey(File, String) | 111 * @see #setRsaHostKey(RSAPrivateKey) |
114 * @see #setRsaHostKey(RSAPrivateKey) | 112 * @see #setDsaHostKey(DSAPrivateKey) |
115 * @see #setDsaHostKey(DSAPrivateKey) | 113 * |
116 * | 114 * @param timeout_milliseconds Timeout in milliseconds, <code>0</code> means no timeout. |
117 * @param timeout_milliseconds Timeout in milliseconds, <code>0</code> means no timeout. | 115 * @throws IOException |
118 * @throws IOException | 116 */ |
119 */ | 117 |
120 public synchronized void connect(int timeout_milliseconds) throws IOException | 118 public synchronized void connect(int timeout_milliseconds) throws IOException { |
121 { | 119 synchronized (state) { |
122 synchronized (state) | 120 if (state.cb_conn == null) |
123 { | 121 throw new IllegalStateException("The callback for connection events has not been set."); |
124 if (state.cb_conn == null) | 122 |
125 throw new IllegalStateException("The callback for connection events has not been set."); | 123 if (state.cb_auth == null) |
126 | 124 throw new IllegalStateException("The callback for authentication events has not been set."); |
127 if (state.cb_auth == null) | 125 |
128 throw new IllegalStateException("The callback for authentication events has not been set."); | 126 if (state.tm != null) |
129 | 127 throw new IllegalStateException("The initial handshake has already been started."); |
130 if (state.tm != null) | 128 |
131 throw new IllegalStateException("The initial handshake has already been started."); | 129 if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) |
132 | 130 throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); |
133 if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) | 131 |
134 throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); | 132 state.tm = new ServerTransportManager(state.s); |
135 | 133 } |
136 state.tm = new ServerTransportManager(state.s); | 134 |
137 } | 135 state.tm.connect(state); |
138 | 136 /* Wait until first KEX has finished */ |
139 state.tm.connect(state); | 137 state.tm.getConnectionInfo(1); |
140 | 138 } |
141 /* Wait until first KEX has finished */ | 139 |
142 | 140 /** |
143 state.tm.getConnectionInfo(1); | 141 * Retrieve the underlying socket. |
144 } | 142 * |
145 | 143 * @return the socket that has been passed to the constructor. |
146 /** | 144 */ |
147 * Retrieve the underlying socket. | 145 public Socket getSocket() { |
148 * | 146 return state.s; |
149 * @return the socket that has been passed to the constructor. | 147 } |
150 */ | 148 |
151 public Socket getSocket() | 149 /** |
152 { | 150 * Force an asynchronous key re-exchange (the call does not block). The |
153 return state.s; | 151 * latest values set for MAC, Cipher and DH group exchange parameters will |
154 } | 152 * be used. If a key exchange is currently in progress, then this method has |
155 | 153 * the only effect that the so far specified parameters will be used for the |
156 /** | 154 * next (client driven) key exchange. You may call this method only after |
157 * Force an asynchronous key re-exchange (the call does not block). The | 155 * the initial key exchange has been established. |
158 * latest values set for MAC, Cipher and DH group exchange parameters will | 156 * <p> |
159 * be used. If a key exchange is currently in progress, then this method has | 157 * Note: This implementation will never start automatically a key exchange (other than the initial one) |
160 * the only effect that the so far specified parameters will be used for the | 158 * unless you or the connected SSH-2 client ask for it. |
161 * next (client driven) key exchange. You may call this method only after | 159 * |
162 * the initial key exchange has been established. | 160 * @throws IOException |
163 * <p> | 161 * In case of any failure behind the scenes. |
164 * Note: This implementation will never start automatically a key exchange (other than the initial one) | 162 */ |
165 * unless you or the connected SSH-2 client ask for it. | 163 |
166 * | 164 public synchronized void forceKeyExchange() throws IOException { |
167 * @throws IOException | 165 synchronized (state) { |
168 * In case of any failure behind the scenes. | 166 if (state.tm == null) |
169 */ | 167 throw new IllegalStateException( |
170 public synchronized void forceKeyExchange() throws IOException | 168 "Cannot force another key exchange, you need to start the key exchange first."); |
171 { | 169 |
172 synchronized (state) | 170 state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
173 { | 171 } |
174 if (state.tm == null) | 172 } |
175 throw new IllegalStateException( | 173 |
176 "Cannot force another key exchange, you need to start the key exchange first."); | 174 /** |
177 | 175 * Returns a {@link ConnectionInfo} object containing the details of |
178 state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | 176 * the connection. May be called as soon as the first key exchange has been |
179 } | 177 * started. The method blocks in case the first key exchange has not been completed. |
180 } | 178 * <p> |
181 | 179 * Note: upon return of this method, authentication may still be pending. |
182 /** | 180 * |
183 * Returns a {@link ConnectionInfo} object containing the details of | 181 * @return A {@link ConnectionInfo} object. |
184 * the connection. May be called as soon as the first key exchange has been | 182 * @throws IOException |
185 * started. The method blocks in case the first key exchange has not been completed. | 183 * In case of any failure behind the scenes; e.g., first key exchange was aborted. |
186 * <p> | 184 */ |
187 * Note: upon return of this method, authentication may still be pending. | 185 |
188 * | 186 public synchronized ConnectionInfo getConnectionInfo() throws IOException { |
189 * @return A {@link ConnectionInfo} object. | 187 synchronized (state) { |
190 * @throws IOException | 188 if (state.tm == null) |
191 * In case of any failure behind the scenes; e.g., first key exchange was aborted. | 189 throw new IllegalStateException( |
192 */ | 190 "Cannot get details of connection, you need to start the key exchange first."); |
193 public synchronized ConnectionInfo getConnectionInfo() throws IOException | 191 } |
194 { | 192 |
195 synchronized (state) | 193 return state.tm.getConnectionInfo(1); |
196 { | 194 } |
197 if (state.tm == null) | 195 |
198 throw new IllegalStateException( | 196 /** |
199 "Cannot get details of connection, you need to start the key exchange first."); | 197 * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with |
200 } | 198 * the client. |
201 | 199 * <p> |
202 return state.tm.getConnectionInfo(1); | 200 * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will |
203 } | 201 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the |
204 | 202 * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. |
205 /** | 203 * |
206 * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with | 204 * @param dsa_hostkey |
207 * the client. | 205 */ |
208 * <p> | 206 |
209 * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will | 207 public synchronized void setDsaHostKey(KeyPair dsa_hostkey) { |
210 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the | 208 synchronized (state) { |
211 * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. | 209 if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) |
212 * | 210 throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); |
213 * @param dsa_hostkey | 211 |
214 */ | 212 state.next_dsa_key = dsa_hostkey; |
215 public synchronized void setDsaHostKey(KeyPair dsa_hostkey) | 213 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
216 { | 214 } |
217 synchronized (state) | 215 } |
218 { | 216 |
219 if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) | 217 /** |
220 throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); | 218 * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with |
221 | 219 * the client. |
222 state.next_dsa_key = dsa_hostkey; | 220 * <p> |
223 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | 221 * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will |
224 } | 222 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the |
225 } | 223 * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. |
226 | 224 * |
227 /** | 225 * @param rsa_hostkey |
228 * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with | 226 */ |
229 * the client. | 227 |
230 * <p> | 228 public synchronized void setRsaHostKey(KeyPair rsa_hostkey) { |
231 * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will | 229 synchronized (state) { |
232 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the | 230 if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) |
233 * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. | 231 throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); |
234 * | 232 |
235 * @param rsa_hostkey | 233 state.next_rsa_key = rsa_hostkey; |
236 */ | 234 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
237 public synchronized void setRsaHostKey(KeyPair rsa_hostkey) | 235 } |
238 { | 236 } |
239 synchronized (state) | 237 |
240 { | 238 /** |
241 if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) | 239 * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with |
242 throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); | 240 * the client. |
243 | 241 * <p> |
244 state.next_rsa_key = rsa_hostkey; | 242 * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will |
245 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | 243 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the |
246 } | 244 * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. |
247 } | 245 * |
248 | 246 * @param rsa_hostkey |
249 /** | 247 */ |
250 * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with | 248 |
251 * the client. | 249 public synchronized void setEcHostKey(KeyPair ec_hostkey) { |
252 * <p> | 250 synchronized (state) { |
253 * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will | 251 if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) |
254 * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the | 252 throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); |
255 * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. | 253 |
256 * | 254 state.next_ec_key = ec_hostkey; |
257 * @param rsa_hostkey | 255 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); |
258 */ | 256 } |
259 public synchronized void setEcHostKey(KeyPair ec_hostkey) | 257 } |
260 { | 258 |
261 synchronized (state) | 259 /** |
262 { | 260 * Utility method that loads a PEM based hostkey (either RSA or DSA based) and |
263 if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) | 261 * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. |
264 throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); | 262 * |
265 | 263 * @param pemdata The PEM data |
266 state.next_ec_key = ec_hostkey; | 264 * @param password Password, may be null in case the PEM data is not password protected |
267 fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); | 265 * @throws IOException In case of any error. |
268 } | 266 */ |
269 } | 267 public void setPEMHostKey(char[] pemdata, String password) throws IOException { |
270 | 268 KeyPair pair = PEMDecoder.decode(pemdata, password); |
271 /** | |
272 * Utility method that loads a PEM based hostkey (either RSA or DSA based) and | |
273 * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. | |
274 * | |
275 * @param pemdata The PEM data | |
276 * @param password Password, may be null in case the PEM data is not password protected | |
277 * @throws IOException In case of any error. | |
278 */ | |
279 public void setPEMHostKey(char[] pemdata, String password) throws IOException | |
280 { | |
281 KeyPair pair = PEMDecoder.decode(pemdata, password); | |
282 PrivateKey key = pair.getPrivate(); | 269 PrivateKey key = pair.getPrivate(); |
283 | 270 |
284 if (key instanceof DSAPrivateKey) setDsaHostKey(pair); | 271 if (key instanceof DSAPrivateKey) setDsaHostKey(pair); |
285 | 272 |
286 if (key instanceof RSAPrivateKey) setRsaHostKey(pair); | 273 if (key instanceof RSAPrivateKey) setRsaHostKey(pair); |
287 | 274 |
288 if (key instanceof ECPrivateKey) setEcHostKey(pair); | 275 if (key instanceof ECPrivateKey) setEcHostKey(pair); |
289 } | 276 } |
290 | 277 |
291 /** | 278 /** |
292 * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and | 279 * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and |
293 * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. | 280 * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. |
294 * | 281 * |
295 * @param pemFile The PEM file | 282 * @param pemFile The PEM file |
296 * @param password Password, may be null in case the PEM file is not password protected | 283 * @param password Password, may be null in case the PEM file is not password protected |
297 * @throws IOException | 284 * @throws IOException |
298 */ | 285 */ |
299 public void setPEMHostKey(File pemFile, String password) throws IOException | 286 public void setPEMHostKey(File pemFile, String password) throws IOException { |
300 { | 287 if (pemFile == null) |
301 if (pemFile == null) | 288 throw new IllegalArgumentException("pemfile argument is null"); |
302 throw new IllegalArgumentException("pemfile argument is null"); | 289 |
303 | 290 char[] buff = new char[256]; |
304 char[] buff = new char[256]; | 291 CharArrayWriter cw = new CharArrayWriter(); |
305 | 292 FileReader fr = new FileReader(pemFile); |
306 CharArrayWriter cw = new CharArrayWriter(); | 293 |
307 | 294 while (true) { |
308 FileReader fr = new FileReader(pemFile); | 295 int len = fr.read(buff); |
309 | 296 |
310 while (true) | 297 if (len < 0) |
311 { | 298 break; |
312 int len = fr.read(buff); | 299 |
313 if (len < 0) | 300 cw.write(buff, 0, len); |
314 break; | 301 } |
315 cw.write(buff, 0, len); | 302 |
316 } | 303 fr.close(); |
317 | 304 setPEMHostKey(cw.toCharArray(), password); |
318 fr.close(); | 305 } |
319 | 306 |
320 setPEMHostKey(cw.toCharArray(), password); | 307 private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) { |
321 } | |
322 | |
323 private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) | |
324 { | |
325 List<String> algos = new ArrayList<String>(); | 308 List<String> algos = new ArrayList<String>(); |
326 if (next_ec_key != null) algos.add("ecdsa-sha2-nistp521"); | 309 |
327 if (next_ec_key != null) algos.add("ecdsa-sha2-nistp384"); | 310 if (next_ec_key != null) algos.add("ecdsa-sha2-nistp521"); |
328 if (next_ec_key != null) algos.add("ecdsa-sha2-nistp256"); | 311 |
329 if (next_dsa_key != null) algos.add("ssh-dss"); | 312 if (next_ec_key != null) algos.add("ecdsa-sha2-nistp384"); |
330 if (next_rsa_key != null) algos.add("ssh-rsa"); | 313 |
331 next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; | 314 if (next_ec_key != null) algos.add("ecdsa-sha2-nistp256"); |
315 | |
316 if (next_dsa_key != null) algos.add("ssh-dss"); | |
317 | |
318 if (next_rsa_key != null) algos.add("ssh-rsa"); | |
319 | |
320 next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; | |
332 algos.toArray(next_cryptoWishList.serverHostKeyAlgorithms); | 321 algos.toArray(next_cryptoWishList.serverHostKeyAlgorithms); |
333 } | 322 } |
334 | 323 |
335 /** | 324 /** |
336 * Callback interface with methods that will be called upon events | 325 * Callback interface with methods that will be called upon events |
337 * generated by the client (e.g., client opens a new Session which results in a <code>ServerSession</code>). | 326 * generated by the client (e.g., client opens a new Session which results in a <code>ServerSession</code>). |
338 * <p> | 327 * <p> |
339 * Note: This must be set before the first handshake. | 328 * Note: This must be set before the first handshake. |
340 * | 329 * |
341 * @param cb The callback implementation | 330 * @param cb The callback implementation |
342 */ | 331 */ |
343 public synchronized void setServerConnectionCallback(ServerConnectionCallback cb) | 332 |
344 { | 333 public synchronized void setServerConnectionCallback(ServerConnectionCallback cb) { |
345 synchronized (state) | 334 synchronized (state) { |
346 { | 335 state.cb_conn = cb; |
347 state.cb_conn = cb; | 336 } |
348 } | 337 } |
349 } | 338 |
350 | 339 /** |
351 /** | 340 * Callback interface with methods that will be called upon authentication events. |
352 * Callback interface with methods that will be called upon authentication events. | 341 * <p> |
353 * <p> | 342 * Note: This must be set before the first handshake. |
354 * Note: This must be set before the first handshake. | 343 * |
355 * | 344 * @param cb The callback implementation |
356 * @param cb The callback implementation | 345 */ |
357 */ | 346 |
358 public synchronized void setAuthenticationCallback(ServerAuthenticationCallback cb) | 347 public synchronized void setAuthenticationCallback(ServerAuthenticationCallback cb) { |
359 { | 348 synchronized (state) { |
360 synchronized (state) | 349 state.cb_auth = cb; |
361 { | 350 } |
362 state.cb_auth = cb; | 351 } |
363 } | 352 |
364 } | 353 /** |
365 | 354 * Close the connection to the SSH-2 server. All assigned sessions will be |
366 /** | 355 * closed, too. Can be called at any time. Don't forget to call this once |
367 * Close the connection to the SSH-2 server. All assigned sessions will be | 356 * you don't need a connection anymore - otherwise the receiver thread may |
368 * closed, too. Can be called at any time. Don't forget to call this once | 357 * run forever. |
369 * you don't need a connection anymore - otherwise the receiver thread may | 358 */ |
370 * run forever. | 359 public void close() { |
371 */ | 360 synchronized (state) { |
372 public void close() | 361 if (state.cm != null) |
373 { | 362 state.cm.closeAllChannels(); |
374 synchronized (state) | 363 |
375 { | 364 if (state.tm != null) { |
376 if (state.cm != null) | 365 state.tm.close(); |
377 state.cm.closeAllChannels(); | 366 } |
378 | 367 } |
379 if (state.tm != null) | 368 } |
380 { | 369 |
381 state.tm.close(); | 370 public void close(IOException t) { |
382 } | 371 synchronized (state) { |
383 } | 372 if (state.cm != null) |
384 } | 373 state.cm.closeAllChannels(); |
385 | 374 |
386 public void close(IOException t) | 375 if (state.tm != null) { |
387 { | 376 state.tm.close(t); |
388 synchronized (state) | 377 } |
389 { | 378 } |
390 if (state.cm != null) | 379 } |
391 state.cm.closeAllChannels(); | |
392 | |
393 if (state.tm != null) | |
394 { | |
395 state.tm.close(t); | |
396 } | |
397 } | |
398 } | |
399 } | 380 } |