#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>
#include <security_cdsa_client/osxsigning.h>
namespace SecurityAgent {
#endif
#define kMaximumAuthorizationTries 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 };
typedef enum {
tool = 'TOOL',
bundle = 'BNDL',
unknown = 'UNKN'
} RequestorType;
#if defined(__cplusplus)
using MachPlusPlus::Port;
using MachPlusPlus::Bootstrap;
using MachPlusPlus::ReceivePort;
using MachPlusPlus::Message;
using Authorization::AuthItemSet;
class Clients;
class Client
{
friend class Clients;
enum MessageType { requestInterruptMessage, didDeactivateMessage, reportErrorMessage };
public:
Client();
Client(uid_t clientUID, Bootstrap clientBootstrap, const char *name);
virtual ~Client();
static AuthItemSet clientHints(CodeSigning::OSXCode *clientCode, pid_t clientPid, uid_t clientUid);
protected:
void establishServer();
public:
bool isActive() { return mActive; }
OSStatus activate();
OSStatus create(const char *pluginId, const char *mechanismId, const SessionId inSessionId);
OSStatus invoke(const Authorization::AuthValueVector& inArguments, const Authorization::AuthItemSet& inHints, const Authorization::AuthItemSet& inContext);
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; }
protected:
void setMessageType(const MessageType inMessageType);
void setStagePort(const mach_port_t inStagePort) { mStagePort = Port(inStagePort); }
protected:
void setup();
void teardown() throw();
Port mServerPort;
Port mStagePort;
Port mClientPort;
bool mActive;
MessageType mMessageType;
OSStatus mErrorState;
AuthorizationResult mResult;
AuthItemSet mHints;
AuthItemSet mContext;
enum PluginState {
init,
created,
current,
deactivating,
active,
interrupting,
dead
};
PluginState mState;
void setState(PluginState mState);
int state();
public:
mach_port_t instance() const { return mClientPort; }
bool operator < (const Client &other) const { return this->instance() < other.instance(); }
AuthItemSet &hints() { return mHints; }
AuthItemSet &context() { return mContext; }
public:
void check(mach_msg_return_t returnCode);
void checkResult();
private:
uid_t mDesktopUid;
bool mKeepAlive;
string mAgentName;
Bootstrap mClientBootstrap;
};
class Clients
{
friend class Client;
protected:
set<Client*> mClients;
public:
Clients() {}
void create(); void insert(Client *agent) { StLock<Mutex> _(mLock); mClients.insert(agent); }
void remove(Client *agent) { StLock<Mutex> _(mLock); mClients.erase(agent); }
Client &find(const mach_port_t instance) const;
bool compare(const Client * client, mach_port_t instance);
mutable Mutex mLock;
static ModuleNexus<Clients> gClients;
};
}
#endif
#endif