-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CoreWLAN returning None for SSID/BSSID #600
Comments
I can see this behaviour on my main machine:
Python 3.12.3, PyObjC 10.2, macOS 14.4.1 on an M1 laptop. One thing I noticed: On the first try it took a long time to obtain authorisation, no problems from the second run onwards. This is in a virtualenv. |
I get the same behaviour with an ObjC program, but... note how I disabled the location authorisation check which was needed because the loop always failed: #import <Foundation/Foundation.h>
#import <CoreWLAN/CoreWLAN.h>
#import <CoreLocation/CoreLocation.h>
#include <time.h>
int main(void)
{
// Initialise CoreLocation
NSLog(@"Obtaining authorisation for location services (required for WiFi scanning)...");
CLLocationManager* location_manager = [[CLLocationManager alloc] init];
[location_manager startUpdatingLocation];
#if 0
// Wait for location services to be authorised
const int max_wait = 10;
for(int i = 0; i < max_wait; i++) {
CLAuthorizationStatus authorization_status = location_manager.authorizationStatus;
NSLog(@"status %ld", (long)authorization_status);
switch (authorization_status) {
case kCLAuthorizationStatusAuthorized:
//case kCLAuthorizationStatusAuthorizedAlways:
//case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"Received authorization, continuing...");
break;
case kCLAuthorizationStatusRestricted:
case kCLAuthorizationStatusDenied:
NSLog(@"No authorization, aborting...");
return 1;
default:
if (i == max_wait - 1) {
NSLog(@"Unable to obtain authorisation, exiting...");
return 1;
}
}
sleep(1);
}
#endif
// Get the default WiFi interface
CWInterface* cwlan_interface = [CWInterface interface];
// Scan for networks
NSLog(@"Scanning for networks...");
NSError* error;
NSSet<CWNetwork*>* scan_result = [cwlan_interface scanForNetworksWithName:nil error:&error];
if (scan_result == nil) {
NSLog(@"scan failed %@", error);
return 1;
}
for (CWNetwork* net in scan_result) {
NSLog(@"net = %@", net);
}
/*
# Iterate through each network in the scan results
for i, net in enumerate(scan_result):
# Extract security type from the CWNetwork description
security = re.search(r'security=(.*?)(,|$)', str(net)).group(1)
# Add the network to the table
table.add_row([i + 1, net.ssid(), net.bssid(), net.rssiValue(), net.channel(), security])
# Display the table
print(table)
*/
return 0;
} Noteworthy: the
That's a red herring though, the modern way to do the same way gives the same result: CWInterface* cwlan_interface = [[CWWiFiClient sharedWiFiClient] interface]; UPDATE: |
I cannot reproduce this after all, just noticed that I disabled the check in the python version as well and had disabled location services for python. After reenabling the code and location services I got the expected result with names and BSSIDs (not sharing the output for obvious reasons). import re, time, CoreWLAN, CoreLocation, Foundation
from prettytable import PrettyTable
# Initialise CoreLocation
print('\nObtaining authorisation for location services (required for WiFi scanning)...\n')
location_manager = CoreLocation.CLLocationManager.alloc().init()
#location_manager.requestWhenInUseAuthorization()
location_manager.startUpdatingLocation()
loop = Foundation.NSRunLoop.currentRunLoop()
# Wait for location services to be authorised
max_wait = 10
for i in range(1, max_wait):
authorization_status = location_manager.authorizationStatus()
print(f"{authorization_status=}")
if authorization_status == 3 or authorization_status == 4:
print('Received authorisation, continuing...\n')
break
#loop.runUntilDate_(Foundation.NSDate.dateWithTimeIntervalSinceNow_(1))
time.sleep(1)
else:
exit('Unable to obtain authorisation, exiting...\n')
# Get the default WiFi interface
cwlan_interface = CoreWLAN.CWInterface.interface()
# Scan for networks
print('Scanning for networks...\n')
scan_result, _ = cwlan_interface.scanForNetworksWithName_error_(None, None)
# Parse scan results and display in a table
table = PrettyTable(['Number', 'Name', 'BSSID', 'RSSI', 'Channel', 'Security'])
# Iterate through each network in the scan results
for i, net in enumerate(scan_result):
# Extract security type from the CWNetwork description
security = re.search(r'security=(.*?)(,|$)', str(net)).group(1)
# Add the network to the table
table.add_row([i + 1, net.ssid(), net.bssid(), net.rssiValue(), net.channel(), security])
# Display the table
print(table) |
Thank you for the response! Just to confirm, you were able to get the code to function as expected simply by disabling and re-enabling Python's location services permission in System Settings? Either way, it's strange that your code ran in the first instance with the correct permissions, but returned 'None' for the SSID and BSSID. Indeed, CoreLocation will have had to return Why did CoreWLAN fail to return the correct SSID/BSSID values despite having correct permissions? And why did disabling/re-enabling Python's location services remedy this issue for you? Is there some additional requirement past location services authorisation for CoreWLAN to return the expected SSID/BSSID values? |
I get the same result here. I have two virtual environments using Python 3.9 and the same version of PyObjC ("pip install pyobjc"):
There are various differences between the two python installations, the most relevant differences are likely: a. The deployment target is different (the python.org installer targets 10.9, the version of Python included with Xcode targets a newer release The latter seems to be the most relevant, an old build of python without code signing that I have lying around also fails to collect the information. |
I haven't tried doing a fresh build yet, I might do that later. Likewise for testing the Python.org installation when strip the code signing from that. |
Hi @ronaldoussoren, I hope you're well! I wanted to follow up on this issue as I'm still running into the bug. I updated my Python version via I've tried disabling and re-enabling Python's location services permission in System Settings, but this doesn't seem to help. It sounds likely that code signing differences between the Python versions may be causing the issue, as you suggested. Do you know how we could troubleshoot this further? |
Hi there! In my project, WiFiCrackPy, several people have opened issues stating that CoreWLAN is returning
None
for the SSIDs and/or BSSIDs of networks (see here).I am aware that an issue was opened in 2022 (#484) where a similar problem was occurring, and I see that this was resolved by granting Python location services permissions.
What is strange is that I do not experience this issue, but people with the same macOS versions and Python versions as me do. They have confirmed they have granted Python location services permissions. I am using Python 3.12.2 installed via Homebrew, macOS 14.4.1, and PyObjC 10.2.
Someone has noticed that the issue does not occur when running the script with the system-native version of Python, but it is not clear why there is an inconsistency with the Homebrew-installed version of Python.
As a note, there is a post in the Apple Developer forums where people have highlighted the same issue and underscored the inconsistency across the same macOS/Python/PyObjC versions.
Here is an excerpt of my WiFiCrackPy script which contains just the location authorisation and network scanning sections. As mentioned, this works fine on my Mac but you can see examples from other people in the issue I linked above where the SSIDs and BSSIDs are shown as
None
:It has been difficult for me to troubleshoot the issue as I have not experienced the problem.
I recently tried to manually load the frameworks using
objc
rather than importingCoreWLAN
andCoreLocation
directly (see here), but that does not seem to have fixed the issue.Thank you in advance for any help or guidance you can give!
The text was updated successfully, but these errors were encountered: