2  * Copyright (c) 2000-2010,2013 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 // server - securityd main server object 
  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> 
  35 #include "notifications.h" 
  37 #include <mach/mach_error.h> 
  38 #include <security_utilities/ccaudit.h> 
  39 #include "pcscmonitor.h" 
  41 #include "agentquery.h" 
  44 using namespace MachPlusPlus
; 
  47 // Construct an Authority 
  49 Authority::Authority(const char *configFile
) 
  50 : Authorization::Engine(configFile
) 
  54 Authority::~Authority() 
  60 // Construct the server object 
  62 Server::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
),  
  69         mWaitForClients(true), mShuttingDown(false) 
  71         // make me eternal (in the object mesh) 
  74     // engage the subsidiary port handler for sleep notifications 
  80 // Clean up the server object 
  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(). 
  94 Connection 
&Server::connection(mach_port_t port
, audit_token_t 
&auditToken
) 
  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
); 
 105 Connection 
&Server::connection(bool tolerant
) 
 107         Connection 
*conn 
= active().mCurrentConnection(); 
 108         assert(conn
);   // have to have one 
 114 void Server::requestComplete(CSSM_RETURN 
&rcode
) 
 116         // note: there may not be an active connection if connection setup failed 
 117         if (RefPointer
<Connection
> &conn 
= active().mCurrentConnection()) { 
 118                 conn
->endWork(rcode
); 
 121         IFDUMPING("state", NodeCore::dumpAll()); 
 126 // Shorthand for "current" process and session. 
 127 // This is the process and session for the current connection. 
 129 Process 
&Server::process() 
 131         return connection().process(); 
 134 Session 
&Server::session() 
 136         return connection().process().session(); 
 139 RefPointer
<Key
> Server::key(KeyHandle key
) 
 141         return U32HandleObject::findRef
<Key
>(key
, CSSMERR_CSP_INVALID_KEY_REFERENCE
); 
 144 RefPointer
<Database
> Server::database(DbHandle db
) 
 146         return find
<Database
>(db
, CSSMERR_DL_INVALID_DB_HANDLE
); 
 149 RefPointer
<KeychainDatabase
> Server::keychain(DbHandle db
) 
 151         return find
<KeychainDatabase
>(db
, CSSMERR_DL_INVALID_DB_HANDLE
); 
 154 RefPointer
<Database
> Server::optionalDatabase(DbHandle db
, bool persistent
) 
 156         if (persistent 
&& db 
!= noDb
) 
 159                 return &process().localStore(); 
 164 // Locate an ACL bearer (database or key) by handle 
 165 // The handle might be used across IPC, so we clamp it accordingly 
 167 AclSource 
&Server::aclBearer(AclKind kind
, U32HandleObject::Handle handle
) 
 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
); 
 177 // Run the server. This will not return until the server is forced to exit. 
 181         MachServer::run(0x10000, 
 182         MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0
) | 
 183         MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT
)); 
 188 // Handle thread overflow. MachServer will call this if it has hit its thread 
 189 // limit and yet still needs another thread. 
 191 void Server::threadLimitReached(UInt32 limit
) 
 193         Syslog::notice("securityd has reached its thread limit (%ld) - service deadlock is possible", 
 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. 
 205 boolean_t 
ucsp_server(mach_msg_header_t 
*, mach_msg_header_t 
*); 
 206 boolean_t 
self_server(mach_msg_header_t 
*, mach_msg_header_t 
*); 
 209 boolean_t 
Server::handle(mach_msg_header_t 
*in
, mach_msg_header_t 
*out
) 
 211         return ucsp_server(in
, out
) || self_server(in
, out
); 
 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). 
 222 void Server::setupConnection(ConnectLevel type
, Port replyPort
, Port taskPort
, 
 223     const audit_token_t 
&auditToken
, const ClientSetupInfo 
*info
) 
 225         AuditToken 
audit(auditToken
); 
 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 
 235                 proc
->reset(taskPort
, info
, audit
); 
 236                 proc
->changeSession(audit
.sessionId()); 
 239                 if (type 
== connectNewThread
)   // client error (or attack) 
 240                         CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
); 
 242                 proc 
= new Process(taskPort
, info
, audit
); 
 243                 notifyIfDead(taskPort
); 
 244                 mPids
[proc
->pid()] = proc
; 
 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
); 
 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. 
 262 void Server::endConnection(Port replyPort
) 
 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
); 
 273 // Handling dead-port notifications. 
 274 // This receives DPNs for all kinds of ports we're interested in. 
 276 void Server::notifyDeadName(Port port
) 
 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. 
 282         StLock
<Mutex
> serverLock(*this); 
 283         secdebug("SSports", "port %d is dead", port
.port()); 
 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
); 
 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
); 
 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); 
 311         // well, what IS IT?! 
 312         SECURITYD_PORTS_DEAD_ORPHAN(port
); 
 313         secdebug("server", "spurious dead port notification for port %d", port
.port()); 
 318 // Handling no-senders notifications. 
 319 // This is currently only used for (subsidiary) service ports 
 321 void Server::notifyNoSenders(Port port
, mach_port_mscount_t
) 
 323         SECURITYD_PORTS_DEAD_SESSION(port
); 
 329 // These are sent as Mach messages from ourselves to escape the limitations of 
 330 // the signal handler environment. 
 332 kern_return_t 
