#include "acl_preauth.h"
#include <security_utilities/debugging.h>
namespace Security {
namespace PreAuthorizationAcls {
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
{
Endian<uint32> auth;
pub(auth);
return new OriginAclSubject(AclAuthorization(auth));
}
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;
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);
}
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);
}
AclSubject *SourceMaker::make(const TypedList &list) const
{
if (list.length() < 2)
CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
ListElement &sub = list[1];
RefPointer<AclSubject> subSubject = ObjectAcl::make(sub);
switch (list.length()) {
case 2: return new SourceAclSubject(subSubject);
case 3:
if (list[2].type() == CSSM_LIST_ELEMENT_WORDID)
return new SourceAclSubject(subSubject, list[2]);
default:
CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
}
}
AclSubject *SourceMaker::make(AclSubject::Version version, Reader &pub, Reader &priv) const
{
RefPointer<AclSubject> subSubject = ObjectAcl::importSubject(pub, priv);
return new SourceAclSubject(subSubject);
}
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; }
void matched(const TypedList *) const { }
private:
const char *mCredTag;
};
bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext &baseCtx) const
{
if (Environment *env = baseCtx.environment<Environment>()) {
AclAuthorization auth = baseCtx.authorization();
if (!CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth)) 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)
{
}
void SourceAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv)
{
mSourceSubject->exportBlob(pub, priv);
}
void SourceAclSubject::exportBlob(Writer &pub, Writer &priv)
{
mSourceSubject->exportBlob(pub, priv);
}
#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
} }