Fix a typo in SUAtomFeedParser.
[sparkle2.git] / BLAuthentication / BLAuthentication.m
blob305ab1d1cebe89e6cc9667e14a97b119662b6c0b
1 //  ======================================================================      //
2 //  BLAuthentication.h                                                                                                          //
3 //                                                                                                                                              //
4 //  Last Modified on Tuesday April 24 2001                                                                      //
5 //  Copyright 2001 Ben Lachman                                                                                          //
6 //                                                                                                                                                      //
7 //      Thanks to Brian R. Hill <http://personalpages.tds.net/~brian_hill/>             //
8 //  ======================================================================      //
10 #import "BLAuthentication.h"
11 #import <Security/AuthorizationTags.h>
13 @implementation BLAuthentication
15 // returns an instace of itself, creating one if needed
16 + sharedInstance {
17     static id sharedTask = nil;
18     if(sharedTask==nil) {
19         sharedTask = [[BLAuthentication alloc] init];
20     }
21     return sharedTask;
24 // initializes the super class and sets authorizationRef to NULL 
25 - (id)init {
26     self = [super init];
27     authorizationRef = NULL;
28     return self;
31 // deauthenticates the user and deallocates memory
32 - (void)dealloc {
33     [self deauthenticate];
34     
35     [super dealloc];
38 //============================================================================
39 //      - (BOOL)isAuthenticated:(NSArray *)forCommands
40 //============================================================================
41 // Find outs if the user has the appropriate authorization rights for the 
42 // commands listed in (NSArray *)forCommands.
43 // This should be called each time you need to know whether the user
44 // is authorized, since the AuthorizationRef can be invalidated elsewhere, or
45 // may expire after a short period of time.
47 - (BOOL)isAuthenticated:(NSArray *)forCommands {
48         AuthorizationRights rights;
49         AuthorizationRights *authorizedRights;
50         AuthorizationFlags flags;
51         
52         int numItems = [forCommands count];
53         AuthorizationItem *items = malloc( sizeof(AuthorizationItem) * numItems );
54         char paths[20][128]; // only handles upto 20 commands with paths upto 128 characters in length
55         
56         OSStatus err = 0;
57         BOOL authorized = NO;
58         int i = 0;
60         if(authorizationRef==NULL) {
61                 rights.count=0;
62                 rights.items = NULL;
63                 
64                 flags = kAuthorizationFlagDefaults;
65                 
66                 err = AuthorizationCreate(&rights, kAuthorizationEmptyEnvironment, flags, &authorizationRef);
67         }
68         
69         if( numItems < 1 ) {
70                 return authorized;
71         }
73         while( i < numItems && i < 20 ) {
74                  [[forCommands objectAtIndex:i] getCString:paths[i]];
75                 
76                 items[i].name = kAuthorizationRightExecute;
77                 items[i].value = paths[i];
78                 items[i].valueLength = [[forCommands objectAtIndex:i] cStringLength];
79                 items[i].flags = 0;
80                 
81                 i++;
82         }
83         
84     rights.count = numItems;
85     rights.items = items;
86     
87     flags = kAuthorizationFlagExtendRights;
88     
89     err = AuthorizationCopyRights(authorizationRef, &rights, kAuthorizationEmptyEnvironment, flags, &authorizedRights);
91     authorized = (errAuthorizationSuccess==err);
93         if(authorized)
94                 AuthorizationFreeItemSet(authorizedRights);
95         
96         free(items);
97         
98     return authorized;
101 //============================================================================
102 //      - (void)deauthenticate
103 //============================================================================
104 // Deauthenticates the user by freeing their authorization.
106 - (void)deauthenticate {
107     if(authorizationRef) {
108         AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights);
109         authorizationRef = NULL;
110         [[NSNotificationCenter defaultCenter]postNotificationName:BLDeauthenticatedNotification object:self];
111     }
114 //============================================================================
115 //      - (BOOL)fetchPassword:(NSArray *)forCommands
116 //============================================================================
117 // Adds rights for commands specified in (NSArray *)forCommands.
118 // Commands should be passed as a NSString comtaining the path to the executable. 
119 // Returns YES if rights were gained
121 - (BOOL)fetchPassword:(NSArray *)forCommands {
122         AuthorizationRights rights;
123         AuthorizationRights *authorizedRights;
124         AuthorizationFlags flags;
125         
126         int numItems = [forCommands count];
127         AuthorizationItem *items = malloc( sizeof(AuthorizationItem) * numItems );
128         char paths[20][128];
129         
130         OSStatus err = 0;
131         BOOL authorized = NO;
132         int i = 0;
133         
134         if( numItems < 1 )
135                 return authorized;
136         
137         while( i < numItems && i < 20 ) {
138                 [[forCommands objectAtIndex:i] getCString:paths[i]];
139                 
140                 items[i].name = kAuthorizationRightExecute;
141                 items[i].value = paths[i];
142                 items[i].valueLength = [[forCommands objectAtIndex:i] cStringLength];
143                 items[i].flags = 0;
144                 
145                 i++;
146         }
147         
148         rights.count = numItems;
149         rights.items = items;
150         
151         flags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
152         
153         err = AuthorizationCopyRights(authorizationRef, &rights, kAuthorizationEmptyEnvironment, flags, &authorizedRights);
154         
155         authorized = (errAuthorizationSuccess == err);
156         
157         if(authorized) {
158                 AuthorizationFreeItemSet(authorizedRights);
159                 [[NSNotificationCenter defaultCenter] postNotificationName:BLAuthenticatedNotification object:self];
160         }                                                    
162         free(items);
163         
164         return authorized;
167 //============================================================================
168 //      - (BOOL)authenticate:(NSArray *)forCommands
169 //============================================================================
170 // Authenticates the commands in the array (NSArray *)forCommands by calling 
171 // fetchPassword.
173 - (BOOL)authenticate:(NSArray *)forCommands {
174         if( ![self isAuthenticated:forCommands] ) {
175         [self fetchPassword:forCommands];
176         }
177         
178         return [self isAuthenticated:forCommands];
182 //============================================================================
183 //      - (int)getPID:(NSString *)forProcess
184 //============================================================================
185 // Retrieves the PID (process ID) for the process specified in 
186 // (NSString *)forProcess.
187 // The more specific forProcess is the better your accuracy will be, esp. when 
188 // multiple versions of the process exist. 
190 - (int)getPID:(NSString *)forProcess {
191         FILE* outpipe = NULL;
192         NSMutableData* outputData = [NSMutableData data];
193         NSMutableData* tempData = [[NSMutableData alloc] initWithLength:512];
194         NSString *commandOutput = nil;
195         NSString *scannerOutput = nil;
196         NSString *popenArgs = [[NSString alloc] initWithFormat:@"/bin/ps -axwwopid,command | grep \"%@\"",forProcess];
197         NSScanner *outputScanner = nil;
198         NSScanner *intScanner = nil;
199         int pid = 0;
200         int len = 0;
201     
202     outpipe = popen([popenArgs cString],"r");
204         [popenArgs release];
206         if(!outpipe) {
207         NSLog(@"Error opening pipe: %@",forProcess);
208         NSBeep();
209         return nil;
210     }
211         
212         do {
213         [tempData setLength:512];
214         len = fread([tempData mutableBytes],1,512,outpipe);
215         if( len > 0 ) {
216             [tempData setLength:len];
217             [outputData appendData:tempData];        
218                 }
219         } while(len==512);
220     
221         [tempData release];
223         pclose(outpipe);
224         
225         commandOutput = [[NSString alloc] initWithData:outputData encoding:NSASCIIStringEncoding];    
226         
227         if( [commandOutput length] > 0 ) {
228                 outputScanner = [NSScanner scannerWithString:commandOutput];
229                 
230                 [commandOutput release];
231                 
232                 [outputScanner setCharactersToBeSkipped:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
233                 
234                 [outputScanner scanUpToString:forProcess intoString:&scannerOutput];
235                 
236                 if( [scannerOutput rangeOfString:@"grep"].length != 0 ) {
237                         return 0;
238                 }
239                 
240                 intScanner = [NSScanner scannerWithString:scannerOutput];
241                 
242                 [intScanner scanInt:&pid];
243                 
244                 if( pid ) {
245                         return pid;
246                 }
247                 else {
248                         return 0;
249                 }
250         }
251         else {
252                 [commandOutput release];
254                 return 0;
255         }
259 //============================================================================
260 //      -(void)executeCommand:(NSString *)pathToCommand withArgs:(NSArray *)arguments
261 //============================================================================
262 // Executes command in (NSString *)pathToCommand with the arguments listed in
263 // (NSArray *)arguments as root.
264 // pathToCommand should be a string contain the path to the command 
265 // (eg., /usr/bin/more), arguments should be an array of strings each containing
266 // a single argument.
268 -(BOOL)executeCommand:(NSString *)pathToCommand withArgs:(NSArray *)arguments {
269         char* args[30]; // can only handle 30 arguments to a given command
270         OSStatus err = 0;
271         int i = 0;
272         
273         if(![self authenticate:[NSArray arrayWithObject:pathToCommand]])
274                 return NO;
275         
276         if( arguments == nil || [arguments count] < 1  ) {
277                 err = AuthorizationExecuteWithPrivileges(authorizationRef, [pathToCommand cString], 0, NULL, NULL);
278         }
279         else {
280                 while( i < [arguments count] && i < 19) {
281                         args[i] = (char*)[[arguments objectAtIndex:i] cString];
282                         i++;
283                 }
284                 args[i] = NULL;
286                 err = AuthorizationExecuteWithPrivileges(authorizationRef,
287                                                                                                 [pathToCommand cString],
288                                                                                                 0, args, NULL);
289         }
291     if(err!=0) {
292                 NSBeep();
293                 NSLog(@"Error %d in AuthorizationExecuteWithPrivileges",err);
294                 return NO;
295         }
296         else {
297                 return YES;
298         }
302 //============================================================================
303 //      - (void)killProcess:(NSString *)commandFromPS
304 //============================================================================
305 // Finds and kills the process specified in (NSString *)commandFromPS using ps 
306 // and kill. (by pid)
307 // The more specific (ie., closer to matching the actual listing in ps) 
308 // commandFromPS is the better your accuracy will be, esp. when multiple 
309 // versions of the process exist.
311 - (BOOL)killProcess:(NSString *)commandFromPS {
312         NSString *pid;
314         if( ![self isAuthenticated:[NSArray arrayWithObject:commandFromPS]] ) {
315                 [self authenticate:[NSArray arrayWithObject:commandFromPS]];
316         }
317         
318         pid = [NSString stringWithFormat:@"%d",[self getPID:commandFromPS]];
319         
320         if( [pid intValue] > 0 ) {
321                 [self executeCommand:@"/bin/kill" withArgs:[NSArray arrayWithObject:pid]];
322                 return YES;
323         }
324         else {
325                 NSBeep();
326                 NSLog(@"Error killing process %@, invalid PID.",pid);
327                 return NO;
328         }
329 }       
330 @end
332 // BLAuthentication sends these notifications are sent when the user  
333 // becomes authenticated or deauthenticated.
334 NSString* BLAuthenticatedNotification = @"BLAuthenticatedNotification";
335 NSString* BLDeauthenticatedNotification = @"BLDeauthenticatedNotification";
337 // Sample notification observer:
339     [[NSNotificationCenter defaultCenter] addObserver:self
340                                         selector:@selector(userAuthenticated:)
341                                         name:BLAuthenticatedNotification
342                                         object:[BLAuthentication sharedInstance]];
343     [[NSNotificationCenter defaultCenter] addObserver:self
344                                         selector:@selector(userDeauthenticated:)
345                                         name:BLDeauthenticatedNotification
346                                         object:[BLAuthentication sharedInstance]];