openvpn: fix invoking user up & down commands from hotplug wrapper
authorJo-Philipp Wich <jo@mein.io>
Sat, 27 Mar 2021 19:33:44 +0000 (20:33 +0100)
committerEtienne Champetier <champetier.etienne@gmail.com>
Thu, 1 Apr 2021 11:20:03 +0000 (07:20 -0400)
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>
net/openvpn/Makefile
net/openvpn/files/etc/hotplug.d/openvpn/01-user
net/openvpn/files/lib/functions/openvpn.sh
net/openvpn/files/openvpn.init

index 36828b5606dbe52e26f6009e3d8d77f80c30f1f5..3b3adce42714cb619c73dbbf71c1711f8e06d423 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=openvpn
 
 PKG_VERSION:=2.5.1
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE_URL:=\
        https://build.openvpn.net/downloads/releases/ \
index f93823e5c55559be61352b096995b9a828e45fdd..4c72f1c4bd7efc4986fcce5aad28d9a9325ea537 100644 (file)
@@ -1,7 +1,5 @@
 #!/bin/sh
 
-. /lib/functions/openvpn.sh
-
 [ -e "/etc/openvpn.user" ] && {
        env -i ACTION="$ACTION" INSTANCE="$INSTANCE" \
                /bin/sh \
 
 # Wrap user defined scripts on up/down events
 case "$ACTION" in
-       up|down)
-               if get_openvpn_option "$config" command "$ACTION"; then
-                       shift
-                       exec /bin/sh -c "$command $*"
-               fi
-       ;;
+       up) command=$user_up ;;
+       down) command=$user_down ;;
+       *) command= ;;
 esac
 
+if [ -n "$command" ]; then
+       shift
+       exec /bin/sh -c "$command $*"
+fi
+
 exit 0
index 83fb1bb453e1f7b7977c262d647c1f5d2dd4dea9..2de6fb730ae0fa91938f98a9911f88105af5f666 100644 (file)
@@ -5,9 +5,9 @@ get_openvpn_option() {
        local variable="$2"
        local option="$3"
 
-       local value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+(([^ \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)"
+       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 | 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
 
        export -n "$variable=$value"
index fba9b3c2c1765f0452bd64d5693e2861fbc0749c..f7dc006ce37eaf990c99cbbfa8fa00afffc6b041 100644 (file)
@@ -141,6 +141,8 @@ openvpn_add_instance() {
        local dir="$2"
        local conf="$3"
        local security="$4"
+       local up="$5"
+       local down="$6"
 
        procd_open_instance "$name"
        procd_set_param command "$PROG" \
@@ -150,6 +152,8 @@ openvpn_add_instance() {
                --config "$conf" \
                --up "/usr/libexec/openvpn-hotplug up $name" \
                --down "/usr/libexec/openvpn-hotplug down $name" \
+               ${up:+--setenv user_up "$up"} \
+               ${down:+--setenv user_down "$down"} \
                --script-security "${security:-2}" \
                $(openvpn_get_dev "$name" "$conf") \
                $(openvpn_get_credentials "$name" "$conf")
@@ -173,14 +177,18 @@ start_instance() {
                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
 
        [ ! -d "/var/run" ] && mkdir -p "/var/run"
 
        if [ ! -z "$config" ]; then
                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
        fi
 
@@ -190,7 +198,7 @@ start_instance() {
        append_params "$s" $OPENVPN_PARAMS
        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() {
@@ -207,6 +215,7 @@ start_service() {
                fi
        }
 
+       . /lib/functions/openvpn.sh
        . /usr/share/openvpn/openvpn.options
        config_load 'openvpn'
 
@@ -216,7 +225,7 @@ start_service() {
        else
                config_foreach start_instance 'openvpn'
 
-               local path name
+               local path name up down
                for path in /etc/openvpn/*.conf; do
                        if [ -f "$path" ]; then
                                name="${path##*/}"; name="${name%.conf}"
@@ -231,7 +240,9 @@ start_service() {
                                        continue
                                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
                done
        fi