2011-07-27 12 views

Respuesta

31

De hecho, AuthorizationExecuteWithPrivileges() ha quedado obsoleto durante mucho tiempo, solo recientemente el archivo de encabezado se ha puesto al día con este hecho.

Puede crear una herramienta de ayuda privilegiada como parte de su aplicación. Puede usar la función ServiceManagement.frameworkSMJobBless() para tener el asistente desplegado en el contexto del sistema launchd: cuando necesita realizar tareas con privilegios, solo debe enviar un mensaje al ayudante con privilegios para que haga ese trabajo.

Hay un poco de complejidad oculta, ya que la aplicación y el ayudante deben declarar la identidad de firma de la otra antes de SMJobBless() cree que se supone que deben usarse juntos, y necesita que el enlazador escriba la el archivo Info.plist de la herramienta auxiliar en el binario. Eso está cubierto por Apple's Documentation y Apple también ha proporcionado a sample project.

que usa SMJobBless() para desplegar su ayudante privilegiado.

+0

Hola, gracias por la respuesta. Si AuthorizationExecuteWithPrivileges() ha quedado obsoleto durante mucho tiempo, ¿debería seguir funcionando? Básicamente, esto dejó de funcionar en mi aplicación desde la actualización de Lion, y supuse que era porque ahora se está marcando como obsoleta ... ¿Debería funcionar de hecho, y mi problema está en otra parte? Muchas gracias – Phill

+4

No debe confiar en 'AuthorizationExecuteWithPrivileges()', es un agujero de seguridad horrendo. La forma de hacer lo que quiere hacer es con 'SMJobBless()'. –

+0

@GrahamLee ¿Y qué hay de usar 'AuthorizationExecuteWithPrivileges' para el instalador? La referencia dice que "debe usar esta función solo para permitir que los instaladores se ejecuten como root y para permitir que una herramienta setuid repare su bit de setuid si se pierde" y la Guía de programación de servicios de autorización sugiere usar esta función para iniciar instaladores (aunque algo desactualizado) . ¿Hay alguna alternativa para iniciar el instalador en aplicaciones simples como la herramienta de línea de comandos? – cody

32

Sé que suena loco, pero esto realmente funciona :

NSDictionary *error = [NSDictionary new]; 
NSString *script = @"do shell script \"whoami > /tmp/me\" with administrator privileges"; 
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:script]; 
if ([appleScript executeAndReturnError:&error]) { 
    NSLog(@"success!"); 
} else { 
    NSLog(@"failure!"); 
} 

Estoy ejecutar un AppleScript de Objective C. La única desventaja es que no se puede obtener privilegios de root permanentes con esto. Le pedirá la contraseña cada vez que ejecute esto.

+5

Mira eso. entonces USTED es 'root' ?! Oh, espera, estoy. No, espera ... _AppleScript is_? Jesús. Eso es ciertamente loco. Lo único que sería más loco es si no pidió su contraseña, lol. –

+0

Intenté usar esto pero nunca me pidió mi contraseña. En su lugar, se saltó a la impresión "¡error!" Cuando imprimí la descripción del error, obtuve esto: "NSAppleScriptErrorMessage =" El nombre de usuario o contraseña del administrador era incorrecto. ";" Esto se encuentra en una aplicación con el sandbox activado ... ¿Alguien tiene sugerencias que funcionen con una aplicación habilitada para sandbox? – ArtOfWarfare

+1

