The following is a list of possible bugs.
Call hierarchy
connectToServerWithBackoffRetries()
SecureSocketsTransport_Connect()
establishConnect()
tlsSetup() <----(1)
SOCKETS_SetSockOpt() <----(2)(3)
(1) The size of char * is passed. This depends on the platform and is typically 4 or 8.
(2) In the caller, char * is passed, but it is assigned to char **.
(3) The loop is the number of times ctx->ulAlpnProtocolsCount minus 1 (the same value as xOptionLength).
While pSocketsConfig->pAlpnProtos is char *, we need to assign char **, and the char ** we assign must be an array with at least sizeof(char *) elements.
This is not a safe implementation and does not appear to be the intended one.
Could you please tell me how to properly specifiy or fix connetToServerWithBackoffRetries()?
Thanks
<mqtt_demo_mutual_auth.c>
... (omitted) ...
/**
* @brief This is the ALPN (Application-Layer Protocol Negotiation) string
* required by AWS IoT for password-based authentication using TCP port 443.
*
* @note OpenSSL requires that the protocol string passed to it for configuration
* be encoded with the prefix of 8-bit length information of the string. Thus, the
* 4 byte (0x04) length information is prefixed to the string.
*/
#define AWS_IOT_PASSWORD_ALPN "\x04mqtt"
/**
* @brief Length of password ALPN.
*/
#define AWS_IOT_PASSWORD_ALPN_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_PASSWORD_ALPN ) - 1 ) )
... (omitted) ...
static int connectToServerWithBackoffRetries( NetworkContext_t * pNetworkContext,
MQTTContext_t * pMqttContext,
bool * pClientSessionPresent,
bool * pBrokerSessionPresent )
{
... (omitted) ...
if( AWS_MQTT_PORT == 443 )
{
/* Pass the ALPN protocol name depending on the port being used.
* Please see more details about the ALPN protocol for the AWS IoT MQTT
* endpoint in the link below.
* https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/
*
* For username and password based authentication in AWS IoT,
* #AWS_IOT_PASSWORD_ALPN is used. More details can be found in the
* link below.
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
*/
#ifdef CLIENT_USERNAME
SocketsConfig.pAlpnProtos = AWS_IOT_PASSWORD_ALPN;
SocketsConfig.alpnProtosLen = AWS_IOT_PASSWORD_ALPN_LENGTH;
#else
SocketsConfig.pAlpnProtos = AWS_IOT_MQTT_ALPN;
SocketsConfig.alpnProtosLen = AWS_IOT_MQTT_ALPN_LENGTH;
#endif
}
... (omitted) ...
xNetworkStatus = SecureSocketsTransport_Connect( pNetworkContext,
&serverInfo,
&SocketsConfig );
... (omitted) ...
return returnStatus;
}
<transport_secure_sockets.c>
static int32_t tlsSetup( const SocketsConfig_t * pSocketsConfig,
Socket_t tcpSocket,
const char * pHostName,
size_t hostnameLength )
{
... (omitted) ...
/* Set ALPN option. */
if( ( secureSocketStatus == SOCKETS_ERROR_NONE ) && ( pSocketsConfig->pAlpnProtos != NULL ) )
{
secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket,
0,
SOCKETS_SO_ALPN_PROTOCOLS,
pSocketsConfig->pAlpnProtos,
sizeof(pSocketsConfig->pAlpnProtos ) ); //<----(1)
if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE )
{
LogError( ( "Failed to set ALPN option socket.secureSocketStatus=%d", secureSocketStatus ) );
}
}
... (omitted) ...
return secureSocketStatus;
}
<iot_secure_sockets.c>
int32_t SOCKETS_SetSockOpt( Socket_t xSocket,
int32_t lLevel,
int32_t lOptionName,
const void * pvOptionValue,
size_t xOptionLength )
{
ss_ctx_t * ctx;
int ret = 0;
char ** ppcAlpnIn = ( char ** ) pvOptionValue; //<----(2)
size_t xLength = 0;
uint32_t ulProtocol;
... (omitted) ...
case SOCKETS_SO_ALPN_PROTOCOLS:
/* Do not set the ALPN option if the socket is already connected. */
if( ctx->status & SS_STATUS_CONNECTED )
{
return SOCKETS_EISCONN;
}
/* Allocate a sufficiently long array of pointers. */
ctx->ulAlpnProtocolsCount = 1 + xOptionLength;
if( NULL == ( ctx->ppcAlpnProtocols =
( char ** ) pvPortMalloc( ctx->ulAlpnProtocolsCount *
sizeof( char * ) ) ) )
{
return SOCKETS_ENOMEM;
}
else
{
memset( ctx->ppcAlpnProtocols,
0x00,
ctx->ulAlpnProtocolsCount * sizeof( char * ) );
}
/* Copy each protocol string. */
for( ulProtocol = 0; ( ulProtocol < ctx->ulAlpnProtocolsCount - 1 ); //<----(3)
ulProtocol++ )
{
xLength = strlen( ppcAlpnIn[ ulProtocol ] );
if( NULL == ( ctx->ppcAlpnProtocols[ ulProtocol ] =
( char * ) pvPortMalloc( 1 + xLength ) ) )
{
ctx->ppcAlpnProtocols[ ulProtocol ] = NULL;
return SOCKETS_ENOMEM;
}
else
{
memcpy( ctx->ppcAlpnProtocols[ ulProtocol ],
ppcAlpnIn[ ulProtocol ],
xLength );
ctx->ppcAlpnProtocols[ ulProtocol ][ xLength ] = '\0';
}
}
break;
... (omitted) ...
return ret;
}