From e6bad58d5fb98b9170a75c401b059fdb6b2dce81 Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Thu, 27 Sep 2012 23:49:25 -0600 Subject: [PATCH] Add extended wildcard matching Now '*' can be used as the last character of a userid or repoid target. Such as: [user_groups] group = st* sm* [repo_groups] rgroup = mirrors/* [repo oss*] * = rw --- Makefile | 4 ++-- git_acl.c | 9 ++++---- git_acl.cfg.example | 8 +++++++ match.c | 33 +++++++++++++++++++++++++++++ match.h | 24 +++++++++++++++++++++ repo_shell.c | 51 +++++++++++++++++++++++++-------------------- stra.c | 16 ++++++++++++++ stra.h | 3 +++ 8 files changed, 118 insertions(+), 30 deletions(-) create mode 100644 match.c create mode 100644 match.h diff --git a/Makefile b/Makefile index 49f7334..eb4728c 100644 --- a/Makefile +++ b/Makefile @@ -15,13 +15,13 @@ PROGRAMS = $(MAIN) mystrtok_test acl_test all: $(MAIN) -repo_shell: repo_shell.c inih/ini.c git_acl.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 match.c version.c $(CC) -I inih $^ -o $@ mystrtok_test: mystrtok_test.c mystrtok.c utility.c $(CC) -g $^ -o $@ -acl_test: acl_test.c git_acl.c inih/ini.c mystrtok.c stra.c utility.c +acl_test: acl_test.c git_acl.c inih/ini.c mystrtok.c stra.c utility.c match.c $(CC) -I inih $^ -o $@ $(INFILES):%: %.in diff --git a/git_acl.c b/git_acl.c index ea171fe..4bb75ee 100644 --- a/git_acl.c +++ b/git_acl.c @@ -28,10 +28,9 @@ #include "utility.h" #include "mystrtok.h" #include "stra.h" +#include "match.h" #include "git_acl.h" -#define ANYID "*" - enum { DFLT_IDS_SZ = 32 }; @@ -123,7 +122,7 @@ static bool str_has_word(const char* string, const char* word) char *p = my_strtok(&s, " \t\n"); while (p) { - if (!strcmp(p, word) || !strcmp(p, ANYID)) { + if (match(p, word)) { free(_s); return true; } @@ -161,8 +160,8 @@ static int acl_handler(void* user, const char* section, const char* name, if (!repo || my_strtok(&p, " \t\n")) die("acl_handler: badly formatted section '%s'", section); /* repo is repo name, name is userid, value is permission */ - if ((!strcmp(repo, ANYID) || stra_find(&acl->repoids, repo) >= 0) && - (!strcmp(name, ANYID) || stra_find(&acl->userids, name) >= 0)) { + if (stra_match(&acl->repoids, repo) >= 0 && + stra_match(&acl->userids, name) >= 0) { acl->perms = perms_from_str(value); set_lm_repoid(repo); set_lm_userid(name); diff --git a/git_acl.cfg.example b/git_acl.cfg.example index 0ff9015..9804b1e 100644 --- a/git_acl.cfg.example +++ b/git_acl.cfg.example @@ -32,9 +32,17 @@ qa = frank bill allusers = * [repo_groups] +mirrors = mirror/* public = oss-web.git repo_shell.git cp210x.git private = redmine.git nesc.git +[repo oss*] +steve = rw + +[repo mirrors] +jobu=rw +devs=r + [repo nesc.git] steve = r devs = rw diff --git a/match.c b/match.c new file mode 100644 index 0000000..32938a1 --- /dev/null +++ b/match.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2012, Titanium Mirror, Inc. + * All Rights Reserved. + * + * This document is the proprietary and confidential property of + * Titanium Mirror, Inc. All use, distribution, reproduction or re-distribution + * is disallowed without the prior express written consent of + * Titanium Mirror, Inc. + */ + +/* + * Match allowing wildcard ('*') + * + * @author R. Steve McKown + */ + +#include +#include + +bool match(const char* pattern, const char* string) +{ + char* p; + + if (!pattern || !string) + return false; + p = index(pattern, '*'); + if (p == pattern) + return true; + else if (p) + return (strncmp(pattern, string, p - pattern) == 0); + else + return (strcmp(pattern, string) == 0); +} diff --git a/match.h b/match.h new file mode 100644 index 0000000..756d6c6 --- /dev/null +++ b/match.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012, Titanium Mirror, Inc. + * All Rights Reserved. + * + * This document is the proprietary and confidential property of + * Titanium Mirror, Inc. All use, distribution, reproduction or re-distribution + * is disallowed without the prior express written consent of + * Titanium Mirror, Inc. + */ + +/* + * Match allowing wildcard ('*') + * + * @author R. Steve McKown + */ + +#ifndef MATCH_H +#define MATCH_H + +#include + +bool match(const char* pattern, const char* string); + +#endif /* end of include guard: MATCH_H */ diff --git a/repo_shell.c b/repo_shell.c index dc9b8d6..660c2fd 100644 --- a/repo_shell.c +++ b/repo_shell.c @@ -216,31 +216,36 @@ int main(int argc, char **argv) return 0; } - 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': + if (argc == 3) { + /* argv[0] = repo_shell, argv[1] = -c, argv[2] = cmd + * cmd = "svnserve -t" or "git-xxx '/path/to/repo.git'" + */ + 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; - break; - case ' ': - arg = prog + len + 1; - break; - default: - continue; + 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)); } - - pw = getpwuid(getuid()); - exit(cmd->exec(cmd->name, arg, pw->pw_name)); } if (!check_ssh_interactive(getuid())) diff --git a/stra.c b/stra.c index 4e2f04b..232419a 100644 --- a/stra.c +++ b/stra.c @@ -17,6 +17,7 @@ #include #include "utility.h" #include "stra.h" +#include "match.h" void stra_init(stra_t *stra, size_t size) { @@ -61,6 +62,21 @@ int stra_add(stra_t *stra, const char *item) return stra->count++; } +int stra_match(stra_t *stra, const char *item) +{ + unsigned i; + + if (!stra) + die("stra_in: stra NULL reference"); + if (!item) + die("stra_in: item is NULL"); + for (i = 0; i < stra->count; i++) { + if (match(item, stra->items[i])) + return i; + } + return -1; +} + int stra_find(stra_t *stra, const char *item) { unsigned i; diff --git a/stra.h b/stra.h index a2f43d6..fad9501 100644 --- a/stra.h +++ b/stra.h @@ -37,6 +37,9 @@ void stra_destroy(stra_t *stra); /* Add an item to the end of the string array, returning its ele# */ int stra_add(stra_t *stra, const char *item); +/* Return the ele# of the first string matching item, which may have * */ +int stra_match(stra_t *stra, const char *item); + /* Return the ele# of the first string matching item */ int stra_find(stra_t *stra, const char *item); -- 2.39.2