#ifndef _H_AGENTCLIENT
#define _H_AGENTCLIENT
#include <Security/Authorization.h>
#include <Security/AuthorizationPlugin.h>
#include <Security/AuthorizationTags.h>
#include <Security/AuthorizationTagsPriv.h>
#include <security_agent_client/sa_types.h>
#if defined(__cplusplus)
#include <string>
#include <security_utilities/mach++.h>
#include <security_cdsa_utilities/AuthorizationData.h>
namespace SecurityAgent {
#endif
#define kMaximumAuthorizationTries 10000
#define kAuthorizationTriesBeforeHint 3
#define maxPassphraseLength 1024
enum Reason {
noReason = 0, unknownReason,
newDatabase = 11, changePassphrase,
invalidPassphrase = 21,
passphraseIsNull = 31, passphraseTooSimple, passphraseRepeated, passphraseUnacceptable, oldPassphraseWrong,
userNotInGroup = 41, unacceptableUser,
tooManyTries = 61, noLongerNeeded, keychainAddFailed, generalErrorCancel, resettingPassword,
worldChanged = 101
};
typedef enum {
tool = 'TOOL',
bundle = 'BNDL',
unknown = 'UNKN'
} RequestorType;
#if defined(__cplusplus)
using MachPlusPlus::Port;
using MachPlusPlus::PortSet;
using MachPlusPlus::Bootstrap;
using MachPlusPlus::ReceivePort;
using MachPlusPlus::Message;
using Authorization::AuthItemSet;
using Authorization::AuthValueVector;
class Clients;
class Client
{
friend class Clients;
enum MessageType { requestInterruptMessage, didDeactivateMessage, reportErrorMessage };
public:
Client();
virtual ~Client();
static AuthItemSet clientHints(SecurityAgent::RequestorType type, std::string &path, pid_t clientPid, uid_t clientUid);
static OSStatus startTransaction(Port serverPort);
static OSStatus endTransaction(Port serverPort);
protected:
void establishServer();
public:
void activate(Port serverPort);
OSStatus contact(mach_port_t jobId, Bootstrap processBootstrap, mach_port_t userPrefs);
OSStatus create(const char *pluginId, const char *mechanismId, const SessionId inSessionId);
void setArguments(const Authorization::AuthValueVector& inArguments) { mArguments = inArguments; }
void setInput(const Authorization::AuthItemSet& inHints, const Authorization::AuthItemSet& inContext) { mInHints = inHints; mInContext = inContext; }
OSStatus invoke();
OSStatus deactivate();
OSStatus destroy();
OSStatus terminate();
void receive();
void didCreate(const mach_port_t inStagePort);
void setResult(const AuthorizationResult inResult, const AuthorizationItemSet *inHints, const AuthorizationItemSet *inContext);
void requestInterrupt(); void didDeactivate();
void setError(const OSStatus inMechanismError); OSStatus getError();
AuthorizationResult result() { return mResult; }
typedef enum _PluginState {
init,
created,
current,
deactivating,
active,
interrupting,
dead
} PluginState;
PluginState state() { return mState; }
protected:
void setMessageType(const MessageType inMessageType);
void setStagePort(const mach_port_t inStagePort);
protected:
void setup();
void teardown() throw();
Port mServerPort;
Port mStagePort;
Port mClientPort;
MessageType mMessageType;
OSStatus mErrorState;
AuthorizationResult mResult;
AuthValueVector mArguments;
AuthItemSet mInHints;
AuthItemSet mInContext;
AuthItemSet mOutHints;
AuthItemSet mOutContext;
PluginState mState;
void setState(PluginState mState);
bool mTerminateOnSleep;
public:
mach_port_t instance() const { return mClientPort; }
bool operator < (const Client &other) const { return this->instance() < other.instance(); }
AuthItemSet &inHints() { return mInHints; }
AuthItemSet &inContext() { return mInContext; }
AuthItemSet &outHints() { return mOutHints; }
AuthItemSet &outContext() { return mOutContext; }
void setTerminateOnSleep(bool terminateOnSleep) {mTerminateOnSleep = terminateOnSleep;}
bool getTerminateOnSleep() {return mTerminateOnSleep;}
public:
void check(mach_msg_return_t returnCode);
void checkResult();
};
class Clients
{
friend class Client;
protected:
set<Client*> mClients;
PortSet mClientPortSet;
public:
Clients() {}
void create(); void insert(Client *agent) { StLock<Mutex> _(mLock); mClients.insert(agent); mClientPortSet += agent->instance(); }
void remove(Client *agent) { StLock<Mutex> _(mLock); mClientPortSet -= agent->instance(); mClients.erase(agent); }
Client &find(const mach_port_t instance) const;
bool receive();
bool compare(const Client * client, mach_port_t instance);
mutable Mutex mLock;
static ThreadNexus<Clients> gClients;
static ModuleNexus<RecursiveMutex> gAllClientsMutex;
static ModuleNexus<set<Client*> > allClients;
static void killAllClients();
};
}
#endif
#endif