2  * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. 
   8  * This file contains Original Code and/or Modifications of Original Code 
   9  * as defined in and that are subject to the Apple Public Source License 
  10  * Version 2.0 (the 'License'). You may not use this file except in 
  11  * compliance with the License. Please obtain a copy of the License at 
  12  * http://www.opensource.apple.com/apsl/ and read it before using this 
  15  * The Original Code and all software distributed under the License are 
  16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  20  * Please see the License for the specific language governing rights and 
  21  * limitations under the License. 
  23  * @APPLE_LICENSE_HEADER_END@ 
  28 // connection - manage connections to clients. 
  30 // Note that Connection objects correspond to client process threads, and are 
  31 // thus inherently single-threaded. It is physically impossible for multiple 
  32 // requests to come in for the same Connection, unless the client side is 
  33 // illegally messing with the IPC protocol (for which we check below). 
  34 // It is still necessary to take the object lock for a Connection because there 
  35 // are times when we want to manipulate a busy Connection from another securityd 
  36 // thread (say, in response to a DPN). 
  38 #include "connection.h" 
  42 #include <security_cdsa_client/keyclient.h> 
  43 #include <security_cdsa_client/genkey.h> 
  44 #include <security_cdsa_client/wrapkey.h> 
  45 #include <security_cdsa_client/signclient.h> 
  46 #include <security_cdsa_client/macclient.h> 
  47 #include <security_cdsa_client/cryptoclient.h> 
  51 // Construct a Connection object. 
  53 Connection::Connection(Process 
&proc
, Port rPort
) 
  54  : mClientPort(rPort
), state(idle
), agentWait(NULL
), 
  55    aclUpdateTrigger(NULL
) 
  59         // bump the send-rights count on the reply port so we keep the right after replying 
  60         mClientPort
.modRefs(MACH_PORT_RIGHT_SEND
, +1); 
  62         secdebug("SS", "New connection %p for process %d clientport=%d", 
  63                 this, process().pid(), int(rPort
)); 
  68 // When a Connection's destructor executes, the connection must already have been 
  69 // terminated. All we have to do here is clean up a bit. 
  71 Connection::~Connection() 
  73         secdebug("SS", "Connection %p destroyed", this); 
  79 // Terminate a Connection normally. 
  80 // This is assumed to be properly sequenced, so no thread races are possible. 
  82 void Connection::terminate() 
  84         // cleanly discard port rights 
  85         assert(state 
== idle
); 
  86         mClientPort
.modRefs(MACH_PORT_RIGHT_SEND
, -1);  // discard surplus send right 
  87         assert(mClientPort
.getRefs(MACH_PORT_RIGHT_SEND
) == 1); // one left for final reply 
  88         secdebug("SS", "Connection %p terminated", this); 
  93 // Abort a Connection. 
  94 // This may be called from thread A while thread B is working a request for the Connection, 
  95 // so we must be careful. 
  97 void Connection::abort(bool keepReplyPort
) 
  99         StLock
<Mutex
> _(*this); 
 101         mClientPort
.destroy();          // dead as a doornail already 
 104                 secdebug("SS", "Connection %p aborted", this); 
 107                 state 
= dying
;                          // shoot me soon, please 
 109                         agentWait
->destroy(); 
 110                 secdebug("SS", "Connection %p abort deferred (busy)", this); 
 113                 assert(false);                          // impossible (we hope) 
 120 // Service request framing. 
 121 // These are here so "hanging" connection service threads don't fall 
 122 // into the Big Bad Void as Connections and processes drop out from 
 125 void Connection::beginWork() 
 132                 secdebug("SS", "Attempt to re-enter connection %p(port %d)", this, mClientPort
.port()); 
 133                 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);        //@@@ some state-error code instead? 
 139 void Connection::checkWork() 
 141         StLock
<Mutex
> _(*this); 
 146                 agentWait 
= NULL
;       // obviously we're not waiting on this 
 153 void Connection::endWork() 
 157                 // process the n-step aclUpdateTrigger 
 158                 if (aclUpdateTrigger
) { 
 159             if (--aclUpdateTriggerCount 
== 0) { 
 160                 aclUpdateTrigger 
= NULL
; 
 161                 secdebug("kcacl", "acl update trigger expires"); 
 163                 secdebug("kcacl", "acl update trigger armed for %d calls", 
 164                     aclUpdateTriggerCount
); 
 170                 secdebug("SS", "Connection %p abort resuming", this);