#include "sstransit.h"
#include <servers/netname.h>
#include <security_utilities/debugging.h>
using MachPlusPlus::check;
using MachPlusPlus::Bootstrap;
namespace Security {
namespace SecurityServer {
UnixPlusPlus::StaticForkMonitor ClientSession::mHasForked;
ModuleNexus<ClientSession::Global> ClientSession::mGlobal;
bool ClientSession::mSetupSession;
const char *ClientSession::mContactName;
SecGuestRef ClientSession::mDedicatedGuest = kSecNoGuest;
ClientSession::ClientSession(Allocator &std, Allocator &rtn)
: ClientCommon(std, rtn), mCallback(NULL), mCallbackContext(NULL)
{ }
ClientSession::~ClientSession()
{ }
void
ClientSession::registerForAclEdits(DidChangeKeyAclCallback *callback, void *context)
{
mCallback = callback;
mCallbackContext = context;
}
void ClientSession::activate()
{
if (mHasForked()) {
secdebug("SSclnt", "process has forked (now pid=%d) - resetting connection object", getpid());
mGlobal.reset();
}
Global &global = mGlobal();
Thread &thread = global.thread();
if (!thread) {
IPCN(ucsp_client_setupThread(UCSP_ARGS, mach_task_self()));
thread.registered = true;
secdebug("SSclnt", "Thread registered with %s", mContactName);
}
if (thread.currentGuest != thread.lastGuest) {
IPCN(ucsp_client_setGuest(UCSP_ARGS, thread.currentGuest, kSecCSDefaultFlags));
thread.lastGuest = thread.currentGuest;
secdebug("SSclnt", "switched guest state to 0x%x", thread.currentGuest);
}
}
void ClientSession::contactName(const char *name)
{
mContactName = name;
}
const char *ClientSession::contactName() const
{
return mContactName;
}
ClientSession::Global::Global()
{
serverPort = findSecurityd();
string extForm;
try {
myself = OSXCode::main();
extForm = myself->encode();
secdebug("SSclnt", "my OSXCode extForm=%s", extForm.c_str());
} catch (...) {
secdebug("SSclnt", "failed to obtain my own OSXCode");
}
ClientSetupInfo info = { 0x1234, SSPROTOVERSION };
Thread &thread = this->thread();
if (mSetupSession) {
secdebug("SSclnt", "sending session setup request");
mSetupSession = false; IPCN(ucsp_client_setupNew(serverPort, thread.replyPort, &securitydCreds, &rcode,
mach_task_self(), info, extForm.c_str(), &serverPort.port()));
secdebug("SSclnt", "new session server port is %d", serverPort.port());
} else {
IPCN(ucsp_client_setup(serverPort, thread.replyPort, &securitydCreds, &rcode,
mach_task_self(), info, extForm.c_str()));
}
thread.registered = true; IFDEBUG(serverPort.requestNotify(thread.replyPort));
secdebug("SSclnt", "contact with %s established", mContactName);
}
void ClientSession::reset()
{
secdebug("SSclnt", "resetting client state (OUCH)");
mGlobal.reset();
}
Port ClientSession::findSecurityd()
{
if (!mContactName)
{
mContactName = getenv(SECURITYSERVER_BOOTSTRAP_ENV);
if (!mContactName)
mContactName = SECURITYSERVER_BOOTSTRAP_NAME;
}
secdebug("SSclnt", "Locating %s", mContactName);
Port serverPort = Bootstrap().lookup(mContactName);
secdebug("SSclnt", "contacting %s at port %d (version %d)",
mContactName, serverPort.port(), SSPROTOVERSION);
return serverPort;
}
void ClientSession::childCheckIn(Port serverPort, Port taskPort)
{
check(ucsp_client_childCheckIn(findSecurityd(), serverPort, taskPort));
}
void ClientSession::notifyAclChange(KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag)
{
if (mCallback) {
secdebug("keyacl", "ACL change key %lu operation %u", key, tag);
mCallback(mCallbackContext, *this, key, tag);
} else
secdebug("keyacl", "dropped ACL change notice for key %lu operation %u",
key, tag);
}
} }