#ifndef _H_CONTEXT
#define _H_CONTEXT
#include <security_utilities/utilities.h>
#include <security_utilities/debugging.h>
#include <security_cdsa_utilities/cssmalloc.h>
#include <security_cdsa_utilities/cssmwalkers.h>
#include <security_cdsa_utilities/cssmacl.h> // to serialize/copy access credentials
#include <security_cdsa_utilities/cssmdates.h>
namespace Security {
class Context : public PodWrapper<Context, CSSM_CONTEXT> {
public:
Context(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS algorithmId);
uint32 attributesInUse() const { return NumberOfAttributes; }
CSSM_CONTEXT_TYPE type() const { return ContextType; }
CSSM_ALGORITHMS algorithm() const { return AlgorithmType; }
CSSM_CSP_HANDLE cspHandle() const { return CSPHandle; }
void deleteAttribute(CSSM_ATTRIBUTE_TYPE type);
size_t copyAttributes(CSSM_CONTEXT_ATTRIBUTE * &attrs, uint32 &count, Allocator &alloc) const;
void copyFrom(const Context &source, Allocator &alloc)
{ source.copyAttributes(ContextAttributes, NumberOfAttributes, alloc); }
public:
class Attr : public PodWrapper<Attr, CSSM_CONTEXT_ATTRIBUTE> {
public:
Attr() { }
Attr(const CSSM_CONTEXT_ATTRIBUTE &attr) { (CSSM_CONTEXT_ATTRIBUTE &)*this = attr; }
template <class T>
Attr(CSSM_ATTRIBUTE_TYPE typ, T &value, size_t size = 0)
{
AttributeType = typ;
Attribute.String = const_cast<char *>(reinterpret_cast<const char *>(&value));
AttributeLength = (uint32_t) (size ? size : sizeof(T));
}
Attr(CSSM_ATTRIBUTE_TYPE typ, uint32 value)
{
AttributeType = typ;
Attribute.Uint32 = value;
AttributeLength = 0;
}
CSSM_ATTRIBUTE_TYPE type() const { return AttributeType; }
uint32 baseType() const { return AttributeType & CSSM_ATTRIBUTE_TYPE_MASK; }
operator char * () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_STRING); return Attribute.String; }
operator CssmData & () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_CSSM_DATA);
return CssmData::overlay(*Attribute.Data); }
operator CssmCryptoData & () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_CRYPTO_DATA);
return CssmCryptoData::overlay(*Attribute.CryptoData); }
operator CssmKey & () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_KEY); return CssmKey::overlay(*Attribute.Key); }
operator AccessCredentials & () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS);
return AccessCredentials::overlay(*Attribute.AccessCredentials); }
operator uint32 () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_UINT32); return Attribute.Uint32; }
operator CSSM_DL_DB_HANDLE &() const
{
assert(baseType() == CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE);
if (Attribute.DLDBHandle == NULL)
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE);
return *Attribute.DLDBHandle;
}
operator CssmDate & () const
{ assert(baseType() == CSSM_ATTRIBUTE_DATA_DATE);
return CssmDate::overlay(*Attribute.Date); }
void operator = (uint32 value) { Attribute.Uint32 = value; }
template <class T>
void operator = (T *ptr) { Attribute.String = reinterpret_cast<char *>(ptr); }
IFDUMP(void dump() const;) };
Attr *attributes() const { return Attr::overlay(ContextAttributes); }
Attr &operator [] (unsigned int ix)
{ assert(ix < NumberOfAttributes); return static_cast<Attr &>(ContextAttributes[ix]); }
const Attr &operator [] (unsigned int ix) const
{ assert(ix < NumberOfAttributes); return static_cast<Attr &>(ContextAttributes[ix]); }
Attr *find(CSSM_ATTRIBUTE_TYPE theType) const
{ return find(theType, ContextAttributes, NumberOfAttributes); }
template <class Elem>
Elem &get(CSSM_ATTRIBUTE_TYPE type, CSSM_RETURN err) const
{
if (Attr *attr = find(type))
return static_cast<Elem &>(*attr);
else
CssmError::throwMe(err);
}
template <class Elem>
Elem *get(CSSM_ATTRIBUTE_TYPE type) const
{
if (Attr *attr = find(type))
return &static_cast<Elem &>(*attr);
else
return NULL;
}
uint32 getInt(CSSM_ATTRIBUTE_TYPE type, CSSM_RETURN err) const
{
if (Attr *attr = find(type))
return static_cast<uint32>(*attr);
else
CssmError::throwMe(err);
}
uint32 getInt(CSSM_ATTRIBUTE_TYPE type) const
{
if (Attr *attr = find(type))
return static_cast<uint32>(*attr);
else
return 0;
}
bool getInt(CSSM_ATTRIBUTE_TYPE type, uint32 &value) const
{
if (Attr *attr = find(type)) {
value = static_cast<uint32>(*attr);
return true;
} else
return false;
}
public:
template <class T>
void replace(CSSM_ATTRIBUTE_TYPE type, const T &newValue) const
{
if (Attr *attr = find(type))
*attr = Attr(type, newValue);
else
CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT);
}
public:
void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc)
{ return alloc.malloc(size); }
void operator delete (void *addr, size_t, Allocator &alloc) throw()
{ return alloc.free(addr); }
static void destroy(Context *context, Allocator &alloc) throw()
{ alloc.free(context->ContextAttributes); alloc.free(context); }
public:
void postIPC(void *base, CSSM_CONTEXT_ATTRIBUTE *ipcAttributes);
public:
class Builder;
IFDUMP(void dump(const char *title = NULL,
const CSSM_CONTEXT_ATTRIBUTE *attrs = NULL) const;)
protected:
static Attr *find(CSSM_ATTRIBUTE_TYPE theType,
const CSSM_CONTEXT_ATTRIBUTE *attrs, unsigned int count);
};
namespace DataWalkers {
template <class Action>
void walk(Action &operate, CSSM_CONTEXT_ATTRIBUTE &attr)
{
operate(attr);
if (attr.Attribute.String) switch (attr.AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) {
case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
walk(operate, attr.Attribute.Data); break;
case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
walk(operate, attr.Attribute.CryptoData); break;
case CSSM_ATTRIBUTE_DATA_KEY:
walk(operate, attr.Attribute.Key); break;
case CSSM_ATTRIBUTE_DATA_STRING:
walk(operate, attr.Attribute.String); break;
case CSSM_ATTRIBUTE_DATA_DATE:
walk(operate, attr.Attribute.Date); break;
case CSSM_ATTRIBUTE_DATA_RANGE:
walk(operate, attr.Attribute.Range); break;
case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS:
walk(operate, attr.Attribute.AccessCredentials); break;
case CSSM_ATTRIBUTE_DATA_VERSION:
walk(operate, attr.Attribute.Version); break;
case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE:
walk(operate, attr.Attribute.DLDBHandle); break;
case CSSM_ATTRIBUTE_NONE:
case CSSM_ATTRIBUTE_DATA_UINT32:
break;
default:
secdebug("walkers", "invalid attribute (%ux) in context", (unsigned)attr.AttributeType);
break;
}
}
template <class Action>
void walk(Action &operate, Context::Attr &attr)
{
walk(operate, static_cast<CSSM_CONTEXT_ATTRIBUTE &>(attr));
}
}
using namespace DataWalkers;
class Context::Builder {
protected:
public:
Builder(Allocator &alloc) : allocator(alloc)
{ slotCount = 0; attributes = NULL; }
~Builder() { allocator.free(attributes); }
Allocator &allocator;
size_t make();
void done(CSSM_CONTEXT_ATTRIBUTE * &attributes, uint32 &count);
public:
template <class T>
void setup(T p, CSSM_RETURN invalidError = CSSM_OK)
{
if (p) {
slotCount++;
walk(sizer, unconst_ref_cast(p));
} else if (invalidError)
CssmError::throwMe(invalidError);
}
void setup(uint32 n, CSSM_RETURN invalidError = CSSM_OK)
{
if (n)
slotCount++;
else if (invalidError)
CssmError::throwMe(invalidError);
}
void setup(CSSM_SIZE n, CSSM_RETURN invalidError = CSSM_OK)
{
if (n)
slotCount++;
else if (invalidError)
CssmError::throwMe(invalidError);
}
void setup(const CSSM_CONTEXT_ATTRIBUTE &attr)
{ slotCount++; walk(sizer, const_cast<CSSM_CONTEXT_ATTRIBUTE &>(attr)); }
void setup(const Context::Attr &attr) { setup(static_cast<const CSSM_CONTEXT_ATTRIBUTE &>(attr)); }
template <class T>
void put(CSSM_ATTRIBUTE_TYPE type, const T *p)
{
if (p) {
assert(slot < slotCount); Attr &attribute = attributes[slot++];
attribute.AttributeType = type;
attribute.AttributeLength = (uint32)size(p); T *tmp = const_cast<T *>(p);
attribute = walk(copier, tmp);
}
}
void put(CSSM_ATTRIBUTE_TYPE type, uint32 value)
{
if (value) {
assert(slot < slotCount); Attr &attribute = attributes[slot++];
attribute.AttributeType = type;
attribute.AttributeLength = 0; attribute = value; }
}
void put(const CSSM_CONTEXT_ATTRIBUTE &attr)
{
assert(slot < slotCount);
Attr &attribute = attributes[slot++];
attribute = attr; walk(copier, attribute); }
void put(const Context::Attr &attr) { put(static_cast<const CSSM_CONTEXT_ATTRIBUTE &>(attr)); }
private:
unsigned slotCount; SizeWalker sizer;
Context::Attr *attributes; CopyWalker copier; uint32 slot; };
}
#endif //_H_CONTEXT