X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/securityd/src/authhost.cpp diff --git a/securityd/src/authhost.cpp b/securityd/src/authhost.cpp new file mode 100644 index 00000000..460a26bc --- /dev/null +++ b/securityd/src/authhost.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2000-2007,2009-2010,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 +#include +#include "authhost.h" +#include "server.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static pthread_once_t agent_cred_init = PTHREAD_ONCE_INIT; +static gid_t agent_gid = 92; +static uid_t agent_uid = 92; + +void initialize_agent_creds() +{ + struct passwd *agentUser = getpwnam("securityagent"); + if (agentUser) + { + agent_uid = agentUser->pw_uid; + agent_gid = agentUser->pw_gid; + endpwent(); + } +} + +AuthHostInstance::AuthHostInstance(Session &session, AuthHostType host) : + mHostType(host) +{ + secdebug("authhost", "authhost born (%p)", this); + referent(session); + session.addReference(*this); + if (host == securityAgent) + pthread_once(&agent_cred_init, initialize_agent_creds); +} + +AuthHostInstance::~AuthHostInstance() +{ + secdebug("authhost", "authhost died (%p)", this); +} + +Session &AuthHostInstance::session() const +{ + return referent(); +} + +bool AuthHostInstance::inDarkWake() +{ + return session().server().inDarkWake(); +} + +void +AuthHostInstance::childAction() +{ + // switch to desired session + CommonCriteria::AuditInfo &audit = this->session().auditInfo(); + audit.get(audit.sessionId()); + audit.set(); + //this->session().auditInfo().set(); + + // Setup the environment for the SecurityAgent + unsetenv("USER"); + unsetenv("LOGNAME"); + unsetenv("HOME"); + + // close down any files that might have been open at this point + int maxDescriptors = getdtablesize (); + int i; + + int devnull = open(_PATH_DEVNULL, O_RDWR, 0); + if (devnull >= 0) for (i = 0; i < 3; ++i) + { + dup2(devnull, i); + } + + for (i = 3; i < maxDescriptors; ++i) + { + close (i); + } + + // construct path to SecurityAgent + char agentExecutable[PATH_MAX + 1]; + const char *path = getenv("SECURITYAGENT"); + if (!path) + path = "/System/Library/CoreServices/SecurityAgent.app"; + secdebug("adhoc", "hostType = %d", mHostType); + + if ((mHostType == userAuthHost) || (mHostType == privilegedAuthHost)) + { + snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/Resources/authorizationhost", path); + secdebug("AuthHostInstance", "execl(%s)", agentExecutable); + execl(agentExecutable, agentExecutable, NULL); + } + else + { + snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/MacOS/SecurityAgent", path); + + pid_t pid = getpid(); + if ((pid <= 0) || + sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &pid, sizeof(pid))) + syslog(LOG_ERR, "Failed to set vfs.generic.noremotehang for pid(%d)", pid); + + setgroups(1, &agent_gid); + setgid(agent_gid); + setuid(agent_uid); + + secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable, agent_uid, agent_gid); + execl(agentExecutable, agentExecutable, NULL); + } + + secdebug("AuthHostInstance", "execl failed, errno=%d", errno); + // Unconditional suicide follows. + _exit(1); +} + +// @@@ these definitions and the logic in lookup() should move into +// libsecurity_agent +#define SECURITYAGENT_BOOTSTRAP_NAME_BASE "com.apple.SecurityAgent" +#define AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE "com.apple.authorizationhost" + +mach_port_t +AuthHostInstance::lookup(SessionId jobId) +{ + StLock _(*this); + + mach_port_t pluginhostPort = MACH_PORT_NULL; + kern_return_t result; + const char *serviceName; + /* PR-7483709 const */ uuid_t instanceId = UUID_INITIALIZER_FROM_SESSIONID(jobId); + uuid_string_t s; + + if ((mHostType == securityAgent)) { + if (!(session().attributes() & sessionHasGraphicAccess)) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + if (inDarkWake()) + CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE); + } + + if (mHostType == securityAgent) + serviceName = SECURITYAGENT_BOOTSTRAP_NAME_BASE; + else + serviceName = AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE; + + secdebug("AuthHostInstance", "looking up %s instance %s", serviceName, + uuid_to_string(instanceId, s)); // XXX/gh debugging + if ((result = bootstrap_look_up3(bootstrap_port, serviceName, + &pluginhostPort, 0, instanceId, BOOTSTRAP_SPECIFIC_INSTANCE)) != KERN_SUCCESS) { + + Syslog::error("error %d looking up %s instance %s", result, serviceName, + uuid_to_string(instanceId, s)); + } else + secdebug("AuthHostInstance", "port = %x", (unsigned int)pluginhostPort); + + return pluginhostPort; +} + +Port AuthHostInstance::activate() +{ + StLock _(*this); + if (state() != alive) + { + if ((mHostType == securityAgent)) { + if (!(session().attributes() & sessionHasGraphicAccess)) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + if (inDarkWake()) + CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE); + } + + fork(); + switch (ServerChild::state()) { + case Child::alive: + secdebug("AuthHostInstance", "%p (pid %d) has launched", this, pid()); + break; + case Child::dead: + secdebug("AuthHostInstance", "%p (pid %d) failed on startup", this, pid()); + break; + default: + assert(false); + } + } + + if (!ready()) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + + return servicePort(); +}