fe382b7b7c3abf42396815e33cb05a65488e0b57
[openafs.git] / src / platform / DARWIN / AFSPreference / afshlp.m
1 //
2 //  afshlp.m
3 //  AFSCommander
4 //
5 //  Created by Claudio on 28/06/07.
6 //
7
8
9 #include <sys/types.h>
10 #include <unistd.h>
11 #include <Security/Authorization.h>
12 #include <Security/AuthorizationTags.h>
13 #include <sys/param.h>
14 #include <sys/stat.h>
15 #include <sys/wait.h>
16 #include <sys/types.h>
17 #include <sys/fcntl.h>
18 #include <sys/errno.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <asl.h>
23 #include <sys/event.h>
24 #include <mach-o/dyld.h>
25 #import "TaskUtil.h"
26 #import "AuthUtil.h"
27 #import "PListManager.h"
28
29 #define AFS_DAEMON_STARTUPSCRIPT        "/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.rc"
30 #define AFS_DAEMON_PATH                         "/Library/LaunchDaemons/org.openafs.filesystems.afs.plist"
31
32  void stopAfs(int argc, char *argv[]);
33  void getPath(char **selfPathPtr);
34  void selfRepair(char *selfPath);
35  void runWithSelfRepair(char *selfPath,int argc, char *argv[]);
36  void runCommand(int argc, char *argv[]);
37
38 int main(int argc, char *argv[])
39 {
40         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
41     char *selfPath;
42         
43         NSLog(@"num of arguments %d", argc);
44         int status = [[AuthUtil shared] autorize];
45         if(status != noErr) exit(-1);
46         
47     // Get the path to the tool's executable
48     getPath(&selfPath);
49
50     //selfRepair(selfPath);
51     // All done with the executable path
52     if(selfPath) free(selfPath);
53         
54         // Now do the real work of running the command.
55     runCommand(argc, argv);
56     [[AuthUtil shared] deautorize];
57     [pool release];
58         
59         return 0;
60 }
61
62 // 
63 void runCommand(int argc, char *argv[])
64 {
65         setuid(0);
66         NSString *cmdString = [NSString stringWithCString:(const char *)argv[1] encoding:NSUTF8StringEncoding];
67
68         if(argc == 2 && [cmdString rangeOfString:@"stop_afs"].location!=NSNotFound ){
69                 NSLog(@"Stop afs from helper");
70                 const char *stopArgs[] = {"stop", 0L};
71                 [[AuthUtil shared] execUnixCommand:AFS_DAEMON_STARTUPSCRIPT
72                                                                           args:stopArgs
73                                                                         output:nil];
74
75         } else  if(argc == 2 && [cmdString rangeOfString:@"start_afs"].location!=NSNotFound){
76                 NSLog(@"Start afs from helper");
77                 const char *startArgs[] = {"start", 0L};
78                 [[AuthUtil shared] execUnixCommand:AFS_DAEMON_STARTUPSCRIPT
79                                                                           args:startArgs
80                                                                         output:nil];
81
82         } else if(argc == 4 && [cmdString rangeOfString:@"enable_krb5_startup"].location!=NSNotFound) {
83                 NSLog(@"Manage KRB5 at login time with option %s from helper", argv[2]);
84                 int arg2 = atoi(argv[2]);
85                 [PListManager krb5TiketAtLoginTime:[[NSNumber numberWithInt:arg2] boolValue]];
86         } else if(argc == 3 && [cmdString rangeOfString:@"start_afs_at_startup"].location!=NSNotFound){
87                 BOOL enable = strcmp("enable", argv[2])==0;
88                 NSLog(@"Manage start_afs_at_startup with option %s from helper", argv[2]);
89                 [PListManager launchctlStringCommand:enable?@"load":@"unload"
90                                                                           option:[NSArray arrayWithObjects:@"-w", nil]
91                                                                    plistName:@AFS_DAEMON_PATH];
92         }
93 }
94
95 void stopAfs(int argc, char *argv[])
96 {
97         
98         
99         setuid(0);
100         const char *umountArgs[] = {"-f", "/afs", 0L};
101         [[AuthUtil shared] execUnixCommand:"/sbin/umount" 
102                                                                   args:umountArgs
103                                                                 output:nil];
104         
105         const char *afsdArgs[] = {"-shutdown", 0L};
106         [[AuthUtil shared] execUnixCommand:argv[3]
107                                                                   args:afsdArgs
108                                                                 output:nil];
109         
110         const char *kernelExtArgs[] = {argv[2], 0L};
111         [[AuthUtil shared] execUnixCommand:"/sbin/kextunload"
112                                                                   args:kernelExtArgs
113                                                                 output:nil];
114         
115         [[AuthUtil shared] deautorize];
116 }
117
118
119 // Code to get the path to the executable using _NSGetExecutablePath.
120 void getPath(char **selfPathPtr)
121 {
122     uint32_t selfPathSize = MAXPATHLEN;
123     if(!(*selfPathPtr = malloc(selfPathSize)))
124     {
125         exit(-1);
126     }
127     if(_NSGetExecutablePath(*selfPathPtr, &selfPathSize) == -1)
128     {
129         // Try reallocating selfPath with the size returned by the function.
130         if(!(*selfPathPtr = realloc(*selfPathPtr, selfPathSize + 1)))
131         {
132             NSLog(@"Could not allocate memory to hold executable path.");
133             exit(-1);
134         }
135         if(_NSGetExecutablePath(*selfPathPtr, &selfPathSize) != 0)
136         {
137             NSLog(@"Could not get executable path.");
138             exit(-1);
139         }
140     }
141 }
142
143 // Self-repair code. Found somehwere in internet
144 void selfRepair(char *selfPath)
145 {
146     struct stat st;
147     int fdTool;
148         printf("selfRepair"); 
149         
150 //    [[AuthUtil shared] autorize];
151     
152     // Open tool exclusively, noone can touch it when we work on it, this idea i kepped somewhere in internet
153     fdTool = open(selfPath, O_NONBLOCK | O_RDONLY | O_EXLOCK, 0);
154     
155     if(fdTool == -1)
156     {
157         NSLog(@"Open Filed: %d.", errno);
158         exit(-1);
159     }
160     
161     if(fstat(fdTool, &st))
162     {
163         NSLog(@"fstat failed.");
164         exit(-1);
165     }
166     
167     if(st.st_uid != 0)
168     {
169         fchown(fdTool, 0, st.st_gid);
170     } else  NSLog(@"st_uid = 0");
171     
172     // Disable group and world writability and make setuid root.
173     fchmod(fdTool, (st.st_mode & (~(S_IWGRP | S_IWOTH))) | S_ISUID);
174     
175     close(fdTool);
176     
177     NSLog(@"Self-repair done.");
178 }
179
180
181 // Code to execute the tool in self-repair mode.
182 void runWithSelfRepair(char *selfPath, int argc, char *argv[])
183 {
184     int status;
185     int pid;
186         
187       
188         // Make the qargs array for passing to child the same args of father
189     const char *arguments[] = {argv[1], argv[2], argv[3], "--self-repair", 0L};
190         
191         // Get the privileged AuthorizationRef
192     [[AuthUtil shared] autorize];
193         [[AuthUtil shared] execUnixCommand:selfPath 
194                                                                   args:arguments 
195                                                                 output:nil];
196
197     pid = wait(&status);
198     if(pid == -1 || !WIFEXITED(status))
199     {
200         NSLog(@"Error returned from wait().");
201         exit(-1);
202     }
203     
204     // Exit with the same exit code as the self-repair child
205     exit(WEXITSTATUS(status));
206 }