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;
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);
}
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);
+#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;
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)
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);
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;
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". */