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

📄 sendmsg.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
			{
			if( messageQueueInfo != NULL )
				*messageQueueInfo = messageQueue[ i ];
			dequeueMessage( i );
			return( TRUE );
			}
		}

	/* Postcondition: There are no more messages for this object present in
	   the queue */
	FORALL( i, 0, krnlData->queueEnd,
			messageQueue[ i ].objectHandle != objectHandle );

	return( FALSE );
	}

/* Dequeue all messages for an object in the queue */

static void dequeueAllMessages( const int objectHandle )
	{
	/* Dequeue all messages for a given object */
	while( getNextMessage( objectHandle, NULL ) );

	/* Postcondition: There are no more messages for this object present in
	   the queue */
	FORALL( i, 0, krnlData->queueEnd,
			krnlData->messageQueue[ i ].objectHandle != objectHandle );
	}

/****************************************************************************
*																			*
*							Message Dispatcher								*
*																			*
****************************************************************************/

/* Dispatch a message to an object */

static int dispatchMessage( const int localObjectHandle,
							const MESSAGE_QUEUE_DATA *messageQueueData,
							OBJECT_INFO *objectInfoPtr,
							const void *aclPtr )
	{
	const MESSAGE_HANDLING_INFO *handlingInfoPtr = \
									messageQueueData->handlingInfoPtr;
	const MESSAGE_FUNCTION messageFunction = objectInfoPtr->messageFunction;
	const MESSAGE_TYPE localMessage = messageQueueData->message & MESSAGE_MASK;
	void *objectPtr = objectInfoPtr->objectPtr;
	const int lockCount = objectInfoPtr->lockCount + 1;
	int status;

	PRE( isValidHandle( localObjectHandle ) );
	PRE( isReadPtr( messageQueueData, sizeof( MESSAGE_QUEUE_DATA ) ) );
	PRE( isWritePtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );

	/* If there's a pre-dispatch handler present, apply it */
	if( handlingInfoPtr->preDispatchFunction != NULL )
		{
		status = handlingInfoPtr->preDispatchFunction( localObjectHandle,
										messageQueueData->message,
										messageQueueData->messageDataPtr,
										messageQueueData->messageValue,
										aclPtr );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Mark the object as busy so that we have it available for our
	   exclusive use and further messages to it will be enqueued, dispatch
	   the message with the object table unlocked, and mark the object as
	   non-busy again */
	objectInfoPtr->lockCount++;
#ifdef USE_THREADS
	objectInfoPtr->lockOwner = THREAD_SELF();
#endif /* USE_THREADS */
	MUTEX_UNLOCK( objectTable );
	status = messageFunction( objectPtr, localMessage,
							  ( void * ) messageQueueData->messageDataPtr,
							  messageQueueData->messageValue );
	MUTEX_LOCK( objectTable );
	objectInfoPtr = &krnlData->objectTable[ localObjectHandle ];
	assert( localObjectHandle == SYSTEM_OBJECT_HANDLE || \
			( objectInfoPtr->type == OBJECT_TYPE_USER && \
			  localMessage == MESSAGE_SETATTRIBUTE && \
			    messageQueueData->messageValue == \
					localObjectHandle == SYSTEM_OBJECT_HANDLE ) || \
			objectInfoPtr->lockCount == lockCount );

	/* The system object and to a lesser extent the user object may unlock
	   themselves while processing a message when they forward the message
	   elsewhere or perform non-object-specific processing, so we only
	   decrement the lock count if it's unchanged and we still own the
	   object.  We have to perform the ownership check to avoid the
	   situation where we unlock the object and another thread locks it,
	   leading to an (apparently) unchanged lock count */
	if( objectInfoPtr->lockCount == lockCount && \
		isObjectOwner( localObjectHandle ) )
		objectInfoPtr->lockCount--;

	/* Postcondition: The lock count is non-negative and, if it's not the
	   system object or a user object, has been reset to its previous
	   value */
	POST( objectInfoPtr->lockCount >= 0 && \
		  ( localObjectHandle == SYSTEM_OBJECT_HANDLE ||
		    ( objectInfoPtr->type == OBJECT_TYPE_USER && \
			  localMessage == MESSAGE_SETATTRIBUTE && \
			  messageQueueData->messageValue == \
				localObjectHandle == SYSTEM_OBJECT_HANDLE ) || \
			objectInfoPtr->lockCount == lockCount - 1 ) );

	/* If there's a post-dispatch handler present, apply it.  Since a
	   destroy object message always succeeds but can return an error code
	   (typically CRYPT_ERROR_INCOMPLETE), we don't treat an error return as
	   a real error status for the purposes of further processing */
	if( ( cryptStatusOK( status ) || localMessage == MESSAGE_DESTROY ) && \
		handlingInfoPtr->postDispatchFunction != NULL )
		status = handlingInfoPtr->postDispatchFunction( localObjectHandle,
												messageQueueData->message,
												messageQueueData->messageDataPtr,
												messageQueueData->messageValue,
												aclPtr );
	return( status );
	}

/* Send a message to an object */

int krnlSendMessage( const int objectHandle, const MESSAGE_TYPE message,
					 void *messageDataPtr, const int messageValue )
	{
	const ATTRIBUTE_ACL *attributeACL = NULL;
	const MESSAGE_HANDLING_INFO *handlingInfoPtr;
	OBJECT_INFO *objectTable = krnlData->objectTable;
	OBJECT_INFO *objectInfoPtr;
	MESSAGE_QUEUE_DATA enqueuedMessageData;
	const BOOLEAN isInternalMessage = \
						( message & MESSAGE_FLAG_INTERNAL ) ? TRUE : FALSE;
	const void *aclPtr = NULL;
	MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
	int localObjectHandle = objectHandle, status = CRYPT_OK;

	/* Preconditions.  For external messages we don't provide any assertions
	   at this point since they're coming straight from the user and could
	   contain any values, and for internal messages we only trap on
	   programming errors (thus for example isValidHandle() vs.
	   isValidObject(), since this would trap if a message is sent to a
	   destroyed object) */
	PRE( isWritePtr( krnlData, sizeof( KERNEL_DATA ) ) );
	PRE( isValidMessage( localMessage ) );
	PRE( !isInternalMessage || isValidHandle( objectHandle ) );

	/* Enforce the precondition at runtime as well */
	if( !isValidMessage( localMessage ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_NOTAVAIL );
		}

	/* Get the information that we need to handle this message */
	handlingInfoPtr = &messageHandlingInfo[ localMessage ];

	/* Inner preconditions now that we have the handling information: Message
	   parameters must be within the allowed range (again, this traps on
	   programming errors only).  This is done as a large number of
	   individual assertions rather than a single huge check so that a failed
	   assertion can provide more detailed information than just "it broke" */
	PRE( handlingInfoPtr->paramCheck == PARAMTYPE_NONE_NONE ||
		 handlingInfoPtr->paramCheck == PARAMTYPE_NONE_ANY || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_NONE_BOOLEAN || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_NONE_CHECKTYPE || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_NONE || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_ANY || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_BOOLEAN || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_LENGTH || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_OBJTYPE || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_MECHTYPE || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_ITEMTYPE || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_FORMATTYPE || \
		 handlingInfoPtr->paramCheck == PARAMTYPE_DATA_COMPARETYPE );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_NONE_NONE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_NONE_NONE && \
		   messageDataPtr == NULL && messageValue == 0 ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_NONE_ANY || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_NONE_ANY && \
		   messageDataPtr == NULL ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_NONE_BOOLEAN || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_NONE_BOOLEAN && \
		   messageDataPtr == NULL && \
		   ( messageValue == FALSE || messageValue == TRUE ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_NONE_CHECKTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_NONE_CHECKTYPE && \
		   messageDataPtr == NULL && \
		   ( messageValue > MESSAGE_CHECK_NONE && \
			 messageValue < MESSAGE_CHECK_LAST ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_NONE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_NONE && \
		   messageDataPtr != NULL && messageValue == 0 ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_ANY || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_ANY && \
		   messageDataPtr != NULL ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_BOOLEAN || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_BOOLEAN && \
		   messageDataPtr != NULL && \
		   ( messageValue == FALSE || messageValue == TRUE ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_LENGTH || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_LENGTH && \
		   messageDataPtr != NULL && messageValue >= 0 ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_OBJTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_OBJTYPE && \
		   messageDataPtr != NULL && \
		   ( messageValue > OBJECT_TYPE_NONE && messageValue < OBJECT_TYPE_LAST ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_MECHTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_MECHTYPE && \
		   messageDataPtr != NULL && \
		   ( messageValue > MECHANISM_NONE && messageValue < MECHANISM_LAST ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_ITEMTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_ITEMTYPE && \
		   messageDataPtr != NULL && \
		   ( messageValue > KEYMGMT_ITEM_NONE && messageValue < KEYMGMT_ITEM_LAST ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_FORMATTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_FORMATTYPE && \
		   messageDataPtr != NULL && \
		   ( messageValue > CRYPT_CERTFORMAT_NONE && messageValue < CRYPT_CERTFORMAT_LAST ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_COMPARETYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_COMPARETYPE && \
		   messageDataPtr != NULL && \
		   ( messageValue > MESSAGE_COMPARE_NONE && \
			 messageValue < MESSAGE_COMPARE_LAST ) ) );

	/* If it's an object-manipulation message get the attribute's mandatory
	   ACL; if it's an object-parameter message get the parameter's mandatory
	   ACL.  Since these doesn't require access to any object information, we
	   can do it before we lock the object table */
	if( isAttributeMessage( localMessage ) )
		{
		attributeACL = findAttributeACL( messageValue, isInternalMessage );
		if( attributeACL == NULL )
			return( CRYPT_ARGERROR_VALUE );
		aclPtr = attributeACL;
		}
	if( isParamMessage( localMessage ) )
		aclPtr = findParamACL( localMessage );

	/* Inner precondition: If it's an attribute-manipulation message, we have
	   a valid ACL for the attribute present */
	PRE( !isAttributeMessage( localMessage ) || attributeACL != NULL );

	/* If we're in the middle of a shutdown, don't allow any further
	   messages except ones related to object destruction (the status read
	   is needed for objects capable of performing async ops, since the
	   shutdown code needs to determine whether they're currently busy).
	   The check outside the object-table lock is done in order to have any
	   remaining active objects exit quickly without tying up the object
	   table, since we don't want them to block the shutdown.  In addition
	   if the thread is a leftover/long-running thread that's still active
	   after the shutdown has occurred, we can't access the object table
	   lock since it'll have been deleted */
	if( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES && \
		!( localMessage == MESSAGE_DESTROY || \
		   localMessage == MESSAGE_DECREFCOUNT || \
		   ( localMessage == MESSAGE_GETATTRIBUTE && \
			 messageValue == CRYPT_IATTRIBUTE_STATUS ) ) )
		return( CRYPT_ERROR_PERMISSION );

	/* Lock the object table to ensure that other threads don't try to
	   access it */
	MUTEX_LOCK( objectTable );

	/* The first line of defence: Make sure that the message is being sent
	   to a valid object and that the object is externally visible and
	   accessible to the caller if required by the message.  The checks
	   performed are:

		if( handle does not correspond to an object )
			error;
		if( message is external )
			{
			if( object is internal )
				error;
			if( object isn't owned by calling thread )
				error;
			}

	   This is equivalent to the shorter form fullObjectCheck() that used
	   elsewhere.  The error condition reported in all of these cases is
	   that the object handle isn't valid */
	if( !isValidObject( objectHandle ) )
		status = CRYPT_ARGERROR_OBJECT;
	else
		if( !isInternalMessage && \
			( isInternalObject( objectHandle ) || \
			  !checkObjectOwnership( objectTable[ objectHandle ] ) ) )
			status = CRYPT_ARGERROR_OBJECT;
	if( cryptStatusError( status ) )
		{
		MUTEX_UNLOCK( objectTable );
		return( status );
		}

	/* Inner precondition now that the outer check has been passed: It's a
	   valid, accessible object and not a system object that can never be
	   explicitly destroyed or have its refCount altered */
	PRE( isValidObject( objectHandle ) );
	PRE( isInternalMessage || ( !isInternalObject( objectHandle ) && \
		 checkObjectOwnership( objectTable[ objectHandle ] ) ) );
	PRE( fullObjectCheck( objectHandle, message ) );
	PRE( objectHandle >= NO_SYSTEM_OBJECTS || \
		 ( localMessage != MESSAGE_DESTROY && \
		   localMessage != MESSAGE_DECREFCOUNT && \
		   localMessage != MESSAGE_INCREFCOUNT ) );

⌨️ 快捷键说明

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