diff options
Diffstat (limited to 'gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java')
-rw-r--r-- | gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java | 120 |
1 files changed, 73 insertions, 47 deletions
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java index c43de60d7f..1d03953795 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java @@ -15,10 +15,10 @@ 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; +import com.google.common.collect.Lists; import com.google.gerrit.common.Version; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.server.config.ConfigUtil; @@ -34,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; @@ -55,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; @@ -62,32 +73,31 @@ 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.channel.ChannelDirectTcpip; +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.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; import org.slf4j.LoggerFactory; +import java.io.File; import java.io.IOException; -import java.net.InetSocketAddress; +import java.net.InetAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.PublicKey; @@ -120,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; @@ -137,7 +152,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, @@ -154,12 +168,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))); @@ -171,6 +179,14 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener { String.valueOf(maxConnectionsPerUser)); } + 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 { @@ -180,7 +196,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener { initMacs(cfg); initSignatures(); initChannels(); - initForwardingFilter(); + initForwarding(); initFileSystemFactory(); initSubsystems(); initCompression(); @@ -190,24 +206,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); } @@ -215,6 +235,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(); @@ -233,13 +259,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); @@ -247,7 +271,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())); } } @@ -461,7 +486,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() // )); } @@ -476,28 +501,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) { - return false; + public boolean canForwardAgent(Session session) { + return false; } @Override - public boolean canForwardX11(ServerSession session) { - return false; + public boolean canForwardX11(Session session) { + return false; } @Override - public boolean canConnect(InetSocketAddress address, ServerSession session) { - return false; + public boolean canListen(SshdSocketAddress address, Session session) { + return false; } @Override - public boolean canListen(InetSocketAddress address, ServerSession session) { - return false; + public boolean canConnect(SshdSocketAddress address, Session session) { + return false; } }); + setTcpipForwarderFactory(new DefaultTcpipForwarderFactory()); } private void initFileSystemFactory() { |