]> git.saurik.com Git - apple/security.git/blob - SecurityServer/Authorization/privPortServer.cpp
Security-179.tar.gz
[apple/security.git] / SecurityServer / Authorization / privPortServer.cpp
1 /*
2 * Copyright (c) 2003 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 // privportserver.cpp - tool-side trampoline support functions
21 //
22 #include <cstdlib>
23 #include <unistd.h>
24 #include <Security/Authorization.h>
25 #include <Security/unix++.h>
26 #include <Security/fdmover.h>
27 #include <Security/debugging.h>
28 #include "privPort.h"
29
30 using namespace UnixPlusPlus;
31 using namespace IPPlusPlus;
32
33
34 //
35 // Default values
36 //
37 #define DEFAULT_TIMEOUT (2 * 60) /* seconds */
38
39
40 //
41 // Local functions
42 //
43 void usage(const char *me);
44 void serve(FdMover client);
45 void sigALRM(int signo);
46
47
48 //
49 // Send a reply (successful or otherwise) to the client and clean up.
50 //
51 void reply(Socket s, OSStatus error)
52 {
53 Reply reply;
54 reply.status = htonl(error);
55 s.write(&reply, sizeof(reply));
56 close(s);
57 }
58
59
60 //
61 // Server main program
62 //
63 int main(int argc, char *argv[])
64 {
65 unsigned timeout = DEFAULT_TIMEOUT;
66
67 extern int optind;
68 extern char *optarg;
69 int arg;
70 while ((arg = getopt(argc, argv, "t:")) != -1)
71 switch (arg) {
72 case 't':
73 timeout = atoi(optarg);
74 break;
75 case '?':
76 usage(argv[0]);
77 }
78 if (optind < argc)
79 usage(argv[0]);
80
81 umask(0111); // allow world-write on created socket
82 Socket server(AF_UNIX, SOCK_STREAM);
83 UNSockAddress serverAddress(kPrivilegedPortBinder);
84 try {
85 server.bind(serverAddress);
86 } catch (const UnixError &error) {
87 switch (error.error) {
88 case EADDRINUSE:
89 unlink(kPrivilegedPortBinder);
90 server.bind(serverAddress);
91 break;
92 default:
93 throw;
94 }
95 }
96 server.listen(5);
97
98 // prepare signals
99 SigSet signals;
100 signals += SIGALRM;
101 sigMask(signals, SIG_BLOCK);
102 if (signal(SIGALRM, sigALRM) == SIG_ERR) {
103 perror("SIGALRM");
104 exit(1);
105 }
106
107 // server loop
108 for (;;) {
109 FdMover s;
110 alarm(timeout);
111 sigMask(signals, SIG_UNBLOCK);
112 server.accept(s);
113 sigMask(signals, SIG_BLOCK);
114 try {
115 serve(s);
116 } catch (const CssmCommonError &error) {
117 reply(s, error.cssmError());
118 } catch (...) {
119 reply(s, -1);
120 }
121 }
122
123 // go away
124 return 0;
125 }
126
127
128 void usage(const char *me)
129 {
130 fprintf(stderr, "Usage: %s [-t timeout-seconds]\n", me);
131 exit(2);
132 }
133
134
135 void sigALRM(int signo)
136 {
137 secdebug("portserver", "timeout; quitting");
138 unlink(kPrivilegedPortBinder);
139 exit(0);
140 }
141
142
143 //
144 // Serve one request
145 void serve(FdMover client)
146 {
147 secdebug("portserver", "processing port request");
148
149 // receive request message
150 Request request;
151 FdVector fds;
152 if (client.receive(&request, sizeof(request), fds) != sizeof(request)) {
153 // short receive - assume sender protocol error
154 return reply(client, 11111);
155 return;
156 }
157 if (fds.size() != 1) {
158 // must send exactly one socket to find
159 return reply(client, 11111);
160 return;
161 }
162
163 // internalize the authorization
164 AuthorizationRef auth;
165 if (OSStatus err = AuthorizationCreateFromExternalForm(&request.authForm, &auth))
166 return reply(client, err);
167
168 // validate authorization; punt if not authorized
169 AuthorizationItem rights[] = {
170 { CONNECTRIGHT, 0, NULL, 0 },
171 { ACCEPTRIGHT, 0, NULL, 0 }
172 };
173 AuthorizationRights rightSet = { sizeof(rights) / sizeof(rights[0]), rights };
174 AuthorizationRights *result;
175 if (OSStatus err = AuthorizationCopyRights(auth, &rightSet, NULL,
176 kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights |
177 kAuthorizationFlagPartialRights,
178 &result))
179 return reply(client, err);
180 UInt32 count = result ? result->count : 0;
181 AuthorizationFreeItemSet(result);
182 if (count == 0)
183 return reply(client, errAuthorizationDenied);
184
185 // okay, bind as requested
186 Socket s; s = fds[0];
187 s.bind(request.requestedName);
188
189 // all is well. Tell the client
190 return reply(client, 0);
191 }