+++ /dev/null
-/*
- * Copyright (c) 2000-2004,2006-2007,2011,2013 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-
-//
-// acl_preauth - a subject type for modeling PINs and similar slot-specific
-// pre-authentication schemes.
-//
-#include "acl_preauth.h"
-#include <security_utilities/debugging.h>
-
-
-namespace Security {
-namespace PreAuthorizationAcls {
-
-
-//
-// Origin forms
-//
-AclSubject *OriginMaker::make(const TypedList &list) const
-{
- ListElement *args[1];
- crack(list, 1, args, CSSM_LIST_ELEMENT_WORDID);
- return new OriginAclSubject(*args[0]);
-}
-
-AclSubject *OriginMaker::make(AclSubject::Version version, Reader &pub, Reader &) const
-{
- // just an integer containing the auth tag
- Endian<uint32> auth;
- pub(auth);
- return new OriginAclSubject(AclAuthorization(auth));
-}
-
-
-//
-// Validate the origin form.
-// This tries to find the source AclObject and hands the question off to it.
-// If anything isn't right, fail the validation.
-//
-bool OriginAclSubject::validate(const AclValidationContext &ctx) const
-{
- if (Environment *env = ctx.environment<Environment>())
- if (ObjectAcl *source = env->preAuthSource())
- if (source->validates(mAuthTag, ctx.cred(), ctx.environment()))
- return true;
-
- // no joy (the sad default)
- return false;
-}
-
-
-CssmList OriginAclSubject::toList(Allocator &alloc) const
-{
- return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH,
- new(alloc) ListElement(mAuthTag));
-}
-
-OriginAclSubject::OriginAclSubject(AclAuthorization auth)
- : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH), mAuthTag(auth)
-{
- if (auth < CSSM_ACL_AUTHORIZATION_PREAUTH_BASE || auth >= CSSM_ACL_AUTHORIZATION_PREAUTH_END)
- CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
-}
-
-
-//
-// Origin exported form is just a four-byte integer (preauth authorization tag)
-//
-void OriginAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv)
-{
- Endian<uint32> auth = mAuthTag;
- pub(auth);
-}
-
-void OriginAclSubject::exportBlob(Writer &pub, Writer &priv)
-{
- Endian<uint32> auth = mAuthTag;
- pub(auth);
-}
-
-
-//
-// Now for the other side of the coin.
-// SourceAclSubjects describe the unusual side (for ACL management) of this game.
-// The AclSubject of a preauth source MUST be of PREAUTH_SOURCE type. This subject
-// contains the actual validation conditions as a sub-subject, and may provide
-// additional information to represent known state of the preauth system.
-//
-// Think of the extra data in a PreAuthSource ACL as "current state informational"
-// that only exists internally, and in the CssmList view. It does not get put into
-// persistent (externalized) ACL storage at all. (After all, there's nothing persistent
-// about it.)
-//
-AclSubject *SourceMaker::make(const TypedList &list) const
-{
- // minimum requirement: item[1] = sub-subject (sublist)
- if (list.length() < 2)
- CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
- ListElement &sub = list[1];
- RefPointer<AclSubject> subSubject = ObjectAcl::make(sub);
-
- // anything else is interpreted as tracking state (defaulted if missing)
- switch (list.length()) {
- case 2: // no tracking state
- return new SourceAclSubject(subSubject);
- case 3:
- if (list[2].type() == CSSM_LIST_ELEMENT_WORDID)
- return new SourceAclSubject(subSubject, list[2]);
- // fall through
- default:
- CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
- }
-}
-
-AclSubject *SourceMaker::make(AclSubject::Version version, Reader &pub, Reader &priv) const
-{
- // external form does not contain tracking state - defaults to unknown
- RefPointer<AclSubject> subSubject = ObjectAcl::importSubject(pub, priv);
- return new SourceAclSubject(subSubject);
-}
-
-
-//
-// Source validation uses its own home-cooked validation context.
-//
-class SourceValidationContext : public AclValidationContext {
-public:
- SourceValidationContext(const AclValidationContext &base)
- : AclValidationContext(base), mCredTag(base.entryTag()) { }
-
- uint32 count() const { return cred() ? cred()->samples().length() : 0; }
- uint32 size() const { return count(); }
- const TypedList &sample(uint32 n) const
- { assert(n < count()); return cred()->samples()[n]; }
-
- const char *credTag() const { return mCredTag; } // override
-
- void matched(const TypedList *) const { } //@@@ prelim
-
-private:
- const char *mCredTag;
-};
-
-bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext &baseCtx) const
-{
- // try to authenticate our sub-subject
- if (Environment *env = baseCtx.environment<Environment>()) {
- AclAuthorization auth = baseCtx.authorization();
- if (!CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth)) // all muddled up; bail
- CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
- uint32 slot = CSSM_ACL_AUTHORIZATION_PREAUTH_SLOT(auth);
- secdebug("preauth", "using state %d@%p", slot, &env->store(this));
- bool &accepted = env->store(this).attachment<AclState>((void *)((size_t) slot)).accepted;
- if (!accepted) {
- secdebug("preauth", "%p needs to authenticate its subject", this);
- SourceValidationContext ctx(baseCtx);
- if (mSourceSubject->validate(ctx)) {
- secdebug("preauth", "%p pre-authenticated", this);
- accepted = true;
- }
- }
- return accepted;
- }
- return false;
-}
-
-
-CssmList SourceAclSubject::toList(Allocator &alloc) const
-{
- return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE,
- new(alloc) ListElement(mSourceSubject->toList(alloc)));
-}
-
-
-SourceAclSubject::SourceAclSubject(AclSubject *subSubject, CSSM_ACL_PREAUTH_TRACKING_STATE state)
- : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH),
- mSourceSubject(subSubject)
-{
-}
-
-
-//
-// Export the subject to a memory blob
-//
-void SourceAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv)
-{
- mSourceSubject->exportBlob(pub, priv);
-}
-
-void SourceAclSubject::exportBlob(Writer &pub, Writer &priv)
-{
- mSourceSubject->exportBlob(pub, priv);
- // tracking state is not exported
-}
-
-
-#ifdef DEBUGDUMP
-
-void OriginAclSubject::debugDump() const
-{
- Debug::dump("Preauth(to slot %d)", mAuthTag - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE);
-}
-
-void SourceAclSubject::debugDump() const
-{
- Debug::dump("Preauth source: ");
- if (mSourceSubject)
- mSourceSubject->debugDump();
- else
- Debug::dump("NULL?");
-}
-
-#endif //DEBUGDUMP
-
-
-} // namespace PreAuthorizationAcls
-} // namespace Security