1/*
2 * Copyright (c) 2000-2004,2006-2007,2011-2012 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// cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures
27//
28#include <security_cdsa_utilities/cssmaclpod.h>
29#include <security_cdsa_utilities/cssmwalkers.h>
30#include <cstdarg>
31
32
33namespace Security {
34
35
36//
37// AclAuthorizationSets
38//
39AclAuthorizationSet::AclAuthorizationSet(AclAuthorization auth0, AclAuthorization auth, ...)
40{
41	insert(auth0);
42
43	va_list args;
44	va_start(args, auth);
45	while (auth) {
46		insert(auth);
47		auth = va_arg(args, AclAuthorization);
48	}
49	va_end(args);
50}
51
52
53//
54// AclAuthorizationGroups
55//
56AuthorizationGroup::AuthorizationGroup(const AclAuthorizationSet &auths, Allocator &alloc)
57{
58	NumberOfAuthTags = (uint32)auths.size();
59	AuthTags = alloc.alloc<CSSM_ACL_AUTHORIZATION_TAG>(NumberOfAuthTags);
60	copy(auths.begin(), auths.end(), AuthTags);	// happens to be sorted
61}
62
63AuthorizationGroup::AuthorizationGroup(CSSM_ACL_AUTHORIZATION_TAG tag, Allocator &alloc)
64{
65	AuthTags = alloc.alloc<CSSM_ACL_AUTHORIZATION_TAG>(1);
66	AuthTags[0] = tag;
67	NumberOfAuthTags = 1;
68}
69
70void AuthorizationGroup::destroy(Allocator &alloc)
71{
72	alloc.free(AuthTags);
73}
74
75bool AuthorizationGroup::contains(CSSM_ACL_AUTHORIZATION_TAG tag) const
76{
77	return find(AuthTags, &AuthTags[NumberOfAuthTags], tag) != &AuthTags[NumberOfAuthTags];
78}
79
80
81AuthorizationGroup::operator AclAuthorizationSet() const
82{
83	return AclAuthorizationSet(AuthTags, &AuthTags[NumberOfAuthTags]);
84}
85
86AclEntryPrototype::AclEntryPrototype(const AclOwnerPrototype &proto)
87{
88	memset(this, 0, sizeof(*this));
89	TypedSubject = proto.subject(); Delegate = proto.delegate();
90	//@@@ set authorization to "is owner" pseudo-auth? See cssmacl.h
91}
92
93void AclEntryPrototype::tag(const char *tagString)
94{
95	if (tagString == NULL)
96		EntryTag[0] = '\0';
97	else if (strlen(tagString) > CSSM_MODULE_STRING_SIZE)
98		CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG);
99	else
100		strcpy(EntryTag, tagString);
101}
102
103void AclEntryPrototype::tag(const string &tagString)
104{
105	if (tagString.length() > CSSM_MODULE_STRING_SIZE)
106		CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG);
107	else
108		memcpy(EntryTag, tagString.c_str(), tagString.length() + 1);
109}
110
111
112AclOwnerPrototype *AutoAclOwnerPrototype::make()
113{
114	if (!mAclOwnerPrototype) {
115		mAclOwnerPrototype = (AclOwnerPrototype*) mAllocator->malloc(sizeof(AclOwnerPrototype));
116        new (mAclOwnerPrototype) AclOwnerPrototype;
117		mAclOwnerPrototype->clearPod();
118	}
119	return mAclOwnerPrototype;
120}
121
122AutoAclOwnerPrototype::~AutoAclOwnerPrototype()
123{
124	if (mAllocator)
125		DataWalkers::chunkFree(mAclOwnerPrototype, *mAllocator);
126}
127
128void
129AutoAclOwnerPrototype::allocator(Allocator &allocator)
130{
131	mAllocator = &allocator;
132}
133
134
135void AutoAclEntryInfoList::size(uint32 newSize)
136{
137	assert(mAllocator);
138	mEntries = mAllocator->alloc<AclEntryInfo>(mEntries, newSize);
139	for (uint32 n = mCount; n < newSize; n++)
140		mEntries[n].clearPod();
141	mCount = newSize;
142}
143
144
145AclEntryInfo &AutoAclEntryInfoList::at(uint32 ix)
146{
147	if (ix >= mCount)
148		size(ix + 1);	// expand vector
149	return mEntries[ix];
150}
151
152
153void AutoAclEntryInfoList::clear()
154{
155	if (mAllocator)
156	{
157		DataWalkers::ChunkFreeWalker w(*mAllocator);
158		for (uint32 ix = 0; ix < mCount; ix++)
159			walk(w, mEntries[ix]);
160		mAllocator->free(mEntries);
161		mEntries = NULL;
162		mCount = 0;
163	}
164}
165
166void AutoAclEntryInfoList::allocator(Allocator &allocator)
167{
168	mAllocator = &allocator;
169}
170
171
172void AutoAclEntryInfoList::add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag /* = NULL */)
173{
174	AclEntryInfo &info = at(size());
175	info.proto() = AclEntryPrototype(subj);
176	info.proto().authorization() = AuthorizationGroup(auths, allocator());
177	info.proto().tag(tag);
178	info.handle(size());
179}
180
181void AutoAclEntryInfoList::addPin(const TypedList &subj, uint32 slot)
182{
183	char tag[20];
184	snprintf(tag, sizeof(tag), "PIN%d", slot);
185	add(subj, CSSM_ACL_AUTHORIZATION_PREAUTH(slot), tag);
186}
187
188void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status)
189{
190	char tag[20];
191	snprintf(tag, sizeof(tag), "PIN%d?", slot);
192	TypedList subj(allocator(), CSSM_WORDID_PIN,
193		new(allocator()) ListElement(slot),
194		new(allocator()) ListElement(status));
195	add(subj, CSSM_WORDID_PIN, tag);
196}
197
198void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status, uint32 count)
199{
200	char tag[20];
201	snprintf(tag, sizeof(tag), "PIN%d?", slot);
202	TypedList subj(allocator(), CSSM_WORDID_PIN,
203		new(allocator()) ListElement(slot),
204		new(allocator()) ListElement(status),
205		new(allocator()) ListElement(count));
206	add(subj, CSSM_WORDID_PIN, tag);
207}
208
209uint32 pinFromAclTag(const char *tag, const char *suffix /* = NULL */)
210{
211	if (tag) {
212		char format[20];
213		snprintf(format, sizeof(format), "PIN%%d%s%%n", suffix ? suffix : "");
214		uint32 pin;
215		unsigned consumed;
216		sscanf(tag, format, &pin, &consumed);
217		if (consumed == strlen(tag))	// complete and sufficient
218			return pin;
219	}
220	return 0;
221}
222
223}	// namespace Security
224