Not Sandbox App, Working on SMAppService as root

I am currently developing a No-Sandbox application.

What I want to achieve is to use AuthorizationCopyRights in a No-Sandbox application to elevate to root, then register SMAppService.daemon after elevation, and finally call the registered daemon from within the No-Sandbox application.

Implementation Details

Here is the Plist that I am registering with SMAppService:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.agent</string>
    
    <key>BundleProgram</key>
    <string>/usr/local/bin/test</string>
    
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/test</string>
      <string>login</string>
    </array>
    
    <key>RunAtLoad</key>
    <true/>

</dict>
</plist>

Code that successfully performs privilege escalation (a helper tool popup appears)

    private func registerSMAppServiceDaemon() -> Bool  {
        let service = SMAppService.daemon(plistName: "com.example.plist")
        do {
            try service.register()
            print("Successfully registered \(service)")
            return true
        } catch {
            print("Unable to register \(error)")
            return false
        }
    }

    private func levelUpRoot() -> Bool {
        var authRef: AuthorizationRef?
        let status = AuthorizationCreate(nil, nil, [], &authRef)
        if status != errAuthorizationSuccess {
            return false
        }
        
        let rightName = kSMRightBlessPrivilegedHelper
        
        return rightName.withCString { cStringName -> Bool in
            var authItem = AuthorizationItem(
                name: cStringName,
                valueLength: 0,
                value: nil,
                flags: 0
            )
            
            return withUnsafeMutablePointer(to: &authItem) { authItemPointer -> Bool in
                var authRights = AuthorizationRights(count: 1, items: authItemPointer)
                let authFlags: AuthorizationFlags = [.interactionAllowed, .preAuthorize, .extendRights]
                let status = AuthorizationCopyRights(authRef!, &authRights, nil, authFlags, nil)
                if status == errAuthorizationSuccess {
                    if !registerSMAppServiceDaemon() {
                        return false
                    }
                    return true
                }
                return false
            }
        }
    }

Error Details

Unable to register Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}

The likely cause of this error is that /usr/local/bin/test is being bundled. However, based on my understanding, since this is a non-sandboxed application, the binary should be accessible as long as it is run as root.

Trying

post as mentioned in the response, placing the test binary under Contents/Resources/ allows SMAppService to successfully register it. However, executing the binary results in a different error.

Here is the plist at that time.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.agent</string>
    
    <key>BundleProgram</key>
    <string>Contents/Resources/test</string>
    
    <key>ProgramArguments</key>
    <array>
      <string>Contents/Resources/test</string>
      <string>login</string>
    </array>
    
    <key>RunAtLoad</key>
    <true/>

</dict>
</plist>

Here is the function at that time.

    private func executeBin() {
        let bundle = Bundle.main
        if let binaryPath = bundle.path(forResource: "test", ofType: nil) {
            print(binaryPath)
            let task = Process()
            task.executableURL = URL(fileURLWithPath: binaryPath)
            task.arguments = ["login"]
            
            let pipe = Pipe()
            task.standardOutput = pipe
            task.standardError = pipe
            
            do {
                try task.run()
                
                let outputData = pipe.fileHandleForReading.readDataToEndOfFile()
                if let output = String(data: outputData, encoding: .utf8) {
                    print("Binary output: \(output)")
                }
                
                task.waitUntilExit()
                
                if task.terminationStatus == 0 {
                    print("Binary executed successfully")
                } else {
                    print("Binary execution failed with status: \(task.terminationStatus)")
                }
            } catch {
                print("Error executing binary: \(error)")
            }
        } else {
            print("Binary not found in the app bundle")
        }
    }

Executed After Error

Binary output: 
Binary execution failed with status: 5

Are there any other ways to execute a specific binary as root when using AuthorizationCopyRights? For example, by preparing a Helper Tool?

I’m confused. You wrote:

Written by flekystyley in 775532021
I want … to use AuthorizationCopyRights … to elevate to root

That doesn’t make sense. AuthorizationCopyRights doesn’t elevate privileges. Rather, it’s a way for apps (and OS subsystems) to voluntarily restrict access to certain operations.

Additionally, kSMRightBlessPrivilegedHelper is relevant to SMJobBless, not SMAppService.

Taking a step back, can you explain more about your high-level goal here?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Not Sandbox App, Working on SMAppService as root
 
 
Q