1 package org
.argeo
.cms
.ssh
;
3 import java
.io
.Console
;
4 import java
.io
.IOException
;
6 import java
.net
.URISyntaxException
;
7 import java
.util
.Arrays
;
8 import java
.util
.HashSet
;
9 import java
.util
.Scanner
;
12 import org
.apache
.sshd
.client
.SshClient
;
13 import org
.apache
.sshd
.client
.channel
.ClientChannel
;
14 import org
.apache
.sshd
.client
.channel
.ClientChannelEvent
;
15 import org
.apache
.sshd
.client
.future
.ConnectFuture
;
16 import org
.apache
.sshd
.client
.session
.ClientSession
;
17 import org
.apache
.sshd
.common
.util
.io
.input
.NoCloseInputStream
;
18 import org
.apache
.sshd
.common
.util
.io
.output
.NoCloseOutputStream
;
19 import org
.apache
.sshd
.sftp
.client
.fs
.SftpFileSystemProvider
;
20 import org
.argeo
.api
.cms
.CmsLog
;
22 @SuppressWarnings("restriction")
23 abstract class AbstractSsh
{
24 private final static CmsLog log
= CmsLog
.getLog(AbstractSsh
.class);
26 private static SshClient sshClient
;
27 private static SftpFileSystemProvider sftpFileSystemProvider
;
29 private boolean passwordSet
= false;
30 private ClientSession session
;
32 private SshKeyPair sshKeyPair
;
34 synchronized SshClient
getSshClient() {
35 if (sshClient
== null) {
36 long begin
= System
.currentTimeMillis();
37 sshClient
= SshClient
.setUpDefaultClient();
39 long duration
= System
.currentTimeMillis() - begin
;
40 if (log
.isDebugEnabled())
41 log
.debug("SSH client started in " + duration
+ " ms");
42 Runtime
.getRuntime().addShutdownHook(new Thread(() -> sshClient
.stop(), "Stop SSH client"));
47 synchronized SftpFileSystemProvider
getSftpFileSystemProvider() {
48 if (sftpFileSystemProvider
== null) {
49 sftpFileSystemProvider
= new SftpFileSystemProvider(sshClient
);
51 return sftpFileSystemProvider
;
56 if (sshKeyPair
!= null) {
57 session
.addPublicKeyIdentity(sshKeyPair
.asKeyPair());
62 Console console
= System
.console();
63 if (console
== null) {// IDE
64 System
.out
.print("Password: ");
65 try (Scanner s
= new Scanner(System
.in
)) {
69 console
.printf("Password: ");
70 char[] pwd
= console
.readPassword();
71 password
= new String(pwd
);
72 Arrays
.fill(pwd
, ' ');
74 session
.addPasswordIdentity(password
);
78 session
.auth().verify(1000l);
79 } catch (IOException e
) {
80 throw new IllegalStateException(e
);
84 void addPassword(String password
) {
85 session
.addPasswordIdentity(password
);
88 void loadKey(String password
) {
89 loadKey(password
, System
.getProperty("user.home") + "/.ssh/id_rsa");
92 void loadKey(String password
, String keyPath
) {
94 // KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
95 // FilePasswordProvider.of(password));
96 // session.addPublicKeyIdentity(keyPair);
97 // } catch (IOException | GeneralSecurityException e) {
98 // throw new IllegalStateException(e);
102 void openSession(URI uri
) {
103 openSession(uri
.getUserInfo(), uri
.getHost(), uri
.getPort() > 0 ? uri
.getPort() : null);
106 void openSession(String login
, String host
, Integer port
) {
108 throw new IllegalStateException("Session is already open");
115 login
= System
.getProperty("user.name");
116 String password
= null;
117 int sepIndex
= login
.indexOf(':');
119 if (sepIndex
+ 1 < login
.length()) {
120 password
= login
.substring(sepIndex
+ 1);
121 login
= login
.substring(0, sepIndex
);
123 throw new IllegalArgumentException("Illegal authority: " + login
);
126 ConnectFuture connectFuture
= getSshClient().connect(login
, host
, port
);
127 connectFuture
.await();
128 ClientSession session
= connectFuture
.getSession();
129 if (password
!= null) {
130 session
.addPasswordIdentity(password
);
133 this.session
= session
;
134 } catch (IOException e
) {
135 throw new IllegalStateException("Cannot connect to " + host
+ ":" + port
);
139 void closeSession() {
141 throw new IllegalStateException("No session is open");
144 } catch (IOException e
) {
151 ClientSession
getSession() {
155 public void setSshKeyPair(SshKeyPair sshKeyPair
) {
156 this.sshKeyPair
= sshKeyPair
;
159 public static void openShell(ClientSession session
) {
160 try (ClientChannel channel
= session
.createChannel(ClientChannel
.CHANNEL_SHELL
)) {
161 channel
.setIn(new NoCloseInputStream(System
.in
));
162 channel
.setOut(new NoCloseOutputStream(System
.out
));
163 channel
.setErr(new NoCloseOutputStream(System
.err
));
166 Set
<ClientChannelEvent
> events
= new HashSet
<>();
167 events
.add(ClientChannelEvent
.CLOSED
);
168 channel
.waitFor(events
, 0);
169 } catch (IOException e
) {
170 // TODO Auto-generated catch block
173 session
.close(false);
177 static URI
toUri(String username
, String host
, int port
) {
179 if (username
== null)
181 return new URI("ssh://" + username
+ "@" + host
+ ":" + port
);
182 } catch (URISyntaxException e
) {
183 throw new IllegalArgumentException("Cannot generate SSH URI to " + host
+ ":" + port
+ " for " + username
,