Allow suexec to run any command as any user
The suexec command can only be run by a peer daemon, and permits the daemon to execute another command as a specific user identity. This is the foundation of allowing writes to be proxied from a slave server into the master, the slave just needs to SSH into the master and use suexec in front of the user supplied command line to perform an action on their behalf on the master. Unfortunately this means we have to trust the slave process, as it can become anyone, including an administrator. A better approach would be to use agent authentication and authenticate back through the slave to the user's agent process, but not every user connection may be using an agent. In particular batch jobs might be using an unencrypted key and no agent to authenticate. Change-Id: Icb8ddb16959f01189a6c0bdfc8fec45cdd99659b Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -28,6 +28,8 @@ import org.apache.sshd.server.session.ServerSession;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Creates a CommandFactory using commands registered by {@link CommandModule}.
|
||||
@@ -55,6 +57,7 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
|
||||
|
||||
private class Trampoline implements Command, SessionAware {
|
||||
private final String commandLine;
|
||||
private final String[] argv;
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
private OutputStream err;
|
||||
@@ -65,6 +68,7 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
|
||||
|
||||
Trampoline(final String cmdLine) {
|
||||
commandLine = cmdLine;
|
||||
argv = split(cmdLine);
|
||||
}
|
||||
|
||||
public void setInputStream(final InputStream in) {
|
||||
@@ -84,7 +88,8 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
|
||||
}
|
||||
|
||||
public void setSession(final ServerSession session) {
|
||||
this.ctx = new Context(session.getAttribute(SshSession.KEY));
|
||||
final SshSession s = session.getAttribute(SshSession.KEY);
|
||||
this.ctx = new Context(s, commandLine);
|
||||
}
|
||||
|
||||
public void start(final Environment env) throws IOException {
|
||||
@@ -92,7 +97,7 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
|
||||
final Context old = SshScope.set(ctx);
|
||||
try {
|
||||
cmd = dispatcher.get();
|
||||
cmd.setCommandLine(commandLine);
|
||||
cmd.setArguments(argv);
|
||||
cmd.setInputStream(in);
|
||||
cmd.setOutputStream(out);
|
||||
cmd.setErrorStream(err);
|
||||
@@ -135,8 +140,7 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
|
||||
private void log(final int rc) {
|
||||
synchronized (this) {
|
||||
if (!logged) {
|
||||
ctx.finished = System.currentTimeMillis();
|
||||
log.onExecute(ctx, commandLine, rc);
|
||||
log.onExecute(rc);
|
||||
logged = true;
|
||||
}
|
||||
}
|
||||
@@ -159,4 +163,41 @@ class CommandFactoryProvider implements Provider<CommandFactory> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Split a command line into a string array. */
|
||||
static String[] split(String commandLine) {
|
||||
final List<String> list = new ArrayList<String>();
|
||||
boolean inquote = false;
|
||||
StringBuilder r = new StringBuilder();
|
||||
for (int ip = 0; ip < commandLine.length();) {
|
||||
final char b = commandLine.charAt(ip++);
|
||||
switch (b) {
|
||||
case '\t':
|
||||
case ' ':
|
||||
if (inquote)
|
||||
r.append(b);
|
||||
else if (r.length() > 0) {
|
||||
list.add(r.toString());
|
||||
r = new StringBuilder();
|
||||
}
|
||||
continue;
|
||||
case '\'':
|
||||
inquote = !inquote;
|
||||
continue;
|
||||
case '\\':
|
||||
if (inquote || ip == commandLine.length())
|
||||
r.append(b); // literal within a quote
|
||||
else
|
||||
r.append(commandLine.charAt(ip++));
|
||||
continue;
|
||||
default:
|
||||
r.append(b);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (r.length() > 0) {
|
||||
list.add(r.toString());
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user