]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.lib.sshd/src/org/argeo/cms/ssh/CmsSshServer.java
Remove explicit dependency to SSHD bundle
[lgpl/argeo-commons.git] / org.argeo.cms.lib.sshd / src / org / argeo / cms / ssh / CmsSshServer.java
1 package org.argeo.cms.ssh;
2
3 import java.io.IOException;
4 import java.nio.file.Files;
5 import java.nio.file.Path;
6 import java.util.Collections;
7
8 import org.apache.sshd.common.forward.PortForwardingEventListener;
9 import org.apache.sshd.common.session.Session;
10 import org.apache.sshd.common.util.net.SshdSocketAddress;
11 import org.apache.sshd.scp.server.ScpCommandFactory;
12 import org.apache.sshd.server.SshServer;
13 import org.apache.sshd.server.auth.gss.GSSAuthenticator;
14 import org.apache.sshd.server.config.keys.DefaultAuthorizedKeysAuthenticator;
15 import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
16 import org.apache.sshd.server.jaas.JaasPasswordAuthenticator;
17 import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
18 import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
19 import org.apache.sshd.sftp.server.SftpSubsystemFactory;
20 import org.argeo.api.cms.CmsAuth;
21 import org.argeo.api.cms.CmsConstants;
22 import org.argeo.api.cms.CmsLog;
23 import org.argeo.api.cms.CmsState;
24 import org.argeo.cms.CmsDeployProperty;
25
26 public class CmsSshServer {
27 private final static CmsLog log = CmsLog.getLog(CmsSshServer.class);
28 private static final String DEFAULT_SSH_HOST_KEY_PATH = CmsConstants.NODE + '/' + CmsConstants.NODE + ".ser";
29
30 private CmsState cmsState;
31 private SshServer sshd = null;
32
33 private int port;
34 private String host;
35
36 public void start() {
37 String portStr = cmsState.getDeployProperty(CmsDeployProperty.SSHD_PORT.getProperty());
38 if (portStr == null)
39 return; // ignore
40 port = Integer.parseInt(portStr);
41
42 host = cmsState.getDeployProperty(CmsDeployProperty.HOST.getProperty());
43
44 Path hostKeyPath = cmsState.getDataPath(DEFAULT_SSH_HOST_KEY_PATH);
45
46 try {
47 sshd = SshServer.setUpDefaultServer();
48 sshd.setPort(port);
49 if (host != null)
50 sshd.setHost(host);
51 if (hostKeyPath == null)
52 throw new IllegalStateException("An SSH server key must be set");
53 sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKeyPath));
54 // sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i",
55 // "-l" }));
56 // String[] shellCommand = OS.LOCAL.getDefaultShellCommand();
57 // FIXME transfer args
58 // sshd.setShellFactory(new ProcessShellFactory(shellCommand));
59 sshd.setShellFactory(InteractiveProcessShellFactory.INSTANCE);
60 sshd.setCommandFactory(new ScpCommandFactory());
61
62 // tunnels
63 sshd.setForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
64 // sshd.setForwardingFilter(ForwardingFilter.asForwardingFilter(null, null,
65 // TcpForwardingFilter.DEFAULT));
66 // sshd.setForwarderFactory(DefaultForwarderFactory.INSTANCE);
67 // TcpForwardingFilter tcpForwardingFilter = sshd.getTcpForwardingFilter();
68 sshd.addPortForwardingEventListener(new PortForwardingEventListener() {
69
70 @Override
71 public void establishingExplicitTunnel(Session session, SshdSocketAddress local,
72 SshdSocketAddress remote, boolean localForwarding) throws IOException {
73 log.debug("Establishing tunnel " + local + ", " + remote);
74 }
75
76 @Override
77 public void establishedExplicitTunnel(Session session, SshdSocketAddress local,
78 SshdSocketAddress remote, boolean localForwarding, SshdSocketAddress boundAddress,
79 Throwable reason) throws IOException {
80 log.debug("Established tunnel " + local + ", " + remote + ", " + boundAddress);
81 }
82
83 @Override
84 public void establishingDynamicTunnel(Session session, SshdSocketAddress local) throws IOException {
85 log.debug("Establishing dynamic tunnel " + local);
86 }
87
88 @Override
89 public void establishedDynamicTunnel(Session session, SshdSocketAddress local,
90 SshdSocketAddress boundAddress, Throwable reason) throws IOException {
91 log.debug("Established dynamic tunnel " + local);
92 }
93
94 });
95
96 // Authentication
97 //sshd.setPublickeyAuthenticator(new DefaultAuthorizedKeysAuthenticator(true));
98 sshd.setPublickeyAuthenticator(null);
99 // sshd.setKeyboardInteractiveAuthenticator(null);
100 JaasPasswordAuthenticator jaasPasswordAuthenticator = new JaasPasswordAuthenticator();
101 jaasPasswordAuthenticator.setDomain(CmsAuth.NODE.getLoginContextName());
102 sshd.setPasswordAuthenticator(jaasPasswordAuthenticator);
103
104 Path krb5keyTab = cmsState.getDataPath("node/krb5.keytab");
105 if (Files.exists(krb5keyTab)) {
106 // FIXME experimental
107 GSSAuthenticator gssAuthenticator = new GSSAuthenticator();
108 gssAuthenticator.setKeytabFile(cmsState.getDataPath("node/krb5.keytab").toString());
109 gssAuthenticator.setServicePrincipalName("HTTP@" + host);
110 sshd.setGSSAuthenticator(gssAuthenticator);
111 }
112
113 // SFTP
114 sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
115
116 // start
117 sshd.start();
118
119 log.debug(() -> "CMS SSH server started on port " + port + (host != null ? " of host " + host : ""));
120 } catch (IOException e) {
121 throw new RuntimeException("Cannot start SSH server on port " + port, e);
122 }
123
124 }
125
126 public void stop() {
127 if (sshd == null)
128 return;
129 try {
130 sshd.stop();
131 log.debug(() -> "CMS SSH server stopped on port " + port + (host != null ? " of host " + host : ""));
132 } catch (IOException e) {
133 throw new RuntimeException("Cannot stop SSH server", e);
134 }
135
136 }
137
138 public void setCmsState(CmsState cmsState) {
139 this.cmsState = cmsState;
140 }
141
142 }