self_server_handleSignal(mach_port_t sport
, 
 333         mach_port_t taskPort
, int sig
) 
 336                 SECURITYD_SIGNAL_HANDLED(sig
); 
 337         if (taskPort 
!= mach_task_self()) { 
 338             Syslog::error("handleSignal: received from someone other than myself"); 
 343                         ServerChild::checkChildren(); 
 346                         SECURITYD_SHUTDOWN_NOW(); 
 347                         Syslog::notice("securityd terminated due to SIGINT"); 
 350                         Server::active().beginShutdown(); 
 353                         fprintf(stderr
, "securityd ignoring SIGPIPE received"); 
 356 #if defined(DEBUGDUMP) 
 364                                 extern PCSCMonitor 
*gPCSC
; 
 365                                 gPCSC
->startSoftTokens(); 
 373                 secdebug("SS", "exception handling a signal (ignored)"); 
 375     mach_port_deallocate(mach_task_self(), taskPort
); 
 380 kern_return_t 
self_server_handleSession(mach_port_t sport
, 
 381         mach_port_t taskPort
, uint32_t event
, uint64_t ident
) 
 384         if (taskPort 
!= mach_task_self()) { 
 385             Syslog::error("handleSession: received from someone other than myself"); 
 388                 if (event 
== AUE_SESSION_CLOSE
) 
 389                         Session::destroy(ident
); 
 391                 secdebug("SS", "exception handling a signal (ignored)"); 
 393     mach_port_deallocate(mach_task_self(), taskPort
); 
 399 // Notifier for system sleep events 
 401 void Server::SleepWatcher::systemWillSleep() 
 403         SECURITYD_POWER_SLEEP(); 
 404     Session::processSystemSleep(); 
 405         for (set
<PowerWatcher 
*>::const_iterator it 
= mPowerClients
.begin(); it 
!= mPowerClients
.end(); it
++) 
 406                 (*it
)->systemWillSleep(); 
 409 void Server::SleepWatcher::systemIsWaking() 
 411         SECURITYD_POWER_WAKE(); 
 412         for (set
<PowerWatcher 
*>::const_iterator it 
= mPowerClients
.begin(); it 
!= mPowerClients
.end(); it
++) 
 413                 (*it
)->systemIsWaking(); 
 416 void Server::SleepWatcher::systemWillPowerOn() 
 418         SECURITYD_POWER_ON(); 
 419         Server::active().longTermActivity(); 
 420         for (set
<PowerWatcher 
*>::const_iterator it 
= mPowerClients
.begin(); it 
!= mPowerClients
.end(); it
++) 
 421                 (*it
)->systemWillPowerOn(); 
 424 void Server::SleepWatcher::add(PowerWatcher 
*client
) 
 426         assert(mPowerClients
.find(client
) == mPowerClients
.end()); 
 427         mPowerClients
.insert(client
); 
 430 void Server::SleepWatcher::remove(PowerWatcher 
*client
) 
 432         assert(mPowerClients
.find(client
) != mPowerClients
.end()); 
 433         mPowerClients
.erase(client
); 
 438 // Expose the process/pid map to the outside 
 440 Process 
*Server::findPid(pid_t pid
) const 
 442         PidMap::const_iterator it 
= mPids
.find(pid
); 
 443         return (it 
== mPids
.end()) ? NULL 
: it
->second
; 
 448 // Set delayed shutdown mode 
 450 void Server::waitForClients(bool waiting
) 
 452         mWaitForClients 
= waiting
; 
 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. 
 461 static FILE *reportFile
; 
 463 void Server::beginShutdown() 
 465         StLock
<Mutex
> _(*this); 
 466         if (!mWaitForClients
) { 
 467                 SECURITYD_SHUTDOWN_NOW(); 
 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"); 
 484 // During shutdown, we report residual clients to dtrace, and allow a state dump 
 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. 
 489 void Server::eventDone() 
 491         if (this->shuttingDown()) { 
 492                 StLock
<Mutex
> lazy(*this, false);       // lazy lock acquisition 
 493                 if (SECURITYD_SHUTDOWN_COUNT_ENABLED()) { 
 495                         SECURITYD_SHUTDOWN_COUNT(mProcesses
.size(), VProc::Transaction::debugCount()); 
 497                 if (verbosity() >= 2) { 
 501                 IFDUMPING("shutdown", NodeCore::dumpAll()); 
 506 void Server::shutdownSnitch() 
 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()); 
 516                                 fprintf(reportFile
, " %s (%d)\n", cfString(path
).c_str(), it
->first
); 
 518                                 fprintf(reportFile
,  "pid=%d (error %d)\n", it
->first
, int32_t(rc
)); 
 520         fprintf(reportFile
, "\n"); 
 524 bool Server::inDarkWake() 
 526     return IOPMIsADarkWake(IOPMConnectionGetSystemCapabilities()); 
 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. 
 535 void Server::loadCssm(bool mdsIsInstalled
) 
 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(); 
 546                         secdebug("SS", "CSSM initializing"); 
 549                         secdebug("SS", "CSSM ready with CSP %s", mCSP
->guid().toString().c_str()); 
 556 // LongtermActivity/lock combo 
 558 LongtermStLock::LongtermStLock(Mutex 
&lck
) 
 559         : StLock
<Mutex
>(lck
, false)     // don't take the lock yet 
 561         if (lck
.tryLock()) {    // uncontested 
 562                 this->mActive 
= true; 
 563         } else {                                // contested - need backup thread 
 564                 Server::active().longTermActivity();