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 public abstract class AbstractSsh
{
23 private final static CmsLog log
= CmsLog
.getLog(AbstractSsh
.class);
25 private SshClient sshClient
;
26 private SftpFileSystemProvider sftpFileSystemProvider
;
28 private boolean passwordSet
= false;
29 private ClientSession session
;
31 private SshKeyPair sshKeyPair
;
33 public synchronized SshClient
getSshClient() {
34 if (sshClient
== null) {
35 long begin
= System
.currentTimeMillis();
36 sshClient
= SshClient
.setUpDefaultClient();
38 long duration
= System
.currentTimeMillis() - begin
;
39 if (log
.isDebugEnabled())
40 log
.debug("SSH client started in " + duration
+ " ms");
41 Runtime
.getRuntime().addShutdownHook(new Thread(() -> sshClient
.stop(), "Stop SSH client"));
46 synchronized SftpFileSystemProvider
getSftpFileSystemProvider() {
47 if (sftpFileSystemProvider
== null) {
48 sftpFileSystemProvider
= new SftpFileSystemProvider(sshClient
);
50 return sftpFileSystemProvider
;
53 public void authenticate() {
54 if (sshKeyPair
!= null) {
55 session
.addPublicKeyIdentity(sshKeyPair
.asKeyPair());
60 Console console
= System
.console();
61 if (console
== null) {// IDE
62 System
.out
.print("Password: ");
63 try (Scanner s
= new Scanner(System
.in
)) {
67 console
.printf("Password: ");
68 char[] pwd
= console
.readPassword();
69 password
= new String(pwd
);
70 Arrays
.fill(pwd
, ' ');
72 session
.addPasswordIdentity(password
);
79 public void verifyAuth() {
81 session
.auth().verify(1000l);
82 } catch (IOException e
) {
83 throw new IllegalStateException("Cannot verify auth", e
);
87 public static char[] readPassword() {
88 Console console
= System
.console();
89 if (console
== null) {// IDE
90 System
.out
.print("Password: ");
91 try (Scanner s
= new Scanner(System
.in
)) {
92 String password
= s
.next();
93 return password
.toCharArray();
96 console
.printf("Password: ");
97 char[] pwd
= console
.readPassword();
102 void addPassword(String password
) {
103 session
.addPasswordIdentity(password
);
106 void loadKey(String password
) {
107 loadKey(password
, System
.getProperty("user.home") + "/.ssh/id_rsa");
110 void loadKey(String password
, String keyPath
) {
112 // KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
113 // FilePasswordProvider.of(password));
114 // session.addPublicKeyIdentity(keyPair);
115 // } catch (IOException | GeneralSecurityException e) {
116 // throw new IllegalStateException(e);
120 void openSession(URI uri
) {
121 openSession(uri
.getUserInfo(), uri
.getHost(), uri
.getPort() > 0 ? uri
.getPort() : null);
124 void openSession(String login
, String host
, Integer port
) {
126 throw new IllegalStateException("Session is already open");
133 login
= System
.getProperty("user.name");
134 String password
= null;
135 int sepIndex
= login
.indexOf(':');
137 if (sepIndex
+ 1 < login
.length()) {
138 password
= login
.substring(sepIndex
+ 1);
139 login
= login
.substring(0, sepIndex
);
141 throw new IllegalArgumentException("Illegal authority: " + login
);
144 ConnectFuture connectFuture
= getSshClient().connect(login
, host
, port
);
145 connectFuture
.await();
146 ClientSession session
= connectFuture
.getSession();
147 if (password
!= null) {
148 session
.addPasswordIdentity(password
);
151 this.session
= session
;
152 } catch (IOException e
) {
153 throw new IllegalStateException("Cannot connect to " + host
+ ":" + port
);
157 public void closeSession() {
159 throw new IllegalStateException("No session is open");
162 } catch (IOException e
) {
169 ClientSession
getSession() {
173 public void setSshKeyPair(SshKeyPair sshKeyPair
) {
174 this.sshKeyPair
= sshKeyPair
;
177 public static void openShell(AbstractSsh ssh
) {
178 openShell(ssh
.getSession());
181 public static void openShell(ClientSession session
) {
182 try (ClientChannel channel
= session
.createChannel(ClientChannel
.CHANNEL_SHELL
)) {
183 channel
.setIn(new NoCloseInputStream(System
.in
));
184 channel
.setOut(new NoCloseOutputStream(System
.out
));
185 channel
.setErr(new NoCloseOutputStream(System
.err
));
188 Set
<ClientChannelEvent
> events
= new HashSet
<>();
189 events
.add(ClientChannelEvent
.CLOSED
);
190 channel
.waitFor(events
, 0);
191 } catch (IOException e
) {
192 // TODO Auto-generated catch block
195 session
.close(false);
199 static URI
toUri(String username
, String host
, int port
) {
201 if (username
== null)
203 return new URI("ssh://" + username
+ "@" + host
+ ":" + port
);
204 } catch (URISyntaxException e
) {
205 throw new IllegalArgumentException("Cannot generate SSH URI to " + host
+ ":" + port
+ " for " + username
,