openvpn: fix invoking user up & down commands from hotplug wrapper

This commit adds a number of fixes to the OpenVPN up/down hotplug command
wrapper which currently fails to actually invoke user defined up and down
commands for uci configurations not using external native configurations.

 - Use the `--setenv` to pass the user configured `up` and `down` commands
   as `user_up` and `user_down` environment variables respectively

 - Instead of attempting to scrape the `up` and `down` settings from the
   (possibly generated) native OpenVPN configuration in
   `/etc/hotplug.d/openvpn/01-user`, read them from the respective
   environment variables instead

 - Fix parsing of native configuration values in `get_openvpn_option()`;
   first try to parse a given setting as single quoted value, then as
   double quoted and finally as non-quoted, potentially white-space
   escaped one. This ensures that `up '/bin/foo'` is interpreted as
   `/bin/foo` and not `'/bin/foo'`

Ref: https://forum.openwrt.org/t/openvpn-up-down-configuration-ignored/91126
Supersedes: #15121, #15284
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
(cherry-picked from commit 7f065a94bb)
This commit is contained in:
Jo-Philipp Wich 2021-03-27 20:33:44 +01:00 committed by Josef Schlehofer
parent 00db3d345f
commit 3ba100928a
4 changed files with 27 additions and 16 deletions

View file

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=openvpn PKG_NAME:=openvpn
PKG_VERSION:=2.5.1 PKG_VERSION:=2.5.1
PKG_RELEASE:=2 PKG_RELEASE:=3
PKG_SOURCE_URL:=\ PKG_SOURCE_URL:=\
https://build.openvpn.net/downloads/releases/ \ https://build.openvpn.net/downloads/releases/ \

View file

@ -1,7 +1,5 @@
#!/bin/sh #!/bin/sh
. /lib/functions/openvpn.sh
[ -e "/etc/openvpn.user" ] && { [ -e "/etc/openvpn.user" ] && {
env -i ACTION="$ACTION" INSTANCE="$INSTANCE" \ env -i ACTION="$ACTION" INSTANCE="$INSTANCE" \
/bin/sh \ /bin/sh \
@ -11,12 +9,14 @@
# Wrap user defined scripts on up/down events # Wrap user defined scripts on up/down events
case "$ACTION" in case "$ACTION" in
up|down) up) command=$user_up ;;
if get_openvpn_option "$config" command "$ACTION"; then down) command=$user_down ;;
*) command= ;;
esac
if [ -n "$command" ]; then
shift shift
exec /bin/sh -c "$command $*" exec /bin/sh -c "$command $*"
fi fi
;;
esac
exit 0 exit 0

View file

@ -5,9 +5,9 @@ get_openvpn_option() {
local variable="$2" local variable="$2"
local option="$3" local option="$3"
local value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+(([^ \t\\]|\\.)+)[ \t]*$/\1/p' "$config" | tail -n1 | sed -re 's/\\(.)/\1/g')" local value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+'"'([^']+)'"'[ \t]*$/\1/p' "$config" | tail -n1)"
[ -n "$value" ] || value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+'"'([^']+)'"'[ \t]*$/\1/p' "$config" | tail -n1)"
[ -n "$value" ] || value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+"(([^"\\]|\\.)+)"[ \t]*$/\1/p' "$config" | tail -n1 | sed -re 's/\\(.)/\1/g')" [ -n "$value" ] || value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+"(([^"\\]|\\.)+)"[ \t]*$/\1/p' "$config" | tail -n1 | sed -re 's/\\(.)/\1/g')"
[ -n "$value" ] || value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+(([^ \t\\]|\\.)+)[ \t]*$/\1/p' "$config" | tail -n1 | sed -re 's/\\(.)/\1/g')"
[ -n "$value" ] || return 1 [ -n "$value" ] || return 1
export -n "$variable=$value" export -n "$variable=$value"

View file

@ -141,6 +141,8 @@ openvpn_add_instance() {
local dir="$2" local dir="$2"
local conf="$3" local conf="$3"
local security="$4" local security="$4"
local up="$5"
local down="$6"
procd_open_instance "$name" procd_open_instance "$name"
procd_set_param command "$PROG" \ procd_set_param command "$PROG" \
@ -150,6 +152,8 @@ openvpn_add_instance() {
--config "$conf" \ --config "$conf" \
--up "/usr/libexec/openvpn-hotplug up $name" \ --up "/usr/libexec/openvpn-hotplug up $name" \
--down "/usr/libexec/openvpn-hotplug down $name" \ --down "/usr/libexec/openvpn-hotplug down $name" \
${up:+--setenv user_up "$up"} \
${down:+--setenv user_down "$down"} \
--script-security "${security:-2}" \ --script-security "${security:-2}" \
$(openvpn_get_dev "$name" "$conf") \ $(openvpn_get_dev "$name" "$conf") \
$(openvpn_get_credentials "$name" "$conf") $(openvpn_get_credentials "$name" "$conf")
@ -173,14 +177,18 @@ start_instance() {
return 1 return 1
} }
local script_security local up down script_security
config_get up "$s" up
config_get down "$s" down
config_get script_security "$s" script_security config_get script_security "$s" script_security
[ ! -d "/var/run" ] && mkdir -p "/var/run" [ ! -d "/var/run" ] && mkdir -p "/var/run"
if [ ! -z "$config" ]; then if [ ! -z "$config" ]; then
append UCI_STARTED "$config" "$LIST_SEP" append UCI_STARTED "$config" "$LIST_SEP"
openvpn_add_instance "$s" "${config%/*}" "$config" "$script_security" [ -n "$up" ] || get_openvpn_option "$config" up up
[ -n "$down" ] || get_openvpn_option "$config" down down
openvpn_add_instance "$s" "${config%/*}" "$config" "$script_security" "$up" "$down"
return return
fi fi
@ -190,7 +198,7 @@ start_instance() {
append_params "$s" $OPENVPN_PARAMS append_params "$s" $OPENVPN_PARAMS
append_list "$s" $OPENVPN_LIST append_list "$s" $OPENVPN_LIST
openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" "$script_security" openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" "$script_security" "$up" "$down"
} }
start_service() { start_service() {
@ -207,6 +215,7 @@ start_service() {
fi fi
} }
. /lib/functions/openvpn.sh
. /usr/share/openvpn/openvpn.options . /usr/share/openvpn/openvpn.options
config_load 'openvpn' config_load 'openvpn'
@ -216,7 +225,7 @@ start_service() {
else else
config_foreach start_instance 'openvpn' config_foreach start_instance 'openvpn'
local path name local path name up down
for path in /etc/openvpn/*.conf; do for path in /etc/openvpn/*.conf; do
if [ -f "$path" ]; then if [ -f "$path" ]; then
name="${path##*/}"; name="${name%.conf}" name="${path##*/}"; name="${name%.conf}"
@ -231,7 +240,9 @@ start_service() {
continue continue
fi fi
openvpn_add_instance "$name" "${path%/*}" "$path" get_openvpn_option "$path" up up || up=""
get_openvpn_option "$path" down down || down=""
openvpn_add_instance "$name" "${path%/*}" "$path" "" "$up" "$down"
fi fi
done done
fi fi