MI_Result IssueGetModuleRequest()

in LCM/dsc/engine/ca/CAInfrastructure/WebPullClient.c [1782:1998]


MI_Result  IssueGetModuleRequest( _In_z_ const MI_Char *configurationID,
                                  _In_z_ const MI_Char *moduleName,
                                  _In_z_ const MI_Char *moduleVersion,
                                  _In_z_ const MI_Char *certificateID,
                                  _In_z_ const MI_Char *filePath,
                                  _Outptr_result_maybenull_z_  MI_Char** result,
                                  _Out_ MI_Uint32* getActionStatusCode,
                                  _In_reads_z_(URL_SIZE) const MI_Char *url,
                                  _In_ MI_Uint32 port,
                                  _In_reads_z_(SUBURL_SIZE) const MI_Char *subUrl,
                                  MI_Boolean bIsHttps,
                                  _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result r = MI_RESULT_OK;
    MI_Char *outputResult = (MI_Char*)DSC_malloc((Tcslen(MI_T("OK"))+1) * sizeof(MI_Char), NitsHere());

    CURL *curl = NULL;
    CURLcode res = CURLE_OK;
    struct HeaderChunk headerChunk;
    struct Chunk dataChunk;
    char configurationUrl[MAX_URL_LENGTH];
    long responseCode = 0;
    size_t i;
    char* checksumResponse = NULL;
    char* checksumAlgorithmResponse = NULL;
    struct curl_slist *list = NULL;
    char agentIdHeader[101];

    *result = NULL;
    if( outputResult == NULL )
    {
        *getActionStatusCode = GetConfigurationCommandFailure;
        return GetCimMIError(r, extendedError, ID_ENGINEHELPER_MEMORY_ERROR);
    }
    DSC_EventWriteGetDscDocumentWebDownloadManagerServerUrl(configurationID, url);
    Stprintf(outputResult,3, MI_T("OK"));

    curl = curl_easy_init();
    if (!curl)
    {
        return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_CURLFAILEDTOINITIALIZE);
    }


    if (bIsHttps)
    {
        Snprintf(configurationUrl, MAX_URL_LENGTH, "https://%s:%d/%s/Modules(ModuleName='%s',ModuleVersion='%s')/ModuleContent", url, port, subUrl, moduleName, moduleVersion);
    }
    else
    {
        Snprintf(configurationUrl, MAX_URL_LENGTH, "http://%s:%d/%s/Modules(ModuleName='%s',ModuleVersion='%s')/ModuleContent", url, port, subUrl, moduleName, moduleVersion);
    }


    r = SetGeneralCurlOptions(curl, extendedError);
    if (r != MI_RESULT_OK)
    {
	curl_easy_cleanup(curl);
	return r;
    }

    InitHeaderChunk(&headerChunk);
    dataChunk.data = (char *)malloc(1);
    dataChunk.size = 0;

    curl_easy_setopt(curl, CURLOPT_URL, configurationUrl);

    list = curl_slist_append(list, "ProtocolVersion: 2.0");
    Snprintf(agentIdHeader, 100, "AgentId: %s", configurationID);
    agentIdHeader[100] = '\0';
    list = curl_slist_append(list, agentIdHeader);

    curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HeaderCallback);
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headerChunk);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &dataChunk);

    res = curl_easy_setopt(curl, CURLOPT_SSLCERT, OAAS_CERTPATH);
    if (res != CURLE_OK)
    {
        curl_slist_free_all(list);
        curl_easy_cleanup(curl);
        return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_CERTOPTS_NOT_SUPPORTED);
    }
    curl_easy_setopt(curl, CURLOPT_SSLKEY, OAAS_KEYPATH);

    if (g_sslOptions.cipherList[0] != '\0')
    {
        res = curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, g_sslOptions.cipherList);
        if (res != CURLE_OK)
        {
            *getActionStatusCode = GetConfigurationCommandFailure;
            curl_easy_cleanup(curl);
            return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_CURLFAILEDTOSETCIPHERLIST);
        }
    }

    if (g_sslOptions.NoSSLv3 == MI_TRUE)
    {
        res = curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
        if (res != CURLE_OK)
        {
            *getActionStatusCode = GetConfigurationCommandFailure;
            curl_easy_cleanup(curl);
            return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_CURLFAILEDTOSETNOSSLV3);
        }
    }

    res = curl_easy_perform(curl);

    curl_slist_free_all(list);
    if (res != CURLE_OK)
    {
        *getActionStatusCode = GetConfigurationCommandFailure;
        CleanupHeaderChunk(&headerChunk);
        free(dataChunk.data);
        DSC_free(outputResult);
        curl_easy_cleanup(curl);

        return GetCimMIError2Params(MI_RESULT_FAILED, extendedError, ID_PULL_CURLPERFORMFAILED, url, curl_easy_strerror(res));
    }

    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
    curl_easy_cleanup(curl);

    if (responseCode != HTTP_SUCCESS_CODE)
    {
        MI_Char statusCodeValue[MAX_STATUSCODE_SIZE] = {0};
        *getActionStatusCode = GetConfigurationCommandFailure;
        CleanupHeaderChunk(&headerChunk);
        free(dataChunk.data);
        DSC_free(outputResult);
        Stprintf(statusCodeValue, MAX_STATUSCODE_SIZE, MI_T("%d"), responseCode);
        return GetCimMIError4Params(MI_RESULT_FAILED, extendedError, ID_PULL_SERVERHTTPERRORCODEMODULE, url, statusCodeValue, moduleName, moduleVersion);
    }

    for (i = 0; i < headerChunk.size; ++i)
    {
        if (checksumResponse != NULL && checksumAlgorithmResponse != NULL)
        {
            break;
        }

        if ( Tcscasecmp(headerChunk.headerKeys[i], "Checksum") == 0 )
        {
            checksumResponse = headerChunk.headerValues[i];
        }
        else if ( Tcscasecmp(headerChunk.headerKeys[i], "ChecksumAlgorithm") == 0 )
        {
            checksumAlgorithmResponse = headerChunk.headerValues[i];
        }
    }
    if (checksumResponse == NULL || checksumAlgorithmResponse == NULL)
    {
        *getActionStatusCode = InvalidChecksumAlgorithm;
        return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_INVALIDRESPONSEFROMSERVER);
    }

    if( Tcscasecmp(checksumAlgorithmResponse, AllowedChecksumAlgorithm) != 0 )
    {
        *getActionStatusCode = InvalidChecksumAlgorithm;
        return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_INVALIDCHECKSUMALGORITHM);
    }

    if( dataChunk.size > 0 )
    {
        FILE *fp = File_OpenT(filePath, MI_T("a"));
        if(fp == NULL)
        {
            *getActionStatusCode = GetConfigurationCommandFailure;
            return GetCimMIError1Param(MI_RESULT_FAILED, extendedError,
                                       ID_PULL_CONFIGURATIONSAVEFAILED, filePath);
        }
        fwrite( dataChunk.data, 1, dataChunk.size, fp);
        File_Close(fp);
    }

    if( !ValidateChecksum(checksumResponse, filePath) )
    {
        DSC_EventWriteWebDownloadManagerGetDocChecksumValidation(NULL, NULL);
        *getActionStatusCode = ConfigurationChecksumValidationFailure;
        return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_CHECKSUMMISMATCH);
    }



    DSC_EventWriteLCMPullConfigurationChecksumValidationResult(configurationID, (MI_Uint32)MI_RESULT_OK);

    //Create checksumFile
    {
        MI_Char checksumFileName[MAX_URL_LENGTH];
        FILE *fp = NULL;
        Stprintf(checksumFileName, MAX_URL_LENGTH,MI_T("%s.checksum"), filePath);
        fp = File_OpenT(checksumFileName,MI_T("w"));
        if( fp != NULL )
        {
            fwrite(checksumResponse, 1, Strlen(checksumResponse), fp);
            File_Close(fp);
        }
        else
        {
            *getActionStatusCode = GetConfigurationCommandFailure;
            DSC_free(outputResult);
            return GetCimMIError1Param(MI_RESULT_FAILED, extendedError, ID_PULLGETCONFIGURATION_CHECKSUMSAVEFAILED, checksumFileName);
        }
    }

    CleanupHeaderChunk(&headerChunk);
    free(dataChunk.data);

    *result = outputResult;
    DSC_EventWriteWebDownloadManagerGetDocGetCall(configurationID, *result );

    return MI_RESULT_OK;
}