#ifndef _H_SERVER
#define _H_SERVER
#include "structure.h"
#include <security_utilities/machserver.h>
#include <security_utilities/powerwatch.h>
#include <security_utilities/ccaudit.h>
#include <security_cdsa_client/cssmclient.h>
#include <security_cdsa_client/cspclient.h>
#include <security_utilities/devrandom.h>
#include <security_cdsa_utilities/uniformrandom.h>
#include <security_utilities/vproc++.h>
#include "codesigdb.h"
#include "connection.h"
#include "key.h"
#include "database.h"
#include "localdatabase.h"
#include "kcdatabase.h"
#include <map>
class Server : public PerGlobal,
public MachPlusPlus::MachServer,
public UniformRandomBlobs<DevRandomGenerator> {
public:
Server(CodeSignatures &signatures, const char *bootstrapName);
~Server();
void run();
static Server &active() { return safer_cast<Server &>(MachServer::active()); }
static const char *bootstrapName() { return active().mBootstrapName.c_str(); }
static unsigned int verbosity() { return active().mVerbosity; }
static Connection &connection(mach_port_t replyPort, audit_token_t &auditToken); static Connection &connection(bool tolerant = false); static void requestComplete(CSSM_RETURN &rcode);
static Process &process();
static Session &session();
static RefPointer<Key> key(KeyHandle key);
static RefPointer<Key> optionalKey(KeyHandle k) { return (k == noKey) ? NULL : key(k); }
static RefPointer<Database> database(DbHandle db);
static RefPointer<KeychainDatabase> keychain(DbHandle db);
static RefPointer<Database> optionalDatabase(DbHandle db, bool persistent = true);
static AclSource &aclBearer(AclKind kind, U32HandleObject::Handle handle);
template <class ProcessBearer>
static RefPointer<ProcessBearer> find(uint32_t handle, CSSM_RETURN notFoundError)
{
RefPointer<ProcessBearer> object =
U32HandleObject::findRef<ProcessBearer>(handle, notFoundError);
if (object->process() != Server::process())
CssmError::throwMe(notFoundError);
return object;
}
static CodeSignatures &codeSignatures() { return active().mCodeSignatures; }
static CssmClient::CSP &csp() { return active().mCSP; }
public:
void loadCssm(bool mdsIsInstalled);
public:
enum ConnectLevel {
connectNewProcess,
connectNewThread
};
void setupConnection(ConnectLevel type, Port replyPort, Port taskPort, const audit_token_t &auditToken,
const ClientSetupInfo *info = NULL);
void endConnection(Port replyPort);
static void releaseWhenDone(Allocator &alloc, void *memory)
{ MachServer::active().releaseWhenDone(alloc, memory); }
static void releaseWhenDone(void *memory)
{ releaseWhenDone(Allocator::standard(), memory); }
protected:
boolean_t handle(mach_msg_header_t *in, mach_msg_header_t *out);
void notifyDeadName(Port port);
void notifyNoSenders(Port port, mach_port_mscount_t);
void threadLimitReached(UInt32 count);
void eventDone();
private:
class SleepWatcher : public MachPlusPlus::PortPowerWatcher {
public:
void systemWillSleep();
void systemIsWaking();
void systemWillPowerOn();
void add(PowerWatcher *client);
void remove(PowerWatcher *client);
private:
set<PowerWatcher *> mPowerClients;
};
SleepWatcher sleepWatcher;
public:
using MachServer::add;
using MachServer::remove;
void add(MachPlusPlus::PowerWatcher *client) { StLock<Mutex> _(*this); sleepWatcher.add(client); }
void remove(MachPlusPlus::PowerWatcher *client) { StLock<Mutex> _(*this); sleepWatcher.remove(client); }
public:
Process *findPid(pid_t pid) const;
void verbosity(unsigned int v) { mVerbosity = v; }
void waitForClients(bool waiting); void beginShutdown(); bool shuttingDown() const { return mShuttingDown; }
void shutdownSnitch(); bool inDarkWake();
void associateThread() { perThread().server = this; }
private:
std::string mBootstrapName;
PortMap<Connection> mConnections;
typedef std::map<pid_t, Process *> PidMap;
PortMap<Process> mProcesses; PidMap mPids;
ThreadNexus<RefPointer<Connection> > mCurrentConnection;
CssmClient::Cssm mCssm; CssmClient::Module mCSPModule; CssmClient::CSP mCSP;
CodeSignatures &mCodeSignatures;
unsigned int mVerbosity;
bool mWaitForClients;
bool mShuttingDown;
};
class LongtermStLock : public StLock<Mutex> {
public:
LongtermStLock(Mutex &lck);
};
kern_return_t self_server_handleSignal(mach_port_t sport, mach_port_t taskPort, int sig);
kern_return_t self_server_handleSession(mach_port_t sport, mach_port_t taskPort, uint32_t event, uint64_t ident);
#endif //_H_SERVER