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

📄 sendmsg.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*							Kernel Message Dispatcher						*
*						Copyright Peter Gutmann 1997-2004					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "crypt.h"
  #include "acl.h"
  #include "kernel.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "acl.h"
  #include "kernel.h"
#else
  #include "crypt.h"
  #include "kernel/acl.h"
  #include "kernel/kernel.h"
#endif /* Compiler-specific includes */

/* A pointer to the kernel data block */

static KERNEL_DATA *krnlData = NULL;

/* The ACL used to check objects passed as message parameters, in this case
   for cert sign/sig-check messages */

static const FAR_BSS MESSAGE_ACL messageParamACLTbl[] = {
	/* Certs can only be signed by (private-key) PKC contexts */
	{ MESSAGE_CRT_SIGN,
	  { ST_CTX_PKC,
		ST_NONE } },

	/* Signatures can be checked with a raw PKC context or a cert or cert
	   chain.  The object being checked can also be checked against a CRL,
	   against revocation data in a cert store, or against an RTCS or OCSP
	   responder */
	{ MESSAGE_CRT_SIGCHECK,
	  { ST_CTX_PKC | ST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL | \
					 ST_KEYSET_DBMS,
		ST_SESS_RTCS | ST_SESS_OCSP } },

	{ MESSAGE_NONE, ST_NONE, ST_NONE }
	};

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Sometimes a message is explicitly non-routable (i.e. it has to be sent
   directly to the appropriate target object).  The following function checks
   that the target object is one of the required types */

int checkTargetType( const int objectHandle, const int targets )
	{
	const OBJECT_TYPE target = targets & 0xFF;
	const OBJECT_TYPE altTarget = targets >> 8;
	OBJECT_INFO *objectTable = krnlData->objectTable;

	/* Precondition: Source is a valid object, destination(s) are valid
	   target(s) */
	PRE( isValidObject( objectHandle ) );
	PRE( isValidType( target ) );
	PRE( altTarget == OBJECT_TYPE_NONE || isValidType( altTarget ) );

	/* Check whether the object matches the required type.  We don't have to
	   check whether the alternative target has a value or not since the
	   object can never be a OBJECT_TYPE_NONE */
	if( !isValidObject( objectHandle ) || \
		( objectTable[ objectHandle ].type != target && \
		  objectTable[ objectHandle ].type != altTarget ) )
		return( CRYPT_ERROR );

	/* Postcondition */
	POST( objectTable[ objectHandle ].type == target || \
		  objectTable[ objectHandle ].type == altTarget );

	return( objectHandle );
	}

/* Find the ACL for a parameter object */

static const MESSAGE_ACL *findParamACL( const MESSAGE_TYPE message )
	{
	int i;

	/* Precondition: It's a message that takes an object parameter */
	PRE( isParamMessage( message ) );

	/* Find the ACL entry for this message type */
	for( i = 0; messageParamACLTbl[ i ].type != MESSAGE_NONE; i++ )
		if( messageParamACLTbl[ i ].type == message )
			return( &messageParamACLTbl[ i ] );

	/* Postcondition: We found a matching ACL entry */
	POST( NOTREACHED );

	/* Return a no-permission ACL in case of error */
	return( &messageParamACLTbl[ i ] );
	}

/* Wait for an object to become available so that we can use it, with a
   timeout for blocked objects.  This is an internal function which is used
   when mapping an object handle to object data, and is never called
   directly.  As an aid in identifying objects acting as bottlenecks, we
   provide a function to warn about excessive waiting, along with information
   on the object that was waited on, in debug mode.  A wait count threshold
   of 100 is generally high enough to avoid false positives caused by (for
   example) network subsystem delays */

#define MAX_WAITCOUNT				10000
#define WAITCOUNT_WARN_THRESHOLD	100

#ifndef NDEBUG

#include <stdio.h>

