From: R. Steve McKown Date: Wed, 26 Sep 2012 21:29:03 +0000 (-0600) Subject: repo_shell changes indention rules X-Git-Tag: 0.3~1 X-Git-Url: https://oss.titaniummirror.com/gitweb?p=repo_shell.git;a=commitdiff_plain;h=2657b21c48ee21f9f1667be242d7e85be8161cf9 repo_shell changes indention rules --- diff --git a/repo_shell.c b/repo_shell.c index df342c8..6ec08b2 100644 --- a/repo_shell.c +++ b/repo_shell.c @@ -16,242 +16,242 @@ #define SHELL "/bin/bash" typedef struct { - char *svn_root; - char *git_root; - char *owner; + char *svn_root; + char *git_root; + char *owner; } cfg_t; static cfg_t cfg; static uid_t user_uid(char *user) { - struct passwd *pw = getpwnam(user); + struct passwd *pw = getpwnam(user); - if (!pw) - die("invalid user %s", user); - return pw->pw_uid; + if (!pw) + die("invalid user %s", user); + return pw->pw_uid; } static void change_user(char *user) { - /* This is the function for which setuid is required, as root */ - setuid(user_uid(user)); + /* This is the function for which setuid is required, as root */ + setuid(user_uid(user)); } static char *dequote(char *arg) { - char* narg = NULL; + char* narg = NULL; - if (arg && *arg == '\'') { - char* end = arg + strlen(arg) - 1; + if (arg && *arg == '\'') { + char* end = arg + strlen(arg) - 1; - if (end != arg && *end == '\'') { - narg = arg + 1; - *end = '\0'; - } - } - return narg; + if (end != arg && *end == '\'') { + narg = arg + 1; + *end = '\0'; + } + } + return narg; } static char *add_prefix(char *prefix, char* arg) { - char *narg = arg; + 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 narg; + 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 narg; } static int check_ssh_interactive(uid_t uid) { - /* TODO: Check the config file for the user owning uid to see if that - * user should be able to execute any commands other than those required - * to support repository access. Return a boolean true/false. - */ - return 1; /* for now */ + /* TODO: Check the config file for the user owning uid to see if that + * user should be able to execute any commands other than those required + * to support repository access. Return a boolean true/false. + */ + return 1; /* for now */ } static int git_acl(const char *user, const char *repo) { - /* TODO: Read GIT_ACL_FILE from cfg.owner's home directory. Look for - * the access level afforded user for repo. A return of 0 means no - * access, a return of 1 means read only, and a return of 2 means - * read/write. - */ + /* TODO: Read GIT_ACL_FILE from cfg.owner's home directory. Look for + * the access level afforded user for repo. A return of 0 means no + * 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; - - pw = getpwnam(cfg.owner); - if (!pw) - die("owner %s has no passwd entry?", cfg.owner); - 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 for git ACLs]\n", file); - free(file); + struct passwd *pw; + char *file; + int len = strlen(cfg.owner) + strlen(GIT_ACL_FILE) + 8; + + pw = getpwnam(cfg.owner); + if (!pw) + die("owner %s has no passwd entry?", cfg.owner); + 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 for git ACLs]\n", file); + free(file); #endif - return 2; /* assume read/write for now */ + return 2; /* assume read/write for now */ } static int git_check_access(const char *cmd, const char *repo, const char *user) { - /* 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; + /* 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; } static int do_git_cmd(const char *cmd, char *arg, char *user) { - const char *nargv[4]; - char* narg; - int ret; - - if (!(arg = dequote(arg))) - die("bad argument"); - if (strncmp(cmd, "git-", 4)) - die("bad command"); - - change_user(cfg.owner); - if (!git_check_access(cmd, arg, user)) - die("permission denied"); - - nargv[0] = cmd; - nargv[1] = add_prefix(cfg.git_root, arg); - nargv[2] = NULL; - - ret = execvp(nargv[0], (char *const *) nargv); - /* Code unreached if execv successful */ - free(narg); - return ret; + const char *nargv[4]; + char* narg; + int ret; + + if (!(arg = dequote(arg))) + die("bad argument"); + if (strncmp(cmd, "git-", 4)) + die("bad command"); + + change_user(cfg.owner); + if (!git_check_access(cmd, arg, user)) + die("permission denied"); + + nargv[0] = cmd; + nargv[1] = add_prefix(cfg.git_root, arg); + nargv[2] = NULL; + + ret = execvp(nargv[0], (char *const *) nargv); + /* Code unreached if execv successful */ + free(narg); + return ret; } static int do_svnserve_cmd(const char *cmd, char *arg, char *user) { - const char *svnserve_argv[7] = { - cmd, "-t", "--root", cfg.svn_root, "--tunnel-user", user, NULL - }; - int ret; + const char *svnserve_argv[7] = { + cmd, "-t", "--root", cfg.svn_root, "--tunnel-user", user, NULL + }; + int ret; - change_user(cfg.owner); - return execvp(svnserve_argv[0], (char *const *) svnserve_argv); + change_user(cfg.owner); + return execvp(svnserve_argv[0], (char *const *) svnserve_argv); } static void cd_to_homedir(void) { - const char *home = getenv("HOME"); - if (!home) - die("user variable HOME is unset"); - if (chdir(home) == -1) - die("could not chdir to user's home directory"); + const char *home = getenv("HOME"); + if (!home) + die("user variable HOME is unset"); + if (chdir(home) == -1) + die("could not chdir to user's home directory"); } static struct commands { - const char *name; - int (*exec)(const char *cmd, char *arg, char *user); + const char *name; + int (*exec)(const char *cmd, char *arg, char *user); } cmd_list[] = { - { "git-receive-pack", do_git_cmd }, - { "git-upload-pack", do_git_cmd }, - { "git-upload-archive", do_git_cmd }, - { "svnserve", do_svnserve_cmd }, - { NULL }, + { "git-receive-pack", do_git_cmd }, + { "git-upload-pack", do_git_cmd }, + { "git-upload-archive", do_git_cmd }, + { "svnserve", do_svnserve_cmd }, + { NULL }, }; static int ini_handler(void* user, const char* section, const char* name, - const char* value) + const char* value) { - cfg_t* pconfig = (cfg_t*)user; - - #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 - if (MATCH("core", "svn_root")) - pconfig->svn_root = xstrdup(value); - else if (MATCH("core", "git_root")) - pconfig->git_root = xstrdup(value); - else if (MATCH("core", "owner")) - pconfig->owner = xstrdup(value); - else - return 0; /* unknown section/name, error */ - return 1; + cfg_t* pconfig = (cfg_t*)user; + + #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 + if (MATCH("core", "svn_root")) + pconfig->svn_root = xstrdup(value); + else if (MATCH("core", "git_root")) + pconfig->git_root = xstrdup(value); + else if (MATCH("core", "owner")) + pconfig->owner = xstrdup(value); + else + return 0; /* unknown section/name, error */ + return 1; } int main(int argc, char **argv) { - char *prog; - const char **user_argv; - struct commands *cmd; - int devnull_fd; - int count; - - /* - * Always open file descriptors 0/1/2 to avoid clobbering files - * in die(). It also avoids not messing up when the pipes are - * dup'ed onto stdin/stdout/stderr in the child processes we spawn. - */ - devnull_fd = open("/dev/null", O_RDWR); - while (devnull_fd >= 0 && devnull_fd <= 2) - devnull_fd = dup(devnull_fd); - if (devnull_fd == -1) - die("opening /dev/null failed"); - close (devnull_fd); - - if (argc == 2 && (!strcmp(argv[1], "-v") || - !strcmp(argv[1], "--version"))) { - fprintf(stderr, "%s\n", version); - return 0; - } - - if (argc == 1 && check_ssh_interactive(getuid())) { - setuid(getuid()); - argv[0] = SHELL; - execvp(argv[0], (char *const *) argv); - } - - if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0) - die("cannot read config file %s", CFG_FILE); - - prog = xstrdup(argv[2]); - if (!strncmp(prog, "git", 3) && isspace(prog[3])) - /* Accept "git foo" as if the caller said "git-foo". */ - prog[3] = '-'; - - for (cmd = cmd_list ; cmd->name ; cmd++) { - int len = strlen(cmd->name); - char *arg; - struct passwd *pw; - 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; - } - - pw = getpwuid(getuid()); - exit(cmd->exec(cmd->name, arg, pw->pw_name)); - } - - if (!check_ssh_interactive(getuid())) - die("only repository access is allowed"); - - setuid(getuid()); - cd_to_homedir(); - argv[0] = SHELL; - execvp(argv[0], (char *const *) argv); + char *prog; + const char **user_argv; + struct commands *cmd; + int devnull_fd; + int count; + + /* + * Always open file descriptors 0/1/2 to avoid clobbering files + * in die(). It also avoids not messing up when the pipes are + * dup'ed onto stdin/stdout/stderr in the child processes we spawn. + */ + devnull_fd = open("/dev/null", O_RDWR); + while (devnull_fd >= 0 && devnull_fd <= 2) + devnull_fd = dup(devnull_fd); + if (devnull_fd == -1) + die("opening /dev/null failed"); + close (devnull_fd); + + if (argc == 2 && (!strcmp(argv[1], "-v") || + !strcmp(argv[1], "--version"))) { + fprintf(stderr, "%s\n", version); + return 0; + } + + if (argc == 1 && check_ssh_interactive(getuid())) { + setuid(getuid()); + argv[0] = SHELL; + execvp(argv[0], (char *const *) argv); + } + + if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0) + die("cannot read config file %s", CFG_FILE); + + prog = xstrdup(argv[2]); + if (!strncmp(prog, "git", 3) && isspace(prog[3])) + /* Accept "git foo" as if the caller said "git-foo". */ + prog[3] = '-'; + + for (cmd = cmd_list ; cmd->name ; cmd++) { + int len = strlen(cmd->name); + char *arg; + struct passwd *pw; + 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; + } + + pw = getpwuid(getuid()); + exit(cmd->exec(cmd->name, arg, pw->pw_name)); + } + + if (!check_ssh_interactive(getuid())) + die("only repository access is allowed"); + + setuid(getuid()); + cd_to_homedir(); + argv[0] = SHELL; + execvp(argv[0], (char *const *) argv); }