2 * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // privportserver.cpp - tool-side trampoline support functions
24 #include <Security/Authorization.h>
25 #include <Security/unix++.h>
26 #include <Security/fdmover.h>
27 #include <Security/debugging.h>
30 using namespace UnixPlusPlus
;
31 using namespace IPPlusPlus
;
37 #define DEFAULT_TIMEOUT (2 * 60) /* seconds */
43 void usage(const char *me
);
44 void serve(FdMover client
);
45 void sigALRM(int signo
);
49 // Send a reply (successful or otherwise) to the client and clean up.
51 void reply(Socket s
, OSStatus error
)
54 reply
.status
= htonl(error
);
55 s
.write(&reply
, sizeof(reply
));
61 // Server main program
63 int main(int argc
, char *argv
[])
65 unsigned timeout
= DEFAULT_TIMEOUT
;
70 while ((arg
= getopt(argc
, argv
, "t:")) != -1)
73 timeout
= atoi(optarg
);
81 umask(0111); // allow world-write on created socket
82 Socket
server(AF_UNIX
, SOCK_STREAM
);
83 UNSockAddress
serverAddress(kPrivilegedPortBinder
);
85 server
.bind(serverAddress
);
86 } catch (const UnixError
&error
) {
87 switch (error
.error
) {
89 unlink(kPrivilegedPortBinder
);
90 server
.bind(serverAddress
);
101 sigMask(signals
, SIG_BLOCK
);
102 if (signal(SIGALRM
, sigALRM
) == SIG_ERR
) {
111 sigMask(signals
, SIG_UNBLOCK
);
113 sigMask(signals
, SIG_BLOCK
);
116 } catch (const CssmCommonError
&error
) {
117 reply(s
, error
.cssmError());
128 void usage(const char *me
)
130 fprintf(stderr
, "Usage: %s [-t timeout-seconds]\n", me
);
135 void sigALRM(int signo
)
137 secdebug("portserver", "timeout; quitting");
138 unlink(kPrivilegedPortBinder
);
145 void serve(FdMover client
)
147 secdebug("portserver", "processing port request");
149 // receive request message
152 if (client
.receive(&request
, sizeof(request
), fds
) != sizeof(request
)) {
153 // short receive - assume sender protocol error
154 return reply(client
, 11111);
157 if (fds
.size() != 1) {
158 // must send exactly one socket to find
159 return reply(client
, 11111);
163 // internalize the authorization
164 AuthorizationRef auth
;
165 if (OSStatus err
= AuthorizationCreateFromExternalForm(&request
.authForm
, &auth
))
166 return reply(client
, err
);
168 // validate authorization; punt if not authorized
169 AuthorizationItem rights
[] = {
170 { CONNECTRIGHT
, 0, NULL
, 0 },
171 { ACCEPTRIGHT
, 0, NULL
, 0 }
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
,
179 return reply(client
, err
);
180 UInt32 count
= result
? result
->count
: 0;
181 AuthorizationFreeItemSet(result
);
183 return reply(client
, errAuthorizationDenied
);
185 // okay, bind as requested
186 Socket s
; s
= fds
[0];
187 s
.bind(request
.requestedName
);
189 // all is well. Tell the client
190 return reply(client
, 0);