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