2 * Copyright (c) 2000-2004,2006-2007,2011,2013 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // acl_preauth - a subject type for modeling PINs and similar slot-specific
27 // pre-authentication schemes.
29 #include "acl_preauth.h"
30 #include <security_utilities/debugging.h>
34 namespace PreAuthorizationAcls
{
40 AclSubject
*OriginMaker::make(const TypedList
&list
) const
43 crack(list
, 1, args
, CSSM_LIST_ELEMENT_WORDID
);
44 return new OriginAclSubject(*args
[0]);
47 AclSubject
*OriginMaker::make(AclSubject::Version version
, Reader
&pub
, Reader
&) const
49 // just an integer containing the auth tag
52 return new OriginAclSubject(AclAuthorization(auth
));
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.
61 bool OriginAclSubject::validate(const AclValidationContext
&ctx
) const
63 if (Environment
*env
= ctx
.environment
<Environment
>())
64 if (ObjectAcl
*source
= env
->preAuthSource())
65 if (source
->validates(mAuthTag
, ctx
.cred(), ctx
.environment()))
68 // no joy (the sad default)
73 CssmList
OriginAclSubject::toList(Allocator
&alloc
) const
75 return TypedList(alloc
, CSSM_ACL_SUBJECT_TYPE_PREAUTH
,
76 new(alloc
) ListElement(mAuthTag
));
79 OriginAclSubject::OriginAclSubject(AclAuthorization auth
)
80 : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH
), mAuthTag(auth
)
82 if (auth
< CSSM_ACL_AUTHORIZATION_PREAUTH_BASE
|| auth
>= CSSM_ACL_AUTHORIZATION_PREAUTH_END
)
83 CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE
);
88 // Origin exported form is just a four-byte integer (preauth authorization tag)
90 void OriginAclSubject::exportBlob(Writer::Counter
&pub
, Writer::Counter
&priv
)
92 Endian
<uint32
> auth
= mAuthTag
;
96 void OriginAclSubject::exportBlob(Writer
&pub
, Writer
&priv
)
98 Endian
<uint32
> auth
= mAuthTag
;
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.
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
115 AclSubject
*SourceMaker::make(const TypedList
&list
) const
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
);
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
);
128 if (list
[2].type() == CSSM_LIST_ELEMENT_WORDID
)
129 return new SourceAclSubject(subSubject
, list
[2]);
132 CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE
);
136 AclSubject
*SourceMaker::make(AclSubject::Version version
, Reader
&pub
, Reader
&priv
) const
138 // external form does not contain tracking state - defaults to unknown
139 RefPointer
<AclSubject
> subSubject
= ObjectAcl::importSubject(pub
, priv
);
140 return new SourceAclSubject(subSubject
);
145 // Source validation uses its own home-cooked validation context.
147 class SourceValidationContext
: public AclValidationContext
{
149 SourceValidationContext(const AclValidationContext
&base
)
150 : AclValidationContext(base
), mCredTag(base
.entryTag()) { }
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
]; }
157 const char *credTag() const { return mCredTag
; } // override
159 void matched(const TypedList
*) const { } //@@@ prelim
162 const char *mCredTag
;
165 bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext
&baseCtx
) const
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));
174 bool &accepted
= env
->store(this).attachment
<AclState
>((void *)((size_t) slot
)).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);
189 CssmList
SourceAclSubject::toList(Allocator
&alloc
) const
191 return TypedList(alloc
, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE
,
192 new(alloc
) ListElement(mSourceSubject
->toList(alloc
)));
196 SourceAclSubject::SourceAclSubject(AclSubject
*subSubject
, CSSM_ACL_PREAUTH_TRACKING_STATE state
)
197 : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH
),
198 mSourceSubject(subSubject
)
204 // Export the subject to a memory blob
206 void SourceAclSubject::exportBlob(Writer::Counter
&pub
, Writer::Counter
&priv
)
208 mSourceSubject
->exportBlob(pub
, priv
);
211 void SourceAclSubject::exportBlob(Writer
&pub
, Writer
&priv
)
213 mSourceSubject
->exportBlob(pub
, priv
);
214 // tracking state is not exported
220 void OriginAclSubject::debugDump() const
222 Debug::dump("Preauth(to slot %d)", mAuthTag
- CSSM_ACL_AUTHORIZATION_PREAUTH_BASE
);
225 void SourceAclSubject::debugDump() const
227 Debug::dump("Preauth source: ");
229 mSourceSubject
->debugDump();
231 Debug::dump("NULL?");
237 } // namespace PreAuthorizationAcls
238 } // namespace Security