in agent/native/ext/backend_comm.cpp [316:427]
ResultCode initConnectionData( const ConfigSnapshot* config, ConnectionData* connectionData, StringView userAgentHttpHeader )
{
ResultCode resultCode;
enum { authBufferSize = 256 };
char auth[authBufferSize];
const char* authKind = NULL;
const char* authValue = NULL;
int snprintfRetVal;
char txtOutStreamBuf[ ELASTIC_APM_TEXT_OUTPUT_STREAM_ON_STACK_BUFFER_SIZE ];
TextOutputStream txtOutStream = ELASTIC_APM_TEXT_OUTPUT_STREAM_FROM_STATIC_BUFFER( txtOutStreamBuf );
ELASTIC_APM_ASSERT_VALID_PTR( connectionData );
ELASTIC_APM_ASSERT( connectionData->curlHandle == NULL, "" );
ELASTIC_APM_ASSERT( connectionData->requestHeaders == NULL, "" );
ELASTIC_APM_LOG_DEBUG_FUNCTION_ENTRY_MSG(
"config: {serverUrl: %s, disableSend: %s, serverTimeout: %s, devInternalBackendCommLogVerbose: %s}"
"; userAgentHttpHeader: `%s'"
"; curl info: %s"
, config->serverUrl, boolToString( config->disableSend ), streamDuration( config->serverTimeout, &txtOutStream ), boolToString( config->devInternalBackendCommLogVerbose )
, streamStringView( userAgentHttpHeader, &txtOutStream )
, streamLibCurlInfo( &txtOutStream ) );
textOutputStreamRewind( &txtOutStream );
connectionData->curlHandle = curl_easy_init();
if ( connectionData->curlHandle == NULL )
{
ELASTIC_APM_LOG_ERROR( "curl_easy_init() returned NULL; curl info: %s", streamLibCurlInfo( &txtOutStream ) );
ELASTIC_APM_SET_RESULT_CODE_AND_GOTO_FAILURE_EX( resultCurlFailure );
}
ELASTIC_APM_CURL_EASY_SETOPT( connectionData->curlHandle, CURLOPT_WRITEFUNCTION, logResponse );
if ( config->devInternalBackendCommLogVerbose )
{
enableCurlVerboseMode( connectionData->curlHandle );
}
if ( config->serverTimeout.valueInUnits == 0 )
{
ELASTIC_APM_LOG_DEBUG_FUNCTION_ENTRY_MSG( "Timeout is disabled. %s (serverTimeout): %s"
, ELASTIC_APM_CFG_OPT_NAME_SERVER_TIMEOUT, streamDuration( config->serverTimeout, &txtOutStream ) );
textOutputStreamRewind( &txtOutStream );
}
else
{
long serverTimeoutInMilliseconds = (long)durationToMilliseconds( config->serverTimeout );
ELASTIC_APM_CURL_EASY_SETOPT( connectionData->curlHandle, CURLOPT_TIMEOUT_MS, serverTimeoutInMilliseconds );
}
if ( ! config->verifyServerCert )
{
ELASTIC_APM_LOG_DEBUG( "verify_server_cert configuration option is set to false - disabling SSL/TLS certificate verification for communication with APM Server..." );
/**
* This option determines whether libcurl verifies that the server cert is for the server it is known as.
* When negotiating TLS and SSL connections, the server sends a certificate indicating its identity.
* When CURLOPT_SSL_VERIFYHOST is 2, that certificate must indicate that the server is the server to which you meant to connect, or the connection fails.
* Simply put, it means it has to have the same name in the certificate as is in the URL you operate against.
* When the verify value is 0, the connection succeeds regardless of the names in the certificate.
*
* @link https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html
*/
ELASTIC_APM_CURL_EASY_SETOPT( connectionData->curlHandle, CURLOPT_SSL_VERIFYHOST, 0L );
/**
* This option determines whether curl verifies the authenticity of the peer's certificate. A value of 1 means curl verifies; 0 (zero) means it does not.
* Authenticating the certificate is not enough to be sure about the server. You typically also want to ensure that the server is the server you mean to be talking to.
* Use CURLOPT_SSL_VERIFYHOST for that.
* The check that the host name in the certificate is valid for the host name you are connecting to is done independently of the CURLOPT_SSL_VERIFYPEER option.
*
* @link https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
*/
ELASTIC_APM_CURL_EASY_SETOPT( connectionData->curlHandle, CURLOPT_SSL_VERIFYPEER, 0L );
}
// Authorization with API key or secret token if present
if ( ! isNullOrEmtpyString( config->apiKey ) )
{
authKind = "ApiKey";
authValue = config->apiKey;
}
else if ( ! isNullOrEmtpyString( config->secretToken ) )
{
authKind = "Bearer";
authValue = config->secretToken;
}
if ( authValue != NULL )
{
snprintfRetVal = snprintf( auth, authBufferSize, "Authorization: %s %s", authKind, authValue );
if ( snprintfRetVal < 0 || snprintfRetVal >= authBufferSize )
{
ELASTIC_APM_LOG_ERROR( "Failed to build Authorization header."
" snprintfRetVal: %d. authKind: %s. authValue: %s.", snprintfRetVal, authKind, authValue );
ELASTIC_APM_SET_RESULT_CODE_AND_GOTO_FAILURE();
}
ELASTIC_APM_LOG_TRACE( "Adding header: %s", auth );
ELASTIC_APM_CALL_IF_FAILED_GOTO( addToCurlStringList( /* in,out */ &connectionData->requestHeaders, auth ) );
}
ELASTIC_APM_CALL_IF_FAILED_GOTO( addToCurlStringList( /* in,out */ &connectionData->requestHeaders, "Content-Type: application/x-ndjson" ) );
ELASTIC_APM_CURL_EASY_SETOPT( connectionData->curlHandle, CURLOPT_HTTPHEADER, connectionData->requestHeaders );
ELASTIC_APM_CURL_EASY_SETOPT( connectionData->curlHandle, CURLOPT_USERAGENT, userAgentHttpHeader );
resultCode = resultSuccess;
finally:
ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT();
return resultCode;
failure:
goto finally;
}