]> git.saurik.com Git - apple/securityd.git/blob - src/AuthorizationMechEval.cpp
securityd-27887.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
58 while ( (result == kAuthorizationResultAllow) &&
59 (currentMechanism != mMechanisms.end()) ) // iterate mechanisms
60 {
61 ClientMap::iterator iter = mClients.find(*currentMechanism);
62 if (iter == mClients.end())
63 {
64 string::size_type extPlugin = currentMechanism->find(':');
65 if (extPlugin != string::npos)
66 {
67 // no whitespace removal
68 string pluginIn(currentMechanism->substr(0, extPlugin));
69 string mechanismIn, authhostIn;
70
71 string::size_type extMechanism = currentMechanism->rfind(',');
72 AuthHostType hostType = securityAgent;
73
74 if (extMechanism != string::npos)
75 {
76 if (extMechanism < extPlugin)
77 return errAuthorizationInternal;
78
79 mechanismIn = currentMechanism->substr(extPlugin + 1, extMechanism - extPlugin - 1);
80 authhostIn = currentMechanism->substr(extMechanism + 1);
81 if (authhostIn == "privileged")
82 hostType = privilegedAuthHost;
83 }
84 else
85 mechanismIn = currentMechanism->substr(extPlugin + 1);
86
87 secdebug("AuthEvalMech", "external mechanism %s:%s", pluginIn.c_str(), mechanismIn.c_str());
88
89 AgentMechanismRef client(hostType, mSession);
90 client->initialize(pluginIn, mechanismIn, inArguments);
91 mClients.insert(ClientMap::value_type(*currentMechanism, client));
92 }
93 else if (*currentMechanism == "authinternal")
94 {
95 secdebug("AuthEvalMech", "performing authentication");
96 result = authinternal(context);
97
98 AuthItem *rightItem = hints.find(AGENT_HINT_AUTHORIZE_RIGHT);
99 string right = (rightItem == NULL) ? string("<unknown right>") : rightItem->stringValue();
100 CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken());
101 if (kAuthorizationResultAllow == result)
102 auditrec.submit(AUE_ssauthint, CommonCriteria::errNone, right.c_str());
103 else // kAuthorizationResultDeny
104 auditrec.submit(AUE_ssauthint, CommonCriteria::errInvalidCredential, right.c_str());
105 }
106 else if (*currentMechanism == "push_hints_to_context")
107 {
108 secdebug("AuthEvalMech", "evaluate push_hints_to_context");
109 // doesn't block evaluation, ever
110 result = kAuthorizationResultAllow;
111 context = hints;
112 }
113 else
114 return errAuthorizationInternal;
115 }
116
117 iter = mClients.find(*currentMechanism);
118 if (iter != mClients.end())
119 {
120 try
121 {
122 AgentMechanismRef &client = iter->second;
123 client->run(inArguments, hints, context, &result);
124
125 bool interrupted = false;
126 while (client->state() == client->current)
127 {
128 // check for interruption
129 vector<std::string>::const_iterator checkMechanism = mMechanisms.begin();
130 while (*checkMechanism != *currentMechanism) {
131 ClientMap::iterator iter2 = mClients.find(*checkMechanism);
132 if (iter2->second->state() == iter2->second->interrupting)
133 {
134 client->deactivate();
135 // nothing can happen until the client mechanism returns control to us
136 while (client->state() == client->deactivating)
137 client->receive();
138
139 secdebug("AuthEvalMech", "evaluate(%s) interrupted by %s.", (iter->first).c_str(), (iter2->first).c_str());
140
141 interrupted = true;
142 hints = iter2->second->inHints();
143 context = iter2->second->inContext();
144 currentMechanism = checkMechanism;
145 break;
146 }
147 else
148 checkMechanism++;
149 }
150 if (client->state() == client->current)
151 client->receive();
152 }
153
154 if (interrupted)
155 {
156 // clear reason for restart from interrupt
157 uint32_t reason = SecurityAgent::worldChanged;
158 AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason));
159 hints.erase(retryHint); hints.insert(retryHint); // replace
160
161 result = kAuthorizationResultAllow;
162 continue;
163 }
164 else
165 secdebug("AuthEvalMech", "evaluate(%s) with result: %lu.", (iter->first).c_str(), result);
166 }
167 catch (...) {
168 secdebug("AuthEvalMech", "exception during evaluate(%s).", (iter->first).c_str());
169 result = kAuthorizationResultUndefined;
170 }
171 }
172
173 if (result == kAuthorizationResultAllow)
174 currentMechanism++;
175 }
176
177 if ((result == kAuthorizationResultUserCanceled) ||
178 (result == kAuthorizationResultAllow))
179 {
180 mHints = hints;
181 mContext = context;
182 }
183
184 // convert AuthorizationResult to OSStatus
185 switch(result)
186 {
187 case kAuthorizationResultDeny:
188 return errAuthorizationDenied;
189 case kAuthorizationResultUserCanceled:
190 return errAuthorizationCanceled;
191 case kAuthorizationResultAllow:
192 return errAuthorizationSuccess;
193 default:
194 return errAuthorizationInternal;
195 }
196 }
197
198 AuthorizationResult AgentMechanismEvaluator::authinternal(AuthItemSet &context)
199 {
200 secdebug("AuthEvalMech", "evaluate authinternal");
201 do {
202 AuthItemSet::iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) );
203 if (found == context.end())
204 break;
205 string username(static_cast<const char *>((*found)->value().data), (*found)->value().length);
206 secdebug("AuthEvalMech", "found username");
207 found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentPassword) );
208 if (found == context.end())
209 break;
210 string password(static_cast<const char *>((*found)->value().data), (*found)->value().length);
211 secdebug("AuthEvalMech", "found password");
212
213 // Call to checkpw in DS
214 Server::active().longTermActivity();
215 Credential newCredential(username, password, true); // create a new shared credential
216
217 if (newCredential->isValid())
218 {
219 Syslog::info("authinternal authenticated user %s (uid %lu).", newCredential->username().c_str(), newCredential->uid());
220 return kAuthorizationResultAllow;
221 }
222
223 Syslog::error("authinternal failed to authenticate user %s.", newCredential->username().c_str());
224
225 } while (0);
226
227 return kAuthorizationResultDeny;
228 }
229
230 /*
231 AuthItemSet &
232 AgentMechanismEvaluator::commonHints(const AuthorizationToken &auth)
233 {
234
235 }
236 */
237
238 } /* namespace Authorization */