summaryrefslogtreecommitdiffstats
path: root/net/privoxy/files/privoxy.init
blob: a9803001f43601e93570da2b0e4b6102c8cb4a7f (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#!/bin/sh /etc/rc.common

START=95
STOP=10

PIDFILE=/var/run/privoxy.pid
CFGFILE=/var/etc/privoxy.conf
CFGTEMP=/var/etc/privoxy.conf.tmp
SSLCERTSTEMP=/var/ssl

_uci2conf() {
	# redefined callback for options when calling config_load
	config_cb() {
		if [ ."$2" != ."privoxy" ]; then
			option_cb() { return 0; }
		else
			option_cb()
			{
				# $1	name of variable
				# $2	value
				local __OPT="$1"
				local __VAL="$2"
				case $__OPT in
					confdir|templdir|temporary_directory|logdir|logfile)
						# needs to be handled separately because we need to set permissions
						# AND needs to be defined first because of a BUG inside privoxy
						# require directories to be defined first inside config 
						;;
					debug_*)
						[ $__VAL -eq 0 ] && return	# not set ignore
						echo -e "debug\t$(echo $__OPT | sed -e 's#debug_##g')" >> $CFGTEMP ;;
					*)
						# detect list options (LENGTH) and ignore
						echo $__OPT | grep -i "_LENGTH" >/dev/null 2>&1 && return
						# detect list options (ITEM) and ignore
						echo $__OPT | grep -i "_ITEM" >/dev/null 2>&1 && __OPT=$(echo $__OPT | sed -e "s#_ITEM.*##g")
						# Ignore certificate generation options (used only in init script)
						case $__OPT in
							certdir|ca_common_name|ca_validity_days|cert_validity_days|cert_key_size|enable_ssl_bumping|boot_delay|_enabled|receive_buffer_size)
								return
								;;
						esac
						# uci only accept "_" but we need "-"
						local __OPT=$(echo $__OPT | sed -e "s#_#-#g")
						# write to config
						echo -e "$__OPT\t$__VAL" >> $CFGTEMP
						;;
				esac
			}

			list_cb()
			{
				option_cb "$@"
			}
		fi
	}

	# temporary config file
	# privoxy need read access
	mkdir -m0755 -p /var/etc
	echo "" > $CFGTEMP
	chmod 644 $CFGTEMP
	chgrp privoxy $CFGTEMP

	echo '### AUTO-GENERATED CONFIGURATION'	   >> $CFGTEMP
	echo '### USED BY PRIVOXY'		   >> $CFGTEMP
	echo '### DO NOT EDIT'			   >> $CFGTEMP
	echo '### SEE /etc/config/privoxy INSTEAD' >> $CFGTEMP
	echo ''					   >> $CFGTEMP

	# logdir and logfile
	# privoxy needs read/write access
	_LOGDIR=$(uci -q get privoxy.privoxy.logdir)   || _LOGDIR="/var/log"
	_LOGFILE=$(uci -q get privoxy.privoxy.logfile) || _LOGFILE="privoxy.log"
	mkdir -m0755 -p $_LOGDIR
	touch $_LOGDIR/$_LOGFILE
	chmod 664 $_LOGDIR/$_LOGFILE
	chown privoxy:privoxy $_LOGDIR/$_LOGFILE
	echo -e "logdir\t$_LOGDIR" >> $CFGTEMP
	echo -e "logfile\t$_LOGFILE" >> $CFGTEMP
	_RECEIVE_BUFFER_SIZE=$(uci -q get privoxy.privoxy.receive_buffer_size) || _RECEIVE_BUFFER_SIZE="30000"
	echo -e "receive-buffer-size\t$_RECEIVE_BUFFER_SIZE" >> $CFGTEMP
	# confdir
	# privoxy needs read access (possibly write access)
	_CONFDIR=$(uci -q get privoxy.privoxy.confdir) || _CONFDIR="/etc/privoxy"
	chmod 755 $_CONFDIR
	chmod 664 $_CONFDIR/*
	chgrp privoxy $_CONFDIR $_CONFDIR/*
	echo -e "confdir\t$_CONFDIR" >> $CFGTEMP

	# templdir
	# privoxy need read access
	_TEMPLDIR=$(uci -q get privoxy.privoxy.templdir)	# no default needed
	if [ -z "$_TEMPLDIR" ]; then
		chmod 755 $_CONFDIR/templates
		chmod 644 $_CONFDIR/templates/*
		chgrp privoxy $_CONFDIR/templates $_CONFDIR/templates/*
	else
		chmod 755 $_TEMPLDIR
		chmod 644 $_TEMPLDIR/*
		chgrp privoxy $_TEMPLDIR $_TEMPLDIR/*
		echo -e "templdir\t$_TEMPLDIR" >> $CFGTEMP
	fi

	# temporary-directory
	# privoxy needs read/write access
	_TMP_DIR=$(uci -q get privoxy.privoxy.temporary_directory)	# no default needed
	if [ -n "$_TMP_DIR" ]; then
		mkdir -m0750 -p $_TMP_DIR
		chown privoxy:privoxy $_TMP_DIR
		echo -e "temporary-directory\t$_TMP_DIR" >> $CFGTEMP
	fi

	# HTTPS Inspection (Section 7.7)
	# ca-directory - directory for CA certificate and key files
	# certificate-directory - directory for generated certificates
	_CERT_DIR=$(uci -q get privoxy.privoxy.certdir)
	if [ -n "$_CERT_DIR" ]; then
		mkdir -m0700 -p $_CERT_DIR
		chown privoxy:privoxy $_CERT_DIR
		chmod 700 $_CERT_DIR

		# Generate CA certificate if it doesn't exist or regeneration requested
		_CA_CERT="$_CERT_DIR/ca-cert.pem"
		_CA_KEY="$_CERT_DIR/ca-key.pem"
		_REGEN_FILE="/etc/privoxy/regenerate_ca"
		if [ -f "$_REGEN_FILE" ]; then
			rm -f "$_CA_CERT" "$_CA_KEY"
			rm -f "$_REGEN_FILE"
		fi
		if [ ! -f "$_CA_CERT" ] || [ ! -f "$_CA_KEY" ]; then
			_CA_NAME=$(uci -q get privoxy.privoxy.ca_common_name) || _CA_NAME="Privoxy CA"
			_CA_DAYS=$(uci -q get privoxy.privoxy.ca_validity_days) || _CA_DAYS="3650"
			_CERT_DAYS=$(uci -q get privoxy.privoxy.cert_validity_days) || _CERT_DAYS="365"
			_CERT_KEY_SIZE=$(uci -q get privoxy.privoxy.cert_key_size) || _CERT_KEY_SIZE="2048"
			logger -p daemon.info -t "privoxy[]" "Generating CA certificate for HTTPS inspection"
			openssl req -new -newkey rsa:$_CERT_KEY_SIZE -days $_CA_DAYS -nodes -x509 \
				-subj "/CN=$_CA_NAME" -keyout "$_CA_KEY" -out "$_CA_CERT" 2>/dev/null
		fi

		# Set permissions: CA cert is public (readable by all), private key is secure
		chmod 644 "$_CA_CERT"
		chown root:root "$_CA_CERT"
		chmod 600 "$_CA_KEY"
		chown privoxy:privoxy "$_CA_KEY"

		# Create symlink for trustedCAs.pem pointing to system CA certificates
		_TRUSTED_CAS="$_CERT_DIR/trustedCAs.pem"
		_SYSTEM_CA_CRT="/etc/ssl/certs/ca-certificates.crt"
		if [ ! -f "$_TRUSTED_CAS" ]; then
			if [ -f "$_SYSTEM_CA_CRT" ]; then
				ln -sf "$_SYSTEM_CA_CRT" "$_TRUSTED_CAS"
			else
				# Fallback: use the CA bundle from ca-cert package
				_CA_BUNDLE="/etc/ssl/certs/ca-bundle.crt"
				if [ -f "$_CA_BUNDLE" ]; then
					ln -sf "$_CA_BUNDLE" "$_TRUSTED_CAS"
				fi
			fi
		fi

		# Write ca-directory directive (directory containing ca-cert.pem and ca-key.pem)
		echo -e "ca-directory\t$_CERT_DIR" >> $CFGTEMP

		# Write ca-cert-file directive (full path to CA certificate)
		echo -e "ca-cert-file\t$_CA_CERT" >> $CFGTEMP

		# Write ca-key-file directive (full path to CA key)
		echo -e "ca-key-file\t$_CA_KEY" >> $CFGTEMP

		# Write certificate-directory directive (directory for generated certificates)
		mkdir -m777 -p $SSLCERTSTEMP
		echo -e "certificate-directory\t$SSLCERTSTEMP" >> $CFGTEMP
	fi

	# enable-ssl-bumping
	_SSL_BUMP=$(uci -q get privoxy.privoxy.enable_ssl_bumping)
	if [ "$_SSL_BUMP" = "1" ]; then
		echo -e "enable-ssl-bumping\t1" >> $CFGTEMP
	fi

	# trustfile
	_TRUSTFILE=$(uci -q get privoxy.privoxy.trustfile)
	if [ -n "$_TRUSTFILE" ]; then
		echo -e "trustfile\t$_TRUSTFILE" >> $CFGTEMP
	fi

	config_load "privoxy"	# calling above option_cb() and write the rest into $CFGTEMP

	# move temp to final privoxy readable configuration
	mv -f $CFGTEMP $CFGFILE
	return 0
}

boot() {
	# check if privoxy is enabled
	[ "$(uci -q get privoxy.privoxy._enabled)" != "1" ] && return 0

	# wait a given time (default 10 seconds) before startup
	# to wait for interfaces to come up / not using hotplug events during boot
	_start() {
		[ $1 -gt 0 ] && {
			logger -p daemon.info -t "privoxy[]" "Scheduled startup in $1 seconds"
			sleep $1
		}
		start
	}

	local _DELAY
	_DELAY=$(uci -q get privoxy.privoxy.boot_delay)
	_start $_DELAY &
	return 0
}

shutdown() {
	rm -f /tmp/privoxy.hotplug
	stop
}

start() {
	# if already running do nothing
	local _PID=$(cat $PIDFILE 2>/dev/null)
	kill -1 $_PID 2>/dev/null && return 0

	_uci2conf
	/usr/sbin/privoxy --pidfile $PIDFILE --user privoxy.privoxy $CFGFILE
	touch /tmp/privoxy.hotplug

	# verify startup
	_PID=$(cat $PIDFILE 2>/dev/null)
	kill -1 $_PID 2>/dev/null
	local _ERR=$?
	[ $_ERR -eq 0 ] \
		&& logger -p daemon.notice -t "privoxy[$_PID]" "Started successfully"\
		|| logger -p daemon.warn -t "privoxy[]" "Failed to start"
	return $_ERR
}

reload() {
	# reload is also used by luci-app-privoxy
	local _PID=$(cat $PIDFILE 2>/dev/null)
	kill -1 $_PID 2>/dev/null
	if [ $? -eq 0 ]; then
		# only restart if already running
		restart
	else
		# only start if enabled
		enabled && start
	fi
	return 0
}

stop() {
	local _PID=$(cat $PIDFILE 2>/dev/null)
	kill -15 $_PID 2>/dev/null
	sleep 1			# give time to shutdown
	local _tmp=$(pgrep /usr/sbin/privoxy | tr "\n" " ")
	if [ -z "$_tmp" ]; then
		logger -p daemon.notice -t "privoxy[$_PID]" "Shutdown successfully"
	else
		kill -9 $_tmp	# Normally never come here
		logger -p daemon.warn -t "privoxy[$_tmp]" "Shutdown forced by KILL"
	fi
	return 0
}