#ifdef __MWERKS__
#define _CPP_ACL_THRESHOLD
#endif
#include <Security/acl_threshold.h>
#include <algorithm>
class SublistValidationContext : public AclValidationContext {
public:
SublistValidationContext(const AclValidationContext &ctx, const TypedList &list)
: AclValidationContext(ctx), sampleList(list) { }
uint32 count() const { return sampleList.length() - 1; }
const TypedList &sample(uint32 n) const
{ return TypedList::overlay(sampleList[n+1].list()); }
const TypedList &sampleList;
};
bool ThresholdAclSubject::validate(const AclValidationContext &baseCtx,
const TypedList &sample) const
{
#ifdef STRICTCOUNTING
uint32 subSampleCount = sample.length() - 1; if (subSampleCount < minimumNeeded) CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
if (subSampleCount > totalSubjects) CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
#endif //STRICTCOUNTING
SublistValidationContext ctx(baseCtx, sample);
uint32 matched = 0;
for (uint32 n = 0; n < totalSubjects; n++) {
if ((matched += elements[n]->validate(ctx)) >= minimumNeeded)
return true;
#ifdef STRICTCOUNTING
else if (matched + subSampleCount - n <= minimumNeeded)
return false; #endif //STRICTCOUNTING
}
return false;
}
CssmList ThresholdAclSubject::toList(CssmAllocator &alloc) const
{
TypedList result(alloc, CSSM_ACL_SUBJECT_TYPE_THRESHOLD,
new(alloc) ListElement(minimumNeeded),
new(alloc) ListElement(totalSubjects));
for (uint32 n = 0; n < totalSubjects; n++)
result += new(alloc) ListElement(elements[n]->toList(alloc));
return result;
}
ThresholdAclSubject *ThresholdAclSubject::Maker::make(const TypedList &list) const
{
if (list.length() < 4) CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
uint32 minimumNeeded = getWord(list[1], 1);
uint32 totalSubjects = getWord(list[2], minimumNeeded);
if (list.length() != 3 + totalSubjects)
CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
AclSubjectVector elements(totalSubjects);
const ListElement *subSubject = &list[3];
for (uint32 n = 0; n < totalSubjects; n++, subSubject = subSubject->next())
elements[n] = ObjectAcl::make(*subSubject);
return new ThresholdAclSubject(totalSubjects, minimumNeeded, elements);
}
ThresholdAclSubject *ThresholdAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const
{
uint32 totalSubjects; pub(totalSubjects);
uint32 minimumNeeded; pub(minimumNeeded);
AclSubjectVector subSubjects(totalSubjects);
for (uint32 n = 0; n < totalSubjects; n++)
subSubjects[n] = ObjectAcl::importSubject(pub, priv);
return new ThresholdAclSubject(totalSubjects, minimumNeeded, subSubjects);
}
ThresholdAclSubject::ThresholdAclSubject(uint32 n, uint32 k,
const AclSubjectVector &subSubjects)
: SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE_THRESHOLD, CSSM_SAMPLE_TYPE_THRESHOLD),
minimumNeeded(k), totalSubjects(n), elements(subSubjects)
{
}
template <class Action>
void ThresholdAclSubject::exportBlobForm(Action &pub, Action &priv)
{
pub(totalSubjects);
pub(minimumNeeded);
for (uint32 n = 0; n < totalSubjects; n++)
ObjectAcl::exportSubject(elements[n], pub, priv);
}
void ThresholdAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv)
{ exportBlobForm(pub, priv); }
void ThresholdAclSubject::exportBlob(Writer &pub, Writer &priv)
{ exportBlobForm(pub, priv); }
#ifdef DEBUGDUMP
void ThresholdAclSubject::debugDump() const
{
Debug::dump("Threshold(%ld of %ld)", minimumNeeded, totalSubjects);
for (unsigned int n = 0; n < elements.size(); n++) {
Debug::dump(" [");
if (Version v = elements[n]->version())
Debug::dump("V=%d ", v);
elements[n]->debugDump();
Debug::dump("]");
}
}
#endif //DEBUGDUMP