📄 cryptses.c
字号:
/****************************************************************************
* *
* cryptlib Secure Session Routines *
* Copyright Peter Gutmann 1998-2005 *
* *
****************************************************************************/
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "crypt.h"
#ifdef INC_ALL
#include "asn1.h"
#include "stream.h"
#include "session.h"
#else
#include "misc/asn1.h"
#include "io/stream.h"
#include "session/session.h"
#endif /* Compiler-specific includes */
#ifdef USE_SESSIONS
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Exit after setting extended error information */
static int exitError( SESSION_INFO *sessionInfoPtr,
const CRYPT_ATTRIBUTE_TYPE errorLocus,
const CRYPT_ERRTYPE_TYPE errorType, const int status )
{
setErrorInfo( sessionInfoPtr, errorLocus, errorType );
return( status );
}
static int exitErrorInited( SESSION_INFO *sessionInfoPtr,
const CRYPT_ATTRIBUTE_TYPE errorLocus )
{
return( exitError( sessionInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT,
CRYPT_ERROR_INITED ) );
}
static int exitErrorNotInited( SESSION_INFO *sessionInfoPtr,
const CRYPT_ATTRIBUTE_TYPE errorLocus )
{
return( exitError( sessionInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT,
CRYPT_ERROR_NOTINITED ) );
}
static int exitErrorNotFound( SESSION_INFO *sessionInfoPtr,
const CRYPT_ATTRIBUTE_TYPE errorLocus )
{
return( exitError( sessionInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT,
CRYPT_ERROR_NOTFOUND ) );
}
/* Exit after saving a detailed error message. This is used by lower-level
session code to provide more information to the caller than a basic error
code */
int retExtFnSession( SESSION_INFO *sessionInfoPtr, const int status,
const char *format, ... )
{
va_list argPtr;
va_start( argPtr, format );
vsnprintf( sessionInfoPtr->errorMessage, MAX_ERRMSG_SIZE, format, argPtr );
va_end( argPtr );
assert( !cryptArgError( status ) ); /* Catch leaks */
return( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );
}
int retExtExFnSession( SESSION_INFO *sessionInfoPtr,
const int status, const CRYPT_HANDLE extErrorObject,
const char *format, ... )
{
RESOURCE_DATA msgData;
va_list argPtr;
int extErrorStatus;
/* Check whether there's any additional error information available */
va_start( argPtr, format );
setMessageData( &msgData, NULL, 0 );
extErrorStatus = krnlSendMessage( extErrorObject, MESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_ATTRIBUTE_INT_ERRORMESSAGE );
if( cryptStatusOK( extErrorStatus ) )
{
char errorString[ MAX_ERRMSG_SIZE + 1 ];
char extraErrorString[ MAX_ERRMSG_SIZE + 1 ];
int errorStringLen, extraErrorStringLen;
/* There's additional information present via the additional object,
fetch it and append it to the session-level error message */
setMessageData( &msgData, extraErrorString, MAX_ERRMSG_SIZE );
extErrorStatus = krnlSendMessage( extErrorObject, MESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_ATTRIBUTE_INT_ERRORMESSAGE );
if( cryptStatusOK( extErrorStatus ) )
extraErrorString[ msgData.length ] = '\0';
else
strcpy( extraErrorString, "(None available)" );
extraErrorStringLen = strlen( extraErrorString );
vsnprintf( errorString, MAX_ERRMSG_SIZE, format, argPtr );
errorStringLen = strlen( errorString );
if( errorStringLen < MAX_ERRMSG_SIZE - 64 )
{
const int extErrorLenToCopy = \
min( MAX_ERRMSG_SIZE - ( 32 + errorStringLen ),
extraErrorStringLen );
strcpy( errorString + errorStringLen, ". Additional information: " );
memcpy( errorString + errorStringLen + 26, extraErrorString,
extErrorLenToCopy );
errorString[ errorStringLen + 26 + extErrorLenToCopy ] = '\0';
}
strcpy( sessionInfoPtr->errorMessage, errorString );
}
else
vsnprintf( sessionInfoPtr->errorMessage, MAX_ERRMSG_SIZE, format, argPtr );
va_end( argPtr );
assert( !cryptArgError( status ) ); /* Catch leaks */
return( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );
}
/* 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 attributeType = userInfoPtr->cursorPos;
BOOLEAN doContinue;
/* If we've just moved the cursor onto this attribute, reset the
position to the first internal attribute */
if( attributeListPtr->flags & ATTR_FLAG_CURSORMOVED )
{
attributeType = 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( attributeType );
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 ] != attributeType && \
attributeOrderList[ i ] != CRYPT_ATTRIBUTE_NONE; i++ );
if( attributeOrderList[ i ] == CRYPT_ATTRIBUTE_NONE )
attributeType = CRYPT_ATTRIBUTE_NONE;
else
if( attrGetType == ATTR_PREV )
attributeType = ( i < 1 ) ? CRYPT_ATTRIBUTE_NONE : \
attributeOrderList[ i - 1 ];
else
attributeType = attributeOrderList[ i + 1 ];
if( attributeType == 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( attributeType )
{
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:
assert( NOTREACHED );
return( FALSE );
}
}
while( doContinue );
attributeListPtr->attributeCursorEntry = attributeType;
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->attribute;
if( attributeID != NULL && \
( attributeListPtr->flags & ATTR_FLAG_COMPOSITE ) )
*attributeID = attributeListPtr->accessFunction( attributeListPtr,
ATTR_NONE );
return( attributeListPtr );
}
/* Add a session attribute */
static int insertSessionAttribute( ATTRIBUTE_LIST **listHeadPtr,
const CRYPT_ATTRIBUTE_TYPE attributeType,
const void *data, const int dataLength,
const int dataMaxLength,
const ATTRACCESSFUNCTION accessFunction,
const int flags )
{
ATTRIBUTE_LIST *newElement, *insertPoint = NULL;
assert( isWritePtr( listHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( attributeType > CRYPT_SESSINFO_FIRST && \
attributeType < CRYPT_SESSINFO_LAST );
assert( ( data == NULL ) || \
( isReadPtr( data, dataLength ) && \
dataLength <= dataMaxLength ) );
assert( dataMaxLength >= 0 );
assert( !( flags & ATTR_FLAG_COMPOSITE ) || \
accessFunction != NULL );
/* Make sure that this attribute isn't already present */
if( *listHeadPtr != NULL )
{
ATTRIBUTE_LIST *prevElement = NULL;
for( insertPoint = *listHeadPtr; insertPoint != NULL;
insertPoint = insertPoint->next )
{
/* If this is a non-multivalued attribute, make sure that it
attribute isn't already present */
if( !( flags & ATTR_FLAG_MULTIVALUED ) && \
insertPoint->attribute == attributeType )
return( CRYPT_ERROR_INITED );
prevElement = insertPoint;
}
insertPoint = prevElement;
}
/* Allocate memory for the new element and copy the information across.
The data is stored in storage ... storage + dataLength, with storage
reserved up to dataMaxLength (if it's greater than dataLength) to
allow the contents to be replaced with a new fixed-length value */
if( ( newElement = ( ATTRIBUTE_LIST * ) \
clAlloc( "addSessionAttribute", sizeof( ATTRIBUTE_LIST ) + \
dataMaxLength ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
initVarStruct( newElement, ATTRIBUTE_LIST, dataMaxLength );
newElement->attribute = attributeType;
newElement->accessFunction = accessFunction;
newElement->flags = flags;
if( data == NULL )
newElement->intValue = dataLength;
else
{
assert( isReadPtr( data, dataLength ) );
memcpy( newElement->value, data, dataLength );
newElement->valueLength = dataLength;
}
insertDoubleListElement( listHeadPtr, insertPoint, newElement );
return( CRYPT_OK );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -