?? cryptusr.c
字號:
}
return( status );
}
/****************************************************************************
* *
* User Management Functions *
* *
****************************************************************************/
/* Perform a zeroise */
static int zeroiseUsers( void )
{
CRYPT_KEYSET iIndexKeyset;
RESOURCE_DATA msgData;
STREAM stream;
static const BYTE zeroUserData[] = { 0x30, 0x00 };
BYTE buffer[ KEYSET_BUFFERSIZE ];
void *bufPtr = buffer;
int length, status;
/* Open the index file and read the index entries from it. We open it in
exclusive mode and keep it open to ensure that noone else can access
it while the zeroise is occurring */
status = openUserKeyset( &iIndexKeyset, "index",
CRYPT_IKEYOPT_EXCLUSIVEACCESS );
if( cryptStatusError( status ) )
/* If there's no index file present, we're already in the zeroised
state */
return( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );
status = readUserData( iIndexKeyset, CRYPT_IATTRIBUTE_USERINDEX,
&bufPtr, &length, 0 );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
free( bufPtr );
return( status );
}
/* Step through each entry clearing the user info for it */
sMemConnect( &stream, bufPtr, length );
while( stell( &stream ) < length )
{
STREAM fileStream;
char userFilePath[ MAX_PATH_LENGTH + 128 ]; /* Protection for Windows */
char userFileName[ 16 ];
long fileRef;
/* Get the file reference for this user */
readSequence( &stream, NULL );
readUniversal( &stream );
readUniversal( &stream );
readUniversal( &stream );
status = readShortInteger( &stream, &fileRef );
if( cryptStatusError( status ) )
continue;
/* Erase the given user keyset */
sprintf( userFileName, "u%06x", fileRef );
fileBuildCryptlibPath( userFilePath, userFileName, FALSE );
status = sFileOpen( &fileStream, userFilePath,
FILE_READ | FILE_WRITE | FILE_EXCLUSIVE_ACCESS );
if( cryptStatusError( status ) )
continue;
fileClearToEOF( &fileStream );
sFileClose( &fileStream );
fileUnlink( userFilePath );
}
sMemDisconnect( &stream );
if( bufPtr != buffer )
free( bufPtr );
/* Erase the index file by setting zero-length user index info, which
results in an empty keyset which is erased on close */
setResourceData( &msgData, ( void * ) zeroUserData, 2 );
status = krnlSendMessage( iIndexKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERINDEX );
krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/* Create a user object keyset */
static int createUserKeyset( CRYPT_KEYSET *iCreatedKeyset,
USER_INFO *userInfoPtr )
{
CRYPT_KEYSET iIndexKeyset, iUserKeyset;
BOOLEAN newIndex = FALSE;
BYTE buffer[ KEYSET_BUFFERSIZE ];
void *bufPtr = buffer;
char userFileName[ 16 ];
int fileRef, length, status;
/* Clear return value */
*iCreatedKeyset = CRYPT_ERROR;
/* Try and open the config file. If we can't open it and the return
status is something other than an indication that the file is in use,
it means the file doesn't exist so we try and create it instead.
Performing the create is safe because the stream subsystem will
either return an appropriate error code to indicate that the file is
locked by another thread/process or will block until it becomes
unlocked, depending on how the OS implements file locking */
status = openUserKeyset( &iIndexKeyset, "index",
CRYPT_IKEYOPT_EXCLUSIVEACCESS );
if( cryptStatusError( status ) && status != CRYPT_ERROR_BUSY )
{
status = openUserKeyset( &iIndexKeyset, "index",
CRYPT_KEYOPT_CREATE );
newIndex = TRUE;
}
if( cryptStatusError( status ) )
return( status );
/* If there's index data present, read it and make sure the new user
isn't already present */
if( !newIndex )
{
/* Read the index entries from the keyset */
status = readUserData( iIndexKeyset, CRYPT_IATTRIBUTE_USERINDEX,
&bufPtr, &length, MAX_USERINDEX_SIZE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
free( bufPtr );
return( status );
}
/* Check whether this user is present in the index */
status = findUser( bufPtr, length, USERID_NAME, userInfoPtr->userName,
userInfoPtr->userNameLength );
if( !cryptStatusError( status ) )
{
krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
free( bufPtr );
return( CRYPT_ERROR_DUPLICATE );
}
/* Make sure the userID is unique */
do
{
status = findUser( bufPtr, length, USERID_USERID,
userInfoPtr->userID, KEYID_SIZE );
if( !cryptStatusError( status ) )
getNonce( userInfoPtr->userID, KEYID_SIZE );
}
while( !cryptStatusError( status ) );
}
else
/* No users present yet, use the first user entry */
fileRef = length = 0;
/* Create the user keyset */
sprintf( userFileName, "u%06x", fileRef );
status = openUserKeyset( &iUserKeyset, userFileName,
CRYPT_KEYOPT_CREATE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
free( bufPtr );
return( status );
}
/* Update the index file */
status = insertIndexEntry( userInfoPtr, bufPtr, &length );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setResourceData( &msgData, bufPtr, length );
status = krnlSendMessage( iIndexKeyset,
RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_USERINDEX );
}
if( cryptStatusError( status ) )
/* We couldn't update the index file, delete the newly-created user
keyset (since we haven't written anything to it, it's zero-length
so it's deleted automatically on close) */
krnlSendNotifier( iUserKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
else
{
userInfoPtr->fileRef = fileRef;
*iCreatedKeyset = iUserKeyset;
}
krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
/* Clean up */
if( bufPtr != buffer )
free( bufPtr );
return( status );
}
/* Set/change the password for a user object */
static int setPassword( USER_INFO *userInfoPtr, const char *password,
const int passwordLength )
{
CRYPT_KEYSET iUserKeyset;
int status;
/* No-one can ever directly set the default SO password */
if( passwordLength == PRIMARYSO_PASSWORD_LENGTH && \
( !memcmp( password, PRIMARYSO_PASSWORD,
PRIMARYSO_PASSWORD_LENGTH ) || \
!memcmp( password, PRIMARYSO_ALTPASSWORD,
PRIMARYSO_PASSWORD_LENGTH ) ) )
return( CRYPT_ERROR_WRONGKEY );
/* If we're setting the password for the primary SO in the zeroised
state, create a new user keyset and SO authentication key and write
the details to the keyset */
if( userInfoPtr->fileRef == -1 )
{
status = createUserKeyset( &iUserKeyset, userInfoPtr );
assert( ( cryptStatusError( status ) && userInfoPtr->fileRef == -1 ) || \
( cryptStatusOK( status ) && userInfoPtr->fileRef == 0 ) );
if( cryptStatusOK( status ) )
{
/* Since this user is created implicitly, there's no userID set
by an explicit create so we set it now. Since this is
effectively a self-created user we also set the creatorID to
the userID */
getNonce( userInfoPtr->userID, KEYID_SIZE );
memcpy( userInfoPtr->creatorID, userInfoPtr->userID,
KEYID_SIZE );
status = createSOKey( iUserKeyset, userInfoPtr,
password, passwordLength );
}
if( cryptStatusOK( status ) )
status = writeUserInfo( iUserKeyset, userInfoPtr,
userInfoPtr->iCryptContext );
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*status = createCAKey( iUserKeyset, userInfoPtr, password, passwordLength );*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
}
else
{
char userFileName[ 16 ];
/* Open an existing user keyset */
sprintf( userFileName, "u%06x", userInfoPtr->fileRef );
status = openUserKeyset( &iUserKeyset, userFileName,
CRYPT_KEYOPT_NONE );
}
if( cryptStatusError( status ) )
return( status );
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* set state = USER_INITED */
/* write MAC( ??? ) to user file - needs PKCS #15 changes */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* Close the keyset and commit the changes */
krnlSendNotifier( iUserKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
/* The password has been set, we're now in the user inited state */
userInfoPtr->state = USER_STATE_USERINITED;
return( CRYPT_OK );
}
/****************************************************************************
* *
* General User Object Functions *
* *
****************************************************************************/
/* Handle a message sent to a user object */
static int userMessageFunction( const CRYPT_USER cryptUser,
const RESOURCE_MESSAGE_TYPE message,
void *messageDataPtr, const int messageValue )
{
USER_INFO *userInfoPtr;
getCheckInternalResource( cryptUser, userInfoPtr, OBJECT_TYPE_USER );
/* Process destroy object messages */
if( message == RESOURCE_MESSAGE_DESTROY )
{
/* Clean up any user-related crypto objects if necessary */
if( userInfoPtr->iCryptContext != CRYPT_ERROR )
krnlSendNotifier( userInfoPtr->iCryptContext,
RESOURCE_IMESSAGE_DECREFCOUNT );
if( userInfoPtr->iKeyset != CRYPT_ERROR )
krnlSendNotifier( userInfoPtr->iKeyset,
RESOURCE_IMESSAGE_DECREFCOUNT );
/* Clean up the config options */
endOptions( userInfoPtr->configOptions );
/* Delete the objects locking variables and the object itself */
unlockResource( userInfoPtr );
deleteResourceLock( userInfoPtr );
zeroise( userInfoPtr, sizeof( USER_INFO ) );
free( userInfoPtr );
return( CRYPT_OK );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
char userFileName[ 16 ];
void *data;
int length, status;
if( messageValue == CRYPT_USERINFO_PASSWORD )
{
RESOURCE_DATA *msgData = messageDataPtr;
status = setPassword( userInfoPtr, msgData->data,
msgData->length );
unlockResourceExit( userInfoPtr, status );
}
if( messageValue == CRYPT_USERINFO_CAKEY_CERTSIGN || \
messageValue == CRYPT_USERINFO_CAKEY_CRLSIGN || \
messageValue == CRYPT_USERINFO_CAKEY_OCSPSIGN )
{
const int objectHandle = *( int * ) messageDataPtr;
const int requiredKeyUsage = \
( messageValue == CRYPT_USERINFO_CAKEY_CERTSIGN ) ? \
CRYPT_KEYUSAGE_KEYCERTSIGN : \
( messageValue == CRYPT_USERINFO_CAKEY_CRLSIGN ) ? \
CRYPT_KEYUSAGE_CRLSIGN : \
( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_NONREPUDIATION );
int value;
/* Make sure we've been given a signing key */
status = krnlSendMessage( objectHandle, RESOURCE_IMESSAGE_CHECK,
NULL, RESOURCE_MESSAGE_CHECK_PKC_SIGN );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
/* Make sure the object has an initialised cert of the correct
type associated with it */
status = krnlSendMessage( objectHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_IMMUTABLE );
if( cryptStatusError( status ) || !value )
return( CRYPT_ARGERROR_NUM1 );
status = krnlSendMessage( objectHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) ||
( value != CRYPT_CERTTYPE_CERTIFICATE && \
value != CRYPT_CERTTYPE_CERTCHAIN ) )
return( CRYPT_ARGERROR_NUM1 );
/* Make sure the key usage required for this action is
permitted. OCSP is a bit difficult since the key may or may
not have an OCSP extended usage (depending on whether the CA
bothers to set it or not, even if they do they may delegate
the functionality to a short-term generic signing key) and the
signing ability may be indicated by either a digital signature
flag or a nonrepudiation flag depending on whether the CA
considers an OCSP signature to be short or long-term, so we
just check for a generic signing ability */
status = krnlSendMessage( objectHandle,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -