From 85fbc79605d886b2b4ec02aa8cfb5b8b05436576 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 10 Apr 2014 18:58:07 -0400
Subject: [PATCH] Authenticate SSH upload pack
---
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java | 120 +++++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 90 insertions(+), 30 deletions(-)
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
index 672f024..597b9ea 100644
--- a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
+++ b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
@@ -16,18 +16,23 @@
import java.io.IOException;
import java.io.StringWriter;
+import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
-import javax.inject.Provider;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Argument;
+import com.gitblit.git.GitblitReceivePackFactory;
+import com.gitblit.git.GitblitUploadPackFactory;
+import com.gitblit.git.RepositoryResolver;
+import com.gitblit.transport.ssh.AbstractGitCommand;
import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.SshSession;
import com.gitblit.utils.cli.SubcommandHandler;
import com.google.common.base.Charsets;
import com.google.common.base.Strings;
@@ -42,28 +47,34 @@
@Argument(index = 1, multiValued = true, metaVar = "ARG")
private List<String> args = new ArrayList<String>();
- private Set<Provider<Command>> commands;
- private Map<String, Provider<Command>> map;
+ private Set<Class<? extends Command>> commands;
+ private Map<String, Class<? extends Command>> map;
+ private Map<String, Command> root;
- public DispatchCommand() {}
-
- public DispatchCommand(Map<String, Provider<Command>> map) {
- this.map = map;
+ public DispatchCommand() {
+ commands = new HashSet<Class<? extends Command>>();
}
- public void setMap(Map<String, Provider<Command>> m) {
- map = m;
+ public void registerDispatcher(String name, Command cmd) {
+ if (root == null) {
+ root = Maps.newHashMap();
+ }
+ root.put(name, cmd);
}
- public DispatchCommand(Set<Provider<Command>> commands) {
- this.commands = commands;
+ public void registerCommand(Class<? extends Command> cmd) {
+ if (!cmd.isAnnotationPresent(CommandMetaData.class)) {
+ throw new RuntimeException(MessageFormat.format("{0} must be annotated with {1}!",
+ cmd.getName(), CommandMetaData.class.getName()));
+ }
+ commands.add(cmd);
}
- private Map<String, Provider<Command>> getMap() {
+ private Map<String, Class<? extends Command>> getMap() {
if (map == null) {
map = Maps.newHashMapWithExpectedSize(commands.size());
- for (Provider<Command> cmd : commands) {
- CommandMetaData meta = cmd.get().getClass().getAnnotation(CommandMetaData.class);
+ for (Class<? extends Command> cmd : commands) {
+ CommandMetaData meta = cmd.getAnnotation(CommandMetaData.class);
map.put(meta.name(), cmd);
}
}
@@ -80,15 +91,7 @@
throw new UnloggedFailure(1, msg.toString());
}
- final Provider<Command> p = getMap().get(commandName);
- if (p == null) {
- String msg =
- (getName().isEmpty() ? "Gitblit" : getName()) + ": "
- + commandName + ": not found";
- throw new UnloggedFailure(1, msg);
- }
-
- final Command cmd = p.get();
+ Command cmd = getCommand();
if (cmd instanceof BaseCommand) {
BaseCommand bc = (BaseCommand) cmd;
if (getName().isEmpty()) {
@@ -97,11 +100,11 @@
bc.setName(getName() + " " + commandName);
}
bc.setArguments(args.toArray(new String[args.size()]));
- } else if (!args.isEmpty()) {
- throw new UnloggedFailure(1, commandName + " does not take arguments");
}
- provideStateTo(cmd);
+ provideBaseStateTo(cmd);
+ provideGitState(cmd);
+ reset();
//atomicCmd.set(cmd);
cmd.start(env);
@@ -116,6 +119,28 @@
}
}
+ private Command getCommand() throws UnloggedFailure {
+ if (root != null && root.containsKey(commandName)) {
+ return root.get(commandName);
+ }
+ final Class<? extends Command> c = getMap().get(commandName);
+ if (c == null) {
+ String msg =
+ (getName().isEmpty() ? "Gitblit" : getName()) + ": "
+ + commandName + ": not found";
+ throw new UnloggedFailure(1, msg);
+ }
+
+ Command cmd = null;
+ try {
+ cmd = c.newInstance();
+ } catch (Exception e) {
+ throw new UnloggedFailure(1, MessageFormat.format("Failed to instantiate {0} command", commandName));
+ }
+ return cmd;
+ }
+
+ @Override
protected String usage() {
final StringBuilder usage = new StringBuilder();
usage.append("Available commands");
@@ -127,15 +152,15 @@
usage.append("\n");
int maxLength = -1;
- Map<String, Provider<Command>> m = getMap();
+ Map<String, Class<? extends Command>> m = getMap();
for (String name : m.keySet()) {
maxLength = Math.max(maxLength, name.length());
}
String format = "%-" + maxLength + "s %s";
for (String name : Sets.newTreeSet(m.keySet())) {
- final Provider<Command> p = m.get(name);
+ final Class<? extends Command> c = m.get(name);
usage.append(" ");
- CommandMetaData meta = p.get().getClass().getAnnotation(CommandMetaData.class);
+ CommandMetaData meta = c.getAnnotation(CommandMetaData.class);
if (meta != null) {
usage.append(String.format(format, name,
Strings.nullToEmpty(meta.description())));
@@ -153,4 +178,39 @@
usage.append("\n");
return usage.toString();
}
+
+ // This is needed because we are not using provider or
+ // clazz.newInstance() for DispatchCommand
+ private void reset() {
+ args = new ArrayList<String>();
+ }
+
+ private void provideGitState(Command cmd) {
+ if (cmd instanceof AbstractGitCommand) {
+ AbstractGitCommand a = (AbstractGitCommand) cmd;
+ a.setRepositoryResolver(repositoryResolver);
+ a.setUploadPackFactory(gitblitUploadPackFactory);
+ a.setReceivePackFactory(gitblitReceivePackFactory);
+ } else if (cmd instanceof DispatchCommand) {
+ DispatchCommand d = (DispatchCommand)cmd;
+ d.setRepositoryResolver(repositoryResolver);
+ d.setUploadPackFactory(gitblitUploadPackFactory);
+ d.setReceivePackFactory(gitblitReceivePackFactory);
+ }
+ }
+
+ private RepositoryResolver<SshSession> repositoryResolver;
+ public void setRepositoryResolver(RepositoryResolver<SshSession> repositoryResolver) {
+ this.repositoryResolver = repositoryResolver;
+ }
+
+ private GitblitUploadPackFactory<SshSession> gitblitUploadPackFactory;
+ public void setUploadPackFactory(GitblitUploadPackFactory<SshSession> gitblitUploadPackFactory) {
+ this.gitblitUploadPackFactory = gitblitUploadPackFactory;
+ }
+
+ private GitblitReceivePackFactory<SshSession> gitblitReceivePackFactory;
+ public void setReceivePackFactory(GitblitReceivePackFactory<SshSession> gitblitReceivePackFactory) {
+ this.gitblitReceivePackFactory = gitblitReceivePackFactory;
+ }
}
--
Gitblit v1.9.1