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

📄 stream.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Set the current user to own this security descriptor */
		if( !InitializeSecurityDescriptor( &sdPermissions,
										   SECURITY_DESCRIPTOR_REVISION1 ) || \
			!SetSecurityDescriptorOwner( &sdPermissions, pUserInfo->User.Sid, 0 ) )
			{
			free( pUserInfo );
			return( CRYPT_ERROR_OPEN );
			}

		/* Set up the discretionary access control list (DACL) with one
		   access control entry (ACE) for the current user which allows full
		   access.  We give the user a somewhat odd set of access rights
		   rather than the more restricted set which would make sense because
		   this set is detected as "Full control" access instead of the
		   peculiar collection of rights we'd get from the more sensible
		   GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL.  The OS can
		   check the full-access ACL much quicker than the one with the more
		   restricted access permissions */
		if( !InitializeAcl( paclKey, ACL_BUFFER_SIZE, ACL_REVISION2 ) || \
			!AddAccessAllowedAce( paclKey, ACL_REVISION2,
								  GENERIC_ALL | STANDARD_RIGHTS_ALL,
								  pUserInfo->User.Sid ) )
			{
			free( pUserInfo );
			return( CRYPT_ERROR_OPEN );
			}

		/* Bind the DACL to the security descriptor */
		if( !SetSecurityDescriptorDacl( &sdPermissions, TRUE, paclKey, FALSE ) )
			{
			free( pUserInfo );
			return( CRYPT_ERROR_OPEN );
			}

		/* Finally, set up the security attributes structure */
		sa.nLength = sizeof( SECURITY_ATTRIBUTES );
		sa.bInheritHandle = FALSE;
		sa.lpSecurityDescriptor = &sdPermissions;
		lpsa = &sa;
		}

	/* Check that the file isn't a special file type, for example a device 
	   pseudo-file which can crash the system under Win95/98/whatever */
	hFile = CreateFile( fileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
						OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
	if( hFile != INVALID_HANDLE_VALUE )
		{
		const DWORD type = GetFileType( hFile );
		
		CloseHandle( hFile );
		if( type != FILE_TYPE_DISK )
			{
			if( pUserInfo != NULL )
				free( pUserInfo );
			return( CRYPT_ERROR_OPEN );
			}
		}

	/* Try and open the file */
	uErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS );
	if( ( mode & FILE_RW_MASK ) == FILE_WRITE )
		stream->hFile = CreateFile( fileName, GENERIC_READ | GENERIC_WRITE, 0, lpsa,
									CREATE_ALWAYS,
									FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
									NULL );
	else
		{
		const int openMode = ( ( mode & FILE_RW_MASK ) == FILE_READ ) ? \
							 GENERIC_READ : GENERIC_READ | GENERIC_WRITE;
		const int shareMode = ( mode & FILE_EXCLUSIVE_ACCESS ) ? \
							  0 : FILE_SHARE_READ;	

		stream->hFile = CreateFile( fileName, openMode, shareMode, NULL, 
									OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 
									NULL );
		}
	SetErrorMode( uErrorMode );
	if( stream->hFile == INVALID_HANDLE_VALUE )
		{
		DWORD dwErrorCode = GetLastError();

		/* Translate the Win32 error code into an equivalent cryptlib error
		   code */
		if( dwErrorCode == ERROR_FILE_NOT_FOUND || \
			dwErrorCode == ERROR_PATH_NOT_FOUND )
			status = CRYPT_ERROR_NOTFOUND;
		else
			if( dwErrorCode == ERROR_ACCESS_DENIED )
				status = CRYPT_ERROR_PERMISSION;
			else
				if( dwErrorCode == ERROR_BUSY )
					status = CRYPT_ERROR_BUSY;
				else
					status = CRYPT_ERROR_OPEN;
		if( pUserInfo != NULL )
			free( pUserInfo );
		return( status );
		}

	/* Clean up */
	if( pUserInfo != NULL )
		free( pUserInfo );
	return( CRYPT_OK );
	}

#elif defined( __MAC__ )

int sFileOpen( STREAM *stream, const char *fileName, const int mode )
	{
	Str255 pFileName;
	OSErr err;

	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;

	CStringToPString( fileName, pFileName );

	err = FSMakeFSSpec(0, 0, pFileName, &stream->fsspec );
	if( err == dirNFErr || err == nsvErr )
		/* Volume or parent directory not found */
		return CRYPT_ERROR_NOTFOUND;
	if( err != noErr && err != fnfErr )
		/* fnfErr is OK since the fsspec is still valid */
		return CRYPT_ERROR_OPEN;

	if( mode & FILE_WRITE )
		{
		/* Try and create the file, specifying its type and creator */
		err = FSpCreate( &stream->fsspec, '????', 'CLib', smSystemScript );
		if ( err == wPrErr || err == vLckdErr || err == afpAccessDenied )
			return CRYPT_ERROR_PERMISSION;
		if ( err != noErr && err != dupFNErr && err != afpObjectTypeErr )
			return CRYPT_ERROR_OPEN;
		}

	err = FSpOpenDF( &stream->fsspec, mode & FILE_RW_MASK, &stream->refNum );
	if( err == nsvErr || err == dirNFErr || err == fnfErr )
		return CRYPT_ERROR_NOTFOUND;
	if( err == opWrErr || err == permErr || err == afpAccessDenied )
		return CRYPT_ERROR_PERMISSION;
	if( err != noErr )
		return CRYPT_ERROR_OPEN;

	return( CRYPT_OK );
	}

