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