Lazarus Pascal: Написание привилегированного вспомогательного инструмента с помощью SMJobBless()

В прошлом я создал приложение в Lazarus Pascal, которое выполняет "dd" для записи образа на диск. Для этого, очевидно, необходимы повышенные права.

В первоначальной версии я использовал AuthorizationExecuteWithPrivileges() ( ссылка), хотя и не совсем предназначенный для этой цели, он работал очень хорошо и очень последовательно. Однако эта функция устарела начиная с OSX 10.7, так как это может быть проблемой безопасности, и операторы командной строки, которые перенаправляют, также не работают должным образом (перенаправление вывода из zip как вход для dd).

В следующей версии я использовал метод, описанный в Lazarus Pascal Wiki ( Выполнение внешних программ), который в основном запускает процесс TP, с которым общается моя программа. С помощью sudo -S dd ..., пароль пользователя спрашивается и вводится, чтобы убедиться, что он / она имеет надлежащие права доступа. Очевидно, это немного грязный метод взлома, и это показывает, что у некоторых пользователей возникают проблемы с этим.

После долгих чтений кажется, что Apple предпочитает, чтобы это делалось с помощью вспомогательного инструмента SMJobBless (). К сожалению, я не очень опытен, когда дело доходит до Objective-C, представленный код в лучшем случае кажется очень минимальным и не очень хорошо документированным.

Мне было интересно, если у кого-то есть опыт или может помочь "перенести" этот метод на Lazarus Pascal... Я все за то, чтобы сделать это правильно. Конечно, альтернативные методы также приветствуются!

Любая помощь будет принята с благодарностью.

1 ответ

К сожалению, я не очень опытный, когда дело доходит до Objective-C

Не позволяйте этому отказаться от использования примера, предоставленного Apple. Если вы внимательно посмотрите на код в SMJobBlessAppController.m, вы увидите, что кроме одной строки кода Objective-C, остальное просто C.

Строка Objective-C регистрирует вспомогательное приложение: -

if (![self blessHelperWithLabel:@"com.apple.bsd.SMJobBlessHelper" error:&error])

Вы бы использовали свой собственный URI вместо com.apple.bsd.SMJobBlessHelper.

Все остальные соответствующие строки являются простыми C-функциями. Разбивая это, вы остаетесь с: -

// Obtain rights 
AuthorizationCopyRights(self->_authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL)


//Start the helper
SMJobBless(kSMDomainSystemLaunchd, (CFStringRef)label, self->_authRef, &cfError);

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

Поскольку мне потребовалось много работы и я подумал, что это будет полезно для других, вот мое окончательное рабочее решение. https://www.tweaking4all.com/software-development/lazarus-development/macos-smjobbless-elevated-privileges-lazarus-pascal/

Вы найдете там пример проекта и тонны информации.

Шаги для воспроизведения этого довольно обширны, поэтому здесь краткий обзор:

Я использовал CFMessages для отправки сообщений в Helper Tool, так как у меня не было привязок для NSXPCConnection.

Вспомогательный инструмент должен быть основан на шаблоне Lazarus Pascal "программа" или "простая программа", не может основываться на каком-либо из классов TApplication и не может создавать какие-либо шаги. Для Helper Tool необходимо создать info.plist и launchd.plist, которые должны быть встроены в двоичный файл.

Основным (тестовым) приложением может быть любое приложение Lazarus Pascal, но ему также необходим соответствующий Info.plist, указывающий, что вспомогательному инструменту разрешено запускаться с повышенными привилегиями.

Инструмент Helper и комплект приложений должны быть подписаны действительным идентификатором Apple Developer ID.

Некоторые недостающие привязки должны быть на месте:

const  kSMRightBlessPrivilegedHelper = 'com.apple.ServiceManagement.blesshelper';
function SMJobBless(domain:CFStringRef; executableLabel:CFStringRef; auth:AuthorizationRef; outError:CFErrorRef): boolean; external name '_SMJobBless'; mwpascal; 
var kSMDomainSystemLaunchd: CFStringRef; external name '_kSMDomainSystemLaunchd';

И надлежащие рамки должны быть включены:

{$linkframework ServiceManagement}
{$linkframework Security}
{$linkframework Foundation}
{$linkframework CoreFoundation}
{$calling mwpascal}

И давайте не забудем установить функцию обратного вызова для обработки входящих сообщений.

Надеюсь это кому-нибудь пригодится...:-)

Другие вопросы по тегам