// Copyright (C) 2009 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.pgm.init;

import static com.google.gerrit.common.FileUtil.chmod;
import static com.google.gerrit.pgm.init.api.InitUtil.die;
import static com.google.gerrit.pgm.init.api.InitUtil.hostname;
import static java.nio.file.Files.exists;

import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.pgm.init.api.Section;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.util.SocketUtil;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;

/** Initialize the {@code sshd} configuration section. */
@Singleton
class InitSshd implements InitStep {
  private final ConsoleUI ui;
  private final SitePaths site;
  private final Libraries libraries;
  private final Section sshd;

  @Inject
  InitSshd(final ConsoleUI ui, final SitePaths site, final Libraries libraries,
      final Section.Factory sections) {
    this.ui = ui;
    this.site = site;
    this.libraries = libraries;
    this.sshd = sections.get("sshd", null);
  }

  @Override
  public void run() throws Exception {
    ui.header("SSH Daemon");

    String hostname = "*";
    int port = 29418;
    String listenAddress = sshd.get("listenAddress");
    if (isOff(listenAddress)) {
      hostname = "off";
    } else if (listenAddress != null && !listenAddress.isEmpty()) {
      final InetSocketAddress addr = SocketUtil.parse(listenAddress, port);
      hostname = SocketUtil.hostname(addr);
      port = addr.getPort();
    }

    hostname = ui.readString(hostname, "Listen on address");
    if (isOff(hostname)) {
      sshd.set("listenAddress", "off");
      return;
    }

    port = ui.readInt(port, "Listen on port");
    sshd.set("listenAddress", SocketUtil.format(hostname, port));

    if (exists(site.ssh_rsa) || exists(site.ssh_dsa)) {
      libraries.bouncyCastleSSL.downloadRequired();
    } else if (!exists(site.ssh_key)) {
      libraries.bouncyCastleSSL.downloadOptional();
    }

    generateSshHostKeys();
  }

  private static boolean isOff(String listenHostname) {
    return "off".equalsIgnoreCase(listenHostname)
        || "none".equalsIgnoreCase(listenHostname)
        || "no".equalsIgnoreCase(listenHostname);
  }

  private void generateSshHostKeys() throws InterruptedException, IOException {
    if (!exists(site.ssh_key) //
        && !exists(site.ssh_rsa) //
        && !exists(site.ssh_dsa)) {
      System.err.print("Generating SSH host key ...");
      System.err.flush();

      if (SecurityUtils.isBouncyCastleRegistered()) {
        // Generate the SSH daemon host key using ssh-keygen.
        //
        final String comment = "gerrit-code-review@" + hostname();

        System.err.print(" rsa...");
        System.err.flush();
        Runtime.getRuntime().exec(new String[] {"ssh-keygen",
            "-q" /* quiet */,
            "-t", "rsa",
            "-P", "",
            "-C", comment,
            "-f", site.ssh_rsa.toAbsolutePath().toString(),
            }).waitFor();

        System.err.print(" dsa...");
        System.err.flush();
        Runtime.getRuntime().exec(new String[] {"ssh-keygen",
            "-q" /* quiet */,
            "-t", "dsa",
            "-P", "",
            "-C", comment,
            "-f", site.ssh_dsa.toAbsolutePath().toString(),
            }).waitFor();

      } else {
        // Generate the SSH daemon host key ourselves. This is complex
        // because SimpleGeneratorHostKeyProvider doesn't mark the data
        // file as only readable by us, exposing the private key for a
        // short period of time. We try to reduce that risk by creating
        // the key within a temporary directory.
        //
        Path tmpdir = site.etc_dir.resolve("tmp.sshkeygen");
        try {
          Files.createDirectory(tmpdir);
        } catch (IOException e) {
          throw die("Cannot create directory " + tmpdir, e);
        }
        chmod(0600, tmpdir);

        Path tmpkey = tmpdir.resolve(site.ssh_key.getFileName().toString());
        SimpleGeneratorHostKeyProvider p;

        System.err.print(" rsa(simple)...");
        System.err.flush();
        p = new SimpleGeneratorHostKeyProvider();
        p.setPath(tmpkey.toAbsolutePath());
        p.setAlgorithm("RSA");
        p.loadKeys(); // forces the key to generate.
        chmod(0600, tmpkey);

        try {
          Files.move(tmpkey, site.ssh_key);
        } catch (IOException e) {
          throw die("Cannot rename " + tmpkey + " to " + site.ssh_key, e);
        }
        try {
          Files.delete(tmpdir);
        } catch (IOException e) {
          throw die("Cannot delete " + tmpdir, e);
        }
      }
      System.err.println(" done");
    }
  }

  @Override
  public void postRun() throws Exception {
  }
}
