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
69	worldChanged = 101
70};
71
72typedef enum {
73	tool = 'TOOL',
74	bundle = 'BNDL',
75	unknown = 'UNKN'
76} RequestorType;
77
78#if defined(__cplusplus)
79
80using MachPlusPlus::Port;
81using MachPlusPlus::PortSet;
82using MachPlusPlus::Bootstrap;
83using MachPlusPlus::ReceivePort;
84using MachPlusPlus::Message;
85using Authorization::AuthItemSet;
86using Authorization::AuthValueVector;
87
88class Clients;
89
90class Client
91{
92friend class Clients;
93
94enum MessageType { requestInterruptMessage, didDeactivateMessage, reportErrorMessage };
95
96public:
97	Client();
98	virtual ~Client();
99
100    static AuthItemSet clientHints(SecurityAgent::RequestorType type, std::string &path, pid_t clientPid, uid_t clientUid);
101
102    static OSStatus startTransaction(Port serverPort);
103    static OSStatus endTransaction(Port serverPort);
104
105protected:
106	void establishServer();
107
108public:
109	void activate(Port serverPort);
110
111    OSStatus contact(mach_port_t jobId, Bootstrap processBootstrap, mach_port_t userPrefs);
112	OSStatus create(const char *pluginId, const char *mechanismId, const SessionId inSessionId);
113    void setArguments(const Authorization::AuthValueVector& inArguments) { mArguments = inArguments; }
114    void setInput(const Authorization::AuthItemSet& inHints, const Authorization::AuthItemSet& inContext) { mInHints = inHints; mInContext = inContext; }
115    OSStatus invoke();
116	OSStatus deactivate();
117	OSStatus destroy();
118	OSStatus terminate();
119    void receive();
120
121	void didCreate(const mach_port_t inStagePort);
122    void setResult(const AuthorizationResult inResult, const AuthorizationItemSet *inHints, const AuthorizationItemSet *inContext);
123	void requestInterrupt(); // setMessageType(requestInterrupt);
124	void didDeactivate(); // setMessageType(didDeactivate);
125
126	void setError(const OSStatus inMechanismError); // setMessageType(reportError); setError(mechanismError);
127    OSStatus getError();
128    AuthorizationResult result() { return mResult; }
129
130	typedef enum _PluginState {
131		init,
132		created,
133		current,
134		deactivating,
135		active,
136		interrupting,
137		dead
138	} PluginState;
139    PluginState state() { return mState; }
140
141protected:
142	void setMessageType(const MessageType inMessageType);
143	// allow didCreate to set stagePort
144	void setStagePort(const mach_port_t inStagePort);
145	// allow server routines to use request port to find instance
146
147	// @@@ implement lessThan operator for set in terms of instance
148
149protected:
150	void setup();
151	void teardown() throw();
152
153    Port mServerPort;
154	Port mStagePort;
155    Port mClientPort;
156
157	MessageType mMessageType;
158
159    OSStatus mErrorState;
160
161    AuthorizationResult mResult;
162    AuthValueVector mArguments;
163    AuthItemSet mInHints;
164    AuthItemSet mInContext;
165    AuthItemSet mOutHints;
166    AuthItemSet mOutContext;
167
168	PluginState mState;
169	void setState(PluginState mState);
170
171public:
172	mach_port_t instance() const { return mClientPort; }
173//	bool operator == (const Client &other) const { return this->instance() == other.instance(); }
174	bool operator < (const Client &other) const { return this->instance() < other.instance(); }
175
176    AuthItemSet &inHints() { return mInHints; }
177    AuthItemSet &inContext() { return mInContext; }
178    AuthItemSet &outHints() { return mOutHints; }
179    AuthItemSet &outContext() { return mOutContext; }
180
181public:
182		void check(mach_msg_return_t returnCode);
183        void checkResult();
184};
185
186class Clients
187{
188friend class Client;
189
190protected:
191	set<Client*> mClients;
192    PortSet mClientPortSet;
193public:
194    Clients() {}
195	void create(); // create an agentclient
196	void insert(Client *agent) { StLock<Mutex> _(mLock); mClients.insert(agent); mClientPortSet += agent->instance(); }
197	void remove(Client *agent) { StLock<Mutex> _(mLock); mClientPortSet -= agent->instance(); mClients.erase(agent); }
198	Client &find(const mach_port_t instance) const;
199    bool receive();
200	bool compare(const Client * client, mach_port_t instance);
201
202	mutable Mutex mLock;
203	static ThreadNexus<Clients> gClients;
204};
205
206} // end namespace Authorization
207
208#endif /* __cplusplus__ */
209
210#endif /* _H_AGENTCLIENT */
211
212