📄 dbxdbms.c
字号:
else
{
cmd.noStrArgs = 0;
argIndex = 0;
}
if( date )
{
#ifndef _BIG_WORDS
assert( sizeof( time_t ) <= 4 );
#endif /* !_BIG_WORDS */
/* Encode the date as a 64-bit value */
memset( encodedDate, 0, 8 );
#ifdef _BIG_WORDS
encodedDate[ 3 ] = ( BYTE )( ( date >> 32 ) & 0xFF );
#endif /* _BIG_WORDS */
encodedDate[ 4 ] = ( BYTE )( ( date >> 24 ) & 0xFF );
encodedDate[ 5 ] = ( BYTE )( ( date >> 16 ) & 0xFF );
encodedDate[ 6 ] = ( BYTE )( ( date >> 8 ) & 0xFF );
encodedDate[ 7 ] = ( BYTE )( ( date ) & 0xFF );
cmd.strArg[ 1 ] = encodedDate;
cmd.strArgLen[ 1 ] = 8;
cmd.noStrArgs++;
argIndex++;
}
cmd.strArg[ argIndex ] = data;
cmd.strArgLen[ argIndex ] = 0;
status = dispatchCommand( &cmd, dbmsInfo->stateInfo,
dbmsInfo->dispatchFunction );
if( cryptStatusOK( status ) )
{
if( queryType == DBMS_QUERY_START )
dbmsInfo->flags |= DBMS_FLAG_QUERYACTIVE;
if( queryType == DBMS_QUERY_CANCEL )
dbmsInfo->flags &= ~DBMS_FLAG_QUERYACTIVE;
if( dataLength != NULL )
*dataLength = cmd.strArgLen[ 0 ];
}
else
{
if( ( queryType == DBMS_QUERY_CONTINUE ) && \
( status == CRYPT_ERROR_COMPLETE ) )
dbmsInfo->flags &= ~DBMS_FLAG_QUERYACTIVE;
performErrorQuery( dbmsInfo );
}
return( status );
}
static int performStaticQuery( DBMS_INFO *dbmsInfo, const char *command,
const DBMS_QUERY_TYPE queryType )
{
return( performQuery( dbmsInfo, command, NULL, NULL, 0, queryType ) );
}
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* The escape char used to escape potentially dangerous values in SQL
strings */
#define SQL_ESCAPE '\''
/* Format input parameters into SQL queries suitable for submission to the
DBMS backend, with assorted safety checks of the query data */
void dbmsFormatSQL( char *buffer, const char *format, ... )
{
va_list argPtr;
char *formatPtr = ( char * ) format;
int bufPos = 0;
va_start( argPtr, format );
while( *formatPtr )
{
if( *formatPtr == '$' )
{
char *strPtr = va_arg( argPtr, char * );
assert( strPtr != NULL ); /* Catch a shortage of args */
/* Copy the string to the output buffer with conversion of any
special characters which are used by SQL */
while( *strPtr )
{
int ch = *strPtr++;
/* If it's a control character, skip it */
if( ( ch & 0x7F ) < ' ' )
continue;
/* Escape metacharacters which could be misused in queries,
for example by specifying a key 'foo; DROP TABLE bar' or
similar shenanigans. We catch the obvious ' and ;, as
well as the less obvious %, which could be used to hide
other metacharacters. Note that none of these characters
are valid in base64, which makes it safe to escape them
in the few instances where they do occur */
if( ch == '\'' || ch == '\\' || ch == ';' || ch == '%' )
/* Escape the character */
buffer[ bufPos++ ] = SQL_ESCAPE;
#ifdef __WINDOWS__
/* Bypass a Microsoft ODBC "enhancement" in which the driver
will execute anything delimited by '|'s as an expression
(an example being '|shell("cmd /c echo " & chr(124) &
" format c:")|'). Because of this we strip gazintas if
we're running under Windoze */
if( ch != '|' )
#endif /* __WINDOWS__ */
buffer[ bufPos++ ] = ch;
/* Make sure we haven't overflowed the input buffer. We
check for MAX_SQL_QUERY_SIZE - 3 rather than
MAX_SQL_QUERY_SIZE - 2 in case the next character needs
escaping which expands it to two chars (MAX_SQL_QUERY_SIZE
- 1 is used for the '\0') */
if( bufPos > MAX_SQL_QUERY_SIZE - 3 )
{
bufPos = 0;
formatPtr = "\x00\x00"; /* Force exit on outer loop */
break;
}
}
formatPtr++;
}
else
{
/* Just copy the char over, with a length check */
if( bufPos > MAX_SQL_QUERY_SIZE - 1 )
{
bufPos = 0;
break;
}
buffer[ bufPos++ ] = *formatPtr++;
}
}
buffer[ bufPos++ ] = '\0'; /* Add der terminador */
va_end( argPtr );
}
/* Format input parameters into SQL queries, replacing meta-values with
actual column names */
int dbmsFormatQuery( char *output, const char *input, const int inputLength,
const int maxLength )
{
int inPos = 0, outPos = 0, status = CRYPT_OK;
while( inPos < inputLength )
{
if( input[ inPos ] == '$' )
{
const int fieldPos = inPos + 1;
const char *fieldName = input + fieldPos;
const char *outputFieldName;
int length;
inPos++; /* Skip '$' */
/* Extract the field name and translate it into the table
column name */
while( isAlpha( input[ inPos ] ) )
inPos++;
length = inPos - fieldPos;
if( length <= 0 || length > 7 )
{
status = CRYPT_ERROR_BADDATA;
break;
}
if( !strCompare( fieldName, "C", length ) )
outputFieldName = "C";
else
if( !strCompare( fieldName, "SP", length ) )
outputFieldName = "SP";
else
if( !strCompare( fieldName, "L", length ) )
outputFieldName = "L";
else
if( !strCompare( fieldName, "O", length ) )
outputFieldName = "O";
else
if( !strCompare( fieldName, "OU", length ) )
outputFieldName = "OU";
else
if( !strCompare( fieldName, "CN", length ) )
outputFieldName = "CN";
else
if( !strCompare( fieldName, "email", length ) )
outputFieldName = "email";
else
if( !strCompare( fieldName, "date", length ) )
outputFieldName = "validTo";
else
{
status = CRYPT_ERROR_BADDATA;
break;
}
length = strlen( outputFieldName );
/* Copy the translated name to the output buffer */
if( outPos + length >= maxLength - 1 )
{
status = CRYPT_ERROR_OVERFLOW;
break;
}
memcpy( output + outPos, outputFieldName, length );
outPos += length;
}
else
{
const char ch = input[ inPos++ ];
/* Just copy the char over, with a length check */
if( outPos > maxLength - 1 )
{
status = CRYPT_ERROR_OVERFLOW;
break;
}
/* Safety checks from formatSQL */
if( ( ch & 0x7F ) < ' ' )
continue;
if( ch == '\\' || ch == ';' || ch == '%' )
/* Escape the character */
output[ outPos++ ] = SQL_ESCAPE;
#ifdef __WINDOWS__
if( ch != '|' )
#endif /* __WINDOWS__ */
output[ outPos++ ] = ch;
}
}
if( cryptStatusError( status ) )
outPos = 0;
output[ outPos++ ] = '\0'; /* Add der terminador */
return( status );
}
/* Parse a user-supplied database name into individual components, used by
the database back-end connect functions. We don't do a syntax check
(since the exact syntax is database-specific) but merely break the single
string up into any recognisable components. The database backend can
determine whether the format is valid or not. The general format that we
look for is:
[generic name]
user:pass
user@server
user:pass@server
user:pass@server/name
One distinction that we make is that if there's something after an '@'
and there's no server/name separator present, we treat it as a name
rather than a server. In other words @foo results in name=foo, while
@foo/bar results in server=foo, name=bar. This is because the most
common situation we have to handle is ODBC, which identifies the database
by name rather than server */
int dbmsParseName( DBMS_NAME_INFO *nameInfo, const char *name,
const int lengthMarker )
{
const char *namePtr, *argEndPtr;
int length;
memset( nameInfo, 0, sizeof( DBMS_NAME_INFO ) );
/* Check for a complex database name */
if( ( namePtr = strchr( name, ':' ) ) == NULL && \
( namePtr = strchr( name, '@' ) ) == NULL )
{
/* It's a straightforward name, use it directly */
nameInfo->name = ( char * ) name;
nameInfo->nameLen = lengthMarker ? lengthMarker : strlen( name );
return( CRYPT_OK );
}
/* Extract the user name */
length = min( namePtr - name, CRYPT_MAX_TEXTSIZE );
if( length <= 0 )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->userBuffer, name, length );
nameInfo->userBuffer[ length ] = '\0';
nameInfo->user = nameInfo->userBuffer;
nameInfo->userLen = lengthMarker ? lengthMarker : length;
/* Extract the password if there is one */
if( *namePtr++ == ':' )
{
argEndPtr = strchr( namePtr, '@' );
if( argEndPtr == NULL )
argEndPtr = strchr( namePtr, '\0' );
length = min( argEndPtr - namePtr, CRYPT_MAX_TEXTSIZE );
if( length <= 0 )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->passwordBuffer, namePtr, length );
nameInfo->passwordBuffer[ length ] = '\0';
nameInfo->password = nameInfo->passwordBuffer;
nameInfo->passwordLen = lengthMarker ? lengthMarker : length;
if( !*argEndPtr )
return( CRYPT_OK );
namePtr = argEndPtr + 1;
}
/* Separate the server and database name if necessary */
argEndPtr = strchr( namePtr, '/' );
if( argEndPtr != NULL )
{
/* There's a distinction between the server name and database name,
extract the server name */
length = min( argEndPtr - namePtr, CRYPT_MAX_TEXTSIZE );
if( length <= 0 )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->serverBuffer, namePtr, length );
nameInfo->serverBuffer[ length ] = '\0';
nameInfo->server = nameInfo->serverBuffer;
nameInfo->serverLen = lengthMarker ? lengthMarker : length;
namePtr = argEndPtr + 1;
}
/* Extract the database name if there is one */
if( *namePtr )
{
length = strlen( namePtr );
memcpy( nameInfo->nameBuffer, namePtr, length );
nameInfo->nameBuffer[ length ] = '\0';
nameInfo->name = nameInfo->nameBuffer;
nameInfo->nameLen = lengthMarker ? lengthMarker : length;
}
return( CRYPT_OK );
}
/* Initialise and shut down a session with a database backend */
int initDbxSession( KEYSET_INFO *keysetInfo, const CRYPT_KEYSET_TYPE type )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
/* Select the appropriate dispatch function for the keyset type */
switch( type )
{
case CRYPT_KEYSET_ODBC:
case CRYPT_KEYSET_ODBC_STORE:
dbmsInfo->dispatchFunction = odbcProcessCommand;
break;
case CRYPT_KEYSET_DATABASE:
case CRYPT_KEYSET_DATABASE_STORE:
dbmsInfo->dispatchFunction = databaseProcessCommand;
break;
case CRYPT_KEYSET_PLUGIN:
case CRYPT_KEYSET_PLUGIN_STORE:
dbmsInfo->dispatchFunction = netProcessCommand;
break;
default:
assert( NOTREACHED );
}
if( dbmsInfo->dispatchFunction == NULL )
return( CRYPT_ARGERROR_NUM1 );
/* Set up the remaining function pointers */
dbmsInfo->openDatabaseFunction = openDatabase;
dbmsInfo->closeDatabaseFunction = closeDatabase;
dbmsInfo->performUpdateFunction = performUpdate;
dbmsInfo->performStaticUpdateFunction = performStaticUpdate;
dbmsInfo->performQueryFunction = performQuery;
dbmsInfo->performStaticQueryFunction = performStaticQuery;
/* Allocate the database session state information */
if( ( keysetInfo->keyData = \
clAlloc( "initDbxSession", sizeof( DBMS_STATE_INFO ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( keysetInfo->keyData, 0, sizeof( DBMS_STATE_INFO ) );
keysetInfo->keyDataSize = sizeof( DBMS_STATE_INFO );
dbmsInfo->stateInfo = keysetInfo->keyData;
if( type == CRYPT_KEYSET_ODBC_STORE || \
type == CRYPT_KEYSET_DATABASE_STORE || \
type == CRYPT_KEYSET_PLUGIN_STORE )
dbmsInfo->flags |= DBMS_FLAG_CERTSTORE | DBMS_FLAG_CERTSTORE_FIELDS;
return( CRYPT_OK );
}
int endDbxSession( KEYSET_INFO *keysetInfo )
{
/* Free the database session state information if necessary */
if( keysetInfo->keyData != NULL )
{
memset( keysetInfo->keyData, 0, keysetInfo->keyDataSize );
clFree( "endDbxSession", keysetInfo->keyData );
keysetInfo->keyData = NULL;
}
return( CRYPT_OK );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -