Skip to content

Commit

Permalink
Add private MAC address for macOS 15
Browse files Browse the repository at this point in the history
  • Loading branch information
tuxudo committed Oct 15, 2024
1 parent 26fb6f6 commit f0e8b23
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 40 deletions.
6 changes: 4 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
WiFi module
==============

Provides connected WiFi network information gathered by `/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I` and various WiFi preferences
Provides connected WiFi network information gathered by macOS binaries and various WiFi preferences

Client Preferences
---
Expand Down Expand Up @@ -35,4 +35,6 @@ Table Schema
* snr (integer) Signal to noise ratio
* known_networks (medium text) JSON string detailing known wireless networks
* phy_mode (string) PHY mode of the current active connection
* country_code (string) Current contry code of the WiFi
* country_code (string) Current contry code of the WiFi
* private_mac_address (string) Private MAC address (macOS 15+ only)
* private_mac_mode_user (string) Private MAC address setting (macOS 15+ only)
7 changes: 6 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,10 @@
"last_discovered_at": "Last Discovered At",
"autojoin_disabled": "Auto Join Disabled",
"add_reason": "Add Method",
"standalone_6g": "Standalone 6G"
"standalone_6g": "Standalone 6G",
"private_mac_address": "Private MAC",
"private_mac_updated_at": "Private MAC Updated",
"private_mac_mode_user": "Private MAC User Setting",
"private_mac_mode_user_updated": "Private MAC User Setting Updated",
"private_mac_eval_at": "Private MAC Evaluated"
}
35 changes: 35 additions & 0 deletions migrations/2024_10_03_000001_wifi_add_private_mac.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Capsule\Manager as Capsule;

class WifiAddPrivateMac extends Migration
{
private $tableName = 'wifi';

public function up()
{
$capsule = new Capsule();

$capsule::schema()->table($this->tableName, function (Blueprint $table) {
$table->string('private_mac_address')->nullable();
$table->string('private_mac_mode_user')->nullable();
});

// Create indexes
$capsule::schema()->table($this->tableName, function (Blueprint $table) {
$table->index('private_mac_address');
$table->index('private_mac_mode_user');
});
}

public function down()
{
$capsule = new Capsule();
$capsule::schema()->table($this->tableName, function (Blueprint $table) {
$table->dropColumn('private_mac_address');
$table->dropColumn('private_mac_mode_user');
});
}
}
50 changes: 45 additions & 5 deletions scripts/wifi
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ def get_wifi_info():
info = {"state": "unknown"}

# Set power state
if "Power : On" in output:
if "Power : On [On]" in output:
info['state'] = "running"
elif "Power : Off" in output:
elif "Power : Off [Off]" in output:
info['state'] = "off"

# Check if Mac has WiFi or sharing is active
Expand Down Expand Up @@ -276,6 +276,26 @@ def get_wifi_bssid(ssid):
except Exception:
return ""

def get_private_mac_info(ssid):

try:
plist = FoundationPlist.readPlist("/Library/Preferences/com.apple.wifi.known-networks.plist")

out = {}

# Check that we have the SSID in the preference file and it contains a PrivateMACAddressModeUserSetting entry
if 'wifi.network.ssid.'+ssid in plist and "PrivateMACAddressModeUserSetting" in plist['wifi.network.ssid.'+ssid]:
out['private_mac_mode_user'] = plist['wifi.network.ssid.'+ssid]['PrivateMACAddressModeUserSetting']

# Check that we have the SSID in the preference file and it contains a CachedPrivateMACAddress entry
if 'wifi.network.ssid.'+ssid in plist and "CachedPrivateMACAddress" in plist['wifi.network.ssid.'+ssid]:
out['private_mac_address'] = plist['wifi.network.ssid.'+ssid]['CachedPrivateMACAddress']

return out

except Exception:
return {}

def get_networks():

try:
Expand Down Expand Up @@ -304,13 +324,18 @@ def get_networks():
"ssid":"",
"channel_history":"",
"bssid_list":"",
"add_reason":""}
"add_reason":"",
"private_mac_address":"",
"private_mac_updated_at":"",
"private_mac_mode_user":"",
"private_mac_mode_user_updated":"",
"private_mac_eval_at":""}

