]> git.saurik.com Git - apple/security.git/blob - SecurityServer/main.cpp
Security-54.tar.gz
[apple/security.git] / SecurityServer / main.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 // SecurityServer - Apple security services daemon.
21 //
22 #include "securityserver.h"
23 #include "server.h"
24 #include "entropy.h"
25
26 #include <Security/daemon.h>
27 #include <Security/osxsigner.h>
28 #include "authority.h"
29 #include "session.h"
30
31 #include <unistd.h>
32 #include <Security/machserver.h>
33
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <signal.h>
37
38 // ACL subject types (their makers are instantiated here)
39 #include <Security/acl_any.h>
40 #include <Security/acl_password.h>
41 #include <Security/acl_protectedpw.h>
42 #include <Security/acl_threshold.h>
43 #include <Security/acl_codesigning.h>
44 #include <Security/acl_comment.h>
45 #include "acl_keychain.h"
46
47
48 namespace Security
49 {
50
51 //
52 // Program options (set by argument scan and environment)
53 //
54 uint32 debugMode = 0;
55
56 } // end namespace Security
57
58
59 //
60 // Local functions of the main program driver
61 //
62 static void usage(const char *me);
63 static void handleSIGCHLD(int);
64 static void handleSIGOther(int);
65
66
67 //
68 // Main driver
69 //
70 int main(int argc, char *argv[])
71 {
72 // program arguments (preset to defaults)
73 bool forceCssmInit = false;
74 bool reExecute = false;
75 int workerTimeout = 0;
76 int maxThreads = 0;
77 const char *authorizationConfig = "/etc/authorization";
78 const char *bootstrapName = "SecurityServer";
79 const char *entropyFile = "/var/db/SystemEntropyCache";
80
81 // parse command line arguments
82 extern char *optarg;
83 extern int optind;
84 int arg;
85 while ((arg = getopt(argc, argv, "a:dEfN:t:T:X")) != -1) {
86 switch (arg) {
87 case 'a':
88 authorizationConfig = optarg;
89 break;
90 case 'd':
91 debugMode++;
92 break;
93 case 'E':
94 entropyFile = optarg;
95 break;
96 case 'f':
97 forceCssmInit = true;
98 break;
99 case 'N':
100 bootstrapName = optarg;
101 break;
102 case 't':
103 if ((maxThreads = atoi(optarg)) < 0)
104 maxThreads = 0;
105 break;
106 case 'T':
107 if ((workerTimeout = atoi(optarg)) < 0)
108 workerTimeout = 0;
109 break;
110 case 'X':
111 reExecute = true;
112 break;
113 default:
114 usage(argv[0]);
115 }
116 }
117
118 // take no non-option arguments
119 if (optind < argc)
120 usage(argv[0]);
121
122 // configure logging first
123 if (debugMode) {
124 Syslog::open(argv[0], LOG_AUTHPRIV, LOG_PERROR);
125 Syslog::notice("SecurityServer started in debug mode");
126 } else {
127 Syslog::open(argv[0], LOG_AUTHPRIV, LOG_CONS);
128 }
129
130 // if we're not running as root in production mode, fail
131 // in debug mode, issue a warning
132 if (uid_t uid = getuid()) {
133 #if defined(NDEBUG)
134 Syslog::alert("Tried to run SecurityServer as user %d: aborted", uid);
135 fprintf(stderr, "You are not allowed to run SecurityServer\n");
136 exit(1);
137 #else
138 fprintf(stderr, "SecurityServer is unprivileged; some features may not work.\n");
139 debug("SS", "Running as user %d (you have been warned)", uid);
140 #endif //NDEBUG
141 }
142
143 // turn into a properly diabolical daemon unless debugMode is on
144 if (!debugMode) {
145 if (!Daemon::incarnate())
146 exit(1); // can't daemonize
147
148 if (reExecute && !Daemon::executeSelf(argv))
149 exit(1); // can't self-execute
150 }
151
152 // create a code signing engine
153 CodeSigning::OSXSigner signer;
154
155 // create an Authorization engine
156 Authority authority(authorizationConfig);
157
158 // establish the ACL machinery
159 new AnyAclSubject::Maker();
160 new PasswordAclSubject::Maker();
161 new ProtectedPasswordAclSubject::Maker();
162 new ThresholdAclSubject::Maker();
163 new CommentAclSubject::Maker();
164 new CodeSignatureAclSubject::Maker(signer);
165 new KeychainPromptAclSubject::Maker();
166
167 // add a temporary registration for a subject type that went out in 10.2 seed 1
168 // this should probably be removed for the next major release >10.2
169 new KeychainPromptAclSubject::Maker(CSSM_WORDID__RESERVED_1);
170
171 // create the main server object and register it
172 Server server(authority, bootstrapName);
173
174 // create the RootSession object (if -d, give it graphics and tty attributes)
175 RootSession rootSession(server.primaryServicePort(),
176 debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0);
177
178 // set server configuration from arguments, if specified
179 if (workerTimeout)
180 server.timeout(workerTimeout);
181 if (maxThreads)
182 server.maxThreads(maxThreads);
183
184 // add the RNG seed timer to it
185 # if defined(NDEBUG)
186 EntropyManager entropy(server, entropyFile);
187 # else
188 if (!getuid()) new EntropyManager(server, entropyFile);
189 # endif
190
191 // set up signal handlers
192 if (signal(SIGCHLD, handleSIGCHLD) == SIG_ERR)
193 debug("SS", "Cannot ignore SIGCHLD: errno=%d", errno);
194 if (signal(SIGINT, handleSIGOther) == SIG_ERR)
195 debug("SS", "Cannot handle SIGINT: errno=%d", errno);
196 if (signal(SIGTERM, handleSIGOther) == SIG_ERR)
197 debug("SS", "Cannot handle SIGTERM: errno=%d", errno);
198
199 // initialize CSSM now if requested
200 if (forceCssmInit)
201 server.loadCssm();
202
203 Syslog::notice("Entering service");
204 debug("SS", "Entering service run loop");
205 server.run();
206
207 // fell out of runloop (should not happen)
208 Syslog::alert("Aborting");
209 return 1;
210 }
211
212
213 //
214 // Issue usage message and die
215 //
216 static void usage(const char *me)
217 {
218 fprintf(stderr, "Usage: %s [-df] [-t maxthreads] [-T threadTimeout]"
219 "\t[-N bootstrapName] [-a authConfigFile]\n", me);
220 exit(2);
221 }
222
223
224 //
225 // Handle SIGCHLD signals to reap our children (zombie cleanup)
226 //
227 static void handleSIGCHLD(int)
228 {
229 int status;
230 switch (pid_t pid = waitpid(-1, &status, WNOHANG)) {
231 case 0:
232 debug("SS", "Spurious SIGCHLD ignored");
233 return;
234 case -1:
235 debug("SS", "waitpid after SIGCHLD failed: errno=%d", errno);
236 return;
237 default:
238 debug("SS", "Reaping child pid=%d", pid);
239 return;
240 }
241 }
242
243
244 //
245 // Handle some other signals to shut down cleanly (and with logging)
246 //
247 static void handleSIGOther(int sig)
248 {
249 switch (sig) {
250 case SIGINT:
251 debug("SS", "Interrupt signal; terminating");
252 Syslog::notice("received interrupt signal; terminating");
253 exit(0);
254 case SIGTERM:
255 debug("SS", "Termination signal; terminating");
256 Syslog::notice("received termination signal; terminating");
257 exit(0);
258 }
259 }