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