]> git.saurik.com Git - apple/securityd.git/blobdiff - src/AuthorizationEngine.cpp
securityd-55199.3.tar.gz
[apple/securityd.git] / src / AuthorizationEngine.cpp
index a2d0f6e70709ccbaaa2843361174428770764c9c..b989fc3681762809ed0849f7c85efc7aa5027bde 100644 (file)
@@ -1,10 +1,8 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2004,2009 Apple Inc. All Rights Reserved.
  * 
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
- * 
  * 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
  * @APPLE_LICENSE_HEADER_END@
  */
 
-
-/*
- *  AuthorizationEngine.cpp
- *  Authorization
- *
- *  Created by Michael Brouwer on Thu Oct 12 2000.
- *
- */
 #include "AuthorizationEngine.h"
 #include <security_cdsa_utilities/AuthorizationWalkers.h>
 #include <Security/AuthorizationPriv.h>
 #include <Security/AuthorizationDB.h>
 
-
 #include "authority.h"
 
 #include <Security/AuthorizationTags.h>
@@ -44,7 +33,6 @@
 #include <security_utilities/logging.h>
 #include <security_utilities/cfutilities.h>
 #include <security_utilities/debugging.h>
-//#include "session.h"
 #include "server.h"
 
 #include <CoreFoundation/CFData.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <float.h>
+#include <sandbox.h>
+
+#include <bsm/audit_uevents.h>      // AUE_ssauth*
+#include "ccaudit_extensions.h"
 
 namespace Authorization {
 
+using namespace CommonCriteria::Securityd;
+    
 
 //
 // Errors to be thrown
@@ -109,6 +103,7 @@ Engine::authorize(const AuthItemSet &inRights, const AuthItemSet &environment,
 {
        CredentialSet credentials;
        OSStatus status = errAuthorizationSuccess;
+    SecurityAgent::Reason reason = SecurityAgent::noReason;
 
        // Get current time of day.
        CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
@@ -146,49 +141,97 @@ Engine::authorize(const AuthItemSet &inRights, const AuthItemSet &environment,
        // generate hints for every authorization
     AuthItemSet environmentToClient = environment;
 
-       AuthItemSet::const_iterator end = inRights.end();
-       for (AuthItemSet::const_iterator it = inRights.begin(); it != end; ++it)
+    RightAuthenticationLogger logger(auth.creatorAuditToken(), AUE_ssauthorize);
+    
+       // create a vector with the first right first
+       std::vector<AuthItemRef>                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<AuthItemRef>::const_iterator end = tempRights.end();
+       for (std::vector<AuthItemRef>::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);
-               OSStatus result = toplevelRule->evaluate(*it, toplevelRule, environmentToClient, flags, now, inCredentials, credentials, auth);
-               secdebug("autheval", "evaluate rule %s for right %s returned %ld.", toplevelRule->name().c_str(), (*it)->name(), result);
 
+               if (false == authExtractPassword)
+                       authExtractPassword = toplevelRule->extractPassword();
+
+        string processName = "unknown";
+        string authCreatorName = "unknown";
                {
-                       CodeSigning::OSXCode *processCode = Server::process().clientCode();
-                       string processName = processCode ? processCode->canonicalPath() : "unknown";
-                       CodeSigning::OSXCode *authCreatorCode = auth.creatorCode();
-                       string authCreatorName = authCreatorCode ? authCreatorCode->canonicalPath() : "unknown";
-                       
-                       if (result == errAuthorizationSuccess)
-                               Syslog::info("Succeeded authorizing right %s by process %s for authorization created by %s.", (*it)->name(), processName.c_str(), authCreatorName.c_str());
-                       else if (result == errAuthorizationDenied)
-                               Syslog::notice("Failed to authorize right %s by process %s for authorization created by %s.", (*it)->name(), processName.c_str(), authCreatorName.c_str());
-               }
-               
-               if (result == errAuthorizationSuccess)
-                       outRights.insert(*it);
-               else if (result == errAuthorizationDenied || result == errAuthorizationInteractionNotAllowed)
-               {
-                       // add creator pid to authorization token
-                       if (!(flags & kAuthorizationFlagPartialRights))
-                       {
-                               status = result;
-                               break;
+                       StLock<Mutex> _(Server::process());
+               if (SecCodeRef code = Server::process().currentGuest()) {
+                   CFRef<CFURLRef> 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;
+        } 
+        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);
@@ -287,12 +330,6 @@ Engine::getRule(string &inRightName, CFDictionaryRef *outRuleDefinition)
 OSStatus 
 Engine::setRule(const char *inRightName, CFDictionaryRef inRuleDefinition, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth)
 {
-       // Get current time of day.
-       CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
-
-       // Update rules from database if needed
-       mAuthdb.sync(now);
-
        // Validate rule by constructing it from the passed dictionary
        if (!mAuthdb.validateRule(inRightName, inRuleDefinition))
                return errAuthorizationDenied; // @@@ separate error for this?