OPNsense Captive Portal mit vordefinierten Voucher
Hallo,
Ziel war es vorhandene Klienten-Daten (Nummer im System) und Kennwörter anzulegen. Voucher werden durch externes Programm in Papierform erstellt, weswegen die Daten schon vorher vorliegen.
Für die API sind hier nur 2x Dateinen zu modifzieren - ACHTUNG diese werden auch von anderen Funktionen genutzt. Fehler in der Datei könne zu Folgefehlern führen:
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/voucher.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/CaptivePortal/Api/VoucherController.php
Vorab: es ist nicht gerade eine beständige Lösung. Ein OPNsense Update kann dazu führen, dass diese 2x Dateien wieder überschrieben werden. Positiv wäre zu erwähnen, dass sich hier in den letzten Monaten aber kaum was geändert hat und man teils einfach die angepassten Dateien wieder drüber kopieren kann.
Es gilt: Einfaches Datei-Compare Tool vorher drüber laufen lassen. Ggf. OPNsense in virtueller Maschine laufen lassen und Update dort vorher einmal testen. Vom Aufwand her ist es überschaubar.
Habe einmal die kompletten Blöcke kopiert, damit es einfach ist die Stelle zu finden. Im Prinzip wurden neue 2x neue Variablen eingegfügt, die Name und Kennwort via API aufnehmen. Im 2. Schritt wurde entsprechend die Vouchererstellung so werweitert, dass bei Übergabe des $usernamedef kein generiertes Name und Kennwort übernommen wird, sondern das via API übergebende.
Voraussetzung ist, dass ein gültiger API-Key vorliegt. Informationen und Beispiel findet ihr hier: https://docs.opnsense.org/development/how-tos/api.html
ACHTUNG: Windows Beipspiel! Darum wurden " mit \ escaped. Statt CURL kann man jede andere Form von Requets nehmen - Sprachen abhängig. CURL kann jeder aber einfach auch Windows nutzen. Darum beschränkt sich mein Beipspiel hier drauf. Ob ihr C#, C++, Perl etc. nehmt ist egal.
Kurz zur Erläuterung:
count: ist die Anzahl. Normal wird über die GUI hier mitgeteilt, wieviele Vouchers die CSV beinhalten soll
validity: Gültigkeit in Sekunden. Hier kann beliebig arbeiten. 4 Std,. 4 Tage oder 4 Wochen.
usernamedef: Der vorher festgelegte Name
passworddef: Das zuvor vergebene Kennwort.
vouchergroup: Der frei defnierbare Gruppename! ACHTUNG. Wen Tickets auch später über API gesperrt werden sollen, hier am besten eine Grupee für alle nehmen. Der Gruppename muss später teils mit angegeben werden.
Zur URL:
VoucherSrv: Ist der Voucher Server Name. Die OPNsense kann mehrere verwalten. Achtet immer auf den richtigen. Sonst geht der Request ins leere.
Wenn der Befehl erfolgreich war, bekommt ihr folgende Meldung:
Warum kein "OK". Das liegt daran, dass im orinmal mehrere Vouchers ausgeben werden. Die Antwort kommt im JSON Format zurück. Kann aber auch so einfach validiert werden. In dem man JSON liest und die Werte vergleicht.
Da sinder Phantasie keine Grenzen gesezt.
ACHTUNG: Fehlerhafter Code hat Auswirkungen auf das gesamte System! Die Voucher.php wird NICHT NUR vom Captive Portal benutzt.
/usr/local/opnsense/mvc/app/controllers/OPNsense/CaptivePortal/Api/VoucherController.php
Original:
Mod:
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/voucher.php
Org:
Ziel war es vorhandene Klienten-Daten (Nummer im System) und Kennwörter anzulegen. Voucher werden durch externes Programm in Papierform erstellt, weswegen die Daten schon vorher vorliegen.
Für die API sind hier nur 2x Dateinen zu modifzieren - ACHTUNG diese werden auch von anderen Funktionen genutzt. Fehler in der Datei könne zu Folgefehlern führen:
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/voucher.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/CaptivePortal/Api/VoucherController.php
Vorab: es ist nicht gerade eine beständige Lösung. Ein OPNsense Update kann dazu führen, dass diese 2x Dateien wieder überschrieben werden. Positiv wäre zu erwähnen, dass sich hier in den letzten Monaten aber kaum was geändert hat und man teils einfach die angepassten Dateien wieder drüber kopieren kann.
Es gilt: Einfaches Datei-Compare Tool vorher drüber laufen lassen. Ggf. OPNsense in virtueller Maschine laufen lassen und Update dort vorher einmal testen. Vom Aufwand her ist es überschaubar.
Habe einmal die kompletten Blöcke kopiert, damit es einfach ist die Stelle zu finden. Im Prinzip wurden neue 2x neue Variablen eingegfügt, die Name und Kennwort via API aufnehmen. Im 2. Schritt wurde entsprechend die Vouchererstellung so werweitert, dass bei Übergabe des $usernamedef kein generiertes Name und Kennwort übernommen wird, sondern das via API übergebende.
Voraussetzung ist, dass ein gültiger API-Key vorliegt. Informationen und Beispiel findet ihr hier: https://docs.opnsense.org/development/how-tos/api.html
curl -XPOST -d "{\"count\":\"1\",\"validity\":\"14400\",\"usernamedef\":\"jondooNEU\",\"passworddef\":\"geheim\",\"vouchergroup\":\"test\"}" -H "Content-Type: application/json" -k -u "MOzGhDB6jRKvmcSqt5YFeFFvFUVFpayYhcdNV+4pefV6hrv3jJmeQmvnf1V+Qysq4rFuVKRvMMGXCzOX":"v5LO4UyEdVRa+BVjOzjEyKQDREx9WcYg9kQUsrPNiZMA6Fz4jrdOPdacBPAnT5IBZTcKkaXxLK9O3tub" http://192.168.0.1/api/captiveportal/voucher/generateVouchers/VoucherSrv/
ACHTUNG: Windows Beipspiel! Darum wurden " mit \ escaped. Statt CURL kann man jede andere Form von Requets nehmen - Sprachen abhängig. CURL kann jeder aber einfach auch Windows nutzen. Darum beschränkt sich mein Beipspiel hier drauf. Ob ihr C#, C++, Perl etc. nehmt ist egal.
Kurz zur Erläuterung:
count: ist die Anzahl. Normal wird über die GUI hier mitgeteilt, wieviele Vouchers die CSV beinhalten soll
validity: Gültigkeit in Sekunden. Hier kann beliebig arbeiten. 4 Std,. 4 Tage oder 4 Wochen.
usernamedef: Der vorher festgelegte Name
passworddef: Das zuvor vergebene Kennwort.
vouchergroup: Der frei defnierbare Gruppename! ACHTUNG. Wen Tickets auch später über API gesperrt werden sollen, hier am besten eine Grupee für alle nehmen. Der Gruppename muss später teils mit angegeben werden.
Zur URL:
VoucherSrv: Ist der Voucher Server Name. Die OPNsense kann mehrere verwalten. Achtet immer auf den richtigen. Sonst geht der Request ins leere.
Wenn der Befehl erfolgreich war, bekommt ihr folgende Meldung:
[{"username":"test","password":"4vFkfV","vouchergroup":"WLAN01","validity":"3628800","expirytime":"0","starttime":null}]
Warum kein "OK". Das liegt daran, dass im orinmal mehrere Vouchers ausgeben werden. Die Antwort kommt im JSON Format zurück. Kann aber auch so einfach validiert werden. In dem man JSON liest und die Werte vergleicht.
Da sinder Phantasie keine Grenzen gesezt.
ACHTUNG: Fehlerhafter Code hat Auswirkungen auf das gesamte System! Die Voucher.php wird NICHT NUR vom Captive Portal benutzt.
/usr/local/opnsense/mvc/app/controllers/OPNsense/CaptivePortal/Api/VoucherController.php
Original:
/**
* generate new vouchers
* @param string $provider auth provider
* @return array generated vouchers
*/
public function generateVouchersAction($provider)
{
$response = array("status" => "error");
if ($this->request->isPost()) {
$authFactory = new AuthenticationFactory();
$auth = $authFactory->get(urldecode($provider));
if ($auth != null && method_exists($auth, 'generateVouchers')) {
$count = $this->request->getPost('count', 'int', 0);
$validity = $this->request->getPost('validity', 'int', 0);
$expirytime = $this->request->getPost('expirytime', 'int', 0);
$vouchergroup = $this->request->getPost('vouchergroup', 'striptags', '---');
// remove characters which are known to provide issues when using in the url
foreach (array("&", "#") as $skip_chars) {
$vouchergroup = str_replace($skip_chars, "", $vouchergroup);
}
if ($count > 0 && $count <= 10000 && $validity > 0) {
return $auth->generateVouchers($vouchergroup, $count, $validity, $expirytime);
}
}
}
return $response;
}
Mod:
/**
* generate new vouchers
* @param string $provider auth provider
* @return array generated vouchers
*/
public function generateVouchersAction($provider)
{
$response = array("status" => "error");
if ($this->request->isPost()) {
$authFactory = new AuthenticationFactory();
$auth = $authFactory->get(urldecode($provider));
if ($auth != null && method_exists($auth, 'generateVouchers')) {
$count = $this->request->getPost('count', 'int', 0);
$validity = $this->request->getPost('validity', 'int', 0);
$expirytime = $this->request->getPost('expirytime', 'int', 0);
$vouchergroup = $this->request->getPost('vouchergroup', 'striptags', '---');
$usernamedef = $this->request->getPost('usernamedef', 'striptags', '---');
$passworddef = $this->request->getPost('passworddef', 'striptags', '---');
// remove characters which are known to provide issues when using in the url
foreach (array("&", "#") as $skip_chars) {
$vouchergroup = str_replace($skip_chars, "", $vouchergroup);
}
if ($count > 0 && $count <= 10000 && $validity > 0) {
return $auth->generateVouchers($vouchergroup, $count, $validity, $usernamedef, $passworddef, $expirytime);
}
}
}
return $response;
}
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/voucher.php
Org:
/**
* generate new vouchers and store in voucher database
* @param string $vouchergroup voucher groupname
* @param int $count number of vouchers to generate
* @param int $validity time (in seconds)
* @param int $starttime valid from
* @param int $expirytime valid until ('0' means no expiry time)
* @return array list of generated vouchers
*/
public function generateVouchers($vouchergroup, $count, $validity, $expirytime, $starttime = null)
{
$response = array();
if ($this->dbHandle != null) {
if ($this->simplePasswords) {
// create a map of easy to read characters
$characterMap = '';
while (strlen($characterMap) < 256) {
$random_bytes = openssl_random_pseudo_bytes(10000);
for ($i = 0; $i < strlen($random_bytes); $i++) {
$chr_ord = ord($random_bytes[$i]);
if (($chr_ord >= 50 && $chr_ord <= 57) || // 2..9
($chr_ord >= 65 && $chr_ord <= 72) || // A..H
($chr_ord >= 74 && $chr_ord <= 78) || // J..N
($chr_ord >= 80 && $chr_ord <= 90) || // P..Z
($chr_ord >= 97 && $chr_ord <= 107) || // a..k
($chr_ord >= 109 && $chr_ord <= 110) || // m..n
($chr_ord >= 112 && $chr_ord <= 122) // p..z
) {
$characterMap .= $random_bytes[$i];
}
}
}
} else {
// list of characters to skip for random generator
$doNotUseChr = array('<', '>', '{', '}', '&', 'l' , 'O' ,'`', '\'', '|' ,'^', '"');
// create map of random readable characters
$characterMap = '';
while (strlen($characterMap) < 256) {
$random_bytes = openssl_random_pseudo_bytes(10000);
for ($i = 0; $i < strlen($random_bytes); $i++) {
$chr_ord = ord($random_bytes[$i]);
if ($chr_ord >= 33 && $chr_ord <= 125 && !in_array($random_bytes[$i], $doNotUseChr)) {
$characterMap .= $random_bytes[$i];
}
}
}
}
// generate new vouchers
$vouchersGenerated = 0;
$expirytime = $expirytime == 0 ? 0 : $expirytime + time();
while ($vouchersGenerated < $count) {
$generatedUsername = '';
$random_bytes = openssl_random_pseudo_bytes($this->usernameLength);
for ($j=0; $j < strlen($random_bytes); $j++) {
$generatedUsername .= $characterMap[ord($random_bytes[$j])];
}
$generatedPassword = '';
$random_bytes = openssl_random_pseudo_bytes($this->passwordLength);
for ($j=0; $j < strlen($random_bytes); $j++) {
$generatedPassword .= $characterMap[ord($random_bytes[$j])];
}
if (!$this->userNameExists($generatedUsername)) {
$vouchersGenerated++;
// save user, hash password first
$generatedPasswordHash = crypt($generatedPassword, '$6$');
$stmt = $this->dbHandle->prepare('
insert into vouchers(username, password, vouchergroup, validity, expirytime, starttime)
values (:username, :password, :vouchergroup, :validity, :expirytime, :starttime)
');
$stmt->bindParam(':username', $generatedUsername);
$stmt->bindParam(':password', $generatedPasswordHash);
$stmt->bindParam(':vouchergroup', $vouchergroup);
$stmt->bindParam(':validity', $validity);
$stmt->bindParam(':expirytime', $expirytime);
$stmt->bindParam(':starttime', $starttime);
$stmt->execute();
$row = array('username' => $generatedUsername,
'password' => $generatedPassword,
'vouchergroup' => $vouchergroup,
'validity' => $validity,
'expirytime' => $expirytime,
'starttime' => $starttime
);
$response = $row;
}
}
}
return $response;
}
/**
* generate new vouchers and store in voucher database
* @param string $vouchergroup voucher groupname
* @param int $count number of vouchers to generate
* @param int $validity time (in seconds)
* @param int $starttime valid from
* @param int $expirytime valid until ('0' means no expiry time)
* @return array list of generated vouchers
*/
public function generateVouchers($vouchergroup, $count, $validity, $usernamedef, $passworddef, $expirytime, $starttime = null)
{
$response = array();
if ($this->dbHandle != null) {
if ($this->simplePasswords) {
// create a map of easy to read characters
$characterMap = '';
while (strlen($characterMap) < 256) {
$random_bytes = openssl_random_pseudo_bytes(10000);
for ($i = 0; $i < strlen($random_bytes); $i++) {
$chr_ord = ord($random_bytes[$i]);
if (($chr_ord >= 50 && $chr_ord <= 57) || // 2..9
($chr_ord >= 65 && $chr_ord <= 72) || // A..H
($chr_ord >= 74 && $chr_ord <= 78) || // J..N
($chr_ord >= 80 && $chr_ord <= 90) || // P..Z
($chr_ord >= 97 && $chr_ord <= 107) || // a..k
($chr_ord >= 109 && $chr_ord <= 110) || // m..n
($chr_ord >= 112 && $chr_ord <= 122) // p..z
) {
$characterMap .= $random_bytes[$i];
}
}
}
} else {
// list of characters to skip for random generator
$doNotUseChr = array('<', '>', '{', '}', '&', 'l' , 'O' ,'`', '\'', '|' ,'^', '"');
// create map of random readable characters
$characterMap = '';
while (strlen($characterMap) < 256) {
$random_bytes = openssl_random_pseudo_bytes(10000);
for ($i = 0; $i < strlen($random_bytes); $i++) {
$chr_ord = ord($random_bytes[$i]);
if ($chr_ord >= 33 && $chr_ord <= 125 && !in_array($random_bytes[$i], $doNotUseChr)) {
$characterMap .= $random_bytes[$i];
}
}
}
}
// generate new vouchers
$vouchersGenerated = 0;
$expirytime = $expirytime == 0 ? 0 : $expirytime + time();
while ($vouchersGenerated < $count) {
$generatedUsername = '';
$random_bytes = openssl_random_pseudo_bytes($this->usernameLength);
for ($j=0; $j < strlen($random_bytes); $j++) {
$generatedUsername .= $characterMap[ord($random_bytes[$j])];
}
$generatedPassword = '';
$random_bytes = openssl_random_pseudo_bytes($this->passwordLength);
for ($j=0; $j < strlen($random_bytes); $j++) {
$generatedPassword .= $characterMap[ord($random_bytes[$j])];
}
#### BLOCK BEGIN ###
if ($usernamedef != '---') {
if (!$this->userNameExists($generatedUsername)) {
$vouchersGenerated++;
// save user, hash password first
$generatedPasswordHash = crypt($passworddef, '$6$');
$stmt = $this->dbHandle->prepare('
insert into vouchers(username, password, vouchergroup, validity, expirytime, starttime)
values (:username, :password, :vouchergroup, :validity, :expirytime, :starttime)
');
$stmt->bindParam(':username', $usernamedef);
$stmt->bindParam(':password', $generatedPasswordHash);
$stmt->bindParam(':vouchergroup', $vouchergroup);
$stmt->bindParam(':validity', $validity);
$stmt->bindParam(':expirytime', $expirytime);
$stmt->bindParam(':starttime', $starttime);
$stmt->execute();
$row = array('username' => $usernamedef,
'password' => $passworddef,
'vouchergroup' => $vouchergroup,
'validity' => $validity,
'expirytime' => $expirytime,
'starttime' => $starttime
);
$response = $row;
}
}
ELSE
{
if (!$this->userNameExists($generatedUsername)) {
$vouchersGenerated++;
// save user, hash password first
$generatedPasswordHash = crypt($generatedPassword, '$6$');
$stmt = $this->dbHandle->prepare('
insert into vouchers(username, password, vouchergroup, validity, expirytime, starttime)
values (:username, :password, :vouchergroup, :validity, :expirytime, :starttime)
');
$stmt->bindParam(':username', $generatedUsername);
$stmt->bindParam(':password', $generatedPasswordHash);
$stmt->bindParam(':vouchergroup', $vouchergroup);
$stmt->bindParam(':validity', $validity);
$stmt->bindParam(':expirytime', $expirytime);
$stmt->bindParam(':starttime', $starttime);
$stmt->execute();
$row = array('username' => $generatedUsername,
'password' => $generatedPassword,
'vouchergroup' => $vouchergroup,
'validity' => $validity,
'expirytime' => $expirytime,
'starttime' => $starttime
);
$response = $row;
}
}
### BLOCK END ###
}
}
return $response;
}
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 497235
Url: https://administrator.de/contentid/497235
Ausgedruckt am: 22.11.2024 um 18:11 Uhr