summaryrefslogtreecommitdiffstats
path: root/net/tor-hs/files/tor-hs.init
blob: 14166d354f1987df598e1fe99641768e9d434d73 (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
#!/bin/sh /etc/rc.common

START=52
STOP=52

USE_PROCD=1

TORRC_FILE=/var/run/tor/torrc_generated # file with torrc config
HS_DIR_PATH=/etc/tor/hidden_service # onion services directory
TOR_USER=tor

config_tor() {
	local restart_tor update_config
	config_get_bool restart_tor common RestartTor
	config_get_bool update_config common UpdateTorConf

	tail_conf=$(uci show tor.conf.tail_include 2>/dev/null)
	head_conf=$(uci show tor.conf.head_include 2>/dev/null)

	if [ "$update_config" = "1" ]; then
		if [ -n "$(echo $tail_conf | grep $TORRC_FILE)" ] || [ -n "$(echo $head_conf | grep $TORRC_FILE)" ]; then
			echo "Info. Not updating tor configuration"
		else
			echo "Info. Updating tor configuration"
			uci add_list tor.conf.tail_include="$TORRC_FILE"
			uci commit tor
		fi
	fi

	if [ "$restart_tor" = "1" ]; then
		/etc/init.d/tor restart
	fi
}

handle_hs_ports_conf() {
	local public_port local_port
	local value="$1"
	local ipv4="$2"

	public_port="${value#*;}"
	local_port="${value%;*}"
	echo "HiddenServicePort $public_port $ipv4:$local_port" >> "$TORRC_FILE"
}

parse_hs_conf() {
	local name public_port local_port enable_hs ipv4
	local config="$1"

	config_get name "$config" Name
	[ -z "$name" ] && return 0
	config_get_bool enable_hs "$config" Enabled 0
	config_get ipv4 "$config" IPv4

	if [ "$enable_hs" = "1" ]; then
		if [ ! -d "$HS_DIR_PATH/$name" ]; then
			echo "New onion service dir is $HS_DIR_PATH/$name"
			mkdir -p -m 700 "$HS_DIR_PATH/"
			mkdir -m 700 "$HS_DIR_PATH/$name"
			chown -R "$TOR_USER:$TOR_USER" "$HS_DIR_PATH/"
		fi

		echo "HiddenServiceDir $HS_DIR_PATH/$name" >> "$TORRC_FILE"
		config_list_foreach "$config" PublicLocalPort handle_hs_ports_conf "$ipv4"
	fi
}

parse_hs_conf_hooks() {
	local name hook_script enable_hs hostname_file
	local config="$1"

	config_get name "$config" Name
	[ -z "$name" ] && return 0
	config_get_bool enable_hs "$config" Enabled 0
	config_get hook_script "$config" HookScript

	hostname_file="$HS_DIR_PATH/$name/hostname"

	# check if we should run hook_script
	if [ "$enable_hs" = "1" ] && [ -x "$hook_script" ] && [ -f "$hostname_file" ]; then
		hostname_uri=$(cat "$hostname_file")
		# call hook script
		$hook_script "--update-onion" "$hostname_uri"
	fi
}

parse_common_conf() {
	local hs_dir generated_config
	config_get generated_config common GenConf
	config_get hs_dir common HSDir
	[ -n "$hs_dir" ] && HS_DIR_PATH="$hs_dir"
	[ -n "$generated_config" ] && TORRC_FILE="$generated_config"
}

start_service() {
	# create runtime dir
	mkdir -p -m 700 /var/run/tor
	chown -R "$TOR_USER:$TOR_USER" /var/run/tor
	config_load tor-hs
	validate_common_section || {
		echo "validation failed"
		return 1
	}
	# load common config
	parse_common_conf
	# clean config
	echo -n "" > "$TORRC_FILE"
	chown "$TOR_USER:$TOR_USER" "$TORRC_FILE"
	# load hs service
	config_foreach validate_hidden_service_section hidden-service parse_hs_conf
	# update tor config
	config_tor
	# load and run tor-hs hooks
	config_foreach parse_hs_conf_hooks hidden-service
}

validate_common_section() {
	uci_validate_section tor-hs tor-hs common \
		'GenConf:string:/var/run/tor/torrc_generated' \
		'HSDir:string:/etc/tor/hidden_service' \
		'RestartTor:bool:1' \
		'UpdateTorConf:bool:1'
}

validate_hidden_service_section() {
	uci_load_validate tor-hs hidden-service "$1" "$2" \
		'Name:string(1)' \
		'Description:string' \
		'Enabled:bool:0' \
		'IPv4:host:127.0.0.1' \
		'PublicLocalPort:list(string)' \
		'HookScript:string'
}