Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Got recipe for cocoa shell on unix app?

Got recipe for cocoa shell on unix app?
Thread Tools
Mac Elite
Join Date: Sep 2000
Location: Norfolk, Va
Status: Offline
Reply With Quote
Mar 2, 2002, 09:33 AM
 
So this has been done a thousand times already, and I'm looking to duplicate it on another tool I use all the time. I have a unix app I run in the terminal, and I'd like to make a cocoa front-end for it, from which I can open/edit/save files, send input/get output from the workhorse of the unix program, and adjust settings.
It sounds like a real app, I know, but I think I'm actually asking for very little. If you think about it, this app doesn't really do anything; all the real work is done in the app somebody else has written. My app is just a nice interface.
So anyway, does anybody know of a tutorial that specifically addresses this, or can walk me through the basics themself? thanks...
you are not your signature
     
Grizzled Veteran
Join Date: Feb 2001
Location: Germany
Status: Offline
Reply With Quote
Mar 2, 2002, 10:34 AM
 
personally, i can recommend two articles on cocoadevcentral:
http://www.cocoadevcentral.com/tutor...w=00000017.php
and http://www.cocoadevcentral.com/tutor...w=00000024.php

and i think i've seen something on stepwise.com; basically, any halfway decent documentation on nstask will do, it's quite straightforward.
     
Dedicated MacNNer
Join Date: Jun 2000
Location: Dundas, Ontario, Canada
Status: Offline
Reply With Quote
Mar 2, 2002, 03:01 PM
 
Yeah, seb2 is right. Those tutorials from CocoaDevCentral were very useful. If all you need to do is run and communicate with those apps the NSTask will be all you need. If you need to launch anything as root, however, it gets a little more difficult. I can post some code for using the security framework if you need that, too.

Good luck,
Jeff.
Spectral Class
"Shedding Light on Innovation"
     
Forum Regular
Join Date: Jan 2002
Location: New York
Status: Offline
Reply With Quote
Mar 2, 2002, 04:49 PM
 
Apocalypse PLEASE post some example code, I've never gotten the Security framework stuff to work
     
Junior Member
Join Date: Nov 2000
Location: Manhattan
Status: Offline
Reply With Quote
Mar 3, 2002, 08:26 PM
 
I also very much would like to see a good example of authorizing a wrapped program to run with root privs; Apocalypse, please post this.

-m
     
Dedicated MacNNer
Join Date: Jun 2000
Location: Dundas, Ontario, Canada
Status: Offline
Reply With Quote
Mar 4, 2002, 12:37 AM
 
Well, here is part of my security abstraction layer. It probably could be cleaner but I don't have the time to fix it up.

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>

AuthorizationRef authRef;

- (void)createEnv
{
AuthorizationRights tempRight;
AuthorizationFlags tempFlag;
OSStatus temperr = <font color = blue>0</font>;
tempRight.count=<font color = blue>0</font>;
tempRight.items = NULL;
authRef=NULL;
tempFlag = kAuthorizationFlagDefaults;
temperr = AuthorizationCreate(&tempRight, kAuthorizationEmptyEnvironment, tempFlag, &authRef);
}

- (BOOL)authorizeThischar *)pathy
{
OSStatus authErr = <font color = blue>0</font>;
AuthorizationRights righty;
AuthorizationFlags flagy;
AuthorizationItem thingy[<font color = blue>1</font>];

thingy[<font color = blue>0</font>].name=kAuthorizationRightExecute;
thingy[<font color = blue>0</font>].value=pathy;
thingy[<font color = blue>0</font>].valueLength=strlen(pathy);
thingy[<font color = blue>0</font>].flags=<font color = blue>0</font>;
righty.count=<font color = blue>1</font>;
righty.items = thingy;
flagy = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
authErr = AuthorizationCopyRights(authRef,&righty, kAuthorizationEmptyEnvironment, flagy, NULL);
return (errAuthorizationSuccess==authErr); <font color = brown>//this should remove a branch and make the code more efficient</font>
}

- (void)loseSecurity
{
AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
}

-(int)launchSecureNSString *)path withArgsNSArray *)args
<font color = brown>//this is used to create a new secure task with the associated path and argument array.</font>
<font color = brown>//return: an integer that represents the task number</font>
{
OSStatus err =<font color = blue>0</font>;
FILE* pipey;
char *pathy;
char *argt[<font color = blue>4</font>];
int counter;
char *temparg = malloc(sizeof(temparg));

<font color = brown>//first make sure that we are looking at a valied binary (ie: not with trailing '/')</font>
if([[path substringFromIndex[path length]<font color = blue>-1</font>)] isEqualToString:<font color = orange>@"/"</font>]){
<font color = brown>//we are looking at a directory (most likely another method decided that there are no valid binaries in this bundle)</font>
return <font color = blue>-2</font>; <font color = brown>//this code is different than the usual erro (<font color = blue>-1</font>) since it is slightly different</font>
}
for(counter=<font color = blue>0</font>;counter&lt;[args count];counter++){
[[args objectAtIndex:counter] getCString:temparg];
argt[counter]=temparg;
<font color = brown>// NSLog(<font color = orange>@"Logging number %d: %s"</font>, counter, temparg);</font>
temparg = malloc(sizeof(temparg));
}
argt[counter]=NULL;
<font color = brown>// [path getCString:temparg];//periodic error here</font>
pathy = [path cString];<font color = brown>//temparg; //this line is supposed to create a qualifier warning (???)</font>
output=[NSFileHandle alloc]; <font color = brown>//why is this here when it is never used?</font>
[self createEnv];<font color = brown>//create the environment</font>
if (![self authorizeThisathy]){
return <font color = blue>-1</font>;<font color = brown>//error code</font>
}

