2013-07-04 25 views
2

我正在爲MacOSX編寫一個安裝程序/ Autoupdater應用程序(使用Qt和C++)。我需要升級權限才能覆蓋應用程序文件夾中的舊文件。在MacOSX下啓動C中的特權應用程序

我的升級代碼是基於下面的例子:http://www.michaelvobrien.com/blog/2009/07/authorizationexecutewithprivileges-a-simple-example/ 我試着重新啓動我的現有應用程序具有管理員權限是這樣的:

void MainDialog::EscalatePrivileges() 
{ 
    AuthorizationRef authorizationRef; 
    OSStatus status; 

    status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); 

    char* tool = QApplication::instance()->applicationFilePath().toLocal8Bit().data(); 
    char* args[] = { "STARTUPDATE", NULL }; 
    FILE* pipe = NULL; 

    status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, AuthorizationFlagDefaults, args, &pipe); 
    QApplication::instance()->quit(); 
} 

不過,我得到錯誤-60031(發射失敗工具) 。 問題:

一)爲什麼會失敗?我懷疑它是因爲工作文件夾設置不正確? (我可以設置工具的工作文件夾不知何故?)

編輯:好了,想通,一出:在ARGS [] - 陣列本身需要以NULL結尾。已經固定在上面的代碼中。

b)其他互聯網來源說功能AuthorizationExecuteWithPrivileges已棄用,不應使用,因爲安全問題。有人可以舉例說明如何以更好的方式做到這一點?

+0

[AuthorizationExecuteWithPrivileges is deprecated]的可能重複(http://stackoverflow.com/questions/6841937/authorizationexecutewithprivileges-is-deprecated) – bdash

回答

1

是的,不推薦使用AuthorizationExecuteWithPrivileges。

蘋果現在提供了一個處理提升應用的更安全的方法,那就是分解出需要提升到另一個,這是給予特別許可,並與提升的權限啓動輔助應用程序的代碼。這樣,如果您的應用程序因惡意軟件或代碼注入而遭到濫用,則無法獲得任何提升的訪問權限。助手應用程序也與您的應用程序簽名,所以只有您的應用程序可以請求它啓動。

如果你看看蘋果的SMJobBless example,它表明你如何去這樣做。首先看看ReadMe.txt,我也會建議做一個關於SMJobBless的Google搜索,因爲有很多關於它的討論。

3

也許我的回答是遲到的,但我希望它可以幫助其他Qt開發人員。我已經在Qt中創建了一個項目來演示如何使用SMJobBless來簽名,安裝一個執行特權輔助工具;你可以在這裏看到代碼:https://github.com/mbsanchez/QtPrivilegedHelperExample

我已經創建了它,因爲沒有關於如何安裝特權輔助工具的文檔,在QtCreator上用C++開發了什麼。

編輯: 我解釋說,我隨後做這個過程。

的問題:你有一個應用程序「APPA」你想從其他應用程序「APPB」關於C++使用QtCreator開發的管理權限來執行的。

解決方案:因爲Mac OS X 10.7的AuthorizationExecuteWithPrivileges功能,已過時,所以你會使用SMJobBless代替。但是關於SMJobBless的所有文檔和示例都在Xcode上,並且直到現在,C++上都沒有。

要使用SMJobBless,您將開發第三個應用程序「AppC」,該應用程序通常被稱爲幫助工具,並將作爲使用SMJobBless的特權幫助工具進行安裝,並通過launchd作爲守護程序執行。然後,像AppC以管理員權限執行一樣,AppC執行的任何應用程序都將獲得管理權限。因此,如果您從AppC執行AppA,則AppA將以管理員身份運行。 有三個東西importants這裏:

  1. APPB將安裝特權輔助工具(APPC),使用SMJobBless,所以,APPB需要一個Info.plist文件,具有 特權輔助工具的列表它可以安裝(在這種情況下爲AppC)。

    <?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>CFBundleIdentifier</key> 
        <string>com.example.AppB</string> 
        <key>CFBundleInfoDictionaryVersion</key> 
        <string>6.0</string> 
        ... 
        <key>SMPrivilegedExecutables</key> 
        <dict> 
         <key>com.example.AppC</key> 
         <string>anchor apple generic and identifier &quot;com.example.AppC&quot; and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = XXXXXXXXXX)</string> 
        </dict> 
    </dict> 
    </plist> 
    

    的Info.plist

  2. APPC需要兩個文件的plist,第一個包含有關的launchd任務信息,什麼是所使用的系統啓動APPC作爲 守護進程(APPC不會被執行通過AppB,一旦該AppC安裝了 ,它將由系統啓動);第二個有 有關什麼應用程序可以將其安裝爲幫助工具(在這種情況下爲AppB )的信息。

    <?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.AppC</string> 
        <key>StandardErrorPath</key> 
        <string>/var/log/com.example.appc.log</string> 
        <key>Sockets</key> 
        <dict> 
         <key>com.example.AppC</key> 
         <dict> 
          <key>SockFamily</key> 
          <string>Unix</string> 
          <key>SockPathMode</key> 
          <integer>438</integer> 
          <key>SockPathName</key> 
          <string>/var/run/com.example.AppC.socket</string> 
          <key>SockType</key> 
          <string>Stream</string> 
         </dict> 
        </dict> 
    </dict> 
    </plist> 
    

    APPC-Launchd.plist

    <?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>CFBundleIdentifier</key> 
        <string>com.example.AppC</string> 
        ... 
        <key>SMAuthorizedClients</key> 
        <array> 
         <string>anchor apple generic and identifier com.example.AppB and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = XXXXXXXXXX)</string> 
        </array> 
    </dict> 
    </plist> 
    

    APPC-Info.plist中

  3. APPC既要對付的plist文件通過使用鏈接「-sectcreate __TEXT __info_plist myinfo.plist -sectcreate __TEXT __launchd_plist mylaunchd.plist「編譯器的鏈接標誌(QMAKE_LFLAGS中的 qmake)。這會將兩個plist文件嵌入特權幫助器應用程序(AppC)的__TEXT 部分。

    QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$PWD/AppC-Info.plist -sectcreate __TEXT __launchd_plist $$PWD/AppC-Launchd.plist 
    

    中的此標誌AppC.pro

  4. 中的plist文件XXXXXXXXXX的每種情況設置,將改變你的蘋果開發者ceritifcate的組織單位。

  5. 使用codesign工具,將使用有效的Apple開發人員 證書對AppB和AppC進行簽名。
  6. APPC將被複制到APPB的內容捆/庫/ LaunchServices
  7. APPA將被複制到APPB的內容捆/資源
  8. APPB的Info.plist將被複制到應用程序包。
  9. 接下來,您將使用編碼工具簽署AppB軟件包。
  10. 本示例使用unix套接字與AppC launchd守護進程通信AppB,然後AppC將啓動服務器連接並等待來自AppB的命令,當AppC收到它將執行AppA的命令時(您可以使用execvp C函數或任何其他想)。
  11. 當需要運行AppA時,AppB將啓動客戶端連接並將命令發送到AppC。

我試圖在這裏解釋所有的細節,但我想你會通過檢查我的代碼來更好地瞭解解決方案。

+1

有用的補充總是受歡迎的,即使「遲到」,這個答案有潛力,你有工作代碼。但是,除了鏈接之外,答案還需要對解決方案的關鍵部分和元素進行充實。鏈接只有答案往往會打破,特別是如果代碼後來被移動或刪除。 – Niall

+1

不錯。我會編輯這個問題來添加一些提示。 – kato2

相關問題