LCOV - code coverage report
Current view: top level - pgm/init - InitSshd.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 89 101 88.1 %
Date: 2022-11-19 15:00:39 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2009 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.pgm.init;
      16             : 
      17             : import static com.google.gerrit.pgm.init.api.InitUtil.hostname;
      18             : import static java.nio.file.Files.exists;
      19             : 
      20             : import com.google.gerrit.pgm.init.api.ConsoleUI;
      21             : import com.google.gerrit.pgm.init.api.InitStep;
      22             : import com.google.gerrit.pgm.init.api.Section;
      23             : import com.google.gerrit.server.config.SitePaths;
      24             : import com.google.gerrit.server.ioutil.HostPlatform;
      25             : import com.google.gerrit.server.util.SocketUtil;
      26             : import com.google.inject.Inject;
      27             : import com.google.inject.Singleton;
      28             : import java.io.IOException;
      29             : import java.lang.ProcessBuilder.Redirect;
      30             : import java.net.InetSocketAddress;
      31             : 
      32             : /** Initialize the {@code sshd} configuration section. */
      33             : @Singleton
      34             : public class InitSshd implements InitStep {
      35             :   private final ConsoleUI ui;
      36             :   private final SitePaths site;
      37             :   private final Section sshd;
      38             :   private final StaleLibraryRemover remover;
      39             : 
      40             :   @Inject
      41          15 :   InitSshd(ConsoleUI ui, SitePaths site, Section.Factory sections, StaleLibraryRemover remover) {
      42          15 :     this.ui = ui;
      43          15 :     this.site = site;
      44          15 :     this.sshd = sections.get("sshd", null);
      45          15 :     this.remover = remover;
      46          15 :   }
      47             : 
      48             :   @Override
      49             :   public void run() throws Exception {
      50          15 :     ui.header("SSH Daemon");
      51             : 
      52          15 :     String hostname = "*";
      53          15 :     int port = 29418;
      54          15 :     String listenAddress = sshd.get("listenAddress");
      55          15 :     if (isOff(listenAddress)) {
      56           7 :       hostname = "off";
      57           8 :     } else if (listenAddress != null && !listenAddress.isEmpty()) {
      58           8 :       final InetSocketAddress addr = SocketUtil.parse(listenAddress, port);
      59           8 :       hostname = SocketUtil.hostname(addr);
      60           8 :       port = addr.getPort();
      61             :     }
      62             : 
      63          15 :     hostname = ui.readString(hostname, "Listen on address");
      64          15 :     if (isOff(hostname)) {
      65           7 :       sshd.set("listenAddress", "off");
      66           7 :       return;
      67             :     }
      68             : 
      69           8 :     port = ui.readInt(port, "Listen on port");
      70           8 :     sshd.set("listenAddress", SocketUtil.format(hostname, port));
      71             : 
      72           8 :     generateSshHostKeys();
      73           8 :     remover.remove("bc(pg|pkix|prov)-.*[.]jar");
      74           8 :   }
      75             : 
      76             :   static boolean isOff(String listenHostname) {
      77          15 :     return "off".equalsIgnoreCase(listenHostname)
      78           8 :         || "none".equalsIgnoreCase(listenHostname)
      79          15 :         || "no".equalsIgnoreCase(listenHostname);
      80             :   }
      81             : 
      82             :   private void generateSshHostKeys() throws InterruptedException, IOException {
      83           8 :     if (!exists(site.ssh_key)
      84           8 :         && (!exists(site.ssh_rsa)
      85           1 :             || !exists(site.ssh_ed25519)
      86           1 :             || !exists(site.ssh_ecdsa_256)
      87           1 :             || !exists(site.ssh_ecdsa_384)
      88           1 :             || !exists(site.ssh_ecdsa_521))) {
      89           8 :       System.err.print("Generating SSH host key ...");
      90           8 :       System.err.flush();
      91             : 
      92             :       // Generate the SSH daemon host key using ssh-keygen.
      93             :       //
      94           8 :       final String comment = "gerrit-code-review@" + hostname();
      95             : 
      96             :       // Workaround for JDK-6518827 - zero-length argument ignored on Win32
      97           8 :       String emptyPassphraseArg = HostPlatform.isWin32() ? "\"\"" : "";
      98           8 :       if (!exists(site.ssh_rsa)) {
      99           8 :         System.err.print(" rsa...");
     100           8 :         System.err.flush();
     101           8 :         new ProcessBuilder(
     102             :                 "ssh-keygen",
     103             :                 "-q" /* quiet */,
     104             :                 "-t",
     105             :                 "rsa",
     106             :                 "-N",
     107             :                 emptyPassphraseArg,
     108             :                 "-C",
     109             :                 comment,
     110             :                 "-f",
     111           8 :                 site.ssh_rsa.toAbsolutePath().toString())
     112           8 :             .redirectError(Redirect.INHERIT)
     113           8 :             .redirectOutput(Redirect.INHERIT)
     114           8 :             .start()
     115           8 :             .waitFor();
     116             :       }
     117             : 
     118           8 :       if (!exists(site.ssh_ed25519)) {
     119           8 :         System.err.print(" ed25519...");
     120           8 :         System.err.flush();
     121             :         try {
     122           8 :           new ProcessBuilder(
     123             :                   "ssh-keygen",
     124             :                   "-q" /* quiet */,
     125             :                   "-t",
     126             :                   "ed25519",
     127             :                   "-N",
     128             :                   emptyPassphraseArg,
     129             :                   "-C",
     130             :                   comment,
     131             :                   "-f",
     132           8 :                   site.ssh_ed25519.toAbsolutePath().toString())
     133           8 :               .redirectError(Redirect.INHERIT)
     134           8 :               .redirectOutput(Redirect.INHERIT)
     135           8 :               .start()
     136           8 :               .waitFor();
     137           0 :         } catch (Exception e) {
     138             :           // continue since older hosts won't be able to generate ed25519 keys.
     139           0 :           System.err.print(" Failed to generate ed25519 key, continuing...");
     140           0 :           System.err.flush();
     141           8 :         }
     142             :       }
     143             : 
     144           8 :       if (!exists(site.ssh_ecdsa_256)) {
     145           8 :         System.err.print(" ecdsa 256...");
     146           8 :         System.err.flush();
     147             :         try {
     148           8 :           new ProcessBuilder(
     149             :                   "ssh-keygen",
     150             :                   "-q" /* quiet */,
     151             :                   "-t",
     152             :                   "ecdsa",
     153             :                   "-b",
     154             :                   "256",
     155             :                   "-N",
     156             :                   emptyPassphraseArg,
     157             :                   "-C",
     158             :                   comment,
     159             :                   "-f",
     160           8 :                   site.ssh_ecdsa_256.toAbsolutePath().toString())
     161           8 :               .redirectError(Redirect.INHERIT)
     162           8 :               .redirectOutput(Redirect.INHERIT)
     163           8 :               .start()
     164           8 :               .waitFor();
     165           0 :         } catch (Exception e) {
     166             :           // continue since older hosts won't be able to generate ecdsa keys.
     167           0 :           System.err.print(" Failed to generate ecdsa 256 key, continuing...");
     168           0 :           System.err.flush();
     169           8 :         }
     170             :       }
     171             : 
     172           8 :       if (!exists(site.ssh_ecdsa_384)) {
     173           8 :         System.err.print(" ecdsa 384...");
     174           8 :         System.err.flush();
     175             :         try {
     176           8 :           new ProcessBuilder(
     177             :                   "ssh-keygen",
     178             :                   "-q" /* quiet */,
     179             :                   "-t",
     180             :                   "ecdsa",
     181             :                   "-b",
     182             :                   "384",
     183             :                   "-N",
     184             :                   emptyPassphraseArg,
     185             :                   "-C",
     186             :                   comment,
     187             :                   "-f",
     188           8 :                   site.ssh_ecdsa_384.toAbsolutePath().toString())
     189           8 :               .redirectError(Redirect.INHERIT)
     190           8 :               .redirectOutput(Redirect.INHERIT)
     191           8 :               .start()
     192           8 :               .waitFor();
     193           0 :         } catch (Exception e) {
     194             :           // continue since older hosts won't be able to generate ecdsa keys.
     195           0 :           System.err.print(" Failed to generate ecdsa 384 key, continuing...");
     196           0 :           System.err.flush();
     197           8 :         }
     198             :       }
     199             : 
     200           8 :       if (!exists(site.ssh_ecdsa_521)) {
     201           8 :         System.err.print(" ecdsa 521...");
     202           8 :         System.err.flush();
     203             :         try {
     204           8 :           new ProcessBuilder(
     205             :                   "ssh-keygen",
     206             :                   "-q" /* quiet */,
     207             :                   "-t",
     208             :                   "ecdsa",
     209             :                   "-b",
     210             :                   "521",
     211             :                   "-N",
     212             :                   emptyPassphraseArg,
     213             :                   "-C",
     214             :                   comment,
     215             :                   "-f",
     216           8 :                   site.ssh_ecdsa_521.toAbsolutePath().toString())
     217           8 :               .redirectError(Redirect.INHERIT)
     218           8 :               .redirectOutput(Redirect.INHERIT)
     219           8 :               .start()
     220           8 :               .waitFor();
     221           0 :         } catch (Exception e) {
     222             :           // continue since older hosts won't be able to generate ecdsa keys.
     223           0 :           System.err.print(" Failed to generate ecdsa 521 key, continuing...");
     224           0 :           System.err.flush();
     225           8 :         }
     226             :       }
     227           8 :       System.err.println(" done");
     228             :     }
     229           8 :   }
     230             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750