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

📄 sendmsg.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:

			if( messageQueueInfo != NULL )
				*messageQueueInfo = messageQueue[ i ];
			status = dequeueMessage( i );
			if( cryptStatusError( status ) )
				return( FALSE );

			return( TRUE );
			}
		}
	ENSURES( i < MESSAGE_QUEUE_SIZE );

	/* 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 )
	{
	int iterationCount = 0;

	/* Preconditions: It's a valid object table entry.  It's not necessarily
	   a valid object since we may be de-queueing messages for it because 
	   it's just been destroyed */
	PRE( objectHandle == SYSTEM_OBJECT_HANDLE || \
		 objectHandle == DEFAULTUSER_OBJECT_HANDLE || \
		 isHandleRangeValid( objectHandle ) );
	
	/* Dequeue all messages for a given object */
	while( getNextMessage( objectHandle, NULL ) && \
		   iterationCount++ < MESSAGE_QUEUE_SIZE );
	ENSURES_V( iterationCount < MESSAGE_QUEUE_SIZE );

	/* 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								*
*																			*
****************************************************************************/

/* Process a message that's handled internally by the kernel, for example 
   one that accesses an object's kernel attributes */

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int processInternalMessage( const int localObjectHandle,
								   const MESSAGE_HANDLING_INFO *handlingInfoPtr,
								   const MESSAGE_TYPE message,
								   IN_OPT void *messageDataPtr,
								   const int messageValue,
								   const void *aclPtr )
	{
	int status;

	/* Precondition: It's a valid message being sent to a valid object */
	PRE( isValidObject( localObjectHandle ) );
	PRE( isReadPtr( handlingInfoPtr, sizeof( MESSAGE_HANDLING_INFO ) ) );
	PRE( isValidMessage( message & MESSAGE_MASK ) );

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

	/* Inner precondition: Either the message as a whole is internally 
	   handled or it's a property attribute */
	PRE( handlingInfoPtr->internalHandlerFunction != NULL || \
		 isAttributeMessage( message & MESSAGE_MASK ) );

	/* If it's an object property attribute (which is handled by the kernel), 
	   get or set its value */
	if( handlingInfoPtr->internalHandlerFunction == NULL )
		{
		/* Precondition: Object properties are always numeric attributes */
		PRE( handlingInfoPtr->messageType == MESSAGE_GETATTRIBUTE || \
			 handlingInfoPtr->messageType == MESSAGE_SETATTRIBUTE );

		if( handlingInfoPtr->messageType == MESSAGE_GETATTRIBUTE )
			status = getPropertyAttribute( localObjectHandle, messageValue, 
										   messageDataPtr );
		else
			status = setPropertyAttribute( localObjectHandle, messageValue, 
										   messageDataPtr );
		}
	else
		{
		/* It's a kernel-handled message, process it */
		status = handlingInfoPtr->internalHandlerFunction( localObjectHandle, 
												messageValue, messageDataPtr, 
												isInternalMessage( message ) );
		}
	if( cryptStatusError( status ) )
		{
		/* Postcondition: It's a genuine error, or a special-case condition
		   such as the object creation being aborted, which produces an 
		   OK_SPECIAL status to tell the caller to convert the message that
		   triggered this into a MESSAGE_DESTROY */
		POST( cryptStatusError( status ) || status == OK_SPECIAL );

		return( status );
		}

	/* If there's a post-dispatch handler, invoke it */
	if( handlingInfoPtr->postDispatchFunction != NULL )
		{
		status = handlingInfoPtr->postDispatchFunction( localObjectHandle, 
									message, messageDataPtr, messageValue, 
									aclPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	
	return( CRYPT_OK );
	}

/* Dispatch a message to an object */

CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \
static int dispatchMessage( const int localObjectHandle,
							const MESSAGE_QUEUE_DATA *messageQueueData,
							INOUT 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;
	MESSAGE_FUNCTION_EXTINFO messageExtInfo;
	void *objectPtr = objectInfoPtr->objectPtr;
	BOOLEAN mayUnlock = FALSE;
	int status;
	ORIGINAL_INT_VAR( lockCount, objectInfoPtr->lockCount );

	PRE( isValidObject( localObjectHandle ) );
	PRE( !isInUse( localObjectHandle ) || \
		 isObjectOwner( localObjectHandle ) );
	PRE( isReadPtr( messageQueueData, sizeof( MESSAGE_QUEUE_DATA ) ) );
	PRE( isWritePtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );
	PRE( messageFunction != NULL );

	/* 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 );
		}

	/* Some objects (generally the system object and to a lesser extent other
	   devices and the default user object) may unlock themselves while 
	   processing a message when they forward the message elsewhere or perform 
	   non-object-specific processing.  If this may be the case then we pass 
	   in an extended message structure to record this information */
	initMessageExtInfo( &messageExtInfo, objectPtr );
	if( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) || \
		( handlingInfoPtr->flags & MESSAGE_HANDLING_FLAG_MAYUNLOCK ) )
		{
		mayUnlock = TRUE;
		objectPtr = &messageExtInfo;
		}

	/* 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 ];
	if( !isValidType( objectInfoPtr->type ) )
		retIntError();	/* Something catastrophic happened while unlocked */
	if( !( mayUnlock && isMessageObjectUnlocked( &messageExtInfo ) ) )
		objectInfoPtr->lockCount--;

	/* Postcondition: The lock count is non-negative and, if it's not the
	   system object, has been reset to its previous value */
	POST( objectInfoPtr->lockCount >= 0 && \
		  ( localObjectHandle == SYSTEM_OBJECT_HANDLE ||
			objectInfoPtr->lockCount == ORIGINAL_VALUE( lockCount ) ) );

	/* 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, *objectInfoPtr;
	MESSAGE_QUEUE_DATA enqueuedMessageData;
	const BOOLEAN isInternalMessage = isInternalMessage( message ) ? \
									  TRUE : FALSE;
	const void *aclPtr = NULL;
	MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
	int localObjectHandle = objectHandle, iterationCount = 0;
	int 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 */
	ENSURES( isValidMessage( localMessage ) );

	/* 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_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_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 ) ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_SETDEPTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_SETDEPTYPE && \
		   messageDataPtr != NULL && \
		   messageValue > SETDEP_OPTION_NONE && \
		   messageValue < SETDEP_OPTION_LAST ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_DATA_CERTMGMTTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_DATA_CERTMGMTTYPE && \
		   messageDataPtr != NULL && \
		   messageValue > CRYPT_CERTACTION_NONE && \
		   messageValue < CRYPT_CERTACTION_LAST ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_ANY_USERMGMTTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_ANY_USERMGMTTYPE && \
		   messageValue > MESSAGE_USERMGMT_NONE && \
		   messageValue < MESSAGE_USERMGMT_LAST ) );
	PRE( handlingInfoPtr->paramCheck != PARAMTYPE_ANY_TRUSTMGMTTYPE || \
		 ( handlingInfoPtr->paramCheck == PARAMTYPE_ANY_TRUSTMGMTTYPE && \
		   messageValue > MESSAGE_TRUSTMGMT_NONE && \
		   messageValue < MESSAGE_TRUSTMGMT_LAST ) );

⌨️ 快捷键说明

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