#ifndef _H_CONTEXT
#define _H_CONTEXT
#include <Security/utilities.h>
#include <Security/debugging.h>
#include <Security/cssmalloc.h>
#include <Security/cssmwalkers.h>
#include <Security/cssmacl.h> // to serialize/copy access credentials
#ifdef _CPP_CONTEXT
# pragma export on
#endif
namespace Security
{
class Context : public PodWrapper<Context, CSSM_CONTEXT> {
public:
Context(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS algorithmId)
{ ContextType = type; AlgorithmType = 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, CssmAllocator &alloc) const;
void copyFrom(const Context &source, CssmAllocator &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 = 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;
}
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, CssmAllocator &alloc) throw(std::bad_alloc)
{ return alloc.malloc(size); }
void operator delete (void *addr, size_t, CssmAllocator &alloc) throw()
{ return alloc.free(addr); }
static void destroy(Context *context, CssmAllocator &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)
{
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:
assert(false); }
}
}
using namespace DataWalkers;
class Context::Builder {
protected:
public:
Builder(CssmAllocator &alloc) : allocator(alloc)
{ slotCount = 0; attributes = NULL; }
~Builder() { allocator.free(attributes); }
CssmAllocator &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, p);
} 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 = size(p); attribute = walk(copier, p);
}
}
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; };
}
#ifdef _CPP_CONTEXT
# pragma export off
#endif
#endif //_H_CONTEXT