]> git.saurik.com Git - apple/securityd.git/blob - src/clientid.cpp
securityd-36489.tar.gz
[apple/securityd.git] / src / clientid.cpp
1 /*
2 * Copyright (c) 2006-2007 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 // clientid - track and manage identity of securityd clients
25 //
26 #include "clientid.h"
27 #include "server.h"
28 #include "osxcodewrap.h"
29
30
31 //
32 // Constructing a ClientIdentification doesn't do much.
33 // We're waiting for setup(), which should be called by the child class's
34 // constructor.
35 //
36 ClientIdentification::ClientIdentification()
37 {
38 }
39
40
41 //
42 // Initialize the ClientIdentification.
43 // This creates a process-level code object for the client.
44 //
45 void ClientIdentification::setup(pid_t pid)
46 {
47 if (IFDEBUG(OSStatus rc =)SecCodeCreateWithPID(pid, kSecCSDefaultFlags,
48 &mClientProcess.aref()))
49 secdebug("clientid", "could not get code for process %d: OSStatus=%ld",
50 pid, rc);
51 }
52
53
54 //
55 // Return a SecCodeRef for the client process itself, regardless of
56 // which guest within it is currently active.
57 // Think twice before using this.
58 //
59 SecCodeRef ClientIdentification::processCode() const
60 {
61 return mClientProcess;
62 }
63
64
65 //
66 // Return a SecCodeRef for the currently active guest within the client
67 // process.
68 //
69 // We make a fair effort to cache client guest identities without over-growing
70 // the cache. Note that there's currently no protocol for being notified of
71 // a guest's death or disappearance (independent from the host process's death),
72 // so we couldn't track guests live even if we tried.
73 //
74 // Note that this consults Server::connection for the currently serviced
75 // Connection object, so this is not entirely a function of ClientIdentification state.
76 //
77 SecCodeRef ClientIdentification::currentGuest() const
78 {
79 if (GuestState *guest = current())
80 return guest->code;
81 else
82 return mClientProcess;
83 }
84
85 ClientIdentification::GuestState *ClientIdentification::current() const
86 {
87 // if we have no client identification, we can't find a current guest either
88 if (!processCode())
89 return NULL;
90
91 SecGuestRef guestRef = Server::connection().guestRef();
92
93 // try to deliver an already-cached entry
94 {
95 StLock<Mutex> _(mLock);
96 GuestMap::iterator it = mGuests.find(guestRef);
97 if (it != mGuests.end())
98 return &it->second;
99 }
100
101 // okay, make a new one (this may take a while)
102 CFRef<CFDictionaryRef> attributes = (guestRef == kSecNoGuest)
103 ? NULL
104 : makeCFDictionary(1, kSecGuestAttributeCanonical, CFTempNumber(guestRef).get());
105 Server::active().longTermActivity();
106 CFRef<SecCodeRef> code;
107 switch (OSStatus rc = SecCodeCopyGuestWithAttributes(processCode(),
108 attributes, kSecCSDefaultFlags, &code.aref())) {
109 case noErr:
110 break;
111 case errSecCSUnsigned: // not signed; clearly not a host
112 case errSecCSNotAHost: // signed but not marked as a (potential) host
113 code = mClientProcess;
114 break;
115 case errSecCSNoSuchCode: // potential host, but...
116 if (guestRef == kSecNoGuest) { // ... no guests (yet), so return the process
117 code = mClientProcess;
118 break;
119 }
120 // else fall through // ... the guest we expected to be there isn't
121 default:
122 MacOSError::throwMe(rc);
123 }
124 StLock<Mutex> _(mLock);
125 GuestState &slot = mGuests[guestRef];
126 if (!slot.code) // if another thread didn't get here first...
127 slot.code = code;
128 return &slot;
129 }
130
131
132 //
133 // Support for the legacy hash identification mechanism.
134 // The legacy machinery deals exclusively in terms of processes.
135 // It knows nothing about guests and their identities.
136 //
137 string ClientIdentification::getPath() const
138 {
139 assert(mClientProcess);
140 return codePath(currentGuest());
141 }
142
143 const CssmData ClientIdentification::getHash() const
144 {
145 if (GuestState *guest = current()) {
146 if (!guest->gotHash) {
147 RefPointer<OSXCode> clientCode = new OSXCodeWrap(guest->code);
148 OSXVerifier::makeLegacyHash(clientCode, guest->legacyHash);
149 guest->gotHash = true;
150 }
151 return CssmData::wrap(guest->legacyHash, SHA1::digestLength);
152 } else
153 return CssmData();
154 }
155
156
157 //
158 // Bonus function: get the path out of a SecCodeRef
159 //
160 std::string codePath(SecStaticCodeRef code)
161 {
162 CFRef<CFURLRef> path;
163 MacOSError::check(SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref()));
164 return cfString(path);
165 }
166
167
168 //
169 // Debug dump support
170 //
171 #if defined(DEBUGDUMP)
172
173 static void dumpCode(SecCodeRef code)
174 {
175 CFRef<CFURLRef> path;
176 if (OSStatus rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref()))
177 Debug::dump("unknown(rc=%ld)", rc);
178 else
179 Debug::dump("%s", cfString(path).c_str());
180 }
181
182 void ClientIdentification::dump()
183 {
184 Debug::dump(" client=");
185 dumpCode(mClientProcess);
186 for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) {
187 Debug::dump(" guest(0x%x)=", it->first);
188 dumpCode(it->second.code);
189 if (it->second.gotHash)
190 Debug::dump(" [got hash]");
191 }
192 }
193
194 #endif //DEBUGDUMP