📄 dbms.c
字号:
*bufPos = position;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
static int copyStringArg( OUT_BUFFER( bufMaxLen, *bufPos ) char *buffer,
IN_LENGTH_SHORT_Z const int bufMaxLen,
OUT_LENGTH_SHORT_Z int *bufPos,
IN_BUFFER( stringLen ) const char *string,
IN_LENGTH_SHORT const int stringLen )
{
int index, position = 0;
assert( isWritePtr( buffer, bufMaxLen ) );
assert( isWritePtr( bufPos, sizeof( int ) ) );
assert( isReadPtr( string, stringLen ) );
REQUIRES( bufMaxLen >= 0 && bufMaxLen < MAX_INTLENGTH_SHORT );
REQUIRES( stringLen > 0 && stringLen < MAX_INTLENGTH_SHORT );
/* Make sure that there's room for at least one more character of
output */
if( bufMaxLen < 1 )
return( CRYPT_ERROR_OVERFLOW );
/* Copy the string to the output buffer with conversion of any special
characters that are used by SQL */
for( index = 0; index < stringLen && \
index < FAILSAFE_ITERATIONS_MAX; index++ )
{
int charsWritten, status;
status = copyChar( buffer + position, bufMaxLen - position,
&charsWritten, string[ index ], TRUE );
if( cryptStatusError( status ) )
return( status );
position += charsWritten;
if( position > bufMaxLen )
{
/* Already checked in copyChar() but we double-check here to be
safe */
return( CRYPT_ERROR_OVERFLOW );
}
}
ENSURES( index < FAILSAFE_ITERATIONS_MAX );
*bufPos = position;
return( CRYPT_OK );
}
/* Format input parameters into SQL queries, replacing meta-values with
actual column names, and null-terminate the resulting string so that
it can be fed to the database backend */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int dbmsFormatQuery( OUT_BUFFER( outMaxLength, *outLength ) char *output,
IN_LENGTH_SHORT const int outMaxLength,
OUT_LENGTH_SHORT_Z int *outLength,
IN_BUFFER( inputLength ) const char *input,
IN_LENGTH_SHORT const int inputLength )
{
int inPos, outPos = 0, status = CRYPT_OK;
assert( isWritePtr( output, outMaxLength ) );
assert( isWritePtr( outLength, sizeof( int ) ) );
assert( isReadPtr( input, inputLength ) );
REQUIRES( outMaxLength >= 0 && outMaxLength < MAX_INTLENGTH_SHORT );
REQUIRES( inputLength > 0 && inputLength < MAX_INTLENGTH_SHORT );
/* Clear return values */
memset( output, 0, min( 16, outMaxLength ) );
*outLength = 0;
for( inPos = 0; inPos < inputLength && inPos < FAILSAFE_ITERATIONS_MAX; )
{
int length;
if( input[ inPos ] == '$' )
{
typedef struct {
BUFFER_FIXED( sourceLength ) \
char *sourceName;
int sourceLength;
BUFFER_FIXED( destLength ) \
char *destName;
int destLength;
} NAMEMAP_INFO;
static const NAMEMAP_INFO nameMapTbl[] = {
{ "C", 1, "C", 1 }, { "SP", 2, "SP", 2 },
{ "L", 1, "L", 1 }, { "O", 1, "O", 1 },
{ "OU", 2, "OU", 2 }, { "CN", 2, "CN", 2 },
{ "email", 5, "email", 5 }, { "uri", 3, "email", 5 },
{ "date", 4, "validTo", 7 },
{ NULL, 0, NULL, 0 }, { NULL, 0, NULL, 0 }
};
const int fieldPos = inPos + 1;
const char *fieldName = input + fieldPos;
int i;
inPos++; /* Skip '$' */
/* Extract the field name and translate it into the table
column name */
while( inPos < inputLength && isAlpha( input[ inPos ] ) )
inPos++;
length = inPos - fieldPos;
if( length <= 0 || length > 5 )
{
status = CRYPT_ERROR_BADDATA;
break;
}
for( i = 0; nameMapTbl[ i ].sourceName != NULL && \
i < FAILSAFE_ARRAYSIZE( nameMapTbl, NAMEMAP_INFO );
i++ )
{
if( length == nameMapTbl[ i ].sourceLength && \
!strCompare( fieldName, nameMapTbl[ i ].sourceName, \
length ) )
break;
}
ENSURES( i < FAILSAFE_ARRAYSIZE( nameMapTbl, NAMEMAP_INFO ) );
if( nameMapTbl[ i ].sourceName == NULL )
{
status = CRYPT_ERROR_BADDATA;
break;
}
/* Copy the translated name to the output buffer */
status = copyStringArg( output + outPos, outMaxLength - outPos,
&length, nameMapTbl[ i ].destName,
nameMapTbl[ i ].destLength );
}
else
{
/* Just copy the character over, with a length check. We don't
escape single quotes in this case because we use these
ourselves in SQL queries */
status = copyChar( output + outPos, outMaxLength - outPos,
&length, input[ inPos++ ], FALSE );
}
if( cryptStatusError( status ) )
break;
outPos += length;
}
ENSURES( inPos < FAILSAFE_ITERATIONS_MAX );
if( cryptStatusError( status ) )
outPos = 0;
output[ outPos ] = '\0'; /* Add der terminador */
*outLength = outPos;
return( status );
}
/****************************************************************************
* *
* Back-end Interface Routines *
* *
****************************************************************************/
/* 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 back-end 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 that we have to handle is ODBC, which identifies the database
by name rather than by server */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int dbmsParseName( INOUT DBMS_NAME_INFO *nameInfo,
IN_BUFFER( nameLen ) const char *name,
IN_LENGTH_NAME const int nameLen )
{
int offset, offset2, length;
assert( isWritePtr( nameInfo, sizeof( DBMS_NAME_INFO ) ) );
assert( isReadPtr( name, nameLen ) );
REQUIRES( nameLen >= MIN_NAME_LENGTH && \
nameLen < MAX_ATTRIBUTE_SIZE );
memset( nameInfo, 0, sizeof( DBMS_NAME_INFO ) );
/* Check for a complex database name */
if( ( offset = strFindCh( name, nameLen, ':' ) ) < 0 && \
( offset = strFindCh( name, nameLen, '@' ) ) < 0 )
{
/* It's a straightforward name, use it directly */
nameInfo->name = ( char * ) name;
nameInfo->nameLen = nameLen;
return( CRYPT_OK );
}
/* Extract the user name */
length = min( offset, CRYPT_MAX_TEXTSIZE );
if( length <= 0 )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->userBuffer, name, length );
nameInfo->user = nameInfo->userBuffer;
nameInfo->userLen = length;
/* We're either at the server name or password, extract the password
if there is one */
ENSURES( name[ offset ] == ':' || name[ offset ] == '@' );
if( name[ offset++ ] == ':' )
{
offset2 = strFindCh( name + offset, nameLen - offset, '@' );
if( offset2 < 0 )
offset2 = nameLen - offset; /* Password is rest of string */
length = min( offset2, CRYPT_MAX_TEXTSIZE );
if( length <= 0 )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->passwordBuffer, name + offset, length );
nameInfo->password = nameInfo->passwordBuffer;
nameInfo->passwordLen = length;
offset += offset2 + 1;
if( offset >= nameLen )
return( CRYPT_OK );
}
/* Separate the server and database name if necessary */
offset2 = strFindCh( name + offset, nameLen - offset, '/' );
if( offset2 >= 0 )
{
/* There's a distinction between the server name and database name,
extract the server name */
length = min( offset2, CRYPT_MAX_TEXTSIZE );
if( length <= 0 )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->serverBuffer, name + offset, length );
nameInfo->server = nameInfo->serverBuffer;
nameInfo->serverLen = length;
offset += offset2 + 1;
}
/* Extract the database name if there is one */
if( offset < nameLen )
{
length = nameLen - offset;
if( length <= 0 || length > CRYPT_MAX_TEXTSIZE )
return( CRYPT_ERROR_OPEN );
memcpy( nameInfo->nameBuffer, name + offset, length );
nameInfo->name = nameInfo->nameBuffer;
nameInfo->nameLen = length;
}
return( CRYPT_OK );
}
/* Initialise and shut down a session with a database back-end */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initDbxSession( INOUT KEYSET_INFO *keysetInfoPtr,
IN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE type )
{
DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;
int status = CRYPT_ERROR;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );
REQUIRES( type > CRYPT_KEYSET_NONE && type < CRYPT_KEYSET_LAST );
/* Select the appropriate dispatch function for the keyset type */
switch( type )
{
case CRYPT_KEYSET_ODBC:
case CRYPT_KEYSET_ODBC_STORE:
status = initDispatchODBC( dbmsInfo );
break;
case CRYPT_KEYSET_DATABASE:
case CRYPT_KEYSET_DATABASE_STORE:
status = initDispatchDatabase( dbmsInfo );
break;
case CRYPT_KEYSET_PLUGIN:
case CRYPT_KEYSET_PLUGIN_STORE:
status = initDispatchNet( dbmsInfo );
break;
default:
retIntError();
}
if( cryptStatusError( status ) )
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( ( keysetInfoPtr->keyData = \
clAlloc( "initDbxSession", sizeof( DBMS_STATE_INFO ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( keysetInfoPtr->keyData, 0, sizeof( DBMS_STATE_INFO ) );
keysetInfoPtr->keyDataSize = sizeof( DBMS_STATE_INFO );
dbmsInfo->stateInfo = keysetInfoPtr->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 );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int endDbxSession( INOUT KEYSET_INFO *keysetInfoPtr )
{
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );
/* Free the database session state information if necessary */
if( keysetInfoPtr->keyData != NULL )
{
memset( keysetInfoPtr->keyData, 0, keysetInfoPtr->keyDataSize );
clFree( "endDbxSession", keysetInfoPtr->keyData );
keysetInfoPtr->keyData = NULL;
}
return( CRYPT_OK );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -