Enable SSH daemon cipher and MAC configuration

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-05-14 11:02:03 -07:00
parent fc9081f462
commit 0bf2f52fd1
2 changed files with 103 additions and 11 deletions

View File

@@ -200,6 +200,32 @@ the daemon can terminate connections if the peer disappears.
+ +
By default, true. By default, true.
sshd.cipher::
+
Available ciphers. To permit multiple ciphers, specify multiple
`sshd.cipher` keys in the configuration file, one cipher name
per key. Cipher names starting with `+` are enabled in addition
to the default ciphers, cipher names starting with `-` are removed
from the default cipher set.
+
Supported ciphers: aes128-cbc, aes128-cbc, aes256-cbc, blowfish-cbc,
3des-cbc, none.
+
By default, all supported ciphers except `none` are available.
sshd.mac::
+
Available MAC (message authentication code) algorithms. To permit
multiple algorithms, specify multiple `sshd.mac` keys in the
configuration file, one MAC per key. MAC names starting with `+`
are enabled in addition to the default MACs, MAC names starting with
`-` are removed from the default MACs.
+
Supported MACs: hmac-md5, hmac-md5-96, hmac-sha1, hmac-sha1-96.
+
By default, all supported MACs are available.
File `replication.config` File `replication.config`
------------------------- -------------------------

View File

@@ -24,17 +24,16 @@ import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.sshd.SshServer; import org.apache.sshd.SshServer;
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.Compression; import org.apache.sshd.common.Compression;
import org.apache.sshd.common.KeyExchange; import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.Mac;
import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Signature; import org.apache.sshd.common.Signature;
import org.apache.sshd.common.cipher.AES128CBC; import org.apache.sshd.common.cipher.AES128CBC;
import org.apache.sshd.common.cipher.AES192CBC; import org.apache.sshd.common.cipher.AES192CBC;
import org.apache.sshd.common.cipher.AES256CBC; import org.apache.sshd.common.cipher.AES256CBC;
import org.apache.sshd.common.cipher.BlowfishCBC; 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.cipher.TripleDESCBC;
import org.apache.sshd.common.compression.CompressionNone; import org.apache.sshd.common.compression.CompressionNone;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
@@ -169,8 +168,8 @@ public class GerritSshDaemon extends SshServer {
} else { } else {
initProviderJce(); initProviderJce();
} }
initCipers(); initCiphers(cfg);
initMac(); initMacs(cfg);
initSignatures(); initSignatures();
initChannels(); initChannels();
initCompression(); initCompression();
@@ -236,20 +235,87 @@ public class GerritSshDaemon extends SshServer {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void initCipers() { private void initCiphers(final RepositoryConfig cfg) {
setCipherFactories(Arrays.<NamedFactory<Cipher>> asList( setCipherFactories(filter(cfg, "cipher", new AES128CBC.Factory(),
new AES128CBC.Factory(), new TripleDESCBC.Factory(), new TripleDESCBC.Factory(), new BlowfishCBC.Factory(),
new BlowfishCBC.Factory(), new AES192CBC.Factory(), new AES192CBC.Factory(), new AES256CBC.Factory(),
new AES256CBC.Factory()));
null, new CipherNone.Factory()));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void initMac() { private void initMacs(final RepositoryConfig cfg) {
setMacFactories(Arrays.<NamedFactory<Mac>> asList(new HMACMD5.Factory(), setMacFactories(filter(cfg, "mac", new HMACMD5.Factory(),
new HMACSHA1.Factory(), new HMACMD596.Factory(), new HMACSHA1.Factory(), new HMACMD596.Factory(),
new HMACSHA196.Factory())); new HMACSHA196.Factory()));
} }
private static <T> List<NamedFactory<T>> filter(final RepositoryConfig cfg,
final String key, final NamedFactory<T>... avail) {
final ArrayList<NamedFactory<T>> def = new ArrayList<NamedFactory<T>>();
for (final NamedFactory<T> n : avail) {
if (n == null) {
break;
}
def.add(n);
}
final String[] want = cfg.getStringList("sshd", null, key);
if (want == null || want.length == 0) {
return def;
}
boolean didClear = false;
for (final String setting : want) {
String name = setting.trim();
boolean add = true;
if (name.startsWith("-")) {
add = false;
name = name.substring(1).trim();
} else if (name.startsWith("+")) {
name = name.substring(1).trim();
} else if (!didClear) {
didClear = true;
def.clear();
}
final NamedFactory<T> n = find(name, avail);
if (n == null) {
final StringBuilder msg = new StringBuilder();
msg.append("sshd." + key + " = " + name + " unsupported; only ");
for (int i = 0; i < avail.length; i++) {
if (avail[i] == null) {
continue;
}
if (i > 0) {
msg.append(", ");
}
msg.append(avail[i].getName());
}
msg.append(" is supported");
log.error(msg.toString());
} else if (add) {
if (!def.contains(n)) {
def.add(n);
}
} else {
def.remove(n);
}
}
return def;
}
private static <T> NamedFactory<T> find(final String name,
final NamedFactory<T>... avail) {
for (final NamedFactory<T> n : avail) {
if (n != null && name.equals(n.getName())) {
return n;
}
}
return null;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void initSignatures() { private void initSignatures() {
setSignatureFactories(Arrays.<NamedFactory<Signature>> asList( setSignatureFactories(Arrays.<NamedFactory<Signature>> asList(