Запуск привилегированных приложений на C под MacOSX

Я пишу приложение Installer / Autoupdater для MacOSX (используя Qt и 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. Уже исправлено в приведенном выше коде.

б) Другие интернет-источники говорят, что функция AuthorizationExecuteWithPrivileges устарела и не должна использоваться из-за соображений безопасности. Может кто-нибудь привести пример, как это сделать лучше?

2

Решение

Да, AuthorizationExecuteWithPrivileges устарела.

Apple теперь предоставляет более безопасный метод обработки приложений с повышенными правами, который заключается в выделении кода, требующего повышения прав, в другое вспомогательное приложение, которому предоставлено специальное разрешение и которое запущено с повышенными правами. Таким образом, если ваше приложение подверглось злоупотреблению из-за вредоносного ПО или внедрения кода, оно также не сможет получить повышенный доступ. Вспомогательное приложение также подписано вашим приложением, поэтому только ваше приложение может запросить его запуск.

Если вы посмотрите на Apple, Пример SMJobBless, это показывает, как вы делаете это. Начните с взгляда на ReadMe.txt и я бы также предложил выполнить поиск SMJobBless в Google, так как об этом довольно много говорят.

1

Другие решения

Возможно, мой ответ для вас запоздал, но я надеюсь, что он поможет другим разработчикам Qt. Я создал проект в Qt, чтобы показать, как подписывать, устанавливать исполняемый привилегированный вспомогательный инструмент с помощью SMJobBless; Вы можете увидеть код здесь: https://github.com/mbsanchez/QtPrivilegedHelperExample

Я создал его, потому что нет документации по установке привилегированного вспомогательного инструмента, который был разработан с C ++ на QtCreator.

Редактировать:
Я объясню процесс, которому я следовал, чтобы сделать это.

Проблема: у вас есть приложение «AppA», которое вы хотите запустить с правами администратора из другого приложения «AppB», разработанного на C ++ с использованием QtCreator.

Решение: начиная с Mac Os X 10.7 функция AuthorizationExecuteWithPrivileges устарела, поэтому вместо нее вы будете использовать SMJobBless. Но вся документация и примеры о SMJobBless есть на Xcode, и до сих пор на C ++ ничего не было.

Чтобы использовать SMJobBless, вы разработаете третье приложение «AppC», которое обычно называют вспомогательным инструментом и устанавливается как привилегированный вспомогательный инструмент с использованием SMJobBless и запускается в виде демона с помощью launchd. Затем, подобно тому, как AppC выполняется с правами администратора, любое приложение, выполняемое AppC, получит права администратора. Итак, если вы запустили AppA из AppC, AppA будет работать с правами администратора.
Здесь есть три важных вещи:

  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 в __TEXT
    раздел привилегированного вспомогательного приложения (AppC).

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

    Этот флаг был установлен в AppC.pro

  4. каждый случай XXXXXXXXXX в plist-файлах будет изменен для подразделения организации вашего сертификата разработчика Apple.

  5. AppB и AppC будут подписаны с помощью действующего разработчика Apple
    Сертификат с помощью инструмента кодирования.
  6. AppC будет скопирован в пакет AppB в Contents / Library / LaunchServices
  7. AppA будет скопирован в пакет AppB в разделе Содержание / Ресурсы
  8. AppB Info.plist будет скопирован в пакет приложений.
  9. Далее вы подпишите AppB Bundle с помощью инструмента кодирования.
  10. В этом примере используется сокет Unix для связи AppB с демоном launchd AppC, затем AppC запускает подключение к серверу и ожидает команды от AppB, когда AppC получает команду, которая выполняет AppA (вы можете использовать функцию execvp C или что угодно).
  11. AppB запустит клиентское соединение и отправит команду в AppC, когда ему потребуется запустить AppA.

Я попытался объяснить все детали здесь, но я думаю, что у вас будет лучшее представление о решении, изучив мой код.

3

По вопросам рекламы [email protected]