1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19//
20// mdsclient - friendly interface to CDSA MDS API
21//
22#include <security_cdsa_client/mdsclient.h>
23#include <Security/mdspriv.h>
24
25
26namespace Security {
27namespace MDSClient {
28
29
30//
31// The MDS access object singleton
32//
33ModuleNexus<Directory> mds;
34
35
36//
37// Directory construction initializes MDS and opens the "CDSA" database
38//
39Directory::Directory()
40	: mMemoryFunctions(Allocator::standard())
41{
42	StLock<Mutex> _(mInitLock);
43	CssmError::check(MDS_Initialize(&mCallerGuid, &mMemoryFunctions,
44		this, &mCDSA.DLHandle));
45	mCDSA.DBHandle = CSSM_INVALID_HANDLE;
46}
47
48
49//
50// Cleanup (only called if the ModuleNexus is explicitly reset)
51//
52Directory::~Directory()
53{
54	if (mCDSA.DBHandle)
55		CssmError::check(DbClose(mCDSA));
56	CssmError::check(MDS_Terminate(mds()));
57}
58
59
60//
61// Open MDS database if needed
62//
63const MDS_DB_HANDLE &Directory::cdsa() const
64{
65	if (mCDSA.DBHandle == CSSM_INVALID_HANDLE) {
66		StLock<Mutex> _(mInitLock);
67		if (mCDSA.DBHandle == CSSM_INVALID_HANDLE)
68			CssmError::check(DbOpen(mCDSA.DLHandle, MDS_CDSA_DIRECTORY_NAME, NULL,
69				CSSM_DB_ACCESS_READ,	// access mode
70				NULL,					// credentials
71				NULL,					// OpenParameters
72				&mCDSA.DBHandle));
73	}
74	return mCDSA;
75}
76
77
78//
79// The DLAccess implementation for MDS.
80// We don't ever return record data, of course; we just zero it out.
81//
82CSSM_HANDLE Directory::dlGetFirst(const CSSM_QUERY &query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes,
83	CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id)
84{
85	CSSM_HANDLE result;
86	switch (CSSM_RETURN rc = DataGetFirst(cdsa(), &query, &result, &attributes, NULL, &id)) {
87	case CSSM_OK:
88		if (data)
89			*data = CssmData();
90		return result;
91	case CSSMERR_DL_ENDOFDATA:
92		return CSSM_INVALID_HANDLE;
93	default:
94		CssmError::throwMe(rc);
95		return CSSM_INVALID_HANDLE; // placebo
96	}
97}
98
99bool Directory::dlGetNext(CSSM_HANDLE handle, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes,
100	CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id)
101{
102	CSSM_RETURN rc = DataGetNext(cdsa(), handle, &attributes, NULL, &id);
103	switch (rc) {
104	case CSSM_OK:
105		if (data)
106			*data = CssmData();
107		return true;
108	case CSSMERR_DL_ENDOFDATA:
109		return false;
110	default:
111		CssmError::throwMe(rc);
112		return false;   // placebo
113	}
114}
115
116void Directory::dlAbortQuery(CSSM_HANDLE handle)
117{
118	CssmError::check(DataAbortQuery(cdsa(), handle));
119}
120
121void Directory::dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id)
122{
123	CssmError::check(FreeUniqueRecord(cdsa(), id));
124}
125
126void Directory::dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id)
127{
128	CssmError::check(DataDelete(cdsa(), id));
129}
130
131Allocator &Directory::allocator()
132{
133	return Allocator::standard();
134}
135
136
137//
138// Public MDS operations
139//
140void Directory::install()
141{
142	CssmError::check(MDS_Install(this->mds()));
143}
144
145void Directory::install(const MDS_InstallDefaults *defaults,
146	const char *path, const char *subdir, const char *file)
147{
148	CssmError::check(MDS_InstallFile(this->mds(), defaults, path, subdir, file));
149}
150
151void Directory::uninstall(const char *guid, uint32 ssid)
152{
153	CssmError::check(MDS_RemoveSubservice(this->mds(), guid, ssid));
154}
155
156
157} // end namespace MDSClient
158} // end namespace Security
159