Package io.fathom.cloud.commands

Source Code of io.fathom.cloud.commands.EmbeddedSshd

package io.fathom.cloud.commands;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.PublicKey;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.sshd.SshServer;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.Channel;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.ForwardingAcceptorFactory;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.FileSystemFactory;
import org.apache.sshd.server.FileSystemView;
import org.apache.sshd.server.ForwardingFilter;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.UserAuth;
import org.apache.sshd.server.auth.UserAuthPublicKey;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fathomdb.Configuration;
import com.fathomdb.crypto.OpenSshUtils;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.Files;

@Singleton
public class EmbeddedSshd {
    private static final Logger log = LoggerFactory.getLogger(EmbeddedSshd.class);

    public static final String CONFIG_ENABLED = "sshd.enabled";

    @Inject
    Configuration configuration;

    private SshServer sshd;

    @Inject
    SshCommandFactory sshCommandFactory;

    public boolean start() throws IOException {
        if (sshd != null) {
            throw new IllegalStateException();
        }

        final boolean authUseKeys = true;

        // TODO: Use AuthorizedSshKeys helper
        final File authorizedKeys = configuration.lookupFile("sshd.authorized_keys", "~/.ssh/authorized_fathomcloud");

        if (!authUseKeys) {
            throw new IllegalArgumentException(
                    "Neither password nor publickey SSH-auth are enabled, so won't start SSH server");
        }

        sshd = SshServer.setUpDefaultServer();

        if (authUseKeys) {
            sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
                @Override
                public boolean authenticate(String username, PublicKey key, ServerSession session) {
                    try {
                        String opensshEncoded = OpenSshUtils.serialize(key);
                        log.info("SSH presented public key: " + opensshEncoded);

                        List<String> match = Lists.newArrayList(Splitter.on(CharMatcher.WHITESPACE).split(
                                opensshEncoded));

                        if (!authorizedKeys.exists()) {
                            log.warn("SSH authorized key file does not exist: {}", authorizedKeys);
                        } else {
                            for (String line : Files.readLines(authorizedKeys, Charsets.UTF_8)) {
                                line = line.trim();
                                List<String> tokens = Lists.newArrayList(Splitter.on(CharMatcher.WHITESPACE)
                                        .split(line));
                                if (tokens.size() < 2) {
                                    continue;
                                }

                                if (!match.get(0).equals(tokens.get(0))) {
                                    continue;
                                }
                                if (!match.get(1).equals(tokens.get(1))) {
                                    continue;
                                }

                                return true;
                            }
                        }

                        return false;
                    } catch (Exception e) {
                        log.error("Exception while verifying public key", e);
                        return false;
                    }
                }
            });
        }

        // Log if anyone even suggests touching the filesystem
        sshd.setFileSystemFactory(new FileSystemFactory() {
            @Override
            public FileSystemView createFileSystemView(Session session) throws IOException {
                log.warn("Blocking SSHD filesystem access");
                throw new IllegalStateException("Blocking SSHD filesystem access");
            }
        });

        // Log if anyone even suggested forwarding a port
        sshd.setForwardingFilter(new ForwardingFilter() {
            @Override
            public boolean canListen(InetSocketAddress address, ServerSession session) {
                log.warn("Blocking SSHD port forwarding");
                return false;
            }

            @Override
            public boolean canForwardX11(ServerSession session) {
                log.warn("Blocking SSHD port forwarding");
                return false;
            }

            @Override
            public boolean canForwardAgent(ServerSession session) {
                log.warn("Blocking SSHD port forwarding");
                return false;
            }

            @Override
            public boolean canConnect(InetSocketAddress address, ServerSession session) {
                log.warn("Blocking SSHD port forwarding");
                return false;
            }
        });

        sshd.setAgentFactory(new SshAgentFactory() {
            @Override
            public NamedFactory<Channel> getChannelForwardingFactory() {
                log.warn("Blocking SSHD agent functionality");
                throw new IllegalStateException("Blocking SSHD agent functionality");
            }

            @Override
            public SshAgentServer createServer(Session session) throws IOException {
                log.warn("Blocking SSHD agent functionality");
                throw new IllegalStateException("Blocking SSHD agent functionality");
            }

            @Override
            public SshAgent createClient(Session session) throws IOException {
                log.warn("Blocking SSHD agent functionality");
                throw new IllegalStateException("Blocking SSHD agent functionality");
            }
        });

        sshd.setTcpipForwardNioSocketAcceptorFactory(new ForwardingAcceptorFactory() {
            @Override
            public NioSocketAcceptor createNioSocketAcceptor(Session session) {
                log.warn("Blocking SSHD Tcpip Forward functionality");
                throw new IllegalStateException("Blocking SSHD Tcpip Forward access");
            }
        });

        sshd.setX11ForwardNioSocketAcceptorFactory(new ForwardingAcceptorFactory() {
            @Override
            public NioSocketAcceptor createNioSocketAcceptor(Session session) {
                log.warn("Blocking SSHD X11 Forward functionality");
                throw new IllegalStateException("Blocking SSHD X11 Forward access");
            }
        });

        sshd.setShellFactory(new Factory<Command>() {
            @Override
            public Command create() {
                log.warn("Blocking SSHD shell functionality");
                throw new IllegalStateException("Blocking SSHD shell access");
            }
        });

        sshd.setPort(configuration.lookup("sshd.port", 2222));
        File hostkeyPath = configuration.lookupFile("sshd.hostkey", "hostkey.ser");
        sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostkeyPath.getAbsolutePath()));
        sshd.setCommandFactory(sshCommandFactory);

        List<NamedFactory<Command>> subsystemFactories = sshd.getSubsystemFactories();
        if (subsystemFactories != null) {
            throw new UnsupportedOperationException();
        }

        List<NamedFactory<Channel>> channelFactories = sshd.getChannelFactories();
        sshd.setChannelFactories(Lists.newArrayList(Iterables.filter(channelFactories,
                new Predicate<NamedFactory<Channel>>() {
                    @Override
                    public boolean apply(NamedFactory<Channel> command) {
                        if (command instanceof ChannelSession.Factory) {
                            log.info("Accepting Channel factory: " + command);
                            return true;
                        } else {
                            return false;
                        }
                    }
                })));

        log.info("Starting SSH server");
        sshd.start();

        for (NamedFactory<UserAuth> authFactory : sshd.getUserAuthFactories()) {
            if (authFactory instanceof UserAuthPublicKey.Factory) {
                if (!authUseKeys) {
                    throw new IllegalStateException();
                }
            } else {
                throw new IllegalStateException();
            }
        }

        return true;
    }

    public void stop() throws InterruptedException {
        if (sshd != null) {
            sshd.stop();
            sshd = null;
        }
    }
}
TOP

Related Classes of io.fathom.cloud.commands.EmbeddedSshd

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.