]> oss.titaniummirror.com Git - repo_shell.git/commitdiff
repo_shell honors git ACLs 0.3
authorR. Steve McKown <rsmckown@gmail.com>
Wed, 26 Sep 2012 22:10:54 +0000 (16:10 -0600)
committerR. Steve McKown <rsmckown@gmail.com>
Wed, 26 Sep 2012 22:21:44 +0000 (16:21 -0600)
* repo_shell uses git_acl.c
* str_has_word returns C99 bool
* git acl filename is set in repo_shell.cfg
* git_acl() accepts const char* args
* git_acl.h doesn't need to include stdbool.h
* git_acl.c manages no default git acl filename
* Use meaningful error message if permission denied due to ACL rule
* repo_shell has -t mode to get git acl function

Makefile
README
git_acl.c
git_acl.h
repo_shell.c

index f6259972cb5a2b6d7ccc3bad5d5abfdc9c91ad94..49f7334e9cc1aafb6ce9fabf305f3d167f3626c0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ PROGRAMS = $(MAIN) mystrtok_test acl_test
 
 all: $(MAIN)
 
-repo_shell: repo_shell.c inih/ini.c mystrtok.c stra.c utility.c version.c
+repo_shell: repo_shell.c inih/ini.c git_acl.c mystrtok.c stra.c utility.c version.c
        $(CC) -I inih $^ -o $@
 
 mystrtok_test: mystrtok_test.c mystrtok.c utility.c
diff --git a/README b/README
index f46578e0c1f145287e68f72226861cc9b8d6ca24..91d9301de89884f9a50c45e7bfb4b642ba6b35e8 100644 (file)
--- a/README
+++ b/README
@@ -40,6 +40,7 @@ The /etc/repo_shell.cfg configuration file is straightforward:
     owner=repo
     git_root=/var/lib/git
     svn_root=/var/lib/svn/repositories
+    git_acl_file=/var/lib/git/.gitacls
 
 The owner field denotes the user that owns all repositories.  The git_root and
 svn_root fields identify the path to the respective repositories.  The latter
index e077f785e54fd2a78e8e828ca1c3ab6a2e088068..6af2c2c03bd0ec896004f1e5d366d2d562f88cb2 100644 (file)
--- a/git_acl.c
+++ b/git_acl.c
@@ -114,7 +114,7 @@ static acl_clear(acl_t *acl)
   stra_destroy(&acl->userids);
 }
 
-static int str_has_word(const char* string, const char* word)
+static bool str_has_word(const char* string, const char* word)
 {
   char *_s = xstrdup(string);
   char *s = _s;
@@ -174,13 +174,11 @@ static int acl_handler(void* user, const char* section, const char* name,
   return 1;
 }
 
-int git_acl(char *user, char *repo, char *file)
+int git_acl(const char *user, const char *repo, const char *file)
 {
   acl_t acl;
 
-  if (!file || !*file)
-    file = GIT_ACL_FILE;
-  if (!user || !*user || !repo || !*repo) {
+  if (!file || !*file || !user || !*user || !repo || !*repo) {
     die("git_acl: invalid args user='%s', repo='%s', file='%s'", user, repo,
        file);
   }
@@ -189,8 +187,8 @@ int git_acl(char *user, char *repo, char *file)
   set_lm_userid(NULL);
   lm_perms = PERMS_NOTFOUND;
   acl_init(&acl);
-  acl.user = user;
-  acl.repo = repo;
+  acl.user = (char*)user;
+  acl.repo = (char*)repo;
   stra_add(&acl.userids, acl.user);
   stra_add(&acl.repoids, acl.repo);
 
index 80440ccfe7dbe96d4689a22baef228b940c263da..47c6aa88af7752b38bc7432e062f7501dde9da01 100644 (file)
--- a/git_acl.h
+++ b/git_acl.h
@@ -18,7 +18,6 @@
 #ifndef GIT_ACL_H
 #define GIT_ACL_H
 
-#include <stdbool.h>
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -32,8 +31,6 @@
 #include "mystrtok.h"
 #include "stra.h"
 
-#define GIT_ACL_FILE "git_acl.cfg"
-
 typedef enum {
   PERMS_NOTFOUND = 0,
   PERMS_NONE,
@@ -42,7 +39,7 @@ typedef enum {
   PERMS_COUNT
 } perms_t;
 
-int git_acl(char *user, char *repo, char *file);
+int git_acl(const char *user, const char *repo, const char *file);
 char *git_acl_last_repoid();
 char *git_acl_last_userid();
 int git_acl_last_perms();
index 6ec08b2f53372ca20251842fc11e5fecce71b7e5..24eb6e20adbdb3e19dde2767aca372ed6a8ac05a 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdbool.h>
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
 #include "ini.h"
 #include "utility.h"
 #include "version.h"
+#include "git_acl.h"
 
 #define CFG_FILE "/etc/repo_shell.cfg"
-#define GIT_ACL_FILE "git_acl.cfg"
 #define SHELL "/bin/bash"
 
 typedef struct {
   char *svn_root;
   char *git_root;
   char *owner;
+  char *git_acl_file;
 } cfg_t;
 
 static cfg_t cfg;
@@ -76,40 +78,18 @@ static int check_ssh_interactive(uid_t uid)
   return 1; /* for now */
 }
 
-static int git_acl(const char *user, const char *repo)
+/* Return true if the user's permissions >= those required */
+static bool git_check_access(const char *cmd, const char *repo,
+    const char *user)
 {
-  /* 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.
+  /* What access is required per the incoming command?  Uploading commands
+   * require PERMS_READ_WRITE, while all other commands are assumed to need only
+   * PERMS_READ.
    */
-#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);
-#endif
-  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;
+  perms_t need = !strncmp(cmd, "git-upload", 10) ? PERMS_READ :
+      PERMS_READ_WRITE;
+  perms_t have = git_acl(user, repo, cfg.git_acl_file);
+  return have >= need;
 }
 
 static int do_git_cmd(const char *cmd, char *arg, char *user)
@@ -125,7 +105,7 @@ static int do_git_cmd(const char *cmd, char *arg, char *user)
 
   change_user(cfg.owner);
   if (!git_check_access(cmd, arg, user))
-    die("permission denied");
+    die("insufficient ACL permissions");
 
   nargv[0] = cmd;
   nargv[1] = add_prefix(cfg.git_root, arg);
@@ -180,6 +160,8 @@ static int ini_handler(void* user, const char* section, const char* name,
     pconfig->git_root = xstrdup(value);
   else if (MATCH("core", "owner"))
     pconfig->owner = xstrdup(value);
+  else if (MATCH("core", "git_acl_file"))
+    pconfig->git_acl_file = xstrdup(value);
   else
     return 0;  /* unknown section/name, error */
   return 1;
@@ -220,6 +202,16 @@ int main(int argc, char **argv)
   if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0)
     die("cannot read config file %s", CFG_FILE);
 
+  if (argc == 4 && (!strcmp(argv[1], "-t") ||
+      !strcmp(argv[1], "--test"))) {
+    perms_t p = git_acl(argv[2], argv[3], cfg.git_acl_file);
+    fprintf(stderr,
+        "user '%s' repo '%s' perms '%s'\n  via userid '%s' repoid '%s'\n",
+        argv[2], argv[3], git_acl_perms_as_str(p), git_acl_last_userid(),
+        git_acl_last_repoid());
+    return 0;
+  }
+
   prog = xstrdup(argv[2]);
   if (!strncmp(prog, "git", 3) && isspace(prog[3]))
     /* Accept "git foo" as if the caller said "git-foo". */