]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2000-2004,2006-2007 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 | // acl_preauth - a subject type for modeling PINs and similar slot-specific | |
27 | // pre-authentication schemes. | |
28 | // | |
29 | #include "acl_preauth.h" | |
30 | #include <security_utilities/debugging.h> | |
31 | ||
32 | ||
33 | namespace Security { | |
34 | namespace PreAuthorizationAcls { | |
35 | ||
36 | ||
37 | // | |
38 | // Origin forms | |
39 | // | |
40 | AclSubject *OriginMaker::make(const TypedList &list) const | |
41 | { | |
42 | ListElement *args[1]; | |
43 | crack(list, 1, args, CSSM_LIST_ELEMENT_WORDID); | |
44 | return new OriginAclSubject(*args[0]); | |
45 | } | |
46 | ||
47 | AclSubject *OriginMaker::make(AclSubject::Version version, Reader &pub, Reader &) const | |
48 | { | |
49 | // just an integer containing the auth tag | |
50 | Endian<uint32> auth; | |
51 | pub(auth); | |
52 | return new OriginAclSubject(AclAuthorization(auth)); | |
53 | } | |
54 | ||
55 | ||
56 | // | |
57 | // Validate the origin form. | |
58 | // This tries to find the source AclObject and hands the question off to it. | |
59 | // If anything isn't right, fail the validation. | |
60 | // | |
61 | bool OriginAclSubject::validate(const AclValidationContext &ctx) const | |
62 | { | |
63 | if (Environment *env = ctx.environment<Environment>()) | |
64 | if (ObjectAcl *source = env->preAuthSource()) | |
65 | if (source->validates(mAuthTag, ctx.cred(), ctx.environment())) | |
66 | return true; | |
67 | ||
68 | // no joy (the sad default) | |
69 | return false; | |
70 | } | |
71 | ||
72 | ||
73 | CssmList OriginAclSubject::toList(Allocator &alloc) const | |
74 | { | |
75 | return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH, | |
76 | new(alloc) ListElement(mAuthTag)); | |
77 | } | |
78 | ||
79 | OriginAclSubject::OriginAclSubject(AclAuthorization auth) | |
80 | : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH), mAuthTag(auth) | |
81 | { | |
82 | if (auth < CSSM_ACL_AUTHORIZATION_PREAUTH_BASE || auth >= CSSM_ACL_AUTHORIZATION_PREAUTH_END) | |
83 | CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); | |
84 | } | |
85 | ||
86 | ||
87 | // | |
88 | // Origin exported form is just a four-byte integer (preauth authorization tag) | |
89 | // | |
90 | void OriginAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) | |
91 | { | |
92 | Endian<uint32> auth = mAuthTag; | |
93 | pub(auth); | |
94 | } | |
95 | ||
96 | void OriginAclSubject::exportBlob(Writer &pub, Writer &priv) | |
97 | { | |
98 | Endian<uint32> auth = mAuthTag; | |
99 | pub(auth); | |
100 | } | |
101 | ||
102 | ||
103 | // | |
104 | // Now for the other side of the coin. | |
105 | // SourceAclSubjects describe the unusual side (for ACL management) of this game. | |
106 | // The AclSubject of a preauth source MUST be of PREAUTH_SOURCE type. This subject | |
107 | // contains the actual validation conditions as a sub-subject, and may provide | |
108 | // additional information to represent known state of the preauth system. | |
109 | // | |
110 | // Think of the extra data in a PreAuthSource ACL as "current state informational" | |
111 | // that only exists internally, and in the CssmList view. It does not get put into | |
112 | // persistent (externalized) ACL storage at all. (After all, there's nothing persistent | |
113 | // about it.) | |
114 | // | |
115 | AclSubject *SourceMaker::make(const TypedList &list) const | |
116 | { | |
117 | // minimum requirement: item[1] = sub-subject (sublist) | |
118 | if (list.length() < 2) | |
119 | CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); | |
120 | ListElement &sub = list[1]; | |
121 | RefPointer<AclSubject> subSubject = ObjectAcl::make(sub); | |
122 | ||
123 | // anything else is interpreted as tracking state (defaulted if missing) | |
124 | switch (list.length()) { | |
125 | case 2: // no tracking state | |
126 | return new SourceAclSubject(subSubject); | |
127 | case 3: | |
128 | if (list[2].type() == CSSM_LIST_ELEMENT_WORDID) | |
129 | return new SourceAclSubject(subSubject, list[2]); | |
130 | // fall through | |
131 | default: | |
132 | CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); | |
133 | } | |
134 | } | |
135 | ||
136 | AclSubject *SourceMaker::make(AclSubject::Version version, Reader &pub, Reader &priv) const | |
137 | { | |
138 | // external form does not contain tracking state - defaults to unknown | |
139 | RefPointer<AclSubject> subSubject = ObjectAcl::importSubject(pub, priv); | |
140 | return new SourceAclSubject(subSubject); | |
141 | } | |
142 | ||
143 | ||
144 | // | |
145 | // Source validation uses its own home-cooked validation context. | |
146 | // | |
147 | class SourceValidationContext : public AclValidationContext { | |
148 | public: | |
149 | SourceValidationContext(const AclValidationContext &base) | |
150 | : AclValidationContext(base), mCredTag(base.entryTag()) { } | |
151 | ||
152 | uint32 count() const { return cred() ? cred()->samples().length() : 0; } | |
153 | uint32 size() const { return count(); } | |
154 | const TypedList &sample(uint32 n) const | |
155 | { assert(n < count()); return cred()->samples()[n]; } | |
156 | ||
157 | const char *credTag() const { return mCredTag; } // override | |
158 | ||
159 | void matched(const TypedList *) const { } //@@@ prelim | |
160 | ||
161 | private: | |
162 | const char *mCredTag; | |
163 | }; | |
164 | ||
165 | bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext &baseCtx) const | |
166 | { | |
167 | // try to authenticate our sub-subject | |
168 | if (Environment *env = baseCtx.environment<Environment>()) { | |
169 | AclAuthorization auth = baseCtx.authorization(); | |
170 | if (!CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth)) // all muddled up; bail | |
171 | CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); | |
172 | uint32 slot = CSSM_ACL_AUTHORIZATION_PREAUTH_SLOT(auth); | |
173 | secdebug("preauth", "using state %d@%p", slot, &env->store(this)); | |
427c49bc | 174 | bool &accepted = env->store(this).attachment<AclState>((void *)((size_t) slot)).accepted; |
b1ab9ed8 A |
175 | if (!accepted) { |
176 | secdebug("preauth", "%p needs to authenticate its subject", this); | |
177 | SourceValidationContext ctx(baseCtx); | |
178 | if (mSourceSubject->validate(ctx)) { | |
179 | secdebug("preauth", "%p pre-authenticated", this); | |
180 | accepted = true; | |
181 | } | |
182 | } | |
183 | return accepted; | |
184 | } | |
185 | return false; | |
186 | } | |
187 | ||
188 | ||
189 | CssmList SourceAclSubject::toList(Allocator &alloc) const | |
190 | { | |
191 | return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE, | |
192 | new(alloc) ListElement(mSourceSubject->toList(alloc))); | |
193 | } | |
194 | ||
195 | ||
196 | SourceAclSubject::SourceAclSubject(AclSubject *subSubject, CSSM_ACL_PREAUTH_TRACKING_STATE state) | |
197 | : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH), | |
198 | mSourceSubject(subSubject) | |
199 | { | |
200 | } | |
201 | ||
202 | ||
203 | // | |
204 | // Export the subject to a memory blob | |
205 | // | |
206 | void SourceAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) | |
207 | { | |
208 | mSourceSubject->exportBlob(pub, priv); | |
209 | } | |
210 | ||
211 | void SourceAclSubject::exportBlob(Writer &pub, Writer &priv) | |
212 | { | |
213 | mSourceSubject->exportBlob(pub, priv); | |
214 | // tracking state is not exported | |
215 | } | |
216 | ||
217 | ||
218 | #ifdef DEBUGDUMP | |
219 | ||
220 | void OriginAclSubject::debugDump() const | |
221 | { | |
222 | Debug::dump("Preauth(to slot %d)", mAuthTag - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE); | |
223 | } | |
224 | ||
225 | void SourceAclSubject::debugDump() const | |
226 | { | |
227 | Debug::dump("Preauth source: "); | |
228 | if (mSourceSubject) | |
229 | mSourceSubject->debugDump(); | |
230 | else | |
231 | Debug::dump("NULL?"); | |
232 | } | |
233 | ||
234 | #endif //DEBUGDUMP | |
235 | ||
236 | ||
237 | } // namespace PreAuthorizationAcls | |
238 | } // namespace Security |