]> git.saurik.com Git - apple/security.git/blob - securityd/src/AuthorizationRule.cpp
Security-57031.40.6.tar.gz
[apple/security.git] / securityd / src / AuthorizationRule.cpp
1 /*
2 * Copyright (c) 2003-2010,2012 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 * AuthorizationRule.cpp
24 * Security
25 *
26 */
27
28 #include "AuthorizationRule.h"
29 #include <Security/AuthorizationTags.h>
30 #include <Security/AuthorizationTagsPriv.h>
31 #include <Security/AuthorizationDB.h>
32 #include <Security/AuthorizationPriv.h>
33 #include <security_utilities/logging.h>
34 #include <bsm/audit_uevents.h>
35 #include "ccaudit_extensions.h"
36 #include "authority.h"
37 #include "server.h"
38 #include "process.h"
39 #include "agentquery.h"
40 #include "AuthorizationMechEval.h"
41
42 #include <asl.h>
43 #include <pwd.h>
44 #include <grp.h>
45 #include <unistd.h>
46 #include <membership.h>
47
48 extern "C" {
49 #include <membershipPriv.h>
50 }
51
52 using namespace CommonCriteria::Securityd;
53
54 //
55 // Rule class
56 //
57 namespace Authorization {
58
59 CFStringRef RuleImpl::kUserGroupID = CFSTR(kAuthorizationRuleParameterGroup);
60 CFStringRef RuleImpl::kTimeoutID = CFSTR(kAuthorizationRuleParameterCredentialTimeout);
61 CFStringRef RuleImpl::kSharedID = CFSTR(kAuthorizationRuleParameterCredentialShared);
62 CFStringRef RuleImpl::kAllowRootID = CFSTR(kAuthorizationRuleParameterAllowRoot);
63 CFStringRef RuleImpl::kMechanismsID = CFSTR(kAuthorizationRuleParameterMechanisms);
64 CFStringRef RuleImpl::kSessionOwnerID = CFSTR(kAuthorizationRuleParameterCredentialSessionOwner);
65 CFStringRef RuleImpl::kKofNID = CFSTR(kAuthorizationRuleParameterKofN);
66 CFStringRef RuleImpl::kPromptID = CFSTR(kAuthorizationRuleParameterDefaultPrompt);
67 CFStringRef RuleImpl::kButtonID = CFSTR(kAuthorizationRuleParameterDefaultButton);
68 CFStringRef RuleImpl::kTriesID = CFSTR("tries"); // XXX/cs move to AuthorizationTagsPriv.h
69 CFStringRef RuleImpl::kExtractPasswordID = CFSTR(kAuthorizationRuleParameterExtractPassword);
70
71 CFStringRef RuleImpl::kRuleClassID = CFSTR(kAuthorizationRuleClass);
72 CFStringRef RuleImpl::kRuleAllowID = CFSTR(kAuthorizationRuleClassAllow);
73 CFStringRef RuleImpl::kRuleDenyID = CFSTR(kAuthorizationRuleClassDeny);
74 CFStringRef RuleImpl::kRuleUserID = CFSTR(kAuthorizationRuleClassUser);
75 CFStringRef RuleImpl::kRuleDelegateID = CFSTR(kAuthorizationRightRule);
76 CFStringRef RuleImpl::kRuleMechanismsID = CFSTR(kAuthorizationRuleClassMechanisms);
77 CFStringRef RuleImpl::kRuleAuthenticateUserID = CFSTR(kAuthorizationRuleParameterAuthenticateUser);
78
79
80 string
81 RuleImpl::Attribute::getString(CFDictionaryRef config, CFStringRef key, bool required = false, const char *defaultValue = "")
82 {
83 CFTypeRef value = CFDictionaryGetValue(config, key);
84 if (value && (CFGetTypeID(value) == CFStringGetTypeID()))
85 {
86 CFStringRef stringValue = reinterpret_cast<CFStringRef>(value);
87 char buffer[512];
88 const char *ptr = CFStringGetCStringPtr(stringValue, kCFStringEncodingUTF8);
89 if (ptr == NULL)
90 {
91 if (CFStringGetCString(stringValue, buffer, sizeof(buffer), kCFStringEncodingUTF8))
92 ptr = buffer;
93 else
94 {
95 Syslog::alert("Could not convert CFString to C string");
96 MacOSError::throwMe(errAuthorizationInternal);
97 }
98 }
99
100 return string(ptr);
101 }
102 else
103 if (!required)
104 return string(defaultValue);
105 else
106 {
107 Syslog::alert("Failed to get rule string");
108 MacOSError::throwMe(errAuthorizationInternal);
109 }
110 }
111
112 double
113 RuleImpl::Attribute::getDouble(CFDictionaryRef config, CFStringRef key, bool required = false, double defaultValue = 0.0)
114 {
115 double doubleValue = 0;
116
117 CFTypeRef value = CFDictionaryGetValue(config, key);
118 if (value && (CFGetTypeID(value) == CFNumberGetTypeID()))
119 {
120 CFNumberGetValue(reinterpret_cast<CFNumberRef>(value), kCFNumberDoubleType, &doubleValue);
121 }
122 else
123 if (!required)
124 return defaultValue;
125 else
126 {
127 Syslog::alert("Failed to get rule double value");
128 MacOSError::throwMe(errAuthorizationInternal);
129 }
130
131 return doubleValue;
132 }
133
134 bool
135 RuleImpl::Attribute::getBool(CFDictionaryRef config, CFStringRef key, bool required = false, bool defaultValue = false)
136 {
137 bool boolValue = false;
138 CFTypeRef value = CFDictionaryGetValue(config, key);
139
140 if (value && (CFGetTypeID(value) == CFBooleanGetTypeID()))
141 {
142 boolValue = CFBooleanGetValue(reinterpret_cast<CFBooleanRef>(value));
143 }
144 else
145 if (!required)
146 return defaultValue;
147 else
148 {
149 Syslog::alert("Failed to get rule bool value");
150 MacOSError::throwMe(errAuthorizationInternal);
151 }
152
153 return boolValue;
154 }
155
156 vector<string>
157 RuleImpl::Attribute::getVector(CFDictionaryRef config, CFStringRef key, bool required = false)
158 {
159 vector<string> valueArray;
160
161 CFTypeRef value = CFDictionaryGetValue(config, key);
162 if (value && (CFGetTypeID(value) == CFArrayGetTypeID()))
163 {
164 CFArrayRef evalArray = reinterpret_cast<CFArrayRef>(value);
165
166 CFIndex numItems = CFArrayGetCount(evalArray);
167 for (CFIndex index=0; index < numItems; index++)
168 {
169 CFTypeRef arrayValue = CFArrayGetValueAtIndex(evalArray, index);
170 if (arrayValue && (CFGetTypeID(arrayValue) == CFStringGetTypeID()))
171 {
172 CFStringRef stringValue = reinterpret_cast<CFStringRef>(arrayValue);
173 char buffer[512];
174 const char *ptr = CFStringGetCStringPtr(stringValue, kCFStringEncodingUTF8);
175 if (ptr == NULL)
176 {
177 if (CFStringGetCString(stringValue, buffer, sizeof(buffer), kCFStringEncodingUTF8))
178 ptr = buffer;
179 else
180 {
181 Syslog::alert("Failed to convert CFString to C string for item %u in array", index);
182 MacOSError::throwMe(errAuthorizationInternal);
183 }
184 }
185 valueArray.push_back(string(ptr));
186 }
187 }
188 }
189 else
190 if (required)
191 {
192 Syslog::alert("Value for key either not present or not a CFArray");
193 MacOSError::throwMe(errAuthorizationInternal);
194 }
195
196 return valueArray;
197 }
198
199
200 bool RuleImpl::Attribute::getLocalizedText(CFDictionaryRef config, map<string,string> &localizedPrompts, CFStringRef dictKey, const char *descriptionKey)
201 {
202 CFIndex numberOfPrompts = 0;
203 CFDictionaryRef promptsDict;
204 if (CFDictionaryContainsKey(config, dictKey))
205 {
206 promptsDict = reinterpret_cast<CFDictionaryRef>(CFDictionaryGetValue(config, dictKey));
207 if (promptsDict && (CFGetTypeID(promptsDict) == CFDictionaryGetTypeID()))
208 numberOfPrompts = CFDictionaryGetCount(promptsDict);
209 }
210 if (numberOfPrompts == 0)
211 return false;
212
213 const void *keys[numberOfPrompts+1];
214 const void *values[numberOfPrompts+1];
215 CFDictionaryGetKeysAndValues(promptsDict, &keys[0], &values[0]);
216
217 while (numberOfPrompts-- > 0)
218 {
219 CFStringRef keyRef = reinterpret_cast<CFStringRef>(keys[numberOfPrompts]);
220 CFStringRef valueRef = reinterpret_cast<CFStringRef>(values[numberOfPrompts]);
221 if (!keyRef || (CFGetTypeID(keyRef) != CFStringGetTypeID())) {
222 continue;
223 }
224 if (!valueRef || (CFGetTypeID(valueRef) != CFStringGetTypeID())) {
225 continue;
226 }
227 string key = cfString(keyRef);
228 string value = cfString(valueRef);
229 localizedPrompts[descriptionKey + key] = value;
230 }
231
232 return true;
233 }
234
235
236 // default rule
237 RuleImpl::RuleImpl() :
238 mType(kUser), mGroupName("admin"), mMaxCredentialAge(300.0), mShared(true), mAllowRoot(false), mSessionOwner(false), mTries(0), mAuthenticateUser(true), mExtractPassword(false)
239 {
240 // XXX/cs read default descriptions from somewhere
241 // @@@ Default rule is shared admin group with 5 minute timeout
242 }
243
244 // return rule built from rule definition; throw if invalid.
245 RuleImpl::RuleImpl(const string &inRightName, CFDictionaryRef cfRight, CFDictionaryRef cfRules) : mRightName(inRightName), mExtractPassword(false)
246 {
247 // @@@ make sure cfRight is non mutable and never used that way
248
249 if (CFGetTypeID(cfRight) != CFDictionaryGetTypeID())
250 {
251 Syslog::alert("Invalid rights set");
252 MacOSError::throwMe(errAuthorizationInternal);
253 }
254
255 mTries = 0;
256
257 string classTag = Attribute::getString(cfRight, kRuleClassID, false, "");
258
259 if (classTag.length())
260 {
261 if (classTag == kAuthorizationRuleClassAllow)
262 {
263 secdebug("authrule", "%s : rule allow", inRightName.c_str());
264 mType = kAllow;
265 }
266 else if (classTag == kAuthorizationRuleClassDeny)
267 {
268 secdebug("authrule", "%s : rule deny", inRightName.c_str());
269 mType = kDeny;
270 }
271 else if (classTag == kAuthorizationRuleClassUser)
272 {
273 mType = kUser;
274 mGroupName = Attribute::getString(cfRight, kUserGroupID);
275 // grab other user-in-group attributes
276 mMaxCredentialAge = Attribute::getDouble(cfRight, kTimeoutID, false, DBL_MAX);
277 mShared = Attribute::getBool(cfRight, kSharedID);
278 mAllowRoot = Attribute::getBool(cfRight, kAllowRootID);
279 mSessionOwner = Attribute::getBool(cfRight, kSessionOwnerID);
280 // authorization tags can have eval now too
281 mEvalDef = Attribute::getVector(cfRight, kMechanismsID);
282 if (mEvalDef.size() == 0 && cfRules /*only rights default see appserver-admin*/)
283 {
284 CFDictionaryRef cfRuleDef = reinterpret_cast<CFDictionaryRef>(CFDictionaryGetValue(cfRules, CFSTR("authenticate")));
285 if (cfRuleDef && CFGetTypeID(cfRuleDef) == CFDictionaryGetTypeID())
286 mEvalDef = Attribute::getVector(cfRuleDef, kMechanismsID);
287 }
288 mTries = int(Attribute::getDouble(cfRight, kTriesID, false, double(kMaximumAuthorizationTries)));
289 mAuthenticateUser = Attribute::getBool(cfRight, kRuleAuthenticateUserID, false, true);
290 mExtractPassword = Attribute::getBool(cfRight, kExtractPasswordID, false, false);
291
292 secdebug("authrule", "%s : rule user in group \"%s\" timeout %g%s%s",
293 inRightName.c_str(),
294 mGroupName.c_str(), mMaxCredentialAge, mShared ? " shared" : "",
295 mAllowRoot ? " allow-root" : "");
296
297 }
298 else if (classTag == kAuthorizationRuleClassMechanisms)
299 {
300 secdebug("authrule", "%s : rule evaluate mechanisms", inRightName.c_str());
301 mType = kEvaluateMechanisms;
302 // mechanisms to evaluate
303 mEvalDef = Attribute::getVector(cfRight, kMechanismsID, true);
304 mTries = int(Attribute::getDouble(cfRight, kTriesID, false, 0.0)); // "forever"
305 mShared = Attribute::getBool(cfRight, kSharedID, false, true);
306 mExtractPassword = Attribute::getBool(cfRight, kExtractPasswordID, false, false);
307 }
308 else if (classTag == kAuthorizationRightRule)
309 {
310 assert(cfRules); // rules can't delegate to other rules
311 secdebug("authrule", "%s : rule delegate rule", inRightName.c_str());
312 mType = kRuleDelegation;
313
314 // string or
315 string ruleDefString = Attribute::getString(cfRight, kRuleDelegateID, false, "");
316 if (ruleDefString.length())
317 {
318 CFStringRef ruleDefRef = makeCFString(ruleDefString);
319 CFDictionaryRef cfRuleDef = reinterpret_cast<CFDictionaryRef>(CFDictionaryGetValue(cfRules, ruleDefRef));
320 if (ruleDefRef)
321 CFRelease(ruleDefRef);
322 if (!cfRuleDef || CFGetTypeID(cfRuleDef) != CFDictionaryGetTypeID())
323 {
324 Syslog::alert("'%s' does not name a built-in rule", ruleDefString.c_str());
325 MacOSError::throwMe(errAuthorizationInternal);
326 }
327 mRuleDef.push_back(Rule(ruleDefString, cfRuleDef, cfRules));
328 }
329 else // array
330 {
331 vector<string> ruleDef = Attribute::getVector(cfRight, kRuleDelegateID, true);
332 for (vector<string>::const_iterator it = ruleDef.begin(); it != ruleDef.end(); it++)
333 {
334 CFStringRef ruleNameRef = makeCFString(*it);
335 CFDictionaryRef cfRuleDef = reinterpret_cast<CFDictionaryRef>(CFDictionaryGetValue(cfRules, ruleNameRef));
336 if (ruleNameRef)
337 CFRelease(ruleNameRef);
338 if (!cfRuleDef || (CFGetTypeID(cfRuleDef) != CFDictionaryGetTypeID()))
339 {
340 Syslog::alert("Invalid rule '%s'in rule set", it->c_str());
341 MacOSError::throwMe(errAuthorizationInternal);
342 }
343 mRuleDef.push_back(Rule(*it, cfRuleDef, cfRules));
344 }
345 }
346
347 mKofN = int(Attribute::getDouble(cfRight, kKofNID, false, 0.0));
348 if (mKofN)
349 mType = kKofN;
350
351 }
352 else
353 {
354 secdebug("authrule", "%s : rule class '%s' unknown.", inRightName.c_str(), classTag.c_str());
355 Syslog::alert("%s : rule class '%s' unknown", inRightName.c_str(), classTag.c_str());
356 MacOSError::throwMe(errAuthorizationInternal);
357 }
358 }
359 else
360 {
361 // no class tag means, this is the abbreviated specification from the API
362 // it _must_ have a definition for "rule" which will be used as a delegate
363 // it may have a comment (not extracted here)
364 // it may have a default prompt, or a whole dictionary of languages (not extracted here)
365 mType = kRuleDelegation;
366 string ruleName = Attribute::getString(cfRight, kRuleDelegateID, true);
367 secdebug("authrule", "%s : rule delegate rule (1): %s", inRightName.c_str(), ruleName.c_str());
368 CFStringRef ruleNameRef = makeCFString(ruleName);
369 CFDictionaryRef cfRuleDef = reinterpret_cast<CFDictionaryRef>(CFDictionaryGetValue(cfRules, ruleNameRef));
370 if (ruleNameRef)
371 CFRelease(ruleNameRef);
372 if (!cfRuleDef || CFGetTypeID(cfRuleDef) != CFDictionaryGetTypeID())
373 {
374 Syslog::alert("Rule '%s' for right '%s' does not exist or is not properly formed", ruleName.c_str(), inRightName.c_str());
375 MacOSError::throwMe(errAuthorizationInternal);
376 }
377 mRuleDef.push_back(Rule(ruleName, cfRuleDef, cfRules));
378 }
379
380 Attribute::getLocalizedText(cfRight, mLocalizedPrompts, kPromptID, kAuthorizationRuleParameterDescription);
381 Attribute::getLocalizedText(cfRight, mLocalizedButtons, kButtonID, kAuthorizationRuleParameterButton);
382 }
383
384 /*
385 RuleImpl::~Rule()
386 {
387 }
388 */
389
390 void
391 RuleImpl::setAgentHints(const AuthItemRef &inRight, const Rule &inTopLevelRule, AuthItemSet &environmentToClient, AuthorizationToken &auth) const
392 {
393 string authorizeString(inRight->name());
394 environmentToClient.erase(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT));
395 environmentToClient.insert(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT, AuthValueOverlay(authorizeString)));
396
397 pid_t creatorPid = auth.creatorPid();
398 environmentToClient.erase(AuthItemRef(AGENT_HINT_CREATOR_PID));
399 environmentToClient.insert(AuthItemRef(AGENT_HINT_CREATOR_PID, AuthValueOverlay(sizeof(pid_t), &creatorPid)));
400
401 audit_token_t creatorAuditToken = auth.creatorAuditToken().auditToken();
402 environmentToClient.erase(AuthItemRef(AGENT_HINT_CREATOR_AUDIT_TOKEN));
403 environmentToClient.insert(AuthItemRef(AGENT_HINT_CREATOR_AUDIT_TOKEN, AuthValueOverlay(sizeof(audit_token_t), &creatorAuditToken)));
404
405 Process &thisProcess = Server::process();
406 string bundlePath;
407 if (SecStaticCodeRef clientCode = auth.creatorCode())
408 bundlePath = codePath(clientCode);
409 AuthItemSet processHints = SecurityAgent::Client::clientHints(
410 SecurityAgent::bundle, bundlePath, thisProcess.pid(), thisProcess.uid());
411 environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_TYPE));
412 environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PATH));
413 environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PID));
414 environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_UID));
415 environmentToClient.insert(processHints.begin(), processHints.end());
416
417 map<string,string> defaultPrompts = inTopLevelRule->localizedPrompts();
418 map<string,string> defaultButtons = inTopLevelRule->localizedButtons();
419
420 if (defaultPrompts.empty())
421 defaultPrompts = localizedPrompts();
422 if (defaultButtons.empty())
423 defaultButtons = localizedButtons();
424
425 if (!defaultPrompts.empty())
426 {
427 map<string,string>::const_iterator it;
428 for (it = defaultPrompts.begin(); it != defaultPrompts.end(); it++)
429 {
430 const string &key = it->first;
431 const string &value = it->second;
432 environmentToClient.insert(AuthItemRef(key.c_str(), AuthValueOverlay(value)));
433 }
434 }
435 if (!defaultButtons.empty())
436 {
437 map<string,string>::const_iterator it;
438 for (it = defaultButtons.begin(); it != defaultButtons.end(); it++)
439 {
440 const string &key = it->first;
441 const string &value = it->second;
442 environmentToClient.insert(AuthItemRef(key.c_str(), AuthValueOverlay(value)));
443 }
444 }
445
446 // add rulename as a hint
447 string ruleName = name();
448 environmentToClient.erase(AuthItemRef(AGENT_HINT_AUTHORIZE_RULE));
449 environmentToClient.insert(AuthItemRef(AGENT_HINT_AUTHORIZE_RULE, AuthValueOverlay(ruleName)));
450 }
451
452 // If a different evaluation for getting a credential is prescribed,
453 // we'll run that and validate the credentials from there.
454 // we fall back on a default configuration from the authenticate rule
455 OSStatus
456 RuleImpl::evaluateAuthentication(const AuthItemRef &inRight, const Rule &inRule,AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const
457 {
458 OSStatus status = errAuthorizationDenied;
459
460 Credential hintCredential;
461 if (errAuthorizationSuccess == evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, hintCredential, reason)) {
462 if (hintCredential->name().length())
463 environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER, AuthValueOverlay(hintCredential->name())));
464 if (hintCredential->realname().length())
465 environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER_LONG, AuthValueOverlay(hintCredential->realname())));
466 }
467
468 if ((mType == kUser) && (mGroupName.length()))
469 environmentToClient.insert(AuthItemRef(AGENT_HINT_REQUIRE_USER_IN_GROUP, AuthValueOverlay(mGroupName)));
470
471 uint32 tries;
472 reason = SecurityAgent::noReason;
473
474 Process &cltProc = Server::process();
475 // Authorization preserves creator's UID in setuid processes
476 // (which is nice, but cltUid ends up being unused except by the debug
477 // message -- AgentMechanismEvaluator ignores it)
478 uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid();
479 secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid);
480
481 // For auditing within AuthorizationMechEval, pass the right name.
482 size_t rightNameSize = inRight->name() ? strlen(inRight->name()) : 0;
483 AuthorizationString rightName = inRight->name() ? inRight->name() : "";
484 // @@@ AuthValueRef's ctor ought to take a const void *
485 AuthValueRef rightValue(rightNameSize, const_cast<char *>(rightName));
486 AuthValueVector authValueVector;
487 authValueVector.push_back(rightValue);
488
489 RightAuthenticationLogger rightAuthLogger(auth.creatorAuditToken(), AUE_ssauthint);
490 rightAuthLogger.setRight(rightName);
491
492 // Just succeed for a continuously active session owner.
493 if (auth.session().originatorUid() == auth.creatorUid() && auth.session().attributes() & AU_SESSION_FLAG_HAS_AUTHENTICATED) {
494 secdebug("AuthEvalMech", "We are an active session owner.");
495 aslmsg m = asl_new(ASL_TYPE_MSG);
496 asl_set(m, "com.apple.message.domain", "com.apple.securityd.UserActivity");
497 asl_set(m, "com.apple.message.signature", "userIsActive");
498 asl_set(m, "com.apple.message.signature2", rightName);
499 asl_set(m, "com.apple.message.result", "failure");
500 asl_log(NULL, m, ASL_LEVEL_NOTICE, "We are an active session owner.");
501 asl_free(m);
502 // Credential rightCredential(rightName, auth.creatorUid(), mShared);
503 // credentials.erase(rightCredential); credentials.insert(rightCredential);
504 // return errAuthorizationSuccess;
505 }
506 else {
507 secdebug("AuthEvalMech", "We are not an active session owner.");
508 aslmsg m = asl_new(ASL_TYPE_MSG);
509 asl_set(m, "com.apple.message.domain", "com.apple.securityd.UserActivity");
510 asl_set(m, "com.apple.message.signature", "userIsNotActive");
511 asl_set(m, "com.apple.message.signature2", rightName);
512 asl_set(m, "com.apple.message.result", "success");
513 asl_log(NULL, m, ASL_LEVEL_NOTICE, "We are not an active session owner.");
514 asl_free(m);
515 }
516
517 AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef);
518
519 for (tries = 0; tries < mTries; tries++)
520 {
521 AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason));
522 environmentToClient.erase(retryHint); environmentToClient.insert(retryHint); // replace
523 AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries));
524 environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace
525
526 status = eval.run(authValueVector, environmentToClient, auth);
527
528 if ((status == errAuthorizationSuccess) ||
529 (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context
530 {
531 secdebug("AuthEvalMech", "storing new context for authorization");
532 auth.setInfoSet(eval.context(), savePassword);
533 }
534
535 // successfully ran mechanisms to obtain credential
536 if (status == errAuthorizationSuccess)
537 {
538 // deny is the default
539 status = errAuthorizationDenied;
540
541 CredentialSet newCredentials = makeCredentials(auth);
542 // clear context after extracting credentials
543 auth.scrubInfoSet(savePassword);
544
545 for (CredentialSet::const_iterator it = newCredentials.begin(); it != newCredentials.end(); ++it)
546 {
547 const Credential& newCredential = *it;
548
549 // @@@ we log the uid a process was running under when it created the authref, which is misleading in the case of loginwindow
550 if (newCredential->isValid()) {
551 Syslog::info("UID %u authenticated as user %s (UID %u) for right '%s'", auth.creatorUid(), newCredential->name().c_str(), newCredential->uid(), rightName);
552 rightAuthLogger.logSuccess(auth.creatorUid(), newCredential->uid(), newCredential->name().c_str());
553 } else {
554 // we can't be sure that the user actually exists so inhibit logging of uid
555 Syslog::error("UID %u failed to authenticate as user '%s' for right '%s'", auth.creatorUid(), newCredential->name().c_str(), rightName);
556 rightAuthLogger.logFailure(auth.creatorUid(), newCredential->name().c_str());
557 }
558
559 if (!newCredential->isValid())
560 {
561 reason = SecurityAgent::invalidPassphrase;
562 continue;
563 }
564
565 // verify that this credential authorizes right
566 status = evaluateUserCredentialForRight(auth, inRight, inRule, environmentToClient, now, newCredential, true, reason);
567
568 if (status == errAuthorizationSuccess)
569 {
570 if (auth.operatesAsLeastPrivileged()) {
571 Credential rightCredential(rightName, mShared);
572 credentials.erase(rightCredential); credentials.insert(rightCredential);
573 if (mShared)
574 credentials.insert(Credential(rightName, false));
575 }
576
577 // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent
578 credentials.erase(newCredential); credentials.insert(newCredential);
579 // just got a new credential - if it's shared also add a non-shared one that to stick in the authorizationref local cache
580 if (mShared)
581 credentials.insert(Credential(newCredential->uid(), newCredential->name(), newCredential->realname(), false));
582
583 // use valid credential to set context info
584 // XXX/cs keeping this for now, such that the uid is passed back
585 auth.setCredentialInfo(newCredential, savePassword);
586 secdebug("SSevalMech", "added valid credential for user %s", newCredential->name().c_str());
587 // set the sessionHasAuthenticated
588 if (newCredential->uid() == auth.session().originatorUid()) {
589 secdebug("AuthEvalMech", "We authenticated as the session owner.\n");
590 SessionAttributeBits flags = auth.session().attributes();
591 flags |= AU_SESSION_FLAG_HAS_AUTHENTICATED;
592 auth.session().setAttributes(flags);
593 }
594
595 status = errAuthorizationSuccess;
596 break;
597 }
598 }
599
600 if (status == errAuthorizationSuccess)
601 break;
602 }
603 else
604 if ((status == errAuthorizationCanceled) || (status == errAuthorizationInternal))
605 {
606 auth.scrubInfoSet(false);
607 break;
608 }
609 else // last mechanism is now authentication - fail
610 if (status == errAuthorizationDenied)
611 reason = SecurityAgent::invalidPassphrase;
612 }
613
614 // If we fell out of the loop because of too many tries, notify user
615 if (tries == mTries)
616 {
617 reason = SecurityAgent::tooManyTries;
618 AuthItemRef retryHint (AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason));
619 environmentToClient.erase(retryHint); environmentToClient.insert(retryHint); // replace
620 AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries));
621 environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace
622 eval.run(AuthValueVector(), environmentToClient, auth);
623 // XXX/cs is this still necessary?
624 auth.scrubInfoSet(false);
625
626 rightAuthLogger.logFailure(NULL, CommonCriteria::errTooManyTries);
627 }
628
629 return status;
630 }
631
632 // create externally verified credentials on the basis of
633 // mechanism-provided information
634 CredentialSet
635 RuleImpl::makeCredentials(const AuthorizationToken &auth) const
636 {
637 // fetch context and construct a credential to be tested
638 const AuthItemSet &context = const_cast<AuthorizationToken &>(auth).infoSet();
639 CredentialSet newCredentials;
640
641 do {
642 AuthItemSet::const_iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) );
643 if (found == context.end())
644 break;
645 string username = (**found).stringValue();
646 secdebug("AuthEvalMech", "found username");
647
648 const uid_t *uid = NULL;
649 found = find_if(context.begin(), context.end(), FindAuthItemByRightName("uid") );
650 if (found != context.end())
651 {
652 uid = static_cast<const uid_t *>((**found).value().data);
653 secdebug("AuthEvalMech", "found uid");
654 }
655
656 if (username.length() && uid)
657 {
658 // credential is valid because mechanism says so
659 newCredentials.insert(Credential(*uid, username, "", mShared));
660 }
661 } while(0);
662
663 return newCredentials;
664 }
665
666 // evaluate whether a good credential of the current session owner would authorize a right
667 OSStatus
668 RuleImpl::evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, const CFAbsoluteTime now, const AuthorizationToken &auth, Credential &credential, SecurityAgent::Reason &reason) const
669 {
670 // username hint is taken from the user who created the authorization, unless it's clearly ineligible
671 // @@@ we have no access to current requester uid here and the process uid is only taken when the authorization is created
672 // meaning that a process like loginwindow that drops privs later is screwed.
673
674 Credential sessionCredential;
675 uid_t uid = auth.session().originatorUid();
676 Server::active().longTermActivity();
677 struct passwd *pw = getpwuid(uid);
678 if (pw != NULL) {
679 // avoid hinting a locked account
680 if ( (pw->pw_passwd == NULL) ||
681 strcmp(pw->pw_passwd, "*") ) {
682 // Check if username will authorize the request and set username to
683 // be used as a hint to the user if so
684 secdebug("AuthEvalMech", "preflight credential from current user, result follows:");
685 sessionCredential = Credential(pw->pw_uid, pw->pw_name, pw->pw_gecos, mShared/*ignored*/);
686 } //fi
687 endpwent();
688 }
689 OSStatus status = evaluateUserCredentialForRight(auth, inRight, inRule, environment, now, sessionCredential, true, reason);
690 if (errAuthorizationSuccess == status)
691 credential = sessionCredential;
692
693 return status;
694 }
695
696
697 OSStatus
698 RuleImpl::evaluateCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared, SecurityAgent::Reason &reason) const
699 {
700 if (auth.operatesAsLeastPrivileged()) {
701 if (credential->isRight() && credential->isValid() && (inRight->name() == credential->name()))
702 {
703 if (!ignoreShared && !mShared && credential->isShared())
704 {
705 // @@@ no proper SA::Reason
706 reason = SecurityAgent::unknownReason;
707 secdebug("autheval", "shared credential cannot be used, denying right %s", inRight->name());
708 return errAuthorizationDenied;
709 } else {
710 return errAuthorizationSuccess;
711 }
712 } else {
713 // @@@ no proper SA::Reason
714 reason = SecurityAgent::unknownReason;
715 return errAuthorizationDenied;
716 }
717 } else
718 return evaluateUserCredentialForRight(auth, inRight, inRule, environment, now, credential, false, reason);
719 }
720
721 // Return errAuthorizationSuccess if this rule allows access based on the specified credential,
722 // return errAuthorizationDenied otherwise.
723 OSStatus
724 RuleImpl::evaluateUserCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared, SecurityAgent::Reason &reason) const
725 {
726 assert(mType == kUser);
727
728 // Ideally we'd set the AGENT_HINT_RETRY_REASON hint in this method, but
729 // evaluateAuthentication() overwrites it before
730 // AgentMechanismEvaluator::run(). That's what led to passing "reason"
731 // everywhere, from RuleImpl::evaluate() on down.
732
733 // Get the username from the credential
734 const char *user = credential->name().c_str();
735
736 // If the credential is not valid or its age is more than the allowed maximum age
737 // for a credential, deny.
738 if (!credential->isValid())
739 {
740 // @@@ it could be the username, not password, was invalid
741 reason = SecurityAgent::invalidPassphrase;
742 secdebug("autheval", "credential for user %s is invalid, denying right %s", user, inRight->name());
743 return errAuthorizationDenied;
744 }
745
746 if (now - credential->creationTime() > mMaxCredentialAge)
747 {
748 // @@@ no proper SA::Reason
749 reason = SecurityAgent::unknownReason;
750 secdebug("autheval", "credential for user %s has expired, denying right %s", user, inRight->name());
751 return errAuthorizationDenied;
752 }
753
754 if (!ignoreShared && !mShared && credential->isShared())
755 {
756 // @@@ no proper SA::Reason
757 reason = SecurityAgent::unknownReason;
758 secdebug("autheval", "shared credential for user %s cannot be used, denying right %s", user, inRight->name());
759 return errAuthorizationDenied;
760 }
761
762 // A root (uid == 0) user can do anything
763 if (credential->uid() == 0)
764 {
765 secdebug("autheval", "user %s has uid 0, granting right %s", user, inRight->name());
766 return errAuthorizationSuccess;
767 }
768
769 if (mSessionOwner)
770 {
771 Session &session = auth.session();
772 uid_t console_user = session.originatorUid();
773
774 if (credential->uid() == console_user)
775 {
776 secdebug("autheval", "user %s is session-owner(uid: %d), granting right %s", user, console_user, inRight->name());
777 return errAuthorizationSuccess;
778 }
779 // set "reason" in this case? not that a proper SA::Reason exists
780 }
781 else
782 {
783 // @@@ no proper SA::Reason
784 reason = SecurityAgent::unknownReason;
785 secdebug("autheval", "session-owner check failed.");
786 }
787
788 if (mGroupName.length())
789 {
790 const char *groupname = mGroupName.c_str();
791 Server::active().longTermActivity();
792
793 if (!groupname)
794 return errAuthorizationDenied;
795
796 do
797 {
798 uuid_t group_uuid, user_uuid;
799 int is_member;
800
801 // @@@ it'd be nice to have SA::Reason codes for the failures
802 // associated with the pre-check-membership mbr_*() functions,
803 // but userNotInGroup will do
804 if (mbr_group_name_to_uuid(groupname, group_uuid))
805 break;
806
807 if (mbr_uid_to_uuid(credential->uid(), user_uuid))
808 {
809 struct passwd *pwd;
810 if (NULL == (pwd = getpwnam(user)))
811 break;
812 if (mbr_uid_to_uuid(pwd->pw_uid, user_uuid))
813 break;
814 }
815
816 if (mbr_check_membership(user_uuid, group_uuid, &is_member))
817 break;
818
819 if (is_member)
820 {
821 secdebug("autheval", "user %s is a member of group %s, granting right %s",
822 user, groupname, inRight->name());
823 return errAuthorizationSuccess;
824 }
825
826 }
827 while (0);
828
829 reason = SecurityAgent::userNotInGroup;
830 secdebug("autheval", "user %s is not a member of group %s, denying right %s",
831 user, groupname, inRight->name());
832 }
833 else if (mSessionOwner) // rule asks only if user is the session owner
834 {
835 reason = SecurityAgent::unacceptableUser;
836 }
837
838 return errAuthorizationDenied;
839 }
840
841
842
843 OSStatus
844 RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const
845 {
846 // If we got here, this is a kUser type rule, let's start looking for a
847 // credential that is satisfactory
848
849 // Zeroth -- Here is an extra special saucy ugly hack to allow authorizations
850 // created by a proccess running as root to automatically get a right.
851 if (mAllowRoot && auth.creatorUid() == 0)
852 {
853 SECURITYD_AUTH_USER_ALLOWROOT(&auth);
854
855 secdebug("autheval", "creator of authorization has uid == 0 granting right %s",
856 inRight->name());
857 return errAuthorizationSuccess;
858 }
859
860 // if we're not supposed to authenticate evaluate the session-owner against the group
861 if (!mAuthenticateUser)
862 {
863 Credential hintCredential;
864 OSStatus status = evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, hintCredential, reason);
865
866 if (!status)
867 {
868 SECURITYD_AUTH_USER_ALLOWSESSIONOWNER(&auth);
869 return errAuthorizationSuccess;
870 }
871
872 return errAuthorizationDenied;
873 }
874
875 // First -- go though the credentials we either already used or obtained during this authorize operation.
876 for (CredentialSet::const_iterator it = credentials.begin(); it != credentials.end(); ++it)
877 {
878 // Passed-in user credentials are allowed for least-privileged mode
879 if (auth.operatesAsLeastPrivileged() && !(*it)->isRight() && (*it)->isValid())
880 {
881 OSStatus status = evaluateUserCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false, reason);
882 if (errAuthorizationSuccess == status) {
883 Credential rightCredential(inRight->name(), mShared);
884 credentials.erase(rightCredential); credentials.insert(rightCredential);
885 if (mShared)
886 credentials.insert(Credential(inRight->name(), false));
887 return status;
888 }
889 }
890
891 // if this is least privileged, this will function differently: match credential to requested right
892 OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false, reason);
893
894 if (status != errAuthorizationDenied) {
895 // add credential to authinfo
896 auth.setCredentialInfo(*it, savePassword);
897 return status;
898 }
899
900 }
901
902 // Second -- go though the credentials passed in to this authorize operation by the state management layer.
903 if (inCredentials)
904 {
905 for (CredentialSet::const_iterator it = inCredentials->begin(); it != inCredentials->end(); ++it)
906 {
907 // if this is least privileged, this will function differently: match credential to requested right
908 OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false, reason);
909
910 if (status == errAuthorizationSuccess)
911 {
912 // Add the credential we used to the output set.
913 // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent
914 credentials.erase(*it); credentials.insert(*it);
915 // add credential to authinfo
916 auth.setCredentialInfo(*it, savePassword);
917
918 return status;
919 }
920 else if (status != errAuthorizationDenied)
921 return status;
922 }
923 }
924
925 // Finally -- We didn't find the credential in our passed in credential lists. Obtain a new credential if our flags let us do so.
926 if (!(flags & kAuthorizationFlagExtendRights))
927 return errAuthorizationDenied;
928
929 // authorizations that timeout immediately cannot be preauthorized
930 if ((flags & kAuthorizationFlagPreAuthorize) &&
931 (mMaxCredentialAge == 0.0))
932 {
933 inRight->setFlags(inRight->flags() | kAuthorizationFlagCanNotPreAuthorize);
934 return errAuthorizationSuccess;
935 }
936
937 if (!(flags & kAuthorizationFlagInteractionAllowed))
938 return errAuthorizationInteractionNotAllowed;
939
940 setAgentHints(inRight, inRule, environmentToClient, auth);
941
942 return evaluateAuthentication(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword);
943 }
944
945 OSStatus
946 RuleImpl::evaluateMechanismOnly(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationToken &auth, CredentialSet &outCredentials, bool savePassword) const
947 {
948 uint32 tries = 0;
949 OSStatus status;
950
951 Process &cltProc = Server::process();
952 // Authorization preserves creator's UID in setuid processes
953 uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid();
954 secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid);
955
956 {
957 AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef);
958 // For auditing within AuthorizationMechEval, pass the right name.
959 size_t rightNameSize = inRight->name() ? strlen(inRight->name()) : 0;
960 AuthorizationString rightName = inRight->name() ? inRight->name() : "";
961 // @@@ AuthValueRef's ctor ought to take a const void *
962 AuthValueRef rightValue(rightNameSize, const_cast<char *>(rightName));
963 AuthValueVector authValueVector;
964 authValueVector.push_back(rightValue);
965
966 do
967 {
968 setAgentHints(inRight, inRule, environmentToClient, auth);
969 AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries));
970 environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace
971
972 status = eval.run(authValueVector, environmentToClient, auth);
973 if ((status == errAuthorizationSuccess) ||
974 (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context
975 {
976 secdebug("AuthEvalMech", "storing new context for authorization");
977 auth.setInfoSet(eval.context(), savePassword);
978 if (status == errAuthorizationSuccess)
979 {
980 // (try to) attach the authorizing UID to the least-priv cred
981 if (auth.operatesAsLeastPrivileged())
982 {
983 outCredentials.insert(Credential(rightName, mShared));
984 if (mShared)
985 outCredentials.insert(Credential(rightName, false));
986
987 RightAuthenticationLogger logger(auth.creatorAuditToken(), AUE_ssauthint);
988 logger.setRight(rightName);
989
990 AuthItem *uidItem = eval.context().find(AGENT_CONTEXT_UID);
991 if (uidItem)
992 {
993 uid_t authorizedUid;
994 memcpy(&authorizedUid, uidItem->value().data, sizeof(authorizedUid));
995 secdebug("AuthEvalMech", "generating least-privilege cred for '%s' authorized by UID %u", inRight->name(), authorizedUid);
996 logger.logLeastPrivilege(authorizedUid, true);
997 }
998 else // cltUid is better than nothing
999 {
1000 secdebug("AuthEvalMech", "generating least-privilege cred for '%s' with process- or auth-UID %u", inRight->name(), cltUid);
1001 logger.logLeastPrivilege(cltUid, false);
1002 }
1003 }
1004
1005 if (0 == strcmp(rightName, "system.login.console") && NULL == eval.context().find(AGENT_CONTEXT_AUTO_LOGIN)) {
1006 secdebug("AuthEvalMech", "We logged in as the session owner.\n");
1007 SessionAttributeBits flags = auth.session().attributes();
1008 flags |= AU_SESSION_FLAG_HAS_AUTHENTICATED;
1009 auth.session().setAttributes(flags);
1010 }
1011 CredentialSet newCredentials = makeCredentials(auth);
1012 outCredentials.insert(newCredentials.begin(), newCredentials.end());
1013 }
1014 }
1015
1016 tries++;
1017 }
1018 while ((status == errAuthorizationDenied) // only if we have an expected failure we continue
1019 && ((mTries == 0) // mTries == 0 means we try forever
1020 || ((mTries > 0) // mTries > 0 means we try up to mTries times
1021 && (tries < mTries))));
1022 }
1023
1024 // HACK kill all hosts to free pages for low memory systems
1025 // (XXX/gh there should be a #define for this right)
1026 if (name() == "system.login.done")
1027 {
1028 // one case where we don't want to mark the agents as "busy"
1029 QueryInvokeMechanism query(securityAgent, auth.session());
1030 query.terminateAgent();
1031 QueryInvokeMechanism query2(privilegedAuthHost, auth.session());
1032 query2.terminateAgent();
1033 }
1034
1035 return status;
1036 }
1037
1038 OSStatus
1039 RuleImpl::evaluateRules(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const
1040 {
1041 // line up the rules to try
1042 if (!mRuleDef.size())
1043 return errAuthorizationSuccess;
1044
1045 uint32_t count = 0;
1046 OSStatus status = errAuthorizationSuccess;
1047 vector<Rule>::const_iterator it;
1048
1049 for (it = mRuleDef.begin();it != mRuleDef.end(); it++)
1050 {
1051 // are we at k yet?
1052 if ((mType == kKofN) && (count == mKofN))
1053 return errAuthorizationSuccess;
1054
1055 // get a rule and try it
1056 status = (*it)->evaluate(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword);
1057
1058 // if status is cancel/internal error abort
1059 if ((status == errAuthorizationCanceled) || (status == errAuthorizationInternal))
1060 return status;
1061
1062 if (status != errAuthorizationSuccess)
1063 {
1064 // continue if we're only looking for k of n
1065 if (mType == kKofN)
1066 continue;
1067
1068 break;
1069 }
1070 else
1071 count++;
1072 }
1073
1074 if ((mType == kKofN) && (status == errAuthorizationSuccess) && (count < mKofN))
1075 status = errAuthorizationDenied;
1076
1077 return status; // return the last failure
1078 }
1079
1080
1081 OSStatus
1082 RuleImpl::evaluate(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const
1083 {
1084 switch (mType)
1085 {
1086 case kAllow:
1087 SECURITYD_AUTH_ALLOW(&auth, (char *)name().c_str());
1088 return errAuthorizationSuccess;
1089 case kDeny:
1090 SECURITYD_AUTH_DENY(&auth, (char *)name().c_str());
1091 return errAuthorizationDenied;
1092 case kUser:
1093 SECURITYD_AUTH_USER(&auth, (char *)name().c_str());
1094 return evaluateUser(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword);
1095 case kRuleDelegation:
1096 SECURITYD_AUTH_RULES(&auth, (char *)name().c_str());
1097 return evaluateRules(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword);
1098 case kKofN:
1099 SECURITYD_AUTH_KOFN(&auth, (char *)name().c_str());
1100 return evaluateRules(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword);
1101 case kEvaluateMechanisms:
1102 SECURITYD_AUTH_MECHRULE(&auth, (char *)name().c_str());
1103 // if we had a SecurityAgent::Reason code for "mechanism denied,"
1104 // it would make sense to pass down "reason"
1105 return evaluateMechanismOnly(inRight, inRule, environmentToClient, auth, credentials, savePassword);
1106 default:
1107 Syslog::alert("Unrecognized rule type %d", mType);
1108 MacOSError::throwMe(errAuthorizationInternal); // invalid rule
1109 }
1110 }
1111
1112 Rule::Rule() : RefPointer<RuleImpl>(new RuleImpl()) {}
1113 Rule::Rule(const string &inRightName, CFDictionaryRef cfRight, CFDictionaryRef cfRules) : RefPointer<RuleImpl>(new RuleImpl(inRightName, cfRight, cfRules)) {}
1114
1115
1116
1117 } // end namespace Authorization