diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java index aa2fcbc36e..e557301fc0 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java @@ -21,6 +21,7 @@ import org.eclipse.jgit.util.IO; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -67,6 +68,15 @@ public class FileUtil { } } + public static long lastModified(Path p) { + // Replicate File#lastModified() behavior of returning 0 on errors. + try { + return Files.getLastModifiedTime(p).toMillis(); + } catch (IOException e) { + return 0; + } + } + private FileUtil() { } } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java index c8f1cd70db..afd503ba9d 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java @@ -29,10 +29,11 @@ import com.google.gwtjsonrpc.server.SignedToken; import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; /** Initialize the {@code httpd} configuration section. */ @Singleton @@ -149,8 +150,9 @@ class InitHttpd implements InitStep { return; } - final File store = site.ssl_keystore; - if (!ui.yesno(!store.exists(), "Create new self-signed SSL certificate")) { + Path store = site.ssl_keystore; + if (!ui.yesno(!Files.exists(store), + "Create new self-signed SSL certificate")) { return; } @@ -167,15 +169,17 @@ class InitHttpd implements InitStep { final String dname = "CN=" + hostname + ",OU=Gerrit Code Review,O=" + domainOf(hostname); - final File tmpdir = new File(site.etc_dir, "tmp.sslcertgen"); - if (!tmpdir.mkdir()) { - throw die("Cannot create directory " + tmpdir); + Path tmpdir = site.etc_dir.toPath().resolve("tmp.sslcertgen"); + try { + Files.createDirectory(tmpdir); + } catch (IOException e) { + throw die("Cannot create directory " + tmpdir, e); } chmod(0600, tmpdir); - final File tmpstore = new File(tmpdir, "keystore"); + Path tmpstore = tmpdir.resolve("keystore"); Runtime.getRuntime().exec(new String[] {"keytool", // - "-keystore", tmpstore.getAbsolutePath(), // + "-keystore", tmpstore.toAbsolutePath().toString(), // "-storepass", ssl_pass, // "-genkeypair", // "-alias", hostname, // @@ -186,11 +190,15 @@ class InitHttpd implements InitStep { }).waitFor(); chmod(0600, tmpstore); - if (!tmpstore.renameTo(store)) { - throw die("Cannot rename " + tmpstore + " to " + store); + try { + Files.move(tmpstore, store); + } catch (IOException e) { + throw die("Cannot rename " + tmpstore + " to " + store, e); } - if (!tmpdir.delete()) { - throw die("Cannot delete " + tmpdir); + try { + Files.delete(tmpdir); + } catch (IOException e) { + throw die("Cannot delete " + tmpdir, e); } } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java index ed18d737a6..acefaa7af4 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java @@ -18,6 +18,8 @@ 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; @@ -29,9 +31,10 @@ import com.google.inject.Singleton; import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; -import java.io.File; 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 @@ -74,9 +77,9 @@ class InitSshd implements InitStep { port = ui.readInt(port, "Listen on port"); sshd.set("listenAddress", SocketUtil.format(hostname, port)); - if (site.ssh_rsa.exists() || site.ssh_dsa.exists()) { + if (exists(site.ssh_rsa) || exists(site.ssh_dsa)) { libraries.bouncyCastleSSL.downloadRequired(); - } else if (!site.ssh_key.exists()) { + } else if (!exists(site.ssh_key)) { libraries.bouncyCastleSSL.downloadOptional(); } @@ -90,9 +93,9 @@ class InitSshd implements InitStep { } private void generateSshHostKeys() throws InterruptedException, IOException { - if (!site.ssh_key.exists() // - && !site.ssh_rsa.exists() // - && !site.ssh_dsa.exists()) { + if (!exists(site.ssh_key) // + && !exists(site.ssh_rsa) // + && !exists(site.ssh_dsa)) { System.err.print("Generating SSH host key ..."); System.err.flush(); @@ -108,7 +111,7 @@ class InitSshd implements InitStep { "-t", "rsa", // "-P", "", // "-C", comment, // - "-f", site.ssh_rsa.getAbsolutePath() // + "-f", site.ssh_rsa.toAbsolutePath().toString() // }).waitFor(); System.err.print(" dsa..."); @@ -118,7 +121,7 @@ class InitSshd implements InitStep { "-t", "dsa", // "-P", "", // "-C", comment, // - "-f", site.ssh_dsa.getAbsolutePath() // + "-f", site.ssh_dsa.toAbsolutePath().toString() // }).waitFor(); } else { @@ -128,28 +131,34 @@ class InitSshd implements InitStep { // short period of time. We try to reduce that risk by creating // the key within a temporary directory. // - final File tmpdir = new File(site.etc_dir, "tmp.sshkeygen"); - if (!tmpdir.mkdir()) { - throw die("Cannot create directory " + tmpdir); + Path tmpdir = site.etc_dir.toPath().resolve("tmp.sshkeygen"); + try { + Files.createDirectory(tmpdir); + } catch (IOException e) { + throw die("Cannot create directory " + tmpdir, e); } chmod(0600, tmpdir); - final File tmpkey = new File(tmpdir, site.ssh_key.getName()); - final SimpleGeneratorHostKeyProvider p; + 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.getAbsolutePath()); + p.setPath(tmpkey.toAbsolutePath().toString()); p.setAlgorithm("RSA"); p.loadKeys(); // forces the key to generate. chmod(0600, tmpkey); - if (!tmpkey.renameTo(site.ssh_key)) { - throw die("Cannot rename " + tmpkey + " to " + site.ssh_key); + try { + Files.move(tmpkey, site.ssh_key); + } catch (IOException e) { + throw die("Cannot rename " + tmpkey + " to " + site.ssh_key, e); } - if (!tmpdir.delete()) { - throw die("Cannot delete " + tmpdir); + try { + Files.delete(tmpdir); + } catch (IOException e) { + throw die("Cannot delete " + tmpdir, e); } } System.err.println(" done"); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java index 44f03405bc..18dd6f5de7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java @@ -50,11 +50,11 @@ public final class SitePaths { public final File secure_config; public final File contact_information_pub; - public final File ssl_keystore; - public final File ssh_key; - public final File ssh_rsa; - public final File ssh_dsa; - public final File peer_keys; + public final Path ssl_keystore; + public final Path ssh_key; + public final Path ssh_rsa; + public final Path ssh_dsa; + public final Path peer_keys; public final Path site_css; public final Path site_header; @@ -90,13 +90,13 @@ public final class SitePaths { secure_config = new File(etc_dir, "secure.config"); contact_information_pub = new File(etc_dir, "contact_information.pub"); - ssl_keystore = new File(etc_dir, "keystore"); - ssh_key = new File(etc_dir, "ssh_host_key"); - ssh_rsa = new File(etc_dir, "ssh_host_rsa_key"); - ssh_dsa = new File(etc_dir, "ssh_host_dsa_key"); - peer_keys = new File(etc_dir, "peer_keys"); - Path etcDirPath = etc_dir.toPath(); + ssl_keystore = etcDirPath.resolve("keystore"); + ssh_key = etcDirPath.resolve("ssh_host_key"); + ssh_rsa = etcDirPath.resolve("ssh_host_rsa_key"); + ssh_dsa = etcDirPath.resolve("ssh_host_dsa_key"); + peer_keys = etcDirPath.resolve("peer_keys"); + site_css = etcDirPath.resolve(CSS_FILENAME); site_header = etcDirPath.resolve(HEADER_FILENAME); site_footer = etcDirPath.resolve(FOOTER_FILENAME); diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java index 93d2e5b342..b72ab27a75 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java @@ -14,6 +14,9 @@ package com.google.gerrit.sshd; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.gerrit.common.FileUtil; import com.google.gerrit.reviewdb.client.AccountSshKey; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.PeerDaemonUser; @@ -33,10 +36,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; -import java.io.File; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.security.KeyPair; import java.security.PublicKey; import java.util.Collection; @@ -170,56 +173,50 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator { } private static class PeerKeyCache { - private final File path; + private final Path path; private final long modified; final Set keys; - PeerKeyCache(final File path) { + PeerKeyCache(Path path) { this.path = path; - this.modified = path.lastModified(); + this.modified = FileUtil.lastModified(path); this.keys = read(path); } - private static Set read(File path) { - try { - final BufferedReader br = new BufferedReader(new FileReader(path)); - try { - final Set keys = new HashSet<>(); - String line; - while ((line = br.readLine()) != null) { - line = line.trim(); - if (line.startsWith("#") || line.isEmpty()) { - continue; - } - - try { - byte[] bin = Base64.decodeBase64(line.getBytes("ISO-8859-1")); - keys.add(new Buffer(bin).getRawPublicKey()); - } catch (RuntimeException e) { - logBadKey(path, line, e); - } catch (SshException e) { - logBadKey(path, line, e); - } + private static Set read(Path path) { + try (BufferedReader br = Files.newBufferedReader(path, UTF_8)) { + final Set keys = new HashSet<>(); + String line; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.startsWith("#") || line.isEmpty()) { + continue; + } + + try { + byte[] bin = Base64.decodeBase64(line.getBytes("ISO-8859-1")); + keys.add(new Buffer(bin).getRawPublicKey()); + } catch (RuntimeException e) { + logBadKey(path, line, e); + } catch (SshException e) { + logBadKey(path, line, e); } - return Collections.unmodifiableSet(keys); - } finally { - br.close(); } + return Collections.unmodifiableSet(keys); } catch (FileNotFoundException noFile) { return Collections.emptySet(); - } catch (IOException err) { log.error("Cannot read " + path, err); return Collections.emptySet(); } } - private static void logBadKey(File path, String line, Exception e) { + private static void logBadKey(Path path, String line, Exception e) { log.warn("Invalid key in " + path + ":\n " + line, e); } boolean isCurrent() { - return path.lastModified() == modified; + return modified == FileUtil.lastModified(path); } PeerKeyCache reload() { diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java index 241f853412..3e6e2f5821 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java @@ -24,7 +24,8 @@ import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; -import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -38,29 +39,29 @@ class HostKeyProvider implements Provider { @Override public KeyPairProvider get() { - final File objKey = site.ssh_key; - final File rsaKey = site.ssh_rsa; - final File dsaKey = site.ssh_dsa; + Path objKey = site.ssh_key; + Path rsaKey = site.ssh_rsa; + Path dsaKey = site.ssh_dsa; final List stdKeys = new ArrayList<>(2); - if (rsaKey.exists()) { - stdKeys.add(rsaKey.getAbsolutePath()); + if (Files.exists(rsaKey)) { + stdKeys.add(rsaKey.toAbsolutePath().toString()); } - if (dsaKey.exists()) { - stdKeys.add(dsaKey.getAbsolutePath()); + if (Files.exists(dsaKey)) { + stdKeys.add(dsaKey.toAbsolutePath().toString()); } - if (objKey.exists()) { + if (Files.exists(objKey)) { if (stdKeys.isEmpty()) { SimpleGeneratorHostKeyProvider p = new SimpleGeneratorHostKeyProvider(); - p.setPath(objKey.getAbsolutePath()); + p.setPath(objKey.toAbsolutePath().toString()); return p; } else { // Both formats of host key exist, we don't know which format // should be authoritative. Complain and abort. // - stdKeys.add(objKey.getAbsolutePath()); + stdKeys.add(objKey.toAbsolutePath().toString()); throw new ProvisionException("Multiple host keys exist: " + stdKeys); }