From b8fa426971bb191592341e858585373c3d6ff327 Mon Sep 17 00:00:00 2001 From: Keith Irwin Date: Sun, 6 Nov 2022 17:09:55 -0700 Subject: [PATCH] First attempt at returning user SSL files --- back/dashboard.Dockerfile | 3 +- back/dashboard_ssl.cgi | 22 +++++++++++ back/lib/dashboard/peer/list | 2 +- back/lib/dashboard/ssl | 71 ++++++++++++++++++++++++++++++++++++ checklist.md | 3 +- front/dashboard.html | 3 +- front/dashboard.js | 2 + 7 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 back/dashboard_ssl.cgi create mode 100644 back/lib/dashboard/ssl diff --git a/back/dashboard.Dockerfile b/back/dashboard.Dockerfile index 928354e..8f9ba7e 100644 --- a/back/dashboard.Dockerfile +++ b/back/dashboard.Dockerfile @@ -31,8 +31,9 @@ RUN echo "www-data ALL=(ALL:ALL) NOPASSWD: /usr/bin/wg, /usr/bin/openssl, /usr/b | sudo EDITOR='tee -a' visudo # Copy over cgi and libs -# TODO: Copy only needed libs COPY dashboard.cgi /var/www/cgi-bin/index.cgi +COPY dashboard_ssl.cgi /var/www/cgi-bin/ssl.cgi +# TODO: Copy only needed libs COPY lib/ /usr/lib/wgapi/ # Run time! diff --git a/back/dashboard_ssl.cgi b/back/dashboard_ssl.cgi new file mode 100644 index 0000000..069b909 --- /dev/null +++ b/back/dashboard_ssl.cgi @@ -0,0 +1,22 @@ +#!/bin/bash +# FILE: wgapi:back/dashboard_ssl.cgi +# DESCRIPTION: Sends SSL certs and keys to users +# ERRORS: +# 3: Bad usage +# 4: Missing config file + +CONFIG_FILE='/etc/wgapi/config' +if ! [ -f "${CONFIG_FILE}" ]; then + printf 'ERROR! %s could not find %s!\n' "${0}" "${CONFIG_FILE}" >>"${LOGFILE}" + exit 4 +fi; source "${CONFIG_FILE}" + +case "${REQUEST_METHOD}" in + + # Cet + 'GET') "${LIB_DIR}/dashboard/ssl" "${HTTP_X_REAL_IP}" "${QUERY_STRING}";; + + # Bad request + *) printf 'Invalid HTTP verb' | "${LIB_DIR}/http_res" 405;; + +esac diff --git a/back/lib/dashboard/peer/list b/back/lib/dashboard/peer/list index 3ea6108..0be4aab 100755 --- a/back/lib/dashboard/peer/list +++ b/back/lib/dashboard/peer/list @@ -1,7 +1,7 @@ #!/bin/bash # FILE: lib/dashboard/peer/list # DESCRIPTION: List a user's peers -# USAGE: add remote_ip +# USAGE: list remote_ip # ERRORS: # 3: bad args/usage # 4: config file not found diff --git a/back/lib/dashboard/ssl b/back/lib/dashboard/ssl new file mode 100644 index 0000000..4b97a36 --- /dev/null +++ b/back/lib/dashboard/ssl @@ -0,0 +1,71 @@ +#!/bin/bash +# FILE: lib/dashboard/ssl +# DESCRIPTION: Get a user's SSL certs and keys +# USAGE: ssl remote_ip querystring +# QUERYSTRING: ?host=$hostname&ext=crt +# ERRORS: +# 3: Bad args/usage +# 4: Config file not found +# 5: Missing part of the querystring +# 6: Invalid extension +# 7: SSL file missing +# 8: Failed to return SSL file + +CONFIG_FILE='/etc/wgapi/config' +if ! [ ${#} -eq 2 ]; then + printf 'ERROR! Bad input: %s %s\n' "${0}" "${*}" >>"${LOGFILE}" + exit 3 +fi & if ! [ -f "${CONFIG_FILE}" ]; then + printf 'ERROR! %s could not find %s!\n' "${0}" "${CONFIG_FILE}" >>"${LOGFILE}" + exit 4 +fi +source "${CONFIG_FILE}" +ip="${1}" +qs="$(<<<"${2}" tr '&' '\n' | sed 's/?//')" + +# Parse querystring +hostname="$(<<<"${qs}" grep -oP 'host=(.*)' | sed 's/^host//' | xargs)" +ext="$(<<<"${qs}" grep -oP 'ext=(.*)' | sed 's/^ext//' | xargs)" + +if ! file="${hostname:?}/server.${ext:?}"; then + printf 'ERROR! Hostname "%s" or extension "%s" or SSL_CONFIG_DIR "%s" missing!\n' "${hostname}" "${username}" "${ext}" "${SSL_CONFIG_DIR}" >>"${LOGFILE}" + printf 'Hostname or username or extension missing!\n' | "${LIB_DIR}/http_res" 400 + exit 5 +else + printf 'User %s requested SSL file %s\n' "${ip}" "${file}" >>"${LOGFILE}" +fi + +# Make sure extension is 'crt' or 'key' +if [ "${ext}" != 'crt' ] && [ "${ext}" != 'key' ]; then + printf 'Invalid extension: %s\n' | tee -a "${LOGFILE}" | "${LIB_DIR}/http_res" 400 + exit 6 +fi + +# Get username +if ! domain="$("${LIB_DIR}/ns_lookup_rdns" "${ip}")"; then + printf 'ERROR! Failed to lookup domain from user IP %s\n' "${ip}" | tee -a "${LOGFILE}" | "${LIB_DIR}/http_res" 500 + exit 7 +fi +if ! username="$(<<<"${domain}" cut -d'.' -f2)"; then + printf 'ERROR! Failed to parse username from domain "%s"\n' "${domain}" >>"${LOGFILE}" + "${LIB_DIR}/http_res" 500 + exit 8 +fi + +if ! path="${SSL_CONFIG_DIR:?}/${username:?}/${file}"; then + printf 'ERROR! Username "${username}" or SSL_CONFIG_DIR "%s" missing!\n' >> "${LOGFILE}" + printf 'Hostname or username or extension missing!\n' | "${LIB_DIR}/http_res" 400 + exit 9 +fi + +# Check that the file exists +if ! [ -f "${path}" ]; then + printf 'ERROR! File missing: "%s"\n' | tee -a "${LOGFILE}" | "${LIB_DIR}/http_res" 404 + exit 10 +fi + +# Try to return it to the user +if ! <"${file}" "${LIB_DIR}/http_res" 200; then + printf 'ERROR! Failed to return file: "%s"\n' | tee -a "${LOGFILE}" | "${LIB_DIR}/http_res" 500 + exit 11 +fi diff --git a/checklist.md b/checklist.md index 342bf33..b0afcd3 100644 --- a/checklist.md +++ b/checklist.md @@ -11,9 +11,10 @@ [X] admin user adding backend [X] admin user deleting backend [X] Add Loading... +[ ] Let users download ssl certs +[ ] Let admins download ssl certs [ ] Replace ns_lookup_rdns with ns_lookup_rxfr where applicable [ ] Prevent deleting user's only peer -[ ] Let users download ssl certs [ ] Show QR code with new config [ ] Clean up bash file headings [ ] Deploy on GF4 diff --git a/front/dashboard.html b/front/dashboard.html index 4d41078..56f088e 100644 --- a/front/dashboard.html +++ b/front/dashboard.html @@ -9,10 +9,11 @@

Loading...

- + +
HostHostSSL
Cert / Key
diff --git a/front/dashboard.js b/front/dashboard.js index e5ad9f7..99b19f9 100644 --- a/front/dashboard.js +++ b/front/dashboard.js @@ -7,6 +7,8 @@ function Peer(data) { this.ipv6 = data.ipv6 this.isDeleting = ko.observable(false) this.deleteText = ko.computed(() => this.isDeleting()?'Deleting...':'Delete') + this.crtHref = ko.computed(() => `/ssl?host=${this.name}&ext=crt`) + this.keyHref = ko.computed(() => '/ssl?host=${this.name}&ext=key') } function PeerList() {