]> git.saurik.com Git - apple/securityd.git/blob - src/AuthorizationMechEval.cpp
securityd-36489.tar.gz
[apple/securityd.git] / src / AuthorizationMechEval.cpp
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, 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 * AuthorizationMechEval.cpp
24 * securityd
25 *
26 */
27 #include "AuthorizationMechEval.h"
28 #include <security_utilities/logging.h>
29 #include <bsm/audit_uevents.h>
30 #include <security_utilities/ccaudit.h>
31
32 namespace Authorization {
33
34 AgentMechanismRef::AgentMechanismRef(const AuthHostType type, Session &session) :
35 RefPointer<QueryInvokeMechanism>(new QueryInvokeMechanism(type, session)) {}
36
37 // we need the vector<string> of mechanisms
38 AgentMechanismEvaluator::AgentMechanismEvaluator(uid_t uid, Session& session, const vector<string>& inMechanisms) :
39 mMechanisms(inMechanisms), mClientUid(uid), mSession(session)
40 {
41 //set up environment
42 }
43
44 OSStatus
45 AgentMechanismEvaluator::run(const AuthValueVector &inArguments, const AuthItemSet &inHints, const AuthorizationToken &auth)
46 {
47 const AuthItemSet &inContext = const_cast<AuthorizationToken &>(auth).infoSet();
48
49 // add process specifics to context?
50
51 vector<std::string>::const_iterator currentMechanism = mMechanisms.begin();
52
53 AuthorizationResult result = kAuthorizationResultAllow;
54
55 AuthItemSet hints = inHints;
56 AuthItemSet context = inContext;
57 // add saved-off sticky context values to context for evaluation
58 context.insert(mStickyContext.begin(), mStickyContext.end());
59
60 while ( (result == kAuthorizationResultAllow) &&
61 (currentMechanism != mMechanisms.end()) ) // iterate mechanisms
62 {
63 ClientMap::iterator iter = mClients.find(*currentMechanism);
64 if (iter == mClients.end())
65 {
66 string::size_type extPlugin = currentMechanism->find(':');
67 if (extPlugin != string::npos)
68 {
69 // no whitespace removal
70 string pluginIn(currentMechanism->substr(0, extPlugin));
71 string mechanismIn, authhostIn;
72
73 string::size_type extMechanism = currentMechanism->rfind(',');
74 AuthHostType hostType = securityAgent;
75
76 if (extMechanism != string::npos)
77 {
78 if (extMechanism < extPlugin)
79 return errAuthorizationInternal;
80
81 mechanismIn = currentMechanism->substr(extPlugin + 1, extMechanism - extPlugin - 1);
82 authhostIn = currentMechanism->substr(extMechanism + 1);
83 if (authhostIn == "privileged")
84 hostType = privilegedAuthHost;
85 }
86 else
87 mechanismIn = currentMechanism->substr(extPlugin + 1);
88
89 secdebug("AuthEvalMech", "external mechanism %s:%s", pluginIn.c_str(), mechanismIn.c_str());
90
91 AgentMechanismRef client(hostType, mSession);
92 client->initialize(pluginIn, mechanismIn, inArguments);
93 mClients.insert(ClientMap::value_type(*currentMechanism, client));
94 }
95 else if (*currentMechanism == "authinternal")
96 {
97 secdebug("AuthEvalMech", "performing authentication");
98 result = authinternal(context);
99
100 AuthItem *rightItem = hints.find(AGENT_HINT_AUTHORIZE_RIGHT);
101 string right = (rightItem == NULL) ? string("<unknown right>") : rightItem->stringValue();
102 CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken());
103 if (kAuthorizationResultAllow == result)
104 auditrec.submit(AUE_ssauthint, CommonCriteria::errNone, right.c_str());
105 else // kAuthorizationResultDeny
106 auditrec.submit(AUE_ssauthint, CommonCriteria::errInvalidCredential, right.c_str());
107 }
108 else if (*currentMechanism == "push_hints_to_context")
109 {
110 secdebug("AuthEvalMech", "evaluate push_hints_to_context");
111 // doesn't block evaluation, ever
112 result = kAuthorizationResultAllow;
113 context = hints;
114 }
115 else
116 return errAuthorizationInternal;
117 }
118
119 iter = mClients.find(*currentMechanism);
120 if (iter != mClients.end())
121 {
122 try
123 {
124 AgentMechanismRef &client = iter->second;
125 client->run(inArguments, hints, context, &result);
126
127 bool interrupted = false;
128 while (client->state() == client->current)
129 {
130 // check for interruption
131 vector<std::string>::const_iterator checkMechanism = mMechanisms.begin();
132 while (*checkMechanism != *currentMechanism) {
133 ClientMap::iterator iter2 = mClients.find(*checkMechanism);
134 if (iter2->second->state() == iter2->second->interrupting)
135 {
136 client->deactivate();
137 // nothing can happen until the client mechanism returns control to us
138 while (client->state() == client->deactivating)
139 client->receive();
140
141 secdebug("AuthEvalMech", "evaluate(%s) interrupted by %s.", (iter->first).c_str(), (iter2->first).c_str());
142
143 interrupted = true;
144 hints = iter2->second->inHints();
145 context = iter2->second->inContext();
146 currentMechanism = checkMechanism;
147 break;
148 }
149 else
150 checkMechanism++;
151 }
152 if (client->state() == client->current)
153 client->receive();
154 }
155
156 if (interrupted)
157 {
158 // clear reason for restart from interrupt
159 uint32_t reason = SecurityAgent::worldChanged;
160 AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason));
161 hints.erase(retryHint); hints.insert(retryHint); // replace
162
163 result = kAuthorizationResultAllow;
164 continue;
165 }
166 else
167 secdebug("AuthEvalMech", "evaluate(%s) with result: %lu.", (iter->first).c_str(), result);
168 }
169 catch (...) {
170 secdebug("AuthEvalMech", "exception during evaluate(%s).", (iter->first).c_str());
171 result = kAuthorizationResultUndefined;
172 }
173 }
174
175 if (result == kAuthorizationResultAllow)
176 currentMechanism++;
177 }
178
179 if ((result == kAuthorizationResultUserCanceled) ||
180 (result == kAuthorizationResultAllow))
181 {
182 mHints = hints;
183 mContext.clear();
184 // only make non-sticky context values available externally
185 AuthItemSet::const_iterator end = context.end();
186 for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) {
187 const AuthItemRef &item = *it;
188 if (item->flags() != kAuthorizationContextFlagSticky)
189 mContext.insert(item);
190 }
191 }
192 else if (result == kAuthorizationResultDeny)
193 {
194 // save off sticky values in context
195 mStickyContext.clear();
196 AuthItemSet::const_iterator end = context.end();
197 for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) {
198 const AuthItemRef &item = *it;
199 if (item->flags() == kAuthorizationContextFlagSticky)
200 mStickyContext.insert(item);
201 }
202 }
203
204 // convert AuthorizationResult to OSStatus
205 switch(result)
206 {
207 case kAuthorizationResultDeny:
208 return errAuthorizationDenied;
209 case kAuthorizationResultUserCanceled:
210 return errAuthorizationCanceled;
211 case kAuthorizationResultAllow:
212 return errAuthorizationSuccess;
213 default:
214 return errAuthorizationInternal;
215 }
216 }
217
218 AuthorizationResult AgentMechanismEvaluator::authinternal(AuthItemSet &context)
219 {
220 secdebug("AuthEvalMech", "evaluate authinternal");
221 do {
222 AuthItemSet::iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) );
223 if (found == context.end())
224 break;
225 string username(static_cast<const char *>((*found)->value().data), (*found)->value().length);
226 secdebug("AuthEvalMech", "found username");
227 found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentPassword) );
228 if (found == context.end())
229 break;
230 string password(static_cast<const char *>((*found)->value().data), (*found)->value().length);
231 secdebug("AuthEvalMech", "found password");
232
233 Credential newCredential(username, password, true); // create a new shared credential
234 if (newCredential->isValid())
235 return kAuthorizationResultAllow;
236
237 } while (0);
238
239 return kAuthorizationResultDeny;
240 }
241
242 /*
243 AuthItemSet &
244 AgentMechanismEvaluator::commonHints(const AuthorizationToken &auth)
245 {
246
247 }
248 */
249
250 } /* namespace Authorization */