]> git.saurik.com Git - apple/security.git/blob - SecurityServer/ssclient.cpp
Security-176.tar.gz
[apple/security.git] / SecurityServer / ssclient.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // ssclient - SecurityServer client interface library
21 //
22 #include "sstransit.h"
23 #include <servers/netname.h>
24 #include <Security/debugging.h>
25
26 using MachPlusPlus::check;
27 using MachPlusPlus::Bootstrap;
28 using CodeSigning::OSXCode;
29
30
31 namespace Security {
32 namespace SecurityServer {
33
34 //
35 // Static callback stuff
36 //
37 ClientSession::DidChangeKeyAclCallback *ClientSession::mCallback = NULL;
38 void *ClientSession::mCallbackContext = NULL;
39
40 //
41 // The process-global object
42 //
43 UnixPlusPlus::StaticForkMonitor ClientSession::mHasForked;
44 ModuleNexus<ClientSession::Global> ClientSession::mGlobal;
45 bool ClientSession::mSetupSession;
46 const char *ClientSession::mContactName;
47
48 //
49 // Construct a client session
50 //
51 ClientSession::ClientSession(CssmAllocator &std, CssmAllocator &rtn)
52 : internalAllocator(std), returnAllocator(rtn)
53 { }
54
55
56 //
57 // Destroy a session
58 //
59 ClientSession::~ClientSession()
60 { }
61
62
63 void
64 ClientSession::registerForAclEdits(DidChangeKeyAclCallback *callback, void *context)
65 {
66 mCallback = callback;
67 mCallbackContext = context;
68 }
69
70 //
71 // Activate a client session: This connects to the SecurityServer and executes
72 // application authentication
73 //
74 void ClientSession::activate()
75 {
76 // Guard against fork-without-exec. If we are the child of a fork
77 // (that has not exec'ed), our apparent connection to SecurityServer
78 // is just a mirage, and we better reset it.
79 if (mHasForked()) {
80 secdebug("SSclnt", "process has forked (now pid=%d) - resetting connection object", getpid());
81 mGlobal.reset();
82 }
83
84 // now pick up the (new or existing) connection state
85 Global &global = mGlobal();
86 Thread &thread = global.thread();
87 if (!thread) {
88 // first time for this thread - use abbreviated registration
89 IPCN(ucsp_client_setupThread(UCSP_ARGS, mach_task_self()));
90 thread.registered = true;
91 global.serverPort.requestNotify(thread.replyPort, MACH_NOTIFY_DEAD_NAME, true);
92 secdebug("SSclnt", "Thread registered with %s", mContactName);
93 }
94 }
95
96
97 //
98 // The contactName method allows the caller to explicitly override the bootstrap
99 // name under which SecurityServer is located. Use this only with great caution,
100 // and probably only for debugging.
101 // Note that no explicit locking is done here. It is the caller's responsibility
102 // to make sure this is called from thread-safe context before the real dance begins.
103 //
104 void ClientSession::contactName(const char *name)
105 {
106 mContactName = name;
107 }
108
109 const char *ClientSession::contactName() const
110 {
111 return mContactName;
112 }
113
114
115 //
116 // Construct the process-global state object.
117 // The ModuleNexus construction magic will ensure that this happens uniquely
118 // even if the face of multithreaded attack.
119 // Do note that the mSetupSession (session creation) case is gated by a global flag,
120 // and it's the caller's responsibility not to multithread-race it.
121 //
122 ClientSession::Global::Global()
123 {
124 // find server port
125 IFDEBUG(if (!mContactName) mContactName = getenv(SECURITYSERVER_BOOTSTRAP_ENV));
126 if (!mContactName)
127 mContactName = SECURITYSERVER_BOOTSTRAP_NAME;
128 secdebug("SSclnt", "Locating %s", mContactName);
129 serverPort = Bootstrap().lookup(mContactName);
130 secdebug("SSclnt", "contacting %s at port %d", mContactName, serverPort.port());
131
132 // send identification/setup message
133 string extForm;
134 try {
135 myself = OSXCode::main();
136 extForm = myself->encode();
137 secdebug("SSclnt", "my OSXCode extForm=%s", extForm.c_str());
138 } catch (...) {
139 // leave extForm empty
140 secdebug("SSclnt", "failed to obtain my own OSXCode");
141 }
142
143 ClientSetupInfo info = { SSPROTOVERSION };
144
145 // cannot use UCSP_ARGS here because it uses mGlobal() -> deadlock
146 Thread &thread = this->thread();
147
148 if (mSetupSession) {
149 secdebug("SSclnt", "sending session setup request");
150 mSetupSession = false;
151 IPCN(ucsp_client_setupNew(serverPort, thread.replyPort, &rcode,
152 mach_task_self(), info, extForm.c_str(), &serverPort.port()));
153 secdebug("SSclnt", "new session server port is %d", serverPort.port());
154 } else {
155 IPCN(ucsp_client_setup(serverPort, thread.replyPort, &rcode,
156 mach_task_self(), info, extForm.c_str()));
157 }
158 thread.registered = true; // as a side-effect of setup call above
159 serverPort.requestNotify(thread.replyPort, MACH_NOTIFY_DEAD_NAME, true);
160 secdebug("SSclnt", "contact with %s established", mContactName);
161 }
162
163
164 //
165 // Terminate a session. This is called by the session destructor, or explicitly.
166 //
167 void ClientSession::terminate()
168 {
169 // currently defunct
170 secdebug("SSclnt", "ClientSession::terminate() call ignored");
171 }
172
173
174 void ClientSession::addApplicationAclSubject(KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag)
175 {
176 /* Notify our client if they are interested. */
177 if (mCallback && mCallbackContext)
178 {
179 secdebug("keyacl", "ClientSession::addApplicationAclSubject(keyHandle: %lu tag: %lu)", key, tag);
180 mCallback(mCallbackContext, *this, key, tag);
181 }
182 else
183 secdebug("keyacl", "ClientSession::addApplicationAclSubject() with NULL mCallback");
184 }
185
186
187 } // end namespace SecurityServer
188 } // end namespace Security