]> git.saurik.com Git - apple/security.git/blob - securityd/src/server.cpp
Security-58286.200.222.tar.gz
[apple/security.git] / securityd / src / server.cpp
1 /*
2 * Copyright (c) 2000-2010,2013 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 // server - securityd main server object
27 //
28 #include <securityd_client/ucsp.h> // MIG ucsp service
29 #include "self.h" // MIG self service
30 #include <security_utilities/logging.h>
31 #include <security_cdsa_client/mdsclient.h>
32 #include "server.h"
33 #include "session.h"
34 #include "acls.h"
35 #include "notifications.h"
36 #include "child.h"
37 #include <mach/mach_error.h>
38 #include <security_utilities/ccaudit.h>
39 #include <security_utilities/casts.h>
40 #include "pcscmonitor.h"
41
42 #include "agentquery.h"
43
44
45 using namespace MachPlusPlus;
46
47 //
48 // Construct the server object
49 //
50 Server::Server(CodeSignatures &signatures, const char *bootstrapName)
51 : MachServer(bootstrapName),
52 mBootstrapName(bootstrapName),
53 mCSPModule(gGuidAppleCSP, mCssm), mCSP(mCSPModule),
54 mCodeSignatures(signatures),
55 mVerbosity(0),
56 mWaitForClients(true), mShuttingDown(false)
57 {
58 // make me eternal (in the object mesh)
59 ref();
60
61 // engage the subsidiary port handler for sleep notifications
62 add(sleepWatcher);
63 }
64
65
66 //
67 // Clean up the server object
68 //
69 Server::~Server()
70 {
71 //@@@ more later
72 }
73
74
75 //
76 // Locate a connection by reply port and make it the current connection
77 // of this thread. The connection will be marked busy, and can be accessed
78 // by calling Server::connection() [no argument] until it is released by
79 // calling Connection::endWork().
80 //
81 Connection &Server::connection(mach_port_t port, audit_token_t &auditToken)
82 {
83 Server &server = active();
84 StLock<Mutex> _(server);
85 Connection *conn = server.mConnections.get(port, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
86 conn->process().checkSession(auditToken);
87 active().mCurrentConnection() = conn;
88 conn->beginWork(auditToken);
89 return *conn;
90 }
91
92 Connection &Server::connection(bool tolerant)
93 {
94 Connection *conn = active().mCurrentConnection();
95 assert(conn); // have to have one
96 if (!tolerant)
97 conn->checkWork();
98 return *conn;
99 }
100
101 void Server::requestComplete(CSSM_RETURN &rcode)
102 {
103 Server &server = active();
104 StLock<Mutex> lock(server);
105 // note: there may not be an active connection if connection setup failed
106 if (RefPointer<Connection> &conn = server.mCurrentConnection()) {
107 conn->endWork(rcode);
108 conn = NULL;
109 }
110 IFDUMPING("state", NodeCore::dumpAll());
111 }
112
113
114 //
115 // Shorthand for "current" process and session.
116 // This is the process and session for the current connection.
117 //
118 Process &Server::process()
119 {
120 return connection().process();
121 }
122
123 Session &Server::session()
124 {
125 return connection().process().session();
126 }
127
128 RefPointer<Key> Server::key(KeyHandle key)
129 {
130 return U32HandleObject::findRef<Key>(key, CSSMERR_CSP_INVALID_KEY_REFERENCE);
131 }
132
133 RefPointer<Database> Server::database(DbHandle db)
134 {
135 return find<Database>(db, CSSMERR_DL_INVALID_DB_HANDLE);
136 }
137
138 RefPointer<KeychainDatabase> Server::keychain(DbHandle db)
139 {
140 return find<KeychainDatabase>(db, CSSMERR_DL_INVALID_DB_HANDLE);
141 }
142
143 RefPointer<Database> Server::optionalDatabase(DbHandle db, bool persistent)
144 {
145 if (persistent && db != noDb)
146 return database(db);
147 else
148 return &process().localStore();
149 }
150
151
152 //
153 // Locate an ACL bearer (database or key) by handle
154 // The handle might be used across IPC, so we clamp it accordingly
155 //
156 AclSource &Server::aclBearer(AclKind kind, U32HandleObject::Handle handle)
157 {
158 AclSource &bearer = U32HandleObject::find<AclSource>(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE);
159 if (kind != bearer.acl().aclKind())
160 CssmError::throwMe(CSSMERR_CSSM_INVALID_HANDLE_USAGE);
161 return bearer;
162 }
163
164
165 //
166 // Run the server. This will not return until the server is forced to exit.
167 //
168 void Server::run()
169 {
170 MachServer::run(0x10000,
171 MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
172 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT));
173 }
174
175
176 //
177 // Handle thread overflow. MachServer will call this if it has hit its thread
178 // limit and yet still needs another thread.
179 //
180 void Server::threadLimitReached(UInt32 limit)
181 {
182 Syslog::notice("securityd has reached its thread limit (%d) - service deadlock is possible",
183 (uint32_t) limit);
184 }
185
186
187 //
188 // The primary server run-loop function.
189 // Invokes the MIG-generated main dispatch function (ucsp_server), as well
190 // as the self-send dispatch (self_server).
191 // For debug builds, look up request names in a MIG-generated table
192 // for better debug-log messages.
193 //
194 boolean_t ucsp_server(mach_msg_header_t *, mach_msg_header_t *);
195 boolean_t self_server(mach_msg_header_t *, mach_msg_header_t *);
196
197
198 boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out)
199 {
200 return ucsp_server(in, out) || self_server(in, out);
201 }
202
203
204 //
205 // Set up a new Connection. This establishes the environment (process et al) as needed
206 // and registers a properly initialized Connection object to run with.
207 // Type indicates how "deep" we need to initialize (new session, process, or connection).
208 // Everything at and below that level is constructed. This is straight-forward except
209 // in the case of session re-initialization (see below).
210 //
211 void Server::setupConnection(ConnectLevel type, Port replyPort, Port taskPort,
212 const audit_token_t &auditToken, const ClientSetupInfo *info)
213 {
214 Security::CommonCriteria::AuditToken audit(auditToken);
215
216 // first, make or find the process based on task port
217 StLock<Mutex> _(*this);
218 RefPointer<Process> &proc = mProcesses[taskPort];
219 if (proc && proc->session().sessionId() != audit.sessionId())
220 proc->changeSession(audit.sessionId());
221 if (proc && type == connectNewProcess) {
222 // the client has amnesia - reset it
223 assert(info);
224 proc->reset(taskPort, info, audit);
225 proc->changeSession(audit.sessionId());
226 }
227 if (!proc) {
228 if (type == connectNewThread) // client error (or attack)
229 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
230 assert(info);
231 proc = new Process(taskPort, info, audit);
232 notifyIfDead(taskPort);
233 mPids[proc->pid()] = proc;
234 }
235
236 // now, establish a connection and register it in the server
237 Connection *connection = new Connection(*proc, replyPort);
238 if (mConnections.contains(replyPort)) // malicious re-entry attempt?
239 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); //@@@ error code? (client error)
240 mConnections[replyPort] = connection;
241 notifyIfDead(replyPort);
242 }
243
244
245 //
246 // Synchronously end a Connection.
247 // This is due to a request from the client, so no thread races are possible.
248 // In practice, this is optional since the DPN for the client thread reply port
249 // will destroy the connection anyway when the thread dies.
250 //
251 void Server::endConnection(Port replyPort)
252 {
253 StLock<Mutex> _(*this);
254 PortMap<Connection>::iterator it = mConnections.find(replyPort);
255 assert(it != mConnections.end());
256 it->second->terminate();
257 mConnections.erase(it);
258 }
259
260
261 //
262 // Handling dead-port notifications.
263 // This receives DPNs for all kinds of ports we're interested in.
264 //
265 void Server::notifyDeadName(Port port)
266 {
267 // We need the lock to get a proper iterator on mConnections or mProcesses,
268 // but must release it before we call abort or kill, as these might take
269 // unbounded time, including calls out to token daemons etc.
270
271 StLock<Mutex> serverLock(*this);
272
273 // is it a connection?
274 PortMap<Connection>::iterator conIt = mConnections.find(port);
275 if (conIt != mConnections.end()) {
276 secinfo("SecServer", "%p dead connection %d", this, port.port());
277 RefPointer<Connection> con = conIt->second;
278 mConnections.erase(conIt);
279 serverLock.unlock();
280 con->abort();
281 return;
282 }
283
284 // is it a process?
285 PortMap<Process>::iterator procIt = mProcesses.find(port);
286 if (procIt != mProcesses.end()) {
287 secinfo("SecServer", "%p dead process %d", this, port.port());
288 RefPointer<Process> proc = procIt->second;
289 mPids.erase(proc->pid());
290 mProcesses.erase(procIt);
291 serverLock.unlock();
292 // The kill may take some time; make sure there is a spare thread around
293 // to prevent deadlocks
294 StLock<MachServer, &Server::busy, &Server::idle> _(*this);
295 proc->kill();
296 return;
297 }
298
299 // well, what IS IT?!
300 secnotice("server", "spurious dead port notification for port %d", port.port());
301 }
302
303
304 //
305 // Handling no-senders notifications.
306 // This is currently only used for (subsidiary) service ports
307 //
308 void Server::notifyNoSenders(Port port, mach_port_mscount_t)
309 {
310 secinfo("SecServer", "%p dead session %d", this, port.port());
311 }
312
313
314 //
315 // Handling signals.
316 // These are sent as Mach messages from ourselves to escape the limitations of
317 // the signal handler environment.
318 //
319 kern_return_t self_server_handleSignal(mach_port_t sport,
320 mach_port_t taskPort, int sig)
321 {
322 try {
323 secnotice("SecServer", "signal handled %d", sig);
324 if (taskPort != mach_task_self()) {
325 Syslog::error("handleSignal: received from someone other than myself");
326 return KERN_SUCCESS;
327 }
328 switch (sig) {
329 case SIGCHLD:
330 ServerChild::checkChildren();
331 break;
332 case SIGINT:
333 secnotice("SecServer", "shutdown due to SIGINT");
334 Syslog::notice("securityd terminated due to SIGINT");
335 _exit(0);
336 case SIGTERM:
337 Server::active().beginShutdown();
338 break;
339 case SIGPIPE:
340 fprintf(stderr, "securityd ignoring SIGPIPE received");
341 break;
342
343 #if defined(DEBUGDUMP)
344 case SIGUSR1:
345 NodeCore::dumpAll();
346 break;
347 #endif //DEBUGDUMP
348
349 case SIGUSR2:
350 {
351 extern PCSCMonitor *gPCSC;
352 gPCSC->startSoftTokens();
353 break;
354 }
355
356 default:
357 assert(false);
358 }
359 } catch(...) {
360 secnotice("SecServer", "exception handling a signal (ignored)");
361 }
362 mach_port_deallocate(mach_task_self(), taskPort);
363 return KERN_SUCCESS;
364 }
365
366
367 kern_return_t self_server_handleSession(mach_port_t sport,
368 mach_port_t taskPort, uint32_t event, uint64_t ident)
369 {
370 try {
371 if (taskPort != mach_task_self()) {
372 Syslog::error("handleSession: received from someone other than myself");
373 mach_port_deallocate(mach_task_self(), taskPort);
374 return KERN_SUCCESS;
375 }
376 if (event == AUE_SESSION_END)
377 Session::destroy(int_cast<uint64_t, Session::SessionId>(ident));
378 } catch(...) {
379 secnotice("SecServer", "exception handling a signal (ignored)");
380 }
381 mach_port_deallocate(mach_task_self(), taskPort);
382 return KERN_SUCCESS;
383 }
384
385
386 //
387 // Notifier for system sleep events
388 //
389 void Server::SleepWatcher::systemWillSleep()
390 {
391 secnotice("SecServer", "%p will sleep", this);
392 Session::processSystemSleep();
393 for (set<PowerWatcher *>::const_iterator it = mPowerClients.begin(); it != mPowerClients.end(); it++)
394 (*it)->systemWillSleep();
395 }
396
397 void Server::SleepWatcher::systemIsWaking()
398 {
399 secnotice("SecServer", "%p is waking", this);
400 for (set<PowerWatcher *>::const_iterator it = mPowerClients.begin(); it != mPowerClients.end(); it++)
401 (*it)->systemIsWaking();
402 }
403
404 void Server::SleepWatcher::systemWillPowerOn()
405 {
406 secnotice("SecServer", "%p will power on", this);
407 Server::active().longTermActivity();
408 for (set<PowerWatcher *>::const_iterator it = mPowerClients.begin(); it != mPowerClients.end(); it++)
409 (*it)->systemWillPowerOn();
410 }
411
412 void Server::SleepWatcher::add(PowerWatcher *client)
413 {
414 assert(mPowerClients.find(client) == mPowerClients.end());
415 mPowerClients.insert(client);
416 }
417
418 void Server::SleepWatcher::remove(PowerWatcher *client)
419 {
420 assert(mPowerClients.find(client) != mPowerClients.end());
421 mPowerClients.erase(client);
422 }
423
424
425 //
426 // Expose the process/pid map to the outside
427 //
428 Process *Server::findPid(pid_t pid) const
429 {
430 PidMap::const_iterator it = mPids.find(pid);
431 return (it == mPids.end()) ? NULL : it->second;
432 }
433
434
435 //
436 // Set delayed shutdown mode
437 //
438 void Server::waitForClients(bool waiting)
439 {
440 mWaitForClients = waiting;
441 }
442
443
444 //
445 // Begin shutdown processing.
446 // We relinquish our primary state authority. From now on, we'll be
447 // kept alive (only) by our current clients.
448 //
449 static FILE *reportFile;
450
451 void Server::beginShutdown()
452 {
453 StLock<Mutex> _(*this);
454 if (!mWaitForClients) {
455 secnotice("SecServer", "%p shutting down now", this);
456 _exit(0);
457 } else {
458 if (!mShuttingDown) {
459 mShuttingDown = true;
460 Session::invalidateAuthHosts();
461 secnotice("SecServer", "%p beginning shutdown", this);
462 if (verbosity() >= 2) {
463 reportFile = fopen("/var/log/securityd-shutdown.log", "w");
464 shutdownSnitch();
465 }
466 }
467 }
468 }
469
470
471 //
472 // During shutdown, we report residual clients to dtrace, and allow a state dump
473 // for debugging.
474 // We don't bother locking for the shuttingDown() check; it's a latching boolean
475 // and we'll be good enough without a lock.
476 //
477 void Server::eventDone()
478 {
479 StLock<Mutex> lock(*this);
480 if (this->shuttingDown()) {
481 if (verbosity() >= 2) {
482 secnotice("SecServer", "shutting down with %ld processes and %ld transactions", mProcesses.size(), VProc::Transaction::debugCount());
483 shutdownSnitch();
484 }
485 IFDUMPING("shutdown", NodeCore::dumpAll());
486 }
487 }
488
489
490 void Server::shutdownSnitch()
491 {
492 time_t now;
493 time(&now);
494 fprintf(reportFile, "%.24s %d residual clients:\n", ctime(&now), int(mPids.size()));
495 for (PidMap::const_iterator it = mPids.begin(); it != mPids.end(); ++it) {
496 string path = it->second->getPath();
497 fprintf(reportFile, " %s (%d)\n", path.c_str(), it->first);
498 }
499 fprintf(reportFile, "\n");
500 fflush(reportFile);
501 }
502
503 bool Server::inDarkWake()
504 {
505 return IOPMIsADarkWake(IOPMConnectionGetSystemCapabilities());
506 }
507
508 //
509 // Initialize the CSSM/MDS subsystem.
510 // This was once done lazily on demand. These days, we are setting up the
511 // system MDS here, and CSSM is pretty much always needed, so this is called
512 // early during program startup. Do note that the server may not (yet) be running.
513 //
514 void Server::loadCssm(bool mdsIsInstalled)
515 {
516 if (!mCssm->isActive()) {
517 StLock<Mutex> _(*this);
518 VProc::Transaction xact;
519 if (!mCssm->isActive()) {
520 if (!mdsIsInstalled) { // non-system securityd instance should not reinitialize MDS
521 secnotice("SecServer", "Installing MDS");
522 IFDEBUG(if (geteuid() == 0))
523 MDSClient::mds().install();
524 }
525 secnotice("SecServer", "CSSM initializing");
526 mCssm->init();
527 mCSP->attach();
528 secnotice("SecServer", "CSSM ready with CSP %s", mCSP->guid().toString().c_str());
529 }
530 }
531 }
532
533
534 //
535 // LongtermActivity/lock combo
536 //
537 LongtermStLock::LongtermStLock(Mutex &lck)
538 : StLock<Mutex>(lck, false) // don't take the lock yet
539 {
540 if (lck.tryLock()) { // uncontested
541 this->mActive = true;
542 } else { // contested - need backup thread
543 Server::active().longTermActivity();
544 this->lock();
545 }
546 }