blob: 3e3458af272daa9c2cfc36c4ddd61ee1bd8b781f (
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
#!/bin/sh
# OpenVPN netifd proto handler for OpenWrt
# Copyright (C) 2026
# shellcheck disable=SC1091,2046,2091,3043,3060
[ -x /usr/sbin/openvpn ] || exit 0
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /usr/share/openvpn/openvpn.options # OPENVPN_* options
. ../netifd-proto.sh
. /usr/share/libubox/jshn.sh
init_proto "$@"
}
# Helper to DRY up repeated option handling in init/setup
option_builder() {
# option_builder <action:add|build> <LIST_VAR_NAME> <type>
local action="$1"; shift
local list_var="$1"; shift
local opt_type="$1"; shift
local f v
for f in $(eval echo \$"$list_var")
do
if [ "$action" = "add" ]; then
f=${f%%:*}
case "$opt_type" in
bool) proto_config_add_boolean "$f:bool" ;;
protobool) proto_config_add_boolean "$f:protobool" ;;
uinteger) proto_config_add_int "$f:uinteger" ;;
integer) proto_config_add_int "$f:integer" ;;
string) proto_config_add_string "$f:string" ;;
protostring) proto_config_add_string "$f:protostring" ;;
file) proto_config_add_string "$f:file" ;;
list) proto_config_add_array "$f:list" ;;
esac
elif [ "$action" = "build" ]; then
[ "${f#*:}" = "d" ] && [ "$ALLOW_DEPRECATED" = 0 ] && continue
f=${f%%:*}
case "$opt_type" in
bool)
json_get_var v "$f"
[ "$v" = 1 ] && append exec_params "--${f//_/-}"
;;
uinteger|integer|string)
json_get_var v "$f"
case $f in
push_remove)
[ -n "$v" ] && append exec_params "--${f//_/-} '$v'"
;;
*)
[ -n "$v" ] && append exec_params "--${f//_/-} $v"
;;
esac
;;
file)
json_get_var v "$f"
[ -f "$v" ] || continue
[ -n "$v" ] && append exec_params "--${f//_/-} '$v'"
;;
list)
local type
json_get_type type "$f"
case "$type" in
object|array)
local keys key
json_select "$f"
json_get_keys keys
for key in $keys; do
json_get_var val "$key"
case $f in
push)
append exec_params "--${f//_/-} '$val'"
;;
*)
append exec_params "--${f//_/-} $val"
;;
esac
done
json_select ..
;;
*) ;;
esac
;;
esac
fi
done
}
# Not real config params used by openvpn - only by our proto handler
PROTO_BOOLS='
allow_deprecated
'
PROTO_STRINGS='
username
password
cert_password
ovpnproto
'
proto_openvpn_init_config() {
available=1
no_device=1
lasterror=1
renew_handler=1
# There may be opvnvpn options which mean that a tap L2 device exists.
# TODO: Set no_device to depend on tap device
proto_add_dynamic_defaults
# Add proto config options - netifd compares these for changes between interface events
option_builder add PROTO_BOOLS protobool
option_builder add PROTO_STRINGS string
option_builder add OPENVPN_BOOLS bool
option_builder add OPENVPN_UINTS uinteger
option_builder add OPENVPN_INTS integer
option_builder add OPENVPN_PARAMS_STRING string
option_builder add OPENVPN_PARAMS_FILE file
option_builder add OPENVPN_LIST list
}
proto_openvpn_setup() {
local config="$1"
local conf_file="/var/run/openvpn.$config.conf"
local exec_params cd_dir
exec_params=
json_get_var dev_type dev_type
[ -z "$dev_type" ] && append exec_params "--dev-type tun"
json_get_var ovpnproto ovpnproto
[ -n "$ovpnproto" ] && append exec_params "--proto $ovpnproto"
json_get_var config_file config
# shellcheck disable=SC2154
cd_dir="${config_file%/*}"
[ "$cd_dir" = "$config_file" ] && cd_dir="/"
append exec_params "--cd $cd_dir"
append exec_params "--status /var/run/openvpn.$config.status"
append exec_params "--syslog openvpn_$config"
append exec_params "--tmp-dir /tmp"
json_get_var ALLOW_DEPRECATED allow_deprecated
[ -z "$ALLOW_DEPRECATED" ] && ALLOW_DEPRECATED=0
# Build exec params from configured options we get from ubus values stored during init_config
option_builder build OPENVPN_BOOLS bool
option_builder build OPENVPN_UINTS uinteger
option_builder build OPENVPN_INTS integer
option_builder build OPENVPN_PARAMS_STRING string
option_builder build OPENVPN_PARAMS_FILE file
option_builder build OPENVPN_LIST list
proto_add_dynamic_defaults
json_get_vars auth_user_pass askpass username password cert_password
mkdir -p /var/run
# combine into --askpass:
if [ -n "$cert_password" ]; then
cp_file="/var/run/openvpn.$config.pass"
umask 077
printf '%s\n' "${cert_password:-}" > "$cp_file"
umask 022
append exec_params "--askpass $cp_file"
elif [ -n "$askpass" ]; then
append exec_params "--askpass $askpass"
fi
# combine into --auth-user-pass:
if [ -n "$username" ] || [ -n "$password" ]; then
auth_file="/var/run/openvpn.$config.auth"
umask 077
printf '%s\n' "${username:-}" "${password:-}" > "$auth_file"
umask 022
append exec_params "--auth-user-pass $auth_file"
elif [ -n "$auth_user_pass" ]; then
append exec_params "--auth-user-pass $auth_user_pass"
fi
# Testing option
# ${tls_exit:+--tls-exit} \
# Check 'script_security' option
json_get_var script_security script_security
[ -z "$script_security" ] && script_security=3
# Add default hotplug handling if 'script_security' option is equal '3'
if [ "$script_security" -eq '3' ]; then
local up down route_up route_pre_down
local client tls_client tls_server
local tls_crypt_v2_verify mode learn_address client_connect
local client_crresponse client_disconnect auth_user_pass_verify
logger -t "openvpn(proto)" \
-p daemon.info "Enabled default hotplug processing, as the openvpn configuration 'script_security' is '3'"
append exec_params "--setenv INTERFACE $config"
append exec_params "--script-security 3"
json_get_vars up down route_up route_pre_down
json_get_vars tls_crypt_v2_verify mode learn_address client_connect
json_get_vars client_crresponse client_disconnect auth_user_pass_verify
json_get_vars ifconfig_noexec route_noexec
[ -z "$ifconfig_noexec" ] && append exec_params "--ifconfig-noexec"
[ -z "$route_noexec" ] && append exec_params "--route-noexec"
append exec_params "--up '/usr/libexec/openvpn-hotplug'"
[ -n "$up" ] && append exec_params "--setenv user_up '$up'"
append exec_params "--down '/usr/libexec/openvpn-hotplug'"
[ -n "$down" ] && append exec_params "--setenv user_down '$down'"
append exec_params "--route-up '/usr/libexec/openvpn-hotplug'"
[ -n "$route_up" ] && append exec_params "--setenv user_route_up '$route_up'"
append exec_params "--route-pre-down '/usr/libexec/openvpn-hotplug'"
[ -n "$route_pre_down" ] && append exec_params "--setenv user_route_pre_down '$route_pre_down'"
append exec_params "--tls-crypt-v2-verify '/usr/libexec/openvpn-hotplug'"
[ -n "$tls_crypt_v2_verify" ] && append exec_params "--setenv user_tls_crypt_v2_verify '$tls_crypt_v2_verify'"
[ "$mode" = 'server' ] && {
append exec_params "--learn-address '/usr/libexec/openvpn-hotplug'"
[ -n "$learn_address" ] && append exec_params "--setenv user_learn_address '$learn_address'"
append exec_params "--client-connect '/usr/libexec/openvpn-hotplug'"
[ -n "$client_connect" ] && append exec_params "--setenv user_client_connect '$client_connect'"
append exec_params "--client-crresponse '/usr/libexec/openvpn-hotplug'"
[ -n "$client_crresponse" ] && append exec_params "--setenv user_client_crresponse '$client_crresponse'"
append exec_params "--client-disconnect '/usr/libexec/openvpn-hotplug'"
[ -n "$client_disconnect" ] && append exec_params "--setenv user_client_disconnect '$client_disconnect'"
[ -n "$auth_user_pass_verify" ] && {
append exec_params "--auth-user-pass-verify '/usr/libexec/openvpn-hotplug' via-file"
append exec_params "--setenv user_auth_user_pass_verify '$auth_user_pass_verify'"
}
}
json_get_vars client tls_client tls_server
if [ "$client" = 1 ] || [ "$tls_client" = 1 ]; then
append exec_params "--ipchange '/usr/libexec/openvpn-hotplug'"
json_get_var ipchange ipchange
[ -n "$ipchange" ] && append exec_params "--setenv user_ipchange '$ipchange'"
fi
if [ "$tls_client" = 1 ] || [ "$tls_server" = 1 ]; then
append exec_params "--tls-verify '/usr/libexec/openvpn-hotplug'"
json_get_var tls_verify tls_verify
[ -n "$tls_verify" ] && append exec_params "--setenv user_tls_verify '$tls_verify'"
fi
else
logger -t "openvpn(proto)" \
-p daemon.warn "Default hotplug processing disabled, as the openvpn configuration 'script_security' is less than '3'"
fi
eval "set -- $exec_params"
umask 077
printf "%b\n" "${exec_params//--/\\n}" > "$conf_file"
umask 022
proto_run_command "$config" openvpn --config "$conf_file"
# last param wins; user provided status or syslog supersedes.
}
proto_openvpn_renew() {
config="$1"
local sigusr1
sigusr1="$(kill -l SIGUSR1)"
[ -n "$sigusr1" ] && proto_kill_command "$config" "$sigusr1"
}
proto_openvpn_teardown() {
local iface="$1"
rm -f \
"/var/run/openvpn.$iface.conf" \
"/var/run/openvpn.$iface.pass" \
"/var/run/openvpn.$iface.auth" \
"/var/run/openvpn.$iface.status"
proto_kill_command "$iface"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol openvpn
}
|