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

📄 sess_rw.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
			{
			/* Errors in the crypto are immediately fatal */
			sessionInfoPtr->writeErrorState = status;
			return( status );
			}

		/* Adjust the buffer position to account for the wrapped packet
		   size */
		sessionInfoPtr->sendBufPos = length;
		}
	length = sessionInfoPtr->sendBufPos - \
			 sessionInfoPtr->sendBufPartialBufPos;
	assert( length > 0 );

	/* Send the data through to the remote system */
	status = swrite( &sessionInfoPtr->stream, 
					 sessionInfoPtr->sendBuffer + \
						sessionInfoPtr->sendBufPartialBufPos,
					 length );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_TIMEOUT )
		{
		/* There was an error other than a (restartable) send timeout,
		   return the error details to the caller */
		sessionInfoPtr->writeErrorState = status;
		sNetGetErrorInfo( &sessionInfoPtr->stream,
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}

	/* If the send timed out before all of the data could be written, 
	   record how much still remains to be sent and inform the caller.  We
	   return this special-case code rather than either a timeout or
	   CRYPT_OK / 0 bytes because the caller can turn this into a situation-
	   specific status at the higher level, a timeout error for an explicit
	   flush but a CRYPT_OK / 0 for an implicit flush performed as part of a
	   write */
	if( status < length )
		{
		assert( status == CRYPT_ERROR_TIMEOUT || \
				( status >= 0 && status < length ) );

		/* If we wrote at least some part of the packet, adjust the partial-
		   write position by the amount that we wrote */
		if( status > 0 )
			sessionInfoPtr->sendBufPartialBufPos += status;

		assert( sessionInfoPtr->sendBufPartialBufPos < \
				sessionInfoPtr->sendBufPos );

		sessionInfoPtr->partialWrite = TRUE;
		return( OK_SPECIAL );
		}

	assert( status == length );

	/* We sent everything, reset the buffer status values */
	sessionInfoPtr->sendBufPos = sessionInfoPtr->sendBufStartOfs;
	sessionInfoPtr->partialWrite = FALSE;
	sessionInfoPtr->sendBufPartialBufPos = 0;

	return( CRYPT_OK );
	}

