X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=repo_shell.c;h=a104602437f5552820f341247b5e0cfc61136163;hb=e1789cd2f72cbf3a7bf3517177334a20d0cf551f;hp=ecce7d3aebc8229f6bbee4e3cfe3ed7bc0ead514;hpb=961cb65d693c36d7811b15a2023a35b9c5413044;p=repo_shell.git diff --git a/repo_shell.c b/repo_shell.c index ecce7d3..a104602 100644 --- a/repo_shell.c +++ b/repo_shell.c @@ -12,6 +12,7 @@ #define CFG_FILE "/etc/repo_shell.cfg" #define GIT_ACL_FILE "git_acl.cfg" +#define SHELL "/bin/bash" typedef struct { char *svn_root; @@ -19,8 +20,6 @@ typedef struct { char *owner; } cfg_t; -static const char* shell_argv[] = { "/bin/bash", NULL }; - #undef USE_DEFAULTS #ifdef USE_DEFAULTS /* perhaps we want defaults? Not sure */ static cfg_t cfg { @@ -32,27 +31,7 @@ static cfg_t cfg { static cfg_t cfg; #endif -#define alloc_nr(x) (((x)+16)*3/2) - -/* - * Realloc the buffer pointed at by variable 'x' so that it can hold - * at least 'nr' entries; the number of entries currently allocated - * is 'alloc', using the standard growing factor alloc_nr() macro. - * - * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'. - */ -#define ALLOC_GROW(x, nr, alloc) \ - do { \ - if ((nr) > alloc) { \ - if (alloc_nr(alloc) < (nr)) \ - alloc = (nr); \ - else \ - alloc = alloc_nr(alloc); \ - x = xrealloc((x), alloc * sizeof(*(x))); \ - } \ - } while (0) - -static inline void die(const char *fmt, ...) +static void die(const char *fmt, ...) { va_list ap; @@ -84,18 +63,6 @@ void *xmalloc(size_t size) return ret; } -void *xrealloc(void *ptr, size_t size) -{ - void *ret; - - ret = realloc(ptr, size); - if (!ret && !size) - ret = realloc(ptr, 1); - if (!ret) - die("Out of memory, realloc failed"); - return ret; -} - static uid_t user_uid(char *user) { struct passwd *pw = getpwnam(user); @@ -128,17 +95,16 @@ static char *dequote(char *arg) static char *add_prefix(char *prefix, char* arg) { - int size; - - if (arg && prefix && strlen(prefix)) { - char *n = xmalloc(sizeof(char *) * - (strlen(prefix) + strlen(arg) + 2)); - strcpy(n, prefix); - strcat(n, "/"); - strcat(n, arg); - arg = n; + char *narg = arg; + int i; + + if (arg && prefix && (i = strlen(prefix))) { + narg = xmalloc(sizeof(char *) * (i + strlen(arg) + 2)); + strcpy(narg, prefix); + strcpy(narg + i++, "/"); + strcpy(narg + i, arg); } - return arg; + return narg; } static int check_ssh_interactive(uid_t uid) @@ -157,6 +123,7 @@ static int git_acl(const char *user, const char *repo) * access, a return of 1 means read only, and a return of 2 means * read/write. */ +#if 0 struct passwd *pw; char *file; int len = strlen(cfg.owner) + strlen(GIT_ACL_FILE) + 8; @@ -167,19 +134,19 @@ static int git_acl(const char *user, const char *repo) len = strlen(pw->pw_dir) + strlen(GIT_ACL_FILE) + 2; file = xmalloc(sizeof(char) * len); sprintf(file, "%s/%s", pw->pw_dir, GIT_ACL_FILE); - fprintf(stderr, "[someday check %s]\n", file); + fprintf(stderr, "[someday check %s for git ACLs]\n", file); free(file); +#endif return 2; /* assume read/write for now */ } static int git_check_access(const char *cmd, const char *repo, const char *user) { - int rw = 1; /* 0=no access, 1=read only, 2=read/write */ - - /* What access is required per the incoming command? */ - if (!strcmp(cmd, "git-upload-pack") || - !strcmp(cmd, "git-upload-archive")) - rw = 2; + /* What access is required per the incoming command? + * 0=none, 1=read-only, 2=read-write + */ + int rw = (!strcmp(cmd, "git-upload-pack") || + !strcmp(cmd, "git-upload-archive")) ? 2 : 1; /* Return true (1) if the user permissions >= those required */ return (git_acl(user, repo) >= rw) ? 1 : 0; @@ -221,75 +188,11 @@ static int do_svnserve_cmd(const char *cmd, char *arg, char *user) return execvp(svnserve_argv[0], (char *const *) svnserve_argv); } -#define SPLIT_CMDLINE_BAD_ENDING 1 -#define SPLIT_CMDLINE_UNCLOSED_QUOTE 2 -static const char *split_cmdline_errors[] = { - "cmdline ends with \\", - "unclosed quote" -}; - -int split_cmdline(char *cmdline, const char ***argv) -{ - int src, dst, count = 0, size = 16; - char quoted = 0; - - *argv = xmalloc(sizeof(char *) * size); - - /* split alias_string */ - (*argv)[count++] = cmdline; - for (src = dst = 0; cmdline[src];) { - char c = cmdline[src]; - if (!quoted && isspace(c)) { - cmdline[dst++] = 0; - while (cmdline[++src] - && isspace(cmdline[src])) - ; /* skip */ - ALLOC_GROW(*argv, count+1, size); - (*argv)[count++] = cmdline + dst; - } else if (!quoted && (c == '\'' || c == '"')) { - quoted = c; - src++; - } else if (c == quoted) { - quoted = 0; - src++; - } else { - if (c == '\\' && quoted != '\'') { - src++; - c = cmdline[src]; - if (!c) { - free(*argv); - *argv = NULL; - return -SPLIT_CMDLINE_BAD_ENDING; - } - } - cmdline[dst++] = c; - src++; - } - } - - cmdline[dst] = 0; - - if (quoted) { - free(*argv); - *argv = NULL; - return -SPLIT_CMDLINE_UNCLOSED_QUOTE; - } - - ALLOC_GROW(*argv, count+1, size); - (*argv)[count] = NULL; - - return count; -} - -const char *split_cmdline_strerror(int split_cmdline_errno) { - return split_cmdline_errors[-split_cmdline_errno-1]; -} - static void cd_to_homedir(void) { const char *home = getenv("HOME"); if (!home) - die("could not determine user's home directory; HOME is unset"); + die("user variable HOME is unset"); if (chdir(home) == -1) die("could not chdir to user's home directory"); } @@ -305,7 +208,7 @@ static struct commands { { NULL }, }; -static int handler(void* user, const char* section, const char* name, +static int ini_handler(void* user, const char* section, const char* name, const char* value) { cfg_t* pconfig = (cfg_t*)user; @@ -350,13 +253,14 @@ int main(int argc, char **argv) if (argc == 1 && check_ssh_interactive(getuid())) { setuid(getuid()); - execvp(shell_argv[0], (char *const *) shell_argv); - } + argv[0] = SHELL; + execvp(argv[0], (char *const *) argv); + } #ifdef USE_DEFAULTS - ini_parse("repo_shell.cfg", handler, &cfg); + ini_parse("repo_shell.cfg", ini_handler, &cfg); #else - if (ini_parse(CFG_FILE, handler, &cfg) < 0) + if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0) die("cannot read config file %s", CFG_FILE); #endif @@ -392,14 +296,6 @@ int main(int argc, char **argv) setuid(getuid()); cd_to_homedir(); - count = split_cmdline(prog, &user_argv); - if (count >= 0) { - execvp(user_argv[0], (char *const *) user_argv); - free(user_argv); - die("unrecognized command '%s'", argv[2]); - } else { - free(prog); - die("invalid command format '%s': %s", argv[2], - split_cmdline_strerror(count)); - } + argv[0] = SHELL; + execvp(argv[0], (char *const *) argv); }