Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion net/openvpn/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=openvpn

PKG_VERSION:=2.7.1
PKG_RELEASE:=2
PKG_RELEASE:=3

PKG_SOURCE_URL:=\
https://build.openvpn.net/downloads/releases/ \
Expand Down
62 changes: 50 additions & 12 deletions net/openvpn/files/lib/netifd/proto/openvpn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ option_builder() {
;;
file)
json_get_var v "$f"
openvpn_is_hotplug_hook_option "$f" && continue
[ -f "$v" ] || continue
[ -n "$v" ] && append exec_params "--${f//_/-} '$v'"
;;
Expand Down Expand Up @@ -88,10 +89,23 @@ option_builder() {
done
}

openvpn_is_hotplug_hook_option() {
case "$1" in
up|down|route_up|route_pre_down|ipchange|learn_address|client_connect|\
client_crresponse|client_disconnect|auth_user_pass_verify|\
tls_crypt_v2_verify|tls_verify)
return 0
;;
esac

return 1
}


# Not real config params used by openvpn - only by our proto handler
PROTO_BOOLS='
allow_deprecated
defaultroute
ipv6
'

Expand Down Expand Up @@ -188,34 +202,47 @@ proto_openvpn_setup() {

# 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
# Match the pre-netifd init script: default to the minimum level
# required for external up/down/route hooks.
[ -z "$script_security" ] && script_security=2

# Add default hotplug handling if 'script_security' allows user scripts.
# OpenVPN requires script-security >= 2 for up/down/route hooks; requiring 3
# prevents netifd from bringing the tunnel interface up for common client
# configurations using script_security=2.
if [ "$script_security" -ge '2' ]; then
local ipv6
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
local defaultroute route_noexec

logger -t "openvpn(proto)" \
-p daemon.info "Enabled default hotplug processing, as the openvpn configuration 'script_security' is '3'"
-p daemon.info "Enabled default hotplug processing, as the openvpn configuration 'script_security' is '$script_security'"

append exec_params "--setenv INTERFACE $config"
append exec_params "--script-security 3"
append exec_params "--script-security $script_security"

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 ipv6
json_get_vars ipv6 defaultroute route_noexec
#default ipv6 is enabled
[ -n "$ipv6" ] || ipv6=1
[ -n "$defaultroute" ] || defaultroute=1
# Leave OpenVPN's native address handling enabled by default, but keep
# route state in netifd by default for routing consumers.
if [ -z "$route_noexec" ]; then
route_noexec=1
append exec_params "--route-noexec"
else
[ "$route_noexec" = 1 ] || route_noexec=0
fi
append exec_params "--setenv IPV6 '$ipv6'"

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 "--setenv DEFAULTROUTE '$defaultroute'"
append exec_params "--setenv NETIFD_ROUTE_NOEXEC '$route_noexec'"

append exec_params "--up '/usr/libexec/openvpn-hotplug'"
[ -n "$up" ] && append exec_params "--setenv user_up '$up'"
Expand Down Expand Up @@ -262,7 +289,7 @@ proto_openvpn_setup() {
fi
else
logger -t "openvpn(proto)" \
-p daemon.warn "Default hotplug processing disabled, as the openvpn configuration 'script_security' is less than '3'"
-p daemon.warn "Default hotplug processing disabled, as the openvpn configuration 'script_security' is less than '2'"
fi

eval "set -- $exec_params"
Expand All @@ -284,6 +311,17 @@ proto_openvpn_renew() {

proto_openvpn_teardown() {
local iface="$1"
local pid

pid="$(cat "/var/run/openvpn.$iface.pid" 2>/dev/null)"
if [ -n "$pid" ]; then
daemon_pid="$pid" /usr/libexec/openvpn-hotplug cleanup "$iface"
else
/usr/libexec/openvpn-hotplug cleanup "$iface" 1
fi
proto_init_update "*" 0
proto_send_update "$iface"

rm -f \
"/var/run/openvpn.$iface.conf" \
"/var/run/openvpn.$iface.pass" \
Expand Down
71 changes: 58 additions & 13 deletions net/openvpn/files/lib/netifd/proto/openvpn.uc
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,23 @@ function is_true(v) {
return v === true || v === '1' || v === 1 || v === 'true';
}

function is_hotplug_hook_param(name) {
return index([
'up',
'down',
'route_up',
'route_pre_down',
'ipchange',
'learn_address',
'client_connect',
'client_crresponse',
'client_disconnect',
'auth_user_pass_verify',
'tls_crypt_v2_verify',
'tls_verify'
], name) >= 0;
}

function add_param(params, key, value) {
// key: option name (underscored), value: single string
let flag = `--${replace(key, '_', '-')}`;
Expand Down Expand Up @@ -336,6 +353,7 @@ function build_exec_params(cfg) {

for (let k in OPENVPN_FILE_PARAMS) {
if (k?.deprecated && !allow_deprecated) continue;
if (is_hotplug_hook_param(k.name)) continue;
let val = cfg[k.name];
if (val && type(val) == 'string') {
if (fs.access(val, fs.F_OK))
Expand Down Expand Up @@ -388,6 +406,10 @@ function pid_from_file(path) {
return data;
}

function shell_quote(value) {
return "'" + replace(`${value}`, "'", "'\\''") + "'";
}

function proto_setup(proto) {
if (!openvpn_exists()) {
warn('OpenVPN binary not found at ' + OPENVPN + '\n');
Expand Down Expand Up @@ -448,9 +470,34 @@ function proto_setup(proto) {
}
}

let script_security = cfg.script_security;
if (script_security == null || script_security === '')
script_security = 2;

// hotplug handler scripts
if (cfg.script_security >= 2) {
if (script_security >= 2) {
let ipv6 = cfg.ipv6;
if (ipv6 == null || ipv6 === '')
ipv6 = 1;
let defaultroute = cfg.defaultroute;
if (defaultroute == null || defaultroute === '')
defaultroute = 1;
// Leave OpenVPN's native address handling enabled by default, but keep
// route state in netifd by default for routing consumers.
let route_noexec;
if (cfg.route_noexec == null || cfg.route_noexec === '') {
route_noexec = 1;
push(params, '--route-noexec');
}
else {
route_noexec = is_true(cfg.route_noexec) ? 1 : 0;
}

push(params, '--setenv', 'INTERFACE', iface);
push(params, '--setenv', 'IPV6', `${ipv6}`);
push(params, '--setenv', 'DEFAULTROUTE', `${defaultroute}`);
push(params, '--setenv', 'NETIFD_ROUTE_NOEXEC', `${route_noexec}`);
push(params, '--script-security', `${script_security}`);
push(params, '--up', '/usr/libexec/openvpn-hotplug');
if (cfg.up) push(params, '--setenv', 'user_up', cfg.up);
push(params, '--down', '/usr/libexec/openvpn-hotplug');
Expand All @@ -471,8 +518,10 @@ function proto_setup(proto) {
if (cfg.client_crresponse) push(params, '--setenv', 'user_client_crresponse', cfg.client_crresponse);
push(params, '--client-disconnect', '/usr/libexec/openvpn-hotplug');
if (cfg.client_disconnect) push(params, '--setenv', 'user_client_disconnect', cfg.client_disconnect);
push(params, '--auth-user-pass-verify', '/usr/libexec/openvpn-hotplug', 'via-file');
if (cfg.auth_user_pass_verify) push(params, '--setenv', 'user_auth_user_pass_verify', cfg.auth_user_pass_verify);
if (cfg.auth_user_pass_verify) {
push(params, '--auth-user-pass-verify', '/usr/libexec/openvpn-hotplug', 'via-file');
push(params, '--setenv', 'user_auth_user_pass_verify', cfg.auth_user_pass_verify);
}
}

if (cfg.tls_client || cfg.tls_server) {
Expand Down Expand Up @@ -524,10 +573,13 @@ function proto_renew(proto) {

function proto_teardown(proto) {
let iface = proto.iface;
let pid = pid_from_file(sprintf(OPENVPN_PID, iface));

// Allow OpenVPN's down script to process

sleep(700);
if (pid)
system(sprintf('daemon_pid=%s /usr/libexec/openvpn-hotplug cleanup %s', shell_quote(pid), shell_quote(iface)));
else
system(sprintf('/usr/libexec/openvpn-hotplug cleanup %s 1', shell_quote(iface)));
proto.update_link(false);

// best-effort cleanup
fs.unlink(sprintf(OPENVPN_PASS, iface));
Expand All @@ -536,14 +588,7 @@ function proto_teardown(proto) {
fs.unlink(sprintf(OPENVPN_PID, iface));
fs.unlink(sprintf(OPENVPN_CONF, iface));

let link_data = {
ifname: iface
};

proto.kill_command();

// remove the link
proto.update_link(true, link_data);
}

netifd.add_proto({
Expand Down
Loading
Loading