static void waitWarn( const int objectHandle, const int waitCount )
	{
	static const char *objectTypeNames[] = {
		"None", "Context", "Keyset", "Envelope", "Certificate", "Device",
		"Session", "User", "None", "None"
		};
	const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
	char buffer[ 128 ];

	if( objectHandle == SYSTEM_OBJECT_HANDLE )
		strcpy( buffer, "system object" );
	else
		if( objectHandle == DEFAULTUSER_OBJECT_HANDLE )
			strcpy( buffer, "default user object" );
		else
			sPrintf( buffer, "object %d (%s, subtype %lX)",
					 objectHandle, objectTypeNames[ objectInfoPtr->type ],
					 objectInfoPtr->subType );
	fprintf( stderr, "\nWarning: Thread %X waited %d iteration%s for %s.\n",
			 THREAD_SELF(), waitCount, ( waitCount == 1 ) ? "" : "s",
			 buffer );
	}
#endif /* Debug mode only */

int waitForObject( const int objectHandle, OBJECT_INFO **objectInfoPtrPtr )
	{
	OBJECT_INFO *objectTable = krnlData->objectTable;
	const unsigned int uniqueID = objectTable[ objectHandle ].uniqueID;
	int waitCount = 0;

	/* Preconditions: The object is in use by another thread */
	PRE( isValidObject( objectHandle ) );
	PRE( isInUse( objectHandle ) && !isObjectOwner( objectHandle ) );

	/* While the object is busy, put the thread to sleep.  This is the
	   optimal portable way to wait on the resource, since it gives up this
	   thread's timeslice to allow other threads (including the one using
	   the object) to run.  Other methods such as mutexes with timers are
	   difficult to manage portably across different platforms */
	while( objectTable[ objectHandle ].uniqueID == uniqueID && \
		   isInUse( objectHandle ) && waitCount < MAX_WAITCOUNT && \
		   krnlData->shutdownLevel < SHUTDOWN_LEVEL_MESSAGES )
		{
		MUTEX_UNLOCK( objectTable );
		waitCount++;
		THREAD_YIELD();
		MUTEX_LOCK( objectTable );
		}
#ifndef NDEBUG
	if( waitCount > WAITCOUNT_WARN_THRESHOLD )
		/* If we waited more than WAITCOUNT_WARN_THRESHOLD iterations for
		   something this could be a sign of a resource usage bottleneck
		   (typically caused by users who don't understand threading), warn
		   the user that there's a potential problem */
		waitWarn( objectHandle, waitCount );
#endif /* NDEBUG */

	/* If cryptlib is shutting down, exit */
	if( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES )
		return( CRYPT_ERROR_PERMISSION );

	/* If we timed out waiting for the object, return a timeout error */
	if( waitCount >= MAX_WAITCOUNT )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_TIMEOUT );
		}

	/* Make sure that nothing happened to the object while we were waiting
	   on it */
	if( objectTable[ objectHandle ].uniqueID != uniqueID )
		return( CRYPT_ERROR_SIGNALLED );

	/* Update the object info pointer in case the object table was updated
	   while we had yielded control */
	*objectInfoPtrPtr = &objectTable[ objectHandle ];

	/* Postconditions: The object is available for use */
	POST( isValidObject( objectHandle ) );
	POST( !isInUse( objectHandle ) );

	return( CRYPT_OK );
	}

#if 0	/* 18/2/04 No need for copy-on-write any more since we can just copy
				   across the instance data referenced in the object table */

/* Handle an object that has been cloned and is subject to copy-on-write */

