diff --git a/README.md b/README.md index 1af57a07..9985bb2b 100644 --- a/README.md +++ b/README.md @@ -288,7 +288,7 @@ Available scripts * [Download, import and update firewall address-lists](doc/fw-addr-lists.md) (`fw-addr-lists`) * [Wait for global functions und modules](doc/global-wait.md) (`global-wait`) * [Send GPS position to server](doc/gps-track.md) (`gps-track`) -* [Use WPA network with hotspot credentials](doc/hotspot-to-wpa.md) (`hotspot-to-wpa`, `hotspot-to-wpa-lease` & `hotspot-to-wpa-cleanup`) +* [Use WPA network with hotspot credentials](doc/hotspot-to-wpa.md) (`hotspot-to-wpa` & `hotspot-to-wpa-cleanup`) * [Create DNS records for IPSec peers](doc/ipsec-to-dns.md) (`ipsec-to-dns`) * [Update configuration on IPv6 prefix change](doc/ipv6-update.md) (`ipv6-update`) * [Manage IP addresses with bridge status](doc/ip-addr-bridge.md) (`ip-addr-bridge`) diff --git a/doc/hotspot-to-wpa.md b/doc/hotspot-to-wpa.md index 5a00f44e..9b3b1976 100644 --- a/doc/hotspot-to-wpa.md +++ b/doc/hotspot-to-wpa.md @@ -26,38 +26,35 @@ Requirements and installation You need a properly configured hotspot on one (open) SSID and a WPA enabled SSID with suffix "`-wpa`". -Then install the scripts. Depending on whether you use `wifi` package -(`/interface/wifi`) or legacy wireless with CAPsMAN (`/caps-man`) you need -to install a different set of scripts. Then set the `on-login` script in hotspot. +Then install the script. +Depending on whether you use `wifi` package (`/interface/wifi`)or legacy +wifi with CAPsMAN (`/caps-man`) you need to install a different script and +set it as `on-login` script in hotspot. For `wifi`: - $ScriptInstallUpdate hotspot-to-wpa.wifi,hotspot-to-wpa-lease.wifi,dhcpv4-server-lease; + $ScriptInstallUpdate hotspot-to-wpa.wifi; /ip/hotspot/user/profile/set on-login="hotspot-to-wpa.wifi" [ find ]; For legacy CAPsMAN: - $ScriptInstallUpdate hotspot-to-wpa.wifi,hotspot-to-wpa-lease.capsman,dhcpv4-server-lease; + $ScriptInstallUpdate hotspot-to-wpa.capsman; /ip/hotspot/user/profile/set on-login="hotspot-to-wpa.capsman" [ find ]; -Finally ad add the lease script your hotspot interfaces' dhcp server. - - /ip/dhcp-server/set lease-script="dhcpv4-server-lease" hotspot; - ### Automatic cleanup -With just the above scripts installed the mac addresses will last in the +With just `hotspot-to-wpa` installed the mac addresses will last in the access list forever. Install the optional script for automatic cleanup and add a scheduler. For `wifi`: - $ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi; + $ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi,dhcpv4-server-lease; /system/scheduler/add interval=1d name="hotspot-to-wpa-cleanup" on-event="/system/script/run hotspot-to-wpa-cleanup.wifi;" start-time=startup; For legacy CAPsMAN: - $ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman; + $ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman,dhcpv4-server-lease; /system/scheduler/add interval=1d name="hotspot-to-wpa-cleanup" on-event="/system/script/run hotspot-to-wpa-cleanup.capsman;" start-time=startup; And add the lease script and matcher comment to your wpa interfaces' dhcp diff --git a/global-functions.rsc b/global-functions.rsc index 414f70c5..6da5e740 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -15,7 +15,7 @@ # Git commit id & info, expected configuration version :global CommitId "unknown"; :global CommitInfo "unknown"; -:global ExpectedConfigVersion 145; +:global ExpectedConfigVersion 144; # global variables not to be changed by user :global GlobalFunctionsReady false; diff --git a/hotspot-to-wpa-lease.capsman.rsc b/hotspot-to-wpa-lease.capsman.rsc deleted file mode 100644 index da86b9d5..00000000 --- a/hotspot-to-wpa-lease.capsman.rsc +++ /dev/null @@ -1,99 +0,0 @@ -#!rsc by RouterOS -# RouterOS script: hotspot-to-wpa-lease.capsman -# Copyright (c) 2019-2026 Christian Hesse -# https://rsc.eworm.de/COPYING.md -# -# provides: dhcpv4-server-lease, order=40 -# requires RouterOS, version=7.21 -# requires device-mode, hotspot -# -# add private WPA passphrase after hotspot login -# https://rsc.eworm.de/doc/hotspot-to-wpa.md -# -# !! Do not edit this file, it is generated from template! - -:local ExitOK false; -:onerror Err { - :global GlobalConfigReady; :global GlobalFunctionsReady; - :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ - do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; - :local ScriptName [ :jobname ]; - - :global EitherOr; - :global LogPrint; - :global ParseKeyValueStore; - :global ScriptLock; - - :if ([ $ScriptLock $ScriptName ] = false) do={ - :set ExitOK true; - :error false; - } - - :if ([ :len [ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ - /caps-man/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; - $LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- hotspot-to-wpa above ---'."); - } - :local PlaceBefore ([ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); - - :foreach Lease in=[ /ip/dhcp-server/lease/find where !dynamic disabled comment~"\\bhotspot-to-wpa\\b" ] do={ - :local LeaseVal [ $ParseKeyValueStore [ /ip/dhcp-server/lease/get $Lease comment ] ]; - /ip/dhcp-server/lease/remove $Lease; - - :if (($LeaseVal->"hotspot-to-wpa") != true) do={ - :continue; - } - - :local MacAddress $"mac-address"; - :local UserName $username; - - :local Date [ /system/clock/get date ]; - :local UserVal ({}); - :if ([ :len [ /ip/hotspot/user/find where name=$UserName ] ] > 0) do={ - :set UserVal [ /ip/hotspot/user/get [ find where name=$UserName ] ]; - } - :local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; - - :if ([ :len [ /caps-man/access-list/find where \ - comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled ] ] = 0) do={ - /caps-man/access-list/add comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled=yes place-before=$PlaceBefore; - $LogPrint warning $ScriptName ("Added template in access-list for hotspot '" . $LeaseVal->"hotspot" . "'."); - } - :local Template [ /caps-man/access-list/get ([ find where \ - comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled ]->0) ]; - - $LogPrint info $ScriptName ("Adding/updating access-list entry for mac address " . $MacAddress . \ - " (user " . $UserName . ")."); - /caps-man/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; - /caps-man/access-list/add private-passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ - mac-address=$MacAddress comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ - action=reject place-before=$PlaceBefore; - - :local Entry [ /caps-man/access-list/find where mac-address=$MacAddress \ - comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; - :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; - :if ([ :len $PrivatePassphrase ] > 0) do={ - :if ($PrivatePassphrase = "ignore") do={ - /caps-man/access-list/set $Entry !private-passphrase; - } else={ - /caps-man/access-list/set $Entry private-passphrase=$PrivatePassphrase; - } - } - :local SsidRegexp [ $EitherOr ($UserInfo->"ssid-regexp") ($Template->"ssid-regexp") ]; - :if ([ :len $SsidRegexp ] > 0) do={ - /caps-man/access-list/set $Entry ssid-regexp=$SsidRegexp; - } - :local VlanId [ $EitherOr ($UserInfo->"vlan-id") ($Template->"vlan-id") ]; - :if ([ :len $VlanId ] > 0) do={ - /caps-man/access-list/set $Entry vlan-id=$VlanId; - } - :local VlanMode [ $EitherOr ($UserInfo->"vlan-mode") ($Template->"vlan-mode") ]; - :if ([ :len $VlanMode] > 0) do={ - /caps-man/access-list/set $Entry vlan-mode=$VlanMode; - } - - :delay 2s; - /caps-man/access-list/set $Entry action=accept; - } -} do={ - :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; -} diff --git a/hotspot-to-wpa-lease.template.rsc b/hotspot-to-wpa-lease.template.rsc deleted file mode 100644 index 4f02a3db..00000000 --- a/hotspot-to-wpa-lease.template.rsc +++ /dev/null @@ -1,119 +0,0 @@ -#!rsc by RouterOS -# RouterOS script: hotspot-to-wpa-lease%TEMPL% -# Copyright (c) 2019-2026 Christian Hesse -# https://rsc.eworm.de/COPYING.md -# -# provides: dhcpv4-server-lease, order=40 -# requires RouterOS, version=7.21 -# requires device-mode, hotspot -# -# add private WPA passphrase after hotspot login -# https://rsc.eworm.de/doc/hotspot-to-wpa.md -# -# !! This is just a template to generate the real script! -# !! Pattern '%TEMPL%' is replaced, paths are filtered. - -:local ExitOK false; -:onerror Err { - :global GlobalConfigReady; :global GlobalFunctionsReady; - :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ - do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; - :local ScriptName [ :jobname ]; - - :global EitherOr; - :global LogPrint; - :global ParseKeyValueStore; - :global ScriptLock; - - :if ([ $ScriptLock $ScriptName ] = false) do={ - :set ExitOK true; - :error false; - } - - :if ([ :len [ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ - :if ([ :len [ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ - /caps-man/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; - /interface/wifi/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; - $LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- hotspot-to-wpa above ---'."); - } - :local PlaceBefore ([ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); - :local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); - - :foreach Lease in=[ /ip/dhcp-server/lease/find where !dynamic disabled comment~"\\bhotspot-to-wpa\\b" ] do={ - :local LeaseVal [ $ParseKeyValueStore [ /ip/dhcp-server/lease/get $Lease comment ] ]; - /ip/dhcp-server/lease/remove $Lease; - - :if (($LeaseVal->"hotspot-to-wpa") != true) do={ - :continue; - } - - :local MacAddress $"mac-address"; - :local UserName $username; - - :local Date [ /system/clock/get date ]; - :local UserVal ({}); - :if ([ :len [ /ip/hotspot/user/find where name=$UserName ] ] > 0) do={ - :set UserVal [ /ip/hotspot/user/get [ find where name=$UserName ] ]; - } - :local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; - - :if ([ :len [ /caps-man/access-list/find where \ - :if ([ :len [ /interface/wifi/access-list/find where \ - comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled ] ] = 0) do={ - /caps-man/access-list/add comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled=yes place-before=$PlaceBefore; - /interface/wifi/access-list/add comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled=yes place-before=$PlaceBefore; - $LogPrint warning $ScriptName ("Added template in access-list for hotspot '" . $LeaseVal->"hotspot" . "'."); - } - :local Template [ /caps-man/access-list/get ([ find where \ - :local Template [ /interface/wifi/access-list/get ([ find where \ - comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled ]->0) ]; - - $LogPrint info $ScriptName ("Adding/updating access-list entry for mac address " . $MacAddress . \ - " (user " . $UserName . ")."); - /caps-man/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; - /interface/wifi/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; - /caps-man/access-list/add private-passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ - /interface/wifi/access-list/add passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ - mac-address=$MacAddress comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ - action=reject place-before=$PlaceBefore; - - :local Entry [ /caps-man/access-list/find where mac-address=$MacAddress \ - :local Entry [ /interface/wifi/access-list/find where mac-address=$MacAddress \ - comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; -# NOT /caps-man/ # - :set ($Template->"private-passphrase") ($Template->"passphrase"); -# NOT /caps-man/ # - :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; - :if ([ :len $PrivatePassphrase ] > 0) do={ - :if ($PrivatePassphrase = "ignore") do={ - /caps-man/access-list/set $Entry !private-passphrase; - /interface/wifi/access-list/set $Entry !passphrase; - } else={ - /caps-man/access-list/set $Entry private-passphrase=$PrivatePassphrase; - /interface/wifi/access-list/set $Entry passphrase=$PrivatePassphrase; - } - } - :local SsidRegexp [ $EitherOr ($UserInfo->"ssid-regexp") ($Template->"ssid-regexp") ]; - :if ([ :len $SsidRegexp ] > 0) do={ - /caps-man/access-list/set $Entry ssid-regexp=$SsidRegexp; - /interface/wifi/access-list/set $Entry ssid-regexp=$SsidRegexp; - } - :local VlanId [ $EitherOr ($UserInfo->"vlan-id") ($Template->"vlan-id") ]; - :if ([ :len $VlanId ] > 0) do={ - /caps-man/access-list/set $Entry vlan-id=$VlanId; - /interface/wifi/access-list/set $Entry vlan-id=$VlanId; - } -# NOT /interface/wifi/ # - :local VlanMode [ $EitherOr ($UserInfo->"vlan-mode") ($Template->"vlan-mode") ]; - :if ([ :len $VlanMode] > 0) do={ - /caps-man/access-list/set $Entry vlan-mode=$VlanMode; - } -# NOT /interface/wifi/ # - - :delay 2s; - /caps-man/access-list/set $Entry action=accept; - /interface/wifi/access-list/set $Entry action=accept; - } -} do={ - :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; -} diff --git a/hotspot-to-wpa-lease.wifi.rsc b/hotspot-to-wpa-lease.wifi.rsc deleted file mode 100644 index 89a33836..00000000 --- a/hotspot-to-wpa-lease.wifi.rsc +++ /dev/null @@ -1,96 +0,0 @@ -#!rsc by RouterOS -# RouterOS script: hotspot-to-wpa-lease.wifi -# Copyright (c) 2019-2026 Christian Hesse -# https://rsc.eworm.de/COPYING.md -# -# provides: dhcpv4-server-lease, order=40 -# requires RouterOS, version=7.21 -# requires device-mode, hotspot -# -# add private WPA passphrase after hotspot login -# https://rsc.eworm.de/doc/hotspot-to-wpa.md -# -# !! Do not edit this file, it is generated from template! - -:local ExitOK false; -:onerror Err { - :global GlobalConfigReady; :global GlobalFunctionsReady; - :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ - do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; - :local ScriptName [ :jobname ]; - - :global EitherOr; - :global LogPrint; - :global ParseKeyValueStore; - :global ScriptLock; - - :if ([ $ScriptLock $ScriptName ] = false) do={ - :set ExitOK true; - :error false; - } - - :if ([ :len [ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ - /interface/wifi/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; - $LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- hotspot-to-wpa above ---'."); - } - :local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); - - :foreach Lease in=[ /ip/dhcp-server/lease/find where !dynamic disabled comment~"\\bhotspot-to-wpa\\b" ] do={ - :local LeaseVal [ $ParseKeyValueStore [ /ip/dhcp-server/lease/get $Lease comment ] ]; - /ip/dhcp-server/lease/remove $Lease; - - :if (($LeaseVal->"hotspot-to-wpa") != true) do={ - :continue; - } - - :local MacAddress $"mac-address"; - :local UserName $username; - - :local Date [ /system/clock/get date ]; - :local UserVal ({}); - :if ([ :len [ /ip/hotspot/user/find where name=$UserName ] ] > 0) do={ - :set UserVal [ /ip/hotspot/user/get [ find where name=$UserName ] ]; - } - :local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; - - :if ([ :len [ /interface/wifi/access-list/find where \ - comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled ] ] = 0) do={ - /interface/wifi/access-list/add comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled=yes place-before=$PlaceBefore; - $LogPrint warning $ScriptName ("Added template in access-list for hotspot '" . $LeaseVal->"hotspot" . "'."); - } - :local Template [ /interface/wifi/access-list/get ([ find where \ - comment=("hotspot-to-wpa template " . $LeaseVal->"hotspot") disabled ]->0) ]; - - $LogPrint info $ScriptName ("Adding/updating access-list entry for mac address " . $MacAddress . \ - " (user " . $UserName . ")."); - /interface/wifi/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; - /interface/wifi/access-list/add passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ - mac-address=$MacAddress comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ - action=reject place-before=$PlaceBefore; - - :local Entry [ /interface/wifi/access-list/find where mac-address=$MacAddress \ - comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; - :set ($Template->"private-passphrase") ($Template->"passphrase"); - :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; - :if ([ :len $PrivatePassphrase ] > 0) do={ - :if ($PrivatePassphrase = "ignore") do={ - /interface/wifi/access-list/set $Entry !passphrase; - } else={ - /interface/wifi/access-list/set $Entry passphrase=$PrivatePassphrase; - } - } - :local SsidRegexp [ $EitherOr ($UserInfo->"ssid-regexp") ($Template->"ssid-regexp") ]; - :if ([ :len $SsidRegexp ] > 0) do={ - /interface/wifi/access-list/set $Entry ssid-regexp=$SsidRegexp; - } - :local VlanId [ $EitherOr ($UserInfo->"vlan-id") ($Template->"vlan-id") ]; - :if ([ :len $VlanId ] > 0) do={ - /interface/wifi/access-list/set $Entry vlan-id=$VlanId; - } - - :delay 2s; - /interface/wifi/access-list/set $Entry action=accept; - } -} do={ - :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; -} diff --git a/hotspot-to-wpa.capsman.rsc b/hotspot-to-wpa.capsman.rsc index 938d0042..f0662706 100644 --- a/hotspot-to-wpa.capsman.rsc +++ b/hotspot-to-wpa.capsman.rsc @@ -5,7 +5,6 @@ # # requires RouterOS, version=7.21 # requires device-mode, hotspot -# requires policy, policy=read;write # # add private WPA passphrase after hotspot login # https://rsc.eworm.de/doc/hotspot-to-wpa.md @@ -14,42 +13,93 @@ :local ExitOK false; :onerror Err { + :global GlobalConfigReady; :global GlobalFunctionsReady; + :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ + do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; :local ScriptName [ :jobname ]; - :local Address $"address"; - :local Interface $"interface"; + :global EitherOr; + :global LogPrint; + :global ParseKeyValueStore; + :global ScriptLock; + :local MacAddress $"mac-address"; - :local UserName $"username"; + :local UserName $username; + :if ([ $ScriptLock $ScriptName ] = false) do={ + :set ExitOK true; + :error false; + } + + :if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={ + $LogPrint error $ScriptName ("This script is supposed to run from hotspot on login."); + :set ExitOK true; + :error false; + } + + :local Date [ /system/clock/get date ]; + :local UserVal ({}); + :if ([ :len [ /ip/hotspot/user/find where name=$UserName ] ] > 0) do={ + :set UserVal [ /ip/hotspot/user/get [ find where name=$UserName ] ]; + } + :local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ]; + + :if ([ :len [ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ + /caps-man/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; + $LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- hotspot-to-wpa above ---'."); + } + :local PlaceBefore ([ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); + :if ([ :len [ /caps-man/access-list/find where \ - comment=("hotspot-to-wpa template " . $Hotspot) disabled action="reject" ] ] > 0) do={ - :log info ($ScriptName . ": Ignoring login for " . $MacAddress . " on hotspot '" . $Hotspot . "'."); + comment=("hotspot-to-wpa template " . $Hotspot) disabled ] ] = 0) do={ + /caps-man/access-list/add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; + $LogPrint warning $ScriptName ("Added template in access-list for hotspot '" . $Hotspot . "'."); + } + :local Template [ /caps-man/access-list/get ([ find where \ + comment=("hotspot-to-wpa template " . $Hotspot) disabled ]->0) ]; + + :if ($Template->"action" = "reject") do={ + $LogPrint info $ScriptName ("Ignoring login for hotspot '" . $Hotspot . "'."); :set ExitOK true; - :error false; + :error true; } - :local Lease [ /ip/dhcp-server/lease/find where mac-address=$MacAddress address=$Address ]; - - :if ([ :len $Lease ] != 1) do={ - :log warning ($ScriptName . ": Did not find exactly one lease for " . $MacAddress . "!"); - :set ExitOK true; - :error false; - } - - :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ]; - - /ip/dhcp-server/lease/set \ - comment=[ :serialize to=json ({ \ - "hotspot-to-wpa"=true; \ - "hotspot"=$Hotspot; \ - "address"=$Address; \ - "interface"=$Interface; \ - "mac-address"=$MacAddress; \ - "username"=$UserName }) ] $Lease; - /ip/dhcp-server/lease/make-static $Lease; + # allow login page to load :delay 1s; - /ip/dhcp-server/lease/disable $Lease; + + $LogPrint info $ScriptName ("Adding/updating access-list entry for mac address " . $MacAddress . \ + " (user " . $UserName . ")."); + /caps-man/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; + /caps-man/access-list/add private-passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ + mac-address=$MacAddress comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ + action=reject place-before=$PlaceBefore; + + :local Entry [ /caps-man/access-list/find where mac-address=$MacAddress \ + comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; + :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; + :if ([ :len $PrivatePassphrase ] > 0) do={ + :if ($PrivatePassphrase = "ignore") do={ + /caps-man/access-list/set $Entry !private-passphrase; + } else={ + /caps-man/access-list/set $Entry private-passphrase=$PrivatePassphrase; + } + } + :local SsidRegexp [ $EitherOr ($UserInfo->"ssid-regexp") ($Template->"ssid-regexp") ]; + :if ([ :len $SsidRegexp ] > 0) do={ + /caps-man/access-list/set $Entry ssid-regexp=$SsidRegexp; + } + :local VlanId [ $EitherOr ($UserInfo->"vlan-id") ($Template->"vlan-id") ]; + :if ([ :len $VlanId ] > 0) do={ + /caps-man/access-list/set $Entry vlan-id=$VlanId; + } + :local VlanMode [ $EitherOr ($UserInfo->"vlan-mode") ($Template->"vlan-mode") ]; + :if ([ :len $VlanMode] > 0) do={ + /caps-man/access-list/set $Entry vlan-mode=$VlanMode; + } + + :delay 2s; + /caps-man/access-list/set $Entry action=accept; } do={ - :if ($ExitOK = false) do={ :log error ([ :jobname ] . ": " . $Err); } + :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; } diff --git a/hotspot-to-wpa.template.rsc b/hotspot-to-wpa.template.rsc index 84bb4181..03905bd9 100644 --- a/hotspot-to-wpa.template.rsc +++ b/hotspot-to-wpa.template.rsc @@ -5,7 +5,6 @@ # # requires RouterOS, version=7.21 # requires device-mode, hotspot -# requires policy, policy=read;write # # add private WPA passphrase after hotspot login # https://rsc.eworm.de/doc/hotspot-to-wpa.md @@ -15,43 +14,112 @@ :local ExitOK false; :onerror Err { + :global GlobalConfigReady; :global GlobalFunctionsReady; + :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ + do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; :local ScriptName [ :jobname ]; - :local Address $"address"; - :local Interface $"interface"; - :local MacAddress $"mac-address"; - :local UserName $"username"; + :global EitherOr; + :global LogPrint; + :global ParseKeyValueStore; + :global ScriptLock; + :local MacAddress $"mac-address"; + :local UserName $username; + + :if ([ $ScriptLock $ScriptName ] = false) do={ + :set ExitOK true; + :error false; + } + + :if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={ + $LogPrint error $ScriptName ("This script is supposed to run from hotspot on login."); + :set ExitOK true; + :error false; + } + + :local Date [ /system/clock/get date ]; + :local UserVal ({}); + :if ([ :len [ /ip/hotspot/user/find where name=$UserName ] ] > 0) do={ + :set UserVal [ /ip/hotspot/user/get [ find where name=$UserName ] ]; + } + :local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ]; + + :if ([ :len [ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ + :if ([ :len [ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ + /caps-man/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; + /interface/wifi/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; + $LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- hotspot-to-wpa above ---'."); + } + :local PlaceBefore ([ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); + :local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); + :if ([ :len [ /caps-man/access-list/find where \ :if ([ :len [ /interface/wifi/access-list/find where \ - comment=("hotspot-to-wpa template " . $Hotspot) disabled action="reject" ] ] > 0) do={ - :log info ($ScriptName . ": Ignoring login for " . $MacAddress . " on hotspot '" . $Hotspot . "'."); + comment=("hotspot-to-wpa template " . $Hotspot) disabled ] ] = 0) do={ + /caps-man/access-list/add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; + /interface/wifi/access-list/add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; + $LogPrint warning $ScriptName ("Added template in access-list for hotspot '" . $Hotspot . "'."); + } + :local Template [ /caps-man/access-list/get ([ find where \ + :local Template [ /interface/wifi/access-list/get ([ find where \ + comment=("hotspot-to-wpa template " . $Hotspot) disabled ]->0) ]; + + :if ($Template->"action" = "reject") do={ + $LogPrint info $ScriptName ("Ignoring login for hotspot '" . $Hotspot . "'."); :set ExitOK true; - :error false; + :error true; } - :local Lease [ /ip/dhcp-server/lease/find where mac-address=$MacAddress address=$Address ]; - - :if ([ :len $Lease ] != 1) do={ - :log warning ($ScriptName . ": Did not find exactly one lease for " . $MacAddress . "!"); - :set ExitOK true; - :error false; - } - - :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ]; - - /ip/dhcp-server/lease/set \ - comment=[ :serialize to=json ({ \ - "hotspot-to-wpa"=true; \ - "hotspot"=$Hotspot; \ - "address"=$Address; \ - "interface"=$Interface; \ - "mac-address"=$MacAddress; \ - "username"=$UserName }) ] $Lease; - /ip/dhcp-server/lease/make-static $Lease; + # allow login page to load :delay 1s; - /ip/dhcp-server/lease/disable $Lease; + + $LogPrint info $ScriptName ("Adding/updating access-list entry for mac address " . $MacAddress . \ + " (user " . $UserName . ")."); + /caps-man/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; + /interface/wifi/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; + /caps-man/access-list/add private-passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ + /interface/wifi/access-list/add passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ + mac-address=$MacAddress comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ + action=reject place-before=$PlaceBefore; + + :local Entry [ /caps-man/access-list/find where mac-address=$MacAddress \ + :local Entry [ /interface/wifi/access-list/find where mac-address=$MacAddress \ + comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; +# NOT /caps-man/ # + :set ($Template->"private-passphrase") ($Template->"passphrase"); +# NOT /caps-man/ # + :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; + :if ([ :len $PrivatePassphrase ] > 0) do={ + :if ($PrivatePassphrase = "ignore") do={ + /caps-man/access-list/set $Entry !private-passphrase; + /interface/wifi/access-list/set $Entry !passphrase; + } else={ + /caps-man/access-list/set $Entry private-passphrase=$PrivatePassphrase; + /interface/wifi/access-list/set $Entry passphrase=$PrivatePassphrase; + } + } + :local SsidRegexp [ $EitherOr ($UserInfo->"ssid-regexp") ($Template->"ssid-regexp") ]; + :if ([ :len $SsidRegexp ] > 0) do={ + /caps-man/access-list/set $Entry ssid-regexp=$SsidRegexp; + /interface/wifi/access-list/set $Entry ssid-regexp=$SsidRegexp; + } + :local VlanId [ $EitherOr ($UserInfo->"vlan-id") ($Template->"vlan-id") ]; + :if ([ :len $VlanId ] > 0) do={ + /caps-man/access-list/set $Entry vlan-id=$VlanId; + /interface/wifi/access-list/set $Entry vlan-id=$VlanId; + } +# NOT /interface/wifi/ # + :local VlanMode [ $EitherOr ($UserInfo->"vlan-mode") ($Template->"vlan-mode") ]; + :if ([ :len $VlanMode] > 0) do={ + /caps-man/access-list/set $Entry vlan-mode=$VlanMode; + } +# NOT /interface/wifi/ # + + :delay 2s; + /caps-man/access-list/set $Entry action=accept; + /interface/wifi/access-list/set $Entry action=accept; } do={ - :if ($ExitOK = false) do={ :log error ([ :jobname ] . ": " . $Err); } + :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; } diff --git a/hotspot-to-wpa.wifi.rsc b/hotspot-to-wpa.wifi.rsc index db6a44b2..09c8923a 100644 --- a/hotspot-to-wpa.wifi.rsc +++ b/hotspot-to-wpa.wifi.rsc @@ -5,7 +5,6 @@ # # requires RouterOS, version=7.21 # requires device-mode, hotspot -# requires policy, policy=read;write # # add private WPA passphrase after hotspot login # https://rsc.eworm.de/doc/hotspot-to-wpa.md @@ -14,42 +13,90 @@ :local ExitOK false; :onerror Err { + :global GlobalConfigReady; :global GlobalFunctionsReady; + :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ + do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; :local ScriptName [ :jobname ]; - :local Address $"address"; - :local Interface $"interface"; + :global EitherOr; + :global LogPrint; + :global ParseKeyValueStore; + :global ScriptLock; + :local MacAddress $"mac-address"; - :local UserName $"username"; + :local UserName $username; + :if ([ $ScriptLock $ScriptName ] = false) do={ + :set ExitOK true; + :error false; + } + + :if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={ + $LogPrint error $ScriptName ("This script is supposed to run from hotspot on login."); + :set ExitOK true; + :error false; + } + + :local Date [ /system/clock/get date ]; + :local UserVal ({}); + :if ([ :len [ /ip/hotspot/user/find where name=$UserName ] ] > 0) do={ + :set UserVal [ /ip/hotspot/user/get [ find where name=$UserName ] ]; + } + :local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ]; + + :if ([ :len [ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ + /interface/wifi/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; + $LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- hotspot-to-wpa above ---'."); + } + :local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ]->0); + :if ([ :len [ /interface/wifi/access-list/find where \ - comment=("hotspot-to-wpa template " . $Hotspot) disabled action="reject" ] ] > 0) do={ - :log info ($ScriptName . ": Ignoring login for " . $MacAddress . " on hotspot '" . $Hotspot . "'."); + comment=("hotspot-to-wpa template " . $Hotspot) disabled ] ] = 0) do={ + /interface/wifi/access-list/add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; + $LogPrint warning $ScriptName ("Added template in access-list for hotspot '" . $Hotspot . "'."); + } + :local Template [ /interface/wifi/access-list/get ([ find where \ + comment=("hotspot-to-wpa template " . $Hotspot) disabled ]->0) ]; + + :if ($Template->"action" = "reject") do={ + $LogPrint info $ScriptName ("Ignoring login for hotspot '" . $Hotspot . "'."); :set ExitOK true; - :error false; + :error true; } - :local Lease [ /ip/dhcp-server/lease/find where mac-address=$MacAddress address=$Address ]; - - :if ([ :len $Lease ] != 1) do={ - :log warning ($ScriptName . ": Did not find exactly one lease for " . $MacAddress . "!"); - :set ExitOK true; - :error false; - } - - :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ]; - - /ip/dhcp-server/lease/set \ - comment=[ :serialize to=json ({ \ - "hotspot-to-wpa"=true; \ - "hotspot"=$Hotspot; \ - "address"=$Address; \ - "interface"=$Interface; \ - "mac-address"=$MacAddress; \ - "username"=$UserName }) ] $Lease; - /ip/dhcp-server/lease/make-static $Lease; + # allow login page to load :delay 1s; - /ip/dhcp-server/lease/disable $Lease; + + $LogPrint info $ScriptName ("Adding/updating access-list entry for mac address " . $MacAddress . \ + " (user " . $UserName . ")."); + /interface/wifi/access-list/remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; + /interface/wifi/access-list/add passphrase=($UserVal->"password") ssid-regexp="-wpa\$" \ + mac-address=$MacAddress comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ + action=reject place-before=$PlaceBefore; + + :local Entry [ /interface/wifi/access-list/find where mac-address=$MacAddress \ + comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; + :set ($Template->"private-passphrase") ($Template->"passphrase"); + :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; + :if ([ :len $PrivatePassphrase ] > 0) do={ + :if ($PrivatePassphrase = "ignore") do={ + /interface/wifi/access-list/set $Entry !passphrase; + } else={ + /interface/wifi/access-list/set $Entry passphrase=$PrivatePassphrase; + } + } + :local SsidRegexp [ $EitherOr ($UserInfo->"ssid-regexp") ($Template->"ssid-regexp") ]; + :if ([ :len $SsidRegexp ] > 0) do={ + /interface/wifi/access-list/set $Entry ssid-regexp=$SsidRegexp; + } + :local VlanId [ $EitherOr ($UserInfo->"vlan-id") ($Template->"vlan-id") ]; + :if ([ :len $VlanId ] > 0) do={ + /interface/wifi/access-list/set $Entry vlan-id=$VlanId; + } + + :delay 2s; + /interface/wifi/access-list/set $Entry action=accept; } do={ - :if ($ExitOK = false) do={ :log error ([ :jobname ] . ": " . $Err); } + :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; } diff --git a/news-and-changes.rsc b/news-and-changes.rsc index 87195292..1b3adb26 100644 --- a/news-and-changes.rsc +++ b/news-and-changes.rsc @@ -69,7 +69,6 @@ 142="Added a setting for 'mod/notification-email' to check availability of certificate chain."; 143="Made backup scripts 'backup-email' and 'backup-upload' support date & time in filenames."; 144="Split and reworked 'mode-button' for compatibility with RouterOS 7.24, configuration was updated automatically."; - 145="Split and reworked 'hotspot-to-wpa' for compatibility with RouterOS 7.24, configuration was updated automatically."; }; # Migration steps to be applied on script updates @@ -82,5 +81,4 @@ 138="/certificate/set trusted=yes [ find where trusted=yes ];"; 140=":if ([ :len [ /system/script/find where name=\"lease-script\" ] ] > 0) do={ /system/script/set name=\"dhcpv4-server-lease\" \"lease-script\"; :global ScriptInstallUpdate; \$ScriptInstallUpdate; /ip/dhcp-server/set lease-script=\"dhcpv4-server-lease\" [ find where lease-script=\"lease-script\" ]; };"; 144=":if ([ :len [ /system/script/find where name=\"mode-button\" ] ] > 0) do={ :global ScriptInstallUpdate; \$ScriptInstallUpdate mode-button-scheduler; };"; - 145=":local Script [ /system/script/find where name~\"^hotspot-to-wpa\\\\.\" ]; :if ([ :len \$Script ] > 0) do={ :local Type ([ :toarray delimiter=\".\" [ /system/script/get \$Script name ] ]->1); :global ScriptInstallUpdate; \$ScriptInstallUpdate (\"dhcpv4-server-lease,hotspot-to-wpa-lease.\" . \$Type); :foreach Hotspot in=[ /ip/hotspot/find ] do={ /ip/dhcp-server/set lease-script=\"dhcpv4-server-lease\" [ find where interface=[ /ip/hotspot/get \$Hotspot interface ] ]; }; };"; };