2 * Copyright (c) 2000-2001 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 // SecurityServer - Apple security services daemon.
22 #include "securityserver.h"
26 #include <Security/daemon.h>
27 #include <Security/osxsigner.h>
28 #include "authority.h"
32 #include <Security/machserver.h>
34 #include <sys/types.h>
38 #include "ktracecodes.h"
40 // ACL subject types (their makers are instantiated here)
41 #include <Security/acl_any.h>
42 #include <Security/acl_password.h>
43 #include <Security/acl_protectedpw.h>
44 #include <Security/acl_threshold.h>
45 #include <Security/acl_codesigning.h>
46 #include <Security/acl_process.h>
47 #include <Security/acl_comment.h>
48 #include "acl_keychain.h"
55 // Program options (set by argument scan and environment)
58 const char *bootstrapName
= NULL
;
60 } // end namespace Security
64 // Local functions of the main program driver
66 static void usage(const char *me
);
67 static void handleSIGCHLD(int);
68 static void handleSIGOther(int);
74 int main(int argc
, char *argv
[])
76 Debug::trace (kSecTraceSecurityServerStart
);
78 // program arguments (preset to defaults)
79 bool forceCssmInit
= false;
80 bool reExecute
= false;
81 int workerTimeout
= 0;
83 const char *authorizationConfig
= "/etc/authorization";
84 const char *entropyFile
= "/var/db/SystemEntropyCache";
85 const char *equivDbFile
= EQUIVALENCEDBPATH
;
87 // parse command line arguments
91 while ((arg
= getopt(argc
, argv
, "a:de:E:fN:t:T:X")) != -1) {
94 authorizationConfig
= optarg
;
100 equivDbFile
= optarg
;
103 entropyFile
= optarg
;
106 forceCssmInit
= true;
109 bootstrapName
= optarg
;
112 if ((maxThreads
= atoi(optarg
)) < 0)
116 if ((workerTimeout
= atoi(optarg
)) < 0)
127 // take no non-option arguments
131 // figure out the bootstrap name
132 IFDEBUG(if (!bootstrapName
) bootstrapName
= getenv(SECURITYSERVER_BOOTSTRAP_ENV
));
134 if (!bootstrapName
) {
135 bootstrapName
= SECURITYSERVER_BOOTSTRAP_NAME
;
138 // configure logging first
140 Syslog::open(bootstrapName
, LOG_AUTHPRIV
, LOG_PERROR
);
141 Syslog::notice("SecurityServer started in debug mode");
143 Syslog::open(bootstrapName
, LOG_AUTHPRIV
, LOG_CONS
);
146 // if we're not running as root in production mode, fail
147 // in debug mode, issue a warning
148 if (uid_t uid
= getuid()) {
150 Syslog::alert("Tried to run SecurityServer as user %d: aborted", uid
);
151 fprintf(stderr
, "You are not allowed to run SecurityServer\n");
154 fprintf(stderr
, "SecurityServer is unprivileged; some features may not work.\n");
155 secdebug("SS", "Running as user %d (you have been warned)", uid
);
159 // turn into a properly diabolical daemon unless debugMode is on
161 if (!Daemon::incarnate())
162 exit(1); // can't daemonize
164 if (reExecute
&& !Daemon::executeSelf(argv
))
165 exit(1); // can't self-execute
168 // create a code signing engine
169 CodeSigning::OSXSigner signer
;
171 // create an Authorization engine
172 Authority
authority(authorizationConfig
);
174 // establish the ACL machinery
175 new AnyAclSubject::Maker();
176 new PasswordAclSubject::Maker();
177 new ProtectedPasswordAclSubject::Maker();
178 new ThresholdAclSubject::Maker();
179 new CommentAclSubject::Maker();
180 new ProcessAclSubject::Maker();
181 new CodeSignatureAclSubject::Maker(signer
);
182 new KeychainPromptAclSubject::Maker();
184 // add a temporary registration for a subject type that went out in 10.2 seed 1
185 // this should probably be removed for the next major release >10.2
186 new KeychainPromptAclSubject::Maker(CSSM_WORDID__RESERVED_1
);
188 // establish the code equivalents database
189 CodeSignatures
codeSignatures(equivDbFile
);
191 // create the main server object and register it
192 Server
server(authority
, codeSignatures
, bootstrapName
);
194 // set server configuration from arguments, if specified
196 server
.timeout(workerTimeout
);
198 server
.maxThreads(maxThreads
);
200 // add the RNG seed timer to it
202 EntropyManager
entropy(server
, entropyFile
);
204 if (!getuid()) new EntropyManager(server
, entropyFile
);
207 // create the RootSession object (if -d, give it graphics and tty attributes)
208 RootSession
rootSession(server
.primaryServicePort(),
209 debugMode
? (sessionHasGraphicAccess
| sessionHasTTY
) : 0);
211 // set up signal handlers
212 if (signal(SIGCHLD
, handleSIGCHLD
) == SIG_ERR
)
213 secdebug("SS", "Cannot ignore SIGCHLD: errno=%d", errno
);
214 if (signal(SIGINT
, handleSIGOther
) == SIG_ERR
)
215 secdebug("SS", "Cannot handle SIGINT: errno=%d", errno
);
216 if (signal(SIGTERM
, handleSIGOther
) == SIG_ERR
)
217 secdebug("SS", "Cannot handle SIGTERM: errno=%d", errno
);
219 // initialize CSSM now if requested
223 Syslog::notice("Entering service");
224 secdebug("SS", "%s initialized", bootstrapName
);
226 Debug::trace (kSecTraceSecurityServerStart
);
230 // fell out of runloop (should not happen)
231 Syslog::alert("Aborting");
237 // Issue usage message and die
239 static void usage(const char *me
)
241 fprintf(stderr
, "Usage: %s [-df] [-t maxthreads] [-T threadTimeout]"
242 "\t[-N bootstrapName] [-a authConfigFile]\n", me
);
248 // Handle SIGCHLD signals to reap our children (zombie cleanup)
250 static void handleSIGCHLD(int)
253 pid_t pid
= waitpid(-1, &status
, WNOHANG
);
256 //secdebug("SS", "Spurious SIGCHLD ignored");
259 //secdebug("SS", "waitpid after SIGCHLD failed: errno=%d", errno);
262 //secdebug("SS", "Reaping child pid=%d", pid);
269 // Handle some other signals to shut down cleanly (and with logging)
271 static void handleSIGOther(int sig
)
275 //secdebug("SS", "Interrupt signal; terminating");
276 Syslog::notice("received interrupt signal; terminating");
279 //secdebug("SS", "Termination signal; terminating");
280 Syslog::notice("received termination signal; terminating");