I have an swift command line tool that changes proxy settings in system preferences via SystemConfiguration framework, does some stuff, and in the end reverts proxy settings back to original.
Here is simplified code:
var authorization: AuthorizationRef?
let status = AuthorizationCreate(nil, nil, [], &authorization)
let prefs = SCPreferencesCreateWithAuthorization(nil, "myapp" as CFString, nil, authorization)
// change proxy setttings
// do some stuff
let prefs2 = SCPreferencesCreateWithAuthorization(nil, "myapp" as CFString, nil, authorization)
// change proxy settings back to original
When I try to change settings for the first time, the system dialog appears requesting permission to change network settings. If I try to change settings again within а short period of time, the dialog does not appear again. However, if it takes more than several minutes after first change, the dialog does appear again. Is there a way to create authorization, so that the dialog appears only once per app launch, no matter how much time passed since the first dialog?
If I try to change settings again within а short period of time …
Yep. System Configuration does this check using Authorization Services to acquire the necessary right. I’m not sure if the actual right is documented as API, but I believe the current implementation uses system.services.systemconfiguration.network. You can then follow the bouncing ball from there:
% security authorizationdb read system.services.systemconfiguration.network | plutil -p -
…
{
"class" => "rule"
"comment" => "For making change to network configuration via System Configuration."
…
"k-of-n" => 1
"rule" => [
0 => "is-root"
1 => "entitled"
2 => "_mbsetupuser-nonshared"
3 => "authenticate-admin-nonshared"
]
}
% security authorizationdb read authenticate-admin-nonshared | plutil -p -
…
{
"allow-root" => 0
"authenticate-user" => 1
"class" => "user"
"comment" => "Authenticate as an administrator."
…
"group" => "admin"
"session-owner" => 0
"shared" => 0
"timeout" => 30
"tries" => 10000
}
So, the right won’t use a credential that’s older than 30 seconds.
The workaround is suggested by the first option in k-of-n list, namely, to do this work as root. See BSD Privilege Escalation on macOS.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"