Update MINA SSHD to 0.3.0-r881338

We specifically install the ChannelDirectTcpip channel factory
so that the daemon understands this protocol feature but our
TcpIpForwardFilter automatically rejects all connection attempts made
by a client.  This will cause nice error messages to be reported
back, letting the user know their port forwarding was denied,
rather than generating an obtuse error message in the client.

Even if we skipped the ChannelDirectTcpip session factory we must
install the TcpIpForwardFilter.  If we don't MINA SSHD would permit
any client to listen for inbound connections on any of our local
ports and redirect them to the client's own server of choice.

We also now specifically configure the subsystem list to be empty.
This is to disable any SFTP support inherited from MINA SSHD,
we actually don't want to service SFTP for anything at this time.
We might consider enabling SFTP off the same virtual filesystem we
use for scp, but its not a very important feature.

Bug: issue 336
Change-Id: I7a64601524ca84f308b76357290c456dc4613b67
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-11-17 09:32:32 -08:00
parent 06b68d60a4
commit f95d6459b1
24 changed files with 135 additions and 60 deletions

View File

@@ -23,8 +23,9 @@ import com.google.gerrit.util.cli.CmdLineParser;
import com.google.inject.Inject;
import org.apache.sshd.common.SshException;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.CommandFactory.ExitCallback;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.session.ServerSession;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
@@ -101,6 +102,10 @@ public abstract class BaseCommand implements Command {
this.commandLine = line;
}
@Override
public void destroy() {
}
/**
* Pass all state into the command, then run its start method.
* <p>
@@ -195,7 +200,8 @@ public abstract class BaseCommand implements Command {
/**
* Spawn a function into its own thread.
* <p>
* Typically this should be invoked within {@link Command#start()}, such as:
* Typically this should be invoked within {@link Command#start(Environment)},
* such as:
*
* <pre>
* startThread(new Runnable() {
@@ -220,7 +226,8 @@ public abstract class BaseCommand implements Command {
/**
* Spawn a function into its own thread.
* <p>
* Typically this should be invoked within {@link Command#start()}, such as:
* Typically this should be invoked within {@link Command#start(Environment)},
* such as:
*
* <pre>
* startThread(new CommandRunnable() {

View File

@@ -18,10 +18,11 @@ import com.google.gerrit.sshd.SshScopes.Context;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.CommandFactory.ExitCallback;
import org.apache.sshd.server.CommandFactory.SessionAware;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.SessionAware;
import org.apache.sshd.server.session.ServerSession;
import java.io.IOException;
@@ -56,6 +57,8 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
private OutputStream err;
private ExitCallback exit;
private ServerSession session;
private Context ctx;
private DispatchCommand cmd;
Trampoline(final String cmdLine) {
commandLine = cmdLine;
@@ -81,19 +84,40 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
this.session = session;
}
public void start() throws IOException {
final Context old = SshScopes.current.get();
try {
SshScopes.current.set(new Context(session));
final DispatchCommand c = dispatcher.get();
c.setCommandLine(commandLine);
c.setInputStream(in);
c.setOutputStream(out);
c.setErrorStream(err);
c.setExitCallback(exit);
c.start();
} finally {
SshScopes.current.set(old);
public void start(final Environment env) throws IOException {
synchronized (this) {
final Context old = SshScopes.current.get();
try {
ctx = new Context(session);
SshScopes.current.set(ctx);
cmd = dispatcher.get();
cmd.setCommandLine(commandLine);
cmd.setInputStream(in);
cmd.setOutputStream(out);
cmd.setErrorStream(err);
cmd.setExitCallback(exit);
cmd.start(env);
} finally {
SshScopes.current.set(old);
}
}
}
@Override
public void destroy() {
synchronized (this) {
if (cmd != null) {
final Context old = SshScopes.current.get();
try {
SshScopes.current.set(ctx);
cmd.destroy();
} finally {
ctx = null;
cmd = null;
SshScopes.current.set(old);
}
}
}
}
}

View File

@@ -17,7 +17,7 @@ package com.google.gerrit.sshd;
import com.google.inject.AbstractModule;
import com.google.inject.binder.LinkedBindingBuilder;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.Command;
/** Module to register commands in the SSH daemon. */
public abstract class CommandModule extends AbstractModule {

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.sshd;
import com.google.inject.Key;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.Command;
import java.lang.annotation.Annotation;
@@ -28,17 +28,17 @@ public class Commands {
/** Magic value signaling the top level. */
public static final CommandName CMD_ROOT = named(ROOT);
public static Key<CommandFactory.Command> key(final String name) {
public static Key<Command> key(final String name) {
return key(named(name));
}
public static Key<CommandFactory.Command> key(final CommandName name) {
return Key.get(CommandFactory.Command.class, name);
public static Key<Command> key(final CommandName name) {
return Key.get(Command.class, name);
}
public static Key<CommandFactory.Command> key(final CommandName parent,
public static Key<Command> key(final CommandName parent,
final String name) {
return Key.get(CommandFactory.Command.class, named(parent, name));
return Key.get(Command.class, named(parent, name));
}
/** Create a CommandName annotation for the supplied name. */

View File

@@ -43,8 +43,8 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
schema = sf;
}
public boolean hasKey(final String username, final PublicKey suppliedKey,
final ServerSession session) {
public boolean authenticate(final String username,
final PublicKey suppliedKey, final ServerSession session) {
final Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
final SshKeyCacheEntry key = find(keyList, suppliedKey);
if (key == null) {

View File

@@ -19,7 +19,8 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -46,7 +47,7 @@ final class DispatchCommand extends BaseCommand {
}
@Override
public void start() throws IOException {
public void start(final Environment env) throws IOException {
if (commandLine.isEmpty()) {
usage();
return;
@@ -92,7 +93,7 @@ final class DispatchCommand extends BaseCommand {
bc.setCommandPrefix(commandPrefix + " " + name);
bc.setCommandLine(args);
}
cmd.start();
cmd.start(env);
} else {
final String msg = prefix + ": " + name + ": not found\n";
err.write(msg.getBytes(ENC));

View File

@@ -20,7 +20,7 @@ import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.Command;
import java.lang.annotation.Annotation;
import java.util.Collections;

View File

@@ -14,7 +14,10 @@
package com.google.gerrit.sshd;
import org.apache.sshd.server.ShellFactory;
import org.apache.sshd.common.Factory;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.eclipse.jgit.lib.Constants;
import java.io.IOException;
@@ -28,9 +31,9 @@ import java.io.OutputStream;
* server without supplying a command will get a reasonable error message, but
* cannot continue further.
*/
class NoShell implements ShellFactory {
public Shell createShell() {
return new Shell() {
class NoShell implements Factory<Command> {
public Command create() {
return new Command() {
private InputStream in;
private OutputStream out;
private OutputStream err;

View File

@@ -29,6 +29,7 @@ import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
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.KeyExchange;
@@ -53,17 +54,18 @@ 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.PublickeyAuthenticator;
import org.apache.sshd.server.ServerChannel;
import org.apache.sshd.server.SessionFactory;
import org.apache.sshd.server.TcpIpForwardFilter;
import org.apache.sshd.server.UserAuth;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.auth.UserAuthPublicKey;
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;
import org.slf4j.LoggerFactory;
@@ -158,6 +160,8 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
initMacs(cfg);
initSignatures();
initChannels();
initTcpIpForwardFilter();
initSubsystems();
initCompression();
initUserAuth(userAuth);
setKeyPairProvider(hostKeyProvider);
@@ -495,8 +499,15 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
@SuppressWarnings("unchecked")
private void initChannels() {
setChannelFactories(Arrays
.<NamedFactory<ServerChannel>> asList(new ChannelSession.Factory()));
setChannelFactories(Arrays.<NamedFactory<Channel>> asList(
new ChannelSession.Factory(), //
new ChannelDirectTcpip.Factory() //
));
}
@SuppressWarnings("unchecked")
private void initSubsystems() {
setSubsystemFactories(Collections.<NamedFactory<Command>> emptyList());
}
@SuppressWarnings("unchecked")
@@ -505,4 +516,18 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
.<NamedFactory<UserAuth>> asList(new UserAuthPublicKey.Factory()));
setPublickeyAuthenticator(pubkey);
}
private void initTcpIpForwardFilter() {
setTcpIpForwardFilter(new TcpIpForwardFilter() {
@Override
public boolean canConnect(InetSocketAddress address, ServerSession session) {
return false;
}
@Override
public boolean canListen(InetSocketAddress address, ServerSession session) {
return false;
}
});
}
}

View File

@@ -19,7 +19,7 @@ import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.Scope;
import org.apache.sshd.common.session.AttributeKey;
import org.apache.sshd.common.Session.AttributeKey;
import org.apache.sshd.server.session.ServerSession;
import java.util.HashMap;

View File

@@ -19,9 +19,9 @@ import com.google.gerrit.reviewdb.AccountSshKey;
import org.apache.commons.codec.binary.Base64;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.session.AttributeKey;
import org.apache.sshd.common.Session.AttributeKey;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.Command;
import org.eclipse.jgit.lib.Constants;
import java.io.BufferedReader;

View File

@@ -20,9 +20,10 @@ import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.sshd.BaseCommand;
import com.google.inject.Inject;
import org.kohsuke.args4j.Argument;
import org.apache.sshd.server.Environment;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;
import org.kohsuke.args4j.Argument;
import java.io.IOException;
@@ -37,7 +38,7 @@ abstract class AbstractGitCommand extends BaseCommand {
protected Project project;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -29,6 +29,7 @@ import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Transaction;
import com.google.inject.Inject;
import org.apache.sshd.server.Environment;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.kohsuke.args4j.Option;
@@ -76,7 +77,7 @@ final class AdminCreateProject extends BaseCommand {
private ReplicationQueue rq;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -18,6 +18,7 @@ import com.google.gerrit.sshd.AdminCommand;
import net.sf.ehcache.Ehcache;
import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Option;
import java.io.PrintWriter;
@@ -40,7 +41,7 @@ final class AdminFlushCaches extends CacheCommand {
private PrintWriter p;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -22,6 +22,7 @@ import com.google.gerrit.sshd.AdminCommand;
import com.google.gerrit.sshd.BaseCommand;
import com.google.inject.Inject;
import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
@@ -51,7 +52,7 @@ final class AdminReplicate extends BaseCommand {
private ProjectCache projectCache;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -20,6 +20,7 @@ import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Statistics;
import net.sf.ehcache.config.CacheConfiguration;
import org.apache.sshd.server.Environment;
import org.eclipse.jgit.lib.WindowCacheStatAccessor;
import java.io.PrintWriter;
@@ -30,7 +31,7 @@ final class AdminShowCaches extends CacheCommand {
private PrintWriter p;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -23,7 +23,8 @@ import com.google.inject.Inject;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IoSession;
import org.apache.sshd.server.CommandFactory.Command;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.session.ServerSession;
import org.kohsuke.args4j.Option;
@@ -50,7 +51,7 @@ final class AdminShowConnections extends BaseCommand {
private SshDaemon daemon;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -20,6 +20,8 @@ import com.google.gerrit.sshd.AdminCommand;
import com.google.gerrit.sshd.BaseCommand;
import com.google.inject.Inject;
import org.apache.sshd.server.Environment;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Collections;
@@ -37,7 +39,7 @@ final class AdminShowQueue extends BaseCommand {
private PrintWriter p;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -41,6 +41,7 @@ import com.google.gwtorm.client.ResultSet;
import com.google.gwtorm.client.Transaction;
import com.google.inject.Inject;
import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
@@ -109,7 +110,7 @@ public class ApproveCommand extends BaseCommand {
private List<ApproveOption> optionList;
@Override
public final void start() {
public final void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Failure {

View File

@@ -16,6 +16,8 @@ package com.google.gerrit.sshd.commands;
import com.google.gerrit.sshd.BaseCommand;
import org.apache.sshd.server.Environment;
import java.io.IOException;
/**
@@ -25,7 +27,7 @@ import java.io.IOException;
*/
final class ErrorSlaveMode extends BaseCommand {
@Override
public void start() {
public void start(final Environment env) {
String msg =
"error: That command is disabled on this server.\n\n"
+ "Please use the master server URL.\n";

View File

@@ -24,6 +24,8 @@ import com.google.gerrit.sshd.BaseCommand;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import org.apache.sshd.server.Environment;
import java.io.PrintWriter;
final class ListProjects extends BaseCommand {
@@ -41,7 +43,7 @@ final class ListProjects extends BaseCommand {
private Project.NameKey wildProject;
@Override
public void start() {
public void start(final Environment env) {
startThread(new CommandRunnable() {
@Override
public void run() throws Exception {

View File

@@ -25,9 +25,10 @@ package com.google.gerrit.sshd.commands;
import com.google.gerrit.common.Version;
import com.google.gerrit.sshd.BaseCommand;
import org.apache.sshd.server.Environment;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.jgit.util.RawParseUtils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
@@ -89,7 +90,7 @@ final class ScpCommand extends BaseCommand {
}
@Override
public void start() {
public void start(final Environment env) {
startThread(new Runnable() {
public void run() {
runImp();

View File

@@ -22,6 +22,7 @@ log4j.logger.com.google.gerrit=INFO
# Silence non-critical messages from MINA SSHD.
#
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

View File

@@ -534,7 +534,7 @@ limitations under the License.
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>0.2.0</version>
<version>0.3.0-r881338</version>
</dependency>
<dependency>