]> git.saurik.com Git - apple/security.git/blob - SecurityServer/Authorization/AuthorizationTrampoline.cpp
Security-28.tar.gz
[apple/security.git] / SecurityServer / Authorization / AuthorizationTrampoline.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // AuthorizationTrampoline - simple suid-root execution trampoline
21 // for the authorization API.
22 //
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <Security/Authorization.h>
28 #include <Security/debugging.h>
29 #include <Security/logging.h>
30
31
32 #define EXECUTERIGHT "system.privilege.admin"
33
34
35 static void fail(OSStatus cause) __attribute__ ((noreturn));
36
37
38 //
39 // Main program entry point.
40 //
41 // Arguments:
42 // argv[0] = my name
43 // argv[1] = path to user tool
44 // argv[2] = "auth n", n=file descriptor of mailbox temp file
45 // argv[3..n] = arguments to pass on
46 //
47 // File descriptors (set by fork/exec code in client):
48 // 0 -> communications pipe (perhaps /dev/null)
49 // 1 -> notify pipe write end
50 // 2 and above -> unchanged from original client
51 //
52 int main(int argc, const char *argv[])
53 {
54 // initial setup
55 Syslog::open("authexec", LOG_AUTH);
56
57 // validate basic integrity
58 if (!argv[0] || !argv[1] || !argv[2]) {
59 Syslog::alert("invalid argument vector");
60 exit(1);
61 }
62
63 // pick up arguments
64 const char *pathToTool = argv[1];
65 const char *mboxFdText = argv[2];
66 const char **restOfArguments = argv + 3;
67 debug("authtramp", "trampoline(%s,%s)", pathToTool, mboxFdText);
68
69 // read the external form
70 AuthorizationExternalForm extForm;
71 int fd;
72 if (sscanf(mboxFdText, "auth %d", &fd) != 1)
73 return errAuthorizationInternal;
74 if (lseek(fd, 0, SEEK_SET) ||
75 read(fd, &extForm, sizeof(extForm)) != sizeof(extForm)) {
76 close(fd);
77 return errAuthorizationInternal;
78 }
79
80 // internalize the authorization
81 AuthorizationRef auth;
82 if (OSStatus error = AuthorizationCreateFromExternalForm(&extForm, &auth))
83 fail(error);
84 debug("authtramp", "authorization recovered");
85
86 // are we allowed to do this?
87 AuthorizationItem right = { EXECUTERIGHT, 0, NULL, 0 };
88 AuthorizationRights inRights = { 1, &right };
89 AuthorizationRights *outRights;
90 if (OSStatus error = AuthorizationCopyRights(auth, &inRights, NULL /*env*/,
91 kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, &outRights))
92 fail(error);
93 if (outRights->count != 1 || strcmp(outRights->items[0].name, EXECUTERIGHT))
94 fail(errAuthorizationDenied);
95
96 // ----- AT THIS POINT WE COMMIT TO PERMITTING THE EXECUTION -----
97
98 // let go of our authorization - the client tool will re-internalize it
99 AuthorizationFree(auth, kAuthorizationFlagDefaults);
100
101 // put the external authorization form into the environment
102 setenv("__AUTHORIZATION", mboxFdText, true);
103
104 // shuffle file descriptors
105 int notify = dup(1); // save notify port
106 fcntl(notify, F_SETFD, 1); // close notify port on (successful) exec
107 dup2(0, 1); // make stdin, stdout point to the comms pipe
108
109 // prepare the argv for the tool (prepend the "myself" element)
110 // note how this overwrites a known-existing argv element (that we copied earlier)
111 *(--restOfArguments) = pathToTool;
112
113 debug("authtramp", "trampoline executes %s", pathToTool);
114 Syslog::notice("executing %s", pathToTool);
115 execv(pathToTool, (char *const *)restOfArguments);
116 debug("authexec", "exec(%s) failed (errno=%d)", pathToTool, errno);
117
118 // report failure
119 OSStatus error = errAuthorizationToolExecuteFailure;
120 write(notify, &error, sizeof(error));
121 exit(1);
122 }
123
124
125 void fail(OSStatus cause)
126 {
127 write(1, &cause, sizeof(cause)); // ignore error - can't do anything if error
128 debug("authtramp", "trampoline aborting with status %ld", cause);
129 exit(1);
130 }