hotspot-to-wpa: rework for RouterOS 7.24 compatibility

This commit is contained in:
Christian Hesse 2026-07-23 12:47:15 +02:00
parent 4663ee6d6d
commit f0303997c0
10 changed files with 398 additions and 253 deletions

View file

@ -288,7 +288,7 @@ Available scripts
* [Download, import and update firewall address-lists](doc/fw-addr-lists.md) (`fw-addr-lists`) * [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`) * [Wait for global functions und modules](doc/global-wait.md) (`global-wait`)
* [Send GPS position to server](doc/gps-track.md) (`gps-track`) * [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-cleanup`) * [Use WPA network with hotspot credentials](doc/hotspot-to-wpa.md) (`hotspot-to-wpa`, `hotspot-to-wpa-lease` & `hotspot-to-wpa-cleanup`)
* [Create DNS records for IPSec peers](doc/ipsec-to-dns.md) (`ipsec-to-dns`) * [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`) * [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`) * [Manage IP addresses with bridge status](doc/ip-addr-bridge.md) (`ip-addr-bridge`)

View file

@ -26,35 +26,38 @@ Requirements and installation
You need a properly configured hotspot on one (open) SSID and a WPA enabled You need a properly configured hotspot on one (open) SSID and a WPA enabled
SSID with suffix "`-wpa`". SSID with suffix "`-wpa`".
Then install the script. Then install the scripts. Depending on whether you use `wifi` package
Depending on whether you use `wifi` package (`/interface/wifi`)or legacy (`/interface/wifi`) or legacy wireless with CAPsMAN (`/caps-man`) you need
wifi with CAPsMAN (`/caps-man`) you need to install a different script and to install a different set of scripts. Then set the `on-login` script in hotspot.
set it as `on-login` script in hotspot.
For `wifi`: For `wifi`:
$ScriptInstallUpdate hotspot-to-wpa.wifi; $ScriptInstallUpdate hotspot-to-wpa.wifi,hotspot-to-wpa-lease.wifi,dhcpv4-server-lease;
/ip/hotspot/user/profile/set on-login="hotspot-to-wpa.wifi" [ find ]; /ip/hotspot/user/profile/set on-login="hotspot-to-wpa.wifi" [ find ];
For legacy CAPsMAN: For legacy CAPsMAN:
$ScriptInstallUpdate hotspot-to-wpa.capsman; $ScriptInstallUpdate hotspot-to-wpa.wifi,hotspot-to-wpa-lease.capsman,dhcpv4-server-lease;
/ip/hotspot/user/profile/set on-login="hotspot-to-wpa.capsman" [ find ]; /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 ### Automatic cleanup
With just `hotspot-to-wpa` installed the mac addresses will last in the With just the above scripts installed the mac addresses will last in the
access list forever. Install the optional script for automatic cleanup access list forever. Install the optional script for automatic cleanup
and add a scheduler. and add a scheduler.
For `wifi`: For `wifi`:
$ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi,dhcpv4-server-lease; $ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi;
/system/scheduler/add interval=1d name="hotspot-to-wpa-cleanup" on-event="/system/script/run hotspot-to-wpa-cleanup.wifi;" start-time=startup; /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: For legacy CAPsMAN:
$ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman,dhcpv4-server-lease; $ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman;
/system/scheduler/add interval=1d name="hotspot-to-wpa-cleanup" on-event="/system/script/run hotspot-to-wpa-cleanup.capsman;" start-time=startup; /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 And add the lease script and matcher comment to your wpa interfaces' dhcp

View file

@ -15,7 +15,7 @@
# Git commit id & info, expected configuration version # Git commit id & info, expected configuration version
:global CommitId "unknown"; :global CommitId "unknown";
:global CommitInfo "unknown"; :global CommitInfo "unknown";
:global ExpectedConfigVersion 144; :global ExpectedConfigVersion 145;
# global variables not to be changed by user # global variables not to be changed by user
:global GlobalFunctionsReady false; :global GlobalFunctionsReady false;

View file

@ -0,0 +1,98 @@
#!rsc by RouterOS
# RouterOS script: hotspot-to-wpa-lease.capsman
# Copyright (c) 2019-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# provides: dhcpv4-server-lease, order=40
# requires RouterOS, version=7.22
# 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!
: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={
:exit;
}
: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") ];
: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 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) ];
$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 ExitOnError; $ExitOnError [ :jobname ] $Err;
}