int putSessionData( SESSION_INFO *sessionInfoPtr, const void *data,
					const int length, int *bytesCopied )
	{
	BYTE *dataPtr = ( BYTE * ) data;
	int dataLength = length, status;

	/* Clear return value */
	*bytesCopied = 0;

	/* Sanity-check the write state */
	if( sessionInfoPtr->sendBufPos < sessionInfoPtr->sendBufStartOfs || \
		sessionInfoPtr->sendBufPos >= sessionInfoPtr->sendBufSize || \
		( !sessionInfoPtr->partialWrite && \
		  sessionInfoPtr->sendBufPos > sessionInfoPtr->sendBufStartOfs + \
									   sessionInfoPtr->maxPacketSize ) || \
		sessionInfoPtr->sendBufPartialBufPos < 0 || \
		sessionInfoPtr->sendBufPartialBufPos >= sessionInfoPtr->sendBufPos )
		{
		assert( NOTREACHED );
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Internal error: Inconsistent state detected in session "
				"write stream" );
		}

	/* If there's an error pending (which will always be fatal, see the
	   comment after the flushData() call below), set the current error state
	   to the pending state and return */
	if( cryptStatusError( sessionInfoPtr->pendingWriteErrorState ) )
		{
		assert( sessionInfoPtr->receiveBufPos == 0 );

		status = sessionInfoPtr->writeErrorState = \
						sessionInfoPtr->pendingWriteErrorState;
		sessionInfoPtr->pendingWriteErrorState = CRYPT_OK;
		return( status );
		}

	/* Update the stream write timeout to the current user-selected write 
	   timeout in case the user has changed the timeout setting */
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_WRITETIMEOUT, NULL,
			sessionInfoPtr->writeTimeout );

	/* If it's a flush, send the data through to the server.  If there's a 
	   timeout error during an explicit flush (that is, some but not all of
	   the data is written, so it's a soft timeout), it's converted into an 
	   explicit hard timeout failure */
	if( dataLength <= 0 )
		{
		const int oldBufPos = sessionInfoPtr->sendBufPartialBufPos;
		int bytesWritten;

		status = flushData( sessionInfoPtr );
		if( status != OK_SPECIAL )
			return( status );

		/* Since a partial write isn't a network-level error condition (it's 
		   only treated as a problem once it gets to the putSessionData() 
		   layer), there's no extended error information set for it, so we
		   have to set the error information here when we turn the partial
		   write into a timeout error */
		bytesWritten = sessionInfoPtr->sendBufPartialBufPos - oldBufPos;
		if( bytesWritten > 0 )
			retExt( sessionInfoPtr, CRYPT_ERROR_TIMEOUT,
					"Timeout during flush, only %d bytes were written "
					"before the timeout of %d seconds expired",
					sessionInfoPtr->sendBufPartialBufPos, 
					sessionInfoPtr->writeTimeout );
		retExt( sessionInfoPtr, CRYPT_ERROR_TIMEOUT,
				"Timeout during flush, no data could be written before the "
				"timeout of %d seconds expired", 
				sessionInfoPtr->writeTimeout );
		}

	/* If there's unwritten data from a previous write still in the buffer, 
	   flush that through first.  Since this isn't an explicit flush by the
	   caller we convert a soft timeout indicator into CRYPT_OK / 0 bytes */
	if( sessionInfoPtr->partialWrite )
		{
		status = flushData( sessionInfoPtr );
		if( cryptStatusError( status ) )
			return( ( status == OK_SPECIAL ) ? CRYPT_OK : status );
		}

	/* If there's too much data to fit in the buffer, send it through to the
	   host */
	while( ( sessionInfoPtr->sendBufPos - \
			 sessionInfoPtr->sendBufStartOfs ) + dataLength >= \
		   sessionInfoPtr->maxPacketSize )
		{
		const int bytesToCopy = sessionInfoPtr->maxPacketSize - \
								( sessionInfoPtr->sendBufPos + \
								  sessionInfoPtr->sendBufStartOfs );

		assert( bytesToCopy >= 0 && bytesToCopy <= dataLength );

		/* Copy in as much data as we have room for and send it through.  The
		   flush can return one of three classes of values:

			1. An error code, but not CRYPT_ERROR_TIMEOUT, which is handled
			   as case (2) below.
			2. OK_SPECIAL to indicate that some of the requested data 
			   (possibly 0 bytes) was written.
			3. CRYPT_OK to indicate that all of the requested data was
			   written and more can be written if necessary */
		if( bytesToCopy > 0 )
			{
			memcpy( sessionInfoPtr->sendBuffer + sessionInfoPtr->sendBufPos,
					dataPtr, bytesToCopy );
			sessionInfoPtr->sendBufPos += bytesToCopy;
			dataPtr += bytesToCopy;
			dataLength -= bytesToCopy;
			*bytesCopied += bytesToCopy;
			}
		status = flushData( sessionInfoPtr );
		if( cryptStatusError( status ) )
			{
			/* If it's a soft timeout indicator, convert it to a CRYPT_OK / 
			   0 bytes written */
			if( status == OK_SPECIAL )
				return( CRYPT_OK );

			/* There was a problem flushing the data through, if we managed 
			   to copy anything into the buffer we've made some progress so 
			   we defer it until the next call */
			if( *bytesCopied > 0 )
				{
				sessionInfoPtr->pendingWriteErrorState = status;
				return( CRYPT_OK );
				}

			/* Nothing was copied before the error occurred, it's 
			   immediately fatal */
			return( status );
			}
		}

	/* If there's anything left, it'll fit completely into the send buffer, 
	   just copy it in */
	if( dataLength > 0 )
		{
		assert( ( sessionInfoPtr->sendBufPos - \
				  sessionInfoPtr->sendBufStartOfs ) + dataLength < \
				sessionInfoPtr->maxPacketSize );

		memcpy( sessionInfoPtr->sendBuffer + sessionInfoPtr->sendBufPos,
				dataPtr, dataLength );
		sessionInfoPtr->sendBufPos += dataLength;
		*bytesCopied += dataLength;
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*				Request/response Session Data Handling Functions			*
*																			*
****************************************************************************/

/* Read/write a PKI (i.e.ASN.1-encoded) datagram */

int readPkiDatagram( SESSION_INFO *sessionInfoPtr )
	{
	int length, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* Read the datagram */
	sessionInfoPtr->receiveBufEnd = 0;
	status = sread( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer,
					sessionInfoPtr->receiveBufSize );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream,
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	if( status < 4 )
		/* Perform a sanity check on the length.  This avoids some
		   assertions in the debug build, and provides somewhat more
		   specific information for the caller than the invalid-encoding
		   error that we'd get later */
		retExt( sessionInfoPtr, CRYPT_ERROR_UNDERFLOW,
				"Invalid PKI message length %d", status );

	/* Find out how much data we got and perform a firewall check that
	   everything is OK.  We rely on this rather than the read byte count
	   since checking the ASN.1, which is the data that will actually be
	   processed, avoids any vagaries of server implementation oddities */
	length = checkObjectEncoding( sessionInfoPtr->receiveBuffer, status );
	if( cryptStatusError( length ) )
		retExt( sessionInfoPtr, length, "Invalid PKI message encoding" );
	sessionInfoPtr->receiveBufEnd = length;
	return( CRYPT_OK );
	}

int writePkiDatagram( SESSION_INFO *sessionInfoPtr )
	{
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( sessionInfoPtr->receiveBufEnd > 4 );

	/* Write the datagram */
	status = swrite( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer,
					 sessionInfoPtr->receiveBufEnd );
	if( cryptStatusError( status ) )
		sNetGetErrorInfo( &sessionInfoPtr->stream,
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
	sessionInfoPtr->receiveBufEnd = 0;

	return( CRYPT_OK );	/* swrite() returns a byte count */
	}
#endif /* USE_SESSIONS */

⌨️ 快捷键说明

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