1/*
2 * Copyright (c) 2000-2008,2011-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// ssclient - SecurityServer client interface library
27//
28// This interface is private to the Security system. It is not a public interface,
29// and it may change at any time. You have been warned.
30//
31#ifndef _H_SSCLIENT
32#define _H_SSCLIENT
33
34#include "sscommon.h"
35#include <Security/Authorization.h>
36#include <Security/AuthSession.h>
37#include <Security/SecCodeHost.h>
38
39#ifdef __cplusplus
40
41#include <security_utilities/osxcode.h>
42#include <security_utilities/unix++.h>
43#include <security_utilities/globalizer.h>
44#include <security_cdsa_utilities/cssmerrors.h>
45#include "ssnotify.h"
46
47
48namespace Security {
49namespace SecurityServer {
50
51#endif //__cplusplus
52
53
54//
55// Unique-identifier blobs for key objects
56//
57typedef struct KeyUID {
58    uint8 signature[20];
59} KeyUID;
60
61
62//
63// Maximum length of hash (digest) arguments (bytes)
64//
65#define maxUcspHashLength 64
66
67
68//
69// Authorization blobs
70//
71typedef struct AuthorizationBlob {
72    uint32 data[2];
73
74#ifdef __cplusplus
75	bool operator < (const AuthorizationBlob &other) const
76	{ return memcmp(data, other.data, sizeof(data)) < 0; }
77
78	bool operator == (const AuthorizationBlob &other) const
79	{ return memcmp(data, other.data, sizeof(data)) == 0; }
80
81    size_t hash() const {	//@@@ revisit this hash
82        return data[0] ^ data[1] << 3;
83    }
84#endif
85} AuthorizationBlob;
86
87
88//
89// Initial-setup data for versioning etc.
90//
91typedef struct {
92	uint32_t order;
93	uint32_t version;
94} ClientSetupInfo;
95
96#define SSPROTOVERSION 20000
97
98
99//
100// Database parameter structure
101//
102typedef struct {
103	uint32_t idleTimeout;				// seconds idle timout lock
104	uint8_t lockOnSleep;				// lock keychain when system sleeps
105} DBParameters;
106
107
108#ifdef __cplusplus
109
110
111//
112// A client connection (session)
113//
114class ClientSession : public ClientCommon {
115public:
116	ClientSession(Allocator &standard = Allocator::standard(),
117		Allocator &returning = Allocator::standard());
118	virtual ~ClientSession();
119
120public:
121	void activate();
122	void reset();
123
124public:
125	// use this only if you know what you're doing...
126	void contactName(const char *name);
127	const char *contactName() const;
128
129    static GenericHandle toIPCHandle(CSSM_HANDLE h) {
130        // implementation subject to change
131        if (h & (CSSM_HANDLE(~0) ^ GenericHandle(~0)))
132            CssmError::throwMe(CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
133        return h & GenericHandle(~0);
134    }
135
136
137public:
138	//
139	// common database interface
140	//
141	void authenticateDb(DbHandle db, CSSM_DB_ACCESS_TYPE type, const AccessCredentials *cred);
142	void releaseDb(DbHandle db);
143
144	//
145	// External database interface
146	//
147	DbHandle openToken(uint32 ssid, const AccessCredentials *cred, const char *name = NULL);
148
149	RecordHandle insertRecord(DbHandle db,
150					  CSSM_DB_RECORDTYPE recordType,
151					  const CssmDbRecordAttributeData *attributes,
152					  const CssmData *data);
153	void deleteRecord(DbHandle db, RecordHandle record);
154	void modifyRecord(DbHandle db, RecordHandle &record,
155					  CSSM_DB_RECORDTYPE recordType,
156					  const CssmDbRecordAttributeData *attributesToBeModified,
157					  const CssmData *dataToBeModified,
158					  CSSM_DB_MODIFY_MODE modifyMode);
159
160	RecordHandle findFirst(DbHandle db,
161						const CssmQuery &query,
162						SearchHandle &outSearchHandle,
163						CssmDbRecordAttributeData *inOutAttributes,
164						CssmData *outData, KeyHandle &key);
165	RecordHandle findNext(SearchHandle searchHandle,
166					   CssmDbRecordAttributeData *inOutAttributes,
167					   CssmData *inOutData, KeyHandle &key);
168	void findRecordHandle(RecordHandle record,
169						 CssmDbRecordAttributeData *inOutAttributes,
170						 CssmData *inOutData, KeyHandle &key);
171	void releaseSearch(SearchHandle searchHandle);
172	void releaseRecord(RecordHandle record);
173
174	void getDbName(DbHandle db, std::string &name);
175	void setDbName(DbHandle db, const std::string &name);
176
177	//
178	// Internal database interface
179	//
180	DbHandle createDb(const DLDbIdentifier &dbId,
181        const AccessCredentials *cred, const AclEntryInput *owner,
182        const DBParameters &params);
183	DbHandle cloneDbForSync(const CssmData &secretsBlob, DbHandle srcDb,
184							const CssmData &agentData);
185	DbHandle recodeDbForSync(DbHandle dbToClone, DbHandle srcDb);
186	DbHandle authenticateDbsForSync(const CssmData &dbHandleArray, const CssmData &agentData);
187    void commitDbForSync(DbHandle srcDb, DbHandle cloneDb, CssmData &blob, Allocator &alloc);
188	DbHandle decodeDb(const DLDbIdentifier &dbId,
189        const AccessCredentials *cred, const CssmData &blob);
190	void encodeDb(DbHandle db, CssmData &blob, Allocator &alloc);
191    void encodeDb(DbHandle db, CssmData &blob) { return encodeDb(db, blob, returnAllocator); }
192	void setDbParameters(DbHandle db, const DBParameters &params);
193	void getDbParameters(DbHandle db, DBParameters &params);
194    void changePassphrase(DbHandle db, const AccessCredentials *cred);
195    void lock(DbHandle db);
196    void lockAll(bool forSleep);
197    void unlock(DbHandle db);
198    void unlock(DbHandle db, const CssmData &passPhrase);
199    void stashDb(DbHandle db);
200    void stashDbCheck(DbHandle db);
201    bool isLocked(DbHandle db);
202    void verifyKeyStorePassphrase(uint32_t retries);
203    void resetKeyStorePassphrase(const CssmData &passphrase);
204    void changeKeyStorePassphrase();
205
206public:
207	//
208	// Key objects
209	//
210	void encodeKey(KeyHandle key, CssmData &blob, KeyUID *uid, Allocator &alloc);
211	void encodeKey(KeyHandle key, CssmData &blob, KeyUID *uid = NULL)
212    { return encodeKey(key, blob, uid, returnAllocator); }
213	KeyHandle decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header);
214	void recodeKey(DbHandle oldDb, KeyHandle key, DbHandle newDb, CssmData &blob);
215	void releaseKey(KeyHandle key);
216
217	CssmKeySize queryKeySizeInBits(KeyHandle key);
218    uint32 getOutputSize(const Security::Context &context, KeyHandle key,
219        uint32 inputSize, bool encrypt = true);
220
221	void getKeyDigest(KeyHandle key, CssmData &digest, Allocator &alloc);
222	void getKeyDigest(KeyHandle key, CssmData &digest)
223	{ return getKeyDigest(key, digest, returnAllocator); }
224
225
226    // key wrapping and unwrapping
227	void wrapKey(const Security::Context &context, KeyHandle key, KeyHandle keyToBeWrapped,
228		const AccessCredentials *cred,
229		const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, Allocator &alloc);
230	void wrapKey(const Security::Context &context, KeyHandle key, KeyHandle keyToBeWrapped,
231		const AccessCredentials *cred,
232		const CssmData *descriptiveData, CssmWrappedKey &wrappedKey)
233    { return wrapKey(context, key, keyToBeWrapped, cred,
234        descriptiveData, wrappedKey, returnAllocator); }
235
236	void unwrapKey(DbHandle db, const Security::Context &context, KeyHandle key, KeyHandle publicKey,
237		const CssmWrappedKey &wrappedKey, uint32 keyUsage, uint32 keyAttr,
238		const AccessCredentials *cred, const AclEntryInput *owner,
239		CssmData &data, KeyHandle &newKey, CssmKey::Header &newKeyHeader, Allocator &alloc);
240	void unwrapKey(DbHandle db, const Security::Context &context, KeyHandle key, KeyHandle publicKey,
241		const CssmWrappedKey &wrappedKey, uint32 keyUsage, uint32 keyAttr,
242		const AccessCredentials *cred, const AclEntryInput *owner, CssmData &data,
243        KeyHandle &newKey, CssmKey::Header &newKeyHeader)
244    { return unwrapKey(db, context, key, publicKey, wrappedKey, keyUsage, keyAttr,
245      cred, owner, data, newKey, newKeyHeader, returnAllocator); }
246
247    // key generation and derivation
248	void generateKey(DbHandle db, const Security::Context &context, uint32 keyUsage, uint32 keyAttr,
249		const AccessCredentials *cred, const AclEntryInput *owner,
250        KeyHandle &newKey, CssmKey::Header &newHeader);
251	void generateKey(DbHandle db, const Security::Context &context,
252		uint32 pubKeyUsage, uint32 pubKeyAttr,
253		uint32 privKeyUsage, uint32 privKeyAttr,
254		const AccessCredentials *cred, const AclEntryInput *owner,
255		KeyHandle &pubKey, CssmKey::Header &pubHeader,
256        KeyHandle &privKey, CssmKey::Header &privHeader);
257	void deriveKey(DbHandle db, const Security::Context &context, KeyHandle baseKey,
258        uint32 keyUsage, uint32 keyAttr, CssmData &param,
259		const AccessCredentials *cred, const AclEntryInput *owner,
260        KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc);
261	void deriveKey(DbHandle db, const Security::Context &context, KeyHandle baseKey,
262        uint32 keyUsage, uint32 keyAttr, CssmData &param,
263		const AccessCredentials *cred, const AclEntryInput *owner,
264        KeyHandle &newKey, CssmKey::Header &newHeader)
265    { return deriveKey(db, context, baseKey, keyUsage, keyAttr, param, cred, owner, newKey, newHeader, returnAllocator); }
266	//void generateAlgorithmParameters();	// not implemented
267
268	void generateRandom(const Security::Context &context, CssmData &data, Allocator &alloc);
269	void generateRandom(const Security::Context &context, CssmData &data)
270	{ return generateRandom(context, data, returnAllocator); }
271
272    // encrypt/decrypt
273	void encrypt(const Security::Context &context, KeyHandle key,
274        const CssmData &in, CssmData &out, Allocator &alloc);
275	void encrypt(const Security::Context &context, KeyHandle key, const CssmData &in, CssmData &out)
276    { return encrypt(context, key, in, out, returnAllocator); }
277	void decrypt(const Security::Context &context, KeyHandle key,
278        const CssmData &in, CssmData &out, Allocator &alloc);
279	void decrypt(const Security::Context &context, KeyHandle key, const CssmData &in, CssmData &out)
280    { return decrypt(context, key, in, out, returnAllocator); }
281
282    // signatures
283	void generateSignature(const Security::Context &context, KeyHandle key,
284        const CssmData &data, CssmData &signature, Allocator &alloc,
285        CSSM_ALGORITHMS signOnlyAlgorithm = CSSM_ALGID_NONE);
286	void generateSignature(const Security::Context &context, KeyHandle key,
287		const CssmData &data, CssmData &signature, CSSM_ALGORITHMS signOnlyAlgorithm = CSSM_ALGID_NONE)
288    { return generateSignature(context, key, data, signature, returnAllocator, signOnlyAlgorithm); }
289	void verifySignature(const Security::Context &context, KeyHandle key,
290		const CssmData &data, const CssmData &signature,
291        CSSM_ALGORITHMS verifyOnlyAlgorithm = CSSM_ALGID_NONE);
292
293    // MACs
294	void generateMac(const Security::Context &context, KeyHandle key,
295		const CssmData &data, CssmData &mac, Allocator &alloc);
296	void generateMac(const Security::Context &context, KeyHandle key,
297		const CssmData &data, CssmData &mac)
298    { return generateMac(context, key, data, mac, returnAllocator); }
299	void verifyMac(const Security::Context &context, KeyHandle key,
300		const CssmData &data, const CssmData &mac);
301
302    // key ACL management
303	void getKeyAcl(KeyHandle key, const char *tag,
304        uint32 &count, AclEntryInfo * &info, Allocator &alloc);
305	void getKeyAcl(KeyHandle key, const char *tag,
306        uint32 &count, AclEntryInfo * &info)
307    { return getKeyAcl(key, tag, count, info, returnAllocator); }
308	void changeKeyAcl(KeyHandle key, const AccessCredentials &cred, const AclEdit &edit);
309	void getKeyOwner(KeyHandle key, AclOwnerPrototype &owner, Allocator &alloc);
310	void getKeyOwner(KeyHandle key, AclOwnerPrototype &owner)
311    { return getKeyOwner(key, owner, returnAllocator); }
312	void changeKeyOwner(KeyHandle key, const AccessCredentials &cred,
313		const AclOwnerPrototype &edit);
314
315    // database ACL management
316	void getDbAcl(DbHandle db, const char *tag,
317        uint32 &count, AclEntryInfo * &info, Allocator &alloc);
318	void getDbAcl(DbHandle db, const char *tag,
319        uint32 &count, AclEntryInfo * &info)
320    { return getDbAcl(db, tag, count, info, returnAllocator); }
321	void changeDbAcl(DbHandle db, const AccessCredentials &cred, const AclEdit &edit);
322	void getDbOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc);
323	void getDbOwner(DbHandle db, AclOwnerPrototype &owner)
324    { return getDbOwner(db, owner, returnAllocator); }
325    void changeDbOwner(DbHandle db, const AccessCredentials &cred,
326		const AclOwnerPrototype &edit);
327
328	// database key manipulations
329	void extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb,
330        uint32 keyUsage, uint32 keyAttr,
331		const AccessCredentials *cred, const AclEntryInput *owner,
332        KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc);
333	void extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb,
334        uint32 keyUsage, uint32 keyAttr,
335		const AccessCredentials *cred, const AclEntryInput *owner,
336        KeyHandle &newKey, CssmKey::Header &newHeader)
337	{ return extractMasterKey(db, context, sourceDb, keyUsage, keyAttr, cred, owner,
338		newKey, newHeader, returnAllocator); }
339
340public:
341	// Authorization API support
342	void authCreate(const AuthorizationItemSet *rights,	const AuthorizationItemSet *environment,
343		AuthorizationFlags flags,AuthorizationBlob &result);
344	void authRelease(const AuthorizationBlob &auth, AuthorizationFlags flags);
345	void authCopyRights(const AuthorizationBlob &auth,
346		const AuthorizationItemSet *rights, const AuthorizationItemSet *environment,
347		AuthorizationFlags flags, AuthorizationItemSet **result);
348	void authCopyInfo(const AuthorizationBlob &auth, const char *tag, AuthorizationItemSet * &info);
349	void authExternalize(const AuthorizationBlob &auth, AuthorizationExternalForm &extForm);
350	void authInternalize(const AuthorizationExternalForm &extForm, AuthorizationBlob &auth);
351
352public:
353    // Session API support
354	void setSessionUserPrefs(SecuritySessionId sessionId, uint32_t userPreferencesLength, const void *userPreferences);
355
356public:
357    // Notification core support
358    void postNotification(NotificationDomain domain, NotificationEvent event, const CssmData &data);
359
360	// low-level callback (C form)
361    typedef OSStatus ConsumeNotification(NotificationDomain domain, NotificationEvent event,
362        const void *data, size_t dataLength, void *context);
363
364public:
365	// AuthorizationDB API
366	void authorizationdbGet(const AuthorizationString rightname, CssmData &rightDefinition, Allocator &alloc);
367	void authorizationdbSet(const AuthorizationBlob &auth, const AuthorizationString rightname, uint32_t rightdefinitionLength, const void *rightdefinition);
368	void authorizationdbRemove(const AuthorizationBlob &auth, const AuthorizationString rightname);
369
370public:
371	// securityd helper support
372	void childCheckIn(Port serverPort, Port taskPort);
373
374public:
375	// miscellaneous administrative calls
376	void addCodeEquivalence(const CssmData &oldCode, const CssmData &newCode,
377		const char *name, bool forSystem = false);
378	void removeCodeEquivalence(const CssmData &code, const char *name, bool forSystem = false);
379	void setAlternateSystemRoot(const char *path);
380
381public:
382	// temporary hack to deal with "edit acl" pseudo-error returns
383	typedef void DidChangeKeyAclCallback(void *context, ClientSession &clientSession,
384		KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag);
385	void registerForAclEdits(DidChangeKeyAclCallback *callback, void *context);
386
387public:
388	// Code Signing hosting interface
389	void registerHosting(mach_port_t hostingPort, SecCSFlags flags);
390	mach_port_t hostingPort(pid_t pid);
391
392	SecGuestRef createGuest(SecGuestRef host,
393		uint32_t status, const char *path, const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags);
394	void setGuestStatus(SecGuestRef guest, uint32 status, const CssmData &attributes);
395	void removeGuest(SecGuestRef host, SecGuestRef guest);
396
397	void selectGuest(SecGuestRef guest);
398	SecGuestRef selectedGuest() const;
399
400private:
401	static Port findSecurityd();
402	void getAcl(AclKind kind, GenericHandle key, const char *tag,
403		uint32 &count, AclEntryInfo * &info, Allocator &alloc);
404	void changeAcl(AclKind kind, GenericHandle key,
405		const AccessCredentials &cred, const AclEdit &edit);
406	void getOwner(AclKind kind, GenericHandle key,
407		AclOwnerPrototype &owner, Allocator &alloc);
408	void changeOwner(AclKind kind, GenericHandle key,
409		const AccessCredentials &cred, const AclOwnerPrototype &edit);
410
411	static OSStatus consumerDispatch(NotificationDomain domain, NotificationEvent event,
412		const void *data, size_t dataLength, void *context);
413
414	void notifyAclChange(KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag);
415
416	void returnAttrsAndData(CssmDbRecordAttributeData *inOutAttributes,
417		CssmDbRecordAttributeData *attrs, CssmDbRecordAttributeData *attrsBase, mach_msg_type_number_t attrsLength,
418		CssmData *inOutData, void *dataPtr, mach_msg_type_number_t dataLength);
419private:
420	DidChangeKeyAclCallback *mCallback;
421	void *mCallbackContext;
422
423	static UnixPlusPlus::StaticForkMonitor mHasForked;	// global fork indicator
424
425	struct Thread {
426		Thread() : registered(false), notifySeq(0),
427			currentGuest(kSecNoGuest), lastGuest(kSecNoGuest) { }
428		operator bool() const { return registered; }
429
430		ReceivePort replyPort;	// dedicated reply port (send right held by SecurityServer)
431        bool registered;		// has been registered with SecurityServer
432		uint32 notifySeq; // notification sequence number
433
434		SecGuestRef currentGuest;	// last set guest path
435		SecGuestRef lastGuest;		// last transmitted guest path
436	};
437
438	struct Global {
439        Global();
440		Port serverPort;
441		RefPointer<OSXCode> myself;
442		ThreadNexus<Thread> thread;
443	};
444
445	static ModuleNexus<Global> mGlobal;
446	static const char *mContactName;
447	static SecGuestRef mDedicatedGuest;
448};
449
450
451} // end namespace SecurityServer
452} // end namespace Security
453
454#endif //__cplusplus
455
456
457#endif //_H_SSCLIENT
458