Droits administrateur

01:17 modifié dans API AppKit #1
Salut à  tous,

J'ai créée une application qui se charge de maintenant à  jour + de 800 logiciels.
Cependant j'avais oublié quelque chose ! Le cas où un utilisateur dit "normal" (sans droits admin) veut faire une mise à  jour sur un logiciel qui nécessite les droits admin pour être supprimé, car je supprime l'ancienne version et remplace par la nouvelle évidemment.

J'ai donc fouillé un peu le code de Sparkle et j'ai trouvé mon bonheur. Enfin à  moitié. ça marche plutôt bien, ça fait ce que je voulais que ça fasse. Sauf que j'aimerai que mon application demande les droits administrateur au lancement de l'application et qu'il les conserve tout le temps, jusqu'à  l'extinction de mon application.

Donc voilà  mes 2 questions :
- Comment détecter si l'utilisateur actuel a les droits administrateur ou non ?
- Si il n'a pas les droits, afficher un panneau qui demande le nom d'utilisateur + mdp de l'administrateur. Et ainsi pouvoir effectuer des manipulation de fichiers sans devoir retaper le mot de passe à  chaque fois.

J'ai pas trop compris comment afficher un panneau de ce genre et conserver les droits.. j'ai l'impression qu'en fait c'est pas sorcier mais je vois vraiment pas comment.


Merci d'avance ;)

