1/*
2 *  agentclient.h
3 *  SecurityAgent
4 *
5 *  Copyright (c) 2002,2008 Apple Inc.. All rights reserved.
6 *
7 */
8
9#ifndef _H_AGENTCLIENT
10#define _H_AGENTCLIENT
11
12#include <Security/Authorization.h>
13#include <Security/AuthorizationPlugin.h>
14#include <Security/AuthorizationTags.h>
15#include <Security/AuthorizationTagsPriv.h>
16
17#include <security_agent_client/sa_types.h>
18
19#if defined(__cplusplus)
20
21#include <string>
22#include <security_utilities/mach++.h>
23#include <security_cdsa_utilities/AuthorizationData.h>
24
25namespace SecurityAgent {
26#endif /* __cplusplus__ */
27
28// Manimum number of failed authentications before
29// SecurityAgent dialog is killed.
30#define kMaximumAuthorizationTries 10000
31
32// Number of failed authentications before a password
33// hint is displayed.
34#define kAuthorizationTriesBeforeHint 3
35
36#define maxPassphraseLength 1024
37
38//
39// Unified reason codes transmitted to SecurityAgent (and internationalized there)
40//
41enum Reason {
42    noReason = 0,                   // no reason (not used, used as a NULL)
43    unknownReason,                  // something else (catch-all internal error)
44
45    // reasons for asking for a new passphrase
46    newDatabase = 11,               // need passphrase for a new database
47    changePassphrase,               // changing passphrase for existing database
48
49    // reasons for retrying an unlock query
50    invalidPassphrase = 21,         // passphrase was wrong
51
52    // reasons for retrying a new passphrase query
53    passphraseIsNull = 31,          // empty passphrase
54    passphraseTooSimple,            // passphrase is not complex enough
55    passphraseRepeated,             // passphrase was used before (must use new one)
56    passphraseUnacceptable,         // passphrase unacceptable for some other reason
57    oldPassphraseWrong,             // the old passphrase given is wrong
58
59    // reasons for retrying an authorization query
60    userNotInGroup = 41,            // authenticated user not in needed group
61    unacceptableUser,               // authenticated user unacceptable for some other reason
62
63    // reasons for canceling a staged query
64    tooManyTries = 61,              // too many failed attempts to get it right
65    noLongerNeeded,                 // the queried item is no longer needed
66    keychainAddFailed,              // the requested itemed couldn't be added to the keychain
67    generalErrorCancel,              // something went wrong so we have to give up now
68    resettingPassword,              // The user has indicated that they wish to reset their password
69
70	worldChanged = 101
71};
72
73typedef enum {
74	tool = 'TOOL',
75	bundle = 'BNDL',
76	unknown = 'UNKN'
77} RequestorType;
78
79#if defined(__cplusplus)
80
81using MachPlusPlus::Port;
82using MachPlusPlus::PortSet;
83using MachPlusPlus::Bootstrap;
84using MachPlusPlus::ReceivePort;
85using MachPlusPlus::Message;
86using Authorization::AuthItemSet;
87using Authorization::AuthValueVector;
88
89class Clients;
90
91class Client
92{
93friend class Clients;
94
95enum MessageType { requestInterruptMessage, didDeactivateMessage, reportErrorMessage };
96
97public:
98	Client();
99	virtual ~Client();
100
101    static AuthItemSet clientHints(SecurityAgent::RequestorType type, std::string &path, pid_t clientPid, uid_t clientUid);
102
103    static OSStatus startTransaction(Port serverPort);
104    static OSStatus endTransaction(Port serverPort);
105
106protected:
107	void establishServer();
108
109public:
110	void activate(Port serverPort);
111
112    OSStatus contact(mach_port_t jobId, Bootstrap processBootstrap, mach_port_t userPrefs);
113	OSStatus create(const char *pluginId, const char *mechanismId, const SessionId inSessionId);
114    void setArguments(const Authorization::AuthValueVector& inArguments) { mArguments = inArguments; }
115    void setInput(const Authorization::AuthItemSet& inHints, const Authorization::AuthItemSet& inContext) { mInHints = inHints; mInContext = inContext; }
116    OSStatus invoke();
117	OSStatus deactivate();
118	OSStatus destroy();
119	OSStatus terminate();
120    void receive();
121
122	void didCreate(const mach_port_t inStagePort);
123    void setResult(const AuthorizationResult inResult, const AuthorizationItemSet *inHints, const AuthorizationItemSet *inContext);
124	void requestInterrupt(); // setMessageType(requestInterrupt);
125	void didDeactivate(); // setMessageType(didDeactivate);
126
127	void setError(const OSStatus inMechanismError); // setMessageType(reportError); setError(mechanismError);
128    OSStatus getError();
129    AuthorizationResult result() { return mResult; }
130
131	typedef enum _PluginState {
132		init,
133		created,
134		current,
135		deactivating,
136		active,
137		interrupting,
138		dead
139	} PluginState;
140    PluginState state() { return mState; }
141
142protected:
143	void setMessageType(const MessageType inMessageType);
144	// allow didCreate to set stagePort
145	void setStagePort(const mach_port_t inStagePort);
146	// allow server routines to use request port to find instance
147
148	// @@@ implement lessThan operator for set in terms of instance
149
150protected:
151	void setup();
152	void teardown() throw();
153
154    Port mServerPort;
155	Port mStagePort;
156    Port mClientPort;
157
158	MessageType mMessageType;
159
160    OSStatus mErrorState;
161
162    AuthorizationResult mResult;
163    AuthValueVector mArguments;
164    AuthItemSet mInHints;
165    AuthItemSet mInContext;
166    AuthItemSet mOutHints;
167    AuthItemSet mOutContext;
168
169	PluginState mState;
170	void setState(PluginState mState);
171
172    bool mTerminateOnSleep;
173
174public:
175	mach_port_t instance() const { return mClientPort; }
176//	bool operator == (const Client &other) const { return this->instance() == other.instance(); }
177	bool operator < (const Client &other) const { return this->instance() < other.instance(); }
178
179    AuthItemSet &inHints() { return mInHints; }
180    AuthItemSet &inContext() { return mInContext; }
181    AuthItemSet &outHints() { return mOutHints; }
182    AuthItemSet &outContext() { return mOutContext; }
183
184    void setTerminateOnSleep(bool terminateOnSleep) {mTerminateOnSleep = terminateOnSleep;}
185    bool getTerminateOnSleep() {return mTerminateOnSleep;}
186
187public:
188    void check(mach_msg_return_t returnCode);
189    void checkResult();
190};
191
192class Clients
193{
194friend class Client;
195
196protected:
197	set<Client*> mClients;
198    PortSet mClientPortSet;
199public:
200    Clients() {}
201    void create(); // create an agentclient
202    void insert(Client *agent) { StLock<Mutex> _(mLock); mClients.insert(agent); mClientPortSet += agent->instance(); }
203    void remove(Client *agent) { StLock<Mutex> _(mLock); mClientPortSet -= agent->instance(); mClients.erase(agent); }
204    Client &find(const mach_port_t instance) const;
205    bool receive();
206    bool compare(const Client * client, mach_port_t instance);
207
208    mutable Mutex mLock;
209    static ThreadNexus<Clients> gClients;
210    static ModuleNexus<RecursiveMutex> gAllClientsMutex;
211    static ModuleNexus<set<Client*> > allClients;
212    static void killAllClients();
213};
214
215} // end namespace Authorization
216
217#endif /* __cplusplus__ */
218
219#endif /* _H_AGENTCLIENT */
220
221