]> git.saurik.com Git - apple/security.git/blob - securityd/src/main.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / securityd / src / main.cpp
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"
31 #include "session.h"
32 #include "notifications.h"
33 #include "auditevents.h"
34 #include "self.h"
35 #include "util.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"
59 #include "acl_partition.h"
60
61 #include <sandbox.h>
62
63 //
64 // Local functions of the main program driver
65 //
66 static void usage(const char *me) __attribute__((noreturn));
67 static void handleSignals(int sig);
68
69 static Port gMainServerPort;
70
71
72 //
73 // Main driver
74 //
75 int main(int argc, char *argv[])
76 {
77 DisableLocalization();
78
79 // clear the umask - we know what we're doing
80 secnotice("SecServer", "starting umask was 0%o", ::umask(0));
81 ::umask(0);
82
83 // tell the keychain (client) layer to turn off the server interface
84 SecKeychainSetServerMode();
85
86 const char *params[] = {"LEGACY_TOKENS_ENABLED", "NO", NULL};
87 char* errorbuf = NULL;
88 if (sandbox_init_with_parameters("com.apple.securityd", SANDBOX_NAMED, params, &errorbuf)) {
89 seccritical("SecServer: unable to enter sandbox: %{public}s", errorbuf);
90 if (errorbuf) {
91 sandbox_free_error(errorbuf);
92 }
93 exit(1);
94 } else {
95 secnotice("SecServer", "entered sandbox");
96 }
97
98 // program arguments (preset to defaults)
99 bool debugMode = false;
100 int workerTimeout = 0;
101 int maxThreads = 0;
102 bool waitForClients = true;
103 bool mdsIsInstalled = false;
104 uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
105 unsigned int verbose = 0;
106
107 // check for the Installation-DVD environment and modify some default arguments if found
108 if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists
109 secnotice("SecServer", "starting in installmode");
110 }
111
112 // parse command line arguments
113 extern char *optarg;
114 extern int optind;
115 int arg;
116 while ((arg = getopt(argc, argv, ":dE:im:t:T:uvW")) != -1) {
117 switch (arg) {
118 case 'd':
119 debugMode = true;
120 break;
121 case 'E':
122 /* was entropyFile, kept to preserve ABI */
123 break;
124 case 'i':
125 keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID;
126 break;
127 case 'm':
128 mdsIsInstalled = true;
129 break;
130 case 't':
131 if ((maxThreads = atoi(optarg)) < 0)
132 maxThreads = 0;
133 break;
134 case 'T':
135 if ((workerTimeout = atoi(optarg)) < 0)
136 workerTimeout = 0;
137 break;
138 case 'W':
139 waitForClients = false;
140 break;
141 case 'u':
142 keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
143 break;
144 case 'v':
145 verbose++;
146 break;
147 default:
148 usage(argv[0]);
149 }
150 }
151
152 // take no non-option arguments
153 if (optind < argc) {
154 usage(argv[0]);
155 }
156
157 const char *bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME;
158 const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName;
159
160 // configure logging first
161 if (debugMode) {
162 Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR);
163 Syslog::notice("%s started in debug mode", argv[0]);
164 } else {
165 Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS);
166 }
167
168 // if we're not running as root in production mode, fail
169 // in debug mode, issue a warning
170 if (uid_t uid = getuid()) {
171 #if defined(NDEBUG)
172 Syslog::alert("Tried to run securityd as user %d: aborted", uid);
173 fprintf(stderr, "You are not allowed to run securityd\n");
174 exit(1);
175 #else
176 fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid);
177 #endif //NDEBUG
178 }
179
180 // turn into a properly diabolical daemon unless debugMode is on
181 if (!debugMode && getppid() != 1 && !Daemon::incarnate(false)) {
182 exit(1); // can't daemonize
183 }
184
185 // arm signal handlers; code below may generate signals we want to see
186 if (signal(SIGCHLD, handleSignals) == SIG_ERR
187 || signal(SIGINT, handleSignals) == SIG_ERR
188 || signal(SIGTERM, handleSignals) == SIG_ERR
189 || signal(SIGPIPE, handleSignals) == SIG_ERR
190 #if !defined(NDEBUG)
191 || signal(SIGUSR1, handleSignals) == SIG_ERR
192 #endif //NDEBUG
193 || signal(SIGUSR2, handleSignals) == SIG_ERR) {
194 perror("signal");
195 exit(1);
196 }
197
198 // The clang static analyzer isn't a big fan of our "object creation hooks object into global pointer graph" model.
199 // Tell it not to worry.
200 #ifndef __clang_analyzer__
201 // introduce all supported ACL subject types
202 new AnyAclSubject::Maker();
203 new PasswordAclSubject::Maker();
204 new ProtectedPasswordAclSubject::Maker();
205 new PromptedAclSubject::Maker();
206 new ThresholdAclSubject::Maker();
207 new CommentAclSubject::Maker();
208 new ProcessAclSubject::Maker();
209 new CodeSignatureAclSubject::Maker();
210 new KeychainPromptAclSubject::Maker(keychainAclDefault);
211 new PartitionAclSubject::Maker();
212 new PreAuthorizationAcls::OriginMaker();
213 new PreAuthorizationAcls::SourceMaker();
214 #endif
215 // establish the code equivalents database
216 CodeSignatures codeSignatures;
217
218
219 // create the main server object and register it
220 Server server(codeSignatures, bootstrapName);
221
222 // Remember the primary service port to send signal events to
223 gMainServerPort = server.primaryServicePort();
224
225 // set server configuration from arguments, if specified
226 if (workerTimeout)
227 server.timeout(workerTimeout);
228 if (maxThreads)
229 server.maxThreads(maxThreads);
230 server.floatingThread(true);
231 server.waitForClients(waitForClients);
232 server.verbosity(verbose);
233
234 // create the RootSession object (if -d, give it graphics and tty attributes)
235 RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server);
236
237 // create a monitor thread to watch for audit session events
238 AuditMonitor audits(gMainServerPort);
239 audits.run();
240
241 // install MDS (if needed) and initialize the local CSSM
242 server.loadCssm(mdsIsInstalled);
243
244 #ifndef __clang_analyzer__
245 // create the shared memory notification hub
246 new SharedMemoryListener(messagingName, kSharedMemoryPoolSize);
247 #endif
248
249
250 // okay, we're ready to roll
251 secnotice("SecServer", "Entering service as %s", (char*)bootstrapName);
252 Syslog::notice("Entering service");
253
254 // go
255 server.run();
256
257 // fell out of runloop (should not happen)
258 Syslog::alert("Aborting");
259 return 1;
260 }
261
262
263 //
264 // Issue usage message and die
265 //
266 static void usage(const char *me)
267 {
268 fprintf(stderr, "Usage: %s [-dwX]"
269 "\n\t[-e equivDatabase] path to code equivalence database"
270 "\n\t[-t maxthreads] [-T threadTimeout] server thread control"
271 "\n", me);
272 exit(2);
273 }
274
275 const CFStringRef kTKSmartCardPreferencesDomain = CFSTR("com.apple.security.smartcard");
276 const CFStringRef kTKLegacyTokendPreferencesKey = CFSTR("Legacy");
277
278 //
279 // Handle signals.
280 // We send ourselves a message (through the "self" service), so actual
281 // actions happen on the normal event loop path. Note that another thread
282 // may be picking up the message immediately.
283 //
284 static void handleSignals(int sig)
285 {
286 (void)self_client_handleSignal(gMainServerPort, mach_task_self(), sig);
287 }