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