Merge changes from topic 'sshd-upgrade-0.14' into stable-2.10
* changes: Revert "Revert "Allow configuration of SSH rekey values"" Revert "Revert "SSHD: Allow ECDSA based public key authentication"" Revert "Revert "SSHD: Prevent double authentication for the same public key"" Revert "Downgrade SSHD to 0.9.0-4-g5967cfd"
This commit is contained in:
commit
e43b1b10b1
|
@ -2863,6 +2863,14 @@ namespace. To alias `replication start` to `gerrit replicate`:
|
|||
[[sshd]]
|
||||
=== Section sshd
|
||||
|
||||
[[sshd.backend]]sshd.backend::
|
||||
+
|
||||
Starting from version 0.9.0 Apache SSHD project added support for NIO2
|
||||
IoSession. To use the new NIO2 session the `backend` option must be set
|
||||
to `NIO2`.
|
||||
+
|
||||
By default, `MINA`.
|
||||
|
||||
[[sshd.listenAddress]]sshd.listenAddress::
|
||||
+
|
||||
Specifies the local addresses the internal SSHD should listen
|
||||
|
@ -3064,6 +3072,24 @@ programmatic configuration.
|
|||
+
|
||||
By default, true.
|
||||
|
||||
[[sshd.rekeyBytesLimit]]sshd.rekeyBytesLimit::
|
||||
+
|
||||
The SSH daemon will issue a rekeying after a certain amount of data.
|
||||
This configuration option allows you to tweak that setting.
|
||||
+
|
||||
By default, 1073741824 (bytes, 1GB).
|
||||
+
|
||||
The rekeyBytesLimit cannot be set to lower than 32.
|
||||
|
||||
[[sshd.rekeyTimeLimit]]sshd.rekeyTimeLimit::
|
||||
+
|
||||
The SSH daemon will issue a rekeying after a certain amount of time.
|
||||
This configuration option allows you to tweak that setting.
|
||||
+
|
||||
By default, 1h.
|
||||
+
|
||||
Set to 0 to disable this check.
|
||||
|
||||
[[suggest]]
|
||||
=== Section suggest
|
||||
|
||||
|
|
|
@ -15,16 +15,16 @@
|
|||
|
||||
# Version should match lib/bouncycastle/BUCK
|
||||
[library "bouncyCastleProvider"]
|
||||
name = Bouncy Castle Crypto Provider v149
|
||||
url = http://www.bouncycastle.org/download/bcprov-jdk15on-149.jar
|
||||
sha1 = f5155f04330459104b79923274db5060c1057b99
|
||||
name = Bouncy Castle Crypto Provider v151
|
||||
url = http://www.bouncycastle.org/download/bcprov-jdk15on-151.jar
|
||||
sha1 = 9ab8afcc2842d5ef06eb775a0a2b12783b99aa80
|
||||
remove = bcprov-.*[.]jar
|
||||
|
||||
# Version should match lib/bouncycastle/BUCK
|
||||
[library "bouncyCastleSSL"]
|
||||
name = Bouncy Castle Crypto SSL v149
|
||||
url = http://www.bouncycastle.org/download/bcpkix-jdk15on-149.jar
|
||||
sha1 = 924cc7ad2f589630c97b918f044296ebf1bb6855
|
||||
name = Bouncy Castle Crypto SSL v151
|
||||
url = http://www.bouncycastle.org/download/bcpkix-jdk15on-151.jar
|
||||
sha1 = 6c8c1f61bf27a09f9b1a8abc201523669bba9597
|
||||
needs = bouncyCastleProvider
|
||||
remove = bcpkix-.*[.]jar
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ import org.bouncycastle.openpgp.PGPPublicKey;
|
|||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||
import org.bouncycastle.openpgp.PGPUtil;
|
||||
import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRingCollection;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -167,12 +170,16 @@ class EncryptedContactStore implements ContactStore {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private final PGPEncryptedDataGenerator cpk()
|
||||
throws NoSuchProviderException, PGPException {
|
||||
final BcPGPDataEncryptorBuilder builder =
|
||||
new BcPGPDataEncryptorBuilder(PGPEncryptedData.CAST5)
|
||||
.setSecureRandom(prng);
|
||||
PGPEncryptedDataGenerator cpk =
|
||||
new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, true, prng, "BC");
|
||||
cpk.addMethod(dest);
|
||||
new PGPEncryptedDataGenerator(builder, true);
|
||||
final BcPublicKeyKeyEncryptionMethodGenerator methodGenerator =
|
||||
new BcPublicKeyKeyEncryptionMethodGenerator(dest);
|
||||
cpk.addMethod(methodGenerator);
|
||||
return cpk;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (C) 2014 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.sshd;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.apache.sshd.common.Session;
|
||||
import org.apache.sshd.common.SessionListener;
|
||||
import org.apache.sshd.server.PublickeyAuthenticator;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Singleton
|
||||
public class CachingPublicKeyAuthenticator implements PublickeyAuthenticator,
|
||||
SessionListener {
|
||||
|
||||
private final PublickeyAuthenticator authenticator;
|
||||
private final Map<ServerSession, Map<PublicKey, Boolean>> sessionCache;
|
||||
|
||||
@Inject
|
||||
public CachingPublicKeyAuthenticator(DatabasePubKeyAuth authenticator) {
|
||||
this.authenticator = authenticator;
|
||||
this.sessionCache = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(String username, PublicKey key,
|
||||
ServerSession session) {
|
||||
Map<PublicKey, Boolean> m = sessionCache.get(session);
|
||||
if (m == null) {
|
||||
m = new HashMap<>();
|
||||
sessionCache.put(session, m);
|
||||
session.addListener(this);
|
||||
}
|
||||
if (m.containsKey(key)) {
|
||||
return m.get(key);
|
||||
}
|
||||
boolean r = authenticator.authenticate(username, key, session);
|
||||
m.put(key, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionCreated(Session session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionEvent(Session sesssion, Event event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionClosed(Session session) {
|
||||
sessionCache.remove(session);
|
||||
}
|
||||
}
|
|
@ -14,13 +14,16 @@
|
|||
|
||||
package com.google.gerrit.sshd;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.gerrit.common.FileUtil;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gerrit.reviewdb.client.AccountSshKey;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.PeerDaemonUser;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.sshd.common.KeyPairProvider;
|
||||
|
@ -48,7 +51,6 @@ import java.util.Set;
|
|||
/**
|
||||
* Authenticates by public key through {@link AccountSshKey} entities.
|
||||
*/
|
||||
@Singleton
|
||||
class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
||||
private static final Logger log =
|
||||
LoggerFactory.getLogger(DatabasePubKeyAuth.class);
|
||||
|
@ -92,10 +94,11 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean authenticate(String username,
|
||||
final PublicKey suppliedKey, final ServerSession session) {
|
||||
final SshSession sd = session.getAttribute(SshSession.KEY);
|
||||
|
||||
@Override
|
||||
public boolean authenticate(String username, PublicKey suppliedKey,
|
||||
ServerSession session) {
|
||||
SshSession sd = session.getAttribute(SshSession.KEY);
|
||||
Preconditions.checkState(sd.getCurrentUser() == null);
|
||||
if (PeerDaemonUser.USER_NAME.equals(username)) {
|
||||
if (myHostKeys.contains(suppliedKey)
|
||||
|| getPeerKeys().contains(suppliedKey)) {
|
||||
|
@ -112,10 +115,10 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||
username = username.toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
final Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
|
||||
final SshKeyCacheEntry key = find(keyList, suppliedKey);
|
||||
Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
|
||||
SshKeyCacheEntry key = find(keyList, suppliedKey);
|
||||
if (key == null) {
|
||||
final String err;
|
||||
String err;
|
||||
if (keyList == SshKeyCacheImpl.NO_SUCH_USER) {
|
||||
err = "user-not-found";
|
||||
} else if (keyList == SshKeyCacheImpl.NO_KEYS) {
|
||||
|
@ -133,7 +136,7 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||
// security check to ensure there aren't two users sharing the same
|
||||
// user name on the server.
|
||||
//
|
||||
for (final SshKeyCacheEntry otherKey : keyList) {
|
||||
for (SshKeyCacheEntry otherKey : keyList) {
|
||||
if (!key.getAccount().equals(otherKey.getAccount())) {
|
||||
sd.authenticationError(username, "keys-cross-accounts");
|
||||
return false;
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.apache.sshd.common.ForwardingFilter;
|
|||
import org.apache.sshd.common.KeyExchange;
|
||||
import org.apache.sshd.common.KeyPairProvider;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.common.RequestHandler;
|
||||
import org.apache.sshd.common.Session;
|
||||
import org.apache.sshd.common.Signature;
|
||||
import org.apache.sshd.common.SshdSocketAddress;
|
||||
|
@ -67,10 +68,11 @@ import org.apache.sshd.common.forward.TcpipServerChannel;
|
|||
import org.apache.sshd.common.future.CloseFuture;
|
||||
import org.apache.sshd.common.future.SshFutureListener;
|
||||
import org.apache.sshd.common.io.IoAcceptor;
|
||||
import org.apache.sshd.common.io.IoServiceFactory;
|
||||
import org.apache.sshd.common.io.IoServiceFactoryFactory;
|
||||
import org.apache.sshd.common.io.IoSession;
|
||||
import org.apache.sshd.common.io.mina.MinaServiceFactory;
|
||||
import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
|
||||
import org.apache.sshd.common.io.mina.MinaSession;
|
||||
import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
|
||||
import org.apache.sshd.common.mac.HMACMD5;
|
||||
import org.apache.sshd.common.mac.HMACMD596;
|
||||
import org.apache.sshd.common.mac.HMACSHA1;
|
||||
|
@ -79,7 +81,9 @@ import org.apache.sshd.common.random.BouncyCastleRandom;
|
|||
import org.apache.sshd.common.random.JceRandom;
|
||||
import org.apache.sshd.common.random.SingletonRandomFactory;
|
||||
import org.apache.sshd.common.session.AbstractSession;
|
||||
import org.apache.sshd.common.session.ConnectionService;
|
||||
import org.apache.sshd.common.signature.SignatureDSA;
|
||||
import org.apache.sshd.common.signature.SignatureECDSA;
|
||||
import org.apache.sshd.common.signature.SignatureRSA;
|
||||
import org.apache.sshd.common.util.Buffer;
|
||||
import org.apache.sshd.common.util.SecurityUtils;
|
||||
|
@ -91,6 +95,10 @@ import org.apache.sshd.server.auth.UserAuthPublicKey;
|
|||
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
|
||||
import org.apache.sshd.server.auth.gss.UserAuthGSS;
|
||||
import org.apache.sshd.server.channel.ChannelSession;
|
||||
import org.apache.sshd.server.global.CancelTcpipForwardHandler;
|
||||
import org.apache.sshd.server.global.KeepAliveHandler;
|
||||
import org.apache.sshd.server.global.NoMoreSessionsHandler;
|
||||
import org.apache.sshd.server.global.TcpipForwardHandler;
|
||||
import org.apache.sshd.server.kex.DHG1;
|
||||
import org.apache.sshd.server.kex.DHG14;
|
||||
import org.apache.sshd.server.session.SessionFactory;
|
||||
|
@ -181,6 +189,15 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
|||
IDLE_TIMEOUT,
|
||||
String.valueOf(SECONDS.toMillis(idleTimeoutSeconds)));
|
||||
|
||||
long rekeyTimeLimit = ConfigUtil.getTimeUnit(cfg, "sshd", null,
|
||||
"rekeyTimeLimit", 3600, SECONDS);
|
||||
getProperties().put(
|
||||
REKEY_TIME_LIMIT,
|
||||
String.valueOf(SECONDS.toMillis(rekeyTimeLimit)));
|
||||
|
||||
getProperties().put(REKEY_BYTES_LIMIT,
|
||||
String.valueOf(cfg.getLong("sshd", "rekeyBytesLimit", 1024 * 1024 * 1024 /* 1GB */)));
|
||||
|
||||
final int maxConnectionsPerUser =
|
||||
cfg.getInt("sshd", "maxConnectionsPerUser", 64);
|
||||
if (0 < maxConnectionsPerUser) {
|
||||
|
@ -193,8 +210,13 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
|||
final String kerberosPrincipal = cfg.getString(
|
||||
"sshd", null, "kerberosPrincipal");
|
||||
|
||||
System.setProperty(IoServiceFactory.class.getName(),
|
||||
MinaServiceFactory.class.getName());
|
||||
SshSessionBackend backend = cfg.getEnum(
|
||||
"sshd", null, "backend", SshSessionBackend.MINA);
|
||||
|
||||
System.setProperty(IoServiceFactoryFactory.class.getName(),
|
||||
backend == SshSessionBackend.MINA
|
||||
? MinaServiceFactoryFactory.class.getName()
|
||||
: Nio2ServiceFactoryFactory.class.getName());
|
||||
|
||||
if (SecurityUtils.isBouncyCastleRegistered()) {
|
||||
initProviderBouncyCastle();
|
||||
|
@ -251,6 +273,12 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
|||
return new GerritServerSession(server, ioSession);
|
||||
}
|
||||
});
|
||||
setGlobalRequestHandlers(Arrays.<RequestHandler<ConnectionService>> asList(
|
||||
new KeepAliveHandler(),
|
||||
new NoMoreSessionsHandler(),
|
||||
new TcpipForwardHandler(),
|
||||
new CancelTcpipForwardHandler()
|
||||
));
|
||||
|
||||
hostKeys = computeHostKeys();
|
||||
}
|
||||
|
@ -492,7 +520,11 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
|||
|
||||
private void initSignatures() {
|
||||
setSignatureFactories(Arrays.<NamedFactory<Signature>> asList(
|
||||
new SignatureDSA.Factory(), new SignatureRSA.Factory()));
|
||||
new SignatureDSA.Factory(),
|
||||
new SignatureRSA.Factory(),
|
||||
new SignatureECDSA.NISTP256Factory(),
|
||||
new SignatureECDSA.NISTP384Factory(),
|
||||
new SignatureECDSA.NISTP521Factory()));
|
||||
}
|
||||
|
||||
private void initCompression() {
|
||||
|
@ -587,6 +619,11 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
|||
@Override
|
||||
public SshFile getFile(String file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileSystemView getNormalizedView() {
|
||||
return this;
|
||||
}};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -81,7 +81,7 @@ public class SshModule extends LifecycleModule {
|
|||
bind(QueueProvider.class).to(CommandExecutorQueueProvider.class).in(SINGLETON);
|
||||
|
||||
bind(GSSAuthenticator.class).to(GerritGSSAuthenticator.class);
|
||||
bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class);
|
||||
bind(PublickeyAuthenticator.class).to(CachingPublicKeyAuthenticator.class);
|
||||
|
||||
bind(ModuleGenerator.class).to(SshAutoRegisterModuleGenerator.class);
|
||||
bind(SshPluginStarterCallback.class);
|
||||
|
|
|
@ -2,19 +2,19 @@ include_defs('//lib/maven.defs')
|
|||
|
||||
# This version must match the version that also appears in
|
||||
# gerrit-pgm/src/main/resources/com/google/gerrit/pgm/libraries.config
|
||||
VERSION = '1.49'
|
||||
VERSION = '1.51'
|
||||
|
||||
maven_jar(
|
||||
name = 'bcprov',
|
||||
id = 'org.bouncycastle:bcprov-jdk15on:' + VERSION,
|
||||
sha1 = 'f5155f04330459104b79923274db5060c1057b99',
|
||||
sha1 = '9ab8afcc2842d5ef06eb775a0a2b12783b99aa80',
|
||||
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
name = 'bcpg',
|
||||
id = 'org.bouncycastle:bcpg-jdk15on:' + VERSION,
|
||||
sha1 = '081d84be5b125e1997ab0e2244d1a2276b5de76c',
|
||||
sha1 = 'b5fa4c280dfbf8bf7c260bc1e78044c7a1de5133',
|
||||
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
|
||||
deps = [':bcprov'],
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ maven_jar(
|
|||
maven_jar(
|
||||
name = 'bcpkix',
|
||||
id = 'org.bouncycastle:bcpkix-jdk15on:' + VERSION,
|
||||
sha1 = '924cc7ad2f589630c97b918f044296ebf1bb6855',
|
||||
sha1 = '6c8c1f61bf27a09f9b1a8abc201523669bba9597',
|
||||
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
|
||||
deps = [':bcprov'],
|
||||
)
|
||||
|
|
|
@ -8,18 +8,17 @@ EXCLUDE = [
|
|||
|
||||
maven_jar(
|
||||
name = 'sshd',
|
||||
id = 'org.apache.sshd:sshd-core:0.9.0-4-g5967cfd',
|
||||
sha1 = '449ec11c4417b295dbf1661585a50c6ec7d9a452',
|
||||
id = 'org.apache.sshd:sshd-core:0.14.0',
|
||||
sha1 = 'cb12fa1b1b07fb5ce3aa4f99b189743897bd4fca',
|
||||
license = 'Apache2.0',
|
||||
deps = [':core'],
|
||||
exclude = EXCLUDE,
|
||||
repository = GERRIT,
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
name = 'core',
|
||||
id = 'org.apache.mina:mina-core:2.0.7',
|
||||
sha1 = 'c878e2aa82de748474a624ec3933e4604e446dec',
|
||||
id = 'org.apache.mina:mina-core:2.0.8',
|
||||
sha1 = 'd6ff69fa049aeaecdf0c04cafbb1ab53b7487883',
|
||||
license = 'Apache2.0',
|
||||
exclude = EXCLUDE,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue