SFAuthorizationView, SFAuthorization, Exécution "root"

schlumschlum Membre
19:02 modifié dans API AppKit #1
Hello !

ça fait 2 jours que je me prend la tête avec les Security Frameworks  :crackboom:-
J'ai un prefPane qui utilise une SFAuthorizationView que j'ai réussi à  configurer aisément en utilisant la doc :

Dans le "awakeFromNib" de mon Contrôleur :
[authView setString:kAuthorizationRightExecute];<br />	[authView setAutoupdate:YES<br />				&nbsp;  interval:5.0];<br />	[authView setDelegate:self];


Les fonctions delegate "authorizationViewDidDeauthorize" et "authorizationViewDidAuthorize" me permettant de mettre à  jour l'interface en activant / désactivant les contrôles devant toucher à  des trucs système.

Donc j'étais plutôt content... jusqu'au moment d'utiliser cette "SFAuthorization" -> grosse prise de tête.
J'ai cherché des exemples, essayé un peu tout, rien à  faire, je n'arrive pas à  exécuter une partie de mon code en euid 0  :'(

Le dernier truc en date que j'ai essayé :
if([authView authorizationState]==SFAuthorizationViewUnlockedState) {<br />	NSLog(@&quot;%d,%d&quot;,getuid(),geteuid());<br />	AuthorizationItem myItems = { kAuthorizationRightExecute, 0, NULL, 0 };<br />	AuthorizationRights myRights = { 1, &amp;myItems };<br />	AuthorizationFlags myFlags = kAuthorizationFlagDefaults|kAuthorizationFlagInteractionAllowed|kAuthorizationFlagPreAuthorize|kAuthorizationFlagExtendRights;<br />	OSStatus myStatus = AuthorizationCopyRights([[authView authorization] authorizationRef],&amp;myRights,NULL,myFlags,NULL);<br />	if(myStatus==errAuthorizationSuccess) {<br />		int uid = seteuid(0);<br />		NSLog(@&quot;%d,%d&quot;,getuid(),geteuid());<br />		if(uid!=-1) {<br />			BOOL res = [@&quot;toto&quot; writeToFile:@&quot;/Users/schlum/Desktop/test/toto&quot;<br />								 atomically:YES];<br />			NSLog(@&quot;%s&quot;,res?&quot;true&quot;:&quot;false&quot;);<br />			seteuid(uid);<br />		} else<br />			NSLog(@&quot;Cannot set euid (%d)&quot;,errno);<br />	} else<br />		NSLog(@&quot;Cannot grant access (%d) !&quot;,myStatus);<br />}


Et si apparemment le "grant access" se passe bien, le "seteuid" foire à  tous les coups.

Alors y a-t-il un autre moyen que d'utiliser "AuthorizationExecuteWithPrivileges" ? (je ne veux pas passer par un utilitaire extérieur !)

Réponses

  • AliGatorAliGator Membre, Modérateur
    février 2008 modifié #2
    J'ai jamais fait mumuse avec ça mais es-tu sûr qu'il faille utiliser "seteuid" ?
    Pour moi ça change le execution-UID de ton propre process, ça. Si tu ne mets même pas la ligne, est-ce que ça marche quand même ? (puisque AuthorizationCopyRights a réussi à  t'attribuier les droits nécessaire à  priori si j'ai tout capté) ?

    En fait c'est l'utilisation du seteuid qui me parrait un peu étrange. Je ne l'aurais même pas utilisé (Mais je le répète je suis pas un spécialiste là  dedans, bien au contraire puisque je n'ai jamais utilisé ça)
    Quand je vois par exemple que dans Ce sample code sur l'ADC ils ne l'utilisent pas (bon ils exécutent un outil avec AutorizationExecuteWithprivileges, il faut pas un writeToFile, mais bon), je me demande si c'est bien la solution.

    A méditer, c'était my two cents.
  • schlumschlum Membre
    19:02 modifié #3
    Le "seteuid" je l'ai ajouté après en désespoir de cause  :'(
    Au début je tentais juste le "writeToFile" qui me renvoyait "false" (le dossier "test" sur mon bureau appartient à  "root" avec les droits 700).
  • schlumschlum Membre
    19:02 modifié #4
    Ah oui, je précise que ceci fonctionne :
    char myToolPath&#91;] = &quot;/usr/bin/touch&quot;;<br />	char *myArguments&#91;] = { &quot;/Users/schlum/Desktop/test/toto&quot;, NULL };<br />	FILE *myCommunicationsPipe = NULL;<br />	<br />	AuthorizationFlags myFlags = kAuthorizationFlagDefaults;<br />	AuthorizationExecuteWithPrivileges([[authView authorization] authorizationRef],myToolPath,myFlags,myArguments,&amp;myCommunicationsPipe);
    


    Je crois que c'est obligatoire de passer par AuthorizationExecuteWithPrivileges  :-\\
    Si quelqu'un a une solution plus pratique...
  • wiskywisky Membre
    février 2008 modifié #5
    Bonjour à  tous,

    Je développe maintenant des outils pour Mac Os X dans le cadre de mon travail !
    Actuellement je travail sur un editeur et table Cron (l'utilitaire de tâche planifier UNIX). Mon gros problème est qu'il faut que le logiciel ai le droit de modifier des fichiers dans les dossiers du système (/var/). Je cherche donc à  faire un self-autorization de l'application.
    Je n'y arrive pas ! Je bute un peut sur l'anglais et j'ai un peut tout essayé.
    Savez vous comment procéder pour faire en sorte de demander le mot de passe administrateur au lancement de l'application ?
    Voici mon code actuel :
    - (int) preAuthorize<br />{<br />	int						err;<br />&nbsp; &nbsp; AuthorizationFlags&nbsp; &nbsp; &nbsp; authFlags;<br /><br /><br />	NSLog (@&quot;MyWindowController: preAuthorize&quot;);<br /><br />	if (_authRef)<br />		return errAuthorizationSuccess;<br />		<br />	NSLog (@&quot;MyWindowController: preAuthorize: ** calling AuthorizationCreate...**&#092;n&quot;);<br />&nbsp; &nbsp; <br />	authFlags = kAuthorizationFlagDefaults;<br />	err = AuthorizationCreate (NULL, kAuthorizationEmptyEnvironment, authFlags, &amp;_authRef);<br />	if (err != errAuthorizationSuccess)<br />		return err;<br /><br />	NSLog (@&quot;MyWindowController: preAuthorize: ** calling AuthorizationCopyRights...**&#092;n&quot;);<br />	<br />	_authItem.name = kAuthorizationRightExecute;<br />	_authItem.valueLength = 0;<br />	_authItem.value = NULL;<br />	_authItem.flags = 0;<br />	_authRights.count = 1;<br />	_authRights.items = (AuthorizationItem*) malloc (sizeof (_authItem));<br />	memcpy (&amp;_authRights.items[0], &amp;_authItem, sizeof (_authItem));<br />	authFlags = kAuthorizationFlagDefaults<br />		| kAuthorizationFlagExtendRights<br />		| kAuthorizationFlagInteractionAllowed<br />		| kAuthorizationFlagPreAuthorize;<br />	err = AuthorizationCopyRights (_authRef, &amp;_authRights, kAuthorizationEmptyEnvironment, authFlags, NULL);<br />	<br />	return err;<br />}<br /><br />- (int) launchAuthPrgm<br />{<br />&nbsp; &nbsp; AuthorizationFlags&nbsp; &nbsp; &nbsp; authFlags;<br />&nbsp; &nbsp; int						err;<br /><br />	// path<br />	NSString * path = [[NSBundle mainBundle] executablePath];<br />&nbsp; &nbsp; if (![[NSFileManager defaultManager] isExecutableFileAtPath: path])<br />		return -1;<br /><br />&nbsp; &nbsp; // auth<br />&nbsp; &nbsp; <br />	if (!_authRef)<br />	{<br />		err = [self preAuthorize];<br />		if (err != errAuthorizationSuccess)<br />			return err;<br />	}<br /><br />&nbsp; &nbsp; // launch<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; NSLog (@&quot;MyWindowController: launchWithPath: ** calling AuthorizationExecuteWithPrivileges...**&#092;n&quot;);<br />&nbsp; &nbsp; authFlags = kAuthorizationFlagDefaults;<br />&nbsp; &nbsp; err = AuthorizationExecuteWithPrivileges (_authRef, [path cString], authFlags, NULL, NULL);&nbsp; <br />&nbsp; &nbsp; if(err==0) [NSApp terminate:self];<br />	<br />&nbsp; &nbsp; return err;<br />}<br />
    


    Dans la fonction init, j'ai mis ceci :
    [self launchAuthPrgm];
    
  • schlumschlum Membre
    19:02 modifié #6
    Actuellement, ce que je sais faire, c'est demander le mot de passe admin et lancer un autre processus en tant que root...
    Par contre, je ne sais pas obtenir une escalade de privilège par le processus en cours.

    Si ça t'intéresse, je peux te donner du code ; sinon, faudra attendre quelqu'un qui s'y connaà®t mieux  :P
  • wiskywisky Membre
    février 2008 modifié #7
    je m'auto répond :
    La solution viens du init il suffit de vérifier si l'exécution est en root !

    if(geteuid()!=0){<br />	[self launchAuthPrgm];<br />}
    



    Je fait la même chose sauf que pour éviter un boucle infini, je vérifie si l'exécution est en root
    <3 <3 <3 <3 <br />
    EDIT:
    Tout le code est là  pour ce que cela intéresse : http://wisky2.blogspot.com/2008/02/autorisation-sur-mac-os-x.html
    C'est inspiré de CBSudo ! Merci CBrant  <3 <3 <3 <3
  • schlumschlum Membre
    19:02 modifié #8
    ça utilise "AuthorizationExecuteWithPrivileges"... Rien de nouveau sous les étoiles donc ; pas d'escalade de privilège pour le processus en cours  :(
  • wiskywisky Membre
    19:02 modifié #9
    Si te observe bien, le plus grand nombre de logiciel qui demande une escalade de droit font comme ça.
    Mis à  part les logiciels made in Apple !
  • ChachaChacha Membre
    19:02 modifié #10
    dans 1203330791:

    Si te observe bien, le plus grand nombre de logiciel qui demande une escalade de droit font comme ça.
    Mis à  part les logiciels made in Apple !

    J'ai eu les mêmes questions, et finalement il semble que la réponse soit claire :
    http://lists.apple.com/archives/cocoa-dev/2004/Dec/msg01004.html
    you can't elevate the privileges of a running task


    Du coup, à  quoi sert ce fameux scénario "Simple, Self-Restricted Applications" ? Je pense que c'est pour rajouter une couche d'authentification "logique", qui ne s'appuie absolument pas sur les droits du système, mais sur des choix du développeur qui veut gérer des utilisateurs "logiques" de son application.

    +
    Chacha
  • schlumschlum Membre
    19:02 modifié #11
    Du coup, vu qu'on ne peut pas obtenir un privilège supérieur au niveau de l'application, la question se pose de savoir comment on peut lancer quand même un autre processus avec des privilèges supérieurs.

    Je suppose qu'il passe par un processus tiers tournant en root qui joue en quelque sorte un rôle de serveur local webservice avec authentification.
  • AliGatorAliGator Membre, Modérateur
    avril 2008 modifié #12
    dans 1207050383:

    Du coup, vu qu'on ne peut pas obtenir un privilège supérieur au niveau de l'application, la question se pose de savoir comment on peut lancer quand même un autre processus avec des privilèges supérieurs.

    Je suppose qu'il passe par un processus tiers tournant en root qui joue en quelque sorte un rôle de serveur local webservice avec authentification.
    Ben là  du coup ça revient à  lancer une NSTask (avec les nouveaux privilèges supérieurs à  ton appli), ce qu'on sait déjà  faire ([tt]AuthorizationExecuteWithPrivileges:[/tt]) :)

    Le seul truc que l'on sait pas faire c'est monter en privilèges notre appli déjà  lancée, pour qu'elle puisse écrire (après avoir acquis les privilèges avec SFAutorization) dans un répertoire nécessitant certains droits. En gros on est obligé de créer une NSTask avec les nouveaux privilèges pour faire ça, on peut pas le faire directement depuis notre task/appli en cours.
  • schlumschlum Membre
    19:02 modifié #13
    dans 1207064262:

    dans 1207050383:

    Du coup, vu qu'on ne peut pas obtenir un privilège supérieur au niveau de l'application, la question se pose de savoir comment on peut lancer quand même un autre processus avec des privilèges supérieurs.

    Je suppose qu'il passe par un processus tiers tournant en root qui joue en quelque sorte un rôle de serveur local webservice avec authentification.
    Ben là  du coup ça revient à  lancer une NSTask (avec les nouveaux privilèges supérieurs à  ton appli), ce qu'on sait déjà  faire ([tt]AuthorizationExecuteWithPrivileges:[/tt]) :)

    Le seul truc que l'on sait pas faire c'est monter en privilèges notre appli déjà  lancée, pour qu'elle puisse écrire (après avoir acquis les privilèges avec SFAutorization) dans un répertoire nécessitant certains droits. En gros on est obligé de créer une NSTask avec les nouveaux privilèges pour faire ça, on peut pas le faire directement depuis notre task/appli en cours.


    Ah ben oui, mais pour lancer un process avec des privilèges, ça s'invente pas, il faut les avoir, d'où mon interrogation  ;)
  • fouffouf Membre
    19:02 modifié #14
    Salut.

    Voila un vieux bout de code que j'avais utiliser pour je ne sais quoi et que j'ai taxé de je ne sais où (bon, ya des chances que ca vienne du code de Sparkle, mais je suis pas sûr). Il s'agit de code pour déplacer un fichier avec eventuellement les autorisations.

    //<br />//&nbsp; NSFileManager+Authentication.m<br />//&nbsp; Sparkle<br />//<br />//&nbsp; Created by Andy Matuschak on 3/9/06.<br />//&nbsp; Copyright 2006 Andy Matuschak. All rights reserved.<br />//<br /><br />// This code based on generous contribution from Allan Odgaard. Thanks, Allan!<br />//<br /><br />#import &quot;NSFileManager+Authentication.h&quot;<br /><br />#import &quot;sys/stat.h&quot;<br />#import &lt;Security/Security.h&gt;<br /><br />#import &lt;unistd.h&gt;<br />#import &lt;sys/stat.h&gt;<br />#import &lt;dirent.h&gt;<br /><br />@implementation NSFileManager (SUAuthenticationAdditions)<br /><br />- (BOOL)currentUserOwnsPath:(NSString *)oPath<br />{<br />	char *path = (char *)[oPath fileSystemRepresentation];<br />	unsigned int uid = getuid();<br />	bool res = false;<br />	struct stat sb;<br />	if(stat(path, &amp;sb) == 0)<br />	{<br />		if(sb.st_uid == uid)<br />		{<br />			res = true;<br />			if(sb.st_mode &amp; S_IFDIR)<br />			{<br />				DIR* dir = opendir(path);<br />				struct dirent* entry = NULL;<br />				while(res &amp;&amp; (entry = readdir(dir)))<br />				{<br />					if(strcmp(entry-&gt;d_name, &quot;.&quot;) == 0 || strcmp(entry-&gt;d_name, &quot;..&quot;) == 0)<br />						continue;<br />					<br />					char descend[strlen(path) + 1 + entry-&gt;d_namlen + 1];<br />					strcpy(descend, path);<br />					strcat(descend, &quot;/&quot;);<br />					strcat(descend, entry-&gt;d_name);<br />					res = [self currentUserOwnsPath:[NSString stringWithUTF8String:descend]];<br />				}<br />				closedir(dir);<br />			}<br />		}<br />	}<br />	return res;<br />}<br /><br />- (BOOL)_movePathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst<br />{<br />	NSString *tmp = [[src stringByDeletingPathExtension] stringByAppendingString:[[NSProcessInfo processInfo] globallyUniqueString]];<br />	BOOL res = NO;<br />	struct stat sb;<br />	if((stat([src UTF8String], &amp;sb) != 0) || (stat([tmp UTF8String], &amp;sb) == 0) || stat([dst UTF8String], &amp;sb) != 0)<br />		return false;<br />	<br />	char* buf = NULL;<br />	asprintf(&amp;buf,<br />			 &quot;mv -f &#092;&quot;$DST_PATH&#092;&quot; &#092;&quot;$TMP_PATH&#092;&quot; &amp;&amp; &quot;<br />			 &quot;mv -f &#092;&quot;$SRC_PATH&#092;&quot; &#092;&quot;$DST_PATH&#092;&quot; &amp;&amp; &quot;<br />			 &quot;rm -rf &#092;&quot;$TMP_PATH&#092;&quot; &amp;&amp; &quot;<br />			 &quot;chown -R %d:%d &#092;&quot;$DST_PATH&#092;&quot;&quot;,<br />			 sb.st_uid, sb.st_gid);<br />	<br />	if(!buf)<br />		return false;<br />	<br />	AuthorizationRef auth;<br />	//if(AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &amp;auth) == errAuthorizationSuccess)<br />	if(AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagExtendRights, &amp;auth) == errAuthorizationSuccess)<br />	{<br />		setenv(&quot;SRC_PATH&quot;, [src UTF8String], 1);<br />		setenv(&quot;DST_PATH&quot;, [dst UTF8String], 1);<br />		setenv(&quot;TMP_PATH&quot;, [tmp UTF8String], 1);<br />		<br />		char const* arguments&#91;] = { &quot;-c&quot;, buf, NULL };<br />		if(AuthorizationExecuteWithPrivileges(auth, &quot;/bin/sh&quot;, kAuthorizationFlagDefaults, (char**)arguments, NULL) == errAuthorizationSuccess)<br />		{<br />			NSLog(@&quot;great&quot;);<br />			int status;<br />			int pid = wait(&amp;status);<br />			if(pid != -1 &amp;&amp; WIFEXITED(status) &amp;&amp; WEXITSTATUS(status) == 0)<br />				res = YES;<br />		}<br />	}<br />	free(buf);<br />	return res;	<br />}<br /><br />- (BOOL)movePathWithAuthentication:(NSString *)src toPath:(NSString *)dst<br />{<br />	if ([[NSFileManager defaultManager] isWritableFileAtPath:dst] &amp;&amp; [[NSFileManager defaultManager] isWritableFileAtPath:[dst stringByDeletingLastPathComponent]])<br />	{<br />		int tag = 0;<br />		BOOL result = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:[dst stringByDeletingLastPathComponent] destination:@&quot;&quot; files:[NSArray arrayWithObject:[dst lastPathComponent]] tag:&amp;tag];<br />		result &amp;= [[NSFileManager defaultManager] movePath:src toPath:dst handler:NULL];<br />		return result;<br />	}<br />	else<br />	{<br />		return [self _movePathWithForcedAuthentication:src toPath:dst];<br />	}<br />}<br /><br />@end<br />
    
  • schlumschlum Membre
    19:02 modifié #15
    Ils lancent "sh" avec les privilèges qu'il faut... Rien de nouveau sous le soleil  ;)
  • AliGatorAliGator Membre, Modérateur
    19:02 modifié #16
    dans 1207071880:

    Ils lancent "sh" avec les privilèges qu'il faut... Rien de nouveau sous le soleil  ;)
    Ben oui mais qu'est ce que tu veux de plus ?
    - L'appli en cours (ton appli que tu codes quoi) ne peux pas faire d'escalade de privilèges, même avec SFAutorization.
    - La seule façon d'accéder à  qqch avec des privilèges suppérieurs à  l'application (task) courrante, c'est de lancer une nouvelle NSTask (qui lance sh, mv, cp, cat, ou l'utilitaire dont tu as besoin) et de l'executer via SFAutorization, après avoir demandé l'autorisation (mot de passe admin), donc via AuthorizationCreate puis AuthorizationExecuteWithprivileges.

    Y'a pas d'autre moyen... puisque faire faire directement à  ton application une action pour laquelle elle n'a pas les droits, c'est pas possible... même avec SFAuth.
  • schlumschlum Membre
    19:02 modifié #17
    Ah ben ça fait longtemps que je me suis résolu à  créer un programme externe et à  faire exactement comme ça  :P
Connectez-vous ou Inscrivez-vous pour répondre.