📄 sess_attr.c
字号:
attribute );
if( attributeListPtr == NULL )
return( exitErrorNotInited( sessionInfoPtr, attribute ) );
*valuePtr = attributeListPtr->intValue;
return( CRYPT_OK );
}
case CRYPT_SESSINFO_VERSION:
*valuePtr = sessionInfoPtr->version;
return( CRYPT_OK );
case CRYPT_SESSINFO_AUTHRESPONSE:
*valuePtr = sessionInfoPtr->authResponse;
return( CRYPT_OK );
}
retIntError();
}
/* Get a string attribute */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int getSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,
INOUT MESSAGE_DATA *msgData,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )
{
const ATTRIBUTE_LIST *attributeListPtr;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );
/* Handle the various information types */
switch( attribute )
{
case CRYPT_OPTION_NET_SOCKS_SERVER:
case CRYPT_OPTION_NET_SOCKS_USERNAME:
case CRYPT_OPTION_NET_HTTP_PROXY:
/* These aren't implemented on a per-session level yet since
they're almost never user */
return( exitErrorNotFound( sessionInfoPtr, attribute ) );
case CRYPT_ATTRIBUTE_INT_ERRORMESSAGE:
{
ERROR_INFO *errorInfo = &sessionInfoPtr->errorInfo;
if( errorInfo->errorStringLength <= 0 )
{
/* We don't set extended error information for this atribute
because it's usually read in response to an existing error,
which would overwrite the existing error information */
return( CRYPT_ERROR_NOTFOUND );
}
return( attributeCopy( msgData, errorInfo->errorString,
errorInfo->errorStringLength ) );
}
case CRYPT_SESSINFO_USERNAME:
case CRYPT_SESSINFO_PASSWORD:
case CRYPT_SESSINFO_SERVER_FINGERPRINT:
case CRYPT_SESSINFO_SERVER_NAME:
case CRYPT_SESSINFO_CLIENT_NAME:
attributeListPtr = findSessionInfo( sessionInfoPtr->attributeList,
attribute );
if( attributeListPtr == NULL )
return( exitErrorNotInited( sessionInfoPtr, attribute ) );
return( attributeCopy( msgData, attributeListPtr->value,
attributeListPtr->valueLength ) );
}
retIntError();
}
/****************************************************************************
* *
* Set Attributes *
* *
****************************************************************************/
/* Set a numeric/boolean attribute */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int setSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,
IN_INT_Z const int value,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )
{
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
REQUIRES( ( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
attribute == CRYPT_ATTRIBUTE_CURRENT ) ||
/* CURRENT = cursor positioning code */
( value >= 0 && value < MAX_INTLENGTH ) );
REQUIRES( isAttribute( attribute ) || \
isInternalAttribute( attribute ) );
/* If we're in the middle of a paired-attribute add, make sure that the
conditions under which it's occurring are valid. In theory since
non-string attributes are never part of any paired attributes we
shouldn't really allow them to be added if we're in the middle of a
paired-attribute add but in practice this isn't such a big deal
because the only attribute add that can affect an attribute pair is
an attempt to move the attribute cursor, so we only disallow cursor-
affecting attribute adds. This leniency makes it less difficult to
add related attributes like a server URL, user name, and port */
if( sessionInfoPtr->lastAddedAttributeID != CRYPT_ATTRIBUTE_NONE && \
( attribute == CRYPT_ATTRIBUTE_CURRENT || \
attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP ) )
return( CRYPT_ARGERROR_VALUE );
/* Handle the various information types */
switch( attribute )
{
case CRYPT_ATTRIBUTE_CURRENT:
case CRYPT_ATTRIBUTE_CURRENT_GROUP:
{
ATTRIBUTE_LIST *attributeListPtr = \
sessionInfoPtr->attributeListCurrent;
status = setSessionAttributeCursor( sessionInfoPtr->attributeList,
&attributeListPtr, attribute, value );
if( cryptStatusError( status ) )
return( exitError( sessionInfoPtr, attribute,
CRYPT_ERRTYPE_ATTR_ABSENT, status ) );
sessionInfoPtr->attributeListCurrent = attributeListPtr;
return( status );
}
case CRYPT_OPTION_NET_CONNECTTIMEOUT:
sessionInfoPtr->connectTimeout = value;
return( CRYPT_OK );
case CRYPT_OPTION_NET_READTIMEOUT:
sessionInfoPtr->readTimeout = value;
return( CRYPT_OK );
case CRYPT_OPTION_NET_WRITETIMEOUT:
sessionInfoPtr->writeTimeout = value;
return( CRYPT_OK );
case CRYPT_ATTRIBUTE_BUFFERSIZE:
REQUIRES( !( sessionInfoPtr->flags & SESSION_ISOPEN ) );
sessionInfoPtr->receiveBufSize = value;
return( CRYPT_OK );
case CRYPT_SESSINFO_ACTIVE:
{
CRYPT_ATTRIBUTE_TYPE missingInfo;
/* Session state and persistent sessions are handled as follows:
The CRYPT_SESSINFO_ACTIVE attribute records the active state
of the session as a whole, and the CRYPT_SESSINFO_-
CONNECTIONACTIVE attribute records the state of the
underlying comms session. Setting CRYPT_SESSINFO_ACTIVE for
the first time activates the comms session, and leaves it
active if the underlying mechanism (e.g. HTTP 1.1 persistent
connections) supports it. The CRYPT_SESSINFO_ACTIVE
attribute is reset once the transaction completes, and
further transactions can be initiated as long as
CRYPT_SESSINFO_CONNECTIONACTIVE is set:
Obj.state _active _connactive
--------- ------- -----------
create 0 0 0
setattr 0 0 0
(clear out_param)
activate 1 0 -> 1 -> 0 1
(clear in_param)
setattr 1 0 1
(clear out_param)
activate 1 0 -> 1 -> 0 1
(clear in_param)
(peer closes conn) 1 0 0
setattr CRYPT_ERROR_COMPLETE */
if( value == FALSE )
return( CRYPT_OK ); /* No-op */
/* If the session is in the partially-open state while we wait
for the caller to allow or disallow the session
authentication, they have to provide a clear yes or no
indication by setting the CRYPT_SESSINFO_AUTHRESPONSE to TRUE
or FALSE before they can try to continue the session
activation */
if( ( sessionInfoPtr->flags & SESSION_PARTIALOPEN ) && \
sessionInfoPtr->authResponse == CRYPT_UNUSED )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_AUTHRESPONSE ) );
/* Make sure that all of the information that we need to proceed
is present */
missingInfo = checkMissingInfo( sessionInfoPtr->attributeList,
isServer( sessionInfoPtr ) ? TRUE : FALSE );
if( missingInfo != CRYPT_ATTRIBUTE_NONE )
return( exitErrorNotInited( sessionInfoPtr, missingInfo ) );
status = activateSession( sessionInfoPtr );
if( cryptArgError( status ) )
{
/* Catch leaked low-level status values. The session
management code does a large amount of work involving
other cryptlib objects so it's possible that an
unexpected failure at some point will leak through an
inappropriate status value */
assert( DEBUG_WARN );
status = CRYPT_ERROR_FAILED;
}
return( status );
}
case CRYPT_SESSINFO_SERVER_PORT:
/* If there's already a transport session or network socket
specified we can't set a port as well */
if( sessionInfoPtr->transportSession != CRYPT_ERROR )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_SESSION ) );
if( sessionInfoPtr->networkSocket != CRYPT_ERROR )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_NETWORKSOCKET ) );
return( addSessionInfo( &sessionInfoPtr->attributeList,
CRYPT_SESSINFO_SERVER_PORT, NULL,
value ) );
case CRYPT_SESSINFO_VERSION:
if( value < sessionInfoPtr->protocolInfo->minVersion || \
value > sessionInfoPtr->protocolInfo->maxVersion )
return( CRYPT_ARGERROR_VALUE );
sessionInfoPtr->version = value;
return( CRYPT_OK );
case CRYPT_SESSINFO_PRIVATEKEY:
{
const int requiredAttributeFlags = isServer( sessionInfoPtr ) ? \
sessionInfoPtr->serverReqAttrFlags : \
sessionInfoPtr->clientReqAttrFlags;
/* Make sure that it's a private key */
status = krnlSendMessage( value, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_PRIVATE );
if( cryptStatusError( status ) )
{
if( sessionInfoPtr->type != CRYPT_SESSION_SSL )
return( CRYPT_ARGERROR_NUM1 );
/* SSL can also do key agreement-based key exchange so we
fall back to this if key transport-based exchange isn't
possible */
status = krnlSendMessage( value, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_KA_EXPORT );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
}
/* If we need a private key with certain capabilities, make sure
that it has these capabilities. This is a more specific check
than that allowed by the kernel ACLs */
if( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYSIGN )
{
status = krnlSendMessage( value, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_SIGN );
if( cryptStatusError( status ) )
{
setErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ARGERROR_NUM1 );
}
}
if( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYCRYPT )
{
status = krnlSendMessage( value, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_DECRYPT );
if( cryptStatusError( status ) )
{
setErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ARGERROR_NUM1 );
}
}
/* If we need a private key with a certificate, make sure that
the appropriate type of initialised certificate object is
present. This is a more specific check than that allowed by
the kernel ACLs */
if( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYCERT )
{
int attrValue;
status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
&attrValue, CRYPT_CERTINFO_IMMUTABLE );
if( cryptStatusError( status ) || !attrValue )
return( CRYPT_ARGERROR_NUM1 );
status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
&attrValue, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) ||
( attrValue != CRYPT_CERTTYPE_CERTIFICATE && \
attrValue != CRYPT_CERTTYPE_CERTCHAIN ) )
return( CRYPT_ARGERROR_NUM1 );
}
if( ( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYCACERT ) && \
cryptStatusError( \
krnlSendMessage( value, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_CA ) ) )
return( CRYPT_ARGERROR_NUM1 );
/* Make sure that the key meets the mininum height requirements.
We only perform this check if we're explicitly being asked to
perform the check and it's a server session (which has certain
minimum length requirements for private keys), for client
sessions the permitted length/security level is controlled by
the server so we can't really perform much checking */
if( sessionInfoPtr->protocolInfo->requiredPrivateKeySize && \
isServer( sessionInfoPtr ) )
{
int length;
status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
&length, CRYPT_CTXINFO_KEYSIZE );
if( cryptStatusError( status ) || \
length < sessionInfoPtr->protocolInfo->requiredPrivateKeySize )
return( exitError( sessionInfoPtr,
CRYPT_SESSINFO_PRIVATEKEY,
CRYPT_ERRTYPE_ATTR_SIZE,
CRYPT_ARGERROR_NUM1 ) );
}
/* Perform any protocol-specific additional checks if necessary */
if( sessionInfoPtr->checkAttributeFunction != NULL )
{
status = sessionInfoPtr->checkAttributeFunction( sessionInfoPtr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -