2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
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;
40 void initialize_agent_creds()
42 struct passwd
*agentUser
= getpwnam("securityagent");
45 agent_uid
= agentUser
->pw_uid
;
46 agent_gid
= agentUser
->pw_gid
;
51 AuthHostInstance::AuthHostInstance(Session
&session
, AuthHostType host
) :
54 secdebug("authhost", "authhost born (%p)", this);
56 session
.addReference(*this);
57 if (host
== securityAgent
)
58 pthread_once(&agent_cred_init
, initialize_agent_creds
);
61 AuthHostInstance::~AuthHostInstance()
63 secdebug("authhost", "authhost died (%p)", this);
66 Session
&AuthHostInstance::session() const
68 return referent
<Session
>();
72 AuthHostInstance::childAction()
74 // Setup the environment for the SecurityAgent
79 // close down any files that might have been open at this point
80 int maxDescriptors
= getdtablesize ();
83 int devnull
= open(_PATH_DEVNULL
, O_RDWR
, 0);
84 if (devnull
>= 0) for (i
= 0; i
< 3; ++i
)
89 for (i
= 3; i
< maxDescriptors
; ++i
)
94 // construct path to SecurityAgent
95 char agentExecutable
[PATH_MAX
+ 1];
96 const char *path
= getenv("SECURITYAGENT");
98 path
= "/System/Library/CoreServices/SecurityAgent.app";
100 if ((mHostType
== userAuthHost
) || (mHostType
== privilegedAuthHost
))
102 snprintf(agentExecutable
, sizeof(agentExecutable
), "%s/Contents/Resources/authorizationhost", path
);
103 secdebug("AuthHostInstance", "execl(%s)", agentExecutable
);
104 execl(agentExecutable
, agentExecutable
, NULL
);
108 snprintf(agentExecutable
, sizeof(agentExecutable
), "%s/Contents/MacOS/SecurityAgent", path
);
110 pid_t pid
= getpid();
112 sysctlbyname("vfs.generic.noremotehang", NULL
, NULL
, &pid
, sizeof(pid
)))
113 syslog(LOG_ERR
, "Failed to set vfs.generic.noremotehang for pid(%d)", pid
);
115 setgroups(1, &agent_gid
);
119 CFRef
<CFDataRef
> userPrefs(session().copyUserPrefs());
121 FILE *mbox
= tmpfile();
123 if (userPrefs
&& mbox
)
125 if (fwrite(CFDataGetBytePtr(userPrefs
), CFDataGetLength(userPrefs
), 1, mbox
) != 1)
129 char mboxFdString
[20];
131 if ((int)sizeof(mboxFdString
) > snprintf(mboxFdString
, sizeof(mboxFdString
), "%d", fileno(mbox
)))
132 setenv("SECURITYAGENT_USERPREFS_FD", mboxFdString
, 1);
136 secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable
, agent_uid
, agent_gid
);
137 execl(agentExecutable
, agentExecutable
, NULL
);
140 secdebug("AuthHostInstance", "execl failed, errno=%d", errno
);
141 // Unconditional suicide follows.
142 // See comments below on why we can't use abort()
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...
154 AuthHostInstance::activate()
156 StLock
<Mutex
> _(*this);
157 if (state() != alive
)
159 if ((mHostType
== securityAgent
) &&
160 !(session().attributes() & sessionHasGraphicAccess
))
161 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION
);
163 Security::MachPlusPlus::StBootstrap
bootSaver(session().bootstrapPort());
166 switch (ServerChild::state()) {
168 secdebug("AuthHostInstance", "%p (pid %d) has launched", this, pid());
171 secdebug("AuthHostInstance", "%p (pid %d) failed on startup", this, pid());
179 CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION
);
181 return servicePort();