]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.lib.sshd/src/org/argeo/cms/ssh/AbstractSsh.java
Merge tag 'v2.3.17' into testing
[lgpl/argeo-commons.git] / org.argeo.cms.lib.sshd / src / org / argeo / cms / ssh / AbstractSsh.java
1 package org.argeo.cms.ssh;
2
3 import java.io.Console;
4 import java.io.IOException;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.util.Arrays;
8 import java.util.HashSet;
9 import java.util.Scanner;
10 import java.util.Set;
11
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;
21
22 public abstract class AbstractSsh {
23 private final static CmsLog log = CmsLog.getLog(AbstractSsh.class);
24
25 private SshClient sshClient;
26 private SftpFileSystemProvider sftpFileSystemProvider;
27
28 private boolean passwordSet = false;
29 private ClientSession session;
30
31 private SshKeyPair sshKeyPair;
32
33 public synchronized SshClient getSshClient() {
34 if (sshClient == null) {
35 long begin = System.currentTimeMillis();
36 sshClient = SshClient.setUpDefaultClient();
37 sshClient.start();
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"));
42 }
43 return sshClient;
44 }
45
46 synchronized SftpFileSystemProvider getSftpFileSystemProvider() {
47 if (sftpFileSystemProvider == null) {
48 sftpFileSystemProvider = new SftpFileSystemProvider(sshClient);
49 }
50 return sftpFileSystemProvider;
51 }
52
53 public void authenticate() {
54 if (sshKeyPair != null) {
55 session.addPublicKeyIdentity(sshKeyPair.asKeyPair());
56 } else {
57
58 if (!passwordSet) {
59 String password;
60 Console console = System.console();
61 if (console == null) {// IDE
62 System.out.print("Password: ");
63 try (Scanner s = new Scanner(System.in)) {
64 password = s.next();
65 }
66 } else {
67 console.printf("Password: ");
68 char[] pwd = console.readPassword();
69 password = new String(pwd);
70 Arrays.fill(pwd, ' ');
71 }
72 session.addPasswordIdentity(password);
73 passwordSet = true;
74 }
75 }
76 verifyAuth();
77 }
78
79 public void verifyAuth() {
80 try {
81 session.auth().verify(1000l);
82 } catch (IOException e) {
83 throw new IllegalStateException("Cannot verify auth", e);
84 }
85 }
86
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();
94 }
95 } else {
96 console.printf("Password: ");
97 char[] pwd = console.readPassword();
98 return pwd;
99 }
100 }
101
102 void addPassword(String password) {
103 session.addPasswordIdentity(password);
104 }
105
106 void loadKey(String password) {
107 loadKey(password, System.getProperty("user.home") + "/.ssh/id_rsa");
108 }
109
110 void loadKey(String password, String keyPath) {
111 // try {
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);
117 // }
118 }
119
120 void openSession(URI uri) {
121 openSession(uri.getUserInfo(), uri.getHost(), uri.getPort() > 0 ? uri.getPort() : null);
122 }
123
124 void openSession(String login, String host, Integer port) {
125 if (session != null)
126 throw new IllegalStateException("Session is already open");
127
128 if (host == null)
129 host = "localhost";
130 if (port == null)
131 port = 22;
132 if (login == null)
133 login = System.getProperty("user.name");
134 String password = null;
135 int sepIndex = login.indexOf(':');
136 if (sepIndex > 0)
137 if (sepIndex + 1 < login.length()) {
138 password = login.substring(sepIndex + 1);
139 login = login.substring(0, sepIndex);
140 } else {
141 throw new IllegalArgumentException("Illegal authority: " + login);
142 }
143 try {
144 ConnectFuture connectFuture = getSshClient().connect(login, host, port);
145 connectFuture.await();
146 ClientSession session = connectFuture.getSession();
147 if (password != null) {
148 session.addPasswordIdentity(password);
149 passwordSet = true;
150 }
151 this.session = session;
152 } catch (IOException e) {
153 throw new IllegalStateException("Cannot connect to " + host + ":" + port);
154 }
155 }
156
157 public void closeSession() {
158 if (session == null)
159 throw new IllegalStateException("No session is open");
160 try {
161 session.close();
162 } catch (IOException e) {
163 e.printStackTrace();
164 } finally {
165 session = null;
166 }
167 }
168
169 ClientSession getSession() {
170 return session;
171 }
172
173 public void setSshKeyPair(SshKeyPair sshKeyPair) {
174 this.sshKeyPair = sshKeyPair;
175 }
176
177 public static void openShell(AbstractSsh ssh) {
178 openShell(ssh.getSession());
179 }
180
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));
186 channel.open();
187
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
193 e.printStackTrace();
194 } finally {
195 session.close(false);
196 }
197 }
198
199 static URI toUri(String username, String host, int port) {
200 try {
201 if (username == null)
202 username = "root";
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,
206 e);
207 }
208 }
209
210 }