STPrivilegedTask запрашивает пароль для каждой задачи
Я хотел бы начать много NSTasks, которые требуют прав root, я обнаружил, что должен использовать Apple Authorization Kit, и я нашел STPrivilegedTask, который предназначен для этого.
Дело в том, что когда я запускаю STPrivilegedTask, он будет запрашивать у меня пароль root каждый раз. Есть ли способ ввести пароль root для первой привилегированной задачи, а затем для других задач приложение будет помнить пароль root, поэтому пользователю не нужно будет вводить пароль снова и снова и снова?
Ответы
Ответ 1
В зависимости от вашего варианта использования вы можете быть счастливы, просто заменив инициализацию authorizationRef
в STPrivilegedTask -launch
на что-то вроде...
// create authorization reference
static AuthorizationRef authorizationRef = NULL;
@synchronized(self) {
if (!authorizationRef) {
err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
if (err != errAuthorizationSuccess) { return err; }
}
}
... и затем удалив AuthorizationFree
:
// free the auth ref
AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
Это позволит вам запускать задачи без приглашения пароля для пять минут.
Если вам нужно больше управления, создайте Command Line Tool
in Xcode
, который выполняет нужные команды, используя обычные вызовы NSTask
.
Когда вы запускаете инструмент с помощью STPrivilegedTask
или AuthorizationExecuteWithPrivileges
, команды NSTask
будут запускаться с правами администратора (euid = 0
).
SMJobBless - это способ запуска инструмента в будущем - особенно если вам нужно выполнять привилегированные операции на регулярной основе, без запроса для пароля.
Это намного сложнее, чтобы сделать это правильно, используя AuthorizationExecuteWithPrivileges
.
Примечания к SMJobBless
SMJobBless
запрашивает пароль и устанавливает помощника.
Когда вы разговариваете с помощником, запрос на ввод пароля не будет.
собственный пример Apple, это довольно запутанно, но есть other примеры.
Некоторые страницы предполагают, что только ваше приложение разрешено разговаривать с вашим помощником. Apple ничего не говорит. После того, как помощник установлен, я уверен, любой может поговорить с ним.
Возможно, вы могли бы обеспечить соблюдение требований подписи кода (PROPERTY LISTS
раздела этого документа), но я не смог найти примеров, которые сделайте это.
Я использовал AuthorizationExecuteWithPrivileges
пару лет назад для установки демона launchd
, но мне еще предстоит запутать себя с SMJobBless
.
Ответ 2
Привет, я нашел некоторые проблемы для этой проблемы. Здесь я перечисляю все шаги, надеюсь, кто-то столкнутся с одной проблемой:
Первый шаг на запуск приложения, чтобы проверить, есть ли у нашего приложения права администратора.
// run a terminal command for admin privileges available or not
NSString* csPluginDirectoryPath = [NSString stringWithFormat:@"%@/supportFiles",[CommonMethods getResourceFolderPath]];
NSString* tapPathCommand = [NSString stringWithFormat:@"chown root %@/tap.kext", csPluginDirectoryPath];
//if app has not admin privileges then it return error text
// if application has admin privileges it will return empty message
NSString* csErrorMessage = [self ExecuteSudoTerminalCommand:tapPathCommand];
if(csErrorMessage && [csErrorMessage length] > 2)
{
// go for admin privileges
[self launchHelperTool];
}
-(NSString*) ExecuteSudoTerminalCommand:(NSString*) terminalCommands
{
NSString* resultOfScript = @"";
NSString* csScript = [NSString stringWithFormat:@"do shell script \"%@\"",terminalCommands];
NSDictionary* errors = [NSDictionary dictionary];
NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource:csScript];
NSAppleEventDescriptor* descriptor = [appleScript executeAndReturnError:&errors];
if(descriptor == nil)
{
resultOfScript = [errors objectForKey:@"NSAppleScriptErrorMessage"];
}
else
resultOfScript = [descriptor stringValue];
return resultOfScript;
}
-(void) launchHelperTool
{
helperToolPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Chameleon VPN"];
NSBundle *thisBundle = [NSBundle mainBundle];
NSString* commonDictionaryPath = [[thisBundle bundleURL] absoluteString];
commonDictionaryPath = [commonDictionaryPath substringToIndex:commonDictionaryPath.length - 1];
commonDictionaryPath = [commonDictionaryPath stringByReplacingOccurrencesOfString:@"file:/" withString:@""];
NSArray *args = [NSArray arrayWithObjects:helperToolPath, commonDictionaryPath, nil];
NSTask *task = [NSTask launchedTaskWithLaunchPath:helperToolPath arguments:args];
[task waitUntilExit];
int status = [task terminationStatus];
if (status == 0)
{
NSLog(@"Task succeeded.");
}
else
{
NSLog(@"Task failed.");
exit(0);
}
}