Merge pull request #2012 from RaspAP/fix/wifi-security-open

Fix: Use SECURITY_OPEN for evaluating network protocol
This commit is contained in:
Bill Zimmerman
2025-11-28 10:27:07 +01:00
committed by GitHub
5 changed files with 345 additions and 148 deletions

120
includes/configure_client.php Executable file → Normal file
View 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"));
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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'];
}
}

View File

@@ -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 } ?>