macos: update AFS prefs pane
[openafs.git] / src / platform / DARWIN / AFSPreference / PListManager.m
1 //
2 //  PListManager.m
3 //  OpenAFS
4 //
5 //  Created by Claudio Bisegni on 25/04/08.
6 //  Copyright 2008 Infn. All rights reserved.
7 //
8
9 #import "portability.h"
10 #import "PListManager.h"
11 #import "FileUtil.h"
12 #import "TaskUtil.h"
13
14 #define BACKGROUNDER_AGENT_NAME                                 @"AFSBackgrounder.app/Contents/MacOS/AFSBackgrounder"
15 #define AD_CONF_FILE @"/Library/Preferences/DirectoryService/ActiveDirectory.plist"
16 @implementation PListManager
17 // -------------------------------------------------------------------------------
18 //  krb5TiketAtLoginTime:
19 // -------------------------------------------------------------------------------
20 +(void) krb5TiketAtLoginTime:(BOOL)enable helper:(NSString *)helper
21 {
22         NSData                                  *plistData = nil;
23         NSString                                *error = nil;
24         NSString                                *toRemove = nil;
25         NSString                                *toAdd = nil;
26         NSPropertyListFormat    format;
27         NSMutableDictionary             *plist = nil;
28         SInt32                                  osxMJVers = 0;
29         SInt32                                  osxMnVers = 0;
30         FileUtil                                *futil = nil;
31         SInt32                                  object_index = 0;
32
33         // check system
34         if (Gestalt(gestaltSystemVersionMajor, &osxMJVers) != noErr || Gestalt(gestaltSystemVersionMinor, &osxMnVers) != noErr) @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" reason:@"Error getting system version" userInfo:nil];
35
36         // are we eligible to run?
37         plistData = [NSData dataWithContentsOfFile:AD_CONF_FILE];
38
39         // Get plist for updating with NSPropertyListMutableContainersAndLeaves
40         plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&error];
41
42         if(plist) {
43                 // Get "AD Advanced Options" dic
44                 NSMutableDictionary *rightsDic = [plist objectForKey:@"AD Advanced Options"];
45                 if ([[rightsDic objectForKey:@"AD Generate AuthAuthority"] boolValue])
46                         return;
47         }
48
49         // get auth plist file
50         plistData = [NSData dataWithContentsOfFile:AUTH_FILE];
51
52         // Get plist for updating with NSPropertyListMutableContainersAndLeaves
53         plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&error];
54
55         if(!plist) {
56                 @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" reason:error userInfo:nil];
57         }
58
59         // Get "rights" dic
60         NSMutableDictionary *rightsDic = [plist objectForKey:@"rights"];
61
62         //Get "system.login.console" dic
63         NSMutableDictionary *loginConsoleDic = [rightsDic objectForKey:@"system.login.console"];
64         
65         //Get "mechanisms" dic
66         NSMutableArray *mechanismsArray = [loginConsoleDic objectForKey:@"mechanisms"];
67         switch(osxMnVers){
68                 case 4:
69                         if(enable){
70                                 //remove
71                                 toRemove = DELETE_IN_10_4;
72                                 toAdd = ADD_IN_PLIST;
73                         } else {
74                                 toRemove = ADD_IN_PLIST;
75                                 toAdd = DELETE_IN_10_4;
76                         }
77                         break;
78                         
79                 case 5:
80                 case 6:
81                         if(enable){
82                                 //remove
83                                 toRemove = DELETE_IN_10_5;
84                                 toAdd = ADD_IN_PLIST;
85                         } else {
86                                 toRemove = ADD_IN_PLIST;
87                                 toAdd = DELETE_IN_10_5;
88                         }
89                         
90                         break;
91         }
92         
93         //Make change
94         object_index = [mechanismsArray indexOfObject: toRemove];
95         [mechanismsArray replaceObjectAtIndex:object_index withObject:toAdd];
96
97         //write plist
98         plistData  = [NSPropertyListSerialization dataFromPropertyList:plist
99                                                                                                                         format:NSPropertyListXMLFormat_v1_0
100                                                                                                   errorDescription:&error];
101         if(!plistData) {
102                 @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" 
103                                                                            reason:error
104                                                                          userInfo:nil];
105                 
106         }
107         if(![plistData writeToFile:TMP_FILE atomically:NO]) {
108                 @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" 
109                                                                            reason:@"Temp file write error"
110                                                                          userInfo:nil];
111                 
112         }
113         
114         //now we can move the file
115         futil = [[FileUtil alloc] init];
116         if(![[NSFileManager defaultManager] fileExistsAtPath:AUTH_FILE_BK]) {
117             //bk file doesn't exist so make it
118             [futil autorizedCopy:AUTH_FILE toPath:AUTH_FILE_BK];
119         }
120         // chmod on tmp file
121         [futil autorizedChown:TMP_FILE owner:@"root" group:@"wheel"];
122         //move the file
123         [futil autorizedMoveFile:TMP_FILE toPath:AUTH_FILE_DIR];
124
125         [futil release];
126 }
127
128 // -------------------------------------------------------------------------------
129 //  checkAklogAtLoginTimeLaunchdEnable:
130 // -------------------------------------------------------------------------------
131 +(BOOL) checkKrb5AtLoginTimeLaunchdEnable {
132         BOOL result = false;
133         NSString *authFileContent = nil;
134         authFileContent = [NSString stringWithContentsOfFile:AUTH_FILE 
135                                                                                                                   encoding:NSUTF8StringEncoding 
136                                                                                                                          error:nil];
137         if(authFileContent) {
138                 result = [authFileContent rangeOfString:ADD_IN_PLIST].location != NSNotFound;   
139         }
140         return result;
141 }
142
143         
144 // -------------------------------------------------------------------------------
145 //  installLaunchdFile:
146 // -------------------------------------------------------------------------------
147 +(void) installBackgrounderLaunchdFile:(BOOL)install resourcePath:(NSString*) rsrcPath {
148         NSData                          *plistData = nil;
149         NSMutableDictionary *launchdDic = nil;  
150         NSMutableDictionary *keepAliveDic = nil;
151         NSString                        *error = nil;
152         NSString                        *backgrounderPath = [[rsrcPath stringByAppendingString:@"/"] stringByAppendingString:BACKGROUNDER_AGENT_NAME];
153         
154         
155         if(![[NSFileManager defaultManager] fileExistsAtPath:[HOME_LAUNCHD_AGENT_FOLDER stringByExpandingTildeInPath]]) {
156                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
157                                                                            reason:@"The folder ~/Library/LaunchAgent doesn't exist!"
158                                                                          userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] 
159                                                                                                                                                   forKey:@"agent_folder_error"]];
160         }
161         
162         if(install) {
163                 if(![[NSFileManager defaultManager] fileExistsAtPath:[BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath]]) {
164                         launchdDic = [[[NSMutableDictionary alloc] init] autorelease];
165                         keepAliveDic = [[[NSMutableDictionary alloc] init] autorelease];
166                         
167                         [launchdDic setObject:@"it.infn.lnf.network.AFSBackgrounder" 
168                                                    forKey:@"Label"];
169                         
170                         [keepAliveDic setObject:[NSNumber numberWithBool:NO]
171                                                          forKey:@"SuccessfulExit"];
172                         
173                         [launchdDic setObject:keepAliveDic 
174                                                    forKey:@"KeepAlive"];
175                         
176                         [launchdDic setObject:@"Aqua"
177                                                    forKey:@"LimitLoadToSessionType"];
178                         
179                         /*[launchdDic setObject:[NSArray arrayWithObject:backgrounderPath]
180                                                    forKey:@"ProgramArguments"];*/
181                         [launchdDic setObject:backgrounderPath
182                                                    forKey:@"Program"];
183                         [launchdDic setObject:[NSNumber numberWithBool:YES] 
184                                                    forKey:@"RunAtLoad"];
185                         
186                         plistData  = [NSPropertyListSerialization dataFromPropertyList:launchdDic
187                                                                                                                                         format:NSPropertyListXMLFormat_v1_0
188                                                                                                                   errorDescription:&error];
189                         
190                         if(!plistData) {
191                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
192                                                                                            reason:error
193                                                                                          userInfo:nil];
194                                 
195                         }
196                         
197                         if(![plistData writeToFile:BACKGROUNDER_LAUNCHD_TMP_CONTROL_FILE atomically:NO]) {
198                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
199                                                                                            reason:@"Temp file write error"
200                                                                                          userInfo:nil];
201                                 
202                         }
203                         
204                         //now we can move the file
205                         [TaskUtil executeTaskSearchingPath:@"mv" args:[NSArray arrayWithObjects:BACKGROUNDER_LAUNCHD_TMP_CONTROL_FILE, [BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath], nil]];
206                 }
207         } else {
208                 // delete launchd configuration file
209                 [TaskUtil executeTaskSearchingPath:@"rm" args:[NSArray arrayWithObjects:[BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath], nil]];
210         }
211         
212 }
213
214 // -------------------------------------------------------------------------------
215 //  checkAklogAtLoginTimeLaunchdEnable:
216 // -------------------------------------------------------------------------------
217 +(BOOL) checkLoginTimeLaunchdBackgrounder {
218         BOOL result = [[NSFileManager defaultManager] fileExistsAtPath:[BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath]];
219         return result;
220 }
221
222 // -------------------------------------------------------------------------------
223 //  installAfsStartupLaunchdFile:
224 // -------------------------------------------------------------------------------
225 +(void) manageAfsStartupLaunchdFile:(BOOL)enable 
226                    afsStartupScript:(NSString*)afsStartupScript
227                         afsBasePath:(NSString*)afsBasePath
228                            afsdPath:(NSString*)afsdPath {
229         NSData                          *plistData = nil;
230         NSMutableDictionary *launchdDic = nil;
231         NSString                        *error = nil;
232         OSErr                           status = noErr;
233         
234         
235         if(![[NSFileManager defaultManager] fileExistsAtPath:[LAUNCHD_DAEMON_FOLDER stringByExpandingTildeInPath]]) {
236                 @throw [NSException exceptionWithName:@"PListManager:installAfsStartupLaunchdFile" 
237                                                                            reason:@"The folder /Library/LaunchDaemon doesn't exist!"
238                                                                          userInfo:nil];
239         }
240         
241         status = [[AuthUtil shared] autorize];
242         if(status != noErr)@throw [NSException exceptionWithName:@"PListManager:installAfsStartupLaunchdFile" 
243                                                                                                           reason:@"Autorization Error"
244                                                                                                         userInfo:nil];
245         
246         if(enable) {
247                 //Check first if the launchd configuration file for startup is present
248                 if(![[NSFileManager defaultManager] fileExistsAtPath:[AFS_STARTUP_CONTROL_FILE stringByExpandingTildeInPath]]) {
249                         launchdDic = [[[NSMutableDictionary alloc] init] autorelease];
250                         //argDic = [[NSMutableArray alloc] init];
251                         
252                         [launchdDic setObject:@"it.infn.lnf.afsstartup" 
253                                                    forKey:@"Label"];
254                         
255                         
256                         [launchdDic setObject:[NSArray arrayWithObjects:afsStartupScript, afsBasePath, afsdPath, nil]
257                                                    forKey:@"ProgramArguments"];
258                         
259                         [launchdDic setObject:[NSNumber numberWithBool:YES] 
260                                                    forKey:@"RunAtLoad"];
261                         
262                         plistData  = [NSPropertyListSerialization dataFromPropertyList:launchdDic
263                                                                                                                                         format:NSPropertyListXMLFormat_v1_0
264                                                                                                                   errorDescription:&error];
265                         
266                         if(!plistData) {
267                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
268                                                                                            reason:error
269                                                                                          userInfo:nil];
270                                 
271                         }
272                         
273                         if(![plistData writeToFile:AFS_STARTUP_TMP_CONTROL_FILE atomically:NO]) {
274                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
275                                                                                            reason:@"Temp file write error"
276                                                                                          userInfo:nil];
277                                 
278                         }
279                         
280                         //now we can move the file
281                         [TaskUtil executeTaskSearchingPath:@"mv" args:[NSArray arrayWithObjects:AFS_STARTUP_TMP_CONTROL_FILE, [LAUNCHD_DAEMON_FOLDER stringByExpandingTildeInPath], nil]];
282                 }
283         }
284         
285 }
286
287 // -------------------------------------------------------------------------------
288 //  launchctlCommand:
289 // -------------------------------------------------------------------------------
290 +(void) launchctlCommand:(BOOL)enable
291               userDomain:(BOOL)userDomain
292                   option:(NSArray*)option
293                plistName:(NSString*)plistName
294 {
295         NSMutableArray *argument = [NSMutableArray array];
296         NSMutableString *commandPath = [NSMutableString stringWithCapacity:0];
297         NSUInteger searchDomain = userDomain?NSUserDomainMask:NSSystemDomainMask;
298         //
299         NSArray *libraryPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, searchDomain,  YES);
300         //set the load unload
301         [argument addObject:enable?@"load":@"unload"];
302
303         //if there are load the user custo option
304         if(option) [argument addObjectsFromArray:option];
305                 
306         //construct the path
307         [commandPath appendString:[libraryPath objectAtIndex:0]];
308         [commandPath appendFormat:@"/LaunchAgents/%@", plistName];
309         
310         [argument addObject:commandPath];
311
312         //exec the command
313         [TaskUtil executeTask:@"/bin/launchctl"
314                   arguments:argument];
315 }
316
317 // -------------------------------------------------------------------------------
318 //  launchctlCommand:
319 // -------------------------------------------------------------------------------
320 +(void) launchctlStringCommandAuth:(NSString *)operation
321                             option:(NSArray *)option
322                          plistName:(NSString *)plistName
323                             helper:(NSString *)helper
324                        withAuthRef:(AuthorizationRef)authRef
325 {
326         NSMutableArray *argument = [NSMutableArray array];
327
328         //set the load unload
329         [argument addObject:operation];
330
331         //if there are load the user custom option
332         if(option) [argument addObjectsFromArray:option];
333
334         //construct the path
335         [argument addObject: plistName];
336
337         //exec the command
338         [TaskUtil executeTaskWithAuth:@"/bin/launchctl"
339                   arguments:argument helper:helper withAuthRef:authRef];
340 }
341
342 // -------------------------------------------------------------------------------
343 //  launchdJobState:
344 // -------------------------------------------------------------------------------
345 +(BOOL) launchdJobState:(NSString*)jobName {
346         NSMutableArray *argument = [NSMutableArray array];
347         
348         //set the load unload
349         [argument addObject:@"list"];
350         [argument addObject:jobName];
351         //exec the command
352         NSString *taskResult =[TaskUtil executeTaskSearchingPath:@"launchctl"  
353                                                                                                                 args:argument];
354         return taskResult && [taskResult rangeOfString:jobName].location != NSNotFound;
355 }
356 @end