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

📄 stream.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifndef NO_STDIO
	/* It's a file stream, find the position in the file */
#if defined( __WIN32__ )
	if( ( position = SetFilePointer( stream->hFile, 0, NULL,
									 FILE_CURRENT ) ) == 0xFFFFFFFF )
#elif defined( __MAC__ )
	if( GetFPos( stream->refNum, &position ) != noErr )
#else
	if( ( position = ftell( stream->filePtr ) ) == -1L )
#endif /* __WIN32__ */
		return( CRYPT_ERROR_READ );
#else
	assert( NOTREACHED );
#endif /* NO_STDIO */

	return( position );
	}

/* Determine whether a stream is out of data */

int seof( const STREAM *stream )
	{
	return( stream->status == CRYPT_ERROR_UNDERFLOW );
	}

/* Skip a number of bytes in a stream */

int sSkip( STREAM *stream, const long length )
	{
	long skipLength = length;

	assert( stream != NULL && \
			( stream->type == STREAM_TYPE_NULL || \
			  stream->type == STREAM_TYPE_MEMORY || \
			  stream->type == STREAM_TYPE_FILE ) );
	assert( length > 0 );

	/* If there's a problem with the stream, don't try to do anything */
	if( stream->status != CRYPT_OK )
		return( stream->status );

	/* If we were ready to unget a char, skip it */
	if( stream->ungetChar )
		{
		stream->ungetChar = FALSE;
		stream->lastChar = 0;
		skipLength--;
		if( skipLength == 0 )
			return( CRYPT_OK );
		}

	/* If it's a memory or null stream, move ahead in the buffer */
	if( stream->type == STREAM_TYPE_NULL )
		{
		stream->bufPos += ( int ) skipLength;
		return( CRYPT_OK );
		}
	if( stream->type == STREAM_TYPE_MEMORY )
		{
		if( stream->bufSize != STREAMSIZE_UNKNOWN && \
			stream->bufPos + skipLength > stream->bufSize )
			{
			stream->bufPos = stream->bufSize;
			stream->status = CRYPT_ERROR_UNDERFLOW;
			return( CRYPT_ERROR_UNDERFLOW );
			}
		stream->bufPos += ( int ) skipLength;
		if( stream->bufPos > stream->bufEnd )
			/* If we've moved past the end of the valid data in the buffer,
			   move the end of data pointer to match the current position.
			   This mimics the behaviour of fseek(), which allows a seek past
			   the end of the file */
			stream->bufEnd = stream->bufPos;

		return( CRYPT_OK );
		}

#ifndef NO_STDIO
	/* It's a file stream, skip the data in the file */
#if defined( __WIN32__ )
	if( SetFilePointer( stream->hFile, skipLength, NULL,
						FILE_CURRENT ) == 0xFFFFFFFF )
#elif defined( __MAC__ )
	if( SetFPos( stream->refNum, fsFromMark, skipLength) != noErr )
#else
	if( fseek( stream->filePtr, skipLength, SEEK_CUR ) )
#endif /* __WIN32__ */
		{
		stream->status = CRYPT_ERROR_READ;
		return( CRYPT_ERROR_READ );
		}
#endif /* NO_STDIO */

	return( CRYPT_OK );
	}

/* Perform an IOCTL on a stream */

