mirror of
https://github.com/billz/raspap-webgui.git
synced 2025-12-26 23:26:47 +01:00
Merge pull request #2012 from RaspAP/fix/wifi-security-open
Fix: Use SECURITY_OPEN for evaluating network protocol
This commit is contained in:
120
includes/configure_client.php
Executable file → Normal file
120
includes/configure_client.php
Executable file → Normal file
@@ -3,7 +3,7 @@
|
||||
use RaspAP\Networking\Hotspot\WiFiManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* WiFi client configuration page handler
|
||||
*
|
||||
*/
|
||||
function DisplayWPAConfig()
|
||||
@@ -16,17 +16,15 @@ function DisplayWPAConfig()
|
||||
$wifi->knownWifiStations($networks);
|
||||
$wifi->setKnownStationsWPA($networks);
|
||||
|
||||
$iface = escapeshellarg($_SESSION['wifi_client_interface']);
|
||||
$clientInterface = $_SESSION['wifi_client_interface'];
|
||||
|
||||
if (isset($_POST['connect'])) {
|
||||
$netid = intval($_POST['connect']);
|
||||
$cmd = "sudo wpa_cli -i $iface select_network $netid";
|
||||
$return = shell_exec($cmd);
|
||||
sleep(2);
|
||||
if (trim($return) == "FAIL") {
|
||||
$status->addMessage('WPA command line client returned failure. Check your adapter.', 'danger');
|
||||
} else {
|
||||
|
||||
if ($wifi->connectToNetwork($clientInterface, $netid)) {
|
||||
$status->addMessage('New network selected', 'success');
|
||||
} else {
|
||||
$status->addMessage('WPA command line client returned failure. Check your adapter.', 'danger');
|
||||
}
|
||||
} elseif (isset($_POST['wpa_reinit'])) {
|
||||
$status->addMessage('Attempting to reinitialize wpa_supplicant', 'warning');
|
||||
@@ -34,120 +32,52 @@ function DisplayWPAConfig()
|
||||
$result = $wifi->reinitializeWPA($force_remove);
|
||||
} elseif (isset($_POST['client_settings'])) {
|
||||
$tmp_networks = $networks;
|
||||
if ($wpa_file = fopen('/tmp/wifidata', 'w')) {
|
||||
fwrite($wpa_file, 'ctrl_interface=DIR=' . RASPI_WPA_CTRL_INTERFACE . ' GROUP=netdev' . PHP_EOL);
|
||||
fwrite($wpa_file, 'update_config=1' . PHP_EOL);
|
||||
|
||||
foreach (array_keys($_POST) as $post) {
|
||||
|
||||
if (preg_match('/delete(\d+)/', $post, $post_match)) {
|
||||
$network = $tmp_networks[$_POST['ssid' . $post_match[1]]];
|
||||
$netid = $network['index'];
|
||||
exec('sudo wpa_cli -i ' . $iface . ' disconnect ' . $netid);
|
||||
exec('sudo wpa_cli -i ' . $iface . ' remove_network ' . $netid);
|
||||
$wifi->deleteNetwork($clientInterface, $netid);
|
||||
unset($tmp_networks[$_POST['ssid' . $post_match[1]]]);
|
||||
|
||||
} elseif (preg_match('/disconnect(\d+)/', $post, $post_match)) {
|
||||
$network = $tmp_networks[$_POST['ssid' . $post_match[1]]];
|
||||
$netid = $network['index'];
|
||||
$wifi->disconnectNetwork($clientInterface, $netid);
|
||||
} elseif (preg_match('/update(\d+)/', $post, $post_match)) {
|
||||
// NB, multiple protocols are separated with a forward slash ('/')
|
||||
$protocol = $_POST['protocol' . $post_match[1]] === $wifi::SECURITY_OPEN ? $wifi::SECURITY_OPEN : 'WPA';
|
||||
$tmp_networks[$_POST['ssid' . $post_match[1]]] = array(
|
||||
'protocol' => ( $_POST['protocol' . $post_match[1]] === 'Open' ? 'Open' : 'WPA' ),
|
||||
'passphrase' => $_POST['passphrase' . $post_match[1]],
|
||||
'protocol' => $protocol,
|
||||
'passphrase' => $_POST['passphrase' . $post_match[1]] ?? '',
|
||||
'configured' => true
|
||||
);
|
||||
if (array_key_exists('priority' . $post_match[1], $_POST)) {
|
||||
$tmp_networks[$_POST['ssid' . $post_match[1]]]['priority'] = $_POST['priority' . $post_match[1]];
|
||||
}
|
||||
$network = $tmp_networks[$_POST['ssid' . $post_match[1]]];
|
||||
$ssid = escapeshellarg('"'.$_POST['ssid' . $post_match[1]].'"');
|
||||
$psk = escapeshellarg('"'.$_POST['passphrase' . $post_match[1]].'"');
|
||||
$netid = trim(shell_exec("sudo wpa_cli -i $iface add_network"));
|
||||
if (isset($netid)) {
|
||||
$commands = [
|
||||
"sudo wpa_cli -i $iface set_network $netid ssid $ssid",
|
||||
"sudo wpa_cli -i $iface set_network $netid psk $psk",
|
||||
"sudo wpa_cli -i $iface enable_network $netid"
|
||||
];
|
||||
foreach ($commands as $cmd) {
|
||||
exec($cmd);
|
||||
}
|
||||
} else {
|
||||
|
||||
$ssid = $_POST['ssid' . $post_match[1]];
|
||||
$passphrase = $_POST['passphrase' . $post_match[1]] ?? '';
|
||||
|
||||
$netid = $wifi->updateNetwork($clientInterface, $ssid, $passphrase, $protocol);
|
||||
if ($netid === null) {
|
||||
$status->addMessage('Unable to add network with WPA command line client', 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ok = true;
|
||||
foreach ($tmp_networks as $ssid => $network) {
|
||||
if ($network['protocol'] === $wifi::SECURITY_OPEN) {
|
||||
fwrite($wpa_file, "network={".PHP_EOL);
|
||||
fwrite($wpa_file, "\tssid=\"".$ssid."\"".PHP_EOL);
|
||||
fwrite($wpa_file, "\tkey_mgmt=NONE".PHP_EOL);
|
||||
fwrite($wpa_file, "\tscan_ssid=1".PHP_EOL);
|
||||
if (array_key_exists('priority', $network)) {
|
||||
fwrite($wpa_file, "\tpriority=".$network['priority'].PHP_EOL);
|
||||
}
|
||||
fwrite($wpa_file, "}".PHP_EOL);
|
||||
} else {
|
||||
if (strlen($network['passphrase']) >=8 && strlen($network['passphrase']) <= 63) {
|
||||
unset($wpa_passphrase);
|
||||
unset($line);
|
||||
exec('wpa_passphrase '. $wifi->ssid2utf8( escapeshellarg($ssid) ) . ' ' . escapeshellarg($network['passphrase']), $wpa_passphrase);
|
||||
foreach ($wpa_passphrase as $line) {
|
||||
if (preg_match('/^\s*}\s*$/', $line)) {
|
||||
if (array_key_exists('priority', $network)) {
|
||||
fwrite($wpa_file, "\tpriority=".$network['priority'].PHP_EOL);
|
||||
}
|
||||
fwrite($wpa_file, $line.PHP_EOL);
|
||||
} else {
|
||||
if ( preg_match('/\\\\x[0-9A-Fa-f]{2}/',$ssid) && strpos($line, "ssid=\"") !== false ) {
|
||||
fwrite($wpa_file, "\tssid=P\"".$ssid."\"".PHP_EOL);
|
||||
} else {
|
||||
fwrite($wpa_file, $line.PHP_EOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (strlen($network['passphrase']) == 0 && strlen($network['passkey']) == 64) {
|
||||
$line = "\tpsk=" . $network['passkey'];
|
||||
fwrite($wpa_file, "network={".PHP_EOL);
|
||||
fwrite($wpa_file, "\tssid=\"".$ssid."\"".PHP_EOL);
|
||||
fwrite($wpa_file, $line.PHP_EOL);
|
||||
if (array_key_exists('priority', $network)) {
|
||||
fwrite($wpa_file, "\tpriority=".$network['priority'].PHP_EOL);
|
||||
}
|
||||
fwrite($wpa_file, "}".PHP_EOL);
|
||||
} else {
|
||||
$status->addMessage('WPA passphrase must be between 8 and 63 characters', 'danger');
|
||||
$ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$result = $wifi->writeWpaSupplicant($tmp_networks, $clientInterface);
|
||||
|
||||
if ($ok) {
|
||||
system('sudo cp /tmp/wifidata ' . RASPI_WPA_SUPPLICANT_CONFIG, $returnval);
|
||||
if ($returnval == 0) {
|
||||
exec('sudo wpa_cli -i ' . $_SESSION['wifi_client_interface'] . ' reconfigure', $reconfigure_out, $reconfigure_return);
|
||||
if ($reconfigure_return == 0) {
|
||||
$status->addMessage('Wifi settings updated successfully', 'success');
|
||||
if ($result['success']) {
|
||||
$status->addMessage($result['message'], 'success');
|
||||
$networks = $tmp_networks;
|
||||
} else {
|
||||
$status->addMessage('Wifi settings updated but cannot restart (cannot execute "wpa_cli reconfigure")', 'danger');
|
||||
}
|
||||
} else {
|
||||
$status->addMessage('Wifi settings failed to be updated', 'danger');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$status->addMessage('Failed to update wifi settings', 'danger');
|
||||
$status->addMessage($result['message'], 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
$clientInterface = $_SESSION['wifi_client_interface'];
|
||||
|
||||
exec('ip a show '.$clientInterface, $stdoutIp);
|
||||
$stdoutIpAllLinesGlued = implode(" ", $stdoutIp);
|
||||
$stdoutIpWRepeatedSpaces = preg_replace('/\s\s+/', ' ', $stdoutIpAllLinesGlued);
|
||||
preg_match('/state (UP|DOWN)/i', $stdoutIpWRepeatedSpaces, $matchesState) || $matchesState[1] = 'unknown';
|
||||
$ifaceStatus = strtolower($matchesState[1]) ? "up" : "down";
|
||||
$ifaceStatus = $wifi->getInterfaceStatus($clientInterface);
|
||||
|
||||
echo renderTemplate("configure_client", compact("status", "clientInterface", "ifaceStatus"));
|
||||
}
|
||||
|
||||
@@ -112,6 +112,9 @@ function getProviderValue($id, $key)
|
||||
if (!isset($obj['providers']) || !is_array($obj['providers'])) {
|
||||
return false;
|
||||
}
|
||||
if ($id === null || !is_numeric($id)) {
|
||||
return false;
|
||||
}
|
||||
$id--;
|
||||
if (!isset($obj['providers'][$id]) || !is_array($obj['providers'][$id])) {
|
||||
return false;
|
||||
|
||||
@@ -9,14 +9,16 @@ www-data ALL=(ALL) NOPASSWD:/sbin/wpa_supplicant -i [a-zA-Z0-9]* -c /etc/wpa_sup
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/rm /var/run/wpa_supplicant/[a-zA-Z0-9]*
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* scan_results
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* scan
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* status
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* reconfigure
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* add_network
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* list_networks
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i enable_network [0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i disconnect [0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* enable_network [0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* disconnect [0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* select_network [0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* set_network [0-9] *
|
||||
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* remove_network [0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/rm -f /var/run/wpa_supplicant/wlan[0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/hostapddata /etc/hostapd/hostapd.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/systemctl start hostapd.service
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/systemctl stop hostapd.service
|
||||
|
||||
@@ -49,7 +49,7 @@ class WiFiManager
|
||||
break;
|
||||
case 'key_mgmt':
|
||||
if (! array_key_exists('passphrase', $network) && $lineArr[1] === 'NONE') {
|
||||
$network['protocol'] = 'Open';
|
||||
$network['protocol'] = self::SECURITY_OPEN;
|
||||
}
|
||||
break;
|
||||
case 'priority':
|
||||
@@ -82,27 +82,27 @@ class WiFiManager
|
||||
$cacheKey,
|
||||
function () use ($iface) {
|
||||
$stdout = shell_exec("sudo iw dev $iface scan");
|
||||
sleep(1);
|
||||
if ($stdout === null) {
|
||||
return [];
|
||||
}
|
||||
return preg_split("/\n/", $stdout);
|
||||
}
|
||||
);
|
||||
|
||||
// exclude the AP from nearby networks
|
||||
exec('sed -rn "s/ssid=(.*)\s*$/\1/p" ' . escapeshellarg(RASPI_HOSTAPD_CONFIG), $ap_ssid);
|
||||
$ap_ssid = $ap_ssid[0] ?? '';
|
||||
|
||||
// determine the next index that follows the indexes of the known networks
|
||||
$index = -1;
|
||||
$index = 0;
|
||||
if (!empty($networks)) {
|
||||
foreach ($networks as $network) {
|
||||
if (isset($network['index']) && ($network['index'] > $index)) {
|
||||
$index = $network['index'];
|
||||
if (isset($network['index']) && is_numeric($network['index']) && ($network['index'] > $index)) {
|
||||
$index = (int)$network['index'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
|
||||
$current = [];
|
||||
$commitCurrent = function () use (&$current, &$networks, &$index, $ap_ssid) {
|
||||
$commitCurrent = function () use (&$current, &$networks, &$index) {
|
||||
if (empty($current['ssid'])) {
|
||||
return;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class WiFiManager
|
||||
$ssid = $current['ssid'];
|
||||
|
||||
// unprintable 7bit ASCII control codes, delete or quotes -> ignore network
|
||||
if ($ssid === $ap_ssid || preg_match('/[\x00-\x1f\x7f\'`\´"]/', $ssid)) {
|
||||
if (preg_match('/[\x00-\x1f\x7f\'`\´"]/', $ssid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ class WiFiManager
|
||||
'RSSI' => $rssi,
|
||||
'index' => $index
|
||||
];
|
||||
++$index;
|
||||
$index++; // increment for next new network
|
||||
}
|
||||
};
|
||||
|
||||
@@ -177,20 +177,50 @@ class WiFiManager
|
||||
}
|
||||
$commitCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Check if networks are connected via wpa_cli status
|
||||
* NB: iwconfig shows the last associated SSID even when connection is inactive
|
||||
*/
|
||||
public function connectedWifiStations(&$networks)
|
||||
{
|
||||
exec('iwconfig ' .$_SESSION['wifi_client_interface'], $iwconfig_return);
|
||||
foreach ($iwconfig_return as $line) {
|
||||
if (preg_match('/ESSID:\"([^"]+)\"/i', $line, $iwconfig_ssid)) {
|
||||
$ssid=hexSequence2lower($iwconfig_ssid[1]);
|
||||
$networks[$ssid]['connected'] = true;
|
||||
//$check=detectCaptivePortal($_SESSION['wifi_client_interface']);
|
||||
$networks[$ssid]["portal-url"]=$check["URL"];
|
||||
$wpa_state = null;
|
||||
$connected_ssid = null;
|
||||
$iface = $_SESSION['wifi_client_interface'];
|
||||
|
||||
$cmd = "sudo wpa_cli -i $iface status";
|
||||
$status_output = shell_exec($cmd);
|
||||
|
||||
if ($status_output === null || empty($status_output)) {
|
||||
error_log("WiFiManager::connectedWifiStations: wpa_cli command failed or returned no output");
|
||||
return;
|
||||
}
|
||||
$lines = explode("\n", trim($status_output));
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if (preg_match('/^wpa_state=(.+)$/', $line, $matches)) {
|
||||
$wpa_state = trim($matches[1]);
|
||||
}
|
||||
if (preg_match('/^ssid=(.+)$/', $line, $matches)) {
|
||||
$connected_ssid = trim($matches[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($wpa_state === 'COMPLETED' && !empty($connected_ssid)) {
|
||||
$ssid = hexSequence2lower($connected_ssid);
|
||||
|
||||
// check if this SSID exists in networks array
|
||||
if (array_key_exists($ssid, $networks)) {
|
||||
$networks[$ssid]['connected'] = true;
|
||||
} else {
|
||||
error_log("WiFiManager::connectedWifiStations: SSID '$ssid' not found. SSIDs: " . implode(', ', array_keys($networks)));
|
||||
}
|
||||
|
||||
// captive portal detection
|
||||
// $check = detectCaptivePortal($iface);
|
||||
// if (isset($check["URL"])) {
|
||||
// $networks[$ssid]["portal-url"] = $check["URL"];
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,8 +285,11 @@ class WiFiManager
|
||||
{
|
||||
$iface = $_SESSION['wifi_client_interface'];
|
||||
if ($force == true) {
|
||||
$cmd = "sudo /sbin/wpa_supplicant -i $unescapedIface -c /etc/wpa_supplicant/wpa_supplicant.conf -B 2>&1";
|
||||
$cmd = "sudo rm -f /var/run/wpa_supplicant/" . $iface;
|
||||
$result = shell_exec($cmd);
|
||||
$cmd = "sudo /sbin/wpa_supplicant -i $iface -c /etc/wpa_supplicant/wpa_supplicant.conf -B 2>&1";
|
||||
$result = shell_exec($cmd);
|
||||
sleep(2);
|
||||
}
|
||||
$cmd = "sudo wpa_cli -i $iface reconfigure";
|
||||
$result = shell_exec($cmd);
|
||||
@@ -425,7 +458,7 @@ class WiFiManager
|
||||
"sudo wpa_cli -i $iface set_network $netid ssid $ssid",
|
||||
];
|
||||
|
||||
if (strtolower($protocol) === 'open') {
|
||||
if ($protocol === self::SECURITY_OPEN) {
|
||||
$commands[] = "sudo wpa_cli -i $iface set_network $netid key_mgmt NONE";
|
||||
} else {
|
||||
$commands[] = "sudo wpa_cli -i $iface set_network $netid psk $psk";
|
||||
@@ -464,7 +497,7 @@ class WiFiManager
|
||||
foreach ($output as $line) {
|
||||
$columns = preg_split('/\t/', $line);
|
||||
if (count($columns) >= 2 && trim($columns[1]) === trim($ssid)) {
|
||||
return (int)$columns[0];
|
||||
return (int)$columns[0]; // return network ID
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -519,5 +552,211 @@ CONF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the operational status of a network interface
|
||||
*
|
||||
* @param string $interface network interface name
|
||||
* @return string returns up, down, or unknown
|
||||
*/
|
||||
public function getInterfaceStatus(string $interface): string
|
||||
{
|
||||
exec('ip a show ' . escapeshellarg($interface), $output);
|
||||
$outputGlued = implode(" ", $output);
|
||||
$outputNormalized = preg_replace('/\s\s+/', ' ', $outputGlued);
|
||||
|
||||
if (preg_match('/state (UP|DOWN)/i', $outputNormalized, $matches)) {
|
||||
return strtolower($matches[1]);
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a network using wpa_cli
|
||||
*
|
||||
* @param string $interface network interface name
|
||||
* @param int $netid network ID to connect to
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function connectToNetwork(string $interface, int $netid): bool
|
||||
{
|
||||
$iface = escapeshellarg($interface);
|
||||
|
||||
$cmd = "sudo wpa_cli -i $iface select_network $netid";
|
||||
$selectResult = shell_exec($cmd);
|
||||
|
||||
if ($selectResult === null || trim($selectResult) === "FAIL") {
|
||||
return false;
|
||||
}
|
||||
sleep(3);
|
||||
|
||||
$cmd = "sudo wpa_cli -i $iface reassociate";
|
||||
$reassociateResult = shell_exec($cmd);
|
||||
|
||||
if ($reassociateResult !== null) {
|
||||
$trimmed = trim($reassociateResult);
|
||||
if ($trimmed === "FAIL") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a network from wpa_cli
|
||||
*
|
||||
* @param string $interface network interface name
|
||||
* @param int $netid network ID to delete
|
||||
* @return void
|
||||
*/
|
||||
public function deleteNetwork(string $interface, int $netid): void
|
||||
{
|
||||
$iface = escapeshellarg($interface);
|
||||
|
||||
exec("sudo wpa_cli -i $iface disconnect $netid");
|
||||
exec("sudo wpa_cli -i $iface remove_network $netid");
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from a network using wpa_cli
|
||||
*
|
||||
* @param string $interface network interface name
|
||||
* @param int $netid network ID to disconnect from
|
||||
* @return void
|
||||
*/
|
||||
public function disconnectNetwork(string $interface, int $netid): void
|
||||
{
|
||||
$iface = escapeshellarg($interface);
|
||||
|
||||
exec("sudo wpa_cli -i $iface disconnect $netid");
|
||||
exec("sudo wpa_cli -i $iface remove_network $netid");
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates/adds a network via wpa_cli
|
||||
*
|
||||
* @param string $interface network interface name
|
||||
* @param string $ssid network SSID
|
||||
* @param string $passphrase network passphrase
|
||||
* @param string $protocol security protocol (OPEN or WPA)
|
||||
* @return int|null network ID on success, null on failure
|
||||
*/
|
||||
public function updateNetwork(string $interface, string $ssid, string $passphrase, string $protocol = 'WPA'): ?int
|
||||
{
|
||||
$iface = escapeshellarg($interface);
|
||||
$escapedSsid = escapeshellarg('"' . $ssid . '"');
|
||||
|
||||
$netid = shell_exec("sudo wpa_cli -i $iface add_network");
|
||||
|
||||
if ($netid === null || !is_numeric(trim($netid))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$netid = trim($netid);
|
||||
$commands = [
|
||||
"sudo wpa_cli -i $iface set_network $netid ssid $escapedSsid"
|
||||
];
|
||||
|
||||
if ($protocol === self::SECURITY_OPEN) {
|
||||
$commands[] = "sudo wpa_cli -i $iface set_network $netid key_mgmt NONE";
|
||||
} else {
|
||||
$escapedPsk = escapeshellarg('"' . $passphrase . '"');
|
||||
$commands[] = "sudo wpa_cli -i $iface set_network $netid psk $escapedPsk";
|
||||
}
|
||||
|
||||
$commands[] = "sudo wpa_cli -i $iface enable_network $netid";
|
||||
|
||||
foreach ($commands as $cmd) {
|
||||
exec($cmd);
|
||||
}
|
||||
|
||||
return (int)$netid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a wpa_supplicant configuration and applies it
|
||||
*
|
||||
* @param array $networks array of network configurations
|
||||
* @param string $interface the network interface name
|
||||
* @return array Array with 'success' (bool) and 'message' (string)
|
||||
*/
|
||||
public function writeWpaSupplicant(array $networks, string $interface): array
|
||||
{
|
||||
$wpa_file = fopen('/tmp/wifidata', 'w');
|
||||
if (!$wpa_file) {
|
||||
return ['success' => false, 'message' => 'Failed to update wifi settings'];
|
||||
}
|
||||
|
||||
fwrite($wpa_file, 'ctrl_interface=DIR=' . RASPI_WPA_CTRL_INTERFACE . ' GROUP=netdev' . PHP_EOL);
|
||||
fwrite($wpa_file, 'update_config=1' . PHP_EOL);
|
||||
|
||||
$ok = true;
|
||||
foreach ($networks as $ssid => $network) {
|
||||
if ($network['protocol'] === self::SECURITY_OPEN) {
|
||||
fwrite($wpa_file, "network={".PHP_EOL);
|
||||
fwrite($wpa_file, "\tssid=\"".$ssid."\"".PHP_EOL);
|
||||
fwrite($wpa_file, "\tkey_mgmt=NONE".PHP_EOL);
|
||||
fwrite($wpa_file, "\tscan_ssid=1".PHP_EOL);
|
||||
if (array_key_exists('priority', $network)) {
|
||||
fwrite($wpa_file, "\tpriority=".$network['priority'].PHP_EOL);
|
||||
}
|
||||
fwrite($wpa_file, "}".PHP_EOL);
|
||||
} else {
|
||||
if (strlen($network['passphrase']) >= 8 && strlen($network['passphrase']) <= 63) {
|
||||
unset($wpa_passphrase);
|
||||
unset($line);
|
||||
exec('wpa_passphrase '. $this->ssid2utf8(escapeshellarg($ssid)) . ' ' . escapeshellarg($network['passphrase']), $wpa_passphrase);
|
||||
foreach ($wpa_passphrase as $line) {
|
||||
if (preg_match('/^\s*}\s*$/', $line)) {
|
||||
if (array_key_exists('priority', $network)) {
|
||||
fwrite($wpa_file, "\tpriority=".$network['priority'].PHP_EOL);
|
||||
}
|
||||
fwrite($wpa_file, $line.PHP_EOL);
|
||||
} else {
|
||||
if (preg_match('/\\\\x[0-9A-Fa-f]{2}/', $ssid) && strpos($line, "ssid=\"") !== false) {
|
||||
fwrite($wpa_file, "\tssid=P\"".$ssid."\"".PHP_EOL);
|
||||
} else {
|
||||
fwrite($wpa_file, $line.PHP_EOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (strlen($network['passphrase']) == 0 && strlen($network['passkey']) == 64) {
|
||||
$line = "\tpsk=" . $network['passkey'];
|
||||
fwrite($wpa_file, "network={".PHP_EOL);
|
||||
fwrite($wpa_file, "\tssid=\"".$ssid."\"".PHP_EOL);
|
||||
fwrite($wpa_file, $line.PHP_EOL);
|
||||
if (array_key_exists('priority', $network)) {
|
||||
fwrite($wpa_file, "\tpriority=".$network['priority'].PHP_EOL);
|
||||
}
|
||||
fwrite($wpa_file, "}".PHP_EOL);
|
||||
} else {
|
||||
$ok = false;
|
||||
fclose($wpa_file);
|
||||
return ['success' => false, 'message' => 'WPA passphrase must be between 8 and 63 characters'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose($wpa_file);
|
||||
|
||||
if ($ok) {
|
||||
system('sudo cp /tmp/wifidata ' . RASPI_WPA_SUPPLICANT_CONFIG, $returnval);
|
||||
if ($returnval == 0) {
|
||||
exec('sudo wpa_cli -i ' . escapeshellarg($interface) . ' reconfigure', $reconfigure_out, $reconfigure_return);
|
||||
if ($reconfigure_return == 0) {
|
||||
return ['success' => true, 'message' => 'Wifi settings updated successfully'];
|
||||
} else {
|
||||
return ['success' => false, 'message' => 'Wifi settings updated but cannot restart (cannot execute "wpa_cli reconfigure")'];
|
||||
}
|
||||
} else {
|
||||
return ['success' => false, 'message' => 'Wifi settings failed to be updated'];
|
||||
}
|
||||
}
|
||||
|
||||
return ['success' => false, 'message' => 'Unknown error'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
use RaspAP\Networking\Hotspot\WiFiManager;
|
||||
$wifi = new WiFiManager();
|
||||
|
||||
// fix: re-apply locale settings in this template context
|
||||
if (!empty($_SESSION['locale'])) {
|
||||
putenv("LANG=" . $_SESSION['locale']);
|
||||
setlocale(LC_ALL, $_SESSION['locale']);
|
||||
bindtextdomain('messages', realpath(__DIR__ . '/../../locale'));
|
||||
bind_textdomain_codeset('messages', 'UTF-8');
|
||||
textdomain('messages');
|
||||
}
|
||||
|
||||
// set defaults
|
||||
$network = $network ?? [];
|
||||
$network['ssid'] = $network['ssid'] ?? '';
|
||||
$network['ssidutf8'] = $network['ssidutf8'] ?? $network['ssid'];
|
||||
$network['configured'] = $network['configured'] ?? false;
|
||||
$network['connected'] = $network['connected'] ?? false;
|
||||
$network['visible'] = $network['visible'] ?? false;
|
||||
$network['channel'] = $network['channel'] ?? '';
|
||||
$network['protocol'] = $network['protocol'] ?? $wifi::SECURITY_OPEN;
|
||||
$network['passphrase'] = $network['passphrase'] ?? '';
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
@@ -57,7 +76,7 @@ $wifi = new WiFiManager();
|
||||
<div class="mb-3">
|
||||
<div class="info-item-wifi mb-2"><?php echo _("Passphrase"); ?></div>
|
||||
<div class="input-group">
|
||||
<?php if ($network['protocol'] === 'Open') { ?>
|
||||
<?php if ($network['protocol'] === $wifi::SECURITY_OPEN) { ?>
|
||||
<input type="password" disabled class="form-control" aria-describedby="passphrase" name="passphrase<?php echo $index ?>" value="" />
|
||||
<?php } else { ?>
|
||||
<input type="password" class="form-control" aria-describedby="passphrase" name="passphrase<?php echo $index ?>" value="<?php echo htmlspecialchars($network['passphrase']); ?>" data-bs-target="#update<?php echo $index ?>" data-colors="#ffd0d0,#d0ffd0">
|
||||
@@ -69,7 +88,11 @@ $wifi = new WiFiManager();
|
||||
<div class="btn-group btn-block d-flex">
|
||||
<?php if ($network['configured']) { ?>
|
||||
<input type="submit" class="btn btn-warning" value="<?php echo _("Update"); ?>" id="update<?php echo $index ?>" name="update<?php echo $index ?>"<?php echo ($network['protocol'] === 'Open' ? ' disabled' : '')?> data-bs-toggle="modal" data-bs-target="#configureClientModal" />
|
||||
<?php if ($network['connected']) { ?>
|
||||
<button type="submit" class="btn btn-info" value="<?php echo $index?>" name="disconnect<?php echo $index ?>"><?php echo _("Disconnect"); ?></button>
|
||||
<?php } else { ?>
|
||||
<button type="submit" class="btn btn-info" value="<?php echo $index?>" name="connect"><?php echo _("Connect"); ?></button>
|
||||
<?php } ?>
|
||||
<?php } else { ?>
|
||||
<input type="submit" class="btn btn-info" value="<?php echo _("Add"); ?>" id="update<?php echo $index ?>" name="update<?php echo $index ?>" data-bs-toggle="modal" data-bs-target="#configureClientModal" />
|
||||
<?php } ?>
|
||||
|
||||
Reference in New Issue
Block a user