blob: de7354f9de3230965fee255c6a27380b7e3848ad [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2017 SAP AG and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Lazar Kirchev, SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.console.ssh;
import java.io.IOException;
import java.security.PublicKey;
import java.util.List;
import org.eclipse.equinox.console.internal.ssh.AuthorizedKeysFileAuthenticator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.apache.felix.service.command.CommandProcessor;
import org.apache.sshd.SshServer;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.jaas.JaasPasswordAuthenticator;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
/**
* This class configures and start an ssh server
*
*/
public class SshServ extends Thread {
private final BundleContext context;
private final int port;
private final String host;
private SshServer sshServer = null;
private SshShellFactory shellFactory = null;
private static final String SSH_KEYSTORE_PROP = "ssh.server.keystore";
private static final String SSH_KEYSTORE_PROP_DEFAULT = "hostkey.ser";
private static final String SSH_AUTHORIZED_KEYS_FILE_PROP = "ssh.server.authorized_keys";
private static final String SSH_CUSTOM_PUBLIC_KEY_AUTHENTICATION = "ssh.custom.publickeys.auth";
private static final String EQUINOX_CONSOLE_DOMAIN = "equinox_console";
public SshServ(List<CommandProcessor> processors, BundleContext context, String host, int port) {
this.context = context;
this.host = host;
this.port = port;
shellFactory = new SshShellFactory(processors, context);
}
@Override
public void run() throws RuntimeException {
sshServer = SshServer.setUpDefaultServer();
if (host != null) {
sshServer.setHost(host);
}
sshServer.setPort(port);
sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(System.getProperty(SSH_KEYSTORE_PROP, SSH_KEYSTORE_PROP_DEFAULT)));
sshServer.setShellFactory(shellFactory);
sshServer.setPasswordAuthenticator(createJaasPasswordAuthenticator());
sshServer.setPublickeyAuthenticator(createSimpleAuthorizedKeysAuthenticator());
try {
sshServer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void stopSshServer() {
try {
sshServer.stop(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void addCommandProcessor(CommandProcessor processor) {
shellFactory.addCommandProcessor(processor);
}
public synchronized void removeCommandProcessor(CommandProcessor processor) {
shellFactory.removeCommandProcessor(processor);
}
private PasswordAuthenticator createJaasPasswordAuthenticator() {
JaasPasswordAuthenticator jaasPasswordAuthenticator = new JaasPasswordAuthenticator();
jaasPasswordAuthenticator.setDomain(EQUINOX_CONSOLE_DOMAIN);
return jaasPasswordAuthenticator;
}
private PublickeyAuthenticator createSimpleAuthorizedKeysAuthenticator() {
// use authorized keys file if property is set
final String authorizedKeysFile = System.getProperty(SSH_AUTHORIZED_KEYS_FILE_PROP);
if (null != authorizedKeysFile) {
AuthorizedKeysFileAuthenticator authenticator = new AuthorizedKeysFileAuthenticator();
authenticator.setAuthorizedKeysFile(authorizedKeysFile);
return authenticator;
}
final String customPublicKeysAuthentication = System.getProperty(SSH_CUSTOM_PUBLIC_KEY_AUTHENTICATION);
// fall back to dynamic provider based on available OSGi services only if explicitly specified
if ("true".equals(customPublicKeysAuthentication)) {
return new PublickeyAuthenticator() {
@Override
public boolean authenticate(String username, PublicKey key, ServerSession session) {
// find available services
try {
for (ServiceReference<PublickeyAuthenticator> reference : context.getServiceReferences(PublickeyAuthenticator.class, null)) {
PublickeyAuthenticator authenticator = null;
try {
authenticator = context.getService(reference);
// first positive match wins; continue looking otherwise
if(authenticator.authenticate(username, key, session))
return true;
} finally {
if(null != authenticator)
context.ungetService(reference);
}
}
} catch (InvalidSyntaxException e) {
// no filter is used
}
return false;
}
};
}
return null;
}
}