1 package org
.argeo
.cms
.ssh
;
3 import java
.io
.Console
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
7 import java
.net
.URISyntaxException
;
8 import java
.util
.Arrays
;
9 import java
.util
.HashSet
;
10 import java
.util
.Scanner
;
13 import org
.apache
.sshd
.client
.SshClient
;
14 import org
.apache
.sshd
.client
.channel
.ClientChannel
;
15 import org
.apache
.sshd
.client
.channel
.ClientChannelEvent
;
16 import org
.apache
.sshd
.client
.future
.ConnectFuture
;
17 import org
.apache
.sshd
.client
.session
.ClientSession
;
18 import org
.apache
.sshd
.common
.util
.io
.input
.NoCloseInputStream
;
19 import org
.apache
.sshd
.common
.util
.io
.output
.NoCloseOutputStream
;
20 import org
.apache
.sshd
.sftp
.client
.fs
.SftpFileSystemProvider
;
21 import org
.argeo
.api
.cms
.CmsLog
;
23 public abstract class AbstractSsh
{
24 private final static CmsLog log
= CmsLog
.getLog(AbstractSsh
.class);
26 private SshClient sshClient
;
27 private 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 authenticate(System
.in
);
58 public void authenticate(InputStream in
) {
59 if (sshKeyPair
!= null) {
60 session
.addPublicKeyIdentity(sshKeyPair
.asKeyPair());
63 if (!passwordSet
&& in
!= null) {
65 Console console
= System
.console();
66 if (console
== null) {// IDE
67 System
.out
.print("Password: ");
68 try (Scanner s
= new Scanner(in
)) {
72 console
.printf("Password: ");
73 char[] pwd
= console
.readPassword();
74 password
= new String(pwd
);
75 Arrays
.fill(pwd
, ' ');
77 session
.addPasswordIdentity(password
);
84 public void verifyAuth() {
86 session
.auth().verify(1000l);
87 } catch (IOException e
) {
88 throw new IllegalStateException("Cannot verify auth", e
);
92 public static char[] readPassword() {
93 Console console
= System
.console();
94 if (console
== null) {// IDE
95 System
.out
.print("Password: ");
96 try (Scanner s
= new Scanner(System
.in
)) {
97 String password
= s
.next();
98 return password
.toCharArray();
101 console
.printf("Password: ");
102 char[] pwd
= console
.readPassword();
107 void addPassword(String password
) {
108 session
.addPasswordIdentity(password
);
111 void loadKey(String password
) {
112 loadKey(password
, System
.getProperty("user.home") + "/.ssh/id_rsa");
115 void loadKey(String password
, String keyPath
) {
117 // KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
118 // FilePasswordProvider.of(password));
119 // session.addPublicKeyIdentity(keyPair);
120 // } catch (IOException | GeneralSecurityException e) {
121 // throw new IllegalStateException(e);
125 void openSession(URI uri
) {
126 openSession(uri
.getUserInfo(), uri
.getHost(), uri
.getPort() > 0 ? uri
.getPort() : null);
129 void openSession(String login
, String host
, Integer port
) {
131 throw new IllegalStateException("Session is already open");
138 login
= System
.getProperty("user.name");
139 String password
= null;
140 int sepIndex
= login
.indexOf(':');
142 if (sepIndex
+ 1 < login
.length()) {
143 password
= login
.substring(sepIndex
+ 1);
144 login
= login
.substring(0, sepIndex
);
146 throw new IllegalArgumentException("Illegal authority: " + login
);
149 ConnectFuture connectFuture
= getSshClient().connect(login
, host
, port
);
150 connectFuture
.await();
151 ClientSession session
= connectFuture
.getSession();
152 if (password
!= null) {
153 session
.addPasswordIdentity(password
);
156 this.session
= session
;
157 } catch (IOException e
) {
158 throw new IllegalStateException("Cannot connect to " + host
+ ":" + port
);
162 public void closeSession() {
164 throw new IllegalStateException("No session is open");
167 } catch (IOException e
) {
174 ClientSession
getSession() {
178 public void setSshKeyPair(SshKeyPair sshKeyPair
) {
179 this.sshKeyPair
= sshKeyPair
;
182 public static void openShell(AbstractSsh ssh
) {
183 openShell(ssh
.getSession());
186 public static void openShell(ClientSession session
) {
187 try (ClientChannel channel
= session
.createChannel(ClientChannel
.CHANNEL_SHELL
)) {
188 channel
.setIn(new NoCloseInputStream(System
.in
));
189 channel
.setOut(new NoCloseOutputStream(System
.out
));
190 channel
.setErr(new NoCloseOutputStream(System
.err
));
193 Set
<ClientChannelEvent
> events
= new HashSet
<>();
194 events
.add(ClientChannelEvent
.CLOSED
);
195 channel
.waitFor(events
, 0);
196 } catch (IOException e
) {
197 // TODO Auto-generated catch block
200 session
.close(false);
204 static URI
toUri(String username
, String host
, int port
) {
206 if (username
== null)
208 return new URI("ssh://" + username
+ "@" + host
+ ":" + port
);
209 } catch (URISyntaxException e
) {
210 throw new IllegalArgumentException("Cannot generate SSH URI to " + host
+ ":" + port
+ " for " + username
,