for key in plist[network]:

if key == "CaptiveProfile" and "CaptiveNetwork" in plist[network]["CaptiveProfile"]:
ssid_entry["captive"] = to_bool(plist[network]["CaptiveProfile"]["CaptiveNetwork"])


elif key == "AddedAt":
ssid_entry["added_ad"] = string_to_time(plist[network][key])
elif key == "JoinedBySystemAt":
Expand All @@ -319,6 +344,12 @@ def get_networks():
ssid_entry["last_connected_user"] = string_to_time(plist[network][key])
elif key == "LastDiscoveredAt":
ssid_entry["last_discovered_at"] = string_to_time(plist[network][key])
elif key == "CachedPrivateMACAddressUpdatedAt":
ssid_entry["private_mac_updated_at"] = string_to_time(plist[network][key])
elif key == "PrivateMACAddressEvaluatedAt":
ssid_entry["private_mac_eval_at"] = string_to_time(plist[network][key])
elif key == "PrivateMACAddressModeUserSettingUpdatedAt":
ssid_entry["private_mac_mode_user_updated"] = string_to_time(plist[network][key])

elif key == "PasspointSPRoamingEnabled":
ssid_entry["passpoint"] = to_bool(plist[network][key])
Expand All @@ -335,16 +366,21 @@ def get_networks():
elif key == "Standalone6G":
ssid_entry["standalone_6g"] = to_bool(plist[network][key])


elif key == "SupportedSecurityTypes":
ssid_entry["security_type"] = plist[network][key]
elif key == "AddReason":
ssid_entry["add_reason"] = plist[network][key]
elif key == "CachedPrivateMACAddress":
ssid_entry["private_mac_address"] = plist[network][key]
elif key == "PrivateMACAddressModeUserSetting":
ssid_entry["private_mac_mode_user"] = plist[network][key]

elif key == "SystemMode":
ssid_entry["system_mode"] = to_bool(plist[network][key])

elif key == "SSID":
ssid_entry["ssid"] = plist[network][key].decode('ascii')
ssid_entry["ssid"] = plist[network][key].decode("utf-8", errors="ignore")


elif key == "__OSSpecific__":
Expand Down Expand Up @@ -600,6 +636,10 @@ def main():
if 'bssid' not in result and 'ssid' in result:
result['bssid'] = get_wifi_bssid(result['ssid'])

# If greater than macOS 15 (Darwin 24), get private MAC address data
if getDarwinVersion() > 23 and 'ssid' in result:
result.update(get_private_mac_info(result['ssid']))

# Write wifi results to cache
cachedir = '%s/cache' % os.path.dirname(os.path.realpath(__file__))
output_plist = os.path.join(cachedir, 'wifi.plist')
Expand Down
38 changes: 14 additions & 24 deletions views/wifi_listing.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
<th data-colname='wifi.ssid'>SSID</th>
<th data-colname='wifi.bssid'>BSSID</th>
<th data-i18n="wifi.state" data-colname='wifi.state'></th>
<th data-i18n="wifi.private_mac_address" data-colname='wifi.private_mac_address'></th>
<th data-i18n="wifi.lasttxrate_short" data-colname='wifi.lasttxrate'></th>
<th data-i18n="wifi.maxrate_short" data-colname='wifi.maxrate'></th>
<th data-i18n="wifi.channel" data-colname='wifi.channel'></th>
<th data-colname='wifi.snr'>SNR</th>
<th data-colname='wifi.agrctlrssi'>RSSI</th>
Expand All @@ -23,26 +23,25 @@
<th data-i18n="wifi.op_mode" data-colname='wifi.op_mode'></th>
<th data-i18n='wifi.country_code' data-colname='wifi.country_code'></th>
<th data-colname='wifi.mcs'>MCS</th>
<th data-i18n='wifi.private_mac_mode_user' data-colname='wifi.private_mac_mode_user'></th>
</tr>
</thead>
<tbody>
<tr>
<td data-i18n="listing.loading" colspan="16" class="dataTables_empty"></td>
<td data-i18n="listing.loading" colspan="17" class="dataTables_empty"></td>
</tr>
</tbody>
</table>
</div> <!-- /span 12 -->
</div> <!-- /span -->
</div> <!-- /row -->
</div> <!-- /container -->

