summaryrefslogtreecommitdiff
path: root/httpconnectd.sh.in
blob: bcbdb1d95236d04d342d8915e71d22a2fb418b71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/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