I made it work by switching from using the Security Foundation framework to Authorization Services Framework:
private func obtainSystemDaemonModificationRights_authServices() -> AuthorizationRef! {
var authRef: AuthorizationRef?
let createStatus = AuthorizationCreate(nil, nil, [], &authRef)
guard createStatus == errAuthorizationSuccess, authRef != nil else {
Logger.app.error("Failed to create authorization object! [\(createStatus)]")
fatalError()
}
kSMRightModifySystemDaemons.withCString { rightCStringPtr in
var rightItem = AuthorizationItem(name: rightCStringPtr,
valueLength: 0,
value: nil,
flags: 0)
withUnsafeMutablePointer(to: &rightItem) { rightItemPtr in
var rights = AuthorizationRights(count: 1, items: rightItemPtr)
var flags: AuthorizationFlags = [.extendRights, .interactionAllowed]
var environment = AuthorizationEnvironment(count: 0, items: nil)
let copyStatus = AuthorizationCopyRights(authRef!,
&rights,
&environment,
flags,
nil)
guard copyStatus == errAuthorizationSuccess else {
Logger.app.error("Failed to copy authorization right! [\(copyStatus)]")
fatalError()
}
}
}
return authRef!
}
I don't know upfront what the difference is, but I'm probably making a programming error while using SFAuthorization.
Furthermore, swapping only the most necessary code parts to SFAuthorization version doesn't work either, and this change immediately makes the above function fail with error code 2 again:
withUnsafeMutablePointer(to: &rightItem) { rightItemPtr in
var rights = AuthorizationRights(count: 1, items: rightItemPtr)
var flags: AuthorizationFlags = [.extendRights, .interactionAllowed]
var environment = AuthorizationEnvironment(count: 0, items: nil)
// let copyStatus = AuthorizationCopyRights(authRef!,
// &rights,
// &environment,
// flags,
// nil)
// guard copyStatus == errAuthorizationSuccess else {
// Logger.app.error("Failed to copy authorization right! [\(copyStatus)]")
// fatalError()
// }
let authorization = SFAuthorization()
try! authorization!.obtain(withRights: &rights,
flags: flags,
environment: &environment,
authorizedRights: nil)
authRef = authorization!.authorizationRef()
}
As some (maybe coincidental) info, I noticed that SMJobSubmit was deprecated in macOS 10.10, and SFAuthorization.obtain was introduced in that same version.