diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | basicauth.conf-sample | 20 | ||||
-rw-r--r-- | httpconnectd.sh | 35 | ||||
-rw-r--r-- | httpconnectd.sh.in | 103 | ||||
-rw-r--r-- | httpconnectd@.service.in | 2 |
6 files changed, 133 insertions, 39 deletions
@@ -1,4 +1,5 @@ httpconnectd@.service httpconnectd +httpconnectd.sh .var.* .tmp.* @@ -4,6 +4,8 @@ prefix = /usr/local bindir = $(prefix)/bin systemddir = $(prefix)/lib/systemd/system +sysconfdir = $(prefix)/etc +pkgconfdir = $(sysconfdir)/httpconnectd DESTDIR = Q = @ @@ -11,19 +13,20 @@ Q = @ MAKEFLAGS += -r vars = $(patsubst .var.%,%,$(filter .var.%,$^)) -build_targets = httpconnectd httpconnectd@.service httpconnectd.socket -install_targets = $(DESTDIR)$(bindir)/httpconnectd $(DESTDIR)$(systemddir)/httpconnectd@.service $(DESTDIR)$(systemddir)/httpconnectd.socket +build_targets = httpconnectd httpconnectd@.service httpconnectd.socket basicauth.conf-sample +install_targets = $(DESTDIR)$(bindir)/httpconnectd $(DESTDIR)$(systemddir)/httpconnectd@.service $(DESTDIR)$(systemddir)/httpconnectd.socket $(DESTDIR)$(pkgconfdir)/basicauth.conf-sample all: $(build_targets) install: $(install_targets) clean: - rm -f -- httpconnectd httpconnectd@.service + rm -f -- httpconnectd httpconnectd.sh httpconnectd@.service uninstall: rm -f -- $(install_targets) rmdir -p -- $(dir $(install_targets)) .PHONY: all install clean uninstall httpconnectd@.service: .var.bindir +httpconnectd.sh: .var.pkgconfdir ######################################################################## @@ -37,6 +40,8 @@ $(DESTDIR)$(bindir)/%: % install -Dm755 $< $@ $(DESTDIR)$(systemddir)/%: % install -Dm644 $< $@ +$(DESTDIR)$(pkgconfdir)/%: % + install -Dm644 $< $@ .var.%: FORCE $(Q)printf '%s' '$($*)' > .tmp$@ && { cmp -s .tmp$@ $@ && rm -f -- .tmp$@ || mv -Tf .tmp$@ $@; } || { rm -f -- .tmp$@; false; } diff --git a/basicauth.conf-sample b/basicauth.conf-sample new file mode 100644 index 0000000..11048fc --- /dev/null +++ b/basicauth.conf-sample @@ -0,0 +1,20 @@ +#!/hint/bash +# Copyright 2016 Luke Shumaker +# License: WTFPLv2 + +# Dependencies: +# - bash +# - base64 -d + +authenticate_basic() { + local authparams="$*" + local pair + pair=$(base64 -d <<<"$authparams") + if [[ "$pair" != *:* ]]; then + return 1; + fi + local username="${pair%%:*}" + local password="${pair#*:}" + + # TODO: check username and password against some DB +} diff --git a/httpconnectd.sh b/httpconnectd.sh deleted file mode 100644 index 24edb68..0000000 --- a/httpconnectd.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2016 Luke Shumaker -# License: WTFPLv2 - -# Dependencies: -# - bash -# - socat -# - date -R - -server='httpconnectd' - -MethodNotAllowed() { - printf '%s\r\n' \ - 'HTTP/1.1 405 Method Not Allowed' \ - "Server: $server" \ - "Date: $(date -R)" \ - 'Allow: CONNECT' \ - '' - exit 0 -} - -worker() { - read -r method dest version - if [[ "$method" != CONNECT ]]; then - MethodNotAllowed - fi - while read -r line; do - if [[ "$line" == $'\r' ]]; then - break; - fi - done - exec socat STDIO TCP-CONNECT:"$dest" -} - -worker "$@" diff --git a/httpconnectd.sh.in b/httpconnectd.sh.in new file mode 100644 index 0000000..747fcea --- /dev/null +++ b/httpconnectd.sh.in @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# Copyright 2016 Luke Shumaker +# License: WTFPLv2 + +# Dependencies: +# - bash +# - sed +# - socat +# - date -R + +server="${0##*/}" + +NoContent() { + printf '%s\r\n' \ + 'HTTP/1.1 204 No Content' \ + "Server: $server" \ + "Date: $(date -R)" \ + '' +} + +Forbidden() { + printf '%s\r\n' \ + 'HTTP/1.1 403 Forbidden' \ + "Server: $server" \ + "Date: $(date -R)" \ + 'Allow: CONNECT' \ + '' +} + +MethodNotAllowed() { + printf '%s\r\n' \ + 'HTTP/1.1 405 Method Not Allowed' \ + "Server: $server" \ + "Date: $(date -R)" \ + 'Allow: CONNECT' \ + '' +} + +ProxyAuthenticationRequired() { + printf '%s\r\n' \ + 'HTTP/1.1 407 Proxy Authentication Required' \ + "Server: $server" \ + "Date: $(date -R)" \ + "Proxy-Authenticate: $(echo $(declare -F|sed -n 's/^declare -f authenticate_//p')|sed 's/ /, /g')" \ + '' +} + +InternalServerError() { + printf '%s\r\n' \ + 'HTTP/1.1 500 Internal Server Error' \ + "Server: $server" \ + "Date: $(date -R)" \ + '' +} + +checkdest() { + true +} + +worker() { + local conffile + for conffile in @pkgconfdir@/*.conf; do + if ! source "$conffile"; then + InternalServerError + fi + done + local method dest version + read -r method dest version || exit 1 + if [[ "$method" != CONNECT ]]; then + MethodNotAllowed + return 0 + fi + local authenticated=false + local line + while read -r line; do + line="${line%$'\r'}" + case "${line,,}" in + proxy-authorization:*) + local scheme authparams + read -r scheme authparams <<<"${line#*:}" + scheme=${scheme,,} + if authenticate_${scheme} "$authparams" 1>&2; then + authenticated=true + fi + ;; + '') + if ! $authenticated; then + ProxyAuthenticationRequired + return 0 + fi + if ! checkdest "$dest"; then + Forbidden + return 0 + fi + NoContent + exec socat STDIO TCP-CONNECT:"$dest" + ;; + esac + done + exit 1 +} + +while worker "$@"; do :; done diff --git a/httpconnectd@.service.in b/httpconnectd@.service.in index a057c27..05bcff8 100644 --- a/httpconnectd@.service.in +++ b/httpconnectd@.service.in @@ -5,7 +5,7 @@ Description=An HTTP CONNECT connection After=network.target [Service] -ExecStart=@bindir@/httpconnectd +ExecStart=-@bindir@/httpconnectd StandardInput=socket StandardOutput=socket StandardError=journal |