View file

@ -0,0 +1,118 @@
#!rsc by RouterOS
# RouterOS script: hotspot-to-wpa-lease%TEMPL%
# Copyright (c) 2019-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# provides: dhcpv4-server-lease, order=40
# requires RouterOS, version=7.22
# 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.
: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={
:exit;
}
: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") ];
:local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ];
:if ([ :len [ /caps-man/access-list/find where \
:if ([ :len [ /interface/wifi/access-list/find where \
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) ];
$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 ExitOnError; $ExitOnError [ :jobname ] $Err;
}

View file

@ -0,0 +1,95 @@
#!rsc by RouterOS
# RouterOS script: hotspot-to-wpa-lease.wifi
# Copyright (c) 2019-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# provides: dhcpv4-server-lease, order=40
# requires RouterOS, version=7.22
# 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!
: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={
:exit;
}
: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") ];
: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 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) ];
$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 ExitOnError; $ExitOnError [ :jobname ] $Err;
}

View file

@ -5,6 +5,7 @@
# #
# requires RouterOS, version=7.22 # requires RouterOS, version=7.22
# requires device-mode, hotspot # requires device-mode, hotspot
# requires policy, policy=read;write
# #
# add private WPA passphrase after hotspot login # add private WPA passphrase after hotspot login
# https://rsc.eworm.de/doc/hotspot-to-wpa.md # https://rsc.eworm.de/doc/hotspot-to-wpa.md
@ -12,90 +13,37 @@
# !! Do not edit this file, it is generated from template! # !! Do not edit this file, it is generated from template!
:onerror Err { :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 ScriptName [ :jobname ];
:global EitherOr; :local Address $"address";
:global LogPrint; :local Interface $"interface";
:global ParseKeyValueStore;
:global ScriptLock;
:local MacAddress $"mac-address"; :local MacAddress $"mac-address";
:local UserName $username; :local UserName $"username";
:if ([ $ScriptLock $ScriptName ] = false) do={
:exit;
}
:if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from hotspot on login.");
:exit;
}
: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 ]; :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ];
:if ([ /caps-man/access-list/find where \
:if ([ :len [ /caps-man/access-list/find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ comment=("hotspot-to-wpa template " . $Hotspot) disabled action="reject" ] ] > 0) do={
/caps-man/access-list/add comment="--- hotspot-to-wpa above ---" disabled=yes; :log info ($ScriptName . ": Ignoring login for " . $MacAddress . " on hotspot '" . $Hotspot . "'.");
$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 ] ] = 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 . "'.");
:exit; :exit;
} }
# allow login page to load :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 . "!");
:exit;
}
/ip/dhcp-server/lease/set \
comment=[ :serialize to=json ({ \
"hotspot-to-wpa"=true; \
"address"=$Address; \
"interface"=$Interface; \
"mac-address"=$MacAddress; \
"username"=$UserName }) ] $Lease;
/ip/dhcp-server/lease/make-static $Lease;
:delay 1s; :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={ } do={
:global ExitOnError; $ExitOnError [ :jobname ] $Err; :log error ([ :jobname ] . ": " . $Err);
} }

View file

