]> git.saurik.com Git - apple/securityd.git/blob - src/authhost.cpp
securityd-36975.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
29 #include <grp.h>
30 #include <pwd.h>
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
33 #include <syslog.h>
34 #include <pthread.h>
35
36 static pthread_once_t agent_cred_init = PTHREAD_ONCE_INIT;
37 static gid_t agent_gid = 92;
38 static uid_t agent_uid = 92;
39
40 void initialize_agent_creds()
41 {
42 struct passwd *agentUser = getpwnam("securityagent");
43 if (agentUser)
44 {
45 agent_uid = agentUser->pw_uid;
46 agent_gid = agentUser->pw_gid;
47 endpwent();
48 }
49 }
50
51 AuthHostInstance::AuthHostInstance(Session &session, AuthHostType host) :
52 mHostType(host)
53 {
54 secdebug("authhost", "authhost born (%p)", this);
55 referent(session);
56 session.addReference(*this);
57 if (host == securityAgent)
58 pthread_once(&agent_cred_init, initialize_agent_creds);
59 }
60
61 AuthHostInstance::~AuthHostInstance()
62 {
63 secdebug("authhost", "authhost died (%p)", this);
64 }
65
66 Session &AuthHostInstance::session() const
67 {
68 return referent<Session>();
69 }
70
71 void
72 AuthHostInstance::childAction()
73 {
74 // Setup the environment for the SecurityAgent
75 unsetenv("USER");
76 unsetenv("LOGNAME");
77 unsetenv("HOME");
78
79 // close down any files that might have been open at this point
80 int maxDescriptors = getdtablesize ();
81 int i;
82
83 int devnull = open(_PATH_DEVNULL, O_RDWR, 0);
84 if (devnull >= 0) for (i = 0; i < 3; ++i)
85 {
86 dup2(devnull, i);
87 }
88
89 for (i = 3; i < maxDescriptors; ++i)
90 {
91 close (i);
92 }
93
94 // construct path to SecurityAgent
95 char agentExecutable[PATH_MAX + 1];
96 const char *path = getenv("SECURITYAGENT");
97 if (!path)
98 path = "/System/Library/CoreServices/SecurityAgent.app";
99
100 if ((mHostType == userAuthHost) || (mHostType == privilegedAuthHost))
101 {
102 snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/Resources/authorizationhost", path);
103 secdebug("AuthHostInstance", "execl(%s)", agentExecutable);
104 execl(agentExecutable, agentExecutable, NULL);
105 }
106 else
107 {
108 snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/MacOS/SecurityAgent", path);
109
110 pid_t pid = getpid();
111 if ((pid <= 0) ||
112 sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &pid, sizeof(pid)))
113 syslog(LOG_ERR, "Failed to set vfs.generic.noremotehang for pid(%d)", pid);
114
115 setgroups(1, &agent_gid);
116 setgid(agent_gid);
117 setuid(agent_uid);
118
119 CFRef<CFDataRef> userPrefs(session().copyUserPrefs());
120
121 FILE *mbox = tmpfile();
122
123 if (userPrefs && mbox)
124 {
125 if (fwrite(CFDataGetBytePtr(userPrefs), CFDataGetLength(userPrefs), 1, mbox) != 1)
126 fclose(mbox);
127 else
128 {
129 char mboxFdString[20];
130 fflush(mbox);
131 if ((int)sizeof(mboxFdString) > snprintf(mboxFdString, sizeof(mboxFdString), "%d", fileno(mbox)))
132 setenv("SECURITYAGENT_USERPREFS_FD", mboxFdString, 1);
133 }
134 }
135
136 secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable, agent_uid, agent_gid);
137 execl(agentExecutable, agentExecutable, NULL);
138 }
139
140 secdebug("AuthHostInstance", "execl failed, errno=%d", errno);
141 // Unconditional suicide follows.
142 // See comments below on why we can't use abort()
143 #if 1
144 _exit(1);
145 #else
146 // NOTE: OS X abort() is implemented as kill(getuid()), which fails
147 // for a setuid-root process that has setuid'd. Go back to root to die...
148 setuid(0);
149 abort();
150 #endif
151 }
152
153 Port
154 AuthHostInstance::activate()
155 {
156 StLock<Mutex> _(*this);
157 if (state() != alive)
158 {
159 if ((mHostType == securityAgent) &&
160 !(session().attributes() & sessionHasGraphicAccess))
161 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
162
163 Security::MachPlusPlus::StBootstrap bootSaver(session().bootstrapPort());
164
165 fork();
166 switch (ServerChild::state()) {
167 case Child::alive:
168 secdebug("AuthHostInstance", "%p (pid %d) has launched", this, pid());
169 break;
170 case Child::dead:
171 secdebug("AuthHostInstance", "%p (pid %d) failed on startup", this, pid());
172 break;
173 default:
174 assert(false);
175 }
176 }
177
178 if (!ready())
179 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
180
181 return servicePort();
182 }