]>
git.saurik.com Git - apple/security.git/blob - SecurityServer/process.cpp
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // process - track a single client process and its belongings
25 #include "authority.h"
29 // Construct a Process object.
31 Process::Process(TaskPort taskPort
, const char *identity
, uid_t uid
, gid_t gid
)
32 : session(Session::find(taskPort
.bootstrap())), mBusyCount(0), mDying(false),
33 mTaskPort(taskPort
), mUid(uid
), mGid(gid
)
35 // let's take a look at our wannabe client...
36 mPid
= mTaskPort
.pid();
38 // register with the session
39 session
.addProcess(this);
41 // identify the client-on-disk
42 // @@@ do this lazily on first use?
43 // @@@ note that the paradigm will shift here when kernel-supported id happens
44 mClientCode
= CodeSigning::OSXCode::decode(identity
);
46 debug("SS", "New process %p(%d) uid=%d gid=%d session=%p TP=%d for %s",
47 this, mPid
, mUid
, mGid
, &session
,
48 mTaskPort
.port(), identity
? identity
: "(unknown)");
51 Process::Process(Process
&prior
)
52 : session(Session::find(prior
.mTaskPort
.bootstrap())), mBusyCount(0), mDying(false),
53 mTaskPort(prior
.mTaskPort
), mUid(prior
.mUid
), mGid(prior
.mGid
)
58 // register with the session
59 session
.addProcess(this);
61 // copy the client-code id (and clear it in the prior so it doesn't get destroyed there)
62 mClientCode
= prior
.mClientCode
;
63 prior
.mClientCode
= NULL
;
64 prior
.mTaskPort
= Port();
66 debug("SS", "Process %p(%d) recloned uid=%d gid=%d session=%p",
67 this, mPid
, mUid
, mGid
, &session
);
73 assert(mBusyCount
== 0); // mustn't die with Connections referencing us
75 // tell all our authorizations that we're gone
76 IFDEBUG(if (!mAuthorizations
.empty())
77 debug("SS", "Process %p(%d) clearing %d authorizations",
78 this, mPid
, int(mAuthorizations
.size())));
79 for (AuthorizationSet::iterator it
= mAuthorizations
.begin();
80 it
!= mAuthorizations
.end(); it
++) {
81 AuthorizationToken
*auth
= *it
;
82 if (removeAuthorization(auth
))
86 // remove all database handles that belong to this process
87 IFDEBUG(if (!mDatabases
.empty())
88 debug("SS", "Process %p(%d) clearing %d database handles",
89 this, mPid
, int(mDatabases
.size())));
90 for (DatabaseSet::iterator it
= mDatabases
.begin();
91 it
!= mDatabases
.end(); it
++)
94 // no need to lock here; the client process has no more active threads
95 debug("SS", "Process %p(%d) has died", this, mPid
);
98 mTaskPort
.destroy(); // either dead or taken by reclone
101 // deregister from session
102 if (session
.removeProcess(this))
108 if (mBusyCount
== 0) {
109 return true; // destroy me now
111 debug("SS", "Process %p(%d) destruction deferred for %d busy connections",
112 this, mPid
, int(mBusyCount
));
114 return false; // destroy me later
120 // Given a task port, determine which session it belongs to.
121 // @@@ Very preliminary, pending true session implementation.
123 Session
&Process::sessionForPort(TaskPort taskPort
)
125 return Session::find(taskPort
.bootstrap());
130 // Connection management
132 void Process::beginConnection(Connection
&)
134 StLock
<Mutex
> _(mLock
);
138 bool Process::endConnection(Connection
&)
140 StLock
<Mutex
> _(mLock
);
141 return --mBusyCount
== 0 && mDying
;
146 // Database management
148 void Process::addDatabase(Database
*database
)
150 StLock
<Mutex
> _(mLock
);
151 mDatabases
.insert(database
);
154 void Process::removeDatabase(Database
*database
)
156 StLock
<Mutex
> _(mLock
);
157 assert(mDatabases
.find(database
) != mDatabases
.end());
158 mDatabases
.erase(database
);
163 // Verify the code signature of the a process's on-disk source.
164 // @@@ In a truly secure solution, we would ask the OS to verify this.
165 // @@@ Only the OS knows for sure what disk file (if any) originated a process.
166 // @@@ In the meantime, we fake it.
168 bool Process::verifyCodeSignature(const CodeSigning::Signature
*signature
)
171 return Server::signer().verify(*mClientCode
, signature
);
173 return false; // identity not known; can't verify
178 // Authorization set maintainance
180 void Process::addAuthorization(AuthorizationToken
*auth
)
183 StLock
<Mutex
> _(mLock
);
184 mAuthorizations
.insert(auth
);
185 auth
->addProcess(*this);
188 bool Process::removeAuthorization(AuthorizationToken
*auth
)
191 StLock
<Mutex
> _(mLock
);
192 // we do everything with a single set lookup call...
193 typedef AuthorizationSet::iterator Iter
;
194 pair
<Iter
, Iter
> range
= mAuthorizations
.equal_range(auth
);
195 assert(range
.first
!= mAuthorizations
.end());
196 Iter next
= range
.first
; next
++; // next element after first hit
197 mAuthorizations
.erase(range
.first
); // erase first hit
198 if (next
== range
.second
) { // if no more hits...
199 if (auth
->endProcess(*this)) // ... tell it to remove us,
200 return true; // ... and tell the caller
202 return false; // keep the auth; it's still in use