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