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:
David Pursehouse 2015-04-06 13:07:47 +00:00 committed by Gerrit Code Review
commit e43b1b10b1
9 changed files with 178 additions and 34 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}};
}
});

View File

@ -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);

View File

@ -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'],
)

View File

@ -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,
)