📄 str_net.c
字号:
}
/* Wait for any async network driver binding to complete */
waitSemaphore( SEMAPHORE_DRIVERBIND );
/* Make sure that the network interface has been initialised */
if( !stream->transportOKFunction() )
{
/* Provide more information on the nature of the problem */
strcpy( errorMessage, "cryptlib network interface not initialised" );
/* Clean up. We can't use cleanupStream() at this point because the
stream hasn't been fully initialised yet */
if( stream->host != NULL )
clFree( "completeConnect", stream->host );
zeroise( stream, sizeof( STREAM ) );
return( CRYPT_ERROR_NOTINITED );
}
/* Allocate room for the I/O buffers and error messages returned from the
lower-level networking code */
if( ( stream->errorMessage = clAlloc( "completeConnect", \
MAX_ERRMSG_SIZE + 1 ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
if( useTransportBuffering )
{
if( ( stream->buffer = clAlloc( "completeConnect", \
NETWORK_BUFFER_SIZE ) ) != NULL )
{
stream->bufSize = NETWORK_BUFFER_SIZE;
if( ( stream->writeBuffer = \
clAlloc( "completeConnect", NETWORK_BUFFER_SIZE ) ) != NULL )
stream->writeBufSize = NETWORK_BUFFER_SIZE;
}
if( stream->writeBufSize <= 0 )
{
cleanupStream( stream, FALSE );
return( CRYPT_ERROR_MEMORY );
}
}
memset( stream->errorMessage, 0, MAX_ERRMSG_SIZE + 1 );
/* If we're not using an already-active network socket supplied by the
user, activate the connection */
if( !( stream->flags & STREAM_NFLAG_USERSOCKET ) )
{
if( proxyURL != NULL )
{
URL_INFO urlInfo;
/* We're going via a proxy, open the connection to the proxy
rather than directly to the target system. Since this is an
HTTP proxy, we specify the default port as port 80 */
status = parseURL( &urlInfo, proxyURL, strlen( proxyURL ), 80 );
if( cryptStatusError( status ) )
{
/* The proxy URL was invalid, provide more information for
the caller */
status = CRYPT_ERROR_OPEN;
stream->errorCode = CRYPT_ERROR_BADDATA;
strcpy( stream->errorMessage, "Invalid HTTP proxy URL" );
}
else
{
char urlBuffer[ MAX_DNS_SIZE + 1 ];
memcpy( urlBuffer, urlInfo.host, urlInfo.hostLen );
urlBuffer[ urlInfo.hostLen ] = '\0';
status = stream->transportConnectFunction( stream, urlBuffer,
urlInfo.port );
}
}
else
status = stream->transportConnectFunction( stream, stream->host,
stream->port );
}
else
/* If it's a dummy open to check parameters that can't be validated
at a higher level, pass the info on down to the low-level
checking routines */
if( options == NET_OPTION_NETWORKSOCKET_DUMMY )
status = stream->transportCheckFunction( stream );
if( cryptStatusError( status ) )
{
/* Copy back the error information to the caller */
*errorCode = stream->errorCode;
strcpy( errorMessage, stream->errorMessage );
/* Clean up */
cleanupStream( stream, FALSE );
return( status );
}
if( options == NET_OPTION_NETWORKSOCKET_DUMMY )
/* If it's a dummy open to check parameters, don't do anything
further */
return( CRYPT_OK );
/* We're connected, update the stream timeout value to contain the
network I/O timeout rather than the connect timeout. We use sioctl()
rather than setting it directly to ensure that it gets reflected down
to any underlying transport-layer objects */
if( netTimeout != CRYPT_ERROR )
timeout = netTimeout;
else
if( cryptStatusError( \
krnlSendMessage( iUserObject, IMESSAGE_GETATTRIBUTE,
&timeout, CRYPT_OPTION_NET_TIMEOUT ) ) )
timeout = 30;
sioctl( stream, STREAM_IOCTL_TIMEOUT, NULL, timeout );
return( CRYPT_OK );
}
/* Open and close a network connection. This parses a location string
(usually a URL) into <scheme>://<host>[:<port>]/<path>[?<query>]
components and opens a connection to the host for non-stateless
protocols */
int sNetConnect( STREAM *stream, const STREAM_PROTOCOL_TYPE protocol,
const NET_CONNECT_INFO *connectInfo, char *errorMessage,
int *errorCode )
{
URL_INFO urlInfo;
char proxyUrlBuffer[ MAX_DNS_SIZE + 1 ], *proxyURL = NULL;
int timeout, status;
assert( isWritePtr( stream, STREAM ) );
assert( protocol == STREAM_PROTOCOL_TCPIP || \
protocol == STREAM_PROTOCOL_HTTP || \
protocol == STREAM_PROTOCOL_HTTP_TRANSACTION || \
protocol == STREAM_PROTOCOL_CMP );
assert( isReadPtr( connectInfo, NET_CONNECT_INFO ) );
assert( errorMessage != NULL && errorCode != NULL );
assert( connectInfo->options != NET_OPTION_HOSTNAME || \
( connectInfo->options == NET_OPTION_HOSTNAME && \
connectInfo->name != NULL && connectInfo->name[ 0 ] && \
connectInfo->iCryptSession == CRYPT_ERROR && \
connectInfo->networkSocket == CRYPT_ERROR ) );
assert( connectInfo->options != NET_OPTION_TRANSPORTSESSION || \
( connectInfo->options == NET_OPTION_TRANSPORTSESSION && \
connectInfo->name == NULL && \
connectInfo->iCryptSession != CRYPT_ERROR && \
connectInfo->networkSocket == CRYPT_ERROR ) );
assert( ( connectInfo->options != NET_OPTION_NETWORKSOCKET && \
connectInfo->options != NET_OPTION_NETWORKSOCKET_DUMMY ) || \
( ( connectInfo->options == NET_OPTION_NETWORKSOCKET || \
connectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY ) && \
connectInfo->name == NULL && \
connectInfo->iCryptSession == CRYPT_ERROR && \
connectInfo->networkSocket != CRYPT_ERROR ) );
assert( connectInfo->iUserObject >= DEFAULTUSER_OBJECT_HANDLE &&
connectInfo->iUserObject < MAX_OBJECTS );
/* Clear the return values */
*errorMessage = '\0';
*errorCode = 0;
/* Initialise the stream structure. While we're connecting, the stream
timeout is the connect timeout. Once we've connected it's set to the
communication timeout */
if( connectInfo->connectTimeout != CRYPT_ERROR )
timeout = connectInfo->connectTimeout;
else
if( cryptStatusError( \
krnlSendMessage( connectInfo->iUserObject, IMESSAGE_GETATTRIBUTE,
&timeout, CRYPT_OPTION_NET_CONNECTTIMEOUT ) ) )
timeout = 30;
if( timeout < 5 )
{
/* Enforce the same minimum connect timeout as the kernel ACLs */
assert( NOTREACHED );
timeout = 5;
}
memset( stream, 0, sizeof( STREAM ) );
stream->type = STREAM_TYPE_NETWORK;
stream->protocol = protocol;
stream->timeout = stream->savedTimeout = timeout;
stream->port = connectInfo->port;
stream->netSocket = stream->listenSocket = CRYPT_ERROR;
stream->iTransportSession = CRYPT_ERROR;
switch( connectInfo->options )
{
case NET_OPTION_HOSTNAME:
/* If we're using standard HTTP then only an HTTP GET is
possible, use of POST requires the HTTP_TRANSACTION variant */
if( protocol == STREAM_PROTOCOL_HTTP )
stream->flags = STREAM_FLAG_READONLY;
/* Parse the URI into its various components */
status = parseURL( &urlInfo, connectInfo->name,
strlen( connectInfo->name ), connectInfo->port );
if( cryptStatusError( status ) )
{
/* There's an error in the URL format, provide more
information to the caller */
strcpy( errorMessage, "Invalid host name/URL" );
return( CRYPT_ERROR_OPEN );
}
status = copyUrlToStream( stream, &urlInfo );
if( cryptStatusError( status ) )
return( status );
/* If it's going to something other than the local system, check
to see whether we're going through a proxy. We only use the
case-insensitive string compares for the text-format host
names, since the numeric forms don't need this */
if( ( protocol == STREAM_PROTOCOL_HTTP || \
protocol == STREAM_PROTOCOL_HTTP_TRANSACTION ) && \
( strcmp( stream->host, "127.0.0.1" ) && \
strcmp( stream->host, "::1" ) && \
strCompareZ( stream->host, "localhost" ) && \
strCompare( stream->host, "localhost.", 10 ) ) ) /* Are you local? */
{
RESOURCE_DATA msgData;
/* Check whether there's an HTTP proxy configured */
setMessageData( &msgData, proxyUrlBuffer, MAX_DNS_SIZE );
status = krnlSendMessage( connectInfo->iUserObject,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_OPTION_NET_HTTP_PROXY );
if( cryptStatusOK( status ) )
{
proxyUrlBuffer[ msgData.length ] = '\0';
proxyURL = proxyUrlBuffer;
stream->flags |= STREAM_NFLAG_HTTPPROXY;
}
}
break;
case NET_OPTION_TRANSPORTSESSION:
stream->iTransportSession = connectInfo->iCryptSession;
break;
case NET_OPTION_NETWORKSOCKET:
case NET_OPTION_NETWORKSOCKET_DUMMY:
stream->netSocket = connectInfo->networkSocket;
stream->flags |= STREAM_NFLAG_USERSOCKET;
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR );
}
/* Set up access mechanisms and complete the connection */
return( completeConnect( stream, protocol, connectInfo->options, proxyURL,
connectInfo->iUserObject, connectInfo->timeout,
errorMessage, errorCode ) );
}
int sNetListen( STREAM *stream, const STREAM_PROTOCOL_TYPE protocol,
const NET_CONNECT_INFO *connectInfo, char *errorMessage,
int *errorCode )
{
URL_INFO urlInfo;
int timeout;
assert( isWritePtr( stream, STREAM ) );
assert( protocol == STREAM_PROTOCOL_TCPIP || \
protocol == STREAM_PROTOCOL_HTTP_TRANSACTION || \
protocol == STREAM_PROTOCOL_CMP );
assert( isReadPtr( connectInfo, NET_CONNECT_INFO ) );
assert( errorMessage != NULL && errorCode != NULL );
assert( connectInfo->options != NET_OPTION_HOSTNAME || \
( connectInfo->options == NET_OPTION_HOSTNAME && \
connectInfo->iCryptSession == CRYPT_ERROR && \
connectInfo->networkSocket == CRYPT_ERROR ) );
assert( connectInfo->options != NET_OPTION_TRANSPORTSESSION || \
( connectInfo->options == NET_OPTION_TRANSPORTSESSION && \
connectInfo->name == NULL && \
connectInfo->iCryptSession != CRYPT_ERROR && \
connectInfo->networkSocket == CRYPT_ERROR ) );
assert( ( connectInfo->options != NET_OPTION_NETWORKSOCKET && \
connectInfo->options != NET_OPTION_NETWORKSOCKET_DUMMY ) || \
( ( connectInfo->options == NET_OPTION_NETWORKSOCKET || \
connectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY ) || \
connectInfo->name == NULL && \
connectInfo->iCryptSession == CRYPT_ERROR && \
connectInfo->networkSocket != CRYPT_ERROR ) );
assert( connectInfo->iUserObject >= DEFAULTUSER_OBJECT_HANDLE &&
connectInfo->iUserObject < MAX_OBJECTS );
/* Clear the return values */
*errorMessage = '\0';
*errorCode = 0;
/* Initialise the stream structure. While we're connecting, the stream
timeout is the connect timeout. Once we've connected it's set to the
communication timeout */
if( connectInfo->connectTimeout != CRYPT_ERROR )
timeout = connectInfo->connectTimeout;
else
if( cryptStatusError( \
krnlSendMessage( connectInfo->iUserObject, IMESSAGE_GETATTRIBUTE,
&timeout, CRYPT_OPTION_NET_CONNECTTIMEOUT ) ) )
timeout = 30;
if( timeout < 5 )
{
/* Enforce the same minimum connect timeout as the kernel ACLs */
assert( NOTREACHED );
timeout = 5;
}
memset( stream, 0, sizeof( STREAM ) );
stream->type = STREAM_TYPE_NETWORK;
stream->protocol = protocol;
stream->timeout = INT_MAX - 1;
stream->savedTimeout = timeout;
stream->port = connectInfo->port;
stream->netSocket = stream->listenSocket = CRYPT_ERROR;
stream->iTransportSession = CRYPT_ERROR;
stream->flags = STREAM_NFLAG_ISSERVER;
switch( connectInfo->options )
{
case NET_OPTION_HOSTNAME:
if( connectInfo->name != NULL )
{
int status;
/* Parse the interface URI into its various components */
status = parseURL( &urlInfo, connectInfo->name,
strlen( connectInfo->name ), connectInfo->port );
if( cryptStatusError( status ) )
{
/* There's an error in the format, provide more
information to the caller */
strcpy( errorMessage, "Invalid interface name" );
return( CRYPT_ERROR_OPEN );
}
status = copyUrlToStream( stream, &urlInfo );
if( cryptStatusError( status ) )
return( status );
}
break;
case NET_OPTION_TRANSPORTSESSION:
stream->iTransportSession = connectInfo->iCryptSession;
break;
case NET_OPTION_NETWORKSOCKET:
case NET_OPTION_NETWORKSOCKET_DUMMY:
stream->netSocket = connectInfo->networkSocket;
stream->flags |= STREAM_NFLAG_USERSOCKET;
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR );
}
/* Set up access mechanisms and complete the connection */
return( completeConnect( stream, protocol, connectInfo->options, NULL,
connectInfo->iUserObject, connectInfo->timeout,
errorMessage, errorCode ) );
}
int sNetDisconnect( STREAM *stream )
{
cleanupStream( stream, TRUE );
return( CRYPT_OK );
}
/* Parse a URL into its various components */
int sNetParseURL( URL_INFO *urlInfo, const char *url, const int urlLen )
{
return( parseURL( urlInfo, url, urlLen, CRYPT_UNUSED ) );
}
/* Get extended information about an error status on a network connection */
void sNetGetErrorInfo( STREAM *stream, char *errorString, int *errorCode )
{
assert( isReadPtr( stream, STREAM ) );
assert( stream->type == STREAM_TYPE_NETWORK );
/* Remember the error code and message. If we're running over a
cryptlib transport session we have to first pull the info up from the
session */
if( stream->iTransportSession != CRYPT_ERROR )
getSessionErrorInfo( stream, CRYPT_OK );
*errorCode = stream->errorCode;
strcpy( errorString, stream->errorMessage );
}
#else
/****************************************************************************
* *
* Network Stream Stubs *
* *
****************************************************************************/
/* If there's no networking support present, we replace the network access
routines with dummy ones that always return an error */
int sNetConnect( STREAM *stream, const STREAM_PROTOCOL_TYPE protocol,
const NET_CONNECT_INFO *connectInfo, char *errorMessage,
int *errorCode )
{
memset( stream, 0, sizeof( STREAM ) );
return( CRYPT_ERROR_OPEN );
}
int sNetListen( STREAM *stream, const STREAM_PROTOCOL_TYPE protocol,
const NET_CONNECT_INFO *connectInfo, char *errorMessage,
int *errorCode )
{
memset( stream, 0, sizeof( STREAM ) );
return( CRYPT_ERROR_OPEN );
}
int sNetDisconnect( STREAM *stream )
{
UNUSED( stream );
return( CRYPT_OK );
}
int sNetParseURL( URL_INFO *urlInfo, const char *url, const int urlLen )
{
memset( urlInfo, 0, sizeof( URL_INFO ) );
return( CRYPT_ERROR_BADDATA );
}
void sNetGetErrorInfo( STREAM *stream, char *errorString, int *errorCode )
{
UNUSED( stream );
*errorString = '\0';
*errorCode = CRYPT_OK;
}
#endif /* USE_TCP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -