📄 dbms.h
字号:
/****************************************************************************
* *
* cryptlib DBMS Interface *
* Copyright Peter Gutmann 1996-2008 *
* *
****************************************************************************/
#include <stdarg.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#endif /* Compiler-specific includes */
/* The size of the ID fields, derived from the base64-encoded first 128 bits
of an SHA-1 hash. The field size value is also given in text form for
use in SQL strings */
#define DBXKEYID_SIZE 16 /* Full keyID = 128 bits */
#define ENCODED_DBXKEYID_SIZE 22 /* base64-encoded key ID */
#define TEXT_DBXKEYID_SIZE "22"
/* The maximum SQL query size */
#define MAX_SQL_QUERY_SIZE 256
/* When performing a query the database glue code limits the maximum returned
data size to a certain size, the following define allows us to declare a
fixed-size buffer that we know will always be big enough */
#define MAX_QUERY_RESULT_SIZE MAX_ENCODED_CERT_SIZE
/* Database status flags. These are:
FLAG_BINARYBLOBS: Database supports binary blobs.
FLAG_CERTSTORE/FLAG_CERTSTORE_FIELDS: Certificate stores are designated
by two flags, a main one for standard database/certificate store
differentiation and a secondary one that indicates that it's a
certificate store opened as a standard database, for example
when it's being used for read-only access with a key server. In
this case it's possible to perform extended queries on fields
that aren't present in standard databases so we set the
secondary flags to indicate that extended queries are possible
even though certificate store functionality isn't present.
FLAG_QUERYACTIVE: A query (returning a multiple-element result set) is
currently in progress.
FLAG_UPDATEACTIVE: An update is currently in progress. This is required
because we can sometimes run into a situation where an update
falls through to an abort without ever having been begun, this
happens if there's a sequence of miscellaneous setup operations
taking place and one of them fails before we begin the update.
Although it'd be better if the caller handled this, in practice
it'd mean passing extra status information (failed vs.failed but
need to abort a commenced update) across a number of different
functions, to avoid this we record whether an update has begun
and if not skip an abort operation if there's no update currently
in progress */
#define DBMS_FLAG_NONE 0x00 /* No DBMS flag */
#define DBMS_FLAG_BINARYBLOBS 0x01 /* DBMS supports blobs */
#define DBMS_FLAG_UPDATEACTIVE 0x02 /* Ongoing update in progress */
#define DBMS_FLAG_QUERYACTIVE 0x04 /* Ongoing query in progress */
#define DBMS_FLAG_CERTSTORE 0x08 /* Full certificate store */
#define DBMS_FLAG_CERTSTORE_FIELDS 0x10 /* Certificate store fields */
#define DBMS_FLAG_MAX 0x1F /* Maximum possible flag value */
/* Database feature information returned when the keyset is opened */
#define DBMS_FEATURE_FLAG_NONE 0x00 /* No DBMS features */
#define DBMS_FEATURE_FLAG_BINARYBLOBS 0x01 /* DBMS supports binary blobs */
#define DBMS_FEATURE_FLAG_READONLY 0x02 /* DBMS doesn't allow write access */
#define DBMS_FEATURE_FLAG_PRIVILEGES 0x04 /* DBMS supports GRANT/REVOKE */
#define DBMS_FEATURE_FLAG_MAX 0x07 /* Maximum possible flag value */
/* The certstore and binary blobs flags are checked often enough that we
define a macro for them */
#define hasBinaryBlobs( dbmsInfo ) \
( ( dbmsInfo )->flags & DBMS_FLAG_BINARYBLOBS )
#define isCertStore( dbmsInfo ) \
( ( dbmsInfo )->flags & DBMS_FLAG_CERTSTORE )
/* When we add or read information to/from a table we sometimes have to
specify type information which is an integer value, however SQL requires
that things be set out as character strings so we use the following
defines to provide the string form of the value for insertion into an SQL
query. Unfortunately we can't check this at compile time so we have to
check it via an assertion in the CA dispatch function */
#define TEXT_CERTTYPE_REQUEST_CERT "5"
#define TEXT_CERTTYPE_REQUEST_REVOCATION "6"
#define TEXT_CERTACTION_CREATE "1"
#define TEXTCH_CERTACTION_ADDUSER '5'
#define TEXT_CERTACTION_REQUEST_CERT "7"
#define TEXTCH_CERTACTION_REQUEST_CERT '7'
#define TEXT_CERTACTION_REQUEST_RENEWAL "8"
#define TEXTCH_CERTACTION_REQUEST_RENEWAL '8'
#define TEXT_CERTACTION_CERT_CREATION "10"
/* Special escape strings used in database keys to indicate that the value is
physically but not logically present. This is used to handle (currently-)
incomplete certificate issues and similar events where intermediate state
information has to be stored in the database but the object in question
isn't ready for use yet */
#define KEYID_ESC1 "--"
#define KEYID_ESC2 "##"
#define KEYID_ESC_SIZE 2
/* The ways in which we can add a certificate object to a table. Normally
we just add the certificate as is, however if we're awaiting confirmation
from a user before we can complete the certificate issue process we
perform a partial add that marks the certificate as not quite ready for
use yet. A variant of this is when we're renewing a certificate (i.e.
re-issuing it with the same key, which is really bad but required by some
certificate mismanagement protocols) in which case we have to process the
update as a multi-stage process because we're replacing an existing
certificate with one which is exactly the same as far as the uniqueness
constraints on the certificate store are concerned */
typedef enum {
CERTADD_NONE, /* No certificate-add operation */
CERTADD_NORMAL, /* Standard one-step add */
CERTADD_PARTIAL, /* Partial add */
CERTADD_PARTIAL_RENEWAL, /* Partial add with certificate replacement to follow */
CERTADD_RENEWAL_COMPLETE, /* Completion of renewal */
CERTADD_LAST /* Last valid certificate-add type */
} CERTADD_TYPE;
/* In order to make reporting of parameter errors in the multi-parameter
CA management function easier we provide symbolic defines mapping the
CA management-specific parameter type to its corresponding parameter
error type */
#define CAMGMT_ARGERROR_CAKEY CRYPT_ARGERROR_NUM1
#define CAMGMT_ARGERROR_REQUEST CRYPT_ARGERROR_NUM2
#define CAMGMT_ARGERROR_ACTION CRYPT_ARGERROR_VALUE
/* A structure to parse the database access information into so that it can
be used by backend-specific connect functions */
typedef struct {
BUFFER( CRYPT_MAX_TEXTSIZE, userLen ) \
char userBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
BUFFER_OPT( CRYPT_MAX_TEXTSIZE, userLen ) \
char *user;
BUFFER( CRYPT_MAX_TEXTSIZE, passwordLen ) \
char passwordBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
BUFFER_OPT( CRYPT_MAX_TEXTSIZE, passwordLen ) \
char *password;
BUFFER( CRYPT_MAX_TEXTSIZE, serverLen ) \
char serverBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
BUFFER_OPT( CRYPT_MAX_TEXTSIZE, serverLen ) \
char *server;
BUFFER( CRYPT_MAX_TEXTSIZE, nameLen ) \
char nameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
BUFFER_OPT( CRYPT_MAX_TEXTSIZE, nameLen ) \
char *name;
int userLen, passwordLen, serverLen, nameLen;
} DBMS_NAME_INFO;
/* To avoid SQL injection attacks and speed up performance we make extensive
use of bound parameters. The following structure is used to communicate
these parameters to the database back-end */
typedef enum {
BOUND_DATA_NONE, /* No bound data type */
BOUND_DATA_STRING, /* Character string */
BOUND_DATA_BLOB, /* Binary string */
BOUND_DATA_TIME, /* Date/time */
BOUND_DATA_LAST /* Last bound data type */
} BOUND_DATA_TYPE;
typedef struct {
BOUND_DATA_TYPE type; /* Type of this data item */
BUFFER_FIXED( dataLength ) \
const void *data; /* Data and data length */
int dataLength;
} BOUND_DATA;
#define BOUND_DATA_MAXITEMS 16
/* Macros to initialise the bound-data information. When we're binding
standard data values (i.e. non-blob data) the buffer to contain the value
is always present but if there's no data in it then the length will be
zero, so we perform a check for a buffer with a length of zero and set
the buffer pointer to NULL if this is the case */
#define initBoundData( boundData ) \
memset( ( boundData ), 0, sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS )
#define setBoundData( bdStorage, bdIndex, bdValue, bdValueLen ) \
{ \
const int bdLocalIndex = ( bdIndex ); \
\
( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_STRING; \
( bdStorage )[ bdLocalIndex ].data = ( bdValueLen > 0 ) ? bdValue : NULL; \
( bdStorage )[ bdLocalIndex ].dataLength = bdValueLen; \
}
#define setBoundDataBlob( bdStorage, bdIndex, bdValue, bdValueLen ) \
{ \
const int bdLocalIndex = ( bdIndex ); \
\
( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_BLOB; \
( bdStorage )[ bdLocalIndex ].data = bdValue; \
( bdStorage )[ bdLocalIndex ].dataLength = bdValueLen; \
}
#define setBoundDataDate( bdStorage, bdIndex, bdValue ) \
{ \
const int bdLocalIndex = ( bdIndex ); \
\
( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_TIME; \
( bdStorage )[ bdLocalIndex ].data = bdValue; \
( bdStorage )[ bdLocalIndex ].dataLength = sizeof( time_t ); \
}
/****************************************************************************
* *
* DBMS Access Macros *
* *
****************************************************************************/
/* Macros to make use of the DBMS access functions less painful. These
assume the existence of a variable 'dbmsInfo' that contains DBMS access
state information */
#define dbmsOpen( name, nameLen, options, featureFlags ) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -