📄 cryptses.c
字号:
for the caller to allow or disallow the session
authentication, they have to provide a clear yes or no
indication if they try to continue the session activation */
if( ( sessionInfoPtr->flags & SESSION_PARTIALOPEN ) && \
sessionInfoPtr->authResponse == CRYPT_UNUSED )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_AUTHRESPONSE ) );
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( NOTREACHED );
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( addSessionAttribute( &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 = \
( sessionInfoPtr->flags & SESSION_ISSERVER ) ? \
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 cert, make sure that the
appropriate type of initialised cert 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 && \
( sessionInfoPtr->flags & SESSION_ISSERVER ) )
{
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 checks if necessary */
if( sessionInfoPtr->checkAttributeFunction != NULL )
{
status = sessionInfoPtr->checkAttributeFunction( sessionInfoPtr,
value, CRYPT_SESSINFO_PRIVATEKEY );
if( cryptStatusError( status ) )
return( status );
}
/* Add the private key and increment its reference count */
krnlSendNotifier( value, IMESSAGE_INCREFCOUNT );
sessionInfoPtr->privateKey = value;
return( CRYPT_OK );
}
case CRYPT_SESSINFO_KEYSET:
{
int type;
/* Make sure that it's either a cert store (rather than just a
generic keyset) or a read-only cert source (and specifically
not a cert store) if required */
if( sessionInfoPtr->serverReqAttrFlags & SESSION_NEEDS_CERTSTORE )
{
status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
&type, CRYPT_IATTRIBUTE_SUBTYPE );
if( cryptStatusError( status ) || \
( type != SUBTYPE_KEYSET_DBMS_STORE ) )
return( CRYPT_ARGERROR_NUM1 );
}
if( sessionInfoPtr->serverReqAttrFlags & SESSION_NEEDS_CERTSOURCE )
{
status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
&type, CRYPT_IATTRIBUTE_SUBTYPE );
if( cryptStatusError( status ) || \
( type == SUBTYPE_KEYSET_DBMS_STORE ) )
return( CRYPT_ARGERROR_NUM1 );
}
/* Add the keyset and increment its reference count */
krnlSendNotifier( value, IMESSAGE_INCREFCOUNT );
sessionInfoPtr->cryptKeyset = value;
return( CRYPT_OK );
}
case CRYPT_SESSINFO_AUTHRESPONSE:
sessionInfoPtr->authResponse = value;
return( CRYPT_OK );
case CRYPT_SESSINFO_SESSION:
/* If there's already a host or network socket specified, we
can't set a transport session as well */
if( findSessionAttribute( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_SERVER_NAME ) != NULL )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_SERVER_NAME ) );
if( sessionInfoPtr->networkSocket != CRYPT_ERROR )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_NETWORKSOCKET ) );
/* Add the transport mechanism and increment its reference
count */
krnlSendNotifier( value, IMESSAGE_INCREFCOUNT );
sessionInfoPtr->transportSession = value;
return( CRYPT_OK );
case CRYPT_SESSINFO_NETWORKSOCKET:
{
NET_CONNECT_INFO connectInfo;
STREAM stream;
/* If there's already a host or session specified, we can't set
a network socket as well */
if( findSessionAttribute( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_SERVER_NAME ) != NULL )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_SERVER_NAME ) );
if( sessionInfoPtr->transportSession != CRYPT_ERROR )
return( exitErrorInited( sessionInfoPtr,
CRYPT_SESSINFO_SESSION ) );
/* Create a dummy network stream to make sure that the network
socket is OK */
initNetConnectInfo( &connectInfo, sessionInfoPtr->ownerHandle,
sessionInfoPtr->readTimeout,
sessionInfoPtr->connectTimeout,
NET_OPTION_NETWORKSOCKET_DUMMY );
connectInfo.networkSocket = value;
status = sNetConnect( &stream, STREAM_PROTOCOL_TCPIP,
&connectInfo, sessionInfoPtr->errorMessage,
&sessionInfoPtr->errorCode );
if( cryptStatusError( status ) )
return( status );
sNetDisconnect( &stream );
/* Add the network socket */
sessionInfoPtr->networkSocket = value;
return( CRYPT_OK );
}
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processGetAttributeS( SESSION_INFO *sessionInfoPtr,
void *messageDataPtr, const int messageValue )
{
const ATTRIBUTE_LIST *attributeListPtr;
RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
/* Handle the various information types */
switch( messageValue )
{
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,
messageValue ) );
case CRYPT_ATTRIBUTE_INT_ERRORMESSAGE:
if( !*sessionInfoPtr->errorMessage )
/* 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, sessionInfoPtr->errorMessage,
strlen( sessionInfoPtr->errorMessage ) ) );
case CRYPT_SESSINFO_USERNAME:
case CRYPT_SESSINFO_PASSWORD:
case CRYPT_SESSINFO_SERVER_FINGERPRINT:
case CRYPT_SESSINFO_SERVER_NAME:
case CRYPT_SESSINFO_CLIENT_NAME:
attributeListPtr = \
findSessionAttribute( sessionInfoPtr->attributeList,
messageValue );
if( attributeListPtr == NULL )
return( exitErrorNotInited( sessionInfoPtr,
CRYPT_ERROR_NOTINITED ) );
return( attributeCopy( msgData, attributeListPtr->value,
attributeListPtr->valueLength ) );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processSetAttributeS( SESSION_INFO *sessionInfoPtr,
void *messageDataPtr, const int messageValue )
{
RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
int status;
/* Handle the various information types */
switch( messageValue )
{
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 used */
return( CRYPT_ARGERROR_VALUE );
case CRYPT_SESSINFO_USERNAME:
case CRYPT_SESSINFO_PASSWORD:
{
int flags = 0;
assert( msgData->length > 0 && \
msgData->length <= CRYPT_MAX_TEXTSIZE );
/* If this attribute is already set, we can't add it again */
if( findSessionAttribute( sessionInfoPtr->attributeList,
messageValue ) != NULL && \
!( sessionInfoPtr->type == CRYPT_SESSION_SSL && \
sessionInfoPtr->flags & SESSION_ISSERVER ) )
return( exitErrorInited( sessionInfoPtr, messageValue ) );
/* If it could be an encoded PKI value, check its validity */
if( ( messageValue == CRYPT_SESSINFO_USERNAME || \
messageValue == CRYPT_SESSINFO_PASSWORD ) && \
isPKIUserValue( msgData->data, msgData->length ) )
{
BYTE decodedValue[ CRYPT_MAX_TEXTSIZE ];
int status;
/* It's an encoded value, make sure that it's in order */
status = decodePKIUserValue( decodedValue, msgData->data,
msgData->length );
zeroise( decodedValue, CRYPT_MAX_TEXTSIZE );
if( cryptStatusError( status ) )
return( status );
flags = ATTR_FLAG_ENCODEDVALUE;
}
/* Remember the value. SSL server sessions maintain multiple
username/password entries possible so we perform a
(potential) update rather than a new add */
if( sessionInfoPtr->type == CRYPT_SESSION_SSL && \
sessionInfoPtr->flags & SESSION_ISSERVER )
status = updateSessionAttribute( &sessionInfoPtr->attributeList,
messageValue, msgData->data,
msgData->length,
CRYPT_MAX_TEXTSIZE, flags );
else
status = insertSessionAttribute( &sessionInfoPtr->attributeList,
messageValue, msgData->data,
msgData->length,
CRYPT_MAX_TEXTSIZE, NULL,
flags );
return( status );
}
case CRYPT_SESSINFO_SERVER_FINGERPRINT:
/* If this attribute is already set, we can't add it again */
if( findSessionAttribute( sessionInfoPtr->attributeList,
messageValue ) != NULL )
return( exitErrorInited( sessionInfoPtr, messageValue ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -