This repository has been archived by the owner on Mar 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 55
/
ConnectionManager.java
369 lines (321 loc) · 11.9 KB
/
ConnectionManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
/*******************************************************************************
* Copyright (c) 2019- UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Initial API and implementation and/or initial documentation -
* Jay Jay Billings, Joe Osborn
*******************************************************************************/
package org.eclipse.ice.commands;
import java.util.Arrays;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.HostKeyRepository;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
/**
* This class manages remote connections, and as such interfaces with all
* classes that are associated with remote connections.
*
* @author Joe Osborn
*
*/
public class ConnectionManager {
/**
* A HashMap of available Connections to the ConnectionManager, organized by the
* name of the connection and the connection itself.
*
*/
private HashMap<String, Connection> connectionList = new HashMap<String, Connection>();
/**
* Logger for handling event messages and other information.
*/
private final Logger logger = LoggerFactory.getLogger(ConnectionManager.class);
/**
* A boolean that the user can set to disable ssh StrictHostKeyChecking. Set to
* true by default since this is the most secure way.
*/
private boolean requireStrictHostKeyChecking = true;
/**
* String containing the path to the known hosts directory. Can be set to
* something else if the user has a different default known_host
*/
private String knownHosts = System.getProperty("user.home") + "/.ssh/known_hosts";
/**
* Default Constructor
*/
public ConnectionManager() {
// If the OS is windows, then change the known hosts to be windows style
if (System.getProperty("os.name").toLowerCase().contains("win"))
knownHosts = System.getProperty("user.home") + "\\.ssh\\known_hosts";
}
/**
* Opens, and thus begins, a connection to a remote system. Also adds the
* connection to the list of connections given in
* {@link org.eclipse.ice.commands.ConnectionManager#connectionList}
*
* @param config - ConnectionConfiguration to be used to open connection
* @return Connection - returns connection if successful, null otherwise
*/
public Connection openConnection(ConnectionConfiguration config) throws JSchException {
// The new connection to be opened
Connection newConnection = new Connection(config);
// Create the shell
JSch jsch = new JSch();
jsch.setKnownHosts(knownHosts);
newConnection.setJShellSession(jsch);
logger.info("Trying to open the connection");
// Get the information necessary to open the connection
if (newConnection.getConfiguration() != null) {
ConnectionAuthorizationHandler auth = newConnection.getConfiguration().getAuthorization();
String username = auth.getUsername();
String hostname = auth.getHostname();
// Try go get and open the new session
try {
newConnection.setSession(newConnection.getJShellSession().getSession(username, hostname));
} catch (JSchException e) {
logger.error("Couldn't open session with given username and hostname. Exiting.", e);
throw new JSchException();
}
// Authorize the JSch session with a ConnectionAuthorizationHandler
authorizeSession(newConnection);
// JSch default requests ssh-rsa host checking, but some keys
// request ecdsa-sha2-nistp256. So loop through the available
// host keys that were grabbed from known_hosts and check what
// type the user-given hostname needs
HostKeyRepository hkr = jsch.getHostKeyRepository();
String type = null;
for (HostKey hk : hkr.getHostKey()) {
// If this hostkey contains the hostname that was supplied by
// the user
if (hk.getHost().contains(hostname)) {
type = hk.getType();
// Set the session configuration key type to that hosts type
newConnection.getSession().setConfig("server_host_key", type);
}
}
// If the user wants to disable StrictHostKeyChecking, add it to the
// session configuration
if (!requireStrictHostKeyChecking)
newConnection.getSession().setConfig("StrictHostKeyChecking", "no");
// Connect the session
try {
newConnection.getSession().connect();
} catch (JSchException e) {
logger.error("Couldn't connect to session with given username and/or password/key. Exiting.", e);
throw new JSchException();
}
// Add the connection to the list since it was successfully created
connectionList.put(newConnection.getConfiguration().getName(), newConnection);
logger.info("Connection at " + username + "@" + hostname + " established successfully");
// Upon success, return the opened connection
return newConnection;
}
// If the connectionConfiguration was not properly specified, or an error
// occurred, return null
return null;
}
/**
* This function deals with the new connection authentication. It takes a
* connection that is being opened, and decides what kind of authentication to
* provide JSch depending on whether or not a password exists in the
* ConnectionAuthorizationHandler.
*
* @param connection
* @throws JSchException
*/
private void authorizeSession(Connection connection) throws JSchException {
// Get the authorization information
ConnectionAuthorizationHandler auth = connection.getConfiguration().getAuthorization();
// If a password was set, then try to authenticate with the password
if (auth.getPassword() != null) {
logger.info("Trying to authenticate with a password");
// Get the password first. If authorization is a text file, then
// username and hostname will be set. Otherwise user must set them
char[] pwd = auth.getPassword();
// Pass it to the session
connection.getSession().setPassword(String.valueOf(pwd));
// Erase contents of pwd and fill with null
Arrays.fill(pwd, Character.MIN_VALUE);
// Set the authentication requirements
connection.getSession().setConfig("PreferredAuthentications", "publickey,password");
} else {
logger.info("Trying to authenticate with a key");
// Otherwise try a key authentication
String keyPath = ((KeyPathConnectionAuthorizationHandler) auth).getKeyPath();
connection.getJShellSession().addIdentity(keyPath);
}
return;
}
/**
* This function finds the particular connection requested by name in the list
* of all connections and returns it.
*
* @param connectionName - name of connection to search for
* @return - Connection instance which was requested
*/
public Connection getConnection(String connectionName) {
// Find the hashmap instance, and return it
Connection returnConnection = connectionList.get(connectionName);
if (returnConnection == null) {
logger.warn("Couldn't find an existing connection with the name " + connectionName + ".");
}
return returnConnection;
}
/**
* Closes a particular connection as specified
*
* @param connectionName - name of connection to be closed
*/
public void closeConnection(String connectionName) {
// Get the connection that was passed
Connection connection = getConnection(connectionName);
// Check the channels first
if (connection.getExecChannel() != null) {
if (connection.getExecChannel().isConnected()) {
connection.getExecChannel().disconnect();
}
}
if (connection.getSftpChannel() != null) {
if (connection.getSftpChannel().isConnected()) {
connection.getSftpChannel().disconnect();
}
}
// Disconnect the session. If the session was not connected in the first place,
// it does nothing
connection.getSession().disconnect();
// Confirm with the logger
logger.debug("Connection " + connectionName + "@"
+ connection.getConfiguration().getAuthorization().getHostname() + " closed");
return;
}
/**
* This function closes/disconnects and removes a particular connection from the
* manager's connection list
*
* @param connectionName - name of connection to remove
*/
public void removeConnection(String connectionName) {
// Close the connection first
if (!isConnectionOpen(connectionName))
closeConnection(connectionName);
// Remove it from the list of connections
connectionList.remove(connectionName);
}
/**
* This function removes all particular connections from the connection list
*/
public void removeAllConnections() {
// First make sure all connections have been disconnected
closeAllConnections();
// Remove all of the items from the hashmap
connectionList.clear();
}
/**
* Closes all connections that remain open.
*/
public void closeAllConnections() {
// Iterate over all available connections in the list and disconnect
for (Connection connection : connectionList.values()) {
if (connection.getExecChannel() != null) {
if (connection.getExecChannel().isConnected()) {
connection.getExecChannel().disconnect();
}
}
if (connection.getSftpChannel() != null) {
if (connection.getSftpChannel().isConnected()) {
connection.getSftpChannel().disconnect();
}
}
connection.getSession().disconnect();
}
}
/**
* This function allows adding a user defined connection to the connection
* manager rather than opening a default connection through the function
* {@link ConnectionManager#openConnection(ConnectionConfiguration)}.
*
* @param connection
*/
public void addConnection(Connection connection) {
connectionList.put(connection.getConfiguration().getName(), connection);
}
/**
* This function lists all the connections (and their statuses, i.e. if open or
* not) to the logger, if so desired. Useful for checking the connections and
* their statuses.
*/
public void listAllConnections() {
// Iterate over all available connections
for (String name : connectionList.keySet()) {
// Build a message
String msg = null;
// Get the host for the connection
String host = connectionList.get(name).getConfiguration().getAuthorization().getHostname();
// Get the username for the connection
String username = connectionList.get(name).getConfiguration().getAuthorization().getUsername();
// Check the status. If it is open or closed (i.e. connected or disconnected)
String status = "";
if (isConnectionOpen(name))
status = "open";
else
status = "closed";
// Build a message to send to the logger
msg = "Connection " + name + ": " + username + "@" + host + " is " + status;
logger.info(msg);
}
}
/**
* This function checks whether or not a particular connection is currently
* connected.
*
* @param connectionName - name of connection to check
* @return - boolean indicating whether or not it is connected (true) or not
* (false)
*/
public boolean isConnectionOpen(String connectionName) {
Connection connection = getConnection(connectionName);
return connection.getSession().isConnected();
}
/**
* Setter function for
* {@link org.eclipse.ice.commands.ConnectionManager#connectionList}
*
* @param connections
*/
public void setConnectionList(HashMap<String, Connection> connectionList) {
this.connectionList = connectionList;
}
/**
* Getter function for
* {@link org.eclipse.ice.commands.ConnectionManager#connectionList}
*
* @return
*/
public HashMap<String, Connection> getConnectionList() {
return connectionList;
}
/**
* Setter for whether or not connections should be open with the requirement of
* StrictHostKeyChecking
*
* @param requireStrictHostKeyChecking
*/
public void setRequireStrictHostKeyChecking(boolean requireStrictHostKeyChecking) {
this.requireStrictHostKeyChecking = requireStrictHostKeyChecking;
}
/**
* Setter for known host directory path
* {@link org.eclipse.ice.commands.ConnectionManager#knownHosts}
*
* @param knownHosts
*/
public void setKnownHosts(String knownHosts) {
this.knownHosts = knownHosts;
}
}