<script type="text/javascript">

$(document).on('appUpdate', function(e){

var oTable = $('.table').DataTable();
oTable.ajax.reload();
return;

});

$(document).on('appReady', function(e, lang) {
Expand Down Expand Up @@ -72,11 +71,17 @@
var link = mr.getClientDetailLink(name, sn, '#tab_wifi-tab');
$('td:eq(0)', nRow).html(link);

// Format Last Tx
var lastTx=$('td:eq(5)', nRow).html();
$('td:eq(5)', nRow).html('<span title="'+(lastTx*0.125)+' MB/sec">'+lastTx+" Mbps</span>");
// Format wifi state
var wifistate=$('td:eq(4)', nRow).html();
wifistate = wifistate == 'running' ? i18n.t('wifi.running') :
wifistate = wifistate == 'off' ? i18n.t('wifi.off') :
wifistate = wifistate == 'no wifi' ? i18n.t('wifi.no_wifi') :
wifistate = wifistate == 'init' ? i18n.t('wifi.init') :
wifistate = wifistate == 'sharing' ? i18n.t('wifi.sharing') :
(wifistate === 'unknown' ? i18n.t('wifi.unknown') : wifistate)
$('td:eq(4)', nRow).text(wifistate)

// Format Max Tx
// Format Last Tx
var maxTx=$('td:eq(6)', nRow).html();
if (maxTx != ""){
$('td:eq(6)', nRow).html('<span title="'+(maxTx*0.125)+' MB/sec">'+maxTx+" Mbps</span>");
Expand Down Expand Up @@ -120,11 +125,6 @@
apmode = apmode == 'station ' ? i18n.t('wifi.station') : (apmode)
$('td:eq(13)', nRow).text(apmode)

// Format 802.1x mode
var eightmode=$('td:eq(16)', nRow).html();
eightmode = eightmode == 'open' ? i18n.t('wifi.open') : (eightmode)
$('td:eq(16)', nRow).text(eightmode)

// Blank row if no wifi
var wifistate=$('td:eq(4)', nRow).html();
if ( wifistate == 'no wifi' || wifistate == 'off' || wifistate == 'init') {
Expand All @@ -142,16 +142,6 @@
$('td:eq(15)', nRow).text("")
$('td:eq(16)', nRow).text("")
}

// Format wifi state
var wifistate=$('td:eq(4)', nRow).html();
wifistate = wifistate == 'running' ? i18n.t('wifi.running') :
wifistate = wifistate == 'off' ? i18n.t('wifi.off') :
wifistate = wifistate == 'no wifi' ? i18n.t('wifi.no_wifi') :
wifistate = wifistate == 'init' ? i18n.t('wifi.init') :
wifistate = wifistate == 'sharing' ? i18n.t('wifi.sharing') :
(wifistate === 'unknown' ? i18n.t('wifi.unknown') : wifistate)
$('td:eq(4)', nRow).text(wifistate)
}
});
});
Expand Down
8 changes: 4 additions & 4 deletions views/wifi_security_widget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ buttons:
- label: none
i18n_label: wifi.open
class: btn-danger
search_component: open
search_component: none
hide_when_zero: true
- label: wep
i18n_label: wifi.wep
Expand All @@ -19,17 +19,17 @@ buttons:
- label: wpa
i18n_label: wifi.wpa-psk
class: btn-danger
search_component: wpa-psk
search_component: wpa
hide_when_zero: true
- label: wpa2
i18n_label: wifi.wpa2-psk
class: btn-warning
search_component: wpa2-psk
search_component: wpa2
hide_when_zero: true
- label: wpa3
i18n_label: wifi.wpa3-sae
class: btn-success
search_component: wpa3-sae
search_component: wpa3
hide_when_zero: true
- label: x8021
i18n_label: wifi.802.1x
Expand Down
Loading

0 comments on commit f0e8b23

Please sign in to comment.