Blame src/core/settings/plugins/keyfile/nms-keyfile-reader.c

Packit Service 5ffa24
/* SPDX-License-Identifier: GPL-2.0-or-later */
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Copyright (C) 2015 Red Hat, Inc.
Packit Service 5ffa24
 */
Packit Service 5ffa24
Packit Service 2bceb2
#include "src/core/nm-default-daemon.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nms-keyfile-reader.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include <sys/stat.h>
Packit Service 5ffa24
Packit Service 2bceb2
#include "nm-keyfile-internal.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "NetworkManagerUtils.h"
Packit Service 5ffa24
#include "nms-keyfile-utils.h"
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static const char *
Packit Service 5ffa24
_fmt_warn(const NMKeyfileHandlerData *handler_data, char **out_message)
Packit Service 5ffa24
{
Packit Service 5ffa24
    const char *group   = handler_data->kf_group_name;
Packit Service 5ffa24
    const char *message = _nm_keyfile_handler_data_warn_get_message(handler_data);
Packit Service 5ffa24
Packit Service 5ffa24
    if (group) {
Packit Service 5ffa24
        NMSetting * setting       = handler_data->cur_setting;
Packit Service 5ffa24
        const char *property_name = handler_data->cur_property;
Packit Service 5ffa24
        const char *setting_name  = setting ? nm_setting_get_name(setting) : NULL;
Packit Service 5ffa24
        char *      res;
Packit Service 5ffa24
Packit Service 5ffa24
        if (setting_name) {
Packit Service 5ffa24
            if (property_name && !strcmp(group, setting_name))
Packit Service 5ffa24
                res = g_strdup_printf("%s.%s: %s", group, property_name, message);
Packit Service 5ffa24
            else if (property_name)
Packit Service 5ffa24
                res = g_strdup_printf("%s/%s.%s: %s", group, setting_name, property_name, message);
Packit Service 5ffa24
            else if (!strcmp(group, setting_name))
Packit Service 5ffa24
                res = g_strdup_printf("%s: %s", group, message);
Packit Service 5ffa24
            else
Packit Service 5ffa24
                res = g_strdup_printf("%s/%s: %s", group, setting_name, message);
Packit Service 5ffa24
        } else
Packit Service 5ffa24
            res = g_strdup_printf("%s: %s", group, message);
Packit Service 5ffa24
        *out_message = res;
Packit Service 5ffa24
        return res;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return message;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    bool verbose;
Packit Service 5ffa24
} ReadInfo;
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
_handler_read(GKeyFile *            keyfile,
Packit Service 5ffa24
              NMConnection *        connection,
Packit Service 5ffa24
              NMKeyfileHandlerType  handler_type,
Packit Service 5ffa24
              NMKeyfileHandlerData *handler_data,
Packit Service 5ffa24
              void *                user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    const ReadInfo *read_info = user_data;
Packit Service 5ffa24
Packit Service 5ffa24
    if (handler_type == NM_KEYFILE_HANDLER_TYPE_WARN) {
Packit Service 5ffa24
        const NMKeyfileHandlerDataWarn *warn_data = &handler_data->warn;
Packit Service 5ffa24
        NMLogLevel                      level;
Packit Service 5ffa24
        char *                          message_free = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!read_info->verbose)
Packit Service 5ffa24
            return TRUE;
Packit Service 5ffa24
Packit Service 5ffa24
        if (warn_data->severity > NM_KEYFILE_WARN_SEVERITY_WARN)
Packit Service 5ffa24
            level = LOGL_ERR;
Packit Service 5ffa24
        else if (warn_data->severity >= NM_KEYFILE_WARN_SEVERITY_WARN)
Packit Service 5ffa24
            level = LOGL_WARN;
Packit Service 5ffa24
        else if (warn_data->severity == NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE)
Packit Service 5ffa24
            level = LOGL_WARN;
Packit Service 5ffa24
        else
Packit Service 5ffa24
            level = LOGL_INFO;
Packit Service 5ffa24
Packit Service 5ffa24
        nm_log(level,
Packit Service 5ffa24
               LOGD_SETTINGS,
Packit Service 5ffa24
               NULL,
Packit Service 5ffa24
               nm_connection_get_uuid(connection),
Packit Service 5ffa24
               "keyfile: %s",
Packit Service 5ffa24
               _fmt_warn(handler_data, &message_free));
Packit Service 5ffa24
        g_free(message_free);
Packit Service 5ffa24
        return TRUE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return FALSE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMConnection *
Packit Service 5ffa24
nms_keyfile_reader_from_keyfile(GKeyFile *  key_file,
Packit Service 5ffa24
                                const char *filename,
Packit Service 5ffa24
                                const char *base_dir,
Packit Service 5ffa24
                                const char *profile_dir,
Packit Service 5ffa24
                                gboolean    verbose,
Packit Service 5ffa24
                                GError **   error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *connection;
Packit Service 5ffa24
    ReadInfo      read_info = {
Packit Service 5ffa24
        .verbose = verbose,
Packit Service 5ffa24
    };
Packit Service 5ffa24
    gs_free char *base_dir_free         = NULL;
Packit Service 5ffa24
    gs_free char *profile_filename_free = NULL;
Packit Service 5ffa24
    gs_free char *filename_id           = NULL;
Packit Service 5ffa24
    const char *  profile_filename      = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(filename && filename[0]);
Packit Service 5ffa24
    nm_assert(!base_dir || base_dir[0] == '/');
Packit Service 5ffa24
    nm_assert(!profile_dir || profile_dir[0] == '/');
Packit Service 5ffa24
Packit Service 5ffa24
    if (base_dir)
Packit Service 5ffa24
        nm_assert(!strchr(filename, '/'));
Packit Service 5ffa24
    else {
Packit Service 5ffa24
        const char *s;
Packit Service 5ffa24
Packit Service 5ffa24
        nm_assert(filename[0] == '/');
Packit Service 5ffa24
Packit Service 5ffa24
        /* @base_dir may be NULL, in which case @filename must be an absolute path,
Packit Service 5ffa24
         * and the directory is taken as the @base_dir. */
Packit Service 5ffa24
        s        = strrchr(filename, '/');
Packit Service 5ffa24
        base_dir = nm_strndup_a(255, filename, s - filename, &base_dir_free);
Packit Service 5ffa24
        if (!profile_dir || nm_streq(base_dir, profile_dir))
Packit Service 5ffa24
            profile_filename = filename;
Packit Service 5ffa24
        filename = &s[1];
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    connection = nm_keyfile_read(key_file,
Packit Service 5ffa24
                                 base_dir,
Packit Service 5ffa24
                                 NM_KEYFILE_HANDLER_FLAGS_NONE,
Packit Service 5ffa24
                                 _handler_read,
Packit Service 5ffa24
                                 &read_info,
Packit Service 5ffa24
                                 error);
Packit Service 5ffa24
    if (!connection)
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (g_str_has_suffix(filename, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION)) {
Packit Service 5ffa24
        gsize l = strlen(filename);
Packit Service 5ffa24
Packit Service 5ffa24
        if (l > NM_STRLEN(NM_KEYFILE_PATH_SUFFIX_NMCONNECTION))
Packit Service 5ffa24
            filename_id = g_strndup(filename, l - NM_STRLEN(NM_KEYFILE_PATH_SUFFIX_NMCONNECTION));
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_keyfile_read_ensure_id(connection, filename_id ?: filename);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!profile_filename) {
Packit Service 5ffa24
        profile_filename_free = g_build_filename(profile_dir ?: base_dir, filename, NULL);
Packit Service 5ffa24
        profile_filename      = profile_filename_free;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    nm_keyfile_read_ensure_uuid(connection, profile_filename);
Packit Service 5ffa24
Packit Service 5ffa24
    return connection;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMConnection *
Packit Service 5ffa24
nms_keyfile_reader_from_file(const char * full_filename,
Packit Service 5ffa24
                             const char * profile_dir,
Packit Service 5ffa24
                             struct stat *out_stat,
Packit Service 5ffa24
                             NMTernary *  out_is_nm_generated,
Packit Service 5ffa24
                             NMTernary *  out_is_volatile,
Packit Service 5ffa24
                             NMTernary *  out_is_external,
Packit Service 5ffa24
                             char **      out_shadowed_storage,
Packit Service 5ffa24
                             NMTernary *  out_shadowed_owned,
Packit Service 5ffa24
                             GError **    error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    nm_auto_unref_keyfile GKeyFile *key_file     = NULL;
Packit Service 5ffa24
    NMConnection *                  connection   = NULL;
Packit Service 5ffa24
    GError *                        verify_error = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(full_filename && full_filename[0] == '/');
Packit Service 5ffa24
    nm_assert(!profile_dir || profile_dir[0] == '/');
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_is_nm_generated, NM_TERNARY_DEFAULT);
Packit Service 5ffa24
    NM_SET_OUT(out_is_volatile, NM_TERNARY_DEFAULT);
Packit Service 5ffa24
    NM_SET_OUT(out_is_external, NM_TERNARY_DEFAULT);
Packit Service 5ffa24
    NM_SET_OUT(out_shadowed_owned, NM_TERNARY_DEFAULT);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nms_keyfile_utils_check_file_permissions(NMS_KEYFILE_FILETYPE_KEYFILE,
Packit Service 5ffa24
                                                  full_filename,
Packit Service 5ffa24
                                                  out_stat,
Packit Service 5ffa24
                                                  error))
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    key_file = g_key_file_new();
Packit Service 5ffa24
    if (!g_key_file_load_from_file(key_file, full_filename, G_KEY_FILE_NONE, error))
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    connection =
Packit Service 5ffa24
        nms_keyfile_reader_from_keyfile(key_file, full_filename, NULL, profile_dir, TRUE, error);
Packit Service 5ffa24
    if (!connection)
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Normalize and verify the connection */
Packit Service 5ffa24
    if (!nm_connection_normalize(connection, NULL, NULL, &verify_error)) {
Packit Service 5ffa24
        g_set_error(error,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR_INVALID_CONNECTION,
Packit Service 5ffa24
                    "invalid connection: %s",
Packit Service 5ffa24
                    verify_error->message);
Packit Service 5ffa24
        g_clear_error(&verify_error);
Packit Service 5ffa24
        g_object_unref(connection);
Packit Service 5ffa24
        connection = NULL;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_is_nm_generated,
Packit Service 5ffa24
               nm_key_file_get_boolean(key_file,
Packit Service 5ffa24
                                       NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                                       NM_KEYFILE_KEY_NMMETA_NM_GENERATED,
Packit Service 5ffa24
                                       NM_TERNARY_DEFAULT));
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_is_volatile,
Packit Service 5ffa24
               nm_key_file_get_boolean(key_file,
Packit Service 5ffa24
                                       NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                                       NM_KEYFILE_KEY_NMMETA_VOLATILE,
Packit Service 5ffa24
                                       NM_TERNARY_DEFAULT));
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_is_external,
Packit Service 5ffa24
               nm_key_file_get_boolean(key_file,
Packit Service 5ffa24
                                       NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                                       NM_KEYFILE_KEY_NMMETA_EXTERNAL,
Packit Service 5ffa24
                                       NM_TERNARY_DEFAULT));
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_shadowed_storage,
Packit Service 5ffa24
               g_key_file_get_string(key_file,
Packit Service 5ffa24
                                     NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                                     NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE,
Packit Service 5ffa24
                                     NULL));
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_shadowed_owned,
Packit Service 5ffa24
               nm_key_file_get_boolean(key_file,
Packit Service 5ffa24
                                       NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                                       NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED,
Packit Service 5ffa24
                                       NM_TERNARY_DEFAULT));
Packit Service 5ffa24
Packit Service 5ffa24
    return connection;
Packit Service 5ffa24
}