err = AuthorizationExecuteWithPrivileges(authRef, pathy, <font color = blue>0</font>, argt, &pipey);
if(err){
return <font color = blue>-1</font>;
}

<font color = brown>//I am going to try this without losing the security</font>
<font color = brown>//[self loseSecurity];</font>

<font color = brown>//right before we get out of here lets free up the memory</font>
free(temparg);
for(counter=<font color = blue>0</font>;counter&lt;[args count];counter++){
free(argt[counter]);
}
return <font color = blue>0</font>;<font color = brown>//replace this with something better later</font>
}

</font>[/code]


Given that code, you should be able to just call [self launchSecureathToTool withArgs:argumentArray]

This is a snippet from "Skeleton Key" which is a rather popular program my company makes. We are planning to release the entire source code soon.

Hope you guys find that useful,
Jeff.
Spectral Class
"Shedding Light on Innovation"
     
Junior Member
Join Date: Nov 2000
Location: Manhattan
Status: Offline
Reply With Quote
Mar 4, 2002, 10:19 AM
 
Apoc, very useful (much cleaner than other implementations I have seen); but it still doesn't solve the two biggest problems I am having. Any idea about these two suckers?:

1. Passing environment variables. Normally you can do this in NSTask setEnvironment:NSDictionary*)dictWithEnvVars. I don't see a similar way to implement this through AuthorizationExecuteWithPrivileges(). If you are calling binaries which resides in your bundle, you sometimes NEED environment variables for it to find support files properly.

2. Is there a simple way to get the FILE* type file-handler to convert into a NSFileHander? Using "mr. buffer overflow" ('fread') for a C file handler seems really inflexible compared to using NSFileHandler availableData:, and I can't for the life of me figure out a good (and safe!) way to do the equivalent of a "while ([NSData data = [NSFileHandler availableData:] length])" loop to pipe the output of the subprocess and provide instant feedback to the user for a process which make take a long time and have a lot of output.
(Also, by default does the FILE* handler take both stdout and stderr?)

3. Why oh why oh why didn't Apple just allow us to have authorized NSTasks? That would make everything about a jillion times simpler.
     
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
Mar 4, 2002, 01:04 PM
 
Originally posted by matthewmodern:
<STRONG>1. Passing environment variables. Normally you can do this in NSTask setEnvironment:NSDictionary*)dictWithEnvVars. I don't see a similar way to implement this through AuthorizationExecuteWithPrivileges(). If you are calling binaries which resides in your bundle, you sometimes NEED environment variables for it to find support files properly.</STRONG>
AEWP() is designed for installers, there are several shortcomings with it. Instead use a self-repairing app with a setuid root tool. See AuthSample (http://developer.apple.com/samplecode) and the Authorization Services draft reference (developer.apple.com/techpubs -&gt; OS X -&gt; Core Services, I think).

Also, why do you need env vars? Won't arguments do?

<STRONG>3. Why oh why oh why didn't Apple just allow us to have authorized NSTasks? That would make everything about a jillion times simpler.</STRONG>
Exactly the reason you gave. You don't want everybody and their mother doing authorized tasks on your computer!

Seriously though, if you have a self-repairing setuid tool you can probably use NSTask to launch it.
     
Junior Member
Join Date: Nov 2000
Location: Manhattan
Status: Offline
Reply With Quote
Mar 4, 2002, 01:46 PM
 
Originally posted by Angus_D:<STRONG>
Also, why do you need env vars? Won't arguments do?</STRONG>
Well, unless you a wrapping a BSD tool which doesn't provide arguments for the option (as is my current case).

I will look into the setuid root method.. the Apple AuthTool example seemed a bit over my head (and poorly documented), and also seemed to imply that you put the authorization and self-repair code inside the wrapped tool itself.. not an option if you are wrapping a precompiled tool. I'm sure there is a way to have a program that setuids a separate binary, but I don't know how to go about doing this (especially since while I know the Cocoa framework, I am not a traditional C/Unix programmer).

Exactly the reason you gave. You don't want everybody and their mother doing authorized tasks on your computer!
Well, authorized tasks by their nature require the users to authenticate for access. So its not like by making this more difficult for programmers Apple is enforcing better security. Rather, quite the opposite, since it seems likely that programmers will then make mistakes that could cause potential security leaks. I'm sure we can all agree that arbitrarily granting setuid root to a binary executable included in the application bundle is NOT good security practice in the long run (especially without any sort of digital 'signature' checking).
     
Junior Member
Join Date: Nov 2000
Location: Manhattan
Status: Offline
Reply With Quote
Mar 4, 2002, 01:56 PM
 
Examining the comments in the authTool sample code another huge problem with bundled setuid apps appears.

/* The tool could disappear from inside the application's package if a user tries to copy the application. Currently, the Finder will complain that it doesn't have permission to copy the tool and if the user decides to go ahead with the copy, the application gets copied without the tool inside. At this point, you should recommend that the user re-install the application. */
If you use that method, the user can't copy/move the application. That's not exactly the Macintosh way.
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 12:12 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2