Example #1
0
void *extension_library_open(const char *name)
{
    if (!enable_extension_libraries)
    {
        return NULL;
    }

    if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") == NULL)
    {
        // Only do loading checks if we are not doing tests.
        attempted_loading = true;
    }

    const char *dir = getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR");
    char lib[] = "/lib";
    if (dir)
    {
        lib[0] = '\0';
    }
    else
    {
        dir = GetWorkDir();
    }
    char path[strlen(dir) + strlen(lib) + strlen(name) + 2];
    sprintf(path, "%s%s/%s", dir, lib, name);
    void *handle = shlib_open(path);
    if (!handle)
    {
        return handle;
    }

    // Version check, to avoid binary incompatible plugins.
    const char * (*GetExtensionLibraryVersion)() = shlib_load(handle, "GetExtensionLibraryVersion");
    if (!GetExtensionLibraryVersion)
    {
        Log(LOG_LEVEL_ERR, "Could not retreive version from extension plugin (%s). Not loading the plugin.", name);
        goto close_and_fail;
    }

    const char *plugin_version = GetExtensionLibraryVersion();
    unsigned int bin_major, bin_minor, bin_patch;
    unsigned int plug_major, plug_minor, plug_patch;
    if (sscanf(VERSION, "%u.%u.%u", &bin_major, &bin_minor, &bin_patch) != 3)
    {
        Log(LOG_LEVEL_ERR, "Not able to extract version number from binary (%s). Not loading extension plugin.", name);
        goto close_and_fail;
    }
    if (sscanf(plugin_version, "%u.%u.%u", &plug_major, &plug_minor, &plug_patch) != 3)
    {
        Log(LOG_LEVEL_ERR, "Not able to extract version number from plugin (%s). Not loading extension plugin.", name);
        goto close_and_fail;
    }

    if (bin_major != plug_major || bin_minor != plug_minor || bin_patch != plug_patch)
    {
        Log(LOG_LEVEL_ERR, "Extension plugin version does not match CFEngine Community version "
            "(CFEngine Community v%u.%u.%u, Extension (%s) v%u.%u.%u). Refusing to load it.",
            bin_major, bin_minor, bin_patch, name, plug_major, plug_minor, plug_patch);
        goto close_and_fail;
    }

    return handle;

close_and_fail:
    shlib_close(handle);
    return NULL;
}
Example #2
0
void *extension_library_open(const char *name)
{
    if (!enable_extension_libraries)
    {
        return NULL;
    }

    if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") == NULL)
    {
        // Only do loading checks if we are not doing tests.
        attempted_loading = true;
    }

    const char *dirs_to_try[3] = { NULL };
    const char *dir = getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR");
    char lib[] = "/lib";
    if (dir)
    {
        lib[0] = '\0';
        dirs_to_try[0] = dir;
    }
    else
    {
        dirs_to_try[0] = GetWorkDir();
        if (strcmp(WORKDIR, dirs_to_try[0]) != 0)
        {
            // try to load from the real WORKDIR in case GetWorkDir returned the local workdir to the user
            // We try this because enterprise "make install" is in WORKDIR, not per user
            dirs_to_try[1] = WORKDIR;
        }
    }

    void *handle = NULL;
    for (int i = 0; dirs_to_try[i]; i++)
    {
        char path[strlen(dirs_to_try[i]) + strlen(lib) + strlen(name) + 2];
        xsnprintf(path, sizeof(path), "%s%s/%s", dirs_to_try[i], lib, name);

        Log(LOG_LEVEL_DEBUG, "Trying to shlib_open extension plugin '%s' from '%s'", name, path);

        handle = shlib_open(path);
        if (handle)
        {
            Log(LOG_LEVEL_VERBOSE, "Successfully opened extension plugin '%s' from '%s'", name, path);
            break;
        }
        else
        {
            const char *error;
            if (errno == ENOENT)
            {
                error = "(not installed)";
            }
            else
            {
                error = GetErrorStr();
            }
            Log(LOG_LEVEL_VERBOSE, "Could not open extension plugin '%s' from '%s': %s", name, path, error);
        }
    }

    if (!handle)
    {
        return handle;
    }

    // Version check, to avoid binary incompatible plugins.
    const char * (*GetExtensionLibraryVersion)() = shlib_load(handle, "GetExtensionLibraryVersion");
    if (!GetExtensionLibraryVersion)
    {
        Log(LOG_LEVEL_ERR, "Could not retrieve version from extension plugin (%s). Not loading the plugin.", name);
        goto close_and_fail;
    }

    const char *plugin_version = GetExtensionLibraryVersion();
    unsigned int bin_major, bin_minor, bin_patch;
    unsigned int plug_major, plug_minor, plug_patch;
    if (sscanf(VERSION, "%u.%u.%u", &bin_major, &bin_minor, &bin_patch) != 3)
    {
        Log(LOG_LEVEL_ERR, "Not able to extract version number from binary (%s). Not loading extension plugin.", name);
        goto close_and_fail;
    }
    if (sscanf(plugin_version, "%u.%u.%u", &plug_major, &plug_minor, &plug_patch) != 3)
    {
        Log(LOG_LEVEL_ERR, "Not able to extract version number from plugin (%s). Not loading extension plugin.", name);
        goto close_and_fail;
    }

    if (bin_major != plug_major || bin_minor != plug_minor || bin_patch != plug_patch)
    {
        Log(LOG_LEVEL_ERR, "Extension plugin version does not match CFEngine Community version "
            "(CFEngine Community v%u.%u.%u, Extension (%s) v%u.%u.%u). Refusing to load it.",
            bin_major, bin_minor, bin_patch, name, plug_major, plug_minor, plug_patch);
        goto close_and_fail;
    }

    Log(LOG_LEVEL_VERBOSE, "Successfully loaded extension plugin '%s'", name);

    return handle;

close_and_fail:
    shlib_close(handle);
    return NULL;
}