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

📄 cryptusr.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
									  RESOURCE_IMESSAGE_GETATTRIBUTE, 
									  &value, CRYPT_CERTINFO_KEYUSAGE );
			if( cryptStatusError( status ) || !( value & requiredKeyUsage ) )
				return( CRYPT_ARGERROR_NUM1 );

			/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
			/* Save this in the keyset at some point */
			/* Handle get (gets public key) */
			/* Handle delete (removes key) */
			/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

			unlockResourceExit( userInfoPtr, status );
			}

		/* Anything else has to be a config option */
		assert( message == RESOURCE_MESSAGE_SETATTRIBUTE || \
				message == RESOURCE_MESSAGE_GETATTRIBUTE || \
				message == RESOURCE_MESSAGE_SETATTRIBUTE_S || \
				message == RESOURCE_MESSAGE_GETATTRIBUTE_S );
		assert( messageValue > CRYPT_OPTION_FIRST && \
				messageValue < CRYPT_OPTION_LAST );

		/* Get/set string attributes */
		if( message == RESOURCE_MESSAGE_GETATTRIBUTE_S )
			{
			RESOURCE_DATA *msgData = messageDataPtr;
			const char *retVal = getOptionString( userInfoPtr->configOptions, 
												  messageValue );
			if( retVal == NULL )
				{
				/* No value set, clear the return value in case the caller
				   isn't checking the return code */
				if( msgData->data != NULL )
					*( ( char * ) msgData->data ) = '\0';
				msgData->length = 0;
				status = CRYPT_ERROR_NOTFOUND;
				}
			else
				status = attributeCopy( msgData, retVal, strlen( retVal ) );
			unlockResourceExit( userInfoPtr, status );
			}
		if( message == RESOURCE_MESSAGE_SETATTRIBUTE_S )
			{
			const RESOURCE_DATA *msgData = messageDataPtr;

			status = setOptionString( userInfoPtr->configOptions, 
									  messageValue, msgData->data,
									  msgData->length );
			unlockResourceExit( userInfoPtr, status );
			}

		/* Get/set numeric attributes */
		if( message == RESOURCE_MESSAGE_GETATTRIBUTE )
			{
			/* Numeric get can never fail */
			*( ( int * ) messageDataPtr ) = \
							getOption( userInfoPtr->configOptions, 
									   messageValue );
			unlockResourceExit( userInfoPtr, CRYPT_OK );
			}
		status = setOption( userInfoPtr->configOptions, messageValue, 
							*( ( int * ) messageDataPtr ) );
		if( !( status == OK_SPECIAL && \
			 ( messageValue == CRYPT_OPTION_CONFIGCHANGED || \
			   messageValue == CRYPT_OPTION_SELFTESTOK ) ) )
			unlockResourceExit( userInfoPtr, status );

		/* The following options control operations which are performed
		   in two phases.  The reason for the split is that the second phase 
		   doesn't require the use of the user object data any more and can 
		   be a somewhat lengthy process due to disk accesses or lengthy 
		   crypto operations.  Because of this we unlock the user object 
		   between the two phases to ensure that the second phase doesn't 
		   stall all other operations which require this user object */		
		assert( status == OK_SPECIAL );

		/* If it's a self-test, forward the message to the system object with
		   the user object unlocked, then re-lock it and set the self-test
		   result value.  Since the self-test value will be in the busy state
		   at this point, we need to update it by setting the 
		   CRYPT_OPTION_LAST pseudo-option */
		if( messageValue == CRYPT_OPTION_SELFTESTOK )
			{
			unlockResource( userInfoPtr );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							RESOURCE_IMESSAGE_SETATTRIBUTE, 
							MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_SELFTEST );
			getCheckInternalResource( cryptUser, userInfoPtr, OBJECT_TYPE_USER );
			setOption( userInfoPtr->configOptions, CRYPT_OPTION_LAST, 
					   cryptStatusOK( status ) ? TRUE : FALSE );
			unlockResourceExit( userInfoPtr, status );
			}

		/* The config option write is performed in two phases, a first phase 
		   which encodes the config data and a second phase which writes the 
		   data to disk */
		assert( messageValue == CRYPT_OPTION_CONFIGCHANGED );
		if( userInfoPtr->fileRef == CRYPT_UNUSED )
			strcpy( userFileName, "cryptlib" );
		else
			sprintf( userFileName, "u%06x", userInfoPtr->fileRef );
		status = encodeConfigData( userInfoPtr->configOptions, 
								   userFileName, &data, &length );
		if( status != OK_SPECIAL )
			unlockResourceExit( userInfoPtr, status );

		/* We've got the config data in a memory buffer, we can unlock the 
		   user object to allow external access while we commit the in-memory 
		   data to disk */
		unlockResource( userInfoPtr );
		status = commitConfigData( userFileName, data, length );
		free( data );
		return( status );
		}

	/* Process messages which lock/unlock an object for exclusive use */
	if( message == RESOURCE_MESSAGE_LOCK )
		/* Exit without unlocking the object.  Any other threads trying to
		   use the object after this point will be blocked */
		return( CRYPT_OK );
	if( message == RESOURCE_MESSAGE_UNLOCK )
		{
		/* "Wenn drei Leute in ein Zimmer reingehen und fuenf kommen raus,
		   dann muessen erst mal zwei wieder reingehen bis das Zimmer leer
		   ist" */
		unlockResource( userInfoPtr );	/* Undo RESOURCE_MESSAGE_LOCK lock */
		unlockResourceExit( userInfoPtr, CRYPT_OK );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/* Open a user object.  This is a low-level function encapsulated by 
   createUser() and used to manage error exits */

static int openUser( CRYPT_USER *iCryptUser, const CRYPT_USER cryptOwner,
					 const USER_FILE_INFO *userFileInfo, 
					 USER_INFO **userInfoPtrPtr )
	{
	USER_INFO *userInfoPtr;
	const int subType = \
		( userFileInfo->type == CRYPT_USER_NORMAL ) ? SUBTYPE_USER_NORMAL : \
		( userFileInfo->type == CRYPT_USER_SO ) ? SUBTYPE_USER_SO : \
		( userFileInfo->type == CRYPT_USER_CA ) ? SUBTYPE_USER_CA : \
		( SUBTYPE_USER_NORMAL | SUBTYPE_USER_SO );
	int status;

	/* The default user is a special type which has both normal user and SO
	   privileges.  This is because in its usual usage mode where cryptlib is 
	   functioning as a single-user system the user doesn't know about the
	   existence of user objects and just wants everything to work the way
	   they expect.  Because of this, the default user has to be able to
	   perform the full range of available operations, requiring that they
	   appear as both a normal user and an SO */
	assert( userFileInfo->type == CRYPT_USER_NORMAL || \
			userFileInfo->type == CRYPT_USER_SO || \
			userFileInfo->type == CRYPT_USER_CA || \
			( userFileInfo->type == CRYPT_USER_NONE && \
			  userFileInfo->userNameLength == \
								defaultUserInfo.userNameLength && \
			  !memcmp( userFileInfo->userName, defaultUserInfo.userName, 
					   defaultUserInfo.userNameLength ) ) );

	/* Clear the return values */
	*iCryptUser = CRYPT_ERROR;
	*userInfoPtrPtr = NULL;

	/* Create the user object */
	status = krnlCreateObject( ( void ** ) &userInfoPtr, cryptOwner,
							   OBJECT_TYPE_USER, subType, 
							   sizeof( USER_INFO ), 0, 0, 
							   userMessageFunction );
	if( cryptStatusError( status ) )
		return( status );
	initResourceLock( userInfoPtr );
	lockResource( userInfoPtr );
	*userInfoPtrPtr = userInfoPtr;
	*iCryptUser = userInfoPtr->objectHandle = status;
	userInfoPtr->type = userFileInfo->type;
	userInfoPtr->state = userFileInfo->state;
	userInfoPtr->fileRef = userFileInfo->fileRef;
	memcpy( userInfoPtr->userName, userFileInfo->userName, 
			userFileInfo->userNameLength );
	userInfoPtr->userNameLength = userFileInfo->userNameLength;
	memcpy( userInfoPtr->userID, userFileInfo->userID, KEYID_SIZE );
	memcpy( userInfoPtr->creatorID, userFileInfo->creatorID, KEYID_SIZE );

	/* Set up any internal objects to contain invalid handles */
	userInfoPtr->iKeyset = userInfoPtr->iCryptContext = CRYPT_ERROR;

	/* Initialise the default user config options */
	return( initOptions( &userInfoPtr->configOptions ) );
	}

int createUser( MESSAGE_CREATEOBJECT_INFO *createInfo, 
				const void *auxDataPtr, const int auxValue )
	{
	CRYPT_USER iCryptUser;
	USER_INFO *userInfoPtr;
	char userFileName[ 16 ];
	int fileRef, initStatus, status;

	assert( auxDataPtr == NULL );
	assert( auxValue == 0 );

	/* Perform basic error checking */
	if( createInfo->strArgLen1 < 2 || \
		createInfo->strArgLen1 > CRYPT_MAX_TEXTSIZE )
		return( CRYPT_ARGERROR_STR1 );
	if( createInfo->strArgLen2 < 2 || \
		createInfo->strArgLen2 > CRYPT_MAX_TEXTSIZE )
		return( CRYPT_ARGERROR_STR2 );

	/* We can't create another user object with the same name as the 
	   cryptlib default user (actually we could and nothing bad would happen, 
	   but we reserve the use of this name just in case) */
	if( createInfo->strArgLen1 == defaultUserInfo.userNameLength && \
		!strnicmp( createInfo->strArg1, defaultUserInfo.userName, 
				   defaultUserInfo.userNameLength ) )
		return( CRYPT_ERROR_INITED );

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* Logging on with the primary SO default password triggers a zeroise, 
   normally we can only use this login after a zeroise but currently there's
   no way for a user to trigger this so we perform it at the same time as
   the login - the effect is the same, it just combines two operations in 
   one */
if( createInfo->strArgLen2 == PRIMARYSO_PASSWORD_LENGTH && \
	( !memcmp( createInfo->strArg2, PRIMARYSO_PASSWORD, 
			   PRIMARYSO_PASSWORD_LENGTH ) || \
	  !memcmp( createInfo->strArg2, PRIMARYSO_ALTPASSWORD, 
			   PRIMARYSO_PASSWORD_LENGTH ) ) )
	zeroiseUsers();
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

	/* Find the user information for the given user */
	status = fileRef = findUserFileRef( USERID_NAME, createInfo->strArg1, 
										createInfo->strArgLen1 );
	if( cryptStatusError( status ) )
		{
		/* If we get a special-case OK status, we're in the zeroised state
		   with no user info present, make sure the user is logging in with
		   the default SO password */
		if( status == OK_SPECIAL )
			status = ( createInfo->strArgLen2 == PRIMARYSO_PASSWORD_LENGTH && \
					   ( !memcmp( createInfo->strArg2, PRIMARYSO_PASSWORD, 
								  PRIMARYSO_PASSWORD_LENGTH ) || \
						 !memcmp( createInfo->strArg2, PRIMARYSO_ALTPASSWORD, 
								  PRIMARYSO_PASSWORD_LENGTH ) ) ) ? \
					 CRYPT_OK : CRYPT_ERROR_WRONGKEY;
		if( cryptStatusError( status ) )
			return( status );
		fileRef = -1;	/* No user file present yet for primary SO */

		/* We're logging in as the primary SO with the SO default password,
		   create the primary SO user object */
		assert( createInfo->strArgLen1 == primarySOInfo.userNameLength && \
				!memcmp( createInfo->strArg1, primarySOInfo.userName,
						 primarySOInfo.userNameLength ) );
		assert( createInfo->strArgLen2 == PRIMARYSO_PASSWORD_LENGTH && \
				( !memcmp( createInfo->strArg2, PRIMARYSO_PASSWORD, 
						   PRIMARYSO_PASSWORD_LENGTH ) || \
				  !memcmp( createInfo->strArg2, PRIMARYSO_ALTPASSWORD, 
						   PRIMARYSO_PASSWORD_LENGTH ) ) );
		initStatus = openUser( &iCryptUser, createInfo->cryptOwner, 
							   &primarySOInfo, &userInfoPtr );
		}
	else
		{
		USER_FILE_INFO userFileInfo;

		/* We're in the non-zeroised state, no user can use the default SO
		   password */
		if( createInfo->strArgLen2 == PRIMARYSO_PASSWORD_LENGTH && \
			( !memcmp( createInfo->strArg2, PRIMARYSO_PASSWORD, 
					   PRIMARYSO_PASSWORD_LENGTH ) || \
			  !memcmp( createInfo->strArg2, PRIMARYSO_ALTPASSWORD, 
					   PRIMARYSO_PASSWORD_LENGTH ) ) )
			return( CRYPT_ERROR_WRONGKEY );

		/* Read the user info from the user file and perform access
		   verification */
		status = getCheckUserInfo( &userFileInfo, fileRef );
		if( cryptStatusError( status ) )	
			return( status );

		/* Pass the call on to the lower-level open function */
		assert( createInfo->strArgLen1 == userFileInfo.userNameLength && \
				!memcmp( createInfo->strArg1, userFileInfo.userName,
						 userFileInfo.userNameLength ) );
		initStatus = openUser( &iCryptUser, createInfo->cryptOwner, 
							   &userFileInfo, &userInfoPtr );
		zeroise( &userFileInfo, sizeof( USER_FILE_INFO ) );
		}
	if( userInfoPtr == NULL )
		return( initStatus );	/* Create object failed, return immediately */
	if( cryptStatusError( initStatus ) )
		/* The session open failed, make sure the object gets destroyed when
		   we notify the kernel that the setup process is complete */
		krnlSendNotifier( iCryptUser, RESOURCE_IMESSAGE_DESTROY );

	/* We've finished setting up the object-type-specific info, tell the
	   kernel the object is ready for use */
	unlockResource( userInfoPtr );
	status = krnlSendMessage( iCryptUser, RESOURCE_IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
		return( cryptStatusError( initStatus ) ? initStatus : status );

	/* If the user object has a corresponding user info file, read any 
	   stored config options into the object.  We have to do this after 
	   it's initialised because the config data, coming from an external 
	   (and therefore untrusted) source has to go through the kernel's 
	   ACL checking */
	if( fileRef >= 0 )
		{
		sprintf( userFileName, "u%06x", fileRef );
		readConfig( iCryptUser, userFileName );
		}
	createInfo->cryptHandle = iCryptUser;
	return( CRYPT_OK );
	}

/* Create the default user object */

int createDefaultUserObject( void )
	{
	CRYPT_USER iUserObject;
	USER_INFO *userInfoPtr;
	int status;

	/* Pass the call on to the lower-level open function.  This user is
	   unique and has no owner or type */
	status = openUser( &iUserObject, SYSTEM_OBJECT_HANDLE, &defaultUserInfo, 
					   &userInfoPtr );
	if( userInfoPtr == NULL )
		return( status );	/* Create object failed, return immediately */
	if( cryptStatusError( status ) )
		{
		/* The user create call failed, we'd normally have to signal the user 
		   object to destroy itself when the init completes, however we don't 
		   have the privileges to do this so we just pass the error code back 
		   to the caller which causes the cryptlib init to fail */
		unlockResource( userInfoPtr );
		return( status );
		}
	assert( iUserObject == DEFAULTUSER_OBJECT_HANDLE );

	/* We've finished setting up the object-type-specific info, tell the 
	   kernel the object is ready for use */
	unlockResource( userInfoPtr );
	status = krnlSendMessage( iUserObject, RESOURCE_IMESSAGE_SETATTRIBUTE, 
							  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	if( cryptStatusError( status ) )
		return( status );

	/* Read any stored config options into the object.  We have to do this
	   after it's initialised because the config data, coming from an 
	   external (and therefore untrusted) source has to go through the
	   kernel's ACL checking */
	readConfig( DEFAULTUSER_OBJECT_HANDLE, "cryptlib" );
	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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