Merge branch 'stable-2.7' into stable-2.8
* stable-2.7: Bump SSHD version to 0.9.0.201311081 Conflicts: gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java pom.xml Change-Id: I29487ae1efb5bdf6f18fc76fe14790a530481c9f
This commit is contained in:
@@ -2507,6 +2507,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
|
||||
@@ -2545,20 +2553,13 @@ of them.
|
||||
+
|
||||
By default, sshd.listenAddress.
|
||||
|
||||
[[sshd.reuseAddress]]sshd.reuseAddress::
|
||||
+
|
||||
If true, permits the daemon to bind to the port even if the port
|
||||
is already in use. If false, the daemon ensures the port is not
|
||||
in use before starting. Busy sites may need to set this to true
|
||||
to permit fast restarts.
|
||||
+
|
||||
By default, true.
|
||||
|
||||
[[sshd.tcpKeepAlive]]sshd.tcpKeepAlive::
|
||||
+
|
||||
If true, enables TCP keepalive messages to the other side, so
|
||||
the daemon can terminate connections if the peer disappears.
|
||||
+
|
||||
Only effective when `sshd.backend` is set to `MINA`.
|
||||
+
|
||||
By default, true.
|
||||
|
||||
[[sshd.threads]]sshd.threads::
|
||||
|
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2013 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 org.apache.sshd.common.future.CloseFuture;
|
||||
import org.apache.sshd.common.future.SshFutureListener;
|
||||
import org.apache.sshd.common.io.IoSession;
|
||||
import org.apache.sshd.server.ServerFactoryManager;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
|
||||
/* Expose addition of close session listeners */
|
||||
class GerritServerSession extends ServerSession {
|
||||
|
||||
GerritServerSession(ServerFactoryManager server,
|
||||
IoSession ioSession) throws Exception {
|
||||
super(server, ioSession);
|
||||
}
|
||||
|
||||
void addCloseSessionListener(SshFutureListener<CloseFuture> l) {
|
||||
closeFuture.addListener(l);
|
||||
}
|
||||
}
|
@@ -15,7 +15,6 @@
|
||||
package com.google.gerrit.sshd;
|
||||
|
||||
import static com.google.gerrit.server.ssh.SshAddressesModule.IANA_SSH_PORT;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
@@ -35,20 +34,18 @@ import com.google.inject.Singleton;
|
||||
import com.jcraft.jsch.HostKey;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
|
||||
import org.apache.mina.core.future.IoFuture;
|
||||
import org.apache.mina.core.future.IoFutureListener;
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.transport.socket.SocketSessionConfig;
|
||||
import org.apache.sshd.SshServer;
|
||||
import org.apache.sshd.common.Channel;
|
||||
import org.apache.sshd.common.Cipher;
|
||||
import org.apache.sshd.common.Compression;
|
||||
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.Session;
|
||||
import org.apache.sshd.common.Signature;
|
||||
import org.apache.sshd.common.SshdSocketAddress;
|
||||
import org.apache.sshd.common.cipher.AES128CBC;
|
||||
import org.apache.sshd.common.cipher.AES192CBC;
|
||||
import org.apache.sshd.common.cipher.AES256CBC;
|
||||
@@ -56,6 +53,19 @@ 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.file.FileSystemFactory;
|
||||
import org.apache.sshd.common.file.FileSystemView;
|
||||
import org.apache.sshd.common.file.SshFile;
|
||||
import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
|
||||
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.IoSession;
|
||||
import org.apache.sshd.common.io.mina.MinaServiceFactory;
|
||||
import org.apache.sshd.common.io.mina.MinaSession;
|
||||
import org.apache.sshd.common.io.nio2.Nio2ServiceFactory;
|
||||
import org.apache.sshd.common.mac.HMACMD5;
|
||||
import org.apache.sshd.common.mac.HMACMD596;
|
||||
import org.apache.sshd.common.mac.HMACSHA1;
|
||||
@@ -63,26 +73,21 @@ import org.apache.sshd.common.mac.HMACSHA196;
|
||||
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.signature.SignatureDSA;
|
||||
import org.apache.sshd.common.signature.SignatureRSA;
|
||||
import org.apache.sshd.common.util.Buffer;
|
||||
import org.apache.sshd.common.util.SecurityUtils;
|
||||
import org.apache.sshd.server.Command;
|
||||
import org.apache.sshd.server.CommandFactory;
|
||||
import org.apache.sshd.server.FileSystemFactory;
|
||||
import org.apache.sshd.server.FileSystemView;
|
||||
import org.apache.sshd.server.ForwardingFilter;
|
||||
import org.apache.sshd.server.PublickeyAuthenticator;
|
||||
import org.apache.sshd.server.SshFile;
|
||||
import org.apache.sshd.server.UserAuth;
|
||||
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.ChannelDirectTcpip;
|
||||
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.session.ServerSession;
|
||||
import org.apache.sshd.server.session.SessionFactory;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.slf4j.Logger;
|
||||
@@ -91,7 +96,6 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.InvalidKeyException;
|
||||
@@ -126,6 +130,11 @@ import java.util.List;
|
||||
public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
private static final Logger log = LoggerFactory.getLogger(SshDaemon.class);
|
||||
|
||||
public static enum SshSessionBackend {
|
||||
MINA,
|
||||
NIO2
|
||||
}
|
||||
|
||||
private final List<SocketAddress> listen;
|
||||
private final List<String> advertised;
|
||||
private final boolean keepAlive;
|
||||
@@ -144,7 +153,6 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
|
||||
this.listen = listen;
|
||||
this.advertised = advertised;
|
||||
reuseAddress = cfg.getBoolean("sshd", "reuseaddress", true);
|
||||
keepAlive = cfg.getBoolean("sshd", "tcpkeepalive", true);
|
||||
|
||||
getProperties().put(SERVER_IDENTIFICATION,
|
||||
@@ -161,12 +169,6 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
|
||||
long idleTimeoutSeconds = ConfigUtil.getTimeUnit(cfg, "sshd", null,
|
||||
"idleTimeout", 0, SECONDS);
|
||||
if (idleTimeoutSeconds == 0) {
|
||||
// Since Apache SSHD does not allow to turn off closing idle connections,
|
||||
// we fake it by using the highest timeout allowed by Apache SSHD, which
|
||||
// amounts to ~24 days.
|
||||
idleTimeoutSeconds = MILLISECONDS.toSeconds(Integer.MAX_VALUE);
|
||||
}
|
||||
getProperties().put(
|
||||
IDLE_TIMEOUT,
|
||||
String.valueOf(SECONDS.toMillis(idleTimeoutSeconds)));
|
||||
@@ -183,6 +185,14 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
final String kerberosPrincipal = cfg.getString(
|
||||
"sshd", null, "kerberosPrincipal");
|
||||
|
||||
SshSessionBackend backend = cfg.getEnum(
|
||||
"sshd", null, "backend", SshSessionBackend.MINA);
|
||||
|
||||
System.setProperty(IoServiceFactory.class.getName(),
|
||||
backend == SshSessionBackend.MINA
|
||||
? MinaServiceFactory.class.getName()
|
||||
: Nio2ServiceFactory.class.getName());
|
||||
|
||||
if (SecurityUtils.isBouncyCastleRegistered()) {
|
||||
initProviderBouncyCastle();
|
||||
} else {
|
||||
@@ -192,7 +202,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
initMacs(cfg);
|
||||
initSignatures();
|
||||
initChannels();
|
||||
initForwardingFilter();
|
||||
initForwarding();
|
||||
initFileSystemFactory();
|
||||
initSubsystems();
|
||||
initCompression();
|
||||
@@ -202,24 +212,28 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
setShellFactory(noShell);
|
||||
setSessionFactory(new SessionFactory() {
|
||||
@Override
|
||||
protected ServerSession createSession(final IoSession io)
|
||||
protected AbstractSession createSession(final IoSession io)
|
||||
throws Exception {
|
||||
if (io.getConfig() instanceof SocketSessionConfig) {
|
||||
final SocketSessionConfig c = (SocketSessionConfig) io.getConfig();
|
||||
c.setKeepAlive(keepAlive);
|
||||
if (io instanceof MinaSession) {
|
||||
if (((MinaSession) io).getSession()
|
||||
.getConfig() instanceof SocketSessionConfig) {
|
||||
((SocketSessionConfig) ((MinaSession) io).getSession()
|
||||
.getConfig())
|
||||
.setKeepAlive(keepAlive);
|
||||
}
|
||||
}
|
||||
|
||||
final ServerSession s = (ServerSession) super.createSession(io);
|
||||
final int id = idGenerator.next();
|
||||
final SocketAddress peer = io.getRemoteAddress();
|
||||
GerritServerSession s = (GerritServerSession)super.createSession(io);
|
||||
int id = idGenerator.next();
|
||||
SocketAddress peer = io.getRemoteAddress();
|
||||
final SshSession sd = new SshSession(id, peer);
|
||||
s.setAttribute(SshSession.KEY, sd);
|
||||
|
||||
// Log a session close without authentication as a failure.
|
||||
//
|
||||
io.getCloseFuture().addListener(new IoFutureListener<IoFuture>() {
|
||||
s.addCloseSessionListener(new SshFutureListener<CloseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(IoFuture future) {
|
||||
public void operationComplete(CloseFuture future) {
|
||||
if (sd.isAuthenticationError()) {
|
||||
sshLog.onAuthFail(sd);
|
||||
}
|
||||
@@ -227,6 +241,12 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSession doCreateSession(IoSession ioSession)
|
||||
throws Exception {
|
||||
return new GerritServerSession(server, ioSession);
|
||||
}
|
||||
});
|
||||
|
||||
hostKeys = computeHostKeys();
|
||||
@@ -245,13 +265,11 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
public synchronized void start() {
|
||||
if (acceptor == null && !listen.isEmpty()) {
|
||||
checkConfig();
|
||||
|
||||
if (sessionFactory == null) {
|
||||
sessionFactory = createSessionFactory();
|
||||
}
|
||||
sessionFactory.setServer(this);
|
||||
acceptor = createAcceptor();
|
||||
configure(acceptor);
|
||||
|
||||
final SessionFactory handler = getSessionFactory();
|
||||
handler.setServer(this);
|
||||
acceptor.setHandler(handler);
|
||||
|
||||
try {
|
||||
acceptor.bind(listen);
|
||||
@@ -259,7 +277,8 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
throw new IllegalStateException("Cannot bind to " + addressList(), e);
|
||||
}
|
||||
|
||||
log.info("Started Gerrit SSHD on " + addressList());
|
||||
log.info(String.format("Started Gerrit %s on %s",
|
||||
version, addressList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,7 +492,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
private void initChannels() {
|
||||
setChannelFactories(Arrays.<NamedFactory<Channel>> asList(
|
||||
new ChannelSession.Factory(), //
|
||||
new ChannelDirectTcpip.Factory() //
|
||||
new TcpipServerChannel.DirectTcpipFactory() //
|
||||
));
|
||||
}
|
||||
|
||||
@@ -514,28 +533,29 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
setPublickeyAuthenticator(pubkey);
|
||||
}
|
||||
|
||||
private void initForwardingFilter() {
|
||||
setForwardingFilter(new ForwardingFilter() {
|
||||
private void initForwarding() {
|
||||
setTcpipForwardingFilter(new ForwardingFilter() {
|
||||
@Override
|
||||
public boolean canForwardAgent(ServerSession session) {
|
||||
public boolean canForwardAgent(Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canForwardX11(ServerSession session) {
|
||||
public boolean canForwardX11(Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnect(InetSocketAddress address, ServerSession session) {
|
||||
public boolean canListen(SshdSocketAddress address, Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canListen(InetSocketAddress address, ServerSession session) {
|
||||
public boolean canConnect(SshdSocketAddress address, Session session) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
setTcpipForwarderFactory(new DefaultTcpipForwarderFactory());
|
||||
}
|
||||
|
||||
private void initFileSystemFactory() {
|
||||
|
@@ -21,8 +21,8 @@ import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.sshd.SshScope.Context;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.mina.core.future.IoFuture;
|
||||
import org.apache.mina.core.future.IoFutureListener;
|
||||
import org.apache.sshd.common.future.CloseFuture;
|
||||
import org.apache.sshd.common.future.SshFutureListener;
|
||||
import org.apache.sshd.common.KeyPairProvider;
|
||||
import org.apache.sshd.common.SshException;
|
||||
import org.apache.sshd.common.util.Buffer;
|
||||
@@ -138,10 +138,11 @@ public class SshUtil {
|
||||
sshScope.set(old);
|
||||
}
|
||||
|
||||
session.getIoSession().getCloseFuture().addListener(
|
||||
new IoFutureListener<IoFuture>() {
|
||||
GerritServerSession s = (GerritServerSession) session;
|
||||
s.addCloseSessionListener(
|
||||
new SshFutureListener<CloseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(IoFuture future) {
|
||||
public void operationComplete(CloseFuture future) {
|
||||
final Context ctx = sshScope.newContext(null, sd, null);
|
||||
final Context old = sshScope.set(ctx);
|
||||
try {
|
||||
|
@@ -32,8 +32,9 @@ import com.google.gerrit.sshd.SshDaemon;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.sshd.common.io.IoAcceptor;
|
||||
import org.apache.sshd.common.io.IoSession;
|
||||
import org.apache.sshd.common.io.mina.MinaSession;
|
||||
import org.apache.sshd.server.Environment;
|
||||
import org.eclipse.jgit.internal.storage.file.WindowCacheStatAccessor;
|
||||
import org.kohsuke.args4j.Option;
|
||||
@@ -274,8 +275,12 @@ final class ShowCaches extends CacheCommand {
|
||||
long now = TimeUtil.nowMs();
|
||||
Collection<IoSession> list = acceptor.getManagedSessions().values();
|
||||
long oldest = now;
|
||||
|
||||
for (IoSession s : list) {
|
||||
oldest = Math.min(oldest, s.getCreationTime());
|
||||
if (s instanceof MinaSession) {
|
||||
MinaSession minaSession = (MinaSession)s;
|
||||
oldest = Math.min(oldest, minaSession.getSession().getCreationTime());
|
||||
}
|
||||
}
|
||||
|
||||
stdout.format(
|
||||
|
@@ -26,8 +26,9 @@ import com.google.gerrit.sshd.SshDaemon;
|
||||
import com.google.gerrit.sshd.SshSession;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.sshd.common.io.IoAcceptor;
|
||||
import org.apache.sshd.common.io.IoSession;
|
||||
import org.apache.sshd.common.io.mina.MinaSession;
|
||||
import org.apache.sshd.server.Environment;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
import org.kohsuke.args4j.Option;
|
||||
@@ -84,11 +85,17 @@ final class ShowConnections extends SshCommand {
|
||||
Collections.sort(list, new Comparator<IoSession>() {
|
||||
@Override
|
||||
public int compare(IoSession arg0, IoSession arg1) {
|
||||
if (arg0.getCreationTime() < arg1.getCreationTime()) {
|
||||
if (arg0 instanceof MinaSession) {
|
||||
MinaSession mArg0 = (MinaSession) arg0;
|
||||
MinaSession mArg1 = (MinaSession) arg1;
|
||||
if (mArg0.getSession().getCreationTime() < mArg1.getSession()
|
||||
.getCreationTime()) {
|
||||
return -1;
|
||||
} else if (arg0.getCreationTime() > arg1.getCreationTime()) {
|
||||
} else if (mArg0.getSession().getCreationTime() > mArg1.getSession()
|
||||
.getCreationTime()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return (int) (arg0.getId() - arg1.getId());
|
||||
}
|
||||
});
|
||||
@@ -104,8 +111,15 @@ final class ShowConnections extends SshCommand {
|
||||
SshSession sd = s != null ? s.getAttribute(SshSession.KEY) : null;
|
||||
|
||||
final SocketAddress remoteAddress = io.getRemoteAddress();
|
||||
final long start = io.getCreationTime();
|
||||
final long idle = now - io.getLastIoTime();
|
||||
MinaSession minaSession = io instanceof MinaSession
|
||||
? (MinaSession) io
|
||||
: null;
|
||||
final long start = minaSession == null
|
||||
? 0
|
||||
: minaSession.getSession().getCreationTime();
|
||||
final long idle = minaSession == null
|
||||
? now
|
||||
: now - minaSession.getSession().getLastIoTime();
|
||||
|
||||
stdout.print(String.format("%8s %8s %8s %-15.15s %s\n", //
|
||||
id(sd), //
|
||||
|
@@ -26,7 +26,7 @@ log4j.logger.org.apache.mina=WARN
|
||||
log4j.logger.org.apache.sshd.common=WARN
|
||||
log4j.logger.org.apache.sshd.server=WARN
|
||||
log4j.logger.org.apache.sshd.common.keyprovider.FileKeyPairProvider=INFO
|
||||
log4j.logger.com.google.gerrit.server.ssh.GerritServerSession=WARN
|
||||
log4j.logger.com.google.gerrit.sshd.GerritServerSession=WARN
|
||||
|
||||
# Silence non-critical messages from Jetty.
|
||||
#
|
||||
|
@@ -8,17 +8,18 @@ EXCLUDE = [
|
||||
|
||||
maven_jar(
|
||||
name = 'core',
|
||||
id = 'org.apache.mina:mina-core:2.0.5',
|
||||
sha1 = '0e134a3761833a3c28c79331e806f64f985a9eec',
|
||||
id = 'org.apache.mina:mina-core:2.0.7',
|
||||
sha1 = 'c878e2aa82de748474a624ec3933e4604e446dec',
|
||||
license = 'Apache2.0',
|
||||
exclude = EXCLUDE,
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
name = 'sshd',
|
||||
id = 'org.apache.sshd:sshd-core:0.6.0',
|
||||
sha1 = '2b9a119dd77a1decec78b0c511ba400c8655e96e',
|
||||
id = 'org.apache.sshd:sshd-core:0.9.0.201311081',
|
||||
sha1 = '38f7ac8602e70fa05fdc6147d204198e9cefe5bc',
|
||||
license = 'Apache2.0',
|
||||
deps = [':core'],
|
||||
exclude = EXCLUDE,
|
||||
repository = GERRIT,
|
||||
)
|
||||
|
Reference in New Issue
Block a user