]> git.argeo.org Git - gpl/argeo-slc.git/blob - cms/org.argeo.cms.integration/src/org/argeo/ssh/AbstractSsh.java
Improve merging
[gpl/argeo-slc.git] / cms / org.argeo.cms.integration / src / org / argeo / ssh / AbstractSsh.java
1 package org.argeo.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.client.subsystem.sftp.fs.SftpFileSystemProvider;
18 import org.apache.sshd.common.util.io.NoCloseInputStream;
19 import org.apache.sshd.common.util.io.NoCloseOutputStream;
20 import org.argeo.api.cms.CmsLog;
21
22 @SuppressWarnings("restriction")
23 abstract class AbstractSsh {
24 private final static CmsLog log = CmsLog.getLog(AbstractSsh.class);
25
26 private static SshClient sshClient;
27 private static SftpFileSystemProvider sftpFileSystemProvider;
28
29 private boolean passwordSet = false;
30 private ClientSession session;
31
32 private SshKeyPair sshKeyPair;
33
34 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 void authenticate() {
55 try {
56 if (sshKeyPair != null) {
57 session.addPublicKeyIdentity(sshKeyPair.asKeyPair());
58 } else {
59
60 if (!passwordSet) {
61 String password;
62 Console console = System.console();
63 if (console == null) {// IDE
64 System.out.print("Password: ");
65 try (Scanner s = new Scanner(System.in)) {
66 password = s.next();
67 }
68 } else {
69 console.printf("Password: ");
70 char[] pwd = console.readPassword();
71 password = new String(pwd);
72 Arrays.fill(pwd, ' ');
73 }
74 session.addPasswordIdentity(password);
75 passwordSet = true;
76 }
77 }
78 session.auth().verify(1000l);
79 } catch (IOException e) {
80 throw new IllegalStateException(e);
81 }
82 }
83
84 void addPassword(String password) {
85 session.addPasswordIdentity(password);
86 }
87
88 void loadKey(String password) {
89 loadKey(password, System.getProperty("user.home") + "/.ssh/id_rsa");
90 }
91
92 void loadKey(String password, String keyPath) {
93 // try {
94 // KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
95 // FilePasswordProvider.of(password));
96 // session.addPublicKeyIdentity(keyPair);
97 // } catch (IOException | GeneralSecurityException e) {
98 // throw new IllegalStateException(e);
99 // }
100 }
101
102 void openSession(URI uri) {
103 openSession(uri.getUserInfo(), uri.getHost(), uri.getPort() > 0 ? uri.getPort() : null);
104 }
105
106 void openSession(String login, String host, Integer port) {
107 if (session != null)
108 throw new IllegalStateException("Session is already open");
109
110 if (host == null)
111 host = "localhost";
112 if (port == null)
113 port = 22;
114 if (login == null)
115 login = System.getProperty("user.name");
116 String password = null;
117 int sepIndex = login.indexOf(':');
118 if (sepIndex > 0)
119 if (sepIndex + 1 < login.length()) {
120 password = login.substring(sepIndex + 1);
121 login = login.substring(0, sepIndex);
122 } else {
123 throw new IllegalArgumentException("Illegal authority: " + login);
124 }
125 try {
126 ConnectFuture connectFuture = getSshClient().connect(login, host, port);
127 connectFuture.await();
128 ClientSession session = connectFuture.getSession();
129 if (password != null) {
130 session.addPasswordIdentity(password);
131 passwordSet = true;
132 }
133 this.session = session;
134 } catch (IOException e) {
135 throw new IllegalStateException("Cannot connect to " + host + ":" + port);
136 }
137 }
138
139 void closeSession() {
140 if (session == null)
141 throw new IllegalStateException("No session is open");
142 try {
143 session.close();
144 } catch (IOException e) {
145 e.printStackTrace();
146 } finally {
147 session = null;
148 }
149 }
150
151 ClientSession getSession() {
152 return session;
153 }
154
155 public void setSshKeyPair(SshKeyPair sshKeyPair) {
156 this.sshKeyPair = sshKeyPair;
157 }
158
159 public static void openShell(ClientSession session) {
160 try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
161 channel.setIn(new NoCloseInputStream(System.in));
162 channel.setOut(new NoCloseOutputStream(System.out));
163 channel.setErr(new NoCloseOutputStream(System.err));
164 channel.open();
165
166 Set<ClientChannelEvent> events = new HashSet<>();
167 events.add(ClientChannelEvent.CLOSED);
168 channel.waitFor(events, 0);
169 } catch (IOException e) {
170 // TODO Auto-generated catch block
171 e.printStackTrace();
172 } finally {
173 session.close(false);
174 }
175 }
176
177 static URI toUri(String username, String host, int port) {
178 try {
179 if (username == null)
180 username = "root";
181 return new URI("ssh://" + username + "@" + host + ":" + port);
182 } catch (URISyntaxException e) {
183 throw new IllegalArgumentException("Cannot generate SSH URI to " + host + ":" + port + " for " + username,
184 e);
185 }
186 }
187
188 }