// Copyright (C) 2008 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.sshd;

import static com.google.gerrit.server.ssh.SshAddressesModule.IANA_SSH_PORT;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.sshd.common.channel.ChannelOutputStream.WAIT_FOR_SPACE_TIMEOUT;

import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Version;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.metrics.Counter0;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.ssh.SshAdvertisedAddresses;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.server.ssh.SshListenAddresses;
import com.google.gerrit.server.util.IdGenerator;
import com.google.gerrit.server.util.SocketUtil;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.JSchException;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.WatchService;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.spi.FileSystemProvider;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.sshd.common.BaseBuilder;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.Cipher;
import org.apache.sshd.common.compression.BuiltinCompressions;
import org.apache.sshd.common.compression.Compression;
import org.apache.sshd.common.forward.DefaultForwarderFactory;
import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.AbstractIoServiceFactory;
import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoServiceFactory;
import org.apache.sshd.common.io.IoServiceFactoryFactory;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
import org.apache.sshd.common.io.mina.MinaSession;
import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.mac.Mac;
import org.apache.sshd.common.random.Random;
import org.apache.sshd.common.random.SingletonRandomFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.helpers.DefaultUnknownChannelReferenceHandler;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.net.SshdSocketAddress;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.ServerBuilder;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.UserAuthFactory;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
import org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory;
import org.apache.sshd.server.command.CommandFactory;
import org.apache.sshd.server.forward.ForwardingFilter;
import org.apache.sshd.server.global.CancelTcpipForwardHandler;
import org.apache.sshd.server.global.KeepAliveHandler;
import org.apache.sshd.server.global.NoMoreSessionsHandler;
import org.apache.sshd.server.global.TcpipForwardHandler;
import org.apache.sshd.server.session.ServerSessionImpl;
import org.apache.sshd.server.session.SessionFactory;
import org.bouncycastle.crypto.prng.RandomGenerator;
import org.bouncycastle.crypto.prng.VMPCRandomGenerator;
import org.eclipse.jgit.lib.Config;

/**
 * SSH daemon to communicate with Gerrit.
 *
 * <p>Use a Git URL such as <code>ssh://${email}@${host}:${port}/${path}</code>, e.g. {@code
 * ssh://sop@google.com@gerrit.com:8010/tools/gerrit.git} to access the SSH daemon itself.
 *
 * <p>Versions of Git before 1.5.3 may require setting the username and port properties in the
 * user's {@code ~/.ssh/config} file, and using a host alias through a URL such as {@code
 * gerrit-alias:/tools/gerrit.git}:
 *
 * <pre>{@code
 * Host gerrit-alias
 *  User sop@google.com
 *  Hostname gerrit.com
 *  Port 8010
 * }</pre>
 */
