MI_Result GetMetaConfigParameters()

in LCM/dsc/engine/ca/CAInfrastructure/WebPullClient.c [584:876]


MI_Result GetMetaConfigParameters(_In_ MI_Instance *metaConfig,
                                  _In_ MI_Char* partialConfigName,
                                  _Outptr_opt_result_maybenull_    MI_Instance **credential,
                                  _Inout_    MI_InstanceA *customParam,
                                  _Outptr_result_maybenull_z_ MI_Char **configurationID,
                                  _Outptr_result_maybenull_z_ MI_Char **certificateID,
                                  _Inout_updates_(URL_SIZE) MI_Char *url,
                                  _Inout_updates_(SUBURL_SIZE) MI_Char *subUrl,
                                  _Out_ MI_Uint32 *port,
                                  _Out_ MI_Boolean *bIsHttps,
                                  _Out_ MI_Uint32* getActionStatusCode,
                                  _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result r = MI_RESULT_OK;
    MI_Value value;
    MI_Value value2;
    MI_Value value3;
    MI_Char serverURL[MAX_URL_LENGTH];
    MI_Uint32 flags;
    MI_Uint32 xCount;
    MI_Char* configurationSource = NULL;
    MI_Boolean allowUnsecureConnection = MI_FALSE;
    MI_InstanceA customData;
    *credential = NULL;
    *extendedError = NULL;
    *getActionStatusCode = Success;
    *configurationID = NULL;
    *certificateID = NULL;
    *bIsHttps = MI_FALSE;
    *port = DEFAULT_SERVERPORT;
    *getActionStatusCode = Success;
    *extendedError = NULL;
    *serverURL = '\0';

    // 1. Get AgentID
    r = MI_Instance_GetElement(metaConfig, MSFT_DSCMetaConfiguration_AgentId, &value, NULL, &flags, NULL);
    if( r != MI_RESULT_OK || (flags & MI_FLAG_NULL))
    {
        *getActionStatusCode = InvalidConfigurationIdInMetaConfig;
        r = GetCimMIError(r, extendedError, ID_PULL_CONFIGURATIONIDNOTSPECIFIED);
        return r;
    }

    *configurationID = (MI_Char*)DSC_malloc((Tcslen(value.string)+1) * sizeof(MI_Char), NitsHere());
    if( *configurationID == NULL)
    {
        *getActionStatusCode = InvalidConfigurationIdInMetaConfig;
        r = GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_ENGINEHELPER_MEMORY_ERROR);
        return r;
    }
    memcpy(*configurationID, value.string, Tcslen(value.string)* sizeof(MI_Char));
    /* Validate the Uuid.*/
