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 public 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 public 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
;
54 public void authenticate() {
55 if (sshKeyPair
!= null) {
56 session
.addPublicKeyIdentity(sshKeyPair
.asKeyPair());
61 Console console
= System
.console();
62 if (console
== null) {// IDE
63 System
.out
.print("Password: ");
64 try (Scanner s
= new Scanner(System
.in
)) {
68 console
.printf("Password: ");
69 char[] pwd
= console
.readPassword();
70 password
= new String(pwd
);
71 Arrays
.fill(pwd
, ' ');
73 session
.addPasswordIdentity(password
);
80 public void verifyAuth() {
82 session
.auth().verify(1000l);
83 } catch (IOException e
) {
84 throw new IllegalStateException("Cannot verify auth", e
);
88 public static char[] readPassword() {
89 Console console
= System
.console();
90 if (console
== null) {// IDE
91 System
.out
.print("Password: ");
92 try (Scanner s
= new Scanner(System
.in
)) {
93 String password
= s
.next();
94 return password
.toCharArray();
97 console
.printf("Password: ");
98 char[] pwd
= console
.readPassword();
103 void addPassword(String password
) {
104 session
.addPasswordIdentity(password
);
107 void loadKey(String password
) {
108 loadKey(password
, System
.getProperty("user.home") + "/.ssh/id_rsa");
111 void loadKey(String password
, String keyPath
) {
113 // KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
114 // FilePasswordProvider.of(password));
115 // session.addPublicKeyIdentity(keyPair);
116 // } catch (IOException | GeneralSecurityException e) {
117 // throw new IllegalStateException(e);
121 void openSession(URI uri
) {
122 openSession(uri
.getUserInfo(), uri
.getHost(), uri
.getPort() > 0 ? uri
.getPort() : null);
125 void openSession(String login
, String host
, Integer port
) {
127 throw new IllegalStateException("Session is already open");
134 login
= System
.getProperty("user.name");
135 String password
= null;
136 int sepIndex
= login
.indexOf(':');
138 if (sepIndex
+ 1 < login
.length()) {
139 password
= login
.substring(sepIndex
+ 1);
140 login
= login
.substring(0, sepIndex
);
142 throw new IllegalArgumentException("Illegal authority: " + login
);
145 ConnectFuture connectFuture
= getSshClient().connect(login
, host
, port
);
146 connectFuture
.await();
147 ClientSession session
= connectFuture
.getSession();
148 if (password
!= null) {
149 session
.addPasswordIdentity(password
);
152 this.session
= session
;
153 } catch (IOException e
) {
154 throw new IllegalStateException("Cannot connect to " + host
+ ":" + port
);
158 public void closeSession() {
160 throw new IllegalStateException("No session is open");
163 } catch (IOException e
) {
170 ClientSession
getSession() {
174 public void setSshKeyPair(SshKeyPair sshKeyPair
) {
175 this.sshKeyPair
= sshKeyPair
;
178 public static void openShell(AbstractSsh ssh
) {
179 openShell(ssh
.getSession());
182 public static void openShell(ClientSession session
) {
183 try (ClientChannel channel
= session
.createChannel(ClientChannel
.CHANNEL_SHELL
)) {
184 channel
.setIn(new NoCloseInputStream(System
.in
));
185 channel
.setOut(new NoCloseOutputStream(System
.out
));
186 channel
.setErr(new NoCloseOutputStream(System
.err
));
189 Set
<ClientChannelEvent
> events
= new HashSet
<>();
190 events
.add(ClientChannelEvent
.CLOSED
);
191 channel
.waitFor(events
, 0);
192 } catch (IOException e
) {
193 // TODO Auto-generated catch block
196 session
.close(false);
200 static URI
toUri(String username
, String host
, int port
) {
202 if (username
== null)
204 return new URI("ssh://" + username
+ "@" + host
+ ":" + port
);
205 } catch (URISyntaxException e
) {
206 throw new IllegalArgumentException("Cannot generate SSH URI to " + host
+ ":" + port
+ " for " + username
,