@Singleton
public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public enum SshSessionBackend {
    MINA,
    NIO2
  }

  private final List<SocketAddress> listen;
  private final List<String> advertised;
  private final boolean keepAlive;
  private final List<HostKey> hostKeys;
  private volatile IoAcceptor daemonAcceptor;
  private final Config cfg;
  private final long gracefulStopTimeout;

  @Inject
  SshDaemon(
      CommandFactory commandFactory,
      NoShell noShell,
      PublickeyAuthenticator userAuth,
      GerritGSSAuthenticator kerberosAuth,
      KeyPairProvider hostKeyProvider,
      IdGenerator idGenerator,
      @GerritServerConfig Config cfg,
      SshLog sshLog,
      @SshListenAddresses List<SocketAddress> listen,
      @SshAdvertisedAddresses List<String> advertised,
      MetricMaker metricMaker) {
    setPort(IANA_SSH_PORT /* never used */);

    this.cfg = cfg;
    this.listen = listen;
    this.advertised = advertised;
    keepAlive = cfg.getBoolean("sshd", "tcpkeepalive", true);

    getProperties()
        .put(
            SERVER_IDENTIFICATION,
            "GerritCodeReview_"
                + Version.getVersion() //
                + " ("
                + super.getVersion()
                + ")");

    getProperties().put(MAX_AUTH_REQUESTS, String.valueOf(cfg.getInt("sshd", "maxAuthTries", 6)));

    getProperties()
        .put(
            AUTH_TIMEOUT,
            String.valueOf(
                MILLISECONDS.convert(
                    ConfigUtil.getTimeUnit(cfg, "sshd", null, "loginGraceTime", 120, SECONDS),
                    SECONDS)));

    long idleTimeoutSeconds = ConfigUtil.getTimeUnit(cfg, "sshd", null, "idleTimeout", 0, SECONDS);
    getProperties().put(IDLE_TIMEOUT, String.valueOf(SECONDS.toMillis(idleTimeoutSeconds)));
    getProperties().put(NIO2_READ_TIMEOUT, String.valueOf(SECONDS.toMillis(idleTimeoutSeconds)));

    long rekeyTimeLimit =
        ConfigUtil.getTimeUnit(cfg, "sshd", null, "rekeyTimeLimit", 3600, SECONDS);
    getProperties().put(REKEY_TIME_LIMIT, String.valueOf(SECONDS.toMillis(rekeyTimeLimit)));

    getProperties()
        .put(
            REKEY_BYTES_LIMIT,
            String.valueOf(cfg.getLong("sshd", "rekeyBytesLimit", 1024 * 1024 * 1024 /* 1GB */)));

    long waitTimeoutSeconds = ConfigUtil.getTimeUnit(cfg, "sshd", null, "waitTimeout", 30, SECONDS);
    getProperties()
        .put(WAIT_FOR_SPACE_TIMEOUT, String.valueOf(SECONDS.toMillis(waitTimeoutSeconds)));

    final int maxConnectionsPerUser = cfg.getInt("sshd", "maxConnectionsPerUser", 64);
    if (0 < maxConnectionsPerUser) {
      getProperties().put(MAX_CONCURRENT_SESSIONS, String.valueOf(maxConnectionsPerUser));
    }

    final String kerberosKeytab = cfg.getString("sshd", null, "kerberosKeytab");
    final String kerberosPrincipal = cfg.getString("sshd", null, "kerberosPrincipal");

    final boolean enableCompression = cfg.getBoolean("sshd", "enableCompression", false);

    SshSessionBackend backend = cfg.getEnum("sshd", null, "backend", SshSessionBackend.NIO2);
    boolean channelIdTracking = cfg.getBoolean("sshd", "enableChannelIdTracking", true);

    gracefulStopTimeout = cfg.getTimeUnit("sshd", null, "gracefulStopTimeout", 0, TimeUnit.SECONDS);

    System.setProperty(
        IoServiceFactoryFactory.class.getName(),
        backend == SshSessionBackend.MINA
            ? MinaServiceFactoryFactory.class.getName()
            : Nio2ServiceFactoryFactory.class.getName());

    initProviderBouncyCastle(cfg);
    initCiphers(cfg);
    initKeyExchanges(cfg);
    initMacs(cfg);
    initSignatures();
    initChannels();
    initUnknownChannelReferenceHandler(channelIdTracking);
    initForwarding();
    initFileSystemFactory();
    initSubsystems();
    initCompression(enableCompression);
    initUserAuth(userAuth, kerberosAuth, kerberosKeytab, kerberosPrincipal);
    setKeyPairProvider(hostKeyProvider);
    setCommandFactory(commandFactory);
    setShellFactory(noShell);

    final AtomicInteger connected = new AtomicInteger();
    metricMaker.newCallbackMetric(
        "sshd/sessions/connected",
        Integer.class,
        new Description("Currently connected SSH sessions").setGauge().setUnit("sessions"),
        connected::get);

    final Counter0 sessionsCreated =
        metricMaker.newCounter(
            "sshd/sessions/created",
            new Description("Rate of new SSH sessions").setRate().setUnit("sessions"));

    final Counter0 authFailures =
        metricMaker.newCounter(
            "sshd/sessions/authentication_failures",
            new Description("Rate of SSH authentication failures").setRate().setUnit("failures"));

    setSessionFactory(
        new SessionFactory(this) {
          @Override
          protected ServerSessionImpl createSession(IoSession io) throws Exception {
            connected.incrementAndGet();
            sessionsCreated.increment();
            if (io instanceof MinaSession) {
              if (((MinaSession) io).getSession().getConfig() instanceof SocketSessionConfig) {
                ((SocketSessionConfig) ((MinaSession) io).getSession().getConfig())
                    .setKeepAlive(keepAlive);
              }
            }

            ServerSessionImpl s = super.createSession(io);
            int id = idGenerator.next();
            SocketAddress peer = io.getRemoteAddress();
            final SshSession sd = new SshSession(id, peer);
            s.setAttribute(SshSession.KEY, sd);

            // Log a session close without authentication as a failure.
            //
            s.addCloseFutureListener(
                future -> {
                  connected.decrementAndGet();
                  if (sd.isAuthenticationError()) {
                    authFailures.increment();
                    sshLog.onAuthFail(sd);
                  }
                });
            return s;
          }

          @Override
          protected ServerSessionImpl doCreateSession(IoSession ioSession) throws Exception {
            return new ServerSessionImpl(getServer(), ioSession);
          }
        });
    setGlobalRequestHandlers(
        Arrays.asList(
            new KeepAliveHandler(),
            new NoMoreSessionsHandler(),
            new TcpipForwardHandler(),
            new CancelTcpipForwardHandler()));

    hostKeys = computeHostKeys();
  }

  @Override
  public List<HostKey> getHostKeys() {
    return hostKeys;
  }

  public IoAcceptor getIoAcceptor() {
    return daemonAcceptor;
  }

  @Override
  public synchronized void start() {
    if (daemonAcceptor == null && !listen.isEmpty()) {
      checkConfig();
      if (getSessionFactory() == null) {
        setSessionFactory(createSessionFactory());
      }
      setupSessionTimeout(getSessionFactory());
      daemonAcceptor = createAcceptor();

      try {
        String listenAddress = cfg.getString("sshd", null, "listenAddress");
        boolean rewrite = !Strings.isNullOrEmpty(listenAddress) && listenAddress.endsWith(":0");
        daemonAcceptor.bind(listen);
        if (rewrite) {
          SocketAddress bound = Iterables.getOnlyElement(daemonAcceptor.getBoundAddresses());
          cfg.setString("sshd", null, "listenAddress", format((InetSocketAddress) bound));
        }
      } catch (IOException e) {
        throw new IllegalStateException("Cannot bind to " + addressList(), e);
      }

      logger.atInfo().log("Started Gerrit %s on %s", getVersion(), addressList());
    }
  }

  private static String format(InetSocketAddress s) {
    return String.format("%s:%d", s.getAddress().getHostAddress(), s.getPort());
  }

  @Override
  public synchronized void stop() {
    if (daemonAcceptor != null) {
      try {
        if (gracefulStopTimeout > 0) {
          logger.atInfo().log(
              "Stopping SSHD sessions gracefully with %d seconds timeout.", gracefulStopTimeout);
          daemonAcceptor.unbind(daemonAcceptor.getBoundAddresses());
          waitForSessionClose();
        }
        daemonAcceptor.close(true).await();
        shutdownExecutors();
        logger.atInfo().log("Stopped Gerrit SSHD");
      } catch (IOException e) {
        logger.atWarning().withCause(e).log("Exception caught while closing");
      } finally {
        daemonAcceptor = null;
      }
    }
  }

  private void waitForSessionClose() {
    Collection<IoSession> ioSessions = daemonAcceptor.getManagedSessions().values();
    CountDownLatch allSessionsClosed = new CountDownLatch(ioSessions.size());
    for (IoSession io : ioSessions) {
      logger.atFine().log("Waiting for session %s to stop.", io.getId());
      io.addCloseFutureListener(
          new SshFutureListener<CloseFuture>() {
            @Override
            public void operationComplete(CloseFuture future) {
              allSessionsClosed.countDown();
            }
          });
    }
    try {
      if (!allSessionsClosed.await(gracefulStopTimeout, TimeUnit.SECONDS)) {
        logger.atWarning().log(
            "Timeout waiting for SSH session to close. SSHD will be shut down immediately.");
      }
    } catch (InterruptedException e) {
      logger.atWarning().withCause(e).log(
          "Interrupted waiting for SSH-sessions to close. SSHD will be shut down immediately.");
    }
  }

  private void shutdownExecutors() {
    if (executor != null) {
      executor.shutdownNow();
    }

    IoServiceFactory serviceFactory = getIoServiceFactory();
    if (serviceFactory instanceof AbstractIoServiceFactory) {
      shutdownServiceFactoryExecutor((AbstractIoServiceFactory) serviceFactory);
    }
  }

  private void shutdownServiceFactoryExecutor(AbstractIoServiceFactory ioServiceFactory) {
    ioServiceFactory.close(true);
    ExecutorService serviceFactoryExecutor = ioServiceFactory.getExecutorService();
    if (serviceFactoryExecutor != null && serviceFactoryExecutor != executor) {
      serviceFactoryExecutor.shutdownNow();
    }
  }

  @Override
  protected void checkConfig() {
    super.checkConfig();
    if (myHostKeys().isEmpty()) {
      throw new IllegalStateException("No SSHD host key");
    }
  }

  private List<HostKey> computeHostKeys() {
    if (listen.isEmpty()) {
      return Collections.emptyList();
    }

    List<HostKey> r = new ArrayList<>();
    List<PublicKey> keys = myHostKeys();
    for (PublicKey pub : keys) {
      Buffer buf = new ByteArrayBuffer();
      buf.putRawPublicKey(pub);
      byte[] keyBin = buf.getCompactData();

      for (String addr : advertised) {
        try {
          r.add(new HostKey(addr, keyBin));
        } catch (JSchException e) {
          logger.atWarning().log(
              "Cannot format SSHD host key [%s]: %s", pub.getAlgorithm(), e.getMessage());
        }
      }
    }

    return Collections.unmodifiableList(r);
  }

  private List<PublicKey> myHostKeys() {
    KeyPairProvider p = getKeyPairProvider();
    List<PublicKey> keys = new ArrayList<>(6);
    try {
      addPublicKey(keys, p, KeyPairProvider.SSH_ED25519);
      addPublicKey(keys, p, KeyPairProvider.ECDSA_SHA2_NISTP256);
      addPublicKey(keys, p, KeyPairProvider.ECDSA_SHA2_NISTP384);
      addPublicKey(keys, p, KeyPairProvider.ECDSA_SHA2_NISTP521);
      addPublicKey(keys, p, KeyPairProvider.SSH_RSA);
      addPublicKey(keys, p, KeyPairProvider.SSH_DSS);
    } catch (IOException | GeneralSecurityException e) {
      throw new IllegalStateException("Cannot load SSHD host key", e);
    }
    return keys;
  }

  private static void addPublicKey(final Collection<PublicKey> out, KeyPairProvider p, String type)
      throws IOException, GeneralSecurityException {
    final KeyPair pair = p.loadKey(null, type);
    if (pair != null && pair.getPublic() != null) {
      out.add(pair.getPublic());
    }
  }

  private String addressList() {
    final StringBuilder r = new StringBuilder();
    for (Iterator<SocketAddress> i = listen.iterator(); i.hasNext(); ) {
      r.append(SocketUtil.format(i.next(), IANA_SSH_PORT));
      if (i.hasNext()) {
        r.append(", ");
      }
    }
    return r.toString();
  }

  private void initKeyExchanges(Config cfg) {
    List<KeyExchangeFactory> a = ServerBuilder.setUpDefaultKeyExchanges(true);
    setKeyExchangeFactories(filter(cfg, "kex", a.toArray(new KeyExchangeFactory[a.size()])));
  }

  private void initProviderBouncyCastle(Config cfg) {
    NamedFactory<Random> factory;
    if (cfg.getBoolean("sshd", null, "testUseInsecureRandom", false)) {
      factory = new InsecureBouncyCastleRandom.Factory();
    } else {
      factory = SecurityUtils.getRandomFactory();
    }
    setRandomFactory(new SingletonRandomFactory(factory));
  }

  private static class InsecureBouncyCastleRandom implements Random {
    private static class Factory implements NamedFactory<Random> {
      @Override
      public String getName() {
        return "INSECURE_bouncycastle";
      }

      @Override
      public Random create() {
        return new InsecureBouncyCastleRandom();
      }
    }

    private final RandomGenerator random;

    private InsecureBouncyCastleRandom() {
      random = new VMPCRandomGenerator();
      random.addSeedMaterial(1234);
    }

    @Override
    public String getName() {
      return "InsecureBouncyCastleRandom";
    }

    @Override
    public void fill(byte[] bytes, int start, int len) {
      random.nextBytes(bytes, start, len);
    }

    @Override
    public void fill(byte[] bytes) {
      random.nextBytes(bytes);
    }

    @Override
    public int random(int n) {
      if (n > 0) {
        if ((n & -n) == n) {
          return (int) ((n * (long) next(31)) >> 31);
        }
        int bits;
        int val;
        do {
          bits = next(31);
          val = bits % n;
        } while (bits - val + (n - 1) < 0);
        return val;
      }
      throw new IllegalArgumentException();
    }

    protected final int next(int numBits) {
      int bytes = (numBits + 7) / 8;
      byte[] next = new byte[bytes];
      int ret = 0;
      random.nextBytes(next);
      for (int i = 0; i < bytes; i++) {
        ret = (next[i] & 0xFF) | (ret << 8);
      }
      return ret >>> (bytes * 8 - numBits);
    }
  }

  @SuppressWarnings("unchecked")
  private void initCiphers(Config cfg) {
    List<NamedFactory<Cipher>> a = BaseBuilder.setUpDefaultCiphers(true);

    for (Iterator<NamedFactory<Cipher>> i = a.iterator(); i.hasNext(); ) {
      NamedFactory<Cipher> f = i.next();
      try {
        Cipher c = f.create();
        byte[] key = new byte[c.getKdfSize()];
        byte[] iv = new byte[c.getIVSize()];
        c.init(Cipher.Mode.Encrypt, key, iv);
      } catch (InvalidKeyException e) {
        logger.atWarning().log(
            "Disabling cipher %s: %s; try installing unlimited cryptography extension",
            f.getName(), e.getMessage());
        i.remove();
      } catch (Exception e) {
        logger.atWarning().log("Disabling cipher %s: %s", f.getName(), e.getMessage());
        i.remove();
      }
    }

    a.add(null);
    setCipherFactories(
        filter(cfg, "cipher", (NamedFactory<Cipher>[]) a.toArray(new NamedFactory<?>[a.size()])));
  }

  @SuppressWarnings("unchecked")
  private void initMacs(Config cfg) {
    List<NamedFactory<Mac>> m = BaseBuilder.setUpDefaultMacs(true);
    setMacFactories(
        filter(cfg, "mac", (NamedFactory<Mac>[]) m.toArray(new NamedFactory<?>[m.size()])));
  }

  @SafeVarargs
  private static <T extends NamedResource> List<T> filter(Config cfg, String key, T... avail) {
    List<T> def = new ArrayList<>();
    for (T n : avail) {
      if (n == null) {
        break;
      }
      def.add(n);
    }

    String[] want = cfg.getStringList("sshd", null, key);
    if (want == null || want.length == 0) {
      return def;
    }

    boolean didClear = false;
    for (String setting : want) {
      String name = setting.trim();
      boolean add = true;
      if (name.startsWith("-")) {
        add = false;
        name = name.substring(1).trim();
      } else if (name.startsWith("+")) {
        name = name.substring(1).trim();
      } else if (!didClear) {
        didClear = true;
        def.clear();
      }

      T n = find(name, avail);
      if (n == null) {
        StringBuilder msg = new StringBuilder();
        msg.append("sshd.").append(key).append(" = ").append(name).append(" unsupported; only ");
        for (int i = 0; i < avail.length; i++) {
          if (avail[i] == null) {
            continue;
          }
          if (i > 0) {
            msg.append(", ");
          }
          msg.append(avail[i].getName());
        }
        msg.append(" is supported");
        logger.atSevere().log(msg.toString());
      } else if (add) {
        if (!def.contains(n)) {
          def.add(n);
        }
      } else {
        def.remove(n);
      }
    }

    return def;
  }

  @SafeVarargs
  private static <T extends NamedResource> T find(String name, T... avail) {
    for (T n : avail) {
      if (n != null && name.equals(n.getName())) {
        return n;
      }
    }
    return null;
  }

  private void initSignatures() {
    setSignatureFactories(ServerBuilder.setUpDefaultSignatureFactories(false));
  }

  private void initCompression(boolean enableCompression) {
    List<NamedFactory<Compression>> compressionFactories = new ArrayList<>();

    // Always support no compression over SSHD.
    compressionFactories.add(BuiltinCompressions.none);

    // In the general case, we want to disable transparent compression, since
    // the majority of our data transfer is highly compressed Git pack files
    // and we cannot make them any smaller than they already are.
    //
    // However, if there are CPU in abundance and the server is reachable through
    // slow networks, gits with huge amount of refs can benefit from SSH-compression
    // since git does not compress the ref announcement during the handshake.
    // Compression can be especially useful when Gerrit replica are being used
    // for the larger clones and fetches and the primary server handling write
    // operations mostly takes small receive-packs.

    if (enableCompression) {
      compressionFactories.add(BuiltinCompressions.zlib);
    }

    setCompressionFactories(compressionFactories);
  }

  private void initChannels() {
    setChannelFactories(ServerBuilder.DEFAULT_CHANNEL_FACTORIES);
  }

  private void initUnknownChannelReferenceHandler(boolean enableChannelIdTracking) {
    setUnknownChannelReferenceHandler(
        enableChannelIdTracking
            ? ChannelIdTrackingUnknownChannelReferenceHandler.TRACKER
            : DefaultUnknownChannelReferenceHandler.INSTANCE);
  }

  private void initSubsystems() {
    setSubsystemFactories(Collections.emptyList());
  }

  private void initUserAuth(
      final PublickeyAuthenticator pubkey,
      final GSSAuthenticator kerberosAuthenticator,
      String kerberosKeytab,
      String kerberosPrincipal) {
    List<UserAuthFactory> authFactories = new ArrayList<>();
    if (kerberosKeytab != null) {
      authFactories.add(UserAuthGSSFactory.INSTANCE);
      logger.atInfo().log("Enabling kerberos with keytab %s", kerberosKeytab);
      if (!new File(kerberosKeytab).canRead()) {
        logger.atSevere().log(
            "Keytab %s does not exist or is not readable; further errors are possible",
            kerberosKeytab);
      }
      kerberosAuthenticator.setKeytabFile(kerberosKeytab);
      if (kerberosPrincipal == null) {
        try {
          kerberosPrincipal = "host/" + InetAddress.getLocalHost().getCanonicalHostName();
        } catch (UnknownHostException e) {
          kerberosPrincipal = "host/localhost";
        }
      }
      logger.atInfo().log("Using kerberos principal %s", kerberosPrincipal);
      if (!kerberosPrincipal.startsWith("host/")) {
        logger.atWarning().log(
            "Host principal does not start with host/ "
                + "which most SSH clients will supply automatically");
      }
      kerberosAuthenticator.setServicePrincipalName(kerberosPrincipal);
      setGSSAuthenticator(kerberosAuthenticator);
    }
    authFactories.add(UserAuthPublicKeyFactory.INSTANCE);
    setUserAuthFactories(authFactories);
    setPublickeyAuthenticator(pubkey);
  }

  private void initForwarding() {
    setForwardingFilter(
        new ForwardingFilter() {
          @Override
          public boolean canForwardAgent(Session session, String requestType) {
            return false;
          }

          @Override
          public boolean canForwardX11(Session session, String requestType) {
            return false;
          }

          @Override
          public boolean canListen(SshdSocketAddress address, Session session) {
            return false;
          }

          @Override
          public boolean canConnect(Type type, SshdSocketAddress address, Session session) {
            return false;
          }
        });
    setForwarderFactory(new DefaultForwarderFactory());
  }

  private void initFileSystemFactory() {
    setFileSystemFactory(
        session ->
            new FileSystem() {
              @Override
              public void close() throws IOException {}

              @Override
              public Iterable<FileStore> getFileStores() {
                return null;
              }

              @Override
              public Path getPath(String arg0, String... arg1) {
                return null;
              }

              @Override
              public PathMatcher getPathMatcher(String arg0) {
                return null;
              }

              @Override
              public Iterable<Path> getRootDirectories() {
                return null;
              }

              @Override
              public String getSeparator() {
                return null;
              }

              @Override
              public UserPrincipalLookupService getUserPrincipalLookupService() {
                return null;
              }

              @Override
              public boolean isOpen() {
                return false;
              }

              @Override
              public boolean isReadOnly() {
                return false;
              }

              @Override
              public WatchService newWatchService() throws IOException {
                return null;
              }

              @Override
              public FileSystemProvider provider() {
                return null;
              }

              @Override
              public Set<String> supportedFileAttributeViews() {
                return null;
              }
            });
  }
}
