My understanding was wrong. System Settings UI navigation to enable the network extension is little bit different in Sequoia from previous MacOS. My Network extension is working now.
Post
Replies
Boosts
Views
Activity
Even it is building properly on Sonona Intel with Xcode 15.4. But failed to build on Sonoma Silicon. What would be the possible reason? Pls help.
One more thing, If I use another app to send the messages by using unixgram domain sockets then immediately i am getting "no buffer space" error even without network extension. Is there any way to increase the network load in mac?
Here I am filtering based on connection only (i.e NEFilterDataProvider). I am reading through all of the data in all of the outbound / inbound flows.
Everything is working fine if we tried manually after user login.
We are not getting popup if automatic login option is enabled. If automatic login option is disabled then popup is coming before user login into the machine. Looks like user space is yet loaded before activating extension.
I think, user space should load to activate the NE.
The code running in .app and available at /Applications directory only. Internally my agent has the .app and few other executable files. When I install my agent, my .app will be placed in /Applications/ folder. One of the process name of my agent is daemon. This daemon process internally will start the .app to activate the NE. Here these is no issue if we choose Allow from below popup. Issue with Don't Allow option only. NE is allowing to filter the network content if we select Don'tAllow and restart the machine. Here my daemon process internally starts the .app as part of bootstrap when machine is up.
I have noticed same issue with one of the cisco product which is available at https://its.gmu.edu/wp-content/uploads/anyconnect-macos-4.10.05085-core-vpn-webdeploy-k9.dmg. I think, this is a bug in apple.
Noticed same issue with https://its.gmu.edu/wp-content/uploads/anyconnect-macos-4.10.05085-core-vpn-webdeploy-k9.dmg also. I think, this is a bug at apple.
I have added a video at https://youtu.be/8gnO8n4gADo for reference.
A Network System Extension will always start during bootup of the system. If the user previously allowed the provider to run, then it will run again regardless of the code in the container app. When the system is booted up, the system extension is run, not the container app.
I think, my intention haven't understood properly. When we try to configure & activate NE, we will get two popups. First one is Security Preferences. Once we allow NE to activate from Security & Privacy then again we will get another popup to allow network content to filter.
Below two images are related to first popup. OS will throw below image whenever submit the activation request and If we allow here then NE will be activated. Once we allow here and if we run systemextensionsctl list command then will NE will show as [activated enabled] I think, you mentioned about this in your previous reply and this is fine for us.
Once we activate the NE from Security&Privacy as shown in above image then will get another popup like Allow/Don't Allow as shown below to enable filter configuration. If we choose Allow to filter network content then will show app as running in Network as shown below.
Now issue is facing when we choose Don't Allow from above popup and restart the machine. we have enableFilterConfiguration() functionality as part of machine bootstrap to confirm from the user to Allow/DontAllow the NE whenever machine is up after restart. But this is not throwing any popup like Allow/DontAllow and allowing network content to filter by default. This can notice from Network as shown above image. Here enableFilterConfiguration() is calling as part of bootstrap before user login into the machine and automatic user login option was enabled in my Mac machine.
If we call enableFilterConfiguration after user login into the machine then popup is coming to Allow/DontAllow. But, If I call this before user login into the machine then popup is not coming to Allow/DontAllow & NE is allowing to filter the content.
NE activation & enableFilterConfiguration() code was added in my previous reply for reference.
One more point, Automatic login option was enabled in my Mac machine.
Regarding:
Case 1: NE was activated but chosen DontAllow option from the popup as shown below. As part of bootstrap, we are trying to save the preferences for the popup if filtermanger object is available & Not Allowed. But the Allow/Don'tAllow popup is not coming and configuring with Allow automatically.
I'm don't think I am understanding what your workflow is here. You are not trying to automatically activate the Network Configuration if the user has disallowed the prompt are you?
No, I want to keep the NE state as previous like 'Dont'Allow'. But NE is allowing without any user action after rebooting the machine. This is not expected behaviour.
Here, we want to confirm from the user to Allow/DontAllow the NE after machine reboot. So, we were added functionality like NEFilterManager.shared().saveToPreferences for the popup to decide if user did not allow the NE for filtering previously. But this is not giving popup and allowing by default. Here NEFilterManager.shared().saveToPreferences is calling before user login into the machine.
One more point, If we call NEFilterManager.shared().saveToPreferences after user login into the machine then popup is coming to Allow/DontAllow. But, If I call this before user login into the machine then popup is not coming & NE is allowing by default.
Is this expected behaviour?
Below is the sample code to start the NE and startFilter() is API to activate & Allow the NE.
class Controller: NSObject {
@objc func startFilter() -> NSNumber {
current_cmd = .start
if NEFilterManager.shared().isEnabled {
exit(Controller.ReturnCodes.success.rawValue)
}
if NEFilterManager.shared().providerConfiguration != nil {
NEFilterManager.shared().isEnabled = true
NEFilterManager.shared().saveToPreferences { serror in
DispatchQueue.main.async {
if let error = serror {
os_log("Error is saving NE configuration %@", error.localizedDescription)
exit(Controller.ReturnCodes.saveConfFailed.rawValue)
}
exit(Controller.ReturnCodes.success.rawValue)
}
}
}
else {
guard let extensionIdentifier = extensionBundle.bundleIdentifier else {
os_log("failed to get the bundleidentified before activation request")
return NSNumber(value:Controller.ReturnCodes.invalidBundleIdentifier.rawValue)
}
let activationRequest = OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: extensionIdentifier, queue: .main)
activationRequest.delegate = self
OSSystemExtensionManager.shared.submitRequest(activationRequest)
}
return NSNumber(value: Controller.ReturnCodes.procStillRunning.rawValue)
}
// MARK: Content Filter Configuration Management
func enableFilterConfiguration() {
let filterManager = NEFilterManager.shared()
if filterManager.providerConfiguration == nil {
let providerConfiguration = NEFilterProviderConfiguration()
providerConfiguration.filterSockets = true
providerConfiguration.filterPackets = false
//providerConfiguration.filterBrowsers = false
filterManager.providerConfiguration = providerConfiguration
if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
filterManager.localizedDescription = appName
}
}
filterManager.isEnabled = true
filterManager.saveToPreferences { saveError in
DispatchQueue.main.async {
if let error = saveError {
os_log("Failed to save the filter configuration: %@", error.localizedDescription)
exit(Controller.ReturnCodes.saveConfFailed.rawValue)
}
exit(Controller.ReturnCodes.success.rawValue)
}
}
}
}
extension Controller: OSSystemExtensionRequestDelegate {
// MARK: OSSystemExtensionActivationRequestDelegate
func request(_ request: OSSystemExtensionRequest,didFinishWithResult result: OSSystemExtensionRequest.Result){
guard result == .completed else {
os_log("Unexpected result %d for system extension request", result.rawValue)
//status = .stopped
exit(Controller.ReturnCodes.RequestFailed.rawValue)
}
if self.current_cmd != .uninstall {
enableFilterConfiguration()
}
else {
exit(Controller.ReturnCodes.success.rawValue)
}
}
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
os_log("System extension request failed: %@", error.localizedDescription)
//status = .stopped
exit(Controller.ReturnCodes.RequestFailed.rawValue)
}
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
os_log("Extension %@ requires user approval", request.identifier)
}
func request(_ request: OSSystemExtensionRequest,
actionForReplacingExtension existing: OSSystemExtensionProperties,
withExtension extension: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
os_log("Replacing extension %@ version %@ with version %@", request.identifier, existing.bundleShortVersion, `extension`.bundleShortVersion)
return .replace
}
}
I have one doubt. If we activate the NE before user login and if we wont choose any option from the above popup then automatically considering as Allow after user login into the machine. Is this intentional?
Here two cases are there.
Case 1: NE was activated but chosen DontAllow option from the popup as shown below.
As part of bootstrap, we are trying to save the preferences for the popup if filtermanger object is available & Not Allowed. But the Allow/Don'tAllow popup is not coming and configuring with Allow automatically.
Case2: NE was activated but not chosen any option from the popup as shown below. Whenever machine is rebooting, preferences are saving with Allow automatically at downtime and extension is running after machine is up.
Code snippet to save the preferences:
NEFilterManager.shared().isEnabled = true
NEFilterManager.shared().saveToPreferences { serror in
DispatchQueue.main.async {
if let error = serror {
exit(Controller.ReturnCodes.saveConfFailed.rawValue)
}
exit(Controller.ReturnCodes.success.rawValue)
}
}
One more doubt, If I reboot the machine without providing the response like Allow/Don'tAllow which is shown in the above popup then by default considering as Allow without generating the popup again after machine up.
Is there any way to generate the popup again after machine up?
Thanks.
Hi,
Few times, I am also facing with "IPC failed" error and few times I am facing with "permission denied" error with savePreferences. But My Content FilterDataProvider is working as expected. But why we got this error with savePreferences?
Thanks.