summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2022-10-11 01:22:15 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2022-10-11 01:22:15 +0200
commit4393288f44a9f318f88d1857e85ea8c57ceb3009 (patch)
treedac41db28e2e0834b73aeeeb5bdca1b0f03527f2
parentAdd rule for free access to index page. (diff)
downloadcgit-filters-4393288f44a9f318f88d1857e85ea8c57ceb3009.tar.gz
cgit-filters-4393288f44a9f318f88d1857e85ea8c57ceb3009.tar.xz
Force current filters.
-rw-r--r--hugo-authentication.lua183
-rwxr-xr-xhugo-highlighting.sh138
-rwxr-xr-xhugo-pre.sh26
3 files changed, 266 insertions, 81 deletions
diff --git a/hugo-authentication.lua b/hugo-authentication.lua
index 4a56bd2..a6187c1 100644
--- a/hugo-authentication.lua
+++ b/hugo-authentication.lua
@@ -1,10 +1,15 @@
-- This script may be used with the auth-filter. Be sure to configure it as you wish.
--
-- Requirements:
--- luacrypto >= 0.3
--- <http://mkottman.github.io/luacrypto/>
+-- luaossl
+-- <http://25thandclement.com/~william/projects/luaossl.html>
+-- luaposix
+-- <https://github.com/luaposix/luaposix>
--
-
+local sysstat = require("posix.sys.stat")
+local unistd = require("posix.unistd")
+local rand = require("openssl.rand")
+local hmac = require("openssl.hmac")
--
--
@@ -13,25 +18,51 @@
--
-- A list of password protected repositories along with the users who can access them.
-local public_repos = {
- vimwiki = true
+local protected_repos = {
+ glouglou = { laurent = true, jason = true },
+ qt = { jason = true, bob = true }
}
--- Please note that, in production, you'll want to replace this simple lookup
--- table with either a table of salted and hashed passwords (using something
--- smart like scrypt), or replace this table lookup with an external support,
--- such as consulting your system's pam / shadow system, or an external
--- database, or an external validating web service. For testing, or for
--- extremely low-security usage, you may be able, however, to get away with
--- compromising on hardcoding the passwords in cleartext, as we have done here.
+local public_repos = {}
+public_repos["wiki-public"] = true
+public_repos["lyslib"] = true
+public_repos["calp"] = true
+public_repos["texttv"] = true
+public_repos["scheme-monad"] = true
+public_repos["scheme/math-parse"] = true
+public_repos["file-descriptor-graph"] = true
+public_repos["rss-filter"] = true
+public_repos["puppet-mpd"] = true
+public_repos["aur-runner"] = true
+public_repos["guile-dns"] = true
+public_repos["puppet/blog"] = true
+public_repos["puppet/cgit"] = true
+public_repos["puppet/dns_record"] = true
+public_repos["puppet/image-shower"] = true
+public_repos["puppet/networking"] = true
+public_repos["puppet/nspawn"] = true
+public_repos["puppet/nsupdate"] = true
+public_repos["puppet/pacman"] = true
+public_repos["puppet/profiles"] = true
+public_repos["puppet/rss_filter"] = true
+public_repos["puppet/shiori"] = true
+public_repos["puppet/syslinux"] = true
+public_repos["puppet/systemd_mount"] = true
+public_repos["puppet/uwsgi"] = true
+public_repos["puppet/webdav_server"] = true
+public_repos["puppet/wpa_supplicant"] = true
+public_repos["puppet/envvar"] = true
+
+-- A list of users and hashes, generated with `mkpasswd -m sha-512 -R 300000`.
local users = {
- hugo = "password"
+ hugo = "$6$13z1Pf.U8itrCRX6$g2BZpaMk1CLiT6117paWXB2qdQFRc3rsGWL4iF5h5QbHo27oljTdHk69oQWAvqlVf13aLTUF3nYw65lEp88r/1",
+ gitlab = "$6$rounds=300000$G/80.k.yO$FCzj0kOmxTMQHPsNHEQVZQI4ofPYz3ae6G0bWNEp3v7GnMkEQufpvWK9lvFqG3oPoy3heIC5sSdSmipUf8QVU/",
+ ove = "$6$rounds=30000$SGWXbaxWPHt$RQsAiAq3xPIyF32X5OZCEfT8gxesN87tqECeFd8h/QmUPpKfzqoJBkN0NRlYodjHImeI5LOrwG.FW9ktPQH/v/",
}
--- All cookies will be authenticated based on this secret. Make it something
--- totally random and impossible to guess. It should be large.
-local secret = "Ianae4woof3ial9ahdahng7ahth9yoo2ri6zuw7eeYaengai0s"
-
+-- Set this to a path this script can write to for storing a persistent
+-- cookie secret, which should be guarded.
+local secret_filename = "/var/cache/cgit/auth-secret"
--
--
@@ -39,53 +70,9 @@ local secret = "Ianae4woof3ial9ahdahng7ahth9yoo2ri6zuw7eeYaengai0s"
--
--
-function printenv(arg)
- local keys = {
- "CGIT_CONFIG",
- "CGIT_REPO_URL", "CGIT_REPO_NAME", "CGIT_REPO_PATH",
- "CGIT_REPO_OWNER", "CGIT_REPO_GROUP", "CGIT_REPO_DEFBRANCH",
- "CGIT_REPO_SECTION", "CGIT_REPO_CLONE_URL",
-
- "GIT_REPO", "GIT_CONFIG_NOSYSTEM",
- "GIT_ATTR_NOSYSTEM",
- "GIT_DIR", "GIT_CONFIG_NOSYSTEM", "GIT_ATTR_NOSYSTEM",
-
- "QUERY_STRING"
- }
-
- -- print "!!!"
- -- html ("!!!")
- -- print ("<h3>body</h3><table border=1 style='border-collapse: collapse;'><tr><th>Key</th><th>Value</th></tr>")
- io.stderr:write(os.time(os.date("!*t")))
- io.stderr:write("\n")
- io.stderr:write(arg);
- for _, attr in pairs(keys) do
- local l = os.getenv(attr)
- -- print("<tr><td><pre>" )
- ---print (attr)
- -- print ("</td><td>")
- -- print (l)
- -- print("</pre></td></tr>")
- io.stderr:write(attr)
- io.stderr:write(" = " )
- if l == nil then
- io.stderr:write("nil");
- else
- io.stderr:write(l)
- end
- io.stderr:write("\n")
- end
- -- print ("</table>")
-end
-
-- Sets HTTP cookie headers based on post and sets up redirection.
--- TODO this tries to authenticate on the root page (good), but fails to set
--- the cookie. I think it gets stuck in the redirect filter (bad).
--- TODO invalid login also kinda breaks the page... Not found should return the
--- user to the login page with an error messsage displaed.
function authenticate_post()
- printenv("Authenticate Post\n=================\n");
- local password = users[post["username"]]
+ local hash = users[post["username"]]
local redirect = validate_value("redirect", post["redirect"])
if redirect == nil then
@@ -95,8 +82,7 @@ function authenticate_post()
redirect_to(redirect)
- -- Lua hashes strings, so these comparisons are time invariant.
- if password == nil or password ~= post["password"] then
+ if hash == nil or hash ~= unistd.crypt(post["password"], hash) then
set_cookie("cgitauth", "")
else
-- One week expiration time
@@ -111,22 +97,21 @@ end
-- Returns 1 if the cookie is valid and 0 if it is not.
function authenticate_cookie()
- printenv("Authenticate Cookie\n===================\n");
-- Everyone has access to the index page.
- if os.getenv("CGIT_REPO_NAME") == nil then
+ -- printenv(os.getenv("CGIT_REPO_NAME"));
+ if cgit["repo"] == "" then
return 1
end
+ ispublic = public_repos[cgit["repo"]]
-- accepted_users = protected_repos[cgit["repo"]]
- if public_repos[cgit["repo"]] then
- -- We return as valid if the repo is not protected.
+ if ispublic == true then
+ -- We return as valid if the repo is public
return 1
end
-
local username = validate_value("username", get_cookie(http["cookie"], "cgitauth"))
- -- if username == nil or not accepted_users[username:lower()] then
if username == nil then
return 0
else
@@ -136,11 +121,9 @@ end
-- Prints the html for the login form.
function body()
- printenv("Body\n====\n");
-
- html("<p>New login form!</p>");
- html("<p>But still don't contact me to gain access.</p>");
html("<h2>Authentication Required</h2>")
+ -- html("HTML = ")
+ -- html(tostring(cgit["repo"] == ""))
html("<form method='post' action='")
html_attr(cgit["login"])
html("'>")
@@ -237,6 +220,13 @@ function get_cookie(cookies, name)
return url_decode(string.match(cookies, ";" .. name .. "=(.-);"))
end
+function tohex(b)
+ local x = ""
+ for i = 1, #b do
+ x = x .. string.format("%.2x", string.byte(b, i))
+ end
+ return x
+end
--
--
@@ -244,7 +234,38 @@ end
--
--
-local crypto = require("crypto")
+local secret = nil
+
+-- Loads a secret from a file, creates a secret, or returns one from memory.
+function get_secret()
+ if secret ~= nil then
+ return secret
+ end
+ local secret_file = io.open(secret_filename, "r")
+ if secret_file == nil then
+ local old_umask = sysstat.umask(63)
+ local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
+ local temporary_file = io.open(temporary_filename, "w")
+ if temporary_file == nil then
+ os.exit(177)
+ end
+ temporary_file:write(tohex(rand.bytes(32)))
+ temporary_file:close()
+ unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
+ unistd.unlink(temporary_filename)
+ sysstat.umask(old_umask)
+ secret_file = io.open(secret_filename, "r")
+ end
+ if secret_file == nil then
+ os.exit(177)
+ end
+ secret = secret_file:read()
+ secret_file:close()
+ if secret:len() ~= 64 then
+ os.exit(177)
+ end
+ return secret
+end
-- Returns value of cookie if cookie is valid. Otherwise returns nil.
function validate_value(expected_field, cookie)
@@ -253,7 +274,7 @@ function validate_value(expected_field, cookie)
local field = ""
local expiration = 0
local salt = ""
- local hmac = ""
+ local chmac = ""
if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
return nil
@@ -272,19 +293,19 @@ function validate_value(expected_field, cookie)
elseif i == 3 then
salt = component
elseif i == 4 then
- hmac = component
+ chmac = component
else
break
end
i = i + 1
end
- if hmac == nil or hmac:len() == 0 then
+ if chmac == nil or chmac:len() == 0 then
return nil
end
-- Lua hashes strings, so these comparisons are time invariant.
- if hmac ~= crypto.hmac.digest("sha1", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, secret) then
+ if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
return nil
end
@@ -305,11 +326,11 @@ function secure_value(field, value, expiration)
end
local authstr = ""
- local salt = crypto.hex(crypto.rand.bytes(16))
+ local salt = tohex(rand.bytes(16))
value = url_encode(value)
field = url_encode(field)
authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
- authstr = authstr .. "|" .. crypto.hmac.digest("sha1", authstr, secret)
+ authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
return authstr
end
diff --git a/hugo-highlighting.sh b/hugo-highlighting.sh
new file mode 100755
index 0000000..603b8ab
--- /dev/null
+++ b/hugo-highlighting.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+# This script can be used to implement syntax highlighting in the cgit
+# tree-view by refering to this file with the source-filter or repo.source-
+# filter options in cgitrc.
+#
+# This script requires a shell supporting the ${var##pattern} syntax.
+# It is supported by at least dash and bash, however busybox environments
+# might have to use an external call to sed instead.
+#
+# Note: the highlight command (http://www.andre-simon.de/) uses css for syntax
+# highlighting, so you'll probably want something like the following included
+# in your css file:
+#
+# Style definition file generated by highlight 2.4.8, http://www.andre-simon.de/
+#
+# table.blob .num { color:#2928ff; }
+# table.blob .esc { color:#ff00ff; }
+# table.blob .str { color:#ff0000; }
+# table.blob .dstr { color:#818100; }
+# table.blob .slc { color:#838183; font-style:italic; }
+# table.blob .com { color:#838183; font-style:italic; }
+# table.blob .dir { color:#008200; }
+# table.blob .sym { color:#000000; }
+# table.blob .kwa { color:#000000; font-weight:bold; }
+# table.blob .kwb { color:#830000; }
+# table.blob .kwc { color:#000000; font-weight:bold; }
+# table.blob .kwd { color:#010181; }
+#
+#
+# Style definition file generated by highlight 2.6.14, http://www.andre-simon.de/
+#
+# body.hl { background-color:#ffffff; }
+# pre.hl { color:#000000; background-color:#ffffff; font-size:10pt; font-family:'Courier New';}
+# .hl.num { color:#2928ff; }
+# .hl.esc { color:#ff00ff; }
+# .hl.str { color:#ff0000; }
+# .hl.dstr { color:#818100; }
+# .hl.slc { color:#838183; font-style:italic; }
+# .hl.com { color:#838183; font-style:italic; }
+# .hl.dir { color:#008200; }
+# .hl.sym { color:#000000; }
+# .hl.line { color:#555555; }
+# .hl.mark { background-color:#ffffbb;}
+# .hl.kwa { color:#000000; font-weight:bold; }
+# .hl.kwb { color:#830000; }
+# .hl.kwc { color:#000000; font-weight:bold; }
+# .hl.kwd { color:#010181; }
+#
+#
+# Style definition file generated by highlight 3.8, http://www.andre-simon.de/
+#
+# body.hl { background-color:#e0eaee; }
+# pre.hl { color:#000000; background-color:#e0eaee; font-size:10pt; font-family:'Courier New';}
+# .hl.num { color:#b07e00; }
+# .hl.esc { color:#ff00ff; }
+# .hl.str { color:#bf0303; }
+# .hl.pps { color:#818100; }
+# .hl.slc { color:#838183; font-style:italic; }
+# .hl.com { color:#838183; font-style:italic; }
+# .hl.ppc { color:#008200; }
+# .hl.opt { color:#000000; }
+# .hl.lin { color:#555555; }
+# .hl.kwa { color:#000000; font-weight:bold; }
+# .hl.kwb { color:#0057ae; }
+# .hl.kwc { color:#000000; font-weight:bold; }
+# .hl.kwd { color:#010181; }
+#
+#
+# Style definition file generated by highlight 3.13, http://www.andre-simon.de/
+#
+# body.hl { background-color:#e0eaee; }
+# pre.hl { color:#000000; background-color:#e0eaee; font-size:10pt; font-family:'Courier New',monospace;}
+# .hl.num { color:#b07e00; }
+# .hl.esc { color:#ff00ff; }
+# .hl.str { color:#bf0303; }
+# .hl.pps { color:#818100; }
+# .hl.slc { color:#838183; font-style:italic; }
+# .hl.com { color:#838183; font-style:italic; }
+# .hl.ppc { color:#008200; }
+# .hl.opt { color:#000000; }
+# .hl.ipl { color:#0057ae; }
+# .hl.lin { color:#555555; }
+# .hl.kwa { color:#000000; font-weight:bold; }
+# .hl.kwb { color:#0057ae; }
+# .hl.kwc { color:#000000; font-weight:bold; }
+# .hl.kwd { color:#010181; }
+#
+#
+# The following environment variables can be used to retrieve the configuration
+# of the repository for which this script is called:
+# CGIT_REPO_URL ( = repo.url setting )
+# CGIT_REPO_NAME ( = repo.name setting )
+# CGIT_REPO_PATH ( = repo.path setting )
+# CGIT_REPO_OWNER ( = repo.owner setting )
+# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
+# CGIT_REPO_SECTION ( = section setting )
+# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
+#
+
+# store filename and extension in local vars
+BASENAME="$1"
+EXTENSION="${BASENAME##*.}"
+
+[ "${BASENAME}" = "${EXTENSION}" ] && EXTENSION=txt
+[ -z "${EXTENSION}" ] && EXTENSION=txt
+
+# map Makefile and Makefile.* to .mk
+[ "${BASENAME%%.*}" = "Makefile" ] && EXTENSION=mk
+
+# highlight versions 2 and 3 have different commandline options. Specifically,
+# the -X option that is used for version 2 is replaced by the -O xhtml option
+# for version 3.
+#
+# Version 2 can be found (for example) on EPEL 5, while version 3 can be
+# found (for example) on EPEL 6.
+#
+# This is for version 2
+#exec highlight --force -f -I -X -S "$EXTENSION" 2>/dev/null
+
+# env
+
+extension=${REQUEST_URI: -3}
+
+case $extension in
+ org)
+ temp=$(mktemp)
+ cat - > $temp.org
+ emacs $temp.org \
+ --quick \
+ --batch \
+ --funcall org-html-export-to-html \
+ --kill
+ tail -n+10 $temp.html
+ exit 0
+ ;;
+esac
+
+exec highlight --force -f -I -O xhtml -S "$EXTENSION" # 2>/dev/null
diff --git a/hugo-pre.sh b/hugo-pre.sh
new file mode 100755
index 0000000..cd303ec
--- /dev/null
+++ b/hugo-pre.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+name=$1
+
+extension=${name: -3}
+
+case $extension in
+ .md) pandoc -f gfm -t html ;;
+ *)
+ cat <<- EOF
+ <pre>$(cat -)</pre>
+ EOF
+ ;;
+esac
+
+prel_head="$(grep -Eo 'h=([-A-Za-z0-9.~_+]|%[A-Fa-f0-9]{2})*' <<< "$REQUEST_URI")"
+if [ $? -eq 0 ]; then
+ head=$(cut -c 3- <<< "$prel_head")
+else
+ head=$CGIT_REPO_DEFBRANCH
+fi
+
+echo "<hr/>"
+echo "<pre>"
+cloc --git "$head" --quiet --md | pandoc -f gfm -t html
+echo "</pre>"