1/*
2 * Copyright (c) 2000-2006,2011-2012,2014 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#include <security_cdsa_utilities/AuthorizationData.h>
25#include <security_cdsa_utilities/AuthorizationWalkers.h>
26#include <security_cdsa_utilities/walkers.h>
27#include <Security/checkpw.h>
28#include <grp.h>
29#include <pwd.h>
30
31
32// checkpw() that uses provided struct passwd
33extern "C"
34{
35int checkpw_internal( const struct passwd *pw, const char* password );
36}
37
38
39namespace Authorization {
40
41
42AuthValueRef::AuthValueRef(const AuthValue &value) :
43	RefPointer<AuthValue>(new AuthValue(value)) {}
44
45AuthValueRef::AuthValueRef(const AuthorizationValue &value) :
46	RefPointer<AuthValue>(new AuthValue(value)) {}
47
48AuthValue::AuthValue(const AuthorizationValue &value) :
49    mOwnsValue(false)
50{
51    mValue.length = value.length;
52    mValue.data = value.data;
53}
54
55AuthValueRef::AuthValueRef(UInt32 length, void *data) :
56	RefPointer<AuthValue>(new AuthValue(length, data)) {}
57
58AuthValue::AuthValue(UInt32 length, void *data) :
59    mOwnsValue(true)
60{
61    mValue.length = length;
62    mValue.data = new uint8_t[length];
63    if (length)
64        memcpy(mValue.data, data, length);
65}
66
67AuthValue::~AuthValue()
68{
69    if (mOwnsValue)
70	{
71		memset(mValue.data, 0, mValue.length);
72        delete[] reinterpret_cast<uint8_t*>(mValue.data);
73	}
74}
75
76AuthValue &
77AuthValue::operator = (const AuthValue &other)
78{
79    if (mOwnsValue)
80	{
81		memset(mValue.data, 0 , mValue.length);
82        delete[] reinterpret_cast<uint8_t*>(mValue.data);
83	}
84
85    mValue = other.mValue;
86    mOwnsValue = other.mOwnsValue;
87    other.mOwnsValue = false;
88    return *this;
89}
90
91void
92AuthValue::fillInAuthorizationValue(AuthorizationValue &value)
93{
94    value.length = mValue.length;
95    value.data = mValue.data;
96}
97
98AuthValueVector &
99AuthValueVector::operator = (const AuthorizationValueVector& valueVector)
100{
101    clear();
102    for (unsigned int i=0; i < valueVector.count; i++)
103        push_back(AuthValueRef(valueVector.values[i]));
104    return *this;
105}
106
107void
108AuthValueVector::copy(AuthorizationValueVector **data, size_t *length) const
109{
110    AuthorizationValueVector valueVector;
111    valueVector.count = (UInt32)size();
112    valueVector.values = new AuthorizationValue[valueVector.count];
113    int i = 0;
114	for (const_iterator it = begin(); it != end(); ++it, ++i)
115    {
116		(*it)->fillInAuthorizationValue(valueVector.values[i]);
117	}
118
119	DataWalkers::Copier<AuthorizationValueVector> flatValueVector(&valueVector);
120	*length = flatValueVector.length();
121	*data = flatValueVector.keep();
122
123	delete[] valueVector.values;
124}
125
126AuthItem::AuthItem(const AuthorizationItem &item) :
127    mFlags(item.flags),
128    mOwnsName(true),
129    mOwnsValue(true)
130{
131	if (!item.name)
132		MacOSError::throwMe(errAuthorizationInternal);
133	size_t nameLen = strlen(item.name) + 1;
134	mName = new char[nameLen];
135	memcpy(const_cast<char *>(mName), item.name, nameLen);
136
137	mValue.length = item.valueLength;
138	mValue.data = new uint8_t[item.valueLength];
139	if (mValue.length)
140		memcpy(mValue.data, item.value, item.valueLength);
141}
142
143
144AuthItem::AuthItem(AuthorizationString name) :
145    mName(name),
146    mFlags(0),
147    mOwnsName(false),
148    mOwnsValue(false)
149{
150    mValue.length = 0;
151    mValue.data = NULL;
152}
153
154AuthItem::AuthItem(AuthorizationString name, AuthorizationValue value, AuthorizationFlags flags) :
155    mFlags(flags),
156    mOwnsName(true),
157    mOwnsValue(true)
158{
159	if (!name)
160		MacOSError::throwMe(errAuthorizationInternal);
161	size_t nameLen = strlen(name) + 1;
162	mName = new char[nameLen];
163	memcpy(const_cast<char *>(mName), name, nameLen);
164
165	mValue.length = value.length;
166	mValue.data = new uint8_t[value.length];
167	if (mValue.length)
168		memcpy(mValue.data, value.data, value.length);
169}
170
171AuthItem::~AuthItem()
172{
173    if (mOwnsName)
174        delete[] mName;
175    if (mOwnsValue)
176	{
177		memset(mValue.data, 0, mValue.length);
178        delete[] reinterpret_cast<uint8_t*>(mValue.data);
179	}
180}
181
182bool
183AuthItem::operator < (const AuthItem &other) const
184{
185    return strcmp(mName, other.mName) < 0;
186}
187
188AuthItem &
189AuthItem::operator = (const AuthItem &other)
190{
191    if (mOwnsName)
192        delete[] mName;
193    if (mOwnsValue)
194	{
195		memset(mValue.data, 0, mValue.length);
196        delete[] reinterpret_cast<uint8_t*>(mValue.data);
197	}
198
199    mName = other.mName;
200    mValue = other.mValue;
201    mFlags = other.mFlags;
202    mOwnsName = other.mOwnsName;
203    other.mOwnsName = false;
204    mOwnsValue = other.mOwnsValue;
205    other.mOwnsValue = false;
206    return *this;
207}
208
209void
210AuthItem::fillInAuthorizationItem(AuthorizationItem &item)
211{
212    item.name = mName;
213    item.valueLength = mValue.length;
214    item.value = mValue.data;
215    item.flags = mFlags;
216}
217
218bool
219AuthItem::getBool(bool &value)
220{
221	if (mValue.length == sizeof(bool))
222	{
223		bool *tmpValue = (bool *)mValue.data;
224
225		if (tmpValue)
226		{
227			value = *tmpValue;
228			return true;
229		}
230	}
231
232	return false;
233}
234
235bool
236AuthItem::getString(string &value)
237{
238    	value = string(static_cast<char*>(mValue.data), mValue.length);
239	return true;
240}
241
242bool
243AuthItem::getCssmData(CssmAutoData &value)
244{
245	value = CssmData(static_cast<uint8_t*>(mValue.data), mValue.length);
246	return true;
247}
248
249
250AuthItemRef::AuthItemRef(const AuthorizationItem &item) : RefPointer<AuthItem>(new AuthItem(item)) {}
251
252AuthItemRef::AuthItemRef(AuthorizationString name) : RefPointer<AuthItem>(new AuthItem(name)) {}
253
254AuthItemRef::AuthItemRef(AuthorizationString name, AuthorizationValue value, AuthorizationFlags flags) : RefPointer<AuthItem>(new AuthItem(name, value, flags)) {}
255
256
257//
258// AuthItemSet
259//
260AuthItemSet::AuthItemSet()
261: firstItemName(NULL)
262{
263}
264
265AuthItemSet::~AuthItemSet()
266{
267	if (NULL != firstItemName)
268		free(firstItemName);
269}
270
271AuthItemSet &
272AuthItemSet::operator = (const AuthorizationItemSet& itemSet)
273{
274    clear();
275
276    for (unsigned int i=0; i < itemSet.count; i++)
277        insert(AuthItemRef(itemSet.items[i]));
278
279    return *this;
280}
281
282AuthItemSet&
283AuthItemSet::operator=(const AuthItemSet& itemSet)
284{
285	std::set<AuthItemRef>::operator=(itemSet);
286
287	if (this != &itemSet) {
288		duplicate(itemSet);
289	}
290
291	return *this;
292}
293
294AuthItemSet::AuthItemSet(const AuthorizationItemSet *itemSet)
295: firstItemName(NULL)
296{
297	if (NULL != itemSet && NULL != itemSet->items)
298	{
299		if (0 < itemSet->count && NULL != itemSet->items[0].name)
300			firstItemName = strdup(itemSet->items[0].name);
301
302		for (unsigned int i=0; i < itemSet->count; i++)
303			insert(AuthItemRef(itemSet->items[i]));
304	}
305}
306
307AuthItemSet::AuthItemSet(const AuthItemSet& itemSet)
308: std::set<AuthItemRef>(itemSet)
309{
310	duplicate(itemSet);
311}
312
313void
314AuthItemSet::duplicate(const AuthItemSet& itemSet)
315{
316	if (itemSet.firstItemName != NULL)
317		firstItemName = strdup(itemSet.firstItemName);
318	else
319		firstItemName = NULL;
320}
321
322void
323AuthItemSet::copy(AuthorizationItemSet *&data, size_t &length, Allocator &alloc) const
324{
325    AuthorizationItemSet itemSet;
326    itemSet.count = (UInt32)size();
327    itemSet.items = new AuthorizationItem[itemSet.count];
328    int i = 0;
329    for (const_iterator it = begin(); it != end(); ++it, ++i)
330    {
331        (*it)->fillInAuthorizationItem(itemSet.items[i]);
332    }
333
334	DataWalkers::Copier<AuthorizationItemSet> flatItemSet(&itemSet, alloc);
335	length = flatItemSet.length();
336
337	data = flatItemSet.keep();
338	// else flatItemSet disappears again
339
340    delete[] itemSet.items;
341}
342
343AuthorizationItemSet *
344AuthItemSet::copy() const
345{
346	AuthorizationItemSet *aCopy;
347	size_t aLength;
348	copy(aCopy, aLength);
349	return aCopy;
350}
351
352AuthItem *
353AuthItemSet::find(const char *name)
354{
355	AuthItemSet::const_iterator found = find_if(this->begin(), this->end(), FindAuthItemByRightName(name) );
356	if (found != this->end())
357		return *found;
358
359	return NULL;
360}
361
362}	// end namespace Authorization
363