⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scorebrd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*							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 + -