/*
    if( !IsValidUuid(*configurationID))
    {
        *getActionStatusCode = InvalidConfigurationIdFormat;
        r = GetCimMIError1Param(MI_RESULT_FAILED, extendedError, ID_PULL_INVALIDCONFIGURATIONIDFORMAT, *configurationID);
        DSC_free(*configurationID);
        return r;
    }
*/

    // 2. Get Credential.
    r = MI_Instance_GetElement(metaConfig, MetaConfig_Credential, &value, NULL, &flags, NULL);
    if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
    {
        *credential = value.instance;
    }



    // If partialConfigName is defined, get the ConfigurationDownloadManagers, else get the DownloadManagerCustomData
    if ( partialConfigName != NULL )
    {
        // NOTE: Request miType for GetElement calls to aid in debugging schema changes.
        MI_Type miType;
        r = MI_Instance_GetElement(metaConfig, MSFT_DSCMetaConfiguration_PartialConfigurations, &value, &miType, &flags, NULL);
        if (r != MI_RESULT_OK || (flags & MI_FLAG_NULL))
        {
            return GetCimMIError(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOPARTIALCONFIGS);
        }

        for (xCount = 0; xCount < value.instancea.size; ++xCount)
        {
            MI_Instance_GetElement(value.instancea.data[xCount], OMI_MetaConfigurationResource_ResourceId, &value2, &miType, &flags, NULL);
            if ( Tcscasecmp(value2.string, partialConfigName) == 0 )
            {
                // Found our partial config! Now let's get the configuration source
                MI_Instance_GetElement(value.instancea.data[xCount], MSFT_PartialConfiguration_ConfigurationSource, &value2, &miType, &flags, NULL);
                if (r != MI_RESULT_OK || (flags & MI_FLAG_NULL))
                {
                    return GetCimMIError1Param(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOCONFIGURATIONSOURCE, partialConfigName);
                }

                configurationSource = value2.stringa.data[0];
                break;
            }
        }
        if (configurationSource == NULL)
        {
            // Unable to find partial configuration with this name.
            return GetCimMIError1Param(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOCONFIGURATIONSOURCE, partialConfigName);
        }

        r = MI_Instance_GetElement(metaConfig, MSFT_DSCMetaConfiguration_ConfigurationDownloadManagers, &value, &miType, &flags, NULL);
        if (r != MI_RESULT_OK || (flags & MI_FLAG_NULL))
        {
            // Unable to get the config download managers
            return GetCimMIError(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOCONFIGDOWNLOADMANAGERS);
        }

        for (xCount = 0; xCount < value.instancea.size; ++xCount)
        {
            MI_Instance_GetElement(value.instancea.data[xCount], OMI_MetaConfigurationResource_ResourceId, &value2, &miType, &flags, NULL);
            if ( Tcscasecmp(value2.string, configurationSource) == 0 )
            {
                // Found the WebDownloadManager with the proper resource ID.
                MI_Instance_GetElement(value.instancea.data[xCount], MI_T("ServerURL"), &value2, &miType, &flags, NULL);
                if (r != MI_RESULT_OK || (flags & MI_FLAG_NULL))
                {
                    return GetCimMIError1Param(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOSERVERURL, value3.string);
                }

                memcpy(serverURL, value2.string, (Tcslen(value2.string) + 1) * sizeof(MI_Char));

                MI_Instance_GetElement(value.instancea.data[xCount], MI_T("CertificateID"), &value2, &miType, &flags, NULL);
                if (r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
                {
                    memcpy(*certificateID, value2.string, Tcslen(value2.string) * sizeof(MI_Char));
                }

                MI_Instance_GetElement(value.instancea.data[xCount], MI_T("AllowUnsecureConnection"), &value2, &miType, &flags, NULL);
                if (r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
                {
                    allowUnsecureConnection = value2.boolean;
                }

                //Check if connection is secure and if unsecure user explicitly asks for it.
                if( Tcsncasecmp(serverURL, MI_T("https"), 5) != 0 && allowUnsecureConnection == MI_FALSE )
                {
                    *getActionStatusCode = InvalidDownloadManagerCustomDataInMetaConfig;
                    r = GetCimMIError1Param( MI_RESULT_INVALID_PARAMETER, extendedError, ID_PULL_UNSECURECONNECTIONNOTALLOWED, serverURL);
                    return r;
                }
                // Found the WebDownloadManager, stop searching.
                break;
            }
        }
    }
    else
    {
        // 3. Get custom arguments.
        r = MI_Instance_GetElement(metaConfig, MetaConfigDownloadManagerCustomData, &value, NULL, &flags, NULL);
        if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
        {
            customParam->size = value.instancea.size;
            customParam->data = value.instancea.data;
        }


        // 4. Get certificate ID.
        for( xCount =0; xCount < customParam->size; xCount++)
        {
            MI_Value value;
            MI_Uint32 flags;
            r = MI_Instance_GetElement(customParam->data[xCount], MSFT_KEYVALUEPAIR_CLASS_KEY, &value, NULL, &flags, NULL);
            if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL) && Tcscasecmp(CertificateIdParamName, value.string) == 0 )
            {
                r = MI_Instance_GetElement(customParam->data[xCount], MSFT_KEYVALUEPAIR_CLASS_VALUE, &value, NULL, &flags, NULL);
                if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL) )
                {
                    *certificateID = (MI_Char*)DSC_malloc((Tcslen(value.string)+1) * sizeof(MI_Char), NitsHere());
                    if( *certificateID == NULL)
                    {
                        *getActionStatusCode = InvalidConfigurationIdInMetaConfig;
                        r = GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_ENGINEHELPER_MEMORY_ERROR);
                        if( *configurationID )
                            DSC_free(*configurationID);
                        *configurationID = NULL;
                        return r;
                    }
                    memcpy(*certificateID, value.string, Tcslen(value.string)* sizeof(MI_Char));
                    break;
                }
            }
        }
    }

    if (*serverURL == '\0')
    {
        r = MI_Instance_GetElement(metaConfig, MetaConfigDownloadManagerCustomData, &value, NULL, &flags, NULL);
        if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
        {
            customData.size = value.instancea.size;
            customData.data = value.instancea.data;

            // Get Server Url.
            for( xCount =0; xCount < customData.size; xCount++)
            {
                MI_Value value;
                MI_Uint32 flags;
                r = MI_Instance_GetElement(customData.data[xCount], MSFT_KEYVALUEPAIR_CLASS_KEY, &value, NULL, &flags, NULL);
                if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL) && Tcscasecmp(ServerUrlParamName, value.string) == 0 )
                {
                    r = MI_Instance_GetElement(customData.data[xCount], MSFT_KEYVALUEPAIR_CLASS_VALUE, &value, NULL, &flags, NULL);
                    if( r == MI_RESULT_OK && !(flags & MI_FLAG_NULL) )
                    {
                        // Found ServerUrl in value.string
                        memcpy(serverURL, value.string, (Tcslen(value.string) + 1) * sizeof(MI_Char));

                        //Check if connection is secure and if unsecure user explicitly asks for it.
                        if( !ConnectionAllowed(&customData, serverURL) )
                        {
                            *getActionStatusCode = InvalidDownloadManagerCustomDataInMetaConfig;
                            r = GetCimMIError1Param( MI_RESULT_INVALID_PARAMETER, extendedError, ID_PULL_UNSECURECONNECTIONNOTALLOWED, serverURL);
                            return r;
                        }

                        break;
                    }
                }
            }
        }
        else
        {
            // There's no DownloadManagerCustomData, AND there's no partial configuration.  We should be able to find WebDownloadManager, and only one!
            r = MI_Instance_GetElement(metaConfig, MSFT_DSCMetaConfiguration_ConfigurationDownloadManagers, &value, NULL, &flags, NULL);
            if (r != MI_RESULT_OK || (flags & MI_FLAG_NULL) || value.instancea.size == 0)
            {
                // Unable to get the config download managers
                return GetCimMIError(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOCONFIGDOWNLOADMANAGERS);
            }

            if (value.instancea.size > 1)
            {
                // Too many download managers defined, please set up partial configuration for this.
                return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_PULL_TOOMANYCONFIGDOWNLOADMANAGERS);
            }

            MI_Instance_GetElement(value.instancea.data[0], OMI_MetaConfigurationResource_ResourceId, &value3, NULL, &flags, NULL);

            // Found the WebDownloadManager with the proper resource ID.
            MI_Instance_GetElement(value.instancea.data[0], MI_T("ServerURL"), &value2, NULL, &flags, NULL);
            if (r != MI_RESULT_OK || (flags & MI_FLAG_NULL))
            {
                return GetCimMIError1Param(MI_RESULT_NO_SUCH_PROPERTY, extendedError, ID_PULL_NOSERVERURL, value3.string);
            }

            memcpy(serverURL, value2.string, (Tcslen(value2.string) + 1) * sizeof(MI_Char));

            MI_Instance_GetElement(value.instancea.data[0], MI_T("CertificateID"), &value2, NULL, &flags, NULL);
            if (r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
            {
                memcpy(*certificateID, value2.string, Tcslen(value2.string) * sizeof(MI_Char));
            }

            MI_Instance_GetElement(value.instancea.data[0], MI_T("AllowUnsecureConnection"), &value2, NULL, &flags, NULL);
            if (r == MI_RESULT_OK && !(flags & MI_FLAG_NULL))
            {
                allowUnsecureConnection = value2.boolean;
            }
        }
    }

    if (*serverURL != '\0')
    {
        if( sscanf(serverURL, MI_T("http://%99[^:]:%d/%199[^\n]"), url, port, subUrl) == 3 ||
            sscanf(serverURL, MI_T("http://%99[^/]/%199[^\n]"), url, subUrl) == 2 )
        {
            //success
        }
        //format is: http://server:port/suburl or http://server/suburl
        else if( sscanf(serverURL, MI_T("https://%99[^:]:%d/%199[^\n]"), url, port, subUrl) == 3 ||
                 sscanf(serverURL, MI_T("https://%99[^/]/%199[^\n]"), url, subUrl) == 2 )
        {
            //success
            *bIsHttps = MI_TRUE;
            if (*port == 80)
            {
                *port = 443;
            }
        }
    }
    else
    {
        // Not found
        *getActionStatusCode = InvalidDownloadManagerCustomDataInMetaConfig;
        return GetCimMIError(r, extendedError, ID_ENGINEHELPER_MEMORY_ERROR);
    }

    return MI_RESULT_OK;

}