]> git.saurik.com Git - apple/security.git/blame - securityd/src/main.cpp
Security-58286.51.6.tar.gz
[apple/security.git] / securityd / src / main.cpp
CommitLineData
d8f41ccd
A
1/*
2 * Copyright (c) 2000-2009,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// securityd - Apple security services daemon.
27//
28#include <securityd_client/ucsp.h>
29
30#include "server.h"
d8f41ccd
A
31#include "session.h"
32#include "notifications.h"
33#include "pcscmonitor.h"
34#include "auditevents.h"
35#include "self.h"
36
37#include <security_utilities/daemon.h>
38#include <security_utilities/machserver.h>
39#include <security_utilities/logging.h>
40
41#include <Security/SecKeychainPriv.h>
42
43#include <unistd.h>
44#include <sys/types.h>
45#include <signal.h>
46#include <syslog.h>
47
48// ACL subject types (their makers are instantiated here)
49#include <security_cdsa_utilities/acl_any.h>
50#include <security_cdsa_utilities/acl_password.h>
51#include <security_cdsa_utilities/acl_prompted.h>
52#include <security_cdsa_utilities/acl_protectedpw.h>
53#include <security_cdsa_utilities/acl_threshold.h>
54#include <security_cdsa_utilities/acl_codesigning.h>
55#include <security_cdsa_utilities/acl_process.h>
56#include <security_cdsa_utilities/acl_comment.h>
57#include <security_cdsa_utilities/acl_preauth.h>
58#include "acl_keychain.h"
e3d460c9 59#include "acl_partition.h"
d8f41ccd
A
60
61
62//
63// Local functions of the main program driver
64//
65static void usage(const char *me) __attribute__((noreturn));
66static void handleSignals(int sig);
67static PCSCMonitor::ServiceLevel scOptions(const char *optionString);
68
69
70static Port gMainServerPort;
71PCSCMonitor *gPCSC;
72
73
74//
75// Main driver
76//
77int main(int argc, char *argv[])
78{
79 // clear the umask - we know what we're doing
fa7225c8 80 secnotice("SS", "starting umask was 0%o", ::umask(0));
d8f41ccd
A
81 ::umask(0);
82
83 // tell the keychain (client) layer to turn off the server interface
84 SecKeychainSetServerMode();
85
86 // program arguments (preset to defaults)
87 bool debugMode = false;
88 const char *bootstrapName = NULL;
6b200bc3 89 const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName;
d8f41ccd
A
90 bool doFork = false;
91 bool reExecute = false;
92 int workerTimeout = 0;
93 int maxThreads = 0;
94 bool waitForClients = true;
95 bool mdsIsInstalled = false;
d8f41ccd 96 const char *tokenCacheDir = "/var/db/TokenCache";
d8f41ccd
A
97 const char *smartCardOptions = getenv("SMARTCARDS");
98 uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
99 unsigned int verbose = 0;
100
101 // check for the Installation-DVD environment and modify some default arguments if found
102 if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists
fa7225c8 103 secnotice("SS", "starting in installmode");
d8f41ccd
A
104 smartCardOptions = "off"; // needs writable directories that aren't
105 }
106
107 // parse command line arguments
108 extern char *optarg;
109 extern int optind;
110 int arg;
fa7225c8 111 while ((arg = getopt(argc, argv, "c:dE:imN:s:t:T:uvWX")) != -1) {
d8f41ccd 112 switch (arg) {
d8f41ccd
A
113 case 'c':
114 tokenCacheDir = optarg;
115 break;
116 case 'd':
117 debugMode = true;
118 break;
d8f41ccd 119 case 'E':
6b200bc3 120 /* was entropyFile, kept to preserve ABI */
d8f41ccd
A
121 break;
122 case 'i':
123 keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID;
124 break;
125 case 'm':
126 mdsIsInstalled = true;
127 break;
128 case 'N':
129 bootstrapName = optarg;
130 break;
131 case 's':
132 smartCardOptions = optarg;
133 break;
134 case 't':
135 if ((maxThreads = atoi(optarg)) < 0)
136 maxThreads = 0;
137 break;
138 case 'T':
139 if ((workerTimeout = atoi(optarg)) < 0)
140 workerTimeout = 0;
141 break;
142 case 'W':
143 waitForClients = false;
144 break;
145 case 'u':
146 keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
147 break;
148 case 'v':
149 verbose++;
150 break;
151 case 'X':
152 doFork = true;
153 reExecute = true;
154 break;
155 default:
156 usage(argv[0]);
157 }
158 }
159
160 // take no non-option arguments
161 if (optind < argc)
162 usage(argv[0]);
163
164 // figure out the bootstrap name
165 if (!bootstrapName) {
166 bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV);
167 if (!bootstrapName)
168 {
169 bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME;
170 }
171 else
172 {
866f8763 173#ifndef __clang_analyzer__
d8f41ccd 174 messagingName = bootstrapName;
866f8763 175#endif
d8f41ccd
A
176 }
177 }
178 else
179 {
866f8763 180#ifndef __clang_analyzer__
d8f41ccd 181 messagingName = bootstrapName;
866f8763 182#endif
d8f41ccd
A
183 }
184
185 // configure logging first
186 if (debugMode) {
187 Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR);
188 Syslog::notice("%s started in debug mode", argv[0]);
189 } else {
190 Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS);
191 }
192
193 // if we're not running as root in production mode, fail
194 // in debug mode, issue a warning
195 if (uid_t uid = getuid()) {
196#if defined(NDEBUG)
197 Syslog::alert("Tried to run securityd as user %d: aborted", uid);
198 fprintf(stderr, "You are not allowed to run securityd\n");
199 exit(1);
200#else
201 fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid);
202#endif //NDEBUG
203 }
204
205 // turn into a properly diabolical daemon unless debugMode is on
206 if (!debugMode && getppid() != 1) {
207 if (!Daemon::incarnate(doFork))
208 exit(1); // can't daemonize
209
210 if (reExecute && !Daemon::executeSelf(argv))
211 exit(1); // can't self-execute
212 }
213
214 // arm signal handlers; code below may generate signals we want to see
215 if (signal(SIGCHLD, handleSignals) == SIG_ERR
216 || signal(SIGINT, handleSignals) == SIG_ERR
217 || signal(SIGTERM, handleSignals) == SIG_ERR
218 || signal(SIGPIPE, handleSignals) == SIG_ERR
219#if !defined(NDEBUG)
220 || signal(SIGUSR1, handleSignals) == SIG_ERR
221#endif //NDEBUG
222 || signal(SIGUSR2, handleSignals) == SIG_ERR) {
223 perror("signal");
224 exit(1);
225 }
226
866f8763
A
227// The clang static analyzer isn't a big fan of our "object creation hooks object into global pointer graph" model.
228// Tell it not to worry.
229#ifndef __clang_analyzer__
d8f41ccd
A
230 // introduce all supported ACL subject types
231 new AnyAclSubject::Maker();
232 new PasswordAclSubject::Maker();
233 new ProtectedPasswordAclSubject::Maker();
234 new PromptedAclSubject::Maker();
235 new ThresholdAclSubject::Maker();
e3d460c9 236 new CommentAclSubject::Maker();
d8f41ccd
A
237 new ProcessAclSubject::Maker();
238 new CodeSignatureAclSubject::Maker();
e3d460c9
A
239 new KeychainPromptAclSubject::Maker(keychainAclDefault);
240 new PartitionAclSubject::Maker();
241 new PreAuthorizationAcls::OriginMaker();
d8f41ccd 242 new PreAuthorizationAcls::SourceMaker();
866f8763 243#endif
5c19dc3a
A
244 // establish the code equivalents database
245 CodeSignatures codeSignatures;
246
866f8763 247
d8f41ccd 248 // create the main server object and register it
fa7225c8 249 Server server(codeSignatures, bootstrapName);
d8f41ccd
A
250
251 // Remember the primary service port to send signal events to
252 gMainServerPort = server.primaryServicePort();
253
254 // set server configuration from arguments, if specified
255 if (workerTimeout)
256 server.timeout(workerTimeout);
257 if (maxThreads)
258 server.maxThreads(maxThreads);
259 server.floatingThread(true);
260 server.waitForClients(waitForClients);
261 server.verbosity(verbose);
262
d8f41ccd
A
263 // create a smartcard monitor to manage external token devices
264 gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions));
265
266 // create the RootSession object (if -d, give it graphics and tty attributes)
267 RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server);
268
269 // create a monitor thread to watch for audit session events
270 AuditMonitor audits(gMainServerPort);
271 audits.run();
272
273 // install MDS (if needed) and initialize the local CSSM
274 server.loadCssm(mdsIsInstalled);
866f8763 275
6b200bc3 276#ifndef __clang_analyzer__
866f8763 277 // create the shared memory notification hub
d8f41ccd 278 new SharedMemoryListener(messagingName, kSharedMemoryPoolSize);
866f8763
A
279#endif
280
6b200bc3 281
d8f41ccd 282 // okay, we're ready to roll
fa7225c8 283 secnotice("SS", "Entering service as %s", (char*)bootstrapName);
d8f41ccd
A
284 Syslog::notice("Entering service");
285
286 // go
287 server.run();
288
289 // fell out of runloop (should not happen)
290 Syslog::alert("Aborting");
291 return 1;
292}
293
294
295//
296// Issue usage message and die
297//
298static void usage(const char *me)
299{
300 fprintf(stderr, "Usage: %s [-dwX]"
d8f41ccd
A
301 "\n\t[-c tokencache] smartcard token cache directory"
302 "\n\t[-e equivDatabase] path to code equivalence database"
303 "\n\t[-N serviceName] MACH service name"
304 "\n\t[-s off|on|conservative|aggressive] smartcard operation level"
305 "\n\t[-t maxthreads] [-T threadTimeout] server thread control"
306 "\n", me);
307 exit(2);
308}
309
310
311//
312// Translate strings (e.g. "conservative") into PCSCMonitor service levels
313//
314static PCSCMonitor::ServiceLevel scOptions(const char *optionString)
315{
316 if (optionString)
317 if (!strcmp(optionString, "off"))
318 return PCSCMonitor::forcedOff;
319 else if (!strcmp(optionString, "on"))
320 return PCSCMonitor::externalDaemon;
321 else if (!strcmp(optionString, "conservative"))
322 return PCSCMonitor::externalDaemon;
323 else if (!strcmp(optionString, "aggressive"))
324 return PCSCMonitor::externalDaemon;
325 else if (!strcmp(optionString, "external"))
326 return PCSCMonitor::externalDaemon;
327 else
328 usage("securityd");
329 else
330 return PCSCMonitor::externalDaemon;
331}
332
333
334//
335// Handle signals.
336// We send ourselves a message (through the "self" service), so actual
337// actions happen on the normal event loop path. Note that another thread
338// may be picking up the message immediately.
339//
340static void handleSignals(int sig)
341{
866f8763 342 (void)self_client_handleSignal(gMainServerPort, mach_task_self(), sig);
d8f41ccd 343}