/ securityd / src / connection.cpp
connection.cpp
  1  /*
  2   * Copyright (c) 2000-2009 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  // connection - manage connections to clients.
 27  //
 28  // Note that Connection objects correspond to client process threads, and are
 29  // thus inherently single-threaded. It is physically impossible for multiple
 30  // requests to come in for the same Connection, unless the client side is
 31  // illegally messing with the IPC protocol (for which we check below).
 32  // It is still necessary to take the object lock for a Connection because there
 33  // are times when we want to manipulate a busy Connection from another securityd
 34  // thread (say, in response to a DPN).
 35  //
 36  #include "connection.h"
 37  #include "key.h"
 38  #include "server.h"
 39  #include "session.h"
 40  #include <security_cdsa_client/keyclient.h>
 41  #include <security_cdsa_client/genkey.h>
 42  #include <security_cdsa_client/wrapkey.h>
 43  #include <security_cdsa_client/signclient.h>
 44  #include <security_cdsa_client/macclient.h>
 45  #include <security_cdsa_client/cryptoclient.h>
 46  
 47  
 48  //
 49  // Construct a Connection object.
 50  //
 51  Connection::Connection(Process &proc, Port rPort)
 52   : mClientPort(rPort), mGuestRef(kSecNoGuest), state(idle), agentWait(NULL)
 53  {
 54  	parent(proc);
 55  	
 56  	// bump the send-rights count on the reply port so we keep the right after replying
 57  	mClientPort.modRefs(MACH_PORT_RIGHT_SEND, +1);
 58  	
 59      secinfo("SecServer", "New client connection %p: %d %d", this, rPort.port(), proc.uid());
 60  }
 61  
 62  
 63  //
 64  // When a Connection's destructor executes, the connection must already have been
 65  // terminated. All we have to do here is clean up a bit.
 66  //
 67  Connection::~Connection() try
 68  {
 69      mClientPort.deallocate();
 70      secinfo("SecServer", "releasing client connection %p", this);
 71  	assert(!agentWait);
 72  } catch (...) {
 73      secerror("SecServer: Error deallocating connection port");
 74      return;
 75  }
 76  
 77  //
 78  // Set the (last known) guest handle for this connection.
 79  //
 80  void Connection::guestRef(SecGuestRef newGuest, SecCSFlags flags)
 81  {
 82  	secinfo("SecServer", "Connection %p switches to guest 0x%x", this, newGuest);
 83  	mGuestRef = newGuest;
 84  }
 85  
 86  //
 87  // Service request framing.
 88  // These are here so "hanging" connection service threads don't fall
 89  // into the Big Bad Void as Connections and processes drop out from
 90  // under them.
 91  //
 92  void Connection::beginWork(audit_token_t &auditToken)
 93  {
 94      // assume the audit token will be valid for the Connection's lifetime 
 95      // (but no longer)
 96      mAuditToken = &auditToken;
 97  	switch (state) {
 98  	case idle:
 99  		state = busy;
100  		mOverrideReturn = CSSM_OK;	// clear override
101  		break;
102  	case busy:
103  		secinfo("SecServer", "Attempt to re-enter connection %p(port %d)", this, mClientPort.port());
104  		CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);	//@@@ some state-error code instead?
105  	default:
106  		assert(false);
107  	}
108  }
109  
110  void Connection::checkWork()
111  {
112  	StLock<Mutex> _(*this);
113  	switch (state) {
114  	case busy:
115  		return;
116  	case dying:
117  		agentWait = NULL;	// obviously we're not waiting on this
118  		throw this;
119  	default:
120  		assert(false);
121  	}
122  }
123  
124  void Connection::endWork(CSSM_RETURN &rcode)
125  {
126      mAuditToken = NULL;
127  
128  	switch (state) {
129  	case busy:
130  		if (mOverrideReturn && rcode == CSSM_OK)
131  			rcode = mOverrideReturn;
132  		state = idle;
133  		return;
134  	case dying:
135  		secinfo("SecServer", "Connection %p abort resuming", this);
136  		return;
137  	default:
138  		assert(false);
139  		return;	// placebo
140  	}
141  }