~cadence/bliz-devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch

[PATCH] Add virtual host support

Details
Message ID
<20220410222758.1204312-1-tim@clifford.lol>
DKIM signature
missing
Download raw message
Patch: +93 -22
---
I originally wanted to deal with certificates via SNI, but it seemed pretty
unworkable without quite a lot more complexity and dependencies. This patch
instead adds some stuff to certs.fish to make it easy to add new domains to the
existing certificate (without breaking TOFU)

 certs.fish      | 84 ++++++++++++++++++++++++++++++++++++++-----------
 src/cgi.fish    | 24 ++++++++++++--
 src/config.fish |  7 +++--
 3 files changed, 93 insertions(+), 22 deletions(-)

diff --git a/certs.fish b/certs.fish
index 87c09d1..4790240 100755
--- a/certs.fish
+++ b/certs.fish
@@ -1,28 +1,76 @@
#!/usr/bin/env fish

# -a or --add to add domains instead of generating a new certificate
argparse 'a/add=+' -- $argv

cd (dirname (status current-filename))/certs; or exit

set days 10000 # 27 years

if test -f key.pem
    echo 'Warning! If you have already generated keys, they will be overwritten.'
    echo 'If you continue, you will fail Trust On First Use, and some browsers may'
    echo 'be unhappy with your site.'
    echo 'If you have not yet published your site, you can ignore this warning.'
if ! test "$_flag_add"
    if test -f key.pem
        echo 'Warning! If you have already generated keys, they will be overwritten.'
        echo 'If you continue, you will fail Trust On First Use, and some browsers may'
        echo 'be unhappy with your site.'
        echo 'If you have not yet published your site, you can ignore this warning.'
        echo
    end

    echo 'To generate certificatates, enter the domain name that your site will be'
    echo 'eventually published on. If you don\'t care, you can enter nothing.'
    echo -n 'Example input: '; set_color cyan; echo 'an-excellent.website'
    read domain -P 'domain name > '
    echo
end

echo 'To generate certificatates, enter the domain name that your site will be'
echo 'eventually published on. If you don\'t care, you can enter nothing.'
echo -n 'Example input: '; set_color cyan; echo 'an-excellent.website'
read domain -P 'domain name > '
echo
    # Country, state, locality, organisation, unit, domain name, email
    echo -en ".\n.\n.\n.\n.\n$domain\n.\n" | \
        openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days $days -nodes \
        ; or exit

    echo
    echo
    echo 'Everything appears to be okay.'
else
    # check a key actually exists

    if ! test -f "key.pem"
        echo "You need to create a key before you can add domains to it!"
        exit 1
    end

    # Get any existing Common Name
    set cn (openssl x509 -noout -subject -in cert.pem | string match -r 'CN *= *([^ ,]*)')[2]

    # Get any existing Subject Alternative Name(s)
    set san (openssl x509 -in cert.pem -noout -ext subjectAltName | grep -v '^X509' | string trim)

# Country, state, locality, organisation, unit, domain name, email
echo -en ".\n.\n.\n.\n.\n$domain\n.\n" | \
    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days $days -nodes \
    ; or exit
    # add new domains
    for dom in $_flag_add
        if test $san
            set san "$san, DNS:$dom"
        else
            set san "DNS:$dom"
        end
    end

echo
echo
echo 'Everything appears to be okay.'
    # some clients (at least amfora) don't seem to like certs that use both CN and SAN,
    # so make sure the CN is in both of them
    if ! string match -rq "DNS:$cn"'($|,)' -- $san
        set san "DNS:$cn, $san"
    end

    echo "This key will now be valid for: '$san'"
    read -P "Ok? (y/N) " yn

    if string match -r '^[Yy]' -- $yn
        openssl req -x509 -key key.pem -config \
                (begin; \
                    cat /etc/ssl/openssl.cnf; \
                    echo "[ subject_alt_name ]"; \
                    echo "subjectAltName = $san"; \
                end | psub) \
            -extensions subject_alt_name \
            -subj "/CN=$cn" \
            -out cert.pem
    end
end
diff --git a/src/cgi.fish b/src/cgi.fish
index 1f66a18..d06d4fc 100644
--- a/src/cgi.fish
+++ b/src/cgi.fish
@@ -45,8 +45,28 @@ if test $req_query = "source=1"
    set source_mode true
end

# future host handling code here?
# ...
server_echo $req_host
# host handling
set serve_root (string match -r -- '^'$req_host':(.*)' $serve_roots)[2]

# if the host is not explicitly configured, use the default
if test -z $serve_root
    set serve_root (string match -r -- '^default:(.*)' $serve_roots)[2]
end

server_echo $serve_root

# if it's still empty, fail
if test -z $serve_root
    gem_header 59 "Bliz server: no server root configured for $req_host"
    exit
end

# if the path doesn't exist, fail
if ! test -d $serve_root
    gem_header 59 "Bliz server: configured server root does not exist on host"
    exit
end

# normalise path to remove /./, some broken clients add it
# `x` is added to the start and end of the string so that leading and trailing slashes won't be removed
diff --git a/src/config.fish b/src/config.fish
index 8e6c474..cd690d6 100644
--- a/src/config.fish
+++ b/src/config.fish
@@ -19,13 +19,16 @@ set spartan_port
# Optional - remove this value to not serve data.
set mercury_port 1964

set serve_root serve
set serve_roots "default:serve" # add vhosts in the form "example1.com:/path/to/root" "example2.com:/another/root" etc
set serve_index # add arguments here for default index preference

set debug_server_echo false

source personal/config.fish


# Normalise

set serve_root (string trim -r -c / -- $serve_root)
for i in (seq (count serve_roots))
    set serve_roots[$i] (string trim -r -c / -- $serve_roots[$i])
end
--
2.35.1
Reply to thread Export thread (mbox)