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

Packit Service 5ffa24
/* SPDX-License-Identifier: GPL-2.0-or-later */
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Copyright (C) 2008 Novell, Inc.
Packit Service 5ffa24
 * Copyright (C) 2008 - 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-writer.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include <stdlib.h>
Packit Service 5ffa24
#include <sys/stat.h>
Packit Service 5ffa24
#include <unistd.h>
Packit Service 5ffa24
Packit Service dff8e4
#include "libnm-core-intern/nm-keyfile-internal.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nms-keyfile-utils.h"
Packit Service 5ffa24
#include "nms-keyfile-reader.h"
Packit Service 5ffa24
Packit Service dff8e4
#include "libnm-glib-aux/nm-io-utils.h"
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    const char *keyfile_dir;
Packit Service 5ffa24
} WriteInfo;
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
cert_writer(NMConnection *                    connection,
Packit Service 5ffa24
            GKeyFile *                        file,
Packit Service 5ffa24
            NMSetting8021x *                  setting,
Packit Service 5ffa24
            const NMSetting8021xSchemeVtable *vtable,
Packit Service 5ffa24
            WriteInfo *                       info,
Packit Service 5ffa24
            GError **                         error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    const char *           setting_name = nm_setting_get_name(NM_SETTING(setting));
Packit Service 5ffa24
    NMSetting8021xCKScheme scheme;
Packit Service 5ffa24
    NMSetting8021xCKFormat format;
Packit Service 5ffa24
    const char *           path = NULL, *ext = "pem";
Packit Service 5ffa24
Packit Service 5ffa24
    scheme = vtable->scheme_func(setting);
Packit Service 5ffa24
    if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
Packit Service 5ffa24
        char *      tmp           = NULL;
Packit Service 5ffa24
        const char *accepted_path = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        path = vtable->path_func(setting);
Packit Service 5ffa24
        g_assert(path);
Packit Service 5ffa24
Packit Service 5ffa24
        if (g_str_has_prefix(path, info->keyfile_dir)) {
Packit Service 5ffa24
            const char *p = path + strlen(info->keyfile_dir);
Packit Service 5ffa24
Packit Service 5ffa24
            /* If the path is rooted in the keyfile directory, just use a
Packit Service 5ffa24
             * relative path instead of an absolute one.
Packit Service 5ffa24
             */
Packit Service 5ffa24
            if (*p == '/') {
Packit Service 5ffa24
                while (*p == '/')
Packit Service 5ffa24
                    p++;
Packit Service 5ffa24
                if (p[0]) {
Packit Service 5ffa24
                    /* If @p looks like an integer list, the following detection will fail too and
Packit Service 5ffa24
                     * we will file:// qualify the path below. We thus avoid writing a path string
Packit Service 5ffa24
                     * that would be interpreted as legacy binary format by reader. */
Packit Service 5ffa24
                    tmp = nm_keyfile_detect_unqualified_path_scheme(info->keyfile_dir,
Packit Service 5ffa24
                                                                    p,
Packit Service 5ffa24
                                                                    -1,
Packit Service 5ffa24
                                                                    FALSE,
Packit Service 5ffa24
                                                                    NULL);
Packit Service 5ffa24
                    if (tmp) {
Packit Service 5ffa24
                        nm_clear_g_free(&tmp);
Packit Service 5ffa24
                        accepted_path = p;
Packit Service 5ffa24
                    }
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
        if (!accepted_path) {
Packit Service 5ffa24
            /* What we are about to write, must also be understood by the reader.
Packit Service 5ffa24
             * Otherwise, add a file:// prefix */
Packit Service 5ffa24
            tmp =
Packit Service 5ffa24
                nm_keyfile_detect_unqualified_path_scheme(info->keyfile_dir, path, -1, FALSE, NULL);
Packit Service 5ffa24
            if (tmp) {
Packit Service 5ffa24
                nm_clear_g_free(&tmp);
Packit Service 5ffa24
                accepted_path = path;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (!accepted_path)
Packit Service 5ffa24
            accepted_path = tmp = g_strconcat(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL);
Packit Service 5ffa24
        nm_keyfile_plugin_kf_set_string(file, setting_name, vtable->setting_key, accepted_path);
Packit Service 5ffa24
        g_free(tmp);
Packit Service 5ffa24
    } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
Packit Service 5ffa24
        nm_keyfile_plugin_kf_set_string(file,
Packit Service 5ffa24
                                        setting_name,
Packit Service 5ffa24
                                        vtable->setting_key,
Packit Service 5ffa24
                                        vtable->uri_func(setting));
Packit Service 5ffa24
    } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
Packit Service 5ffa24
        GBytes *      blob;
Packit Service 5ffa24
        const guint8 *blob_data;
Packit Service 5ffa24
        gsize         blob_len;
Packit Service 5ffa24
        gboolean      success;
Packit Service 5ffa24
        GError *      local = NULL;
Packit Service 5ffa24
        char *        new_path;
Packit Service 5ffa24
Packit Service 5ffa24
        blob = vtable->blob_func(setting);
Packit Service 5ffa24
        g_assert(blob);
Packit Service 5ffa24
        blob_data = g_bytes_get_data(blob, &blob_len);
Packit Service 5ffa24
Packit Service 5ffa24
        if (vtable->format_func) {
Packit Service 5ffa24
            /* Get the extension for a private key */
Packit Service 5ffa24
            format = vtable->format_func(setting);
Packit Service 5ffa24
            if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
Packit Service 5ffa24
                ext = "p12";
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            /* DER or PEM format certificate? */
Packit Service 5ffa24
            if (blob_len > 2 && blob_data[0] == 0x30 && blob_data[1] == 0x82)
Packit Service 5ffa24
                ext = "der";
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        /* Write the raw data out to the standard file so that we can use paths
Packit Service 5ffa24
         * from now on instead of pushing around the certificate data.
Packit Service 5ffa24
         */
Packit Service 5ffa24
        new_path = g_strdup_printf("%s/%s-%s.%s",
Packit Service 5ffa24
                                   info->keyfile_dir,
Packit Service 5ffa24
                                   nm_connection_get_uuid(connection),
Packit Service 5ffa24
                                   vtable->file_suffix,
Packit Service 5ffa24
                                   ext);
Packit Service 5ffa24
Packit Service 5ffa24
        /* FIXME(keyfile-parse-in-memory): writer must not access/write to the file system before
Packit Service 5ffa24
         * being sure that the entire profile can be written and all circumstances are good to
Packit Bot c44df3
         * proceed. That means, while writing we must only collect the blobs in-memory, and write
Packit Service 5ffa24
         * them all in the end together (or not at all). */
Packit Service 5ffa24
        success = nm_utils_file_set_contents(new_path,
Packit Service 5ffa24
                                             (const char *) blob_data,
Packit Service 5ffa24
                                             blob_len,
Packit Service 5ffa24
                                             0600,
Packit Service 5ffa24
                                             NULL,
Packit Bot c44df3
                                             NULL,
Packit Service 5ffa24
                                             &local);
Packit Service 5ffa24
        if (success) {
Packit Service 5ffa24
            /* Write the path value to the keyfile.
Packit Service 5ffa24
             * We know, that basename(new_path) starts with a UUID, hence no conflict with "data:;base64,"  */
Packit Service 5ffa24
            nm_keyfile_plugin_kf_set_string(file,
Packit Service 5ffa24
                                            setting_name,
Packit Service 5ffa24
                                            vtable->setting_key,
Packit Service 5ffa24
                                            strrchr(new_path, '/') + 1);
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            nm_log_warn(LOGD_SETTINGS,
Packit Service 5ffa24
                        "keyfile: %s.%s: failed to write certificate to file %s: %s",
Packit Service 5ffa24
                        setting_name,
Packit Service 5ffa24
                        vtable->setting_key,
Packit Service 5ffa24
                        new_path,
Packit Service 5ffa24
                        local->message);
Packit Service 5ffa24
            g_error_free(local);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        g_free(new_path);
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        /* scheme_func() returns UNKNOWN in all other cases. The only valid case
Packit Service 5ffa24
         * where a scheme is allowed to be UNKNOWN, is unsetting the value. In this
Packit Service 5ffa24
         * case, we don't expect the writer to be called, because the default value
Packit Service 5ffa24
         * will not be serialized.
Packit Service 5ffa24
         * The only other reason for the scheme to be UNKNOWN is an invalid cert.
Packit Service 5ffa24
         * But our connection verifies, so that cannot happen either. */
Packit Service 5ffa24
        g_return_if_reached();
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
_handler_write(NMConnection *        connection,
Packit Service 5ffa24
               GKeyFile *            keyfile,
Packit Service 5ffa24
               NMKeyfileHandlerType  type,
Packit Service 5ffa24
               NMKeyfileHandlerData *type_data,
Packit Service 5ffa24
               void *                user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if (type == NM_KEYFILE_HANDLER_TYPE_WRITE_CERT) {
Packit Service 5ffa24
        cert_writer(connection,
Packit Service 5ffa24
                    keyfile,
Packit Service 5ffa24
                    NM_SETTING_802_1X(type_data->cur_setting),
Packit Service 5ffa24
                    type_data->write_cert.vtable,
Packit Service 5ffa24
                    user_data,
Packit Service 5ffa24
                    type_data->p_error);
Packit Service 5ffa24
        return TRUE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return FALSE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
_internal_write_connection(NMConnection *                  connection,
Packit Service 5ffa24
                           gboolean                        is_nm_generated,
Packit Service 5ffa24
                           gboolean                        is_volatile,
Packit Service 5ffa24
                           gboolean                        is_external,
Packit Service 5ffa24
                           const char *                    shadowed_storage,
Packit Service 5ffa24
                           gboolean                        shadowed_owned,
Packit Service 5ffa24
                           const char *                    keyfile_dir,
Packit Service 5ffa24
                           const char *                    profile_dir,
Packit Service 5ffa24
                           gboolean                        with_extension,
Packit Service 5ffa24
                           uid_t                           owner_uid,
Packit Service 5ffa24
                           pid_t                           owner_grp,
Packit Service 5ffa24
                           const char *                    existing_path,
Packit Service 5ffa24
                           gboolean                        existing_path_read_only,
Packit Service 5ffa24
                           gboolean                        force_rename,
Packit Service 5ffa24
                           NMSKeyfileWriterAllowFilenameCb allow_filename_cb,
Packit Service 5ffa24
                           gpointer                        allow_filename_user_data,
Packit Service 5ffa24
                           char **                         out_path,
Packit Service 5ffa24
                           NMConnection **                 out_reread,
Packit Service 5ffa24
                           gboolean *                      out_reread_same,
Packit Service 5ffa24
                           GError **                       error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    nm_auto_unref_keyfile GKeyFile *kf_file        = NULL;
Packit Service 5ffa24
    gs_free char *                  kf_content_buf = NULL;
Packit Service 5ffa24
    gsize                           kf_content_len;
Packit Service 5ffa24
    gs_free char *                  path = NULL;
Packit Service 5ffa24
    const char *                    id;
Packit Service 5ffa24
    WriteInfo                       info = {0};
Packit Service 5ffa24
    gs_free_error GError *local_err      = NULL;
Packit Service 5ffa24
    int                   errsv;
Packit Service 5ffa24
    gboolean              rename;
Packit Service 5ffa24
    int                   i_path;
Packit Service 5ffa24
    gs_unref_object NMConnection *reread      = NULL;
Packit Service 5ffa24
    gboolean                      reread_same = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    g_return_val_if_fail(!out_path || !*out_path, FALSE);
Packit Service 5ffa24
    g_return_val_if_fail(keyfile_dir && keyfile_dir[0] == '/', FALSE);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(_nm_connection_verify(connection, NULL) == NM_SETTING_VERIFY_SUCCESS);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(!shadowed_owned || shadowed_storage);
Packit Service 5ffa24
Packit Service 5ffa24
    rename = force_rename || existing_path_read_only
Packit Service 5ffa24
             || (existing_path && !nm_utils_file_is_in_path(existing_path, keyfile_dir));
Packit Service 5ffa24
Packit Service 5ffa24
    id = nm_connection_get_id(connection);
Packit Service 5ffa24
    nm_assert(id && *id);
Packit Service 5ffa24
Packit Service 5ffa24
    info.keyfile_dir = keyfile_dir;
Packit Service 5ffa24
Packit Service 5ffa24
    kf_file =
Packit Service 5ffa24
        nm_keyfile_write(connection, NM_KEYFILE_HANDLER_FLAGS_NONE, _handler_write, &info, error);
Packit Service 5ffa24
    if (!kf_file)
Packit Service 5ffa24
        return FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    if (is_nm_generated) {
Packit Service 5ffa24
        g_key_file_set_boolean(kf_file,
Packit Service 5ffa24
                               NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                               NM_KEYFILE_KEY_NMMETA_NM_GENERATED,
Packit Service 5ffa24
                               TRUE);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (is_volatile) {
Packit Service 5ffa24
        g_key_file_set_boolean(kf_file,
Packit Service 5ffa24
                               NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                               NM_KEYFILE_KEY_NMMETA_VOLATILE,
Packit Service 5ffa24
                               TRUE);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (is_external) {
Packit Service 5ffa24
        g_key_file_set_boolean(kf_file,
Packit Service 5ffa24
                               NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                               NM_KEYFILE_KEY_NMMETA_EXTERNAL,
Packit Service 5ffa24
                               TRUE);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (shadowed_storage) {
Packit Service 5ffa24
        g_key_file_set_string(kf_file,
Packit Service 5ffa24
                              NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                              NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE,
Packit Service 5ffa24
                              shadowed_storage);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (shadowed_owned) {
Packit Service 5ffa24
        g_key_file_set_boolean(kf_file,
Packit Service 5ffa24
                               NM_KEYFILE_GROUP_NMMETA,
Packit Service 5ffa24
                               NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED,
Packit Service 5ffa24
                               TRUE);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    kf_content_buf = g_key_file_to_data(kf_file, &kf_content_len, error);
Packit Service 5ffa24
    if (!kf_content_buf)
Packit Service 5ffa24
        return FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!g_file_test(keyfile_dir, G_FILE_TEST_IS_DIR))
Packit Service 5ffa24
        (void) g_mkdir_with_parents(keyfile_dir, 0755);
Packit Service 5ffa24
Packit Service 5ffa24
    for (i_path = -2; i_path < 10000; i_path++) {
Packit Service 5ffa24
        gs_free char *path_candidate = NULL;
Packit Service 5ffa24
        gboolean      is_existing_path;
Packit Service 5ffa24
Packit Service 5ffa24
        if (i_path == -2) {
Packit Service 5ffa24
            if (!existing_path || rename)
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            path_candidate = g_strdup(existing_path);
Packit Service 5ffa24
        } else if (i_path == -1) {
Packit Service 5ffa24
            gs_free char *filename_escaped = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
            filename_escaped = nm_keyfile_utils_create_filename(id, with_extension);
Packit Service 5ffa24
            path_candidate   = g_build_filename(keyfile_dir, filename_escaped, NULL);
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            gs_free char *filename_escaped = NULL;
Packit Service 5ffa24
            gs_free char *filename         = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
            if (i_path == 0)
Packit Service 5ffa24
                filename = g_strdup_printf("%s-%s", id, nm_connection_get_uuid(connection));
Packit Service 5ffa24
            else
Packit Service 5ffa24
                filename =
Packit Service 5ffa24
                    g_strdup_printf("%s-%s-%d", id, nm_connection_get_uuid(connection), i_path);
Packit Service 5ffa24
Packit Service 5ffa24
            filename_escaped = nm_keyfile_utils_create_filename(filename, with_extension);
Packit Service 5ffa24
Packit Service 5ffa24
            path_candidate = g_strdup_printf("%s/%s", keyfile_dir, filename_escaped);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        is_existing_path = existing_path && nm_streq(existing_path, path_candidate);
Packit Service 5ffa24
Packit Service 5ffa24
        if (is_existing_path && rename)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (allow_filename_cb && !allow_filename_cb(path_candidate, allow_filename_user_data))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!is_existing_path) {
Packit Service 5ffa24
            if (g_file_test(path_candidate, G_FILE_TEST_EXISTS))
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        path = g_steal_pointer(&path_candidate);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!path) {
Packit Service 5ffa24
        gs_free char *ss = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        /* this really should not happen, we tried hard to find an unused name... bail out. */
Packit Service 5ffa24
        g_set_error(error,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR_FAILED,
Packit Service 5ffa24
                    "could not find suitable keyfile file name (%s already used)",
Packit Service 5ffa24
                    ss = ({
Packit Service 5ffa24
                        gs_free char *filename_escaped = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
                        filename_escaped = nm_keyfile_utils_create_filename(id, with_extension);
Packit Service 5ffa24
                        g_build_filename(keyfile_dir, filename_escaped, NULL);
Packit Service 5ffa24
                    }));
Packit Service 5ffa24
Packit Service 5ffa24
        return FALSE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (out_reread || out_reread_same) {
Packit Service 5ffa24
        gs_free_error GError *reread_error = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        reread =
Packit Service 5ffa24
            nms_keyfile_reader_from_keyfile(kf_file, path, NULL, profile_dir, FALSE, &reread_error);
Packit Service 5ffa24
Packit Service 5ffa24
        if (!reread || !nm_connection_normalize(reread, NULL, NULL, &reread_error)) {
Packit Service 5ffa24
            nm_log_err(
Packit Service 5ffa24
                LOGD_SETTINGS,
Packit Service 5ffa24
                "BUG: the profile cannot be stored in keyfile format without becoming unusable: %s",
Packit Service 5ffa24
                reread_error->message);
Packit Service 5ffa24
            g_set_error(error,
Packit Service 5ffa24
                        NM_SETTINGS_ERROR,
Packit Service 5ffa24
                        NM_SETTINGS_ERROR_FAILED,
Packit Service 5ffa24
                        "keyfile writer produces an invalid connection: %s",
Packit Service 5ffa24
                        reread_error->message);
Packit Service 5ffa24
            nm_assert_not_reached();
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (out_reread_same) {
Packit Service 5ffa24
            reread_same =
Packit Service 5ffa24
                !!nm_connection_compare(reread, connection, NM_SETTING_COMPARE_FLAG_EXACT);
Packit Service 5ffa24
Packit Service 5ffa24
            nm_assert(reread_same
Packit Service 5ffa24
                      == nm_connection_compare(connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
Packit Service 5ffa24
            nm_assert(reread_same == ({
Packit Service 5ffa24
                          gs_unref_hashtable GHashTable *_settings = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
                          (nm_connection_diff(reread,
Packit Service 5ffa24
                                              connection,
Packit Service 5ffa24
                                              NM_SETTING_COMPARE_FLAG_EXACT,
Packit Service 5ffa24
                                              &_settings)
Packit Service 5ffa24
                           && !_settings);
Packit Service 5ffa24
                      }));
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Bot c44df3
    nm_utils_file_set_contents(path, kf_content_buf, kf_content_len, 0600, NULL, NULL, &local_err);
Packit Service 5ffa24
    if (local_err) {
Packit Service 5ffa24
        g_set_error(error,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR_FAILED,
Packit Service 5ffa24
                    "error writing to file '%s': %s",
Packit Service 5ffa24
                    path,
Packit Service 5ffa24
                    local_err->message);
Packit Service 5ffa24
        return FALSE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (chown(path, owner_uid, owner_grp) < 0) {
Packit Service 5ffa24
        errsv = errno;
Packit Service 5ffa24
        g_set_error(error,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR,
Packit Service 5ffa24
                    NM_SETTINGS_ERROR_FAILED,
Packit Service 5ffa24
                    "error chowning '%s': %s (%d)",
Packit Service 5ffa24
                    path,
Packit Service 5ffa24
                    nm_strerror_native(errsv),
Packit Service 5ffa24
                    errsv);
Packit Service 5ffa24
        unlink(path);
Packit Service 5ffa24
        return FALSE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* In case of updating the connection and changing the file path,
Packit Service 5ffa24
     * we need to remove the old one, not to end up with two connections.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (existing_path && !existing_path_read_only && !nm_streq(path, existing_path))
Packit Service 5ffa24
        unlink(existing_path);
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_reread, g_steal_pointer(&reread));
Packit Service 5ffa24
    NM_SET_OUT(out_reread_same, reread_same);
Packit Service 5ffa24
    NM_SET_OUT(out_path, g_steal_pointer(&path));
Packit Service 5ffa24
Packit Service 5ffa24
    return TRUE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
gboolean
Packit Service 5ffa24
nms_keyfile_writer_connection(NMConnection *                  connection,
Packit Service 5ffa24
                              gboolean                        is_nm_generated,
Packit Service 5ffa24
                              gboolean                        is_volatile,
Packit Service 5ffa24
                              gboolean                        is_external,
Packit Service 5ffa24
                              const char *                    shadowed_storage,
Packit Service 5ffa24
                              gboolean                        shadowed_owned,
Packit Service 5ffa24
                              const char *                    keyfile_dir,
Packit Service 5ffa24
                              const char *                    profile_dir,
Packit Service 5ffa24
                              const char *                    existing_path,
Packit Service 5ffa24
                              gboolean                        existing_path_read_only,
Packit Service 5ffa24
                              gboolean                        force_rename,
Packit Service 5ffa24
                              NMSKeyfileWriterAllowFilenameCb allow_filename_cb,
Packit Service 5ffa24
                              gpointer                        allow_filename_user_data,
Packit Service 5ffa24
                              char **                         out_path,
Packit Service 5ffa24
                              NMConnection **                 out_reread,
Packit Service 5ffa24
                              gboolean *                      out_reread_same,
Packit Service 5ffa24
                              GError **                       error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return _internal_write_connection(connection,
Packit Service 5ffa24
                                      is_nm_generated,
Packit Service 5ffa24
                                      is_volatile,
Packit Service 5ffa24
                                      is_external,
Packit Service 5ffa24
                                      shadowed_storage,
Packit Service 5ffa24
                                      shadowed_owned,
Packit Service 5ffa24
                                      keyfile_dir,
Packit Service 5ffa24
                                      profile_dir,
Packit Service 5ffa24
                                      TRUE,
Packit Service 5ffa24
                                      0,
Packit Service 5ffa24
                                      0,
Packit Service 5ffa24
                                      existing_path,
Packit Service 5ffa24
                                      existing_path_read_only,
Packit Service 5ffa24
                                      force_rename,
Packit Service 5ffa24
                                      allow_filename_cb,
Packit Service 5ffa24
                                      allow_filename_user_data,
Packit Service 5ffa24
                                      out_path,
Packit Service 5ffa24
                                      out_reread,
Packit Service 5ffa24
                                      out_reread_same,
Packit Service 5ffa24
                                      error);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
gboolean
Packit Service 5ffa24
nms_keyfile_writer_test_connection(NMConnection * connection,
Packit Service 5ffa24
                                   const char *   keyfile_dir,
Packit Service 5ffa24
                                   uid_t          owner_uid,
Packit Service 5ffa24
                                   pid_t          owner_grp,
Packit Service 5ffa24
                                   char **        out_path,
Packit Service 5ffa24
                                   NMConnection **out_reread,
Packit Service 5ffa24
                                   gboolean *     out_reread_same,
Packit Service 5ffa24
                                   GError **      error)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return _internal_write_connection(connection,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      NULL,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      keyfile_dir,
Packit Service 5ffa24
                                      keyfile_dir,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      owner_uid,
Packit Service 5ffa24
                                      owner_grp,
Packit Service 5ffa24
                                      NULL,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      FALSE,
Packit Service 5ffa24
                                      NULL,
Packit Service 5ffa24
                                      NULL,
Packit Service 5ffa24
                                      out_path,
Packit Service 5ffa24
                                      out_reread,
Packit Service 5ffa24
                                      out_reread_same,
Packit Service 5ffa24
                                      error);
Packit Service 5ffa24
}