#elif defined( NO_STDIO )

int sFileOpen( STREAM *stream, const char *fileName, const int mode )
	{
	const BOOLEAN useBBRAM = ( mode & FILE_SENSITIVE ) ? TRUE : FALSE;
	long length, status;

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

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

#if defined( __IBM4758__ )
	/* Make sure the filename matches the 4758's data item naming conventions
	   and remember the filename.  The best error code to return if there's
	   a problem is a file open error, since this is buried so many levels
	   down that a parameter error won't be meaningful to the caller */
	if( strlen( fileName ) > 8 )
		return( CRYPT_ERROR_OPEN );
	strcpy( stream->name, fileName );

	/* If we're doing a read, fetch the data into memory and convert the
	   stream to a memory stream (which is done implicitly by allocating a
	   memory buffer for it) */
	if( mode & FILE_READ )
		{
		/* Find out how big the data item is and allocate a buffer for
		   it */
		status = sccGetPPDLen( ( char * ) fileName, &length );
		if( status != PPDGood )
			return( ( status == PPD_NOT_FOUND ) ? CRYPT_ERROR_NOTFOUND : \
					( status == PPD_NOT_AUTHORIZED ) ? CRYPT_ERROR_PERMISSION : \
					CRYPT_ERROR_OPEN );
		if( ( stream->buffer = malloc( length ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		stream->bufSize = stream->bufEnd = length;
		stream->isIOStream = TRUE;

		/* Fetch the data into the buffer so it can be read as a memory
		   stream */
		status = sccGetPPD( ( char * ) fileName, stream->buffer, length );
		return( ( status != PPDGood ) ? CRYPT_ERROR_READ : CRYPT_OK );
		}

	/* We're doing a write, make sure there's enough room available (this
	   doesn't guarantee that there'll be enough when the data is committed,
	   but it makes sense to at least check when the "file" is opened) */
	status = sccQueryPPDSpace( &length, ( useBBRAM ) ? PPD_BBRAM : PPD_FLASH );
	if( status != PPDGood || length < STREAM_BUFSIZE )
		return( CRYPT_ERROR_OPEN );
#elif defined( __VMCMS__ )
	/* If we're going to be doing a write either now or later, we can't open
	   the file until we have all the data to write to it available since the
	   open arg has to include the file format information so all we can do at
	   this point is remember the name for later use */
	strcpy( stream->name, fileName );

	/* If we're doing a read, fetch the data into memory and convert the
	   stream to a memory stream (which is done implicitly by allocating a
	   memory buffer for it) */
	if( mode & FILE_READ )
		{
		FILE *filePtr;
		fldata_t fileData;
		char fileBuffer[ MAX_PATH_LENGTH ], formatBuffer[ 32 ];
		int count;

		/* Open the file and determine how large it is */
		filePtr = fopen( fileName, "rb" );
		if( filePtr == NULL )
			return( CRYPT_ERROR_OPEN );
		status = fldata( filePtr, fileBuffer, &fileData );
		if( status )
			{
			fclose( filePtr );
			return( CRYPT_ERROR_OPEN );
			}
		length = fileData.__maxreclen;

		/* Fetch the data into the buffer so it can be read as a memory
		   stream */
		if( ( stream->buffer = malloc( length ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		stream->bufSize = stream->bufEnd = length;
		stream->isIOStream = TRUE;
		status = fread( stream->buffer, length, 1, filePtr );
		fclose( filePtr );
		return( ( status != 1 ) ? CRYPT_ERROR_READ : CRYPT_OK );
		}
#else
	#error Need to add mechanism to read data from backing store
#endif /* Nonstandard I/O enviroments */

	/* Allocate the initial I/O buffer for the data */
	if( ( stream->buffer = malloc( STREAM_BUFSIZE ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	stream->bufSize = STREAM_BUFSIZE;
	stream->isSensitive = useBBRAM;
	stream->isIOStream = TRUE;

	return( CRYPT_OK );
	}

#else

int sFileOpen( STREAM *stream, const char *fileName, const int mode )
	{
#if defined( __UNIX__ ) && defined( sun )
	/* Under Slowaris the read/write mode must be given as r+b rather
	   than rb+ because of a bug in the stdio library */
	static const char *modes[] = { "x", "rb", "wb", "r+b" };
#else
	static const char *modes[] = { "x", "rb", "wb", "rb+" };
#endif /* Sun stdio bug */
	const char *openMode;

	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;
	openMode = modes[ mode & FILE_RW_MASK ];

	/* If we're trying to write to the file, check whether we've got
	   permission to do so */
	if( ( mode & FILE_WRITE ) && fileReadonly( fileName ) )
		return( CRYPT_ERROR_PERMISSION );

	/* Under Unix we try to defend against writing through links, but this is
	   somewhat difficult since the there's no atomic way to do this, and
	   without resorting to low-level I/O it can't be done at all.  What we
	   do is lstat() the file, open it as appropriate, and if it's an
	   existing file ftstat() it and compare various important fields to make
	   sure the file wasn't changed between the lstat() and the open().  If
	   everything is OK, we then use the lstat() information to make sure it
	   isn't a symlink (or at least that it's a normal file) and that the
	   link count is 1.  These checks also catch other weird things like
	   STREAMS stuff fattach()'d over files.

	   If these checks pass and the file already exists we truncate it to
	   mimic the effect of an open with create.  Finally, we use fdopen() to
	   convert the file handle for stdio use */
#ifdef __UNIX__
	if( ( mode & FILE_RW_MASK ) == FILE_WRITE )
		{
		struct stat lstatInfo;
		char *mode = "rb+";
		int fd;

		/* lstat() the file.  If it doesn't exist, create it with O_EXCL.  If
		   it does exist, open it for read/write and perform the fstat()
		   check */
		if( lstat( fileName, &lstatInfo ) == -1 )
			{
			/* If the lstat() failed for reasons other than the file not
			   existing, return a file open error */
			if( errno != ENOENT )
				return( CRYPT_ERROR_OPEN );

			/* The file doesn't exist, create it with O_EXCL to make sure an
			   attacker can't slip in a file between the lstat() and open() */
			if( ( fd = open( fileName, O_CREAT | O_EXCL | O_RDWR, 0600 ) ) == -1 )
				return( CRYPT_ERROR_OPEN );
			mode = "wb";
			}
		else
			{
			struct stat fstatInfo;

			/* Open an existing file */
			if( ( fd = open( fileName, O_RDWR ) ) == -1 )
				return( CRYPT_ERROR_OPEN );

			/* fstat() the opened file and check that the file mode bits and
			   inode and device match */
			if( fstat( fd, &fstatInfo ) == -1 || \
				lstatInfo.st_mode != fstatInfo.st_mode || \
				lstatInfo.st_ino != fstatInfo.st_ino || \
				lstatInfo.st_dev != fstatInfo.st_dev )
				{
				close( fd );
				return( CRYPT_ERROR_OPEN );
				}

			/* If the above check was passed, we know that the lstat() and
			   fstat() were done to the same file.  Now check that there's
			   only one link, and that it's a normal file (this isn't
			   strictly necessary because the fstat() vs lstat() st_mode
			   check would also find this) */
			if( fstatInfo.st_nlink > 1 || !S_ISREG( lstatInfo.st_mode ) )
				{
				close( fd );
				return( CRYPT_ERROR_OPEN );
				}

			/* Turn the file into an empty file */
			ftruncate( fd, 0 );
			}

		/* Open a stdio file over the low-level one */
		stream->filePtr = fdopen( fd, mode );
		if( stream->filePtr == NULL )
			{
			close( fd );
			unlink( fileName );
			return( CRYPT_ERROR_OPEN );
			}
		}
	else
#endif /* __UNIX__ */
#if defined( __UNIX__ ) || defined( __MSDOS16__ ) || defined( __WIN16__ ) || \
	defined( __OS2__ )
	/* Try and open the file */
	stream->filePtr = fopen( fileName, openMode );
	if( stream->filePtr == NULL )
		/* The open failed, determine whether it was because the file doesn't
		   exist or because we can't use that access mode */
		return( ( access( fileName, 0 ) == -1 ) ? \
				CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );
#elif defined( __TANDEM__ )
	stream->filePtr = fopen( fileName, openMode );
	if( stream->filePtr == NULL )
		return( ( errno == ENOENT ) ? \
				CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );
#else
  #error Need to add file accessibility call
#endif /* OS-specific file accessibility check */

	/* Set the file access permissions so only the owner can access it if
	   necessary */
#if defined( __UNIX__ )
	if( mode & FILE_PRIVATE )
		chmod( fileName, 0600 );
#endif /* __UNIX__ */

	/* Lock the file if necessary to make sure noone else tries to do things
	   to it.  We don't do anything fancy with timeouts and whatnot because
	   no process should ever lock the file for more than a fraction of a
	   second, in theory this could lead to a hung process causing all other
	   process which try to access the file to also hang, but since they 
	   can't access the file anyway they'd just end up failing in a less
	   obvious way */
#ifdef __UNIX__
	flock(

⌨️ 快捷键说明

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