Avoid repeated authorization dialogs when changing network settings

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?

Answered by DTS Engineer in 863561022
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"

Accepted Answer
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"

Avoid repeated authorization dialogs when changing network settings
 
 
Q