From f77d3558f7aa413572990c5113d601412294899e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 2 Dec 2020 18:20:07 -0700 Subject: [PATCH 1/8] executors: add wifi executor --- Makefile | 3 +- executor-scripts/linux/wifi | 73 +++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/wifi diff --git a/Makefile b/Makefile index 147ec78..a5b9a7d 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,8 @@ EXECUTOR_SCRIPTS_OPT ?= \ gre \ wireguard \ ethtool \ - batman + batman \ + wifi EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} diff --git a/executor-scripts/linux/wifi b/executor-scripts/linux/wifi new file mode 100755 index 0000000..14f812a --- /dev/null +++ b/executor-scripts/linux/wifi @@ -0,0 +1,73 @@ +#!/bin/sh +# Copyright (c) 2020 Ariadne Conill +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# This software is provided 'as is' and without any warranty, express or +# implied. In no event shall the authors be liable for any damages arising +# from the use of this software. +# +# Manage wifi connections using wpa_supplicant. +# +# Vocabulary: +# wifi-ssid - The SSID name to connect to. +# wifi-psk - The pre-shared key to use. +# wifi-config - A path to a wpa_supplicant config file, for special configs. +# +# If wifi-config is not set, wifi-ssid and wifi-psk are required, and a config +# will be generated as /run/wpa_supplicant.$IFACE.conf. +# +# The wpa_supplicant PID is stored in /run/wpa_supplicant.$IFACE.pid. + +die() { + printf "ERROR: %s\n" "$1" >&2 + exit 1 +} + +[ -z "$IFACE" ] && die "IFACE not set" +[ -z "$PHASE" ] && die "PHASE not set" +PIDFILE="/run/wpa_supplicant.$IFACE.pid" + +# Set IF_WIFI_CONFIG_PATH to the default path if not already set. +[ -z "$IF_WIFI_CONFIG_PATH" ] && IF_WIFI_CONFIG_PATH="/run/wpa_supplicant.$IFACE.conf" + +# Supplicant options. +WPA_SUPPLICANT_OPTS="-qq -B -i$IFACE -c$IF_WIFI_CONFIG_PATH -P$PIDFILE" + +# Given $IF_WIFI_SSID and $IF_WIFI_PSK, generate a config file at $IF_WIFI_CONFIG_PATH. +generate_config() { + [ -z "$IF_WIFI_SSID" ] && die "wifi-ssid not set" + [ -z "$IF_WIFI_PSK" ] && die "wifi-psk not set" + + # We use a pipeline here to avoid leaking PSK into the process name. + (echo $IF_WIFI_PSK | /sbin/wpa_passphrase $IF_WIFI_SSID) >$IF_WIFI_CONFIG_PATH + + [ ! -e "$IF_WIFI_CONFIG_PATH" ] && die "failed to write temporary config: $IF_WIFI_CONFIG_PATH" +} + +# Start a supplicant process for $IFACE. +start() { + # If there is no config file located at $IF_WIFI_CONFIG_PATH, generate one. + [ ! -e "$IF_WIFI_CONFIG_PATH" ] && generate_config + + /sbin/wpa_supplicant $WPA_SUPPLICANT_OPTS +} + +# Stop the supplicant process for $IFACE. +stop() { + kill -9 $(cat $PIDFILE) 2>/dev/null + rm $PIDFILE +} + +[ -z "$VERBOSE" ] || set -x + +case "$PHASE" in +pre-up) + start + ;; +post-down) + stop + ;; +esac From b2f5a62c356f63290e5457d108e39c4d6424b771 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 2 Dec 2020 18:31:39 -0700 Subject: [PATCH 2/8] wifi executor: protect against unintentionally clobbering $IF_WIFI_CONFIG_PATH --- executor-scripts/linux/wifi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/executor-scripts/linux/wifi b/executor-scripts/linux/wifi index 14f812a..55aef66 100755 --- a/executor-scripts/linux/wifi +++ b/executor-scripts/linux/wifi @@ -30,6 +30,10 @@ die() { [ -z "$PHASE" ] && die "PHASE not set" PIDFILE="/run/wpa_supplicant.$IFACE.pid" +# Do not allow mixing wifi-config-path and wifi-ssid/wifi-psk. +[ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_SSID" ] && die "wifi-config-path cannot be used with wifi-ssid" +[ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_PSK" ] && die "wifi-config-path cannot be used with wifi-psk" + # Set IF_WIFI_CONFIG_PATH to the default path if not already set. [ -z "$IF_WIFI_CONFIG_PATH" ] && IF_WIFI_CONFIG_PATH="/run/wpa_supplicant.$IFACE.conf" From eeb40937fb57d3e8219c56f1f2bf4af5078b37e1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 2 Dec 2020 18:48:57 -0700 Subject: [PATCH 3/8] doc: document the wifi executor as interfaces-wifi(5). --- Makefile | 1 + doc/interfaces-wifi.scd | 55 +++++++++++++++++++++++++++++++++++++++++ doc/interfaces.scd | 5 ++++ 3 files changed, 61 insertions(+) create mode 100644 doc/interfaces-wifi.scd diff --git a/Makefile b/Makefile index a5b9a7d..5a44d07 100644 --- a/Makefile +++ b/Makefile @@ -164,6 +164,7 @@ MANPAGES_5 = \ doc/interfaces-ppp.5 \ doc/interfaces-vrf.5 \ doc/interfaces-vxlan.5 \ + doc/interfaces-wifi.5 \ doc/interfaces-wireguard.5 MANPAGES_7 = \ diff --git a/doc/interfaces-wifi.scd b/doc/interfaces-wifi.scd new file mode 100644 index 0000000..018138b --- /dev/null +++ b/doc/interfaces-wifi.scd @@ -0,0 +1,55 @@ +interfaces-wifi(5) + +# NAME + +*interfaces-wifi* - WiFi vocabulary for the interfaces(5) file format + +# DESCRIPTION + +Wi-Fi (the IEEE 802.11 family of protocols) is a commonly used wireless +networking standard. The following options allow for configuration of +Wi-Fi client interfaces. + +# WIFI-RELATED OPTIONS + +*wifi-config-path* _path_ + Denotes the absolute _path_ to a *wpa_supplicant* configuration file. + If no path is given, _/run/wpa_supplicant..conf_ will be + used for a temporary configuration file. This option may not be used + with other configuration options. + +*wifi-ssid* _ssid_ + The SSID the Wi-Fi client should connect to. + +*wifi-psk* _psk_ + The passphrase for connecting to the Wi-Fi network. If unset, the + client will connect without WPA2 encryption. + +# EXAMPLES + +A typical setup may involve connecting to a home and work network. To +achieve this, we can define a pair of virtual interfaces called *wifi-home* +and *wifi-work*, which connect to their respective wifi networks: + +``` +iface wifi-home + use dhcp + wifi-ssid HomeNetwork + wifi-psk ExamplePassphrase + +iface wifi-work + use dhcp + wifi-config-path /etc/network/wpa-work.conf +``` + +The virtual interfaces can be used with *ifup* and *ifdown*: + +``` +# ifup wlan0=wifi-home +# ifdown wlan0 +# ifup wlan0=wifi-work +``` + +# AUTHORS + +Ariadne Conill diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 15c43e6..00f465f 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -178,6 +178,11 @@ most common executors are: The interface is a Virtual Extensible LAN (VXLAN) tunnel endpoint. +*wifi* + The interface is a Wi-Fi (IEEE 802.11) client interface. + Configuration of the WiFi client interface requires the + *wpa_supplicant* package to be installed. + *wireguard* The interface is a Wireguard VPN tunnel endpoint. From 4e3a4c6cb89b4f32eb2acac61b8e6c2d523ca98a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 2 Dec 2020 19:27:28 -0700 Subject: [PATCH 4/8] wifi executor: add support for insecure wifi networks --- executor-scripts/linux/wifi | 38 +++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/executor-scripts/linux/wifi b/executor-scripts/linux/wifi index 55aef66..19a3102 100755 --- a/executor-scripts/linux/wifi +++ b/executor-scripts/linux/wifi @@ -35,34 +35,52 @@ PIDFILE="/run/wpa_supplicant.$IFACE.pid" [ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_PSK" ] && die "wifi-config-path cannot be used with wifi-psk" # Set IF_WIFI_CONFIG_PATH to the default path if not already set. -[ -z "$IF_WIFI_CONFIG_PATH" ] && IF_WIFI_CONFIG_PATH="/run/wpa_supplicant.$IFACE.conf" +WIFI_CONFIG_PATH="$IF_WIFI_CONFIG_PATH" +[ -z "$WIFI_CONFIG_PATH" ] && WIFI_CONFIG_PATH="/run/wpa_supplicant.$IFACE.conf" # Supplicant options. -WPA_SUPPLICANT_OPTS="-qq -B -i$IFACE -c$IF_WIFI_CONFIG_PATH -P$PIDFILE" +WPA_SUPPLICANT_OPTS="-qq -B -i$IFACE -c$WIFI_CONFIG_PATH -P$PIDFILE" -# Given $IF_WIFI_SSID and $IF_WIFI_PSK, generate a config file at $IF_WIFI_CONFIG_PATH. +# Given $IF_WIFI_SSID and $IF_WIFI_PSK, generate a config file at $WIFI_CONFIG_PATH. generate_config() { [ -z "$IF_WIFI_SSID" ] && die "wifi-ssid not set" [ -z "$IF_WIFI_PSK" ] && die "wifi-psk not set" # We use a pipeline here to avoid leaking PSK into the process name. - (echo $IF_WIFI_PSK | /sbin/wpa_passphrase $IF_WIFI_SSID) >$IF_WIFI_CONFIG_PATH + (echo $IF_WIFI_PSK | /sbin/wpa_passphrase $IF_WIFI_SSID) >$WIFI_CONFIG_PATH - [ ! -e "$IF_WIFI_CONFIG_PATH" ] && die "failed to write temporary config: $IF_WIFI_CONFIG_PATH" + [ ! -e "$WIFI_CONFIG_PATH" ] && die "failed to write temporary config: $WIFI_CONFIG_PATH" +} + +# Should we use the supplicant? +use_supplicant() { + [ -n "$IF_WIFI_CONFIG_PATH" ] && return 0 + [ -n "$IF_WIFI_PSK" ] && return 0 + + return 1 } # Start a supplicant process for $IFACE. start() { - # If there is no config file located at $IF_WIFI_CONFIG_PATH, generate one. - [ ! -e "$IF_WIFI_CONFIG_PATH" ] && generate_config + if use_supplicant; then + # If there is no config file located at $WIFI_CONFIG_PATH, generate one. + [ ! -e "$WIFI_CONFIG_PATH" ] && generate_config - /sbin/wpa_supplicant $WPA_SUPPLICANT_OPTS + /sbin/wpa_supplicant $WPA_SUPPLICANT_OPTS + else + /usr/sbin/iwconfig $IFACE essid -- "$IF_WIFI_SSID" ap any + fi } # Stop the supplicant process for $IFACE. stop() { - kill -9 $(cat $PIDFILE) 2>/dev/null - rm $PIDFILE + if use_supplicant; then + kill -9 $(cat $PIDFILE) 2>/dev/null + [ -z "$IF_WIFI_CONFIG_PATH" ] && rm $WIFI_CONFIG_PATH + rm $PIDFILE + else + /usr/sbin/iwconfig $IFACE essid any + fi } [ -z "$VERBOSE" ] || set -x From 589a1f30238cc6b4a0e9140bad2e178eeb9c38b8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 2 Dec 2020 19:29:22 -0700 Subject: [PATCH 5/8] docs: interfaces-wifi: add manpage xrefs for iwconfig(8) and wpa_supplicant(8). --- doc/interfaces-wifi.scd | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/interfaces-wifi.scd b/doc/interfaces-wifi.scd index 018138b..a169723 100644 --- a/doc/interfaces-wifi.scd +++ b/doc/interfaces-wifi.scd @@ -10,6 +10,9 @@ Wi-Fi (the IEEE 802.11 family of protocols) is a commonly used wireless networking standard. The following options allow for configuration of Wi-Fi client interfaces. +WPA-secured networks are managed using *wpa_supplicant*(8), while insecure +networks are managed directly with *iwconfig*(8). + # WIFI-RELATED OPTIONS *wifi-config-path* _path_ @@ -50,6 +53,11 @@ The virtual interfaces can be used with *ifup* and *ifdown*: # ifup wlan0=wifi-work ``` +# SEE ALSO + +*iwconfig*(8)++ +*wpa_supplicant*(8) + # AUTHORS Ariadne Conill From 93c8827205680c2e7b5d1ad70ce969622789ed25 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 3 Dec 2020 04:56:47 -0700 Subject: [PATCH 6/8] wifi executor: fix up some shell nitpicks --- executor-scripts/linux/wifi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/executor-scripts/linux/wifi b/executor-scripts/linux/wifi index 19a3102..1f239f5 100755 --- a/executor-scripts/linux/wifi +++ b/executor-scripts/linux/wifi @@ -60,7 +60,8 @@ use_supplicant() { return 1 } -# Start a supplicant process for $IFACE. +# Either start a supplicant process for $IFACE, or use iwconfig to trigger an +# association attempt. start() { if use_supplicant; then # If there is no config file located at $WIFI_CONFIG_PATH, generate one. @@ -72,12 +73,13 @@ start() { fi } -# Stop the supplicant process for $IFACE. +# Either stop the supplicant process for $IFACE, or use iwconfig to dissociate +# from the current SSID. stop() { if use_supplicant; then kill -9 $(cat $PIDFILE) 2>/dev/null - [ -z "$IF_WIFI_CONFIG_PATH" ] && rm $WIFI_CONFIG_PATH - rm $PIDFILE + [ -z "$IF_WIFI_CONFIG_PATH" ] && rm -- "$WIFI_CONFIG_PATH" + rm -- "$PIDFILE" else /usr/sbin/iwconfig $IFACE essid any fi From d7cc2a99176b3bce051eb93dc80baf6a3b3743bd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 3 Dec 2020 04:58:45 -0700 Subject: [PATCH 7/8] doc: interfaces: clarify that both wireless-tools and wpa_supplicant are needed for full functionality --- doc/interfaces.scd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 00f465f..d1131ca 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -181,7 +181,9 @@ most common executors are: *wifi* The interface is a Wi-Fi (IEEE 802.11) client interface. Configuration of the WiFi client interface requires the - *wpa_supplicant* package to be installed. + *wireless-tools* package to be installed. + The *wpa_supplicant* package must also be installed to + connect to hotspots using WPA-based security. *wireguard* The interface is a Wireguard VPN tunnel endpoint. From 383ae313722184ede465cf20bbe6a4984d1c5bb5 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 4 Dec 2020 07:01:47 +0100 Subject: [PATCH 8/8] wifi executor: And some sanity checks to stopping wpa_supplicant Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/wifi | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/executor-scripts/linux/wifi b/executor-scripts/linux/wifi index 1f239f5..93243f1 100755 --- a/executor-scripts/linux/wifi +++ b/executor-scripts/linux/wifi @@ -73,13 +73,35 @@ start() { fi } +# Stop wpa_supplicant safely +stop_wpa_supplicant() { + # Remove generated config file + [ -z "$IF_WIFI_CONFIG_PATH" ] && rm -- "$WIFI_CONFIG_PATH" + + # If there is no PIDFILE, there is nothing we can do + [ ! -d "$PIDFILE" ] && return + + pid=$(cat "$PIDFILE") + rm -- "$PIDFILE" + + # If there is no process with this PID running, we're done here + if [ ! -d "/proc/$pid/" ]; then + return + fi + + # Verify that the name of the running process matches wpa_supplicant + progname_path=$(readlink -n "/proc/$pid/exe") + progname=$(basename "$progname_path") + if [ "$progname" = "wpa_supplicant" ]; then + kill -9 $pid 2>/dev/null + fi +} + # Either stop the supplicant process for $IFACE, or use iwconfig to dissociate # from the current SSID. stop() { if use_supplicant; then - kill -9 $(cat $PIDFILE) 2>/dev/null - [ -z "$IF_WIFI_CONFIG_PATH" ] && rm -- "$WIFI_CONFIG_PATH" - rm -- "$PIDFILE" + stop_wpa_supplicant else /usr/sbin/iwconfig $IFACE essid any fi