]> git.saurik.com Git - apple/securityd.git/blob - src/authhost.cpp
securityd-55126.5.tar.gz
[apple/securityd.git] / src / authhost.cpp
1 /*
2 * Copyright (c) 2000-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
24 #include <paths.h>
25 #include <fcntl.h>
26 #include "authhost.h"
27 #include "server.h"
28 #include <security_utilities/logging.h>
29 #include <security_utilities/debugging.h>
30 #include <security_agent_client/sa_request.h>
31 #include <security_agent_client/utils.h>
32 #include <bsm/audit.h>
33 #include <bootstrap_priv.h>
34
35 #include <grp.h>
36 #include <pwd.h>
37 #include <sys/types.h>
38 #include <sys/sysctl.h>
39 #include <syslog.h>
40 #include <pthread.h>
41
42 static pthread_once_t agent_cred_init = PTHREAD_ONCE_INIT;
43 static gid_t agent_gid = 92;
44 static uid_t agent_uid = 92;
45
46 void initialize_agent_creds()
47 {
48 struct passwd *agentUser = getpwnam("securityagent");
49 if (agentUser)
50 {
51 agent_uid = agentUser->pw_uid;
52 agent_gid = agentUser->pw_gid;
53 endpwent();
54 }
55 }
56
57 AuthHostInstance::AuthHostInstance(Session &session, AuthHostType host) :
58 mHostType(host)
59 {
60 secdebug("authhost", "authhost born (%p)", this);
61 referent(session);
62 session.addReference(*this);
63 if (host == securityAgent)
64 pthread_once(&agent_cred_init, initialize_agent_creds);
65 }
66
67 AuthHostInstance::~AuthHostInstance()
68 {
69 secdebug("authhost", "authhost died (%p)", this);
70 }
71
72 Session &AuthHostInstance::session() const
73 {
74 return referent<Session>();
75 }
76
77 bool AuthHostInstance::inDarkWake()
78 {
79 return this->session().server().inDarkWake();
80 }
81
82 void
83 AuthHostInstance::childAction()
84 {
85 // switch to desired session
86 CommonCriteria::AuditInfo &audit = this->session().auditInfo();
87 audit.get(audit.sessionId());
88 audit.set();
89 //this->session().auditInfo().set();
90
91 // Setup the environment for the SecurityAgent
92 unsetenv("USER");
93 unsetenv("LOGNAME");
94 unsetenv("HOME");
95
96 // close down any files that might have been open at this point
97 int maxDescriptors = getdtablesize ();
98 int i;
99
100 int devnull = open(_PATH_DEVNULL, O_RDWR, 0);
101 if (devnull >= 0) for (i = 0; i < 3; ++i)
102 {
103 dup2(devnull, i);
104 }
105
106 for (i = 3; i < maxDescriptors; ++i)
107 {
108 close (i);
109 }
110
111 // construct path to SecurityAgent
112 char agentExecutable[PATH_MAX + 1];
113 const char *path = getenv("SECURITYAGENT");
114 if (!path)
115 path = "/System/Library/CoreServices/SecurityAgent.app";
116 secdebug("adhoc", "hostType = %d", mHostType);
117
118 if ((mHostType == userAuthHost) || (mHostType == privilegedAuthHost))
119 {
120 snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/Resources/authorizationhost", path);
121 secdebug("AuthHostInstance", "execl(%s)", agentExecutable);
122 execl(agentExecutable, agentExecutable, NULL);
123 }
124 else
125 {
126 snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/MacOS/SecurityAgent", path);
127
128 pid_t pid = getpid();
129 if ((pid <= 0) ||
130 sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &pid, sizeof(pid)))
131 syslog(LOG_ERR, "Failed to set vfs.generic.noremotehang for pid(%d)", pid);
132
133 setgroups(1, &agent_gid);
134 setgid(agent_gid);
135 setuid(agent_uid);
136
137 secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable, agent_uid, agent_gid);
138 execl(agentExecutable, agentExecutable, NULL);
139 }
140
141 secdebug("AuthHostInstance", "execl failed, errno=%d", errno);
142 // Unconditional suicide follows.
143 _exit(1);
144 }
145
146 // @@@ these definitions and the logic in lookup() should move into
147 // libsecurity_agent
148 #define SECURITYAGENT_BOOTSTRAP_NAME_BASE "com.apple.SecurityAgent"
149 #define AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE "com.apple.authorizationhost"
150
151 mach_port_t
152 AuthHostInstance::lookup(SessionId jobId)
153 {
154 StLock<Mutex> _(*this);
155
156 mach_port_t pluginhostPort = MACH_PORT_NULL;
157 kern_return_t result;
158 const char *serviceName;
159 /* PR-7483709 const */ uuid_t instanceId = UUID_INITIALIZER_FROM_SESSIONID(jobId);
160 uuid_string_t s;
161
162 if ((mHostType == securityAgent)) {
163 if (!(session().attributes() & sessionHasGraphicAccess))
164 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
165 if (inDarkWake())
166 CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE);
167 }
168
169 if (mHostType == securityAgent)
170 serviceName = SECURITYAGENT_BOOTSTRAP_NAME_BASE;
171 else
172 serviceName = AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE;
173
174 secdebug("AuthHostInstance", "looking up %s instance %s", serviceName,
175 uuid_to_string(instanceId, s)); // XXX/gh debugging
176 if ((result = bootstrap_look_up3(bootstrap_port, serviceName,
177 &pluginhostPort, 0, instanceId, BOOTSTRAP_SPECIFIC_INSTANCE)) != KERN_SUCCESS) {
178
179 Syslog::error("error %d looking up %s instance %s", result, serviceName,
180 uuid_to_string(instanceId, s));
181 } else
182 secdebug("AuthHostInstance", "port = %x", (unsigned int)pluginhostPort);
183
184 return pluginhostPort;
185 }
186
187 Port AuthHostInstance::activate()
188 {
189 StLock<Mutex> _(*this);
190 if (state() != alive)
191 {
192 if ((mHostType == securityAgent)) {
193 if (!(session().attributes() & sessionHasGraphicAccess))
194 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
195 if (inDarkWake())
196 CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE);
197 }
198
199 fork();
200 switch (ServerChild::state()) {
201 case Child::alive:
202 secdebug("AuthHostInstance", "%p (pid %d) has launched", this, pid());
203 break;
204 case Child::dead:
205 secdebug("AuthHostInstance", "%p (pid %d) failed on startup", this, pid());
206 break;
207 default:
208 assert(false);
209 }
210 }
211
212 if (!ready())
213 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
214
215 return servicePort();
216 }