Bump SSHD version to 0.9.0.201311081
With new Mina project release two backends are supported Mina & NIO2. Expose new NIO2 backend through new configuration option while preserving the Mina backend to be default. Remove the fake to turn off closing idle connections by using the highest timeout allowed by Apache SSD (~24 days). That special treatment is not needed any more. Restrict `sshd.tcpKeepAlive` configuration option to be used only for Mina backend. Remove `sshd.reuseAddress` (it is per default true) as there is no obvious way how to set it. SSHD 0.9.0 incorrectly sends "Authenticated with..." message: davido@wizball:>ssh gerrit cookbook say-hello Dude Authenticated with partial success. Hello Dude! That bug is tracked under [1]. With that patch applied the problem with "Authenticated with partial success." is solved. Gerrit's Maven repository contains 0.9.0.201311081 which is 0.9.0 with [2] cherry-picked on top. [1] https://issues.apache.org/jira/browse/SSHD-254 [2] https://github.com/apache/mina-sshd/pull/2 Bug: issue 2003 Change-Id: Ic352d7e6a9e6f8ab4122b2667ead24ac3d73f68a
This commit is contained in:
@@ -2269,6 +2269,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
|
||||
@@ -2307,20 +2315,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::
|
||||
|
||||
@@ -25,8 +25,8 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
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;
|
||||
@@ -178,12 +178,13 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
||||
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) {
|
||||
final Context ctx = sshScope.newContext(null, sd, null);
|
||||
final Context old = sshScope.set(ctx);
|
||||
public void operationComplete(CloseFuture future) {
|
||||
Context ctx = sshScope.newContext(null, sd, null);
|
||||
Context old = sshScope.set(ctx);
|
||||
try {
|
||||
sshLog.onLogout();
|
||||
} finally {
|
||||
|
||||
@@ -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,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) {
|
||||
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() {
|
||||
|
||||
@@ -30,8 +30,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;
|
||||
@@ -275,8 +276,12 @@ final class ShowCaches extends CacheCommand {
|
||||
long now = System.currentTimeMillis();
|
||||
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(
|
||||
|
||||
@@ -25,8 +25,10 @@ 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;
|
||||
|
||||
@@ -62,11 +64,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());
|
||||
}
|
||||
});
|
||||
@@ -80,8 +88,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 %.30s\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.
|
||||
#
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -582,13 +582,13 @@ limitations under the License.
|
||||
<dependency>
|
||||
<groupId>org.apache.mina</groupId>
|
||||
<artifactId>mina-core</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.sshd</groupId>
|
||||
<artifactId>sshd-core</artifactId>
|
||||
<version>0.6.0</version>
|
||||
<version>0.9.0.201311081</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
Reference in New Issue
Block a user