#!/usr/bin/env bash # Copyright 2016 Luke Shumaker # License: WTFPLv2 # Dependencies: # - bash # - sed # - socat # - date -R server="${0##*/}" OK() { printf '%s\r\n' \ 'HTTP/1.1 200 OK' \ "Server: $server" \ "Date: $(date -R)" \ '' } Forbidden() { body='403 Forbidden' printf '%s\r\n' \ 'HTTP/1.1 403 Forbidden' \ "Server: $server" \ "Date: $(date -R)" \ 'Allow: CONNECT' \ "Content-Length: ${#body}" \ '' printf '%s' "$body" } MethodNotAllowed() { body='405 Method Not Allowed' printf '%s\r\n' \ 'HTTP/1.1 405 Method Not Allowed' \ "Server: $server" \ "Date: $(date -R)" \ 'Allow: CONNECT' \ "Content-Length: ${#body}" \ '' printf '%s' "$body" } ProxyAuthenticationRequired() { body='407 Proxy Authentication Required' 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')" \ "Content-Length: ${#body}" \ '' printf '%s' "$body" } InternalServerError() { body='500 Internal Server Error' printf '%s\r\n' \ 'HTTP/1.1 500 Internal Server Error' \ "Server: $server" \ "Date: $(date -R)" \ "Content-Length: ${#body}" \ '' printf '%s' "$body" } 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 OK exec socat STDIO TCP-CONNECT:"$dest" ;; esac done exit 1 } while worker "$@"; do :; done