]> git.saurik.com Git - apple/securityd.git/blob - src/connection.cpp
securityd-32596.tar.gz
[apple/securityd.git] / src / connection.cpp
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, 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), state(idle), agentWait(NULL),
53 aclUpdateTrigger(NULL)
54 {
55 parent(proc);
56
57 // bump the send-rights count on the reply port so we keep the right after replying
58 mClientPort.modRefs(MACH_PORT_RIGHT_SEND, +1);
59
60 secdebug("SS", "New connection %p for process %d clientport=%d",
61 this, process().pid(), int(rPort));
62 }
63
64
65 //
66 // When a Connection's destructor executes, the connection must already have been
67 // terminated. All we have to do here is clean up a bit.
68 //
69 Connection::~Connection()
70 {
71 secdebug("SS", "Connection %p destroyed", this);
72 assert(!agentWait);
73 }
74
75
76 //
77 // Terminate a Connection normally.
78 // This is assumed to be properly sequenced, so no thread races are possible.
79 //
80 void Connection::terminate()
81 {
82 // cleanly discard port rights
83 assert(state == idle);
84 mClientPort.modRefs(MACH_PORT_RIGHT_SEND, -1); // discard surplus send right
85 assert(mClientPort.getRefs(MACH_PORT_RIGHT_SEND) == 1); // one left for final reply
86 secdebug("SS", "Connection %p terminated", this);
87 }
88
89
90 //
91 // Abort a Connection.
92 // This may be called from thread A while thread B is working a request for the Connection,
93 // so we must be careful.
94 //
95 void Connection::abort(bool keepReplyPort)
96 {
97 StLock<Mutex> _(*this);
98 if (!keepReplyPort)
99 mClientPort.destroy(); // dead as a doornail already
100 switch (state) {
101 case idle:
102 secdebug("SS", "Connection %p aborted", this);
103 break;
104 case busy:
105 state = dying; // shoot me soon, please
106 if (agentWait)
107 agentWait->destroy();
108 secdebug("SS", "Connection %p abort deferred (busy)", this);
109 break;
110 default:
111 assert(false); // impossible (we hope)
112 break;
113 }
114 }
115
116
117 //
118 // Service request framing.
119 // These are here so "hanging" connection service threads don't fall
120 // into the Big Bad Void as Connections and processes drop out from
121 // under them.
122 //
123 void Connection::beginWork()
124 {
125 switch (state) {
126 case idle:
127 state = busy;
128 break;
129 case busy:
130 secdebug("SS", "Attempt to re-enter connection %p(port %d)", this, mClientPort.port());
131 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); //@@@ some state-error code instead?
132 default:
133 assert(false);
134 }
135 }
136
137 void Connection::checkWork()
138 {
139 StLock<Mutex> _(*this);
140 switch (state) {
141 case busy:
142 return;
143 case dying:
144 agentWait = NULL; // obviously we're not waiting on this
145 throw this;
146 default:
147 assert(false);
148 }
149 }
150
151 void Connection::endWork()
152 {
153 switch (state) {
154 case busy:
155 // process the n-step aclUpdateTrigger
156 if (aclUpdateTrigger) {
157 if (--aclUpdateTriggerCount == 0) {
158 aclUpdateTrigger = NULL;
159 secdebug("kcacl", "acl update trigger expires");
160 } else
161 secdebug("kcacl", "acl update trigger armed for %d calls",
162 aclUpdateTriggerCount);
163 }
164 // end involvement
165 state = idle;
166 return;
167 case dying:
168 secdebug("SS", "Connection %p abort resuming", this);
169 return;
170 default:
171 assert(false);
172 return; // placebo
173 }
174 }