Enable SSH daemon cipher and MAC configuration
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -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`
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@@ -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(
|
||||||
|
Reference in New Issue
Block a user