diff options
| -rw-r--r-- | custom/extensions/auth-file.lua | 16 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | custom/extensions/auth-inline.lua | 16 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | tests/extensions/test-auth.lua | 13 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rwxr-xr-x | tests/t0505-auth.sh | 36 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4 files changed, 63 insertions, 18 deletions
diff --git a/custom/extensions/auth-file.lua b/custom/extensions/auth-file.lua index 18a80fd..0573549 100644 --- a/custom/extensions/auth-file.lua +++ b/custom/extensions/auth-file.lua @@ -20,7 +20,9 @@ -- posix.sys.stat and posix.unistd and lives at -- <https://github.com/luaposix/luaposix>. The reliable cross-platform way to -- install them is LuaRocks matched to your Lua version, and luaossl also needs --- the OpenSSL development headers present. +-- the OpenSSL development headers present. Each is loaded only once a request +-- needs it, so a public repository is served without them while a protected +-- one is refused. -- -- # Debian and Ubuntu -- sudo apt install luarocks libssl-dev @@ -45,11 +47,6 @@ -- secret file accept each other's cookies. That is acceptable for gating -- read access to a git browser, so weigh it before guarding anything more. -local sysstat = require("posix.sys.stat") -local unistd = require("posix.unistd") -local rand = require("openssl.rand") -local hmac = require("openssl.hmac") - -- The values that follow are the configuration and are meant to be edited. -- Accounts live one per line as username:hash, where the hash is any kind this @@ -272,6 +269,9 @@ function get_secret() end local secret_file = io.open(secret_filename, "r") if secret_file == nil then + local sysstat = require("posix.sys.stat") + local unistd = require("posix.unistd") + local rand = require("openssl.rand") -- The secret is written under a tightened mask so it is not -- created readable by anyone but the user cgit runs as, and -- the old mask goes back on every way out. @@ -365,6 +365,7 @@ function validate_value(expected_field, cookie) end local payload = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt + local hmac = require("openssl.hmac") local expected_signature = tohex(hmac.new(get_secret(), "sha256"):final(payload)) if not constant_equals(signature, expected_signature) then return nil @@ -395,6 +396,8 @@ function secure_value(field, value, expiration) return "" end + local rand = require("openssl.rand") + local hmac = require("openssl.hmac") local salt = tohex(rand.bytes(16)) value = url_encode(value) field = url_encode(field) @@ -469,6 +472,7 @@ function authenticate_post() local password = post["password"] local ok = false if username ~= nil and password ~= nil and #password <= max_password_bytes then + local unistd = require("posix.unistd") local hash, stand_in = account_hash(username) if hash == nil then -- Spend the work anyway, see account_hash. diff --git a/custom/extensions/auth-inline.lua b/custom/extensions/auth-inline.lua index f6a0521..1b46fba 100644 --- a/custom/extensions/auth-inline.lua +++ b/custom/extensions/auth-inline.lua @@ -20,7 +20,9 @@ -- posix.sys.stat and posix.unistd and lives at -- <https://github.com/luaposix/luaposix>. The reliable cross-platform way to -- install them is LuaRocks matched to your Lua version, and luaossl also needs --- the OpenSSL development headers present. +-- the OpenSSL development headers present. Each is loaded only once a request +-- needs it, so a public repository is served without them while a protected +-- one is refused. -- -- # Debian and Ubuntu -- sudo apt install luarocks libssl-dev @@ -45,11 +47,6 @@ -- secret file accept each other's cookies. That is acceptable for gating -- read access to a git browser, so weigh it before guarding anything more. -local sysstat = require("posix.sys.stat") -local unistd = require("posix.unistd") -local rand = require("openssl.rand") -local hmac = require("openssl.hmac") - -- The values that follow are the configuration and are meant to be edited. -- Protected repositories and the users allowed into each. A repository named @@ -233,6 +230,9 @@ function get_secret() end local secret_file = io.open(secret_filename, "r") if secret_file == nil then + local sysstat = require("posix.sys.stat") + local unistd = require("posix.unistd") + local rand = require("openssl.rand") -- The secret is written under a tightened mask so it is not -- created readable by anyone but the user cgit runs as, and -- the old mask goes back on every way out. @@ -326,6 +326,7 @@ function validate_value(expected_field, cookie) end local payload = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt + local hmac = require("openssl.hmac") local expected_signature = tohex(hmac.new(get_secret(), "sha256"):final(payload)) if not constant_equals(signature, expected_signature) then return nil @@ -356,6 +357,8 @@ function secure_value(field, value, expiration) return "" end + local rand = require("openssl.rand") + local hmac = require("openssl.hmac") local salt = tohex(rand.bytes(16)) value = url_encode(value) field = url_encode(field) @@ -430,6 +433,7 @@ function authenticate_post() local password = post["password"] local ok = false if username ~= nil and password ~= nil and #password <= max_password_bytes then + local unistd = require("posix.unistd") local hash, stand_in = account_hash(username) if hash == nil then -- Spend the work anyway, see account_hash. diff --git a/tests/extensions/test-auth.lua b/tests/extensions/test-auth.lua index e0d2fe5..eb402da 100644 --- a/tests/extensions/test-auth.lua +++ b/tests/extensions/test-auth.lua @@ -328,4 +328,17 @@ out, ret = run_action("authenticate-post", { }) h.contains("even a signed unsafe destination is not followed", out, "Status: 404") +-- The libraries load only once a request needs one, so with every one of +-- them gone a public repository is still served, while a protected one +-- fails closed instead of reaching its content. +for _, name in ipairs({ "openssl.rand", "openssl.hmac", "posix.sys.stat", "posix.unistd" }) do + package.loaded[name] = nil + h.preload_failure(name) +end +out, ret = run_action("authenticate-cookie", { repo = "unlisted" }) +h.equals("without the libraries a public repository is served", ret, 1) +h.check("while a protected one fails closed", not pcall(run_action, + "authenticate-cookie", { repo = "secret-repo", cookie = "cgitauth=" .. session })) +h.check("and so does its login form", not pcall(run_action, "body", {})) + h.finish() diff --git a/tests/t0505-auth.sh b/tests/t0505-auth.sh index 2ebee10..526840d 100755 --- a/tests/t0505-auth.sh +++ b/tests/t0505-auth.sh @@ -4,9 +4,9 @@ # differ only in where accounts live. The unit checks meet luaossl and # luaposix with deterministic stand-ins from the harness, proving tampered # and expired cookies turned away, header injection stripped, unsafe -# redirects refused and the login flows answering as documented. The run -# through cgit itself needs the real modules inside the binary's own Lua, so -# it is probed for, and proves an unedited copy protects nothing. +# redirects refused and the login flows answering as documented. Through cgit +# itself an unedited copy protects nothing, with or without the modules, and +# when the binary's own Lua lacks them a protected repository stays closed. test_description='Check the shipped auth extensions' CGIT_TEST_NO_CREATE_REPOS=YesPlease @@ -41,11 +41,16 @@ if test "$CGIT_HAS_LUA" -eq 1 && cgit_lua_probe "$PWD/repos/authy/.git" openssl.rand openssl.hmac posix.sys.stat posix.unistd then test_set_prereq CGIT_LUA_AUTH +elif test "$CGIT_HAS_LUA" -eq 1 +then + test_set_prereq CGIT_LUA_NOAUTH + say 'cgit lua lacks luaossl or luaposix, expecting protected pages refused' else - say 'cgit lua lacks luaossl or luaposix, checks through cgit skipped' + say 'cgit built without lua, checks through cgit skipped' fi +test "$CGIT_HAS_LUA" -eq 1 && test_set_prereq CGIT_LUA -test_expect_success CGIT_LUA_AUTH 'point cgit at the unedited auth filter' ' +test_expect_success CGIT_LUA 'point cgit at the unedited auth filter' ' cat >cgitrc <<-EOF virtual-root=/ cache-size=0 @@ -55,9 +60,28 @@ test_expect_success CGIT_LUA_AUTH 'point cgit at the unedited auth filter' ' EOF ' -test_expect_success CGIT_LUA_AUTH 'an unedited copy protects nothing' ' +test_expect_success CGIT_LUA 'an unedited copy protects nothing' ' cgit_url "authy/log/" >tmp && grep ">guarded commit</a>" tmp ' +test_expect_success CGIT_LUA_NOAUTH 'without the modules a protected repository stays closed' ' + cat >protect.awk <<-\EOF && + { print } + /^local protected_repos = [{]$/ { print "\t[\"authy\"] = { alice = true }," } + EOF + awk -f protect.awk "$EXTENSIONS_DIRECTORY/auth-inline.lua" >guarded.lua && + grep "\"authy\"" guarded.lua && + cat >guardedrc <<-EOF && + virtual-root=/ + cache-size=0 + auth-filter=lua:$PWD/guarded.lua + repo.url=authy + repo.path=$PWD/repos/authy/.git + EOF + CGIT_CONFIG="$PWD/guardedrc" QUERY_STRING="url=authy/log/" cgit >tmp && + ! grep "guarded commit" tmp && + grep "Unable to complete the request" tmp +' + test_done |
