我的mytool主應用程式包中有一個輔助二進制檔案,我需要將其復制到/usr/local/bin.
現在bin可能并不總是存在或具有寫訪問權限,因此標準NSWorkspace呼叫將失敗。我研究了不同的方法來做到這一點,但沒有一個是令人滿意的(或者我做錯了)
為獲得授權
replaceFile的NSWorkspace.requestAuthorization這似乎不起作用,因為在嘗試
/usr/local/bin/mytool用我的包中的檔案“替換”檔案后,我仍然收到權限錯誤。通過
AuthorizationCreate.這里的問題是它
AuthorizationExecuteWithPrivileges已被棄用(或者在我的情況下甚至在 Swift 中都不可用),并且SMJobBless似乎僅適用于更長時間運行的輔助行程。還SMJobBless需要我的輔助工具有Info.plist自己的,它沒有,因為它只是一個普通的二進制檔案
那么我如何設法在 Swift 中執行特權檔案復制?
PS:該應用程式未經過沙盒處理,因此NSOpenPanel無濟于事。
uj5u.com熱心網友回復:
好吧,我使用 挖出了已棄用的 API dlsym,因為除了手動詢問用戶密碼之外別無他法,除非已棄用的 API 完全消失,否則我不想這樣做。
所以我現在要做的是驗證對mytool --installusing的呼叫,AuthorizationExecuteWithPrivileges如下所示:
import Foundation
import Security
public struct Sudo {
private typealias AuthorizationExecuteWithPrivilegesImpl = @convention(c) (
AuthorizationRef,
UnsafePointer<CChar>, // path
AuthorizationFlags,
UnsafePointer<UnsafeMutablePointer<CChar>?>, // args
UnsafeMutablePointer<UnsafeMutablePointer<FILE>>?
) -> OSStatus
/// This wraps the deprecated AuthorizationExecuteWithPrivileges
/// and makes it accessible by Swift
///
/// - Parameters:
/// - path: The executable path
/// - arguments: The executable arguments
/// - Returns: `errAuthorizationSuccess` or an error code
public static func run(path: String, arguments: [String]) -> Bool {
var authRef: AuthorizationRef!
var status = AuthorizationCreate(nil, nil, [], &authRef)
guard status == errAuthorizationSuccess else { return false }
defer { AuthorizationFree(authRef, [.destroyRights]) }
var item = kAuthorizationRightExecute.withCString { name in
AuthorizationItem(name: name, valueLength: 0, value: nil, flags: 0)
}
var rights = withUnsafeMutablePointer(to: &item) { ptr in
AuthorizationRights(count: 1, items: ptr)
}
status = AuthorizationCopyRights(authRef, &rights, nil, [.interactionAllowed, .preAuthorize, .extendRights], nil)
guard status == errAuthorizationSuccess else { return false }
status = executeWithPrivileges(authorization: authRef, path: path, arguments: arguments)
return status == errAuthorizationSuccess
}
private static func executeWithPrivileges(authorization: AuthorizationRef,
path: String,
arguments: [String]) -> OSStatus {
let RTLD_DEFAULT = dlopen(nil, RTLD_NOW)
guard let funcPtr = dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges") else { return -1 }
let args = arguments.map { strdup($0) }
defer { args.forEach { free($0) }}
let impl = unsafeBitCast(funcPtr, to: AuthorizationExecuteWithPrivilegesImpl.self)
return impl(authorization, path, [], args, nil)
}
}
uj5u.com熱心網友回復:
如果您想使用公共 API(意味著不使用已棄用的 API、呼叫 Apple 腳本、通過 Process 退出等)來做到這一點,那么實作這一目標的唯一方法是使用SMJobBless. 無論好壞,這是 Apple 仍正式支持的唯一選擇。
如果你想安裝你的二進制檔案,/usr/local/bin那么二進制檔案本身不需要有一個 Info.plist。您想創建一個不同的幫助工具,通過SMJobBless它可以將您的二進制檔案復制到/usr/bin/local. 它將能夠做到這一點,因為安裝的幫助工具SMJobBless始終以 root 身份運行。完成所有這些操作后,您可以使用SMJobBless卸載本身安裝的幫助工具。不可否認,它相當復雜。
如果您確實想沿著這條路線走下去,請查看SwiftAuthorizationSample。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/350215.html
上一篇:Axios不斷下載損壞的PDF