Réponses

  • schlumschlum Membre
    01:17 modifié #2
    Il faut utiliser les frameworks Security et Security Foundation

    Si tu veux une interface avec le petit cadenas, Security Interface

    Par contre, la seule chose qu'on peut faire avec les droits admins, c'est lancer un autre exécutable ; le processus en cours ne peut obtenir de " promotion ".

    J'en ai parlé ici.


    Sinon, c'est comme "sudo", donc limité dans le temps ; si tu veux le garder plus longtemps, il faut jouer avec le trousseau (je ne sais pas comment ça par contre).
  • 01:17 modifié #3
    dans 1218386145:

    Il faut utiliser les frameworks Security et Security Foundation

    Si tu veux une interface avec le petit cadenas, Security Interface

    Par contre, la seule chose qu'on peut faire avec les droits admins, c'est lancer un autre exécutable ; le processus en cours ne peut obtenir de " promotion ".

    J'en ai parlé ici.

    Sinon, c'est comme "sudo", donc limité dans le temps ; si tu veux le garder plus longtemps, il faut jouer avec le trousseau (je ne sais pas comment ça par contre).


    Super merci 
  • fouffouf Membre
    01:17 modifié #4
    Moi aussi j'ai eu a utiliser le code de Sparkle pour un vieux truc (aussi pour les mises a jour).

    <br />	AuthorizationRef auth = NULL;<br />	OSStatus authStat = errAuthorizationDenied;<br />	while (authStat == errAuthorizationDenied) {<br />		authStat = AuthorizationCreate(NULL,<br />									&nbsp;  kAuthorizationEmptyEnvironment,<br />									&nbsp;  kAuthorizationFlagDefaults,<br />									&nbsp;  &amp;auth);<br />	}<br />
    


    Ce code va t'afficher la fenêtre d'authentification jusqu'au moment où le mdp est bon ou que l'utilisateur a cliqué sur annuler (tu testes authStat).
  • 01:17 modifié #5
    Bon je reviens sur le sujet car je suis face à  un petit problème.
    Mon application va remplacer les fichiers système (du genre les skins du Dock), et pour ça j'ai besoin des autorisations admins.

    Petit problème : Lorsqu'un fichier est manquant !
    Voici le code de Sparkle que j'utilise, ce que je ne pige pas bien c'est tout ce qui est dans "_movePathWithForcedAuthentication:toPath:" qui est appelé si on a besoin des autorisations administrateur :
    <br />- (BOOL)_movePathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst<br />{<br />	NSString *tmp = [[[dst stringByDeletingPathExtension] stringByAppendingString:@&quot;.old&quot;] stringByAppendingPathExtension:[dst pathExtension]];<br />	BOOL res = NO;<br />	struct stat sb;<br />	<br />	<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 />	<br />	char* buf = NULL;<br />	<br />	//if(![[NSFileManager defaultManager] fileExistsAtPath:dst])<br />	//	asprintf(&amp;buf,<br />	//			 &quot;mv -f &#092;&quot;$SRC_PATH&#092;&quot; &#092;&quot;$DST_PATH&#092;&quot;&quot;,<br />	//			 sb.st_uid, sb.st_gid);	<br />	//else<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 />	{<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 />		sig_t oldSigChildHandler = signal(SIGCHLD, SIG_DFL);<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 />			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 />		signal(SIGCHLD, oldSigChildHandler);<br />	}<br />	AuthorizationFree(auth, 0);<br />	free(buf);<br />	return res;	<br />}<br /><br />- (BOOL)movePathWithAuthentication:(NSString *)src toPath:(NSString *)dst<br />{<br />	if(![[NSFileManager defaultManager] fileExistsAtPath:dst] &amp;&amp; [[NSFileManager defaultManager] isWritableFileAtPath:[dst stringByDeletingLastPathComponent]]){<br />		BOOL result;<br />		result = [[NSFileManager defaultManager] copyPath:src toPath:dst handler:NULL];<br />		return result;<br />	}else 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] copyPath:src toPath:dst handler:NULL];<br />		return result;<br />	}<br />	else<br />	{<br />		return [self _movePathWithForcedAuthentication:src toPath:dst];<br />	}<br />}<br />
    


    Donc il faudrait que mon code s'adapte au cas où le fichier est inexistant et qu'il le copie bien. J'avais commencé, ce qui est en commentaire dans le code c'est ce que j'ai rajouté pour gérer cette situation, mais ça marche pas, car je suppose que ça n'est pas suffisant et qu'il faut changer d'autres trucs (Schlum, t'es ptête mon sauveur :D)

    En bref, vous l'aurez compris, il me faudrait adapter ce code dans le cas où j'ai des fichiers de destination (dst) inexistants, enfin d'eviter la méthode de suppression.
    Autre problème aussi, c'est que lorsque je remplace par des nouveaux fichiers et que tous les originaux sont bien existants, il me demande le mot de passe autant de fois qu'il y a de fichier à  copier.
  • 01:17 modifié #6
    Bon ben avec fouf on a matté le code du nouveau Sparkle et j'y ai trouvé mon bonheur  :o
  • fouffouf Membre
    01:17 modifié #7
    dans 1219582737:

    Bon ben avec fouf on a matté le code du nouveau Sparkle et j'y ai trouvé mon bonheur  :o

    Oh oui, on a bien maté ...

    Blagues a part, faut regarder la méthode _copy.. (je ne me souviens plus du reste du nom) dans NSFileManager+Authorization.m
  • GreensourceGreensource Membre
    juin 2009 modifié #8
    Je re-ouvre le sujet pour une toute petit question. C'est une erreur de link très bête mais je ne la comprend pas.
    J'utilise authentificationCreate(...) donc le seul Framework dont j'ai besoin c'est bien Security?
    Je l'ai donc importé, et pourtant j'ai cette erreur à  la compilation:
    Line Location Tool:0: "_AuthorizationCreate", referenced from:

    Qui il me semble arrive notamment lorsqu'on oubli d'importer un Framework?

    Mais bon ça doit aussi être autre chose puisque là  je l'importe bien.

    [edit] Bon c'est finalement une erreur toute bête, j'avait pas importer le bon framework. J'avais importé SecurityFoundation ::)
  • GreensourceGreensource Membre
    01:17 modifié #9
    Bon du coup j'ai bien avancé grâce notamment à  votre code.
    Il me reste un souci. Certes mon outils se lance bien en mode root mais j'ai besoin de récupérer la valeur du résultat pour savoir si ça c'est bien passer ou pas.
    Or dans la doc de AuthorizationExecuteWithPrivileges, rien vue qui parlais de ça.
    Si je comprend bien c'est un autre Thread qui est lancé, donc il me faudrait un moyen de s'y accrocher. Je sais pas si ça veut dire grand choses ce que je dit ;)
  • schlumschlum Membre
    01:17 modifié #10
    Non, ce n'est pas un thread, c'est un process...
    Pour la communication, il faut un pipe ou de la mémoire partagée.
Connectez-vous ou Inscrivez-vous pour répondre.