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 : }
|