#ifndef _H_DATABASE
#define _H_DATABASE
#include "securityserver.h"
#include "acls.h"
#include "dbcrypto.h"
#include "notifications.h"
#include <Security/utilities.h>
#include <Security/handleobject.h>
#include <Security/cssmdb.h>
#include <Security/machserver.h>
#include "SecurityAgentClient.h"
#include <Security/timeflow.h>
#include <string>
#include <map>
class Key;
class Connection;
class Process;
using MachPlusPlus::MachServer;
class Database : public HandleObject, public SecurityServerAcl {
static const Listener::Event lockedEvent = Listener::lockedEvent;
static const Listener::Event unlockedEvent = Listener::unlockedEvent;
static const Listener::Event passphraseChangedEvent = Listener::passphraseChangedEvent;
public:
class Common; friend class Common;
Database(const DLDbIdentifier &id, const DBParameters ¶ms, Process &proc,
const AccessCredentials *cred, const AclEntryPrototype *owner);
virtual ~Database();
Process &process;
static const int maxUnlockTryCount = 3;
public:
typedef DbBlob::Signature Signature;
class DbIdentifier {
public:
DbIdentifier(const DLDbIdentifier &id, Signature sig)
: mIdent(id), mSig(sig) { }
operator const DLDbIdentifier &() const { return mIdent; }
operator const Signature &() const { return mSig; }
const char *dbName() const { return mIdent.dbName(); }
bool operator < (const DbIdentifier &id) const {
if (mIdent < id.mIdent) return true;
if (id.mIdent < mIdent) return false;
return mSig < id.mSig;
}
private:
DLDbIdentifier mIdent;
Signature mSig;
};
public:
class CommonMap : public map<DbIdentifier, Common *>, public Mutex {
};
public:
class Common : public DatabaseCryptoCore, public MachServer::Timer, public Mutex {
public:
Common(const DbIdentifier &id, CommonMap &pool);
~Common();
bool unlock(DbBlob *blob, void **privateAclBlob = NULL);
void lock(bool holdingCommonLock, bool forSleep = false); bool isLocked() const { return mIsLocked; } void activity();
void makeNewSecrets();
const DbIdentifier &identifier() const {return mIdentifier; }
const DLDbIdentifier &dlDbIdent() const { return identifier(); }
const char *dbName() const { return dlDbIdent().dbName(); }
DbBlob *encode(Database &db);
protected:
void action();
public:
CommonMap &pool;
DbIdentifier mIdentifier; uint32 sequence; DBParameters mParams;
uint32 useCount; uint32 version;
private:
bool mIsLocked; bool mValidParams; };
const DbIdentifier &identifier() const { return common->identifier(); }
const char *dbName() const { return common->dbName(); }
public:
DbBlob *blob();
Database(const DLDbIdentifier &id, const DbBlob *blob, Process &proc,
const AccessCredentials *cred);
void authenticate(const AccessCredentials *cred);
void changePassphrase(const AccessCredentials *cred);
Key *extractMasterKey(Database *db,
const AccessCredentials *cred, const AclEntryPrototype *owner,
uint32 usage, uint32 attrs);
void getDbIndex(CssmData &indexData);
void lock(); void unlock(); void unlock(const CssmData &passphrase);
bool decode(); bool decode(const CssmData &passphrase);
bool validatePassphrase(const CssmData &passphrase) const; bool isLocked() const { return common->isLocked(); }
void activity() const { common->activity(); } static void lockAllDatabases(CommonMap &commons, bool forSleep = false);
void decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl);
KeyBlob *encodeKey(const CssmKey &key, const CssmData &pubAcl, const CssmData &privAcl);
bool validBlob() const { return mBlob && version == common->version; }
void setParameters(const DBParameters ¶ms);
void getParameters(DBParameters ¶ms);
void instantiateAcl();
void changedAcl();
const Database *relatedDatabase() const;
IFDUMP(void debugDump(const char *msg));
protected:
void makeUnlocked(); void makeUnlocked(const AccessCredentials *cred); void makeUnlocked(const CssmData &passphrase);
void establishOldSecrets(const AccessCredentials *creds);
void establishNewSecrets(const AccessCredentials *creds, SecurityAgent::Reason reason);
static CssmClient::Key keyFromCreds(const TypedList &sample);
void encode();
static void discard(Common *common);
private:
Common *common;
bool mValidData;
uint32 version; DbBlob *mBlob;
AccessCredentials *mCred; };
class SystemKeychainKey {
public:
SystemKeychainKey(const char *path);
~SystemKeychainKey();
bool matches(const DbBlob::Signature &signature);
CssmKey &key() { return mKey; }
private:
std::string mPath; CssmKey mKey;
bool mValid; UnlockBlob mBlob;
Time::Absolute mCachedDate; Time::Absolute mUpdateThreshold;
static const int checkDelay = 1;
bool update();
};
#endif //_H_DATABASE