static int handleAliasedObject( const int objectHandle,
								const MESSAGE_TYPE message,
								const void *messageDataPtr,
								const int messageValue )
	{
	OBJECT_INFO *objectTable = krnlData->objectTable;
	OBJECT_INFO *objectInfoPtr =  &objectTable[ objectHandle ];
	CRYPT_CONTEXT originalObject = objectHandle;
	CRYPT_CONTEXT clonedObject = objectInfoPtr->clonedObject;
	int status;

	/* Preconditions */
	PRE( isValidObject( objectHandle ) && \
		 objectHandle >= NO_SYSTEM_OBJECTS );
	PRE( isValidObject( clonedObject ) && \
		 clonedObject >= NO_SYSTEM_OBJECTS );
	PRE( objectInfoPtr->type == OBJECT_TYPE_CONTEXT );
	PRE( objectTable[ clonedObject ].type == OBJECT_TYPE_CONTEXT );
	PRE( objectHandle != clonedObject );
	PRE( isAliasedObject( objectHandle ) && isAliasedObject( clonedObject ) );
	PRE( isClonedObject( objectHandle ) || isClonedObject( clonedObject ) );

	/* If it's a destroy-object message, make sure that the (incomplete)
	   clone is the one that gets destroyed rather than the original */
	if( message == MESSAGE_DESTROY )
		{
		OBJECT_INFO *originalObjectInfoPtr, *clonedObjectInfoPtr;
		OBJECT_INFO tempObjectInfo;

		/* If we're destroying the clone, we're done */
		if( isClonedObject( objectHandle ) )
			return( CRYPT_OK );

		/* We're trying to destroy the original, switch it with the clone */
		memcpy( &tempObjectInfo, &objectTable[ objectHandle ],
				sizeof( OBJECT_INFO ) );
		memcpy( &objectTable[ objectHandle ], &objectTable[ clonedObject ],
				sizeof( OBJECT_INFO ) );
		memcpy( &objectTable[ clonedObject ], &tempObjectInfo,
				sizeof( OBJECT_INFO ) );

		/* Inner precondition: Now the original is the clone and the clone is
		   the original */
		PRE( isClonedObject( objectHandle ) );
		PRE( !isClonedObject( clonedObject ) );

		/* We've now swapped the clone and the original, mark them as normal
		   (non-aliased) objects since we're about to destroy the clone */
		originalObjectInfoPtr =  &objectTable[ clonedObject ];
		clonedObjectInfoPtr = &objectTable[ objectHandle ];
		originalObjectInfoPtr->flags &= ~OBJECT_FLAG_ALIASED;
		clonedObjectInfoPtr->flags &= ~( OBJECT_FLAG_ALIASED | OBJECT_FLAG_CLONE );
		originalObjectInfoPtr->clonedObject = \
			clonedObjectInfoPtr->clonedObject = CRYPT_ERROR;

		/* Postconditions: The two objects are back to being normal objects */
		POST( !isAliasedObject( objectHandle ) && !isClonedObject( objectHandle ) );
		POST( !isAliasedObject( clonedObject ) && !isClonedObject( clonedObject ) );

		return( CRYPT_OK );
		}

	/* If it's not a message that modifies the object's state, we're done */
	if( !isActionMessage( message ) && \
		!( message == MESSAGE_SETATTRIBUTE || \
		   message == MESSAGE_SETATTRIBUTE_S || \
		   message == MESSAGE_DELETEATTRIBUTE ) && \
		!( message == MESSAGE_CTX_GENIV || message == MESSAGE_CLONE ) )
		return( CRYPT_OK );

	/* If the object that we've been passed is the clone, get the original
	   and clone into their correct roles */
	if( isClonedObject( objectHandle ) )
		{
		clonedObject = objectHandle;
		originalObject = objectInfoPtr->clonedObject;
		objectInfoPtr = &objectTable[ originalObject ];
		}

	/* Inner precondition: We've sorted out the original vs.the clone, and
	   the two are distinct */
	PRE( isClonedObject( clonedObject ) );
	PRE( clonedObject != originalObject );

	/* We're about to modify one of the two aliased objects, create distinct
	   objects to enforce copy-on-write semantics and reset the cloned/
	   aliased status.  We also create two distinct objects if a second
	   attempt is made to clone the original rather than allowing the
	   creation of multiple aliased objects.  This is done for two reasons,
	   firstly because handling arbitrarily large collections of cloned
	   objects, while possible, complicates the kernel since it's no longer
	   a straighforward message filter that needs to add relatively complex
	   processing to manage chains of cloned objects.  Secondly, having
	   multiple aliased objects is exceedingly rare (it can only happen if a
	   user, for some reason, pushes the same session key or hash into
	   multiple envelopes), so the extra overhead of a forced clone is
	   negligible */
	status = cloneContext( clonedObject, originalObject );
	if( cryptStatusOK( status ) )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -