]> git.saurik.com Git - apple/security.git/blob - securityd/src/connection.cpp
Security-58286.20.16.tar.gz
[apple/security.git] / securityd / src / 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("SS", "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()
68 {
69 secinfo("SS", "releasing client connection %p", this);
70 assert(!agentWait);
71 }
72
73
74 //
75 // Set the (last known) guest handle for this connection.
76 //
77 void Connection::guestRef(SecGuestRef newGuest, SecCSFlags flags)
78 {
79 secinfo("SS", "Connection %p switches to guest 0x%x", this, newGuest);
80 mGuestRef = newGuest;
81 }
82
83
84 //
85 // Terminate a Connection normally.
86 // This is assumed to be properly sequenced, so no thread races are possible.
87 //
88 void Connection::terminate()
89 {
90 // cleanly discard port rights
91 assert(state == idle);
92 mClientPort.modRefs(MACH_PORT_RIGHT_SEND, -1); // discard surplus send right
93 assert(mClientPort.getRefs(MACH_PORT_RIGHT_SEND) == 1); // one left for final reply
94 secinfo("SS", "Connection %p terminated", this);
95 }
96
97
98 //
99 // Abort a Connection.
100 // This may be called from thread A while thread B is working a request for the Connection,
101 // so we must be careful.
102 //
103 void Connection::abort(bool keepReplyPort)
104 {
105 StLock<Mutex> _(*this);
106 if (!keepReplyPort)
107 mClientPort.destroy(); // dead as a doornail already
108 switch (state) {
109 case idle:
110 secinfo("SS", "Connection %p aborted", this);
111 break;
112 case busy:
113 state = dying; // shoot me soon, please
114 secinfo("SS", "Connection %p abort deferred (busy)", this);
115 break;
116 default:
117 assert(false); // impossible (we hope)
118 break;
119 }
120 }
121
122
123 //
124 // Service request framing.
125 // These are here so "hanging" connection service threads don't fall
126 // into the Big Bad Void as Connections and processes drop out from
127 // under them.
128 //
129 void Connection::beginWork(audit_token_t &auditToken)
130 {
131 // assume the audit token will be valid for the Connection's lifetime
132 // (but no longer)
133 mAuditToken = &auditToken;
134 switch (state) {
135 case idle:
136 state = busy;
137 mOverrideReturn = CSSM_OK; // clear override
138 break;
139 case busy:
140 secinfo("SS", "Attempt to re-enter connection %p(port %d)", this, mClientPort.port());
141 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); //@@@ some state-error code instead?
142 default:
143 assert(false);
144 }
145 }
146
147 void Connection::checkWork()
148 {
149 StLock<Mutex> _(*this);
150 switch (state) {
151 case busy:
152 return;
153 case dying:
154 agentWait = NULL; // obviously we're not waiting on this
155 throw this;
156 default:
157 assert(false);
158 }
159 }
160
161 void Connection::endWork(CSSM_RETURN &rcode)
162 {
163 mAuditToken = NULL;
164
165 switch (state) {
166 case busy:
167 if (mOverrideReturn && rcode == CSSM_OK)
168 rcode = mOverrideReturn;
169 state = idle;
170 return;
171 case dying:
172 secinfo("SS", "Connection %p abort resuming", this);
173 return;
174 default:
175 assert(false);
176 return; // placebo
177 }
178 }