2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
28 // securityd - Apple security services daemon.
30 #include <securityd_client/ucsp.h>
32 #include "securityserver.h"
36 #include <security_utilities/daemon.h>
37 #include <security_cdsa_client/osxsigner.h>
38 #include "authority.h"
40 #include "pcscmonitor.h"
43 #include <security_utilities/machserver.h>
45 #include <sys/types.h>
48 #include <security_utilities/ktracecodes.h>
50 // #define PERFORMANCE_MEASUREMENT 1
52 #ifdef PERFORMANCE_MEASUREMENT
53 #include <mach/mach_time.h>
56 // ACL subject types (their makers are instantiated here)
57 #include <security_cdsa_utilities/acl_any.h>
58 #include <security_cdsa_utilities/acl_password.h>
59 #include <security_cdsa_utilities/acl_protectedpw.h>
60 #include <security_cdsa_utilities/acl_threshold.h>
61 #include <security_cdsa_utilities/acl_codesigning.h>
62 #include <security_cdsa_utilities/acl_process.h>
63 #include <security_cdsa_utilities/acl_comment.h>
65 #include "acl_keychain.h"
72 // Program options (set by argument scan and environment)
75 const char *bootstrapName
= NULL
;
77 } // end namespace Security
81 // Local functions of the main program driver
83 static void usage(const char *me
);
84 static void handleSIGCHLD(int);
85 static void handleSIGOther(int);
86 IFDEBUG(static void handleSIGdebug(int));
88 static Port gMainServerPort
;
93 int main(int argc
, char *argv
[])
95 #ifdef PERFORMANCE_MEASUREMENT
96 // needed for automated timing of securityd startup
97 uint64_t startTime
= mach_absolute_time ();
100 Debug::trace (kSecTraceSecurityServerStart
);
102 // program arguments (preset to defaults)
104 bool forceCssmInit
= false;
105 bool reExecute
= false;
106 int workerTimeout
= 0;
108 const char *authorizationConfig
= "/etc/authorization";
109 const char *entropyFile
= "/var/db/SystemEntropyCache";
110 const char *equivDbFile
= EQUIVALENCEDBPATH
;
112 // parse command line arguments
116 while ((arg
= getopt(argc
, argv
, "a:de:E:fN:t:T:X")) != -1) {
119 authorizationConfig
= optarg
;
125 equivDbFile
= optarg
;
128 entropyFile
= optarg
;
131 forceCssmInit
= true;
134 bootstrapName
= optarg
;
137 if ((maxThreads
= atoi(optarg
)) < 0)
141 if ((workerTimeout
= atoi(optarg
)) < 0)
153 // take no non-option arguments
157 // figure out the bootstrap name
158 IFDEBUG(if (!bootstrapName
) bootstrapName
= getenv(SECURITYSERVER_BOOTSTRAP_ENV
));
160 if (!bootstrapName
) {
161 bootstrapName
= SECURITYSERVER_BOOTSTRAP_NAME
;
164 // configure logging first
166 Syslog::open(bootstrapName
, LOG_AUTHPRIV
, LOG_PERROR
);
167 Syslog::notice("SecurityServer started in debug mode");
169 Syslog::open(bootstrapName
, LOG_AUTHPRIV
, LOG_CONS
);
172 // if we're not running as root in production mode, fail
173 // in debug mode, issue a warning
174 if (uid_t uid
= getuid()) {
176 Syslog::alert("Tried to run securityd as user %d: aborted", uid
);
177 fprintf(stderr
, "You are not allowed to run securityd\n");
180 fprintf(stderr
, "securityd is unprivileged; some features may not work.\n");
181 secdebug("SS", "Running as user %d (you have been warned)", uid
);
185 // turn into a properly diabolical daemon unless debugMode is on
187 if (!Daemon::incarnate(doFork
))
188 exit(1); // can't daemonize
190 if (reExecute
&& !Daemon::executeSelf(argv
))
191 exit(1); // can't self-execute
194 // create a code signing engine
195 CodeSigning::OSXSigner signer
;
197 // create an Authorization engine
198 Authority
authority(authorizationConfig
);
200 // establish the ACL machinery
201 new AnyAclSubject::Maker();
202 new PasswordAclSubject::Maker();
203 new ProtectedPasswordAclSubject::Maker();
204 new ThresholdAclSubject::Maker();
205 new CommentAclSubject::Maker();
206 new ProcessAclSubject::Maker();
207 new CodeSignatureAclSubject::Maker(signer
);
208 new KeychainPromptAclSubject::Maker();
210 // add a temporary registration for a subject type that went out in 10.2 seed 1
211 // this should probably be removed for the next major release >10.2
212 new KeychainPromptAclSubject::Maker(CSSM_WORDID__RESERVED_1
);
214 // establish the code equivalents database
215 CodeSignatures
codeSignatures(equivDbFile
);
217 // create the main server object and register it
218 Server
server(authority
, codeSignatures
, bootstrapName
);
220 // Remember the primary service port to send signal events to.
221 gMainServerPort
= server
.primaryServicePort();
223 // set server configuration from arguments, if specified
225 server
.timeout(workerTimeout
);
227 server
.maxThreads(maxThreads
);
229 // add the RNG seed timer to it
231 EntropyManager
entropy(server
, entropyFile
);
233 if (!getuid()) new EntropyManager(server
, entropyFile
);
236 // create smartcard monitors to manage external token devices
237 PCSCMonitor
secureCards(server
);
239 // create the RootSession object (if -d, give it graphics and tty attributes)
240 RootSession
rootSession(server
.primaryServicePort(),
241 debugMode
? (sessionHasGraphicAccess
| sessionHasTTY
) : 0);
243 // set up signal handlers
244 if (signal(SIGCHLD
, handleSIGCHLD
) == SIG_ERR
)
245 secdebug("SS", "Cannot handle SIGCHLD: errno=%d", errno
);
246 if (signal(SIGINT
, handleSIGOther
) == SIG_ERR
)
247 secdebug("SS", "Cannot handle SIGINT: errno=%d", errno
);
248 if (signal(SIGTERM
, handleSIGOther
) == SIG_ERR
)
249 secdebug("SS", "Cannot handle SIGTERM: errno=%d", errno
);
251 if (signal(SIGUSR1
, handleSIGdebug
) == SIG_ERR
)
252 secdebug("SS", "Cannot handle SIGHUP: errno=%d", errno
);
255 // initialize CSSM now if requested
259 Syslog::notice("Entering service");
260 secdebug("SS", "%s initialized", bootstrapName
);
262 Debug::trace (kSecTraceSecurityServerInitialized
);
264 #ifdef PERFORMANCE_MEASUREMENT
265 // needed for automated timing of securityd startup
266 uint64_t endTime
= mach_absolute_time ();
268 // compute how long it took to initialize
269 uint64_t elapsedTime
= endTime
- startTime
;
270 mach_timebase_info_data_t multiplier
;
271 mach_timebase_info (&multiplier
);
273 elapsedTime
= elapsedTime
* multiplier
.numer
/ multiplier
.denom
;
275 FILE* f
= fopen ("/var/log/startuptime.txt", "a");
278 // probably not running as root.
279 f
= fopen ("/tmp/startuptime.txt", "a");
282 fprintf (f
, "%lld\n", elapsedTime
);
288 // fell out of runloop (should not happen)
289 Syslog::alert("Aborting");
295 // Issue usage message and die
297 static void usage(const char *me
)
299 fprintf(stderr
, "Usage: %s [-df] [-t maxthreads] [-T threadTimeout]"
300 "\t[-N bootstrapName] [-a authConfigFile]\n", me
);
306 // Handle SIGCHLD signals to reap our children (zombie cleanup)
308 static void handleSIGCHLD(int signal_number
)
310 kern_return_t kt
= ucsp_client_handleSignal(gMainServerPort
, mach_task_self(), signal_number
);
312 syslog(LOG_ERR
, "ucsp_client_handleSignal returned: %d", kt
);
317 // Handle some other signals to shut down cleanly (and with logging)
319 static void handleSIGOther(int sig
)
323 //secdebug("SS", "Interrupt signal; terminating");
324 Syslog::notice("received interrupt signal; terminating");
327 //secdebug("SS", "Termination signal; terminating");
328 Syslog::notice("received termination signal; terminating");
336 static void handleSIGdebug(int)