📄 scorebrd.c
字号:
/****************************************************************************
* *
* cryptlib Session Scoreboard *
* Copyright Peter Gutmann 1998-2006 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "session.h"
#include "ssl.h"
#else
#include "crypt.h"
#include "session/session.h"
#include "session/ssl.h"
#endif /* Compiler-specific includes */
#ifdef USE_SSL
/* The maximum size of any data value to be stored in the scoreboard.
Currently this is SSL_SECRET_SIZE, 48 bytes */
#define SCOREBOARD_DATA_SIZE SSL_SECRET_SIZE
/* Scoreboard data and index information */
typedef BYTE SCOREBOARD_DATA[ SCOREBOARD_DATA_SIZE ];
typedef struct {
/* Identification information: The checksum and hash of the session ID */
int checkValue;
BYTE hashValue[ HASH_DATA_SIZE + 4 ];
/* Misc info */
time_t timeStamp; /* Time entry was added to the scoreboard */
int uniqueID; /* Unique ID for this entry */
BOOLEAN fixedEntry; /* Whether entry was added manually */
} SCOREBOARD_INDEX;
/* A template used to initialise scoreboard entries */
static const SCOREBOARD_INDEX SCOREBOARD_INDEX_TEMPLATE = \
{ 0, { 0 }, 0, 0, FALSE };
/* The maximum amount of time that an entry is retained in the scoreboard,
1 hour */
#define SCOREBOARD_TIMEOUT 3600
/* The action to perform on the scoreboard. These are:
ADD: Add the given key and value.
LOOKUP: Look up the given key and return the associated value.
PRESENCECHECK: Check whether the given key is present and return its
uniqueID value if it is */
typedef enum {
SCOREBOARD_ACTION_NONE, /* No scoreboard action */
SCOREBOARD_ACTION_PRESENCECHECK,/* Check for an entry presence */
SCOREBOARD_ACTION_LOOKUP, /* Look up a scoreboard entry */
SCOREBOARD_ACTION_ADD, /* Add a scoreboard entry */
SCOREBOARD_ACTION_LAST /* Last possible scoreboard action */
} SCOREBOARD_ACTION;
/****************************************************************************
* *
* Scoreboard Management Functions *
* *
****************************************************************************/
/* Find an entry, returning its position in the scoreboard. This function
currently uses a straightforward linear search with entries clustered
towards the start of the scoreboard. Although this may seem somewhat
suboptimal, since cryptlib isn't a high-performance server the scoreboard
will rarely contain more than a handful of entries (if any). In any case
a quick scan through a small number of integers is probably still faster
than the complex in-memory database lookup schemes used by many servers,
and is also required to handle things like scoreboard LRU management */
static int findEntry( SCOREBOARD_INFO *scoreboardInfo,
const void *key, const int keyLength,
const time_t currentTime, int *position )
{
SCOREBOARD_INDEX *scoreboardIndex = scoreboardInfo->index;
SCOREBOARD_DATA *scoreboardData = scoreboardInfo->data;
BYTE hashValue[ HASH_DATA_SIZE + 8 ];
BOOLEAN dataHashed = FALSE;
time_t oldestTime = currentTime;
const int checkValue = checksumData( key, keyLength );
int nextFreeEntry = CRYPT_ERROR, lastUsedEntry = 0, oldestEntry = 0;
int i;
assert( isWritePtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );
assert( isReadPtr( key, keyLength ) && keyLength >= 8 );
assert( currentTime > MIN_TIME_VALUE );
assert( isWritePtr( position, sizeof( int ) ) );
assert( isWritePtr( scoreboardIndex,
scoreboardInfo->size * sizeof( SCOREBOARD_INDEX ) ) );
assert( isWritePtr( scoreboardData,
scoreboardInfo->size * sizeof( SCOREBOARD_DATA ) ) );
/* Clear return value */
*position = CRYPT_ERROR;
for( i = 0; i < scoreboardInfo->lastEntry && \
i < FAILSAFE_ITERATIONS_MAX; i++ )
{
SCOREBOARD_INDEX *scorebordIndexEntry = &scoreboardIndex[ i ];
/* If this entry has expired, delete it */
if( scorebordIndexEntry->timeStamp + SCOREBOARD_TIMEOUT < currentTime )
{
scoreboardIndex[ i ] = SCOREBOARD_INDEX_TEMPLATE;
zeroise( scoreboardData[ i ], sizeof( SCOREBOARD_DATA ) );
}
/* Check for a free entry and the oldest non-free entry. We could
perform an early-out once we find a free entry, but this would
prevent any following expired entries from being deleted */
if( scorebordIndexEntry->timeStamp <= MIN_TIME_VALUE )
{
/* We've found a free entry, remember it for future use if
required and continue */
if( nextFreeEntry == CRYPT_ERROR )
nextFreeEntry = i;
continue;
}
lastUsedEntry = i;
if( scorebordIndexEntry->timeStamp < oldestTime )
{
/* We've found an older entry than the current oldest entry,
remember it */
oldestTime = scorebordIndexEntry->timeStamp;
oldestEntry = i;
}
/* Perform a quick check using a checksum of the name to weed out
most entries */
if( scorebordIndexEntry->checkValue == checkValue )
{
if( !dataHashed )
{
hashData( hashValue, HASH_DATA_SIZE, key, keyLength );
dataHashed = TRUE;
}
if( !memcmp( scorebordIndexEntry->hashValue, hashValue,
HASH_DATA_SIZE ) )
{
/* Remember the match position. We can't immediately exit
at this point because we still need to look for the last
used entry and potentually shrink the scoreboard-used
size */
*position = i;
}
}
}
if( i >= FAILSAFE_ITERATIONS_MAX )
retIntError();
/* If the total number of entries has shrunk due to old entries expiring,
reduce the overall scoreboard-used size */
if( lastUsedEntry + 1 < scoreboardInfo->lastEntry )
scoreboardInfo->lastEntry = lastUsedEntry + 1;
/* If we've found a match, we're done */
if( *position >= 0 )
return( CRYPT_OK );
/* The entry wasn't found, return the location where we can add a new
entry */
if( nextFreeEntry > 0 )
/* We've freed up an existing position (which will be before any
remaining free entries), add the new entry there */
*position = nextFreeEntry;
else
{
/* If there are still free positions in the scoreboard, use the next
available one */
if( scoreboardInfo->lastEntry < scoreboardInfo->size )
*position = scoreboardInfo->lastEntry;
else
/* There are no free positions, overwrite the oldest entry */
*position = oldestEntry;
}
return( CRYPT_ERROR );
}
/* Add an entry to the scoreboard */
static int addEntry( SCOREBOARD_INFO *scoreboardInfo, const int position,
const void *key, const int keyLength,
const void *value, const int valueLength,
const time_t currentTime )
{
SCOREBOARD_INDEX *scoreboardIndex = scoreboardInfo->index;
SCOREBOARD_INDEX *scorebordIndexEntry = &scoreboardIndex[ position ];
SCOREBOARD_DATA *scoreboardData = scoreboardInfo->data;
const int checkValue = checksumData( key, keyLength );
assert( isWritePtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );
assert( isReadPtr( key, keyLength ) && keyLength >= 8 );
assert( isReadPtr( value, valueLength ) );
assert( currentTime > MIN_TIME_VALUE );
assert( isWritePtr( scoreboardIndex,
scoreboardInfo->size * sizeof( SCOREBOARD_INDEX ) ) );
assert( isWritePtr( scoreboardData,
scoreboardInfo->size * sizeof( SCOREBOARD_DATA ) ) );
/* Clear the entry (this should already be done, but we make it explicit
here just in case) */
*scorebordIndexEntry = SCOREBOARD_INDEX_TEMPLATE;
zeroise( scoreboardData[ position ], sizeof( SCOREBOARD_DATA ) );
/* Copy across the key and value */
scorebordIndexEntry->checkValue = checkValue;
hashData( scorebordIndexEntry->hashValue, HASH_DATA_SIZE,
key, keyLength );
scorebordIndexEntry->timeStamp = currentTime;
scorebordIndexEntry->uniqueID = scoreboardInfo->uniqueID++;
memcpy( scoreboardData[ position ], value, valueLength );
/* If we've used a new entry, update the position-used index */
if( position >= scoreboardInfo->lastEntry )
scoreboardInfo->lastEntry = position + 1;
return( scoreboardIndex[ position ].uniqueID );
}
/* Umbrella interface for all scoreboard operations */
static int handleScoreboard( SCOREBOARD_INFO *scoreboardInfo,
const SCOREBOARD_ACTION action,
const void *key, const int keyLength,
void *value, const int valueLength )
{
SCOREBOARD_INDEX *scoreboardIndex = scoreboardInfo->index;
SCOREBOARD_DATA *scoreboardData = scoreboardInfo->data;
const time_t currentTime = getTime();
int position, uniqueID = SCOREBOARD_UNIQUEID_NONE, status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -