1/*
2 * Copyright (c) 2000-2004,2006,2011,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
25//
26// cssmcred - enhanced PodWrappers and construction aids for ACL credentials
27//
28#ifndef _CSSMCRED
29#define _CSSMCRED
30
31#include <security_utilities/utilities.h>
32#include <security_cdsa_utilities/cssmlist.h>
33#include <security_cdsa_utilities/cssmalloc.h>
34#include <list>
35
36namespace Security {
37
38
39//
40// PodWrappers for samples and sample groups
41//
42class CssmSample : public PodWrapper<CssmSample, CSSM_SAMPLE> {
43public:
44	CssmSample(const TypedList &list)
45	{ TypedSample = list; Verifier = NULL; }
46	CssmSample(const TypedList &list, const CssmSubserviceUid &ver)
47	{ TypedSample = list; Verifier = &ver; }
48
49	TypedList &value() { return TypedList::overlay(TypedSample); }
50	const TypedList &value() const { return TypedList::overlay(TypedSample); }
51	operator TypedList & () { return value(); }
52
53	const CssmSubserviceUid *verifier() const { return CssmSubserviceUid::overlay(Verifier); }
54	CssmSubserviceUid * &verifier()
55	{ return const_cast<CssmSubserviceUid * &>(CssmSubserviceUid::overlayVar(Verifier)); }
56};
57
58class SampleGroup : public PodWrapper<SampleGroup, CSSM_SAMPLEGROUP> {
59public:
60	SampleGroup() { clearPod(); }
61	SampleGroup(CssmSample &single)	{ NumberOfSamples = 1; Samples = &single; }
62
63	uint32 size() const { return NumberOfSamples; }
64	uint32 length() const { return size(); }	// legacy; prefer size()
65	CssmSample *&samples() { return CssmSample::overlayVar(const_cast<CSSM_SAMPLE *&>(Samples)); }
66	CssmSample *samples() const { return CssmSample::overlay(const_cast<CSSM_SAMPLE *>(Samples)); }
67
68	CssmSample &operator [] (uint32 ix) const
69	{ assert(ix < size()); return samples()[ix]; }
70
71public:
72	// extract all samples of a given sample type. return true if any found
73	// note that you get a shallow copy of the sample structures for temporary use ONLY
74	bool collect(CSSM_SAMPLE_TYPE sampleType, list<CssmSample> &samples) const;
75};
76
77
78//
79// The PodWrapper for the top-level CSSM credentials structure
80//
81class AccessCredentials : public PodWrapper<AccessCredentials, CSSM_ACCESS_CREDENTIALS> {
82public:
83	AccessCredentials() { clearPod(); }
84	explicit AccessCredentials(const SampleGroup &samples, const char *tag = NULL)
85	{ this->samples() = samples; this->tag(tag); }
86	explicit AccessCredentials(const SampleGroup &samples, const std::string &tag)
87	{ this->samples() = samples; this->tag(tag); }
88
89	const char *tag() const { return EntryTag[0] ? EntryTag : NULL; }
90	std::string s_tag() const { return EntryTag; }
91	void tag(const char *tagString);
92	void tag(const std::string &tagString) { return tag(tagString.c_str()); }
93
94	SampleGroup &samples() { return SampleGroup::overlay(Samples); }
95	const SampleGroup &samples() const { return SampleGroup::overlay(Samples); }
96
97	// pass-throughs to our SampleGroup
98	uint32 size() const { return samples().size(); }
99	CssmSample &operator [] (uint32 ix) const { return samples()[ix]; }
100
101public:
102    static const AccessCredentials &null;	// all null credential
103
104	// turn NULL into a null credential if needed
105	static const AccessCredentials *needed(const CSSM_ACCESS_CREDENTIALS *cred)
106	{ return cred ? overlay(cred) : &null; }
107};
108
109
110//
111// An AccessCredentials object with some construction help.
112// Note that this is NOT a PodWrapper.
113//
114class AutoCredentials : public AccessCredentials {
115public:
116	AutoCredentials(Allocator &alloc);
117	AutoCredentials(Allocator &alloc, uint32 nSamples);
118
119	Allocator &allocator;
120
121	CssmSample &sample(uint32 n) { return getSample(n); }
122
123	CssmSample &append(const CssmSample &sample)
124	{ return getSample(samples().length()) = sample; }
125	TypedList &append(const TypedList &exhibit)
126	{ return (getSample(samples().length()) = exhibit).value(); }
127
128	CssmSample &operator += (const CssmSample &sample)	{ return append(sample); }
129	TypedList &operator += (const TypedList &exhibit)	{ return append(exhibit); }
130
131private:
132	void init();
133	CssmSample &getSample(uint32 n);
134
135	CssmSample *sampleArray;
136	uint32 nSamples;
137};
138
139
140//
141// Walkers for the CSSM API structure types.
142// Note that there are irrational "const"s strewn about the credential sub-structures.
143// They make it essentially impossible to incrementally construction them without
144// violating them. Since we know what we're doing, we do.
145//
146namespace DataWalkers
147{
148
149// CssmSample (with const override)
150template <class Action>
151void walk(Action &operate, CssmSample &sample)
152{
153	operate(sample);
154	walk(operate, sample.value());
155	if (sample.verifier())
156		walk(operate, sample.verifier());
157}
158
159// SampleGroup
160template <class Action>
161void walk(Action &operate, SampleGroup &samples)
162{
163	operate(samples);
164	enumerateArray(operate, samples, &SampleGroup::samples);
165}
166
167// AccessCredentials
168template <class Action>
169AccessCredentials *walk(Action &operate, AccessCredentials * &cred)
170{
171	operate(cred);
172	//@@@ ignoring BaseCerts
173	walk(operate, cred->samples());
174	//@@@ ignoring challenge callback
175	return cred;
176}
177
178template <class Action>
179CSSM_ACCESS_CREDENTIALS *walk(Action &operate, CSSM_ACCESS_CREDENTIALS * &cred)
180{ return walk(operate, AccessCredentials::overlayVar(cred)); }
181
182template <class Action>
183AutoCredentials *walk(Action &operate, AutoCredentials * &cred)
184{ return (AutoCredentials *)walk(operate, (AccessCredentials * &)cred); }
185
186
187} // end namespace DataWalkers
188} // end namespace Security
189
190
191#endif //_CSSMCRED
192