]> oss.titaniummirror.com Git - repo_shell.git/commitdiff
Implement allow_interactive feature
authorR. Steve McKown <rsmckown@gmail.com>
Fri, 28 Sep 2012 19:11:00 +0000 (13:11 -0600)
committerR. Steve McKown <rsmckown@gmail.com>
Fri, 28 Sep 2012 19:15:19 +0000 (13:15 -0600)
README
repo_shell.c

diff --git a/README b/README
index 14db116d35606c399de95841e6275edc0a4cedbd..8a5db3ab9179952fbd82414d8aadaf7bddc5fa76 100644 (file)
--- 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:
index 7ef610d247bf4c22cfd8591de37c93b97f418f99..887c4d3430350c1025e32cc60066182ee92d49b4 100644 (file)
 #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;