diff --git a/README b/README index f096c31..500ca44 100644 --- a/README +++ b/README @@ -11,6 +11,7 @@ Optional: - dialog: for the interactive assistant - ifplugd: for automatic wired connections - ppp: for PPP support +- rosenpass: for Rosenpass key exchange over WireGuard - wireguard-tools: for WireGuard support For documentation generation: diff --git a/contrib/PKGBUILD.in b/contrib/PKGBUILD.in index 9f8ff3f..a21cbe1 100644 --- a/contrib/PKGBUILD.in +++ b/contrib/PKGBUILD.in @@ -16,6 +16,7 @@ optdepends=('dialog: for the menu based wifi assistant' 'ifplugd: for automatic wired connections through netctl-ifplugd' 'ppp: for PPP connections' 'openvswitch: for Open vSwitch connections' + 'rosenpass: for Rosenpass key exchange over WireGuard' 'wireguard-tools: for WireGuard connections') install=netctl.install source=(https://sources.archlinux.org/other/packages/netctl/netctl-${pkgver}.tar.xz{,.sig}) @@ -34,4 +35,3 @@ package() { ln -s netctl "$pkgdir/usr/share/bash-completion/completions/wifi-menu" install -D -m644 contrib/zsh-completion "$pkgdir/usr/share/zsh/site-functions/_netctl" } - diff --git a/docs/examples/rosenpass b/docs/examples/rosenpass new file mode 100644 index 0000000..dd15977 --- /dev/null +++ b/docs/examples/rosenpass @@ -0,0 +1,11 @@ +Description="Example Rosenpass tunnel connection" +Interface=wg0 +Connection=rosenpass +RosenpassConfigFile=/etc/rosenpass/wg0.toml + +## Example IP configuration +IP=static +Address=('10.0.0.2/24') + +IP6=static +Address6=('fd00::2/120') diff --git a/docs/netctl.profile.5.txt b/docs/netctl.profile.5.txt index e8f0312..7c516a8 100644 --- a/docs/netctl.profile.5.txt +++ b/docs/netctl.profile.5.txt @@ -64,6 +64,8 @@ AVAILABLE CONNECTION TYPES For MACVLANs on ethernet-like connections. +wireguard+:: For WireGuard interfaces. ++rosenpass+:: + For Rosenpass key exchange over WireGuard interfaces. GENERAL OPTIONS @@ -580,6 +582,21 @@ the `wireguard' type: '/etc/wireguard/$Interface.conf'. +OPTIONS FOR `rosenpass' CONNECTIONS +----------------------------------- +The name of the WireGuard interface is specified in 'Interface='. Next +to the *ip options*, the following are understood for connections of +the `rosenpass' type: + +'RosenpassConfigFile=':: + Path to a *Rosenpass* configuration file. Defaults to + '/etc/rosenpass/$Interface.toml'. + +'RosenpassBinary=':: + Name or path of the *Rosenpass* executable. Defaults to + 'rosenpass'. + + SPECIAL QUOTING RULES --------------------- Configuration files for *wpa_supplicant* use non-standard quoting. diff --git a/src/lib/connections/rosenpass b/src/lib/connections/rosenpass new file mode 100644 index 0000000..7073247 --- /dev/null +++ b/src/lib/connections/rosenpass @@ -0,0 +1,88 @@ +# Contributed by: Rosenpass contributors + +. "$SUBR_DIR/ip" + +# Make sure BindsToInterfaces is set +BindsToInterfaces=("${BindsToInterfaces[@]}") + +rosenpass_state_dir() { + printf "%s/rosenpass-%s-%s" "$STATE_DIR" "$Interface" "$Profile" +} + +rosenpass_stop() { + local pidfile pid + pidfile="$(rosenpass_state_dir)/pid" + + if [[ -r $pidfile ]]; then + read -r pid < "$pidfile" + if [[ $pid =~ ^[0-9]+$ ]] && kill -0 "$pid" 2>/dev/null; then + kill "$pid" + timeout_wait 3 "! kill -0 $pid 2>/dev/null" + fi + fi +} + +rosenpass_up() { + local state_dir pidfile pid rosenpass_bin config_file + state_dir="$(rosenpass_state_dir)" + pidfile="$state_dir/pid" + rosenpass_bin="${RosenpassBinary:-rosenpass}" + config_file="${RosenpassConfigFile:-/etc/rosenpass/$Interface.toml}" + + if is_interface "$Interface"; then + report_error "Interface '$Interface' already exists" + return 1 + fi + if ! command -v "$rosenpass_bin" &>/dev/null; then + report_error "Rosenpass executable '$rosenpass_bin' is unavailable" + return 1 + fi + if [[ ! -r $config_file ]]; then + report_error "Rosenpass config '$config_file' does not exist or is not readable" + return 1 + fi + + # Treat $MACAddress as in other connections, but it has no effect here + interface_add wireguard "$Interface" "$MACAddress" || return + + rm -rf "$state_dir" + mkdir -p "$state_dir" + "$rosenpass_bin" exchange-config "$config_file" > "$state_dir/stdout" 2> "$state_dir/stderr" & + pid=$! + printf "%s\n" "$pid" > "$pidfile" + + if ! timeout_wait "${TimeoutUp:-5}" "kill -0 $pid 2>/dev/null"; then + report_error "Failed to start Rosenpass for profile '$Profile'" + rm -rf "$state_dir" + interface_delete "$Interface" + return 1 + fi + + if ! bring_interface_up "$Interface"; then + report_error "Failed to bring interface '$Interface' up" + rosenpass_stop + rm -rf "$state_dir" + interface_delete "$Interface" + return 1 + fi + + if ! ip_set; then + rosenpass_stop + rm -rf "$state_dir" + interface_delete "$Interface" + return 1 + fi +} + +rosenpass_down() { + local state_dir + state_dir="$(rosenpass_state_dir)" + + ip_unset + rosenpass_stop + rm -rf "$state_dir" + interface_delete "$Interface" +} + + +# vim: ft=sh ts=4 et sw=4: