X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/ce3c8656732c924baf7e88df75eab50891bdc471..fa7225c82381bac4432a6edf16f53b5370238d85:/securityd/src/AuthorizationEngine.cpp diff --git a/securityd/src/AuthorizationEngine.cpp b/securityd/src/AuthorizationEngine.cpp deleted file mode 100644 index c34507c4..00000000 --- a/securityd/src/AuthorizationEngine.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2000-2004,2006-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include "AuthorizationEngine.h" -#include -#include -#include - -#include "authority.h" - -#include -#include -#include -#include -#include -#include "server.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include // AUE_ssauth* -#include "ccaudit_extensions.h" - -namespace Authorization { - -using namespace CommonCriteria::Securityd; - - -// -// Errors to be thrown -// -Error::Error(int err) : error(err) -{ -} - -const char *Error::what() const throw() -{ return "Authorization error"; } - -int Error::unixError() const throw() -{ return error; } // @@@ eventually... - -OSStatus Error::osStatus() const throw() -{ return error; } - -void Error::throwMe(int err) { throw Error(err); } - -// -// Engine class -// -Engine::Engine(const char *configFile) : mAuthdb(configFile) -{ -} - -Engine::~Engine() -{ -} - - -/*! - @function AuthorizationEngine::authorize - - @@@. - - @param inRights (input) List of rights being requested for authorization. - @param environment (optional/input) Environment containing information to be used during evaluation. - @param flags (input) Optional flags @@@ see AuthorizationCreate for a description. - @param inCredentials (input) Credentials already held by the caller. - @param outCredentials (output/optional) Credentials obtained, used or refreshed during this call to authorize the requested rights. - @param outRights (output/optional) Subset of inRights which were actually authorized. - - @results Returns errAuthorizationSuccess if all rights requested are authorized, or if the kAuthorizationFlagPartialRights flag was specified. Might return other status values like errAuthorizationDenied, errAuthorizationCanceled or errAuthorizationInteractionNotAllowed -*/ -OSStatus -Engine::authorize(const AuthItemSet &inRights, const AuthItemSet &environment, - AuthorizationFlags flags, const CredentialSet *inCredentials, CredentialSet *outCredentials, - AuthItemSet &outRights, AuthorizationToken &auth) -{ - CredentialSet credentials; - OSStatus status = errAuthorizationSuccess; - SecurityAgent::Reason reason = SecurityAgent::noReason; - - // Get current time of day. - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); - - // Update rules from database if needed - mAuthdb.sync(now); - - // Check if a credential was passed into the environment and we were asked to extend the rights - if (flags & kAuthorizationFlagExtendRights) - { - string username, password; - bool shared = false; - for (AuthItemSet::iterator item = environment.begin(); item != environment.end(); item ++) - { - if (!strcmp((*item)->name(), kAuthorizationEnvironmentUsername)) - username = (*item)->stringValue(); - else if (!strcmp((*item)->name(), kAuthorizationEnvironmentPassword)) - password = (*item)->stringValue(); - else if (!strcmp((*item)->name(), kAuthorizationEnvironmentShared)) - shared = true; - } - - if (username.length()) - { - // Let's create a credential from the passed in username and password. - Credential newCredential(username, password, shared); - // If it's valid insert it into the credentials list. Normally this is - // only done if it actually authorizes a requested right, but for this - // special case (environment) we do it even when no rights are being requested. - if (newCredential->isValid()) - credentials.insert(newCredential); - } - } - - // generate hints for every authorization - AuthItemSet environmentToClient = environment; - - RightAuthenticationLogger logger(auth.creatorAuditToken(), AUE_ssauthorize); - - // create a vector with the first right first - std::vector tempRights; - for (AuthItemSet::const_iterator it = inRights.begin(); it != inRights.end(); ++it) { - if (inRights.firstItemName != NULL && strcmp((*it)->name(), inRights.firstItemName) == 0) - tempRights.insert(tempRights.begin(), *it); - else - tempRights.push_back(*it); - } - - bool authExtractPassword = false; - std::vector::const_iterator end = tempRights.end(); - for (std::vector::const_iterator it = tempRights.begin(); it != end; ++it) - { - // Get the rule for each right we are trying to obtain. - const Rule &toplevelRule = mAuthdb.getRule(*it); - - if (false == authExtractPassword) - authExtractPassword = toplevelRule->extractPassword(); - - string processName = "unknown"; - string authCreatorName = "unknown"; - { - StLock _(Server::process()); - if (SecCodeRef code = Server::process().currentGuest()) { - CFRef path; - if (!SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())) - processName = cfString(path); - } - } - authCreatorName = auth.creatorPath(); - - if (sandbox_check(Server::process().pid(), "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, (*it)->name())) { - Syslog::error("Sandbox denied authorizing right '%s' by client '%s' [%d]", (*it)->name(), processName.c_str(), Server::process().pid()); - return errAuthorizationDenied; - } - if (auth.creatorSandboxed() && sandbox_check(auth.creatorPid(), "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, (*it)->name())) { - Syslog::error("Sandbox denied authorizing right '%s' for authorization created by '%s' [%d]", (*it)->name(), authCreatorName.c_str(), auth.creatorPid()); - return errAuthorizationDenied; - } - - OSStatus result = toplevelRule->evaluate(*it, toplevelRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, authExtractPassword); - secdebug("autheval", "evaluate rule %s for right %s returned %d.", toplevelRule->name().c_str(), (*it)->name(), int(result)); - SECURITYD_AUTH_EVALRIGHT(&auth, (char *)(*it)->name(), result); - - logger.setRight((*it)->name()); - logger.logAuthorizationResult(processName.c_str(), authCreatorName.c_str(), result); - - if (result == errAuthorizationSuccess) - { - outRights.insert(*it); - Syslog::info("Succeeded authorizing right '%s' by client '%s' [%d] for authorization created by '%s' [%d] (%X,%d)", (*it)->name(), processName.c_str(), Server::process().pid(), authCreatorName.c_str(), auth.creatorPid(), uint32_t(flags), auth.operatesAsLeastPrivileged()); - } - else if (result == errAuthorizationDenied || result == errAuthorizationInteractionNotAllowed) - { - if (result == errAuthorizationDenied) - { - secdebug("autheval", "Failed to authorize right '%s' by client '%s' [%d] for authorization created by '%s' [%d] (%X,%d)", (*it)->name(), processName.c_str(), Server::process().pid(), authCreatorName.c_str(), auth.creatorPid(), uint32_t(flags), auth.operatesAsLeastPrivileged()); - } - - // add creator pid to authorization token - if (!(flags & kAuthorizationFlagPartialRights)) - { - status = result; - break; - } - } - else if (result == errAuthorizationCanceled) - { - status = result; - break; - } - else - { - Syslog::error("Engine::authorize: Rule::evaluate returned %ld returning errAuthorizationInternal", result); - status = errAuthorizationInternal; - break; - } - } - - // purge all uid credentials from the outCredentials for least privileged mode - if (auth.operatesAsLeastPrivileged()) { - CredentialSet::const_iterator current, it = outCredentials->begin(); - while(it != outCredentials->end()) { - current = it++; - if (!(*current)->isRight()) { - outCredentials->erase(current); - } - } - } - - if (outCredentials) - outCredentials->swap(credentials); - - return status; -} - -OSStatus -Engine::verifyModification(string inRightName, bool remove, - const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) -{ - // Validate right - - // meta rights are constructed as follows: - // we don't allow setting of wildcard rights, so you can only be more specific - // note that you should never restrict things with a wildcard right without disallowing - // changes to the entire domain. ie. - // system.privilege. -> never - // config.add.system.privilege. -> never - // config.modify.system.privilege. -> never - // config.delete.system.privilege. -> never - // For now we don't allow any configuration of configuration rules - // config.config. -> never - - string rightnameToCheck; - - // @@@ verify right name is is not NULL or zero length - if (inRightName.length() == 0) - return errAuthorizationDenied; - - // @@@ make sure it isn't a wildcard right by checking trailing "." - if ( *(inRightName.rbegin()) == '.') - return errAuthorizationDenied; - - // @@@ make sure it isn't a configure right by checking it doesn't start with config. - if (inRightName.find(kConfigRight, 0) != string::npos) - { - // special handling of meta right change: - // config.add. config.modify. config.remove. config.{}. - // check for config. (which always starts with config.config.) - rightnameToCheck = string(kConfigRight) + inRightName; - } - else - { - // regular check of rights - bool existingRule = mAuthdb.existRule(inRightName); - if (!remove) - { - if (existingRule) - rightnameToCheck = string(kAuthorizationConfigRightModify) + inRightName; - else - rightnameToCheck = string(kAuthorizationConfigRightAdd) + inRightName; - } - else - { - if (existingRule) - rightnameToCheck = string(kAuthorizationConfigRightRemove) + inRightName; - else - { - secdebug("engine", "rule %s doesn't exist.", inRightName.c_str()); - return errAuthorizationSuccess; // doesn't exist, done - } - } - } - - - AuthItemSet rights, environment, outRights; - rights.insert(AuthItemRef(rightnameToCheck.c_str())); - secdebug("engine", "authorizing %s for db modification.", rightnameToCheck.c_str()); - return authorize(rights, environment, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, inCredentials, outCredentials, outRights, auth); -} - -OSStatus -Engine::getRule(string &inRightName, CFDictionaryRef *outRuleDefinition) -{ - // Get current time of day. - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); - - // Update rules from database if needed - mAuthdb.sync(now); - - CFDictionaryRef definition = mAuthdb.getRuleDefinition(inRightName); - if (definition) - { - if (outRuleDefinition) - *outRuleDefinition = definition; - else - CFRelease(definition); - - return errAuthorizationSuccess; - } - - return errAuthorizationDenied; -} - -OSStatus -Engine::setRule(const char *inRightName, CFDictionaryRef inRuleDefinition, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) -{ - // Validate rule by constructing it from the passed dictionary - if (!mAuthdb.validateRule(inRightName, inRuleDefinition)) - return errAuthorizationDenied; // @@@ separate error for this? - - OSStatus result = verifyModification(inRightName, false /*setting, not removing*/, inCredentials, outCredentials, auth); - if (result != errAuthorizationSuccess) - return result; - - // set the rule for the right and save the database - mAuthdb.setRule(inRightName, inRuleDefinition); - - return errAuthorizationSuccess; -} - -OSStatus -Engine::removeRule(const char *inRightName, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) -{ - // Get current time of day. - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); - - // Update rules from database if needed - mAuthdb.sync(now); - - OSStatus result = verifyModification(inRightName, true /*removing*/, inCredentials, outCredentials, auth); - if (result != errAuthorizationSuccess) - return result; - - // set the rule for the right and save the database - mAuthdb.removeRule(inRightName); - - return errAuthorizationSuccess; -} - -} // end namespace Authorization