From: R. Steve McKown Date: Fri, 28 Sep 2012 19:11:00 +0000 (-0600) Subject: Implement allow_interactive feature X-Git-Tag: 0.5~15 X-Git-Url: https://oss.titaniummirror.com/gitweb?p=repo_shell.git;a=commitdiff_plain;h=e49dc7b9511adbcfeed98a2f5ac5d3a121d1d4e4 Implement allow_interactive feature --- diff --git a/README b/README index 14db116..8a5db3a 100644 --- a/README +++ b/README @@ -27,12 +27,14 @@ Please build from a repository clone, as the make script uses = Configure /etc/repo_shell.cfg -The file /etc/repo_shell.cfg must contain certain fields: +The file /etc/repo_shell.cfg must contain certain fields as shown in the example +below. The spaces surrounding the equal sign ('=') are optional. - owner=repo - svn_root=/var/lib/svn/repositories - git_root=/var/lib/git - git_acl_file=/var/lib/git/.gitacls + owner = repo + svn_root = /var/lib/svn/repositories + git_root = /var/lib/git + git_acl_file = /var/lib/git/.gitacls + allowed_interactive = owner is the system account username which will own all repositories, and is preferaby a system account used for no other purpose. Use the adduser or @@ -46,6 +48,13 @@ git_acl_file is the pathname of a file providing ACL information for git repository access, as implemented internally bit repo_shell. A recommended pathname is /var/lib/git/.gitacls +allow_interactive contains a list of users that may log into the server via SSH, +or that may issue arbitrary commands to the server via SSH. Instead of a list, +the wildcard character '*' can be used to indicate all users. Note that this +only affects users that have /usr/local/bin/repo_shell as their login shell. +If the server is only hosting repositories, there is no reason for users to be +allowed 'interactive' access. + = Create owner and paths In accordance with the contents of /etc/repo_shell.cfg: diff --git a/repo_shell.c b/repo_shell.c index 7ef610d..887c4d3 100644 --- a/repo_shell.c +++ b/repo_shell.c @@ -18,27 +18,24 @@ #define SHELL "/bin/bash" typedef struct { + char *user; char *svn_root; char *git_root; char *owner; char *git_acl_file; + bool allow_interactive; } cfg_t; static cfg_t cfg; -static uid_t user_uid(char *user) +/* This is the function for which setuid root is needed for repo_shell */ +static void change_user(char *user) { struct passwd *pw = getpwnam(user); 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)); + die("invalid user %s", pw->pw_name); + setuid(pw->pw_uid); } static char *dequote(char *arg) @@ -70,15 +67,6 @@ static char *add_prefix(char *prefix, char* 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 */ -} - /* Return true if the user's permissions >= those required */ static bool git_check_access(const char *cmd, const char *repo, const char *user) @@ -163,6 +151,8 @@ static int ini_handler(void* user, const char* section, const char* name, pconfig->owner = xstrdup(value); else if (!strcmp(name, "git_acl_file")) pconfig->git_acl_file = xstrdup(value); + else if (!strcmp(name, "allow_interactive")) + pconfig->allow_interactive = str_has_word(value, pconfig->user); else return 0; /* unknown section/name, error */ return 1; @@ -175,6 +165,7 @@ int main(int argc, char **argv) struct commands *cmd; int devnull_fd; int count; + struct passwd *pw; /* * Always open file descriptors 0/1/2 to avoid clobbering files @@ -193,18 +184,22 @@ int main(int argc, char **argv) return 0; } + pw = getpwuid(getuid()); + cfg.user = xstrdup(pw->pw_name); + if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0) + die("cannot read config file %s", CFG_FILE); + if (argc == 1) { - if (!check_ssh_interactive(getuid())) + if (!cfg.allow_interactive) { + fprintf(stderr, "\n"); die("only repository access is allowed"); + } setuid(getuid()); argv[0] = SHELL; execvp(argv[0], (char *const *) argv); return 1; } - if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0) - die("cannot read config file %s", CFG_FILE); - if ((!strcmp(argv[1], "-t") || !strcmp(argv[1], "--test"))) { perms_t p; @@ -230,7 +225,6 @@ int main(int argc, char **argv) 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; @@ -245,14 +239,12 @@ int main(int argc, char **argv) continue; } - pw = getpwuid(getuid()); - exit(cmd->exec(cmd->name, arg, pw->pw_name)); + exit(cmd->exec(cmd->name, arg, cfg.user)); } } - if (!check_ssh_interactive(getuid())) + if (!cfg.allow_interactive) die("only repository access is allowed"); - setuid(getuid()); cd_to_homedir(); argv[0] = SHELL;