#ifndef _SECURITYD_SECDBITEM_H_
#define _SECURITYD_SECDBITEM_H_
#include <CoreFoundation/CoreFoundation.h>
#include <TargetConditionals.h>
#include <corecrypto/ccsha1.h> // For CCSHA1_OUTPUT_SIZE
#include <sqlite3.h>
#include <utilities/SecCFError.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecDb.h>
#include <securityd/SecKeybagSupport.h>
#include <Security/SecAccessControl.h>
#include <Security/SecBasePriv.h>
typedef enum {
kSecDbBlobAttr, kSecDbDataAttr,
kSecDbStringAttr,
kSecDbNumberAttr,
kSecDbDateAttr,
kSecDbCreationDateAttr,
kSecDbModificationDateAttr,
kSecDbSHA1Attr,
kSecDbRowIdAttr,
kSecDbEncryptedDataAttr,
kSecDbPrimaryKeyAttr,
kSecDbSyncAttr,
kSecDbTombAttr,
kSecDbUTombAttr,
kSecDbAccessAttr,
kSecDbAccessControlAttr,
kSecDbUUIDAttr,
} SecDbAttrKind;
enum {
kSecDbPrimaryKeyFlag = (1 << 0), kSecDbInFlag = (1 << 1), kSecDbIndexFlag = (1 << 2), kSecDbSHA1ValueInFlag = (1 << 3), kSecDbReturnAttrFlag = (1 << 4),
kSecDbReturnDataFlag = (1 << 5),
kSecDbReturnRefFlag = (1 << 6),
kSecDbInCryptoDataFlag = (1 << 7),
kSecDbInHashFlag = (1 << 8),
kSecDbInBackupFlag = (1 << 9),
kSecDbDefault0Flag = (1 << 10), kSecDbDefaultEmptyFlag = (1 << 11), kSecDbNotNullFlag = (1 << 12), kSecDbInAuthenticatedDataFlag = (1 << 13), kSecDbSyncPrimaryKeyV0 = (1 << 14),
kSecDbSyncPrimaryKeyV2 = (1 << 15),
};
#define SecVersionDbFlag(v) ((v & 0xFF) << 8)
#define SecDbFlagGetVersion(flags) ((flags >> 8) & 0xFF)
#define SECDB_ATTR(var, name, kind, flags, copyValue, setValue) const SecDbAttr var = { CFSTR(name), kSecDb ## kind ## Attr, flags, copyValue, setValue }
typedef struct SecDbItem *SecDbItemRef;
typedef struct SecDbAttr SecDbAttr;
typedef CFTypeRef (*SecDbItemCopyAttrValue)(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error);
typedef bool (*SecDbItemSetAttrValue)(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value, CFErrorRef *error);
struct SecDbAttr {
CFStringRef name;
SecDbAttrKind kind;
CFOptionFlags flags;
SecDbItemCopyAttrValue copyValue;
SecDbItemSetAttrValue setValue;
};
typedef struct SecDbClass {
CFStringRef name;
const SecDbAttr *attrs[];
} SecDbClass;
typedef struct SecDbSchema {
int version;
const SecDbClass *classes[];
} SecDbSchema;
#define SecDbForEachAttr(class, attr) for (const SecDbAttr * const* _pattr = (class)->attrs, *attr = *_pattr; attr; attr = *(++_pattr))
#define SecDbForEachAttrWithMask(class, attr, flag_mask) SecDbForEachAttr(class, attr) if ((attr->flags & (flag_mask)) == (flag_mask))
CFTypeRef SecDbAttrCopyDefaultValue(const SecDbAttr *attr, CFErrorRef *error);
enum SecDbItemState {
kSecDbItemDirty, kSecDbItemEncrypted, kSecDbItemClean, kSecDbItemDecrypting, kSecDbItemEncrypting, kSecDbItemAlwaysEncrypted, };
struct SecDbItem {
CFRuntimeBase _base;
const SecDbClass *class;
keyclass_t keyclass;
keybag_handle_t keybag;
enum SecDbItemState _edataState;
CFMutableDictionaryRef attributes;
CFTypeRef credHandle;
CFTypeRef cryptoOp;
CFArrayRef callerAccessGroups;
};
bool SecDbItemDecrypt(SecDbItemRef item, CFDataRef edata, CFErrorRef *error);
CFTypeID SecDbItemGetTypeID(void);
static inline size_t SecDbClassAttrCount(const SecDbClass *dbClass) {
size_t n_attrs = 0;
SecDbForEachAttr(dbClass, attr) { n_attrs++; }
return n_attrs;
}
const SecDbAttr *SecDbClassAttrWithKind(const SecDbClass *class, SecDbAttrKind kind, CFErrorRef *error);
SecDbItemRef SecDbItemCreateWithAttributes(CFAllocatorRef allocator, const SecDbClass *class, CFDictionaryRef attributes, keybag_handle_t keybag, CFErrorRef *error);
const SecDbClass *SecDbItemGetClass(SecDbItemRef item);
keybag_handle_t SecDbItemGetKeybag(SecDbItemRef item);
bool SecDbItemSetKeybag(SecDbItemRef item, keybag_handle_t keybag, CFErrorRef *error);
void SecDbItemSetCredHandle(SecDbItemRef item, CFTypeRef cred_handle);
void SecDbItemSetCallerAccessGroups(SecDbItemRef item, CFArrayRef caller_access_groups);
CFTypeRef SecDbItemGetCachedValueWithName(SecDbItemRef item, CFStringRef name);
CFTypeRef SecDbItemGetValue(SecDbItemRef item, const SecDbAttr *desc, CFErrorRef *error);
bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value, CFErrorRef *error);
bool SecDbItemSetValues(SecDbItemRef item, CFDictionaryRef values, CFErrorRef *error);
bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef value, CFErrorRef *error);
sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error);
bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error);
bool SecDbItemClearRowId(SecDbItemRef item, CFErrorRef *error);
bool SecDbItemIsSyncableOrCorrupted(SecDbItemRef item);
bool SecDbItemIsSyncable(SecDbItemRef item);
bool SecDbItemSetSyncable(SecDbItemRef item, bool sync, CFErrorRef *error);
bool SecDbItemIsTombstone(SecDbItemRef item);
CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error);
CFDataRef SecDbItemGetPrimaryKey(SecDbItemRef item, CFErrorRef *error);
CFDataRef SecDbItemGetSHA1(SecDbItemRef item, CFErrorRef *error);
CFDataRef SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item, uint64_t handle, CFErrorRef *error);
SecDbItemRef SecDbItemCreateWithStatement(CFAllocatorRef allocator, const SecDbClass *class, sqlite3_stmt *stmt, keybag_handle_t keybag, CFErrorRef *error, bool (^return_attr)(const SecDbAttr *attr));
SecDbItemRef SecDbItemCreateWithEncryptedData(CFAllocatorRef allocator, const SecDbClass *class,
CFDataRef edata, keybag_handle_t keybag, CFErrorRef *error);
SecDbItemRef SecDbItemCreateWithPrimaryKey(CFAllocatorRef allocator, const SecDbClass *class, CFDataRef primary_key);
#if 0
SecDbItemRef SecDbItemCreateWithRowId(CFAllocatorRef allocator, const SecDbClass *class, sqlite_int64 row_id, keybag_handle_t keybag, CFErrorRef *error);
#endif
bool SecDbItemEnsureDecrypted(SecDbItemRef item, CFErrorRef *error);
SecDbItemRef SecDbItemCopyWithUpdates(SecDbItemRef item, CFDictionaryRef updates, CFErrorRef *error);
bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error, void(^duplicate)(SecDbItemRef item, SecDbItemRef *replace));
bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error);
bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, CFErrorRef *error);
bool SecDbItemDoDeleteSilently(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error);
bool SecDbItemDoUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, CFErrorRef *error, bool (^use_attr_in_where)(const SecDbAttr *attr));
bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, CFErrorRef *error);
void SecDbAppendElement(CFMutableStringRef sql, CFStringRef value, bool *needComma);
void SecDbAppendWhereOrAnd(CFMutableStringRef sql, bool *needWhere);
void SecDbAppendWhereOrAndEquals(CFMutableStringRef sql, CFStringRef col, bool *needWhere);
void SecDbAppendWhereOrAndNotEquals(CFMutableStringRef sql, CFStringRef col, bool *needWhere);
void SecDbAppendWhereOrAndIn(CFMutableStringRef sql, CFStringRef col, bool *needWhere, CFIndex count);
void SecDbAppendWhereOrAndNotIn(CFMutableStringRef sql, CFStringRef col, bool *needWhere, CFIndex count);
CFStringRef copyString(CFTypeRef obj);
CFDataRef copyData(CFTypeRef obj);
CFTypeRef copyBlob(CFTypeRef obj);
CFDataRef copySHA1(CFTypeRef obj);
CFTypeRef copyNumber(CFTypeRef obj);
CFDateRef copyDate(CFTypeRef obj);
CFTypeRef copyUUID(CFTypeRef obj);
static inline
bool SecErrorPropagate(CFErrorRef possibleError CF_CONSUMED, CFErrorRef *error) {
if (possibleError && error && *error && CFErrorGetCode(*error) == errSecAuthNeeded)
CFReleaseNull(*error);
return CFErrorPropagate(possibleError, error);
}
bool SecDbItemInV2(SecDbItemRef item);
bool SecDbItemInV2AlsoInV0(SecDbItemRef item);
__END_DECLS
#endif