FYI: Como se documenta en la Nota técnica TN2065: realice un script de shell en AppleScript (http://developer.apple.com/library/mac/#technotes/tn2065/_index.html): Use los privilegios de administrador, nombre de usuario y Parámetros de contraseña como este: do shell script "comando" nombre de usuario "me" contraseña "mypassword" con privilegios de administrador – geowar

17

Sobre la base de un gran hallazgo por user950473 he implementado su/su descubrimiento como un método; pensé en compartir el código en caso de que fuera útil.

- (BOOL) runProcessAsAdministrator:(NSString*)scriptPath 
        withArguments:(NSArray *)arguments 
          output:(NSString **)output 
        errorDescription:(NSString **)errorDescription { 

    NSString * allArgs = [arguments componentsJoinedByString:@" "]; 
    NSString * fullScript = [NSString stringWithFormat:@"'%@' %@", scriptPath, allArgs]; 

    NSDictionary *errorInfo = [NSDictionary new]; 
    NSString *script = [NSString stringWithFormat:@"do shell script \"%@\" with administrator privileges", fullScript]; 

    NSAppleScript *appleScript = [[NSAppleScript new] initWithSource:script]; 
    NSAppleEventDescriptor * eventResult = [appleScript executeAndReturnError:&errorInfo]; 

    // Check errorInfo 
    if (! eventResult) 
    { 
     // Describe common errors 
     *errorDescription = nil; 
     if ([errorInfo valueForKey:NSAppleScriptErrorNumber]) 
     { 
      NSNumber * errorNumber = (NSNumber *)[errorInfo valueForKey:NSAppleScriptErrorNumber]; 
      if ([errorNumber intValue] == -128) 
       *errorDescription = @"The administrator password is required to do this."; 
     } 

     // Set error message from provided message 
     if (*errorDescription == nil) 
     { 
      if ([errorInfo valueForKey:NSAppleScriptErrorMessage]) 
       *errorDescription = (NSString *)[errorInfo valueForKey:NSAppleScriptErrorMessage]; 
     } 

     return NO; 
    } 
    else 
    { 
     // Set output to the AppleScript's output 
     *output = [eventResult stringValue]; 

     return YES; 
    } 
} 

Ejemplo de uso:

NSString * output = nil; 
    NSString * processErrorDescription = nil; 
    BOOL success = [self runProcessAsAdministrator:@"/usr/bin/id" 
         withArguments:[NSArray arrayWithObjects:@"-un", nil] 
         output:&output 
         errorDescription:&processErrorDescription]; 


    if (!success) // Process failed to run 
    { 
     // ...look at errorDescription 
    } 
    else 
    { 
     // ...process output 
    } 

Es muy ligeramente hacky, pero en mi humilde opinión es una solución satisfactoria.

+1

Este método falla si hay un espacio en la ruta de la escritura, que es probable si desea ejecutar un script incluido en su paquete de aplicaciones. Para solucionar esto, simplemente cambie el formato cuando configure fullScript en @ "'% @'% @" para que el nombre de la ruta del proceso sea citado. – Jim

+1

Gracias - he arreglado esto en el código. –

+0

Hola, ¿hay alguna manera de agregar el icono de la aplicación en el indicador de contraseña en lugar del archivo en blanco con la solución? – Yann86

6

AuthorizationExecuteWithPrivileges es de hecho obsoleta.
Pero, afortunadamente, hay una nueva forma recomendada de proceder.

A partir de 10.6 existe la nueva API y se recomienda instalar una herramienta de ayuda que realizará la operación con privilegios. Apple proporciona un code sample que demuestra claramente cómo administrarlo.

Asegúrate de revisar readme.txt ya que, contrariamente a la muestra de otro código, hay mucho más que hacer que simplemente descargar el proyecto y ejecutarlo.

De La introducción SMJobBless ejemplo

SMJobBless muestra cómo instalar de forma segura una herramienta auxiliar que lleva a cabo una operación privilegiada y la forma de asociar la herramienta con una aplicación que invoca.

A partir de Snow Leopard, este es el método preferido para la gestión de privilegio escalada en Mac OS X y deben utilizarse en lugar de los anteriores enfoques tales como BetterAuthorizationSample o llamando directamente AuthorizationExecuteWithPrivileges.

SMJobBless utiliza ServiceManagement.framework que se introdujo en Mac OS X v10.6 Snow Leopard.

Fuente: Apple SMJobBless code sample

+1

vergüenza que utilizar SMJobBless necesita un desarrollador de OSX ID pagado Applescript ... –

+0

¿Por qué dices eso? Pude descargar el código de muestra hoy, usando el enlace que proporcioné y una cuenta de desarrollador no pago. – Jean

+3

¿Ya ejecutó un proyecto con éxito? Estaba pidiendo la firma de código de la aplicación con una cuenta de desarrollador de OSX. –

Cuestiones relacionadas