1/*
2 * Copyright (c) 2000-2005,2007-2010,2012-2013 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// passphrases - canonical code to obtain passphrases
27//
28#ifndef _H_AGENTQUERY
29#define _H_AGENTQUERY
30
31#include <security_agent_client/agentclient.h>
32#include <security_cdsa_utilities/AuthorizationData.h>
33#include <security_utilities/ccaudit.h> // some queries do their own authentication
34#include <Security/AuthorizationPlugin.h>
35#include "kcdatabase.h"
36#include "AuthorizationEngine.h"
37#include "authhost.h"
38#include "server.h"
39#include "session.h"
40#include <xpc/xpc.h>
41
42using Authorization::AuthItemSet;
43using Authorization::AuthValueVector;
44using Security::OSXCode;
45
46//
47// base for classes talking to SecurityAgent and authorizationhost
48//
49class SecurityAgentConnection : public SecurityAgent::Client,
50public SecurityAgentConnectionInterface
51{
52public:
53    SecurityAgentConnection(const AuthHostType type = securityAgent, Session &session = Server::session());
54    virtual ~SecurityAgentConnection();
55    virtual void activate();
56    virtual void reconnect();
57    virtual void disconnect()  { };
58    virtual void terminate();
59
60    AuthHostType hostType()  { return mAuthHostType; }
61
62protected:
63    AuthHostType mAuthHostType;
64    RefPointer<AuthHostInstance> mHostInstance;
65    Port mPort;
66    const RefPointer<Connection> mConnection;
67    audit_token_t *mAuditToken;
68};
69
70//
71// base for classes talking to com.apple.security.agent and com.apple.security.authhost
72//
73class SecurityAgentXPCConnection : public SecurityAgentConnectionInterface
74{
75public:
76    SecurityAgentXPCConnection(const AuthHostType type = securityAgent, Session &session = Server::session());
77    virtual ~SecurityAgentXPCConnection();
78    virtual void activate(bool ignoreUid);
79    virtual void reconnect();
80    virtual void disconnect()  { };
81    virtual void terminate();
82
83    AuthHostType hostType()  { return mAuthHostType; }
84
85protected:
86    AuthHostType mAuthHostType;
87    RefPointer<AuthHostInstance> mHostInstance;
88    Session &mSession;
89    xpc_connection_t mXPCConnection;
90    xpc_connection_t mXPCStubConnection;
91    const RefPointer<Connection> mConnection;
92    audit_token_t *mAuditToken;
93    uid_t mNobodyUID;
94
95    bool inDarkWake();
96
97};
98
99//
100// The main SecurityAgent/authorizationhost interaction base class
101//
102class SecurityAgentQuery : public SecurityAgentConnection
103{
104public:
105	typedef SecurityAgent::Reason Reason;
106
107	SecurityAgentQuery(const AuthHostType type = securityAgent, Session &session = Server::session());
108
109
110	void inferHints(Process &thisProcess);
111	void addHint(const char *name, const void *value = NULL, UInt32 valueLen = 0, UInt32 flags = 0);
112
113	virtual ~SecurityAgentQuery();
114
115	virtual void disconnect();
116	virtual void terminate();
117	void create(const char *pluginId, const char *mechanismId, const SessionId inSessionId);
118
119	void readChoice();
120
121	bool allow;
122	bool remember;
123
124protected:
125	AuthItemSet mClientHints;
126};
127
128//
129// The main com.apple.security.agent/com.apple.security.authhost interaction base class
130//
131class SecurityAgentXPCQuery : public SecurityAgentXPCConnection
132{
133public:
134    static void killAllXPCClients();
135
136    typedef SecurityAgent::Reason Reason;
137
138	SecurityAgentXPCQuery(const AuthHostType type = securityAgent, Session &session = Server::session());
139
140
141	void inferHints(Process &thisProcess);
142	void addHint(const char *name, const void *value = NULL, UInt32 valueLen = 0, UInt32 flags = 0);
143
144	virtual ~SecurityAgentXPCQuery();
145
146	virtual void disconnect();
147	virtual void terminate();
148	void create(const char *pluginId, const char *mechanismId, const SessionId inSessionId);
149    OSStatus invoke();
150    void setTerminateOnSleep(bool terminateOnSleep) {mTerminateOnSleep = terminateOnSleep;}
151    bool getTerminateOnSleep() {return mTerminateOnSleep;}
152    void setInput(const AuthItemSet& inHints, const AuthItemSet& inContext) { mInHints = inHints; mInContext = inContext; }
153    void checkResult();
154
155	void readChoice();
156
157	bool allow;
158	bool remember;
159
160protected:
161	AuthItemSet mClientHints;
162    AuthItemSet mImmutableHints;
163    AuthItemSet mInHints;
164    AuthItemSet mInContext;
165    AuthItemSet mOutHints;
166    AuthItemSet mOutContext;
167    bool mAgentConnected;
168    uint64_t mLastResult;
169    bool mTerminateOnSleep;
170};
171
172//
173// Specialized for "rogue app" alert queries
174//
175class QueryKeychainUse : public SecurityAgentXPCQuery {
176public:
177    QueryKeychainUse(bool needPass, const Database *db);
178    Reason queryUser (const char* database, const char *description, AclAuthorization action);
179
180private:
181    const KeychainDatabase *mPassphraseCheck; // NULL to not check passphrase
182};
183
184
185//
186// Specialized for code signature adjustment queries
187//
188class QueryCodeCheck : public SecurityAgentXPCQuery {
189public:
190    bool operator () (const char *aclPath);
191};
192
193
194//
195// A query for an existing passphrase
196//
197class QueryOld : public SecurityAgentXPCQuery {
198	static const int maxTries = kMaximumAuthorizationTries;
199public:
200	QueryOld(Database &db) : database(db) {setTerminateOnSleep(true);}
201
202	Database &database;
203
204	Reason operator () ();
205
206protected:
207	Reason query();
208	virtual Reason accept(CssmManagedData &) = 0;
209};
210
211
212class QueryUnlock : public QueryOld {
213public:
214	QueryUnlock(KeychainDatabase &db) : QueryOld(db) { }
215    Reason retrievePassword(CssmOwnedData &passphrase);
216
217protected:
218	Reason accept(CssmManagedData &passphrase);
219};
220
221
222class QueryKeybagPassphrase : public SecurityAgentXPCQuery {
223public:
224    QueryKeybagPassphrase(Session &session, int32_t retries = kMaximumAuthorizationTries);
225
226    Reason query();
227    Reason accept(CssmManagedData &passphrase);
228protected:
229    Session &mSession;
230    service_context_t mContext;
231    int32_t mRetries;
232};
233
234class QueryKeybagNewPassphrase : public QueryKeybagPassphrase {
235public:
236    QueryKeybagNewPassphrase(Session &session);
237
238    Reason query(CssmOwnedData &oldPassphrase, CssmOwnedData &passphrase);
239};
240
241//
242// Repurpose QueryUnlock for PIN prompting
243// Not very clean - but this stuff is an outdated hack as it is...
244//
245class QueryPIN : public QueryOld {
246public:
247	QueryPIN(Database &db);
248
249	const CssmData &pin() const { return mPin; }
250
251protected:
252	Reason accept(CssmManagedData &pin);
253
254private:
255	CssmAutoData mPin;		// PIN obtained
256};
257
258
259//
260// A query for a new passphrase
261//
262class QueryNewPassphrase : public SecurityAgentXPCQuery {
263	static const int maxTries = kMaximumAuthorizationTries;
264public:
265	QueryNewPassphrase(Database &db, Reason reason) :
266	    database(db), initialReason(reason),
267	    mPassphrase(Allocator::standard(Allocator::sensitive)),
268        mOldPassphrase(Allocator::standard(Allocator::sensitive)),
269	    mPassphraseValid(false) { }
270
271	Database &database;
272
273	Reason operator () (CssmOwnedData &oldPassphrase, CssmOwnedData &passphrase);
274
275protected:
276	Reason query();
277	virtual Reason accept(CssmManagedData &passphrase, CssmData *oldPassphrase);
278
279private:
280	Reason initialReason;
281	CssmAutoData mPassphrase;
282    CssmAutoData mOldPassphrase;
283    bool mPassphraseValid;
284};
285
286
287//
288// Generic passphrase query (not associated with a database)
289//
290class QueryGenericPassphrase : public SecurityAgentXPCQuery {
291public:
292    QueryGenericPassphrase()    { }
293    Reason operator () (const CssmData *prompt, bool verify,
294                        string &passphrase);
295
296protected:
297    Reason query(const CssmData *prompt, bool verify, string &passphrase);
298};
299
300
301//
302// Generic secret query (not associated with a database)
303//
304class QueryDBBlobSecret : public SecurityAgentXPCQuery {
305	static const int maxTries = kMaximumAuthorizationTries;
306public:
307    QueryDBBlobSecret()    { }
308    Reason operator () (DbHandle *dbHandleArray, uint8 dbHandleArrayCount, DbHandle *dbHandleAuthenticated);
309
310protected:
311    Reason query(DbHandle *dbHandleArray, uint8 dbHandleArrayCount, DbHandle *dbHandleAuthenticated);
312	Reason accept(CssmManagedData &passphrase, DbHandle *dbHandlesToAuthenticate, uint8 dbHandleCount, DbHandle *dbHandleAuthenticated);
313};
314
315class QueryInvokeMechanism : public SecurityAgentQuery, public RefCount {
316public:
317	QueryInvokeMechanism(const AuthHostType type, Session &session);
318    void initialize(const string &inPluginId, const string &inMechanismId, const AuthValueVector &arguments, const SessionId inSessionId = 0);
319    void run(const AuthValueVector &inArguments, AuthItemSet &inHints, AuthItemSet &inContext, AuthorizationResult *outResult);
320
321    bool operator () (const string &inPluginId, const string &inMechanismId, const Authorization::AuthValueVector &inArguments, AuthItemSet &inHints, AuthItemSet &inContext, AuthorizationResult *outResult);
322    void terminateAgent();
323    //~QueryInvokeMechanism();
324
325    AuthValueVector mArguments;
326};
327
328// hybrid of confirm-access and generic authentication queries, for
329// securityd's use; keep the Frankenstein references to yourself
330// (the alternative is to ask the user to unlock the system keychain,
331// and you don't want that, do you?)
332class QueryKeychainAuth : public SecurityAgentXPCQuery {
333	static const int maxTries = kMaximumAuthorizationTries;
334public:
335    QueryKeychainAuth()  { }
336    // "prompt" can be NULL
337    Reason operator () (const char *database, const char *description, AclAuthorization action, const char *prompt);
338    Reason accept(string &username, string &passphrase);
339};
340
341#endif //_H_AGENTQUERY
342