diff options
author | Richard Ipsum <richard.ipsum@codethink.co.uk> | 2014-01-13 17:08:29 +0000 |
---|---|---|
committer | Richard Ipsum <richard.ipsum@codethink.co.uk> | 2014-01-23 17:18:41 +0000 |
commit | 4ad632980d66816dec19c8c571a525297bbf182f (patch) | |
tree | cb987d88e9053c64382ec3cf53c92a32587049a7 | |
parent | 0cfb688153bcc877820866d89cd2f60bfc739e6f (diff) | |
download | gitano-4ad632980d66816dec19c8c571a525297bbf182f.tar.gz |
is_authorized and check get requests are authd
-rwxr-xr-x | cgi/gitano-smart-http.cgi | 199 |
1 files changed, 188 insertions, 11 deletions
diff --git a/cgi/gitano-smart-http.cgi b/cgi/gitano-smart-http.cgi index 74ddd5e..18a6058 100755 --- a/cgi/gitano-smart-http.cgi +++ b/cgi/gitano-smart-http.cgi @@ -5,27 +5,204 @@ sio = require "luxio.simple" stream = sio.stderr +function is_authorized(cmdline) + --print("cmdline: " .. cmdline) + --print("package.path: " .. package.path .. '\n') + + local gitano = require "gitano" + local gall = require "gall" + local luxio = require "luxio" + local sio = require "luxio.simple" + local sp = require "luxio.subprocess" + + gitano.config.lib_bin_path("/usr/lib/gitano/bin") + gitano.config.share_path("/usr/share/gitano") + + local repo_root = "/home/git/repos" + local username = "richardipsum" -- TODO: sort out + local keytag = "default" + + local authorized = false + + gitano.config.repo_path(repo_root) + + --gitano.log.set_source("ssh") + + local transactionid = gitano.log.syslog.open() + + local parsed_cmdline, warnings = gitano.util.parse_cmdline(cmdline) + + local start_log_level = gitano.log.get_level() + -- Clamp level at info until we have checked if the caller + -- is an admin or not + gitano.log.cap_level(gitano.log.level.INFO) + + if (#warnings > 0) then + gitano.log.error("Warnings encountered parsing commandline."); + gitano.log.warn("\t" .. cmdline) + gitano.log.warn("") + gitano.log.warn("Parsed as:") + for i = 1, #parsed_cmdline do + gitano.log.warn((" =[%2d]> %s"):format(i, parsed_cmdline[i])) + end + gitano.log.warn("\nWarnings were:") + for i = 1, #warnings do + gitano.log.warn(" * " .. warnings[i]) + end + gitano.log.warn("") + gitano.log.critical("Game over, sorry\n") + end + + -- Now load the administration data + + local admin_repo = gall.repository.new((repo_root or "") .. "/gitano-admin.git") + + if not admin_repo then + gitano.log.critical("Unable to locate administration repository. Cannot continue"); + end + + local admin_head = admin_repo:get(admin_repo.HEAD) + + if not admin_head then + gitano.log.critical("Unable to find the HEAD of the administration repository. Cannot continue"); + end + + local config, msg = gitano.config.parse(admin_head) + + if not config then + gitano.log.critical("Unable to parse administration repository.") + gitano.log.critical(" * " .. (msg or "No error?")) + gitano.log.critical("Cannot continue") + end + + -- Now, are we an admin? + if config.groups["gitano-admin"].filtered_members[username] then + -- Yep, so blithely reset logging level + gitano.log.set_level(start_log_level) + end + + if not config.global.silent then + -- Not silent, bump to chatty level automatically + gitano.log.bump_level(gitano.log.level.CHAT) + end + + local repo + + -- Find the command + + + -- ip = string.match(luxio.getenv "SSH_CLIENT", "^[^ ]+") or "" + + gitano.log.syslog.info("Client connected from", ip, "as", username, + "(" .. keytag .. ")", "Executing command:", + cmdline) + + local cmd = gitano.command.get(parsed_cmdline[1]) + + if not cmd then + gitano.log.critical("Unknown command: " .. parsed_cmdline[1]) + end + + if cmd.takes_repo and #parsed_cmdline > 1 then + -- Acquire the repository object for the target repo + local msg + repo, msg = gitano.repository.find(config, parsed_cmdline[2]) + if not repo then + gitano.log.critical("Unable to locate repository.") + gitano.log.critical(" * " .. (tostring(msg))) + gitano.log.critical("Cannot continue") + end + + if repo.is_nascent then + gitano.log.info("Repository " .. repo.name .. " is nascent") + end + end + + -- Validate the commandline, massaging it as necessary. + + if not cmd.validate(config, repo, parsed_cmdline) then + gitano.log.critical("Validation of command line failed") + end + + -- Construct our context ready for prep + local context = { + source = "ssh", + user = username, + keytag = keytag, + } + + local action, reason = cmd.prep(config, repo, parsed_cmdline, context) + + if not action then + gitano.log.critical(reason) + gitano.log.critical("Ruleset did not complete cleanly") + end + + if action == "allow" then + gitano.log.info(reason or "Ruleset permitted action") + authorized = true + else + gitano.log.critical(reason) + gitano.log.critical("Ruleset denied action. Sorry.") + end + + return authorized +end + envbackup = {} local names = {'PATH_INFO', 'REMOTE_USER', 'REMOTE_ADDR', 'CONTENT_TYPE', 'QUERY_STRING', 'REQUEST_METHOD'} for _, name in pairs(names) do - stream:write(name .. '\n') -- debug - envbackup[name] = luxio.getenv(name) + s = luxio.getenv(name) or "" + stream:write("in: " .. name .. " " .. s .. "\n") -- debug + --envbackup[name] = luxio.getenv(name) + --stream:write(" " .. envbackup[name] .. '\n') end -local authorized = false +request_method = os.getenv("REQUEST_METHOD") -if authorized then - os.execute("/usr/lib/git-core/git-http-backend") -else - print("Status: 403 Forbidden\r\n\r\n") +function parse_get_request() + query_string = os.getenv("QUERY_STRING") + + if query_string then + command = string.gsub(query_string, "^service=", "") + end + + local cmdline = command .. " '" .. + string.match(os.getenv("PATH_INFO"), '/(.+)/info/refs') .. "'" + + return cmdline end -for _, name in pairs(names) do - if envbackup[name] then - stream:write(name .. ": " .. envbackup[name] .. '\n') -- debug - luxio.setenv(name, envbackup[name]) +--if command == "git-upload-pack" or command == "git-receive-pack" then + +if request_method == "GET" then + local cmdline = parse_get_request() + + stream:write('cmdline: ' .. cmdline .. '\n') -- debug + + local authorized = is_authorized(cmdline) + + stream:write("authorized: " .. tostring(authorized) .. '\n') -- debug + + if authorized == true then + -- set the push env var or whatever if push access is required + os.execute("/usr/lib/git-core/git-http-backend") + else + print("Status: 403 Forbidden\r\n\r\n") end +elseif request_method == "POST" then + os.execute("/usr/lib/git-core/git-http-backend") +else + -- some sort of error happens + stream:write("no request method?") end + +--for _, name in pairs(names) do +-- if envbackup[name] then +-- stream:write("out: " .. name .. ": " .. envbackup[name] .. '\n') -- debug +-- luxio.setenv(name, envbackup[name]) +-- end +--end |