📄 sess_iattr.c
字号:
/****************************************************************************
* *
* cryptlib Session-specific Attribute Support Routines *
* Copyright Peter Gutmann 1998-2005 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "session.h"
#else
#include "crypt.h"
#include "session/session.h"
#endif /* Compiler-specific includes */
#ifdef USE_SESSIONS
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Reset the internal virtual cursor in a attribute-list item after we've
moved the attribute cursor */
#define resetVirtualCursor( attributeListPtr ) \
if( attributeListPtr != NULL ) \
attributeListPtr->flags |= ATTR_FLAG_CURSORMOVED
/* Helper function used to access internal attributes within an attribute
group */
#if 0 /* Currently unused, will be enabled in 3.3 with the move to
composite attributes for host/client info */
static int accessFunction( ATTRIBUTE_LIST *attributeListPtr,
const ATTR_TYPE attrGetType )
{
static const CRYPT_ATTRIBUTE_TYPE attributeOrderList[] = {
CRYPT_SESSINFO_NAME, CRYPT_SESSINFO_PASSWORD,
CRYPT_SESSINFO_KEY, CRYPT_ATTRIBUTE_NONE,
CRYPT_ATTRIBUTE_NONE };
USER_INFO *userInfoPtr = attributeListPtr->value;
CRYPT_ATTRIBUTE_TYPE attributeID = userInfoPtr->cursorPos;
BOOLEAN doContinue;
int iterationCount = 0;
/* If we've just moved the cursor onto this attribute, reset the
position to the first internal attribute */
if( attributeListPtr->flags & ATTR_FLAG_CURSORMOVED )
{
attributeID = userInfoPtr->cursorPos = \
CRYPT_ENVINFO_SIGNATURE_RESULT;
attributeListPtr->flags &= ~ATTR_FLAG_CURSORMOVED;
}
/* If it's an info fetch, return the currently-selected attribute */
if( attrGetType == ATTR_NONE )
return( attributeID );
do
{
int i;
/* Find the position of the current sub-attribute in the attribute
order list and use that to get its successor/predecessor sub-
attribute */
for( i = 0;
attributeOrderList[ i ] != attributeID && \
attributeOrderList[ i ] != CRYPT_ATTRIBUTE_NONE && \
i < FAILSAFE_ARRAYSIZE( attributeOrderList, CRYPT_ATTRIBUTE_TYPE );
i++ );
if( i >= FAILSAFE_ARRAYSIZE( attributeOrderList, CRYPT_ATTRIBUTE_TYPE ) )
retIntError_False();
if( attributeOrderList[ i ] == CRYPT_ATTRIBUTE_NONE )
attributeID = CRYPT_ATTRIBUTE_NONE;
else
if( attrGetType == ATTR_PREV )
attributeID = ( i < 1 ) ? CRYPT_ATTRIBUTE_NONE : \
attributeOrderList[ i - 1 ];
else
attributeID = attributeOrderList[ i + 1 ];
if( attributeID == CRYPT_ATTRIBUTE_NONE )
/* We've reached the first/last sub-attribute within the current
item/group, tell the caller that there are no more sub-
attributes present and they have to move on to the next
group */
return( FALSE );
/* Check whether the required sub-attribute is present. If not, we
continue and try the next one */
doContinue = FALSE;
switch( attributeID )
{
case CRYPT_SESSINFO_NAME:
break; /* Always present */
case CRYPT_SESSINFO_PASSWORD:
if( userInfoPtr->passwordLen <= 0 )
doContinue = TRUE;
break;
case CRYPT_SESSINFO_KEY:
if( userInfoPtr->key == CRYPT_ERROR )
doContinue = TRUE;
break;
default:
retIntError_Boolean();
}
}
while( doContinue && iterationCount++ < FAILSAFE_ITERATIONS_SMALL );
if( iterationCount >= FAILSAFE_ITERATIONS_SMALL )
retIntError_False();
attributeListPtr->attributeCursorEntry = attributeID;
return( TRUE );
}
#endif /* 0 */
/* Callback function used to provide external access to attribute list-
internal fields */
static const void *getAttrFunction( const void *attributePtr,
CRYPT_ATTRIBUTE_TYPE *groupID,
CRYPT_ATTRIBUTE_TYPE *attributeID,
CRYPT_ATTRIBUTE_TYPE *instanceID,
const ATTR_TYPE attrGetType )
{
ATTRIBUTE_LIST *attributeListPtr = ( ATTRIBUTE_LIST * ) attributePtr;
BOOLEAN subGroupMove;
assert( attributeListPtr == NULL || \
isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );
/* Clear return values */
if( groupID != NULL )
*groupID = CRYPT_ATTRIBUTE_NONE;
if( attributeID != NULL )
*attributeID = CRYPT_ATTRIBUTE_NONE;
if( instanceID != NULL )
*instanceID = CRYPT_ATTRIBUTE_NONE;
/* Move to the next or previous attribute if required. This isn't just a
case of following the prev/next links because some attribute-list
items contain an entire attribute group, so positioning by attribute
merely changes the current selection within the group (== attribute-
list item) rather than moving to the previous/next entry. Because of
this we have to special-case the code for composite items and allow
virtual positioning within the item */
if( attributeListPtr == NULL )
return( NULL );
subGroupMove = ( attrGetType == ATTR_PREV || \
attrGetType == ATTR_NEXT ) && \
( attributeListPtr->flags & ATTR_FLAG_COMPOSITE );
if( subGroupMove )
{
assert( attrGetType == ATTR_NEXT || attrGetType == ATTR_PREV );
assert( attributeListPtr->flags & ATTR_FLAG_COMPOSITE );
assert( attributeListPtr->accessFunction != NULL );
subGroupMove = attributeListPtr->accessFunction( attributeListPtr,
attrGetType );
}
/* If we're moving by group, move to the next/previous attribute list
item and reset the internal virtual cursor. Note that we always
advance the cursor to the next/prev attribute, it's up to the calling
code to manage attribute by attribute vs.group by group moves */
if( !subGroupMove && attrGetType != ATTR_CURRENT )
{
attributeListPtr = ( attrGetType == ATTR_PREV ) ? \
attributeListPtr->prev : attributeListPtr->next;
resetVirtualCursor( attributeListPtr );
}
if( attributeListPtr == NULL )
return( NULL );
/* Return ID information to the caller. We only return the group ID if
we've moved within the attribute group, if we've moved from one group
to another we leave it cleared because sessions can contain multiple
groups with the same ID, and returning an ID identical to the one from
the group that we've moved out of would make it look as if we're still
within the same group. Note that this relies on the behaviour of the
attribute-move functions, which first get the current group using
ATTR_CURRENT and then move to the next or previous using ATTR_NEXT/
PREV */
if( groupID != NULL && ( attrGetType == ATTR_CURRENT || subGroupMove ) )
*groupID = attributeListPtr->groupID;
if( attributeID != NULL )
{
if( attributeListPtr->flags & ATTR_FLAG_COMPOSITE )
*attributeID = attributeListPtr->accessFunction( attributeListPtr,
ATTR_NONE );
else
*attributeID = attributeListPtr->attributeID;
}
return( attributeListPtr );
}
/* Lock ephemeral attributes so that they can't be deleted any more by
resetEphemeralAttributes(). This just clears the ephemeral flag so that
they're treated as normal attributes */
void lockEphemeralAttributes( ATTRIBUTE_LIST *attributeListHead )
{
ATTRIBUTE_LIST *attributeListCursor;
int iterationCount = 0;
assert( isWritePtr( attributeListHead, sizeof( ATTRIBUTE_LIST * ) ) );
/* Clear the ATTR_FLAG_EPHEMERAL flag on all attributes */
for( attributeListCursor = attributeListHead;
attributeListCursor != NULL && \
iterationCount++ < FAILSAFE_ITERATIONS_MAX;
attributeListCursor = attributeListCursor->next )
attributeListCursor->flags &= ~ATTR_FLAG_EPHEMERAL;
if( iterationCount >= FAILSAFE_ITERATIONS_MAX )
retIntError_Void();
}
/* Check that a set of attributes is well-formed. We can perform most of
the checking as the attributes are added, but some checks (for example
whether each username has a corresponding password) aren't possible
until all of the attributes are present */
CRYPT_ATTRIBUTE_TYPE checkMissingInfo( const ATTRIBUTE_LIST *attributeListHead,
const BOOLEAN isServer )
{
const ATTRIBUTE_LIST *attributeListPtr = attributeListHead;
if( attributeListPtr == NULL )
return( CRYPT_ATTRIBUTE_NONE );
/* Make sure that every username attribute is paired up with a
corresponding authentication attribute. This only applies to
servers, because clients can also use private keys for
authentication, and the presence of a key or password is checked
elsewhere */
if( isServer )
{
int iterationCount = 0;
while( ( attributeListPtr = \
attributeFind( attributeListPtr, getAttrFunction,
CRYPT_SESSINFO_USERNAME,
CRYPT_ATTRIBUTE_NONE ) ) != NULL && \
iterationCount++ < FAILSAFE_ITERATIONS_MAX )
{
/* Make sure that there's a matching authentication attribute */
if( ( attributeListPtr = attributeListPtr->next ) == NULL )
return( CRYPT_SESSINFO_PASSWORD );
/* The authentication attribute is currently a password, but in
future versions could also be a public key used for
authentication */
if( attributeListPtr->attributeID != CRYPT_SESSINFO_PASSWORD )
return( CRYPT_SESSINFO_PASSWORD );
/* Move on to the next attribute */
attributeListPtr = attributeListPtr->next;
}
if( iterationCount >= FAILSAFE_ITERATIONS_MAX )
retIntError_Ext( CRYPT_SESSINFO_ACTIVE );
}
return( CRYPT_ATTRIBUTE_NONE );
}
/****************************************************************************
* *
* Attribute Cursor Management Routines *
* *
****************************************************************************/
/* Get/set the attribute cursor */
int getSessionAttributeCursor( ATTRIBUTE_LIST *attributeListHead,
ATTRIBUTE_LIST *attributeListCursor,
const CRYPT_ATTRIBUTE_TYPE sessionInfoType,
int *valuePtr )
{
BOOLEAN initAttributeList = FALSE;
assert( attributeListHead == NULL || \
isWritePtr( attributeListHead, sizeof( ATTRIBUTE_LIST ) ) );
assert( attributeListCursor == NULL || \
isWritePtr( attributeListCursor, sizeof( ATTRIBUTE_LIST ) ) );
assert( ( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT ) || \
( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP ) || \
( sessionInfoType > CRYPT_SESSINFO_FIRST && \
sessionInfoType < CRYPT_SESSINFO_LAST ) );
assert( isWritePtr( valuePtr, sizeof( int ) ) );
/* Clear return value */
*valuePtr = CRYPT_ATTRIBUTE_NONE;
/* We're querying something that resides in the attribute list, make
sure that there's an attribute list present. If it's present but
nothing is selected, select the first entry */
if( attributeListCursor == NULL )
{
if( attributeListHead == NULL )
return( CRYPT_ERROR_NOTFOUND );
attributeListCursor = attributeListHead;
resetVirtualCursor( attributeListCursor );
initAttributeList = TRUE;
}
/* If we're reading the group, return the group type */
if( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP )
*valuePtr = attributeListCursor->groupID;
else
/* If it's a single-attribute group, return the attribute type */
if( !( attributeListCursor->flags & ATTR_FLAG_COMPOSITE ) )
*valuePtr = attributeListCursor->groupID;
else
/* It's a composite type, get the currently-selected sub-attribute */
*valuePtr = attributeListCursor->accessFunction( attributeListCursor,
ATTR_NONE );
return( initAttributeList ? OK_SPECIAL : CRYPT_OK );
}
int setSessionAttributeCursor( ATTRIBUTE_LIST *attributeListHead,
ATTRIBUTE_LIST **attributeListCursorPtr,
const CRYPT_ATTRIBUTE_TYPE sessionInfoType,
const int position )
{
ATTRIBUTE_LIST *attributeListPtr = *attributeListCursorPtr;
assert( attributeListHead == NULL || \
isWritePtr( attributeListHead, sizeof( ATTRIBUTE_LIST ) ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -