Catch Bouncy Castle Crypto not installed when loading SSH keys

If the Bouncy Castle Crypto library isn't installed but the site
administrator has created PEM encoded host keys for the server
we should let them know the library is missing, rather than throw
a more obtuse NoClassDefError from deep within the PEM reader.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-08-17 19:54:44 -07:00
parent 0f49e51d03
commit c88ecad3c9
3 changed files with 83 additions and 42 deletions

View File

@@ -0,0 +1,77 @@
// 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.server.ssh;
import com.google.gerrit.server.config.SitePath;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import org.apache.sshd.common.KeyPairProvider;
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.util.ArrayList;
import java.util.List;
class HostKeyProvider implements Provider<KeyPairProvider> {
private final File sitePath;
@Inject
HostKeyProvider(@SitePath final File sitePath) {
this.sitePath = sitePath;
}
@Override
public KeyPairProvider get() {
final File anyKey = new File(sitePath, "ssh_host_key");
final File rsaKey = new File(sitePath, "ssh_host_rsa_key");
final File dsaKey = new File(sitePath, "ssh_host_dsa_key");
final List<String> keys = new ArrayList<String>(2);
if (rsaKey.exists()) {
keys.add(rsaKey.getAbsolutePath());
}
if (dsaKey.exists()) {
keys.add(dsaKey.getAbsolutePath());
}
if (anyKey.exists() && !keys.isEmpty()) {
// If both formats of host key exist, we don't know which format
// should be authoritative. Complain and abort.
//
keys.add(anyKey.getAbsolutePath());
throw new ProvisionException("Multiple host keys exist: " + keys);
}
if (keys.isEmpty()) {
// No administrator created host key? Generate and save our own.
//
final SimpleGeneratorHostKeyProvider keyp;
keyp = new SimpleGeneratorHostKeyProvider();
keyp.setPath(anyKey.getAbsolutePath());
return keyp;
}
if (!SecurityUtils.isBouncyCastleRegistered()) {
throw new ProvisionException("Bouncy Castle Crypto not installed;"
+ " needed to read server host keys: " + keys + "");
}
return new FileKeyPairProvider(keys.toArray(new String[keys.size()]));
}
}

View File

@@ -16,7 +16,6 @@ package com.google.gerrit.server.ssh;
import com.google.gerrit.server.GerritServer;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePath;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Singleton;
@@ -39,7 +38,6 @@ import org.apache.sshd.common.cipher.BlowfishCBC;
import org.apache.sshd.common.cipher.CipherNone;
import org.apache.sshd.common.cipher.TripleDESCBC;
import org.apache.sshd.common.compression.CompressionNone;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.common.mac.HMACMD5;
import org.apache.sshd.common.mac.HMACMD596;
import org.apache.sshd.common.mac.HMACSHA1;
@@ -60,13 +58,11 @@ import org.apache.sshd.server.auth.UserAuthPublicKey;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.kex.DHG1;
import org.apache.sshd.server.kex.DHG14;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spearce.jgit.lib.Config;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -105,8 +101,7 @@ import java.util.List;
public class SshDaemon extends SshServer implements SshInfo {
private static final int DEFAULT_PORT = 29418;
private static final Logger log =
LoggerFactory.getLogger(SshDaemon.class);
private static final Logger log = LoggerFactory.getLogger(SshDaemon.class);
private static String format(final SocketAddress addr) {
if (addr instanceof InetSocketAddress) {
@@ -132,7 +127,8 @@ public class SshDaemon extends SshServer implements SshInfo {
@Inject
SshDaemon(final GerritServer srv, final CommandFactory commandFactory,
final PublickeyAuthenticator userAuth, @SitePath final File sitePath,
final PublickeyAuthenticator userAuth,
final KeyPairProvider hostKeyProvider,
@GerritServerConfig final Config cfg) {
setPort(22/* never used */);
@@ -151,7 +147,7 @@ public class SshDaemon extends SshServer implements SshInfo {
initChannels();
initCompression();
initUserAuth(userAuth);
setKeyPairProvider(initHostKey(sitePath));
setKeyPairProvider(hostKeyProvider);
setCommandFactory(commandFactory);
setShellFactory(new NoShell());
setSessionFactory(new SessionFactory() {
@@ -481,38 +477,4 @@ public class SshDaemon extends SshServer implements SshInfo {
.<NamedFactory<UserAuth>> asList(new UserAuthPublicKey.Factory()));
setPublickeyAuthenticator(pubkey);
}
private KeyPairProvider initHostKey(final File sitePath) {
final File anyKey = new File(sitePath, "ssh_host_key");
final File rsaKey = new File(sitePath, "ssh_host_rsa_key");
final File dsaKey = new File(sitePath, "ssh_host_dsa_key");
final List<String> keys = new ArrayList<String>(2);
if (rsaKey.exists()) {
keys.add(rsaKey.getAbsolutePath());
}
if (dsaKey.exists()) {
keys.add(dsaKey.getAbsolutePath());
}
if (anyKey.exists() && !keys.isEmpty()) {
// If both formats of host key exist, we don't know which format
// should be authoritative. Complain and abort.
//
keys.add(anyKey.getAbsolutePath());
throw new IllegalStateException("Multiple host keys exist: " + keys);
}
if (keys.isEmpty()) {
// No administrator created host key? Generate and save our own.
//
final SimpleGeneratorHostKeyProvider keyp;
keyp = new SimpleGeneratorHostKeyProvider();
keyp.setPath(anyKey.getAbsolutePath());
return keyp;
}
return new FileKeyPairProvider(keys.toArray(new String[keys.size()]));
}
}

View File

@@ -26,6 +26,7 @@ import com.google.inject.Provider;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.SessionScoped;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PublickeyAuthenticator;
@@ -54,6 +55,7 @@ public class SshModule extends FactoryModule {
bind(CommandFactory.class).toProvider(CommandFactoryProvider.class);
bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class);
bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON);
install(new DefaultCommandModule());
}