Import Upstream version 1.8.5
[hcoop/debian/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