int sioctl( STREAM *stream, const STREAM_IOCTL_TYPE type, void *data, 
			const int dataLen )
	{
	assert( stream != NULL && stream->type == STREAM_TYPE_NETWORK );
	assert( type > STREAM_IOCTL_NONE && type < STREAM_IOCTL_LAST );

	switch( type )
		{
		case STREAM_IOCTL_TIMEOUT:
			assert( data == NULL );
			assert( dataLen >= 0 );

			stream->timeout = dataLen;
			break;

		case STREAM_IOCTL_GETTIMEOUT:
			assert( data != NULL );
			assert( dataLen == 0 );

			*( ( int * ) data ) = stream->timeout;
			break;

		case STREAM_IOCTL_GETCLIENTNAME:
			assert( data != NULL );
			assert( dataLen == 0 );

			strcpy( data, stream->clientAddress );
			break;

		case STREAM_IOCTL_GETCLIENTPORT:
			assert( data != NULL );
			assert( dataLen == 0 );

			*( ( int * ) data ) = stream->clientPort;
			break;

		case STREAM_IOCTL_CONTENTTYPE:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( data != NULL );
			assert( dataLen > 0 && dataLen < CRYPT_MAX_TEXTSIZE );

			memcpy( stream->contentType, data, dataLen );
			stream->contentType[ dataLen ] = '\0';
			break;

		case STREAM_IOCTL_QUERY:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( data != NULL );
			assert( dataLen > 0 && dataLen < CRYPT_MAX_TEXTSIZE );

			/* Set up the buffer to contain the query if necessary */
			if( stream->queryLen <= dataLen )
				{
				if( stream->query != NULL )
					{
					free( stream->query );
					stream->queryLen = 0;
					}
				if( ( stream->query = malloc( max( CRYPT_MAX_TEXTSIZE, \
												   dataLen + 1 ) ) ) == NULL )
					return( CRYPT_ERROR_MEMORY );
				stream->queryLen = dataLen;
				}

			/* Copy in the query */
			memcpy( stream->query, data, dataLen );
			stream->query[ dataLen ] = '\0';
			break;

		case STREAM_IOCTL_LASTMESSAGE:
			assert( stream->protocol == STREAM_PROTOCOL_CMP );
			assert( data == NULL );
			assert( dataLen == TRUE );

			stream->lastMessage = TRUE;
			break;

		case STREAM_IOCTL_CALLBACKFUNCTION:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( data != NULL );
			assert( dataLen == 0 );

			stream->callbackFunction = ( CALLBACKFUNCTION ) data;
			break;

		case STREAM_IOCTL_CALLBACKPARAMS:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( data != NULL );
			assert( dataLen == 0 );

			stream->callbackParams = data;
			break;

		default:
			assert( NOTREACHED );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Memory Stream Functions							*
*																			*
****************************************************************************/

/* Open a memory stream.  If the buffer parameter is NULL and the length is
   zero, this creates a null stream which serves as a data sink - this is
   useful for implementing sizeof() functions by writing data to null
   streams */

int sMemOpen( STREAM *stream, void *buffer, const int length )
	{
	assert( stream != NULL );
	assert( ( buffer == NULL && length == 0 ) || \
			( buffer != NULL && \
			  ( length > 1 || length == STREAMSIZE_UNKNOWN ) ) );

	memset( stream, 0, sizeof( STREAM ) );
	if( buffer == NULL )
		{
		/* Make it a null stream */
		stream->type = STREAM_TYPE_NULL;
		return( CRYPT_OK );
		}

	/* Initialise the stream structure */
	stream->type = STREAM_TYPE_MEMORY;
	stream->buffer = buffer;
	stream->bufSize = length;
	if( stream->bufSize != STREAMSIZE_UNKNOWN )
		/* The stream buffers can be arbitrarily large so we only clear
		   the entire buffer in the debug version */
#ifdef NDEBUG
		memset( stream->buffer, 0, stream->bufSize );
#else
		memset( stream->buffer, 0, min( 256, stream->bufSize ) );
#endif /* NDEBUG */

	return( CRYPT_OK );
	}

/* Close a memory stream */

int sMemClose( STREAM *stream )
	{
	assert( stream != NULL && \
			( stream->type == STREAM_TYPE_NULL || \
			  stream->type == STREAM_TYPE_MEMORY ) );

	/* Clear the stream structure */
	if( stream->buffer != NULL )
		if( stream->bufSize != STREAMSIZE_UNKNOWN )
			zeroise( stream->buffer, stream->bufSize );
		else
			/* If it's of an unknown size we can still zap as much as was
			   written to/read from it */
			if( stream->bufEnd > 0 )
				zeroise( stream->buffer, stream->bufEnd );
	zeroise( stream, sizeof( STREAM ) );

	return( CRYPT_OK );
	}

/* Connect a memory stream without destroying the buffer contents */

int sMemConnect( STREAM *stream, const void *buffer, const int length )
	{
	assert( stream != NULL );
	assert( buffer != NULL );
	assert( length >= 1 || length == STREAMSIZE_UNKNOWN );

	/* Initialise the stream structure */
	memset( stream, 0, sizeof( STREAM ) );
	stream->type = STREAM_TYPE_MEMORY;
	stream->buffer = ( void * ) buffer;
	stream->bufSize = stream->bufEnd = length;
	stream->flags = STREAM_FLAG_READONLY;

	return( CRYPT_OK );
	}

/* Disconnect a memory stream without destroying the buffer contents */

int sMemDisconnect( STREAM *stream )
	{
	assert( stream != NULL && \
			( stream->type == STREAM_TYPE_NULL || \
			  stream->type == STREAM_TYPE_MEMORY ) );

	/* Clear the stream structure */
	memset( stream, 0, sizeof( STREAM ) );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							File Stream Functions							*
*																			*
****************************************************************************/

/* Usually we'd use the C stdio routines for file I/O, but we can get 
   enhanced control over things like file security and buffering by using
   OS-level file routines (in fact this is almost essential to work with 
   things like ACL's for sensitive files and forcing disk writes for files we
   want to erase.  Without the forced disk write the data in the cache
   doesn't get flushed before the file delete request arrives, after which
   it's discarded rather than being written, so the file never gets
   overwritten).  In addition some embedded environments don't support stdio
   so we have to supply our own alternatives.
   
   When implementing the following for new systems there are certain things
   which you need to ensure to guarantee error-free operation:

	- File permissions should be set as indicated by the file open flags.
	- File sharing controls (shared vs exclusive access locks) should be 
	  implemented.
	- If the file is locked for exclusive access, the open call should either
	  block until the lock is released (they're never held for more than a
	  fraction of a second) or return CRYPT_ERROR_BUSY depending on how the
	  OS handles locks */

/* Open a file stream */

#if defined( __WIN32__ )

/* Get information on the current user.  This works in an extraordinarily
   ugly manner because although the TOKEN_USER struct is only 8 bytes long,
   Windoze allocates an extra 24 bytes after the end of the struct into which
   it stuffs data which the SID in the TOKEN_USER struct points to.  This
   means we can't return the SID pointer from the function because it would
   point to freed memory, so we need to return the pointer to the entire
   TOKEN_USER struct to ensure that what the SID pointer points to remains
   around for the caller to use */

TOKEN_USER *getUserInfo( void )
	{
	TOKEN_USER *pUserInfo = NULL;
	HANDLE hToken = INVALID_HANDLE_VALUE;	/* See comment below */
	DWORD cbTokenUser;

	/* Get the security token for this thread.  We initialise the hToken even
	   though it shouldn't be necessary because Windows tries to read its
	   contents, which indicates there might be problems if it happens to
	   have the wrong value */
	if( !OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken ) )
		{
		/* If the thread doesn't have a security token, try the token 
		   associated with the process */
		if( ( GetLastError() != ERROR_NO_TOKEN ) || \
			!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
			return( NULL );
		}

	/* Query the size of the user information associated with the token,
	   allocate a buffer for it, and fetch the information into the buffer */
	GetTokenInformation( hToken, TokenUser, NULL, 0, &cbTokenUser );
	if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
		{
		pUserInfo = ( TOKEN_USER * ) malloc( cbTokenUser );
		if( !GetTokenInformation( hToken, TokenUser, pUserInfo, cbTokenUser,
								 &cbTokenUser ) )
			{
			free( pUserInfo );
			pUserInfo = NULL;
			}
		}

	/* Clean up */
	CloseHandle( hToken );
	return( pUserInfo );
	}

int sFileOpen( STREAM *stream, const char *fileName, const int mode )
	{
	SECURITY_ATTRIBUTES sa;
	LPSECURITY_ATTRIBUTES lpsa = NULL;
	SECURITY_DESCRIPTOR sdPermissions;
	TOKEN_USER *pUserInfo = NULL;
	BYTE aclBuffer[ ACL_BUFFER_SIZE ];
	PACL paclKey = ( PACL ) aclBuffer;
	HANDLE hFile;
	UINT uErrorMode;
	int status;

	assert( stream != NULL );
	assert( fileName != NULL );
	assert( mode != 0 );

	/* Initialise the stream structure */
	memset( stream, 0, sizeof( STREAM ) );
	stream->type = STREAM_TYPE_FILE;
	if( ( mode & FILE_RW_MASK ) == FILE_READ )
		stream->flags = STREAM_FLAG_READONLY;

	/* If we're creating the file and we don't want others to get to it, set
	   up the security attributes to reflect this provided the OS supports
	   security */
	if( !isWin95 && ( mode & FILE_WRITE ) && ( mode & FILE_PRIVATE ) )
		{
		/* Get the SID for the current user */
		if( ( pUserInfo = getUserInfo() ) == NULL )
			return( CRYPT_ERROR_OPEN );

⌨️ 快捷键说明

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