From mboxrd@z Thu Jan 1 00:00:00 1970 From: ranger at risk.ee (The Ranger) Date: Fri, 27 Nov 2015 20:46:33 -0000 Subject: [PATCH 04/07] Inject repo authorization filter. Provide sample for gitolite integration. Message-ID: <1448657217.362252.7291.nullmailer@cypher.risk.ee> --- filters/gitolite-authorization.lua | 74 ++++++++++++++++++++++++++++++++++++++ scan-tree.c | 18 ++++++++++ 2 files changed, 92 insertions(+) create mode 100644 filters/gitolite-authorization.lua diff --git a/filters/gitolite-authorization.lua b/filters/gitolite-authorization.lua new file mode 100644 index 0000000..2f0e4f5 --- /dev/null +++ b/filters/gitolite-authorization.lua @@ -0,0 +1,74 @@ +-- This script can be used with project-filter option +-- It uses REMOTE_USER environment variable to obtain the user who needs to be authorized +-- This variable is normally set by HTTP Basic Authentication. +-- In Apache something like this can be used: +-- +-- AuthType Basic +-- AuthName Protected area +-- AuthUserFile users.htpasswd +-- Require valid-user +-- +-- For anonymous access a public username can be set in environment config. +-- In Apache, using mod_env: +-- +-- SetEnv REMOTE_USER gitweb +-- +-- Gitolite requires HOME environment variable to work properly and point to valid Gitolite +-- environment. Since the user, under which web server process runs, usually does not have +-- this set, HOME should be explicitly configured and pointed to valid gitolite setup. +-- In Apache, using mod_env: +-- +-- SetEnv HOME /path/to/gitolite/home + + +local git = {} +local http = {} +local repos = {} +local action = nil + +function action_init() + -- Anonymous access, cancel repo list building + if git.user == nil or git.user == "" then return end + + local handle = io.popen("gitolite list-phy-repos | gitolite access % " .. git.user .. " R any") + + while true do + local repo = handle:read() + if repo == nil then break end + + -- Skip DENIED repos + if not string.find(repo, "DENIED") then + -- Gitolite returns string: \t\t + -- We are interested only in the first field for now + -- Append .git extension since Gitolite does not and cgit repo name has it + local name = string.sub(repo, 0, string.find(repo, "\t") - 1) .. ".git" + repos[name] = 1 -- Authorize flag is > 0 + end + end + + handle:close() +end + +function action_filter() + -- Return > 0 if access is authorized + return repos[git.repo] +end + +local actions = {} +actions["init"] = action_init; +actions["filter"] = action_filter; + +function filter_open(...) + action = actions[select(1, ...)] + + git["repo"] = select(2, ...) + git["user"] = select(3, ...) + + http["server"] = select(4, ...) + http["path"] = select(5, ...) +end + +function filter_close() + return action() +end + diff --git a/scan-tree.c b/scan-tree.c index e17bca9..7490e74 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -74,6 +74,14 @@ static char *xstrrchr(char *s, char *from, int c) return from < s ? NULL : from; } +static int open_project_filter(const char *action, const char *repo) { + return cgit_open_filter(ctx.cfg.project_filter, action, repo, + ctx.env.remote_user ? ctx.env.remote_user : "", + ctx.env.server_name ? ctx.env.server_name : "", + ctx.env.path_info ? ctx.env.path_info : "" + ); +} + static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) { struct stat st; @@ -115,6 +123,11 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) else if (rel.len && rel.buf[rel.len - 1] == '/') strbuf_setlen(&rel, rel.len - 1); + if(ctx.cfg.project_filter) { + if(open_project_filter("filter", rel.buf)) return; + if(cgit_close_filter(ctx.cfg.project_filter) < 1) return; + } + repo = cgit_add_repo(rel.buf); config_fn = fn; if (ctx.cfg.enable_git_config) { @@ -261,6 +274,11 @@ void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn void scan_tree(const char *path, repo_config_fn fn) { + if (ctx.cfg.project_filter) { + open_project_filter("init", path); + cgit_close_filter(ctx.cfg.project_filter); + } + if (ctx.cfg.project_list) { scan_projects(path, ctx.cfg.project_list, fn); return; -- 2.1.4