summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 38cc7ab)
raw | patch | inline | side by side (parent: 38cc7ab)
author | Linus Torvalds <torvalds@osdl.org> | |
Sun, 23 Oct 2005 21:30:45 +0000 (14:30 -0700) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Mon, 24 Oct 2005 22:12:41 +0000 (15:12 -0700) |
This adds a very git specific restricted shell, that can be
added to /etc/shells and set to the pw_shell in the /etc/passwd
file, to give users ability to push into repositories over ssh
without giving them full interactive shell acount.
[jc: I updated Linus' patch to match what the current sq_quote()
does.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
added to /etc/shells and set to the pw_shell in the /etc/passwd
file, to give users ability to push into repositories over ssh
without giving them full interactive shell acount.
[jc: I updated Linus' patch to match what the current sq_quote()
does.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Makefile | patch | blob | history | |
quote.c | patch | blob | history | |
quote.h | patch | blob | history | |
shell.c | [new file with mode: 0644] | patch | blob |
diff --git a/Makefile b/Makefile
index 5bdf3cc8dd569af4fc12382e47dbb9c1dfdf7c5e..5b0306d3910f1e19a2b80c75e180dc5121366667 100644 (file)
--- a/Makefile
+++ b/Makefile
git-merge-index$X git-mktag$X git-pack-objects$X git-patch-id$X \
git-peek-remote$X git-prune-packed$X git-read-tree$X \
git-receive-pack$X git-rev-list$X git-rev-parse$X \
- git-send-pack$X git-show-branch$X \
+ git-send-pack$X git-show-branch$X git-shell$X \
git-show-index$X git-ssh-fetch$X \
git-ssh-upload$X git-tar-tree$X git-unpack-file$X \
git-unpack-objects$X git-update-index$X git-update-server-info$X \
index 009e69494b007fc7bfe590029c144d9ce41aa6b5..e662a7da71e39c1ffc3d1a4bf485fda17df5e907 100644 (file)
--- a/quote.c
+++ b/quote.c
#undef EMIT
#define EMIT(x) ( (++len < n) && (*bp++ = (x)) )
+static inline int need_bs_quote(char c)
+{
+ return (c == '\'' || c == '!');
+}
+
size_t sq_quote_buf(char *dst, size_t n, const char *src)
{
char c;
EMIT('\'');
while ((c = *src++)) {
- if (c == '\'' || c == '!') {
+ if (need_bs_quote(c)) {
EMIT('\'');
EMIT('\\');
EMIT(c);
return buf;
}
+char *sq_dequote(char *arg)
+{
+ char *dst = arg;
+ char *src = arg;
+ char c;
+
+ if (*src != '\'')
+ return NULL;
+ for (;;) {
+ c = *++src;
+ if (!c)
+ return NULL;
+ if (c != '\'') {
+ *dst++ = c;
+ continue;
+ }
+ /* We stepped out of sq */
+ switch (*++src) {
+ case '\0':
+ *dst = 0;
+ return arg;
+ case '\\':
+ c = *++src;
+ if (need_bs_quote(c) && *++src == '\'') {
+ *dst++ = c;
+ continue;
+ }
+ /* Fallthrough */
+ default:
+ return NULL;
+ }
+ }
+}
+
/*
* C-style name quoting.
*
index 2fdde3b66b99d142beaa602d72d72e459b7daf2a..2486e6e68c2d7fa7bc2f78c18df323cc9adcc894 100644 (file)
--- a/quote.h
+++ b/quote.h
extern char *sq_quote(const char *src);
extern size_t sq_quote_buf(char *dst, size_t n, const char *src);
+/* This unwraps what sq_quote() produces in place, but returns
+ * NULL if the input does not look like what sq_quote would have
+ * produced.
+ */
+extern char *sq_dequote(char *);
+
extern int quote_c_style(const char *name, char *outbuf, FILE *outfp,
int nodq);
extern char *unquote_c_style(const char *quoted, const char **endp);
diff --git a/shell.c b/shell.c
--- /dev/null
+++ b/shell.c
@@ -0,0 +1,59 @@
+#include "cache.h"
+#include "quote.h"
+
+static int do_generic_cmd(const char *me, char *arg)
+{
+ const char *my_argv[4];
+
+ arg = sq_dequote(arg);
+ if (!arg)
+ die("bad argument");
+
+ my_argv[0] = me;
+ my_argv[1] = arg;
+ my_argv[2] = NULL;
+
+ return execvp(me, (char**) my_argv);
+}
+
+static struct commands {
+ const char *name;
+ int (*exec)(const char *me, char *arg);
+} cmd_list[] = {
+ { "git-receive-pack", do_generic_cmd },
+ { "git-upload-pack", do_generic_cmd },
+ { NULL },
+};
+
+int main(int argc, char **argv)
+{
+ char *prog;
+ struct commands *cmd;
+
+ /* We want to see "-c cmd args", and nothing else */
+ if (argc != 3 || strcmp(argv[1], "-c"))
+ die("What do you think I am? A shell?");
+
+ prog = argv[2];
+ argv += 2;
+ argc -= 2;
+ for (cmd = cmd_list ; cmd->name ; cmd++) {
+ int len = strlen(cmd->name);
+ char *arg;
+ if (strncmp(cmd->name, prog, len))
+ continue;
+ arg = NULL;
+ switch (prog[len]) {
+ case '\0':
+ arg = NULL;
+ break;
+ case ' ':
+ arg = prog + len + 1;
+ break;
+ default:
+ continue;
+ }
+ exit(cmd->exec(cmd->name, arg));
+ }
+ die("unrecognized command '%s'", prog);
+}