2  * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 
   4  * The contents of this file constitute Original Code as defined in and are 
   5  * subject to the Apple Public Source License Version 1.2 (the 'License'). 
   6  * You may not use this file except in compliance with the License. Please obtain 
   7  * a copy of the License at http://www.apple.com/publicsource and read it before 
  10  * This Original Code and all software distributed under the License are 
  11  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 
  12  * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 
  13  * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
  14  * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 
  15  * specific language governing rights and limitations under the License. 
  20 // ssclient - SecurityServer client interface library 
  22 #include "sstransit.h" 
  23 #include <servers/netname.h> 
  24 #include <Security/debugging.h> 
  26 using MachPlusPlus::check
; 
  27 using MachPlusPlus::Bootstrap
; 
  28 using CodeSigning::OSXCode
; 
  32 namespace SecurityServer 
{ 
  36 // The process-global object 
  38 UnixPlusPlus::StaticForkMonitor 
ClientSession::mHasForked
; 
  39 ModuleNexus
<ClientSession::Global
> ClientSession::mGlobal
; 
  40 bool ClientSession::mSetupSession
; 
  41 const char *ClientSession::mContactName
; 
  45 // Construct a client session 
  47 ClientSession::ClientSession(CssmAllocator 
&std
, CssmAllocator 
&rtn
) 
  48 : internalAllocator(std
), returnAllocator(rtn
) 
  55 ClientSession::~ClientSession() 
  60 // Activate a client session: This connects to the SecurityServer and executes 
  61 // application authentication 
  63 void ClientSession::activate() 
  65         // Guard against fork-without-exec. If we are the child of a fork 
  66         // (that has not exec'ed), our apparent connection to SecurityServer 
  67         // is just a mirage, and we better reset it. 
  69                 secdebug("SSclnt", "process has forked (now pid=%d) - resetting connection object", getpid()); 
  73         // now pick up the (new or existing) connection state 
  74         Global 
&global 
= mGlobal(); 
  75     Thread 
&thread 
= global
.thread(); 
  77                 // first time for this thread - use abbreviated registration 
  78                 IPCN(ucsp_client_setupThread(UCSP_ARGS
, mach_task_self())); 
  79         thread
.registered 
= true; 
  80         global
.serverPort
.requestNotify(thread
.replyPort
, MACH_NOTIFY_DEAD_NAME
, true); 
  81         secdebug("SSclnt", "Thread registered with %s", mContactName
); 
  87 // The contactName method allows the caller to explicitly override the bootstrap 
  88 // name under which SecurityServer is located. Use this only with great caution, 
  89 // and probably only for debugging. 
  90 // Note that no explicit locking is done here. It is the caller's responsibility 
  91 // to make sure this is called from thread-safe context before the real dance begins. 
  93 void ClientSession::contactName(const char *name
) 
  98 const char *ClientSession::contactName() const 
 105 // Construct the process-global state object. 
 106 // The ModuleNexus construction magic will ensure that this happens uniquely 
 107 // even if the face of multithreaded attack. 
 108 // Do note that the mSetupSession (session creation) case is gated by a global flag, 
 109 // and it's the caller's responsibility not to multithread-race it. 
 111 ClientSession::Global::Global() 
 114         IFDEBUG(if (!mContactName
) mContactName 
= getenv(SECURITYSERVER_BOOTSTRAP_ENV
)); 
 116                 mContactName 
= SECURITYSERVER_BOOTSTRAP_NAME
; 
 117     secdebug("SSclnt", "Locating %s", mContactName
); 
 118     serverPort 
= Bootstrap().lookup(mContactName
); 
 119         secdebug("SSclnt", "contacting %s at port %d", mContactName
, serverPort
.port()); 
 121     // send identification/setup message 
 124         myself 
= OSXCode::main(); 
 125         extForm 
= myself
->encode(); 
 126         secdebug("SSclnt", "my OSXCode extForm=%s", extForm
.c_str()); 
 128         // leave extForm empty 
 129         secdebug("SSclnt", "failed to obtain my own OSXCode"); 
 132         ClientSetupInfo info 
= { SSPROTOVERSION 
}; 
 134     // cannot use UCSP_ARGS here because it uses mGlobal() -> deadlock 
 135     Thread 
&thread 
= this->thread(); 
 138                 secdebug("SSclnt", "sending session setup request"); 
 139                 mSetupSession 
= false; 
 140                 IPCN(ucsp_client_setupNew(serverPort
, thread
.replyPort
, &rcode
, 
 141                         mach_task_self(), info
, extForm
.c_str(), &serverPort
.port())); 
 142                 secdebug("SSclnt", "new session server port is %d", serverPort
.port()); 
 144                 IPCN(ucsp_client_setup(serverPort
, thread
.replyPort
, &rcode
, 
 145                         mach_task_self(), info
, extForm
.c_str())); 
 147     thread
.registered 
= true;   // as a side-effect of setup call above 
 148         serverPort
.requestNotify(thread
.replyPort
, MACH_NOTIFY_DEAD_NAME
, true); 
 149         secdebug("SSclnt", "contact with %s established", mContactName
); 
 154 // Terminate a session. This is called by the session destructor, or explicitly. 
 156 void ClientSession::terminate() 
 159         secdebug("SSclnt", "ClientSession::terminate() call ignored"); 
 163 } // end namespace SecurityServer 
 164 } // end namespace Security