]> git.saurik.com Git - apple/securityd.git/blob - src/connection.cpp
d99dcc915ba69e1f7567d06a3d432e11bcbee108
[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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 //
28 // connection - manage connections to clients.
29 //
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).
37 //
38 #include "connection.h"
39 #include "key.h"
40 #include "server.h"
41 #include "session.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>
48
49
50 //
51 // Construct a Connection object.
52 //
53 Connection::Connection(Process &proc, Port rPort)
54 : mClientPort(rPort), state(idle), agentWait(NULL),
55 aclUpdateTrigger(NULL)
56 {
57 parent(proc);
58
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);
61
62 secdebug("SS", "New connection %p for process %d clientport=%d",
63 this, process().pid(), int(rPort));
64 }
65
66
67 //
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.
70 //
71 Connection::~Connection()
72 {
73 secdebug("SS", "Connection %p destroyed", this);
74 assert(!agentWait);
75 }
76
77
78 //
79 // Terminate a Connection normally.
80 // This is assumed to be properly sequenced, so no thread races are possible.
81 //
82 void Connection::terminate()
83 {
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);
89 }
90
91
92 //
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.
96 //
97 void Connection::abort(bool keepReplyPort)
98 {
99 StLock<Mutex> _(*this);
100 if (!keepReplyPort)
101 mClientPort.destroy(); // dead as a doornail already
102 switch (state) {
103 case idle:
104 secdebug("SS", "Connection %p aborted", this);
105 break;
106 case busy:
107 state = dying; // shoot me soon, please
108 if (agentWait)
109 agentWait->destroy();
110 secdebug("SS", "Connection %p abort deferred (busy)", this);
111 break;
112 default:
113 assert(false); // impossible (we hope)
114 break;
115 }
116 }
117
118
119 //
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
123 // under them.
124 //
125 void Connection::beginWork()
126 {
127 switch (state) {
128 case idle:
129 state = busy;
130 break;
131 case busy:
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?
134 default:
135 assert(false);
136 }
137 }
138
139 void Connection::checkWork()
140 {
141 StLock<Mutex> _(*this);
142 switch (state) {
143 case busy:
144 return;
145 case dying:
146 agentWait = NULL; // obviously we're not waiting on this
147 throw this;
148 default:
149 assert(false);
150 }
151 }
152
153 void Connection::endWork()
154 {
155 switch (state) {
156 case busy:
157 // process the n-step aclUpdateTrigger
158 if (aclUpdateTrigger) {
159 if (--aclUpdateTriggerCount == 0) {
160 aclUpdateTrigger = NULL;
161 secdebug("kcacl", "acl update trigger expires");
162 } else
163 secdebug("kcacl", "acl update trigger armed for %d calls",
164 aclUpdateTriggerCount);
165 }
166 // end involvement
167 state = idle;
168 return;
169 case dying:
170 secdebug("SS", "Connection %p abort resuming", this);
171 return;
172 default:
173 assert(false);
174 return; // placebo
175 }
176 }