@ -5,6 +5,7 @@
# #
# requires RouterOS, version=7.22 # requires RouterOS, version=7.22
# requires device-mode, hotspot # requires device-mode, hotspot
# requires policy, policy=read;write
# #
# add private WPA passphrase after hotspot login # add private WPA passphrase after hotspot login
# https://rsc.eworm.de/doc/hotspot-to-wpa.md # https://rsc.eworm.de/doc/hotspot-to-wpa.md
@ -13,109 +14,38 @@
# !! Pattern '%TEMPL%' is replaced, paths are filtered. # !! Pattern '%TEMPL%' is replaced, paths are filtered.
:onerror Err { :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 ScriptName [ :jobname ];
:global EitherOr; :local Address $"address";
:global LogPrint; :local Interface $"interface";
:global ParseKeyValueStore;
:global ScriptLock;
:local MacAddress $"mac-address"; :local MacAddress $"mac-address";
:local UserName $username; :local UserName $"username";
:if ([ $ScriptLock $ScriptName ] = false) do={
:exit;
}
:if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from hotspot on login.");
:exit;
}
: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 ]; :local Hotspot [ /ip/hotspot/host/get [ find where mac-address=$MacAddress authorized ] server ];
:if ([ /caps-man/access-list/find where \
: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 \ :if ([ :len [ /interface/wifi/access-list/find where \
comment=("hotspot-to-wpa template " . $Hotspot) disabled ] ] = 0) do={ comment=("hotspot-to-wpa template " . $Hotspot) disabled action="reject" ] ] > 0) do={
/caps-man/access-list/add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; :log info ($ScriptName . ": Ignoring login for " . $MacAddress . " on hotspot '" . $Hotspot . "'.");
/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 . "'.");
:exit; :exit;
} }
# allow login page to load :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 . "!");
:exit;
}
/ip/dhcp-server/lease/set \
comment=[ :serialize to=json ({ \
"hotspot-to-wpa"=true; \
"address"=$Address; \
"interface"=$Interface; \
"mac-address"=$MacAddress; \
"username"=$UserName }) ] $Lease;
/ip/dhcp-server/lease/make-static $Lease;
:delay 1s; :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={ } do={
:global ExitOnError; $ExitOnError [ :jobname ] $Err; :log error ([ :jobname ] . ": " . $Err);
} }

View file

@ -5,6 +5,7 @@
# #
# requires RouterOS, version=7.22 # requires RouterOS, version=7.22
# requires device-mode, hotspot # requires device-mode, hotspot
# requires policy, policy=read;write
# #
# add private WPA passphrase after hotspot login # add private WPA passphrase after hotspot login
# https://rsc.eworm.de/doc/hotspot-to-wpa.md # https://rsc.eworm.de/doc/hotspot-to-wpa.md
@ -12,87 +13,37 @@
# !! Do not edit this file, it is generated from template! # !! Do not edit this file, it is generated from template!
:onerror Err { :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 ScriptName [ :jobname ];
:global EitherOr; :local Address $"address";
:global LogPrint; :local Interface $"interface";
:global ParseKeyValueStore;
:global ScriptLock;
:local MacAddress $"mac-address"; :local MacAddress $"mac-address";
:local UserName $username; :local UserName $"username";
:if ([ $ScriptLock $ScriptName ] = false) do={
:exit;
}
:if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from hotspot on login.");
:exit;
}
: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 ]; :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 \ :if ([ :len [ /interface/wifi/access-list/find where \
comment=("hotspot-to-wpa template " . $Hotspot) disabled ] ] = 0) do={ comment=("hotspot-to-wpa template " . $Hotspot) disabled action="reject" ] ] > 0) do={
/interface/wifi/access-list/add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; :log info ($ScriptName . ": Ignoring login for " . $MacAddress . " on hotspot '" . $Hotspot . "'.");
$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 . "'.");
:exit; :exit;
} }
# allow login page to load :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 . "!");
:exit;
}
/ip/dhcp-server/lease/set \
comment=[ :serialize to=json ({ \
"hotspot-to-wpa"=true; \
"address"=$Address; \
"interface"=$Interface; \
"mac-address"=$MacAddress; \
"username"=$UserName }) ] $Lease;
/ip/dhcp-server/lease/make-static $Lease;
:delay 1s; :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={ } do={
:global ExitOnError; $ExitOnError [ :jobname ] $Err; :log error ([ :jobname ] . ": " . $Err);
} }

View file

@ -69,6 +69,7 @@
142="Added a setting for 'mod/notification-email' to check availability of certificate chain."; 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."; 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."; 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 # Migration steps to be applied on script updates
@ -81,4 +82,5 @@
138="/certificate/set trusted=yes [ find where trusted=yes ];"; 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\" ]; };"; 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; };"; 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~\"^hostspot-to-wap\\\\.\" ]; :if ([ :len \$Script ] > 0) do={ :local Type ([ :toarray delimiter=\".\" [ /system/script/get name \$Script ] ]->1); :global ScriptInstallUpdate; \$ScriptInstallUpdate (\"dhcpv4-server-lease,hostspot-to-wap-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 ] ]; }; };";
}; };