mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-21 06:20:06 +01:00
keyfile: merge branch 'th/libnm-keyfile-bgo744699'
Move basic keyfile functionality from settings plugin to libnm-core. This is a first step to have a semi-standard way to stringify connections back and forth, which is also available to libnm users. Still the new functions are internal API (nm-keyfile-internal.h). Let's decide later how the public API should really look like. https://bugzilla.gnome.org/show_bug.cgi?id=744699
This commit is contained in:
commit
59eb5312a5
41 changed files with 4336 additions and 2620 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -143,6 +143,7 @@ valgrind-*.log
|
||||||
/libnm-core/tests/test-crypto
|
/libnm-core/tests/test-crypto
|
||||||
/libnm-core/tests/test-settings-defaults
|
/libnm-core/tests/test-settings-defaults
|
||||||
/libnm-core/tests/test-general
|
/libnm-core/tests/test-general
|
||||||
|
/libnm-core/tests/test-keyfile
|
||||||
/libnm-core/tests/test-need-secrets
|
/libnm-core/tests/test-need-secrets
|
||||||
/libnm-core/tests/test-secrets
|
/libnm-core/tests/test-secrets
|
||||||
/libnm-core/tests/test-setting-8021x
|
/libnm-core/tests/test-setting-8021x
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "nm-glib-compat.h"
|
#include "nm-glib-compat.h"
|
||||||
|
#include "nm-utils-internal.h"
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static char *wep_key_type_to_string (NMWepKeyType type);
|
static char *wep_key_type_to_string (NMWepKeyType type);
|
||||||
|
|
@ -2691,13 +2692,12 @@ nmc_property_connection_describe_secondaries (NMSetting *setting, const char *pr
|
||||||
static gboolean \
|
static gboolean \
|
||||||
def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
|
def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
|
||||||
{ \
|
{ \
|
||||||
const char *SCHEME_PATH = "file://"; \
|
|
||||||
char *val_strip = g_strstrip (g_strdup (val)); \
|
char *val_strip = g_strstrip (g_strdup (val)); \
|
||||||
char *p = val_strip; \
|
char *p = val_strip; \
|
||||||
gboolean success; \
|
gboolean success; \
|
||||||
\
|
\
|
||||||
if (strncmp (val_strip, SCHEME_PATH, strlen (SCHEME_PATH)) == 0) \
|
if (strncmp (val_strip, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0) \
|
||||||
p += strlen (SCHEME_PATH); \
|
p += STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); \
|
||||||
\
|
\
|
||||||
success = set_func (NM_SETTING_802_1X (setting), \
|
success = set_func (NM_SETTING_802_1X (setting), \
|
||||||
p, \
|
p, \
|
||||||
|
|
@ -2713,14 +2713,13 @@ nmc_property_connection_describe_secondaries (NMSetting *setting, const char *pr
|
||||||
def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
|
def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
|
||||||
{ \
|
{ \
|
||||||
char **strv = NULL; \
|
char **strv = NULL; \
|
||||||
const char *SCHEME_PATH = "file://"; \
|
|
||||||
char *val_strip = g_strstrip (g_strdup (val)); \
|
char *val_strip = g_strstrip (g_strdup (val)); \
|
||||||
char *p = val_strip; \
|
char *p = val_strip; \
|
||||||
const char *path, *password; \
|
const char *path, *password; \
|
||||||
gboolean success; \
|
gboolean success; \
|
||||||
\
|
\
|
||||||
if (strncmp (val_strip, SCHEME_PATH, strlen (SCHEME_PATH)) == 0) \
|
if (strncmp (val_strip, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0) \
|
||||||
p += strlen (SCHEME_PATH); \
|
p += STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); \
|
||||||
\
|
\
|
||||||
strv = nmc_strsplit_set (p, " \t,", 2); \
|
strv = nmc_strsplit_set (p, " \t,", 2); \
|
||||||
path = strv[0]; \
|
path = strv[0]; \
|
||||||
|
|
|
||||||
|
|
@ -576,6 +576,39 @@ __nmtst_spawn_sync (const char *working_directory, char **standard_out, char **s
|
||||||
|
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
|
|
||||||
|
inline static char *
|
||||||
|
nmtst_file_resolve_relative_path (const char *rel, const char *cwd)
|
||||||
|
{
|
||||||
|
gs_free char *cwd_free = NULL;
|
||||||
|
|
||||||
|
g_assert (rel && *rel);
|
||||||
|
|
||||||
|
if (g_path_is_absolute (rel))
|
||||||
|
return g_strdup (rel);
|
||||||
|
|
||||||
|
if (!cwd)
|
||||||
|
cwd = cwd_free = g_get_current_dir ();
|
||||||
|
return g_build_filename (cwd, rel, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void
|
||||||
|
_nmtst_assert_resolve_relative_path_equals (const char *f1, const char *f2, const char *file, int line)
|
||||||
|
{
|
||||||
|
gs_free char *p1 = NULL, *p2 = NULL;
|
||||||
|
|
||||||
|
p1 = nmtst_file_resolve_relative_path (f1, NULL);
|
||||||
|
p2 = nmtst_file_resolve_relative_path (f2, NULL);
|
||||||
|
g_assert (p1 && *p1);
|
||||||
|
|
||||||
|
/* Fixme: later we might need to coalesce repeated '/', "./", and "../".
|
||||||
|
* For now, it's good enough. */
|
||||||
|
if (g_strcmp0 (p1, p2) != 0)
|
||||||
|
g_error ("%s:%d : filenames don't match \"%s\" vs. \"%s\" // \"%s\" - \"%s\"", file, line, f1, f2, p1, p2);
|
||||||
|
}
|
||||||
|
#define nmtst_assert_resolve_relative_path_equals(f1, f2) _nmtst_assert_resolve_relative_path_equals (f1, f2, __FILE__, __LINE__);
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
#ifdef __NETWORKMANAGER_PLATFORM_H__
|
#ifdef __NETWORKMANAGER_PLATFORM_H__
|
||||||
|
|
||||||
inline static NMPlatformIP6Address *
|
inline static NMPlatformIP6Address *
|
||||||
|
|
@ -1028,6 +1061,36 @@ nmtst_assert_hwaddr_equals (gconstpointer hwaddr1, gssize hwaddr1_len, const cha
|
||||||
nmtst_assert_hwaddr_equals (hwaddr1, hwaddr1_len, expected, G_STRLOC)
|
nmtst_assert_hwaddr_equals (hwaddr1, hwaddr1_len, expected, G_STRLOC)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__) && defined(__NM_KEYFILE_INTERNAL_H__)
|
||||||
|
|
||||||
|
inline static NMConnection *
|
||||||
|
nmtst_create_connection_from_keyfile (const char *keyfile_str, const char *keyfile_name, const char *base_dir)
|
||||||
|
{
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean success;
|
||||||
|
NMConnection *con;
|
||||||
|
|
||||||
|
g_assert (keyfile_str);
|
||||||
|
|
||||||
|
keyfile = g_key_file_new ();
|
||||||
|
success = g_key_file_load_from_data (keyfile, keyfile_str, strlen (keyfile_str), G_KEY_FILE_NONE, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
|
||||||
|
con = nm_keyfile_read (keyfile, keyfile_name, base_dir, NULL, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (NM_IS_CONNECTION (con));
|
||||||
|
|
||||||
|
g_key_file_unref (keyfile);
|
||||||
|
|
||||||
|
nmtst_connection_normalize (con);
|
||||||
|
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __NM_CONNECTION_H__
|
#ifdef __NM_CONNECTION_H__
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ libnm_core_private_headers = \
|
||||||
$(core)/crypto.h \
|
$(core)/crypto.h \
|
||||||
$(core)/nm-connection-private.h \
|
$(core)/nm-connection-private.h \
|
||||||
$(core)/nm-core-internal.h \
|
$(core)/nm-core-internal.h \
|
||||||
|
$(core)/nm-keyfile-internal.h \
|
||||||
|
$(core)/nm-keyfile-utils.h \
|
||||||
$(core)/nm-property-compare.h \
|
$(core)/nm-property-compare.h \
|
||||||
$(core)/nm-setting-private.h \
|
$(core)/nm-setting-private.h \
|
||||||
$(core)/nm-utils-private.h
|
$(core)/nm-utils-private.h
|
||||||
|
|
@ -57,6 +59,9 @@ libnm_core_sources = \
|
||||||
$(core)/crypto.c \
|
$(core)/crypto.c \
|
||||||
$(core)/nm-connection.c \
|
$(core)/nm-connection.c \
|
||||||
$(core)/nm-errors.c \
|
$(core)/nm-errors.c \
|
||||||
|
$(core)/nm-keyfile-reader.c \
|
||||||
|
$(core)/nm-keyfile-utils.c \
|
||||||
|
$(core)/nm-keyfile-writer.c \
|
||||||
$(core)/nm-property-compare.c \
|
$(core)/nm-property-compare.c \
|
||||||
$(core)/nm-setting-8021x.c \
|
$(core)/nm-setting-8021x.c \
|
||||||
$(core)/nm-setting-adsl.c \
|
$(core)/nm-setting-adsl.c \
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,10 @@ char ** _nm_utils_strsplit_set (const char *str,
|
||||||
|
|
||||||
char *nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, gpointer type_args);
|
char *nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, gpointer type_args);
|
||||||
|
|
||||||
|
#define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905"
|
||||||
|
|
||||||
|
char *_nm_utils_uuid_generate_from_strings (const char *string1, ...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
void _nm_dbus_errors_init (void);
|
void _nm_dbus_errors_init (void);
|
||||||
|
|
||||||
extern gboolean _nm_utils_is_manager_process;
|
extern gboolean _nm_utils_is_manager_process;
|
||||||
|
|
@ -132,4 +136,6 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data,
|
||||||
char **out_password,
|
char **out_password,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
166
libnm-core/nm-keyfile-internal.h
Normal file
166
libnm-core/nm-keyfile-internal.h
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* NetworkManager system settings service - keyfile plugin
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Novell, Inc.
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NM_KEYFILE_INTERNAL_H__
|
||||||
|
#define __NM_KEYFILE_INTERNAL_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "nm-connection.h"
|
||||||
|
#include "nm-setting-8021x.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
#define NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB "data:;base64,"
|
||||||
|
#define NM_KEYFILE_CERT_SCHEME_PREFIX_PATH "file://"
|
||||||
|
|
||||||
|
char *nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
|
||||||
|
gconstpointer pdata,
|
||||||
|
gsize data_len,
|
||||||
|
gboolean consider_exists,
|
||||||
|
gboolean *out_exists);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NM_KEYFILE_READ_TYPE_WARN = 1,
|
||||||
|
} NMKeyfileReadType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NMKeyfileReadHandler:
|
||||||
|
*
|
||||||
|
* Hook to nm_keyfile_read(). The user might fail the reading by setting
|
||||||
|
* @error.
|
||||||
|
*
|
||||||
|
* Returns: should return TRUE, if the reading was handled. Otherwise,
|
||||||
|
* a default action will be performed that depends on the @type.
|
||||||
|
* For %NM_KEYFILE_READ_TYPE_WARN type, the default action is doing nothing.
|
||||||
|
*/
|
||||||
|
typedef gboolean (*NMKeyfileReadHandler) (GKeyFile *keyfile,
|
||||||
|
NMConnection *connection,
|
||||||
|
NMKeyfileReadType type,
|
||||||
|
void *type_data,
|
||||||
|
void *user_data,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NM_KEYFILE_WARN_SEVERITY_DEBUG = 1000,
|
||||||
|
NM_KEYFILE_WARN_SEVERITY_INFO = 2000,
|
||||||
|
NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE = 2901,
|
||||||
|
NM_KEYFILE_WARN_SEVERITY_WARN = 3000,
|
||||||
|
} NMKeyfileWarnSeverity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NMKeyfileReadTypeDataWarn:
|
||||||
|
*
|
||||||
|
* this struct is passed as @type_data for the @NMKeyfileReadHandler of
|
||||||
|
* type %NM_KEYFILE_READ_TYPE_WARN.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/* might be %NULL, if the warning is not about a group. */
|
||||||
|
const char *group;
|
||||||
|
|
||||||
|
/* might be %NULL, if the warning is not about a setting. */
|
||||||
|
NMSetting *setting;
|
||||||
|
|
||||||
|
/* might be %NULL, if the warning is not about a property. */
|
||||||
|
const char *property_name;
|
||||||
|
|
||||||
|
NMKeyfileWarnSeverity severity;
|
||||||
|
const char *message;
|
||||||
|
} NMKeyfileReadTypeDataWarn;
|
||||||
|
|
||||||
|
|
||||||
|
NMConnection *nm_keyfile_read (GKeyFile *keyfile,
|
||||||
|
const char *keyfile_name,
|
||||||
|
const char *base_dir,
|
||||||
|
NMKeyfileReadHandler handler,
|
||||||
|
void *user_data,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NM_KEYFILE_WRITE_TYPE_CERT = 1,
|
||||||
|
} NMKeyfileWriteType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NMKeyfileWriteHandler:
|
||||||
|
*
|
||||||
|
* This is a hook to tweak the serialization.
|
||||||
|
*
|
||||||
|
* Handler for certain properties or events that are not entirely contained
|
||||||
|
* within the keyfile or that might be serialized differently. The @type and
|
||||||
|
* @type_data arguments tell which kind of argument we have at hand.
|
||||||
|
*
|
||||||
|
* Currently only the type %NM_KEYFILE_WRITE_TYPE_CERT is supported, which provides
|
||||||
|
* @type_data as %NMKeyfileWriteTypeDataCert. However, this handler should be generic enough
|
||||||
|
* to support other types as well.
|
||||||
|
*
|
||||||
|
* This don't have to be only "properties". For example, nm_keyfile_read() uses
|
||||||
|
* a similar handler to push warnings to the caller.
|
||||||
|
*
|
||||||
|
* If the handler raises an error, it should set the @error value. This causes
|
||||||
|
* the an overall failure.
|
||||||
|
*
|
||||||
|
* Returns: whether the issue was handled. If the type was unhandled,
|
||||||
|
* a default action will be performed. This might be raise an error,
|
||||||
|
* do some fallback parsing, or do nothing.
|
||||||
|
*/
|
||||||
|
typedef gboolean (*NMKeyfileWriteHandler) (NMConnection *connection,
|
||||||
|
GKeyFile *keyfile,
|
||||||
|
NMKeyfileWriteType type,
|
||||||
|
void *type_data,
|
||||||
|
void *user_data,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NMKeyfileWriteTypeDataCert:
|
||||||
|
*
|
||||||
|
* this struct is passed as @type_data for the @NMKeyfileWriteHandler of
|
||||||
|
* type %NM_KEYFILE_WRITE_TYPE_CERT.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
NMSetting8021x *setting;
|
||||||
|
const char *property_name;
|
||||||
|
|
||||||
|
/* The following functions are helpers that simplify the implementation
|
||||||
|
* of the handler. */
|
||||||
|
const char *suffix;
|
||||||
|
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
|
||||||
|
NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
|
||||||
|
const char * (*path_func) (NMSetting8021x *setting);
|
||||||
|
GBytes * (*blob_func) (NMSetting8021x *setting);
|
||||||
|
} NMKeyfileWriteTypeDataCert;
|
||||||
|
|
||||||
|
|
||||||
|
GKeyFile *nm_keyfile_write (NMConnection *connection,
|
||||||
|
NMKeyfileWriteHandler handler,
|
||||||
|
void *user_data,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
char *nm_keyfile_plugin_kf_get_string (GKeyFile *kf, const char *group, const char *key, GError **error);
|
||||||
|
void nm_keyfile_plugin_kf_set_string (GKeyFile *kf, const char *group, const char *key, const char *value);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __NM_KEYFILE_INTERNAL_H__ */
|
||||||
1656
libnm-core/nm-keyfile-reader.c
Normal file
1656
libnm-core/nm-keyfile-reader.c
Normal file
File diff suppressed because it is too large
Load diff
207
libnm-core/nm-keyfile-utils.c
Normal file
207
libnm-core/nm-keyfile-utils.c
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* NetworkManager system settings service
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* (C) Copyright 2010 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "nm-keyfile-utils.h"
|
||||||
|
#include "nm-keyfile-internal.h"
|
||||||
|
#include "nm-setting-wired.h"
|
||||||
|
#include "nm-setting-wireless.h"
|
||||||
|
#include "nm-setting-wireless-security.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *setting;
|
||||||
|
const char *alias;
|
||||||
|
} SettingAlias;
|
||||||
|
|
||||||
|
static const SettingAlias alias_list[] = {
|
||||||
|
{ NM_SETTING_WIRED_SETTING_NAME, "ethernet" },
|
||||||
|
{ NM_SETTING_WIRELESS_SETTING_NAME, "wifi" },
|
||||||
|
{ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-security" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (setting_name != NULL, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (alias_list); i++) {
|
||||||
|
if (strcmp (setting_name, alias_list[i].setting) == 0)
|
||||||
|
return alias_list[i].alias;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_keyfile_plugin_get_setting_name_for_alias (const char *alias)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (alias != NULL, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (alias_list); i++) {
|
||||||
|
if (strcmp (alias, alias_list[i].alias) == 0)
|
||||||
|
return alias_list[i].setting;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/* List helpers */
|
||||||
|
#define DEFINE_KF_LIST_WRAPPER(stype, get_ctype, set_ctype) \
|
||||||
|
get_ctype \
|
||||||
|
nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
gsize *out_length, \
|
||||||
|
GError **error) \
|
||||||
|
{ \
|
||||||
|
get_ctype list; \
|
||||||
|
const char *alias; \
|
||||||
|
GError *local = NULL; \
|
||||||
|
\
|
||||||
|
list = g_key_file_get_##stype##_list (kf, group, key, out_length, &local); \
|
||||||
|
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
||||||
|
if (alias) { \
|
||||||
|
g_clear_error (&local); \
|
||||||
|
list = g_key_file_get_##stype##_list (kf, alias, key, out_length, &local); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (local) \
|
||||||
|
g_propagate_error (error, local); \
|
||||||
|
return list; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void \
|
||||||
|
nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
set_ctype list[], \
|
||||||
|
gsize length) \
|
||||||
|
{ \
|
||||||
|
const char *alias; \
|
||||||
|
\
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
||||||
|
g_key_file_set_##stype##_list (kf, alias ? alias : group, key, list, length); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_KF_LIST_WRAPPER(integer, gint*, gint);
|
||||||
|
DEFINE_KF_LIST_WRAPPER(string, gchar **, const gchar* const);
|
||||||
|
|
||||||
|
/* Single value helpers */
|
||||||
|
#define DEFINE_KF_WRAPPER(stype, get_ctype, set_ctype) \
|
||||||
|
get_ctype \
|
||||||
|
nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
GError **error) \
|
||||||
|
{ \
|
||||||
|
get_ctype val; \
|
||||||
|
const char *alias; \
|
||||||
|
GError *local = NULL; \
|
||||||
|
\
|
||||||
|
val = g_key_file_get_##stype (kf, group, key, &local); \
|
||||||
|
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
||||||
|
if (alias) { \
|
||||||
|
g_clear_error (&local); \
|
||||||
|
val = g_key_file_get_##stype (kf, alias, key, &local); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (local) \
|
||||||
|
g_propagate_error (error, local); \
|
||||||
|
return val; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void \
|
||||||
|
nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
set_ctype value) \
|
||||||
|
{ \
|
||||||
|
const char *alias; \
|
||||||
|
\
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
||||||
|
g_key_file_set_##stype (kf, alias ? alias : group, key, value); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_KF_WRAPPER(string, gchar*, const gchar*);
|
||||||
|
DEFINE_KF_WRAPPER(integer, gint, gint);
|
||||||
|
DEFINE_KF_WRAPPER(uint64, guint64, guint64);
|
||||||
|
DEFINE_KF_WRAPPER(boolean, gboolean, gboolean);
|
||||||
|
DEFINE_KF_WRAPPER(value, gchar*, const gchar*);
|
||||||
|
|
||||||
|
|
||||||
|
gchar **
|
||||||
|
nm_keyfile_plugin_kf_get_keys (GKeyFile *kf,
|
||||||
|
const char *group,
|
||||||
|
gsize *out_length,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gchar **keys;
|
||||||
|
const char *alias;
|
||||||
|
GError *local = NULL;
|
||||||
|
|
||||||
|
keys = g_key_file_get_keys (kf, group, out_length, &local);
|
||||||
|
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (group);
|
||||||
|
if (alias) {
|
||||||
|
g_clear_error (&local);
|
||||||
|
keys = g_key_file_get_keys (kf, alias, out_length, &local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (local)
|
||||||
|
g_propagate_error (error, local);
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_keyfile_plugin_kf_has_key (GKeyFile *kf,
|
||||||
|
const char *group,
|
||||||
|
const char *key,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean has;
|
||||||
|
const char *alias;
|
||||||
|
GError *local = NULL;
|
||||||
|
|
||||||
|
has = g_key_file_has_key (kf, group, key, &local);
|
||||||
|
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (group);
|
||||||
|
if (alias) {
|
||||||
|
g_clear_error (&local);
|
||||||
|
has = g_key_file_has_key (kf, alias, key, &local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (local)
|
||||||
|
g_propagate_error (error, local);
|
||||||
|
return has;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
79
libnm-core/nm-keyfile-utils.h
Normal file
79
libnm-core/nm-keyfile-utils.h
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* NetworkManager system settings service
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* (C) Copyright 2010-2015 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NM_KEYFILE_UTILS_H__
|
||||||
|
#define __NM_KEYFILE_UTILS_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#define VPN_SECRETS_GROUP "vpn-secrets"
|
||||||
|
|
||||||
|
const char *nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name);
|
||||||
|
|
||||||
|
const char *nm_keyfile_plugin_get_setting_name_for_alias (const char *alias);
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
/* List helpers */
|
||||||
|
#define DEFINE_KF_LIST_WRAPPER_PROTO(stype, get_ctype, set_ctype) \
|
||||||
|
get_ctype nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
gsize *out_length, \
|
||||||
|
GError **error); \
|
||||||
|
\
|
||||||
|
void nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
set_ctype list[], \
|
||||||
|
gsize length);
|
||||||
|
DEFINE_KF_LIST_WRAPPER_PROTO(integer, gint*, gint)
|
||||||
|
DEFINE_KF_LIST_WRAPPER_PROTO(string, gchar**, const gchar* const)
|
||||||
|
|
||||||
|
/* Single-value helpers */
|
||||||
|
#define DEFINE_KF_WRAPPER_PROTO(stype, get_ctype, set_ctype) \
|
||||||
|
get_ctype nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
GError **error); \
|
||||||
|
\
|
||||||
|
void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
|
||||||
|
const char *group, \
|
||||||
|
const char *key, \
|
||||||
|
set_ctype value);
|
||||||
|
DEFINE_KF_WRAPPER_PROTO(string, gchar*, const gchar*)
|
||||||
|
DEFINE_KF_WRAPPER_PROTO(integer, gint, gint)
|
||||||
|
DEFINE_KF_WRAPPER_PROTO(uint64, guint64, guint64)
|
||||||
|
DEFINE_KF_WRAPPER_PROTO(boolean, gboolean, gboolean)
|
||||||
|
DEFINE_KF_WRAPPER_PROTO(value, gchar*, const gchar*)
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
|
gchar ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf,
|
||||||
|
const char *group,
|
||||||
|
gsize *out_length,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean nm_keyfile_plugin_kf_has_key (GKeyFile *kf,
|
||||||
|
const char *group,
|
||||||
|
const char *key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
#endif /* __NM_KEYFILE_UTILS_H__ */
|
||||||
|
|
||||||
751
libnm-core/nm-keyfile-writer.c
Normal file
751
libnm-core/nm-keyfile-writer.c
Normal file
|
|
@ -0,0 +1,751 @@
|
||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* NetworkManager system settings service - keyfile plugin
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 - 2015 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
|
#include "nm-setting.h"
|
||||||
|
#include "nm-setting-connection.h"
|
||||||
|
#include "nm-setting-ip4-config.h"
|
||||||
|
#include "nm-setting-ip6-config.h"
|
||||||
|
#include "nm-setting-vpn.h"
|
||||||
|
#include "nm-setting-wired.h"
|
||||||
|
#include "nm-setting-wireless.h"
|
||||||
|
#include "nm-setting-ip4-config.h"
|
||||||
|
#include "nm-setting-bluetooth.h"
|
||||||
|
#include "nm-setting-8021x.h"
|
||||||
|
#include "nm-utils.h"
|
||||||
|
|
||||||
|
#include "gsystem-local-alloc.h"
|
||||||
|
#include "nm-glib-compat.h"
|
||||||
|
#include "nm-keyfile-internal.h"
|
||||||
|
#include "nm-keyfile-utils.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMConnection *connection;
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
GError *error;
|
||||||
|
NMKeyfileWriteHandler handler;
|
||||||
|
void *user_data;
|
||||||
|
} KeyfileWriterInfo;
|
||||||
|
|
||||||
|
|
||||||
|
/* Some setting properties also contain setting names, such as
|
||||||
|
* NMSettingConnection's 'type' property (which specifies the base type of the
|
||||||
|
* connection, eg ethernet or wifi) or the 802-11-wireless setting's
|
||||||
|
* 'security' property which specifies whether or not the AP requires
|
||||||
|
* encrpytion. This function handles translating those properties' values
|
||||||
|
* from the real setting name to the more-readable alias.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
setting_alias_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
const char *str, *alias;
|
||||||
|
|
||||||
|
str = g_value_get_string (value);
|
||||||
|
alias = nm_keyfile_plugin_get_alias_for_setting_name (str);
|
||||||
|
nm_keyfile_plugin_kf_set_string (info->keyfile,
|
||||||
|
nm_setting_get_name (setting),
|
||||||
|
key,
|
||||||
|
alias ? alias : str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_array_of_uint (GKeyFile *file,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
GArray *array;
|
||||||
|
int i;
|
||||||
|
int *tmp_array;
|
||||||
|
|
||||||
|
array = (GArray *) g_value_get_boxed (value);
|
||||||
|
if (!array || !array->len)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp_array = g_new (gint, array->len);
|
||||||
|
for (i = 0; i < array->len; i++)
|
||||||
|
tmp_array[i] = g_array_index (array, int, i);
|
||||||
|
|
||||||
|
nm_keyfile_plugin_kf_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len);
|
||||||
|
g_free (tmp_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dns_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
char **list;
|
||||||
|
|
||||||
|
list = g_value_get_boxed (value);
|
||||||
|
if (list && list[0]) {
|
||||||
|
nm_keyfile_plugin_kf_set_string_list (info->keyfile, nm_setting_get_name (setting), key,
|
||||||
|
(const char **) list, g_strv_length (list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_ip_values (GKeyFile *file,
|
||||||
|
const char *setting_name,
|
||||||
|
GPtrArray *array,
|
||||||
|
const char *gateway,
|
||||||
|
gboolean is_route)
|
||||||
|
{
|
||||||
|
GString *output;
|
||||||
|
int family, i;
|
||||||
|
const char *addr, *gw;
|
||||||
|
guint32 plen, metric;
|
||||||
|
char key_name[30], *key_name_idx;
|
||||||
|
|
||||||
|
if (!array->len)
|
||||||
|
return;
|
||||||
|
|
||||||
|
family = !strcmp (setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6;
|
||||||
|
|
||||||
|
strcpy (key_name, is_route ? "route" : "address");
|
||||||
|
key_name_idx = key_name + strlen (key_name);
|
||||||
|
|
||||||
|
output = g_string_sized_new (2*INET_ADDRSTRLEN + 10);
|
||||||
|
for (i = 0; i < array->len; i++) {
|
||||||
|
if (is_route) {
|
||||||
|
NMIPRoute *route = array->pdata[i];
|
||||||
|
|
||||||
|
addr = nm_ip_route_get_dest (route);
|
||||||
|
plen = nm_ip_route_get_prefix (route);
|
||||||
|
gw = nm_ip_route_get_next_hop (route);
|
||||||
|
metric = MAX (0, nm_ip_route_get_metric (route));
|
||||||
|
} else {
|
||||||
|
NMIPAddress *address = array->pdata[i];
|
||||||
|
|
||||||
|
addr = nm_ip_address_get_address (address);
|
||||||
|
plen = nm_ip_address_get_prefix (address);
|
||||||
|
gw = i == 0 ? gateway : NULL;
|
||||||
|
metric = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_set_size (output, 0);
|
||||||
|
g_string_append_printf (output, "%s/%u", addr, plen);
|
||||||
|
if (metric || gw) {
|
||||||
|
/* Older versions of the plugin do not support the form
|
||||||
|
* "a.b.c.d/plen,,metric", so, we always have to write the
|
||||||
|
* gateway, even if there isn't one.
|
||||||
|
* The current version supports reading of the above form.
|
||||||
|
*/
|
||||||
|
if (!gw) {
|
||||||
|
if (family == AF_INET)
|
||||||
|
gw = "0.0.0.0";
|
||||||
|
else
|
||||||
|
gw = "::";
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append_printf (output, ",%s", gw);
|
||||||
|
if (metric)
|
||||||
|
g_string_append_printf (output, ",%lu", (unsigned long) metric);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf (key_name_idx, "%d", i + 1);
|
||||||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str);
|
||||||
|
}
|
||||||
|
g_string_free (output, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addr_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
GPtrArray *array;
|
||||||
|
const char *setting_name = nm_setting_get_name (setting);
|
||||||
|
const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
|
||||||
|
|
||||||
|
array = (GPtrArray *) g_value_get_boxed (value);
|
||||||
|
if (array && array->len)
|
||||||
|
write_ip_values (info->keyfile, setting_name, array, gateway, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ip4_addr_label_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
/* skip */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gateway_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
/* skip */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
GPtrArray *array;
|
||||||
|
const char *setting_name = nm_setting_get_name (setting);
|
||||||
|
|
||||||
|
array = (GPtrArray *) g_value_get_boxed (value);
|
||||||
|
if (array && array->len)
|
||||||
|
write_ip_values (info->keyfile, setting_name, array, NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_hash_of_string (GKeyFile *file,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
const char *property = NULL, *data = NULL;
|
||||||
|
const char *group_name = nm_setting_get_name (setting);
|
||||||
|
gboolean vpn_secrets = FALSE;
|
||||||
|
|
||||||
|
/* Write VPN secrets out to a different group to keep them separate */
|
||||||
|
if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) {
|
||||||
|
group_name = VPN_SECRETS_GROUP;
|
||||||
|
vpn_secrets = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value));
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *) &property, (gpointer *) &data)) {
|
||||||
|
gboolean write_item = TRUE;
|
||||||
|
|
||||||
|
/* Handle VPN secrets specially; they are nested in the property's hash;
|
||||||
|
* we don't want to write them if the secret is not saved, not required,
|
||||||
|
* or owned by a user's secret agent.
|
||||||
|
*/
|
||||||
|
if (vpn_secrets) {
|
||||||
|
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||||
|
|
||||||
|
nm_setting_get_secret_flags (setting, property, &secret_flags, NULL);
|
||||||
|
if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
|
||||||
|
write_item = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_item)
|
||||||
|
nm_keyfile_plugin_kf_set_string (file, group_name, property, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ssid_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
GBytes *bytes;
|
||||||
|
const guint8 *ssid_data;
|
||||||
|
gsize ssid_len;
|
||||||
|
const char *setting_name = nm_setting_get_name (setting);
|
||||||
|
gboolean new_format = TRUE;
|
||||||
|
unsigned int semicolons = 0;
|
||||||
|
int i, *tmp_array;
|
||||||
|
char *ssid;
|
||||||
|
|
||||||
|
g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
|
||||||
|
|
||||||
|
bytes = g_value_get_boxed (value);
|
||||||
|
if (!bytes)
|
||||||
|
return;
|
||||||
|
ssid_data = g_bytes_get_data (bytes, &ssid_len);
|
||||||
|
if (ssid_len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Check whether each byte is printable. If not, we have to use an
|
||||||
|
* integer list, otherwise we can just use a string.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ssid_len; i++) {
|
||||||
|
char c = ssid_data[i] & 0xFF;
|
||||||
|
if (!g_ascii_isprint (c)) {
|
||||||
|
new_format = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == ';')
|
||||||
|
semicolons++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_format) {
|
||||||
|
ssid = g_malloc0 (ssid_len + semicolons + 1);
|
||||||
|
if (semicolons == 0)
|
||||||
|
memcpy (ssid, ssid_data, ssid_len);
|
||||||
|
else {
|
||||||
|
/* Escape semicolons with backslashes to make strings
|
||||||
|
* containing ';', such as '16;17;' unambiguous */
|
||||||
|
int j = 0;
|
||||||
|
for (i = 0; i < ssid_len; i++) {
|
||||||
|
if (ssid_data[i] == ';')
|
||||||
|
ssid[j++] = '\\';
|
||||||
|
ssid[j++] = ssid_data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, ssid);
|
||||||
|
g_free (ssid);
|
||||||
|
} else {
|
||||||
|
tmp_array = g_new (gint, ssid_len);
|
||||||
|
for (i = 0; i < ssid_len; i++)
|
||||||
|
tmp_array[i] = (int) ssid_data[i];
|
||||||
|
nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, ssid_len);
|
||||||
|
g_free (tmp_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
password_raw_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
const char *setting_name = nm_setting_get_name (setting);
|
||||||
|
GBytes *array;
|
||||||
|
int *tmp_array;
|
||||||
|
gsize i, len;
|
||||||
|
const char *data;
|
||||||
|
|
||||||
|
g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
|
||||||
|
|
||||||
|
array = (GBytes *) g_value_get_boxed (value);
|
||||||
|
if (!array)
|
||||||
|
return;
|
||||||
|
data = g_bytes_get_data (array, &len);
|
||||||
|
if (!data || !len)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp_array = g_new (gint, len);
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
tmp_array[i] = (int) data[i];
|
||||||
|
nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, len);
|
||||||
|
g_free (tmp_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct ObjectType {
|
||||||
|
const char *key;
|
||||||
|
const char *suffix;
|
||||||
|
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
|
||||||
|
NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
|
||||||
|
const char * (*path_func) (NMSetting8021x *setting);
|
||||||
|
GBytes * (*blob_func) (NMSetting8021x *setting);
|
||||||
|
} ObjectType;
|
||||||
|
|
||||||
|
static const ObjectType objtypes[10] = {
|
||||||
|
{ NM_SETTING_802_1X_CA_CERT,
|
||||||
|
"ca-cert",
|
||||||
|
nm_setting_802_1x_get_ca_cert_scheme,
|
||||||
|
NULL,
|
||||||
|
nm_setting_802_1x_get_ca_cert_path,
|
||||||
|
nm_setting_802_1x_get_ca_cert_blob },
|
||||||
|
|
||||||
|
{ NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||||
|
"inner-ca-cert",
|
||||||
|
nm_setting_802_1x_get_phase2_ca_cert_scheme,
|
||||||
|
NULL,
|
||||||
|
nm_setting_802_1x_get_phase2_ca_cert_path,
|
||||||
|
nm_setting_802_1x_get_phase2_ca_cert_blob },
|
||||||
|
|
||||||
|
{ NM_SETTING_802_1X_CLIENT_CERT,
|
||||||
|
"client-cert",
|
||||||
|
nm_setting_802_1x_get_client_cert_scheme,
|
||||||
|
NULL,
|
||||||
|
nm_setting_802_1x_get_client_cert_path,
|
||||||
|
nm_setting_802_1x_get_client_cert_blob },
|
||||||
|
|
||||||
|
{ NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||||
|
"inner-client-cert",
|
||||||
|
nm_setting_802_1x_get_phase2_client_cert_scheme,
|
||||||
|
NULL,
|
||||||
|
nm_setting_802_1x_get_phase2_client_cert_path,
|
||||||
|
nm_setting_802_1x_get_phase2_client_cert_blob },
|
||||||
|
|
||||||
|
{ NM_SETTING_802_1X_PRIVATE_KEY,
|
||||||
|
"private-key",
|
||||||
|
nm_setting_802_1x_get_private_key_scheme,
|
||||||
|
nm_setting_802_1x_get_private_key_format,
|
||||||
|
nm_setting_802_1x_get_private_key_path,
|
||||||
|
nm_setting_802_1x_get_private_key_blob },
|
||||||
|
|
||||||
|
{ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||||
|
"inner-private-key",
|
||||||
|
nm_setting_802_1x_get_phase2_private_key_scheme,
|
||||||
|
nm_setting_802_1x_get_phase2_private_key_format,
|
||||||
|
nm_setting_802_1x_get_phase2_private_key_path,
|
||||||
|
nm_setting_802_1x_get_phase2_private_key_blob },
|
||||||
|
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
cert_writer_default (NMConnection *connection,
|
||||||
|
GKeyFile *file,
|
||||||
|
NMKeyfileWriteTypeDataCert *cert_data)
|
||||||
|
{
|
||||||
|
const char *setting_name = nm_setting_get_name (NM_SETTING (cert_data->setting));
|
||||||
|
NMSetting8021xCKScheme scheme;
|
||||||
|
|
||||||
|
scheme = cert_data->scheme_func (cert_data->setting);
|
||||||
|
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||||
|
const char *path;
|
||||||
|
char *path_free = NULL, *tmp;
|
||||||
|
gs_free char *base_dir = NULL;
|
||||||
|
|
||||||
|
path = cert_data->path_func (cert_data->setting);
|
||||||
|
g_assert (path);
|
||||||
|
|
||||||
|
/* If the path is relative, make it an absolute path.
|
||||||
|
* Relative paths make a keyfile not easily usable in another
|
||||||
|
* context. */
|
||||||
|
if (path[0] && path[0] != '/') {
|
||||||
|
base_dir = g_get_current_dir ();
|
||||||
|
path = path_free = g_strconcat (base_dir, "/", path, NULL);
|
||||||
|
} else
|
||||||
|
base_dir = g_path_get_dirname (path);
|
||||||
|
|
||||||
|
/* path cannot start with "file://" or "data:;base64,", because it is an absolute path.
|
||||||
|
* Still, make sure that a prefix-less path will be recognized. This can happen
|
||||||
|
* for example if the path is longer then 500 chars. */
|
||||||
|
tmp = nm_keyfile_detect_unqualified_path_scheme (base_dir, path, -1, FALSE, NULL);
|
||||||
|
if (tmp)
|
||||||
|
g_clear_pointer (&tmp, g_free);
|
||||||
|
else
|
||||||
|
path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL);
|
||||||
|
|
||||||
|
/* Path contains at least a '/', hence it cannot be recognized as the old
|
||||||
|
* binary format consisting of a list of integers. */
|
||||||
|
|
||||||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, path);
|
||||||
|
g_free (tmp);
|
||||||
|
g_free (path_free);
|
||||||
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
|
GBytes *blob;
|
||||||
|
const guint8 *blob_data;
|
||||||
|
gsize blob_len;
|
||||||
|
char *blob_base64, *val;
|
||||||
|
|
||||||
|
blob = cert_data->blob_func (cert_data->setting);
|
||||||
|
g_assert (blob);
|
||||||
|
blob_data = g_bytes_get_data (blob, &blob_len);
|
||||||
|
|
||||||
|
blob_base64 = g_base64_encode (blob_data, blob_len);
|
||||||
|
val = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB, blob_base64, NULL);
|
||||||
|
|
||||||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, val);
|
||||||
|
g_free (val);
|
||||||
|
g_free (blob_base64);
|
||||||
|
} else {
|
||||||
|
/* scheme_func() returns UNKNOWN in all other cases. The only valid case
|
||||||
|
* where a scheme is allowed to be UNKNOWN, is unsetting the value. In this
|
||||||
|
* case, we don't expect the writer to be called, because the default value
|
||||||
|
* will not be serialized.
|
||||||
|
* The only other reason for the scheme to be UNKNOWN is an invalid cert.
|
||||||
|
* But our connection verifies, so that cannot happen either. */
|
||||||
|
g_return_if_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cert_writer (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
const ObjectType *objtype = NULL;
|
||||||
|
guint i;
|
||||||
|
NMKeyfileWriteTypeDataCert type_data = { 0 };
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (objtypes) && objtypes[i].key; i++) {
|
||||||
|
if (g_strcmp0 (objtypes[i].key, key) == 0) {
|
||||||
|
objtype = &objtypes[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!objtype)
|
||||||
|
g_return_if_reached ();
|
||||||
|
|
||||||
|
type_data.setting = NM_SETTING_802_1X (setting);
|
||||||
|
type_data.property_name = key;
|
||||||
|
type_data.suffix = objtype->suffix;
|
||||||
|
type_data.scheme_func = objtype->scheme_func;
|
||||||
|
type_data.format_func = objtype->format_func;
|
||||||
|
type_data.path_func = objtype->path_func;
|
||||||
|
type_data.blob_func = objtype->blob_func;
|
||||||
|
|
||||||
|
if (info->handler) {
|
||||||
|
if (info->handler (info->connection,
|
||||||
|
info->keyfile,
|
||||||
|
NM_KEYFILE_WRITE_TYPE_CERT,
|
||||||
|
&type_data,
|
||||||
|
info->user_data,
|
||||||
|
&info->error))
|
||||||
|
return;
|
||||||
|
if (info->error)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cert_writer_default (info->connection, info->keyfile, &type_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *setting_name;
|
||||||
|
const char *key;
|
||||||
|
void (*writer) (KeyfileWriterInfo *info,
|
||||||
|
NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value);
|
||||||
|
} KeyWriter;
|
||||||
|
|
||||||
|
/* A table of keys that require further parsing/conversion because they are
|
||||||
|
* stored in a format that can't be automatically read using the key's type.
|
||||||
|
* i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are
|
||||||
|
* stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored
|
||||||
|
* in struct in6_addr internally, but as string in keyfiles.
|
||||||
|
*/
|
||||||
|
static KeyWriter key_writers[] = {
|
||||||
|
{ NM_SETTING_CONNECTION_SETTING_NAME,
|
||||||
|
NM_SETTING_CONNECTION_TYPE,
|
||||||
|
setting_alias_writer },
|
||||||
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_ADDRESSES,
|
||||||
|
addr_writer },
|
||||||
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||||
|
"address-labels",
|
||||||
|
ip4_addr_label_writer },
|
||||||
|
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_ADDRESSES,
|
||||||
|
addr_writer },
|
||||||
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||||
|
gateway_writer },
|
||||||
|
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||||
|
gateway_writer },
|
||||||
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_ROUTES,
|
||||||
|
route_writer },
|
||||||
|
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_ROUTES,
|
||||||
|
route_writer },
|
||||||
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_DNS,
|
||||||
|
dns_writer },
|
||||||
|
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||||
|
NM_SETTING_IP_CONFIG_DNS,
|
||||||
|
dns_writer },
|
||||||
|
{ NM_SETTING_WIRELESS_SETTING_NAME,
|
||||||
|
NM_SETTING_WIRELESS_SSID,
|
||||||
|
ssid_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_PASSWORD_RAW,
|
||||||
|
password_raw_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_CA_CERT,
|
||||||
|
cert_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_CLIENT_CERT,
|
||||||
|
cert_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_PRIVATE_KEY,
|
||||||
|
cert_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||||
|
cert_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||||
|
cert_writer },
|
||||||
|
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||||
|
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||||
|
cert_writer },
|
||||||
|
{ NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_setting_value (NMSetting *setting,
|
||||||
|
const char *key,
|
||||||
|
const GValue *value,
|
||||||
|
GParamFlags flag,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
KeyfileWriterInfo *info = user_data;
|
||||||
|
const char *setting_name;
|
||||||
|
GType type = G_VALUE_TYPE (value);
|
||||||
|
KeyWriter *writer = &key_writers[0];
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
if (info->error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Setting name gets picked up from the keyfile's section name instead */
|
||||||
|
if (!strcmp (key, NM_SETTING_NAME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Don't write the NMSettingConnection object's 'read-only' property */
|
||||||
|
if ( NM_IS_SETTING_CONNECTION (setting)
|
||||||
|
&& !strcmp (key, NM_SETTING_CONNECTION_READ_ONLY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
setting_name = nm_setting_get_name (setting);
|
||||||
|
|
||||||
|
/* If the value is the default value, remove the item from the keyfile */
|
||||||
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
|
||||||
|
if (pspec) {
|
||||||
|
if (g_param_value_defaults (pspec, (GValue *) value)) {
|
||||||
|
g_key_file_remove_key (info->keyfile, setting_name, key, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't write secrets that are owned by user secret agents or aren't
|
||||||
|
* supposed to be saved. VPN secrets are handled specially though since
|
||||||
|
* the secret flags there are in a third-level hash in the 'secrets'
|
||||||
|
* property.
|
||||||
|
*/
|
||||||
|
if (pspec && (pspec->flags & NM_SETTING_PARAM_SECRET) && !NM_IS_SETTING_VPN (setting)) {
|
||||||
|
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||||
|
|
||||||
|
if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL))
|
||||||
|
g_assert_not_reached ();
|
||||||
|
if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look through the list of handlers for non-standard format key values */
|
||||||
|
while (writer->setting_name) {
|
||||||
|
if (!strcmp (writer->setting_name, setting_name) && !strcmp (writer->key, key)) {
|
||||||
|
(*writer->writer) (info, setting, key, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writer++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == G_TYPE_STRING) {
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
str = g_value_get_string (value);
|
||||||
|
if (str)
|
||||||
|
nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str);
|
||||||
|
} else if (type == G_TYPE_UINT)
|
||||||
|
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value));
|
||||||
|
else if (type == G_TYPE_INT)
|
||||||
|
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, g_value_get_int (value));
|
||||||
|
else if (type == G_TYPE_UINT64) {
|
||||||
|
char *numstr;
|
||||||
|
|
||||||
|
numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value));
|
||||||
|
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||||
|
g_free (numstr);
|
||||||
|
} else if (type == G_TYPE_INT64) {
|
||||||
|
char *numstr;
|
||||||
|
|
||||||
|
numstr = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (value));
|
||||||
|
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||||
|
g_free (numstr);
|
||||||
|
} else if (type == G_TYPE_BOOLEAN) {
|
||||||
|
nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value));
|
||||||
|
} else if (type == G_TYPE_CHAR) {
|
||||||
|
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value));
|
||||||
|
} else if (type == G_TYPE_BYTES) {
|
||||||
|
GBytes *bytes;
|
||||||
|
const guint8 *data;
|
||||||
|
gsize len = 0;
|
||||||
|
|
||||||
|
bytes = g_value_get_boxed (value);
|
||||||
|
data = bytes ? g_bytes_get_data (bytes, &len) : NULL;
|
||||||
|
|
||||||
|
if (data != NULL && len > 0) {
|
||||||
|
int *tmp_array;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
tmp_array = g_new (gint, len);
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
tmp_array[i] = (int) data[i];
|
||||||
|
|
||||||
|
nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, len);
|
||||||
|
g_free (tmp_array);
|
||||||
|
}
|
||||||
|
} else if (type == G_TYPE_STRV) {
|
||||||
|
char **array;
|
||||||
|
|
||||||
|
array = (char **) g_value_get_boxed (value);
|
||||||
|
nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array));
|
||||||
|
} else if (type == G_TYPE_HASH_TABLE) {
|
||||||
|
write_hash_of_string (info->keyfile, setting, key, value);
|
||||||
|
} else if (type == G_TYPE_ARRAY) {
|
||||||
|
write_array_of_uint (info->keyfile, setting, key, value);
|
||||||
|
} else if (G_VALUE_HOLDS_FLAGS (value)) {
|
||||||
|
/* Flags are guint but GKeyFile has no uint reader, just uint64 */
|
||||||
|
nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value));
|
||||||
|
} else if (G_VALUE_HOLDS_ENUM (value))
|
||||||
|
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value));
|
||||||
|
else
|
||||||
|
g_warn_if_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
GKeyFile *
|
||||||
|
nm_keyfile_write (NMConnection *connection,
|
||||||
|
NMKeyfileWriteHandler handler,
|
||||||
|
void *user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
KeyfileWriterInfo info = { 0 };
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||||
|
g_return_val_if_fail (!error || !*error, NULL);
|
||||||
|
|
||||||
|
if (!nm_connection_verify (connection, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
info.connection = connection;
|
||||||
|
info.keyfile = g_key_file_new ();
|
||||||
|
info.error = NULL;
|
||||||
|
info.handler = handler;
|
||||||
|
info.user_data = user_data;
|
||||||
|
nm_connection_for_each_setting_value (connection, write_setting_value, &info);
|
||||||
|
|
||||||
|
if (info.error) {
|
||||||
|
g_propagate_error (error, info.error);
|
||||||
|
g_key_file_unref (info.keyfile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return info.keyfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
#include "nm-utils-private.h"
|
#include "nm-utils-private.h"
|
||||||
#include "nm-setting-private.h"
|
#include "nm-setting-private.h"
|
||||||
#include "nm-core-enum-types.h"
|
#include "nm-core-enum-types.h"
|
||||||
|
#include "nm-utils-internal.h"
|
||||||
|
#include "gsystem-local-alloc.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:nm-setting-8021x
|
* SECTION:nm-setting-8021x
|
||||||
|
|
@ -60,8 +62,6 @@
|
||||||
* ISBN: 978-1587051548
|
* ISBN: 978-1587051548
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define SCHEME_PATH "file://"
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING,
|
G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING,
|
||||||
_nm_register_setting (802_1X, 2))
|
_nm_register_setting (802_1X, 2))
|
||||||
NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_802_1X)
|
NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_802_1X)
|
||||||
|
|
@ -400,25 +400,122 @@ nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
static NMSetting8021xCKScheme
|
static NMSetting8021xCKScheme
|
||||||
get_cert_scheme (GBytes *bytes)
|
get_cert_scheme (GBytes *bytes, GError **error)
|
||||||
{
|
{
|
||||||
gconstpointer data;
|
const char *data;
|
||||||
gsize length;
|
gsize length;
|
||||||
|
|
||||||
if (!bytes)
|
if (!bytes) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("data missing"));
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
data = g_bytes_get_data (bytes, &length);
|
data = g_bytes_get_data (bytes, &length);
|
||||||
if (!length)
|
return nm_setting_802_1x_check_cert_scheme (data, length, error);
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_setting_802_1x_check_cert_scheme:
|
||||||
|
* @pdata: (allow-none): the data pointer
|
||||||
|
* @length: the length of the data
|
||||||
|
* @error: (allow-none): (out): validation reason
|
||||||
|
*
|
||||||
|
* Determines and verifies the blob type.
|
||||||
|
* When setting certificate properties of NMSetting8021x
|
||||||
|
* the blob must be not UNKNOWN (or NULL).
|
||||||
|
*
|
||||||
|
* Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
|
||||||
|
* For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
**/
|
||||||
|
NMSetting8021xCKScheme
|
||||||
|
nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error)
|
||||||
|
{
|
||||||
|
const char *data = pdata;
|
||||||
|
|
||||||
|
g_return_val_if_fail (!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
|
if (!length || !data) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("binary data missing"));
|
||||||
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interpret the blob as PATH if it starts with "file://". */
|
||||||
|
if ( length >= STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)
|
||||||
|
&& !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) {
|
||||||
|
/* But it must also be NUL terminated, contain at least
|
||||||
|
* one non-NUL character, and contain only one trailing NUL
|
||||||
|
* chracter.
|
||||||
|
* And ensure it's UTF-8 valid too so we can pass it through
|
||||||
|
* D-Bus and stuff like that. */
|
||||||
|
|
||||||
|
if (data[length - 1] != '\0') {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("file:// URI not NUL terminated"));
|
||||||
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
}
|
||||||
|
length--;
|
||||||
|
|
||||||
|
if (length <= STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("file:// URI is empty"));
|
||||||
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_utf8_validate (data + STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH), length - STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH), NULL)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("file:// URI is not valid UTF-8"));
|
||||||
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
if ( (length > strlen (SCHEME_PATH))
|
|
||||||
&& !memcmp (data, SCHEME_PATH, strlen (SCHEME_PATH)))
|
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_PATH;
|
return NM_SETTING_802_1X_CK_SCHEME_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
return NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GByteArray *
|
||||||
|
load_and_verify_certificate (const char *cert_path,
|
||||||
|
NMSetting8021xCKScheme scheme,
|
||||||
|
NMCryptoFileFormat *out_file_format,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||||
|
GByteArray *array;
|
||||||
|
|
||||||
|
array = crypto_load_and_verify_certificate (cert_path, &format, error);
|
||||||
|
|
||||||
|
if (!array || !array->len || format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
|
||||||
|
/* the array is empty or the format is already unknown. */
|
||||||
|
format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||||
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
|
/* If we load the file as blob, we must ensure that the binary data does not
|
||||||
|
* start with file://. NMSetting8021x cannot represent blobs that start with
|
||||||
|
* file://.
|
||||||
|
* If that's the case, coerce the format to UNKNOWN. The callers will take care
|
||||||
|
* of that and not set the blob. */
|
||||||
|
if (nm_setting_802_1x_check_cert_scheme (array->data, array->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB)
|
||||||
|
format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_file_format)
|
||||||
|
*out_file_format = format;
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_setting_802_1x_get_ca_cert_scheme:
|
* nm_setting_802_1x_get_ca_cert_scheme:
|
||||||
* @setting: the #NMSetting8021x
|
* @setting: the #NMSetting8021x
|
||||||
|
|
@ -434,7 +531,7 @@ nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert);
|
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -488,20 +585,23 @@ nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting)
|
||||||
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
||||||
|
|
||||||
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
|
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
|
||||||
return (const char *)data + strlen (SCHEME_PATH);
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GBytes *
|
static GBytes *
|
||||||
path_to_scheme_value (const char *path)
|
path_to_scheme_value (const char *path)
|
||||||
{
|
{
|
||||||
GByteArray *array;
|
GByteArray *array;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
g_return_val_if_fail (path != NULL, NULL);
|
g_return_val_if_fail (path != NULL && path[0], NULL);
|
||||||
|
|
||||||
/* Add the path scheme tag to the front, then the fielname */
|
len = strlen (path);
|
||||||
array = g_byte_array_sized_new (strlen (path) + strlen (SCHEME_PATH) + 1);
|
|
||||||
g_byte_array_append (array, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
/* Add the path scheme tag to the front, then the filename */
|
||||||
g_byte_array_append (array, (const guint8 *) path, strlen (path));
|
array = g_byte_array_sized_new (len + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1);
|
||||||
|
g_byte_array_append (array, (const guint8 *) NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
|
||||||
|
g_byte_array_append (array, (const guint8 *) path, len);
|
||||||
g_byte_array_append (array, (const guint8 *) "\0", 1);
|
g_byte_array_append (array, (const guint8 *) "\0", 1);
|
||||||
|
|
||||||
return g_byte_array_free_to_bytes (array);
|
return g_byte_array_free_to_bytes (array);
|
||||||
|
|
@ -558,7 +658,7 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
/* wpa_supplicant can only use raw x509 CA certs */
|
/* wpa_supplicant can only use raw x509 CA certs */
|
||||||
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
||||||
|
|
@ -766,7 +866,7 @@ nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert);
|
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -814,7 +914,7 @@ nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting)
|
||||||
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
||||||
|
|
||||||
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL);
|
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL);
|
||||||
return (const char *)data + strlen (SCHEME_PATH);
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -872,7 +972,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
gboolean valid = FALSE;
|
gboolean valid = FALSE;
|
||||||
|
|
||||||
|
|
@ -1029,7 +1129,7 @@ nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert);
|
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1083,7 +1183,7 @@ nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting)
|
||||||
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
||||||
|
|
||||||
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL);
|
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL);
|
||||||
return (const char *)data + strlen (SCHEME_PATH);
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1137,7 +1237,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
/* wpa_supplicant can only use raw x509 CA certs */
|
/* wpa_supplicant can only use raw x509 CA certs */
|
||||||
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
||||||
|
|
@ -1349,7 +1449,7 @@ nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert);
|
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1397,7 +1497,7 @@ nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting)
|
||||||
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
||||||
|
|
||||||
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL);
|
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL);
|
||||||
return (const char *)data + strlen (SCHEME_PATH);
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1455,7 +1555,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
gboolean valid = FALSE;
|
gboolean valid = FALSE;
|
||||||
|
|
||||||
|
|
@ -1604,7 +1704,7 @@ nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key);
|
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1656,7 +1756,7 @@ nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting)
|
||||||
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
||||||
|
|
||||||
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL);
|
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL);
|
||||||
return (const char *)data + strlen (SCHEME_PATH);
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1678,7 +1778,7 @@ file_to_secure_bytes (const char *filename)
|
||||||
if (g_file_get_contents (filename, &contents, &length, NULL)) {
|
if (g_file_get_contents (filename, &contents, &length, NULL)) {
|
||||||
array = g_byte_array_sized_new (length);
|
array = g_byte_array_sized_new (length);
|
||||||
g_byte_array_append (array, (guint8 *) contents, length);
|
g_byte_array_append (array, (guint8 *) contents, length);
|
||||||
g_assert (array->len == length);
|
memset (contents, 0, length);
|
||||||
g_free (contents);
|
g_free (contents);
|
||||||
return g_bytes_new_with_free_func (array->data, array->len, free_secure_bytes, array);
|
return g_bytes_new_with_free_func (array->data, array->len, free_secure_bytes, array);
|
||||||
}
|
}
|
||||||
|
|
@ -1790,7 +1890,8 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
|
||||||
|
|
||||||
priv->private_key_password = g_strdup (password);
|
priv->private_key_password = g_strdup (password);
|
||||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
/* Shouldn't fail this since we just verified the private key above */
|
/* FIXME: potential race after verifying the private key above */
|
||||||
|
/* FIXME: ensure blob doesn't start with file:// */
|
||||||
priv->private_key = file_to_secure_bytes (key_path);
|
priv->private_key = file_to_secure_bytes (key_path);
|
||||||
g_assert (priv->private_key);
|
g_assert (priv->private_key);
|
||||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
|
||||||
|
|
@ -1941,7 +2042,7 @@ nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
|
||||||
|
|
||||||
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key);
|
return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1993,7 +2094,7 @@ nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting)
|
||||||
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
|
||||||
|
|
||||||
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL);
|
data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL);
|
||||||
return (const char *)data + strlen (SCHEME_PATH);
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -2101,7 +2202,8 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
|
||||||
|
|
||||||
priv->phase2_private_key_password = g_strdup (password);
|
priv->phase2_private_key_password = g_strdup (password);
|
||||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
/* Shouldn't fail this since we just verified the private key above */
|
/* FIXME: potential race after verifying the private key above */
|
||||||
|
/* FIXME: ensure blob doesn't start with file:// */
|
||||||
priv->phase2_private_key = file_to_secure_bytes (key_path);
|
priv->phase2_private_key = file_to_secure_bytes (key_path);
|
||||||
g_assert (priv->phase2_private_key);
|
g_assert (priv->phase2_private_key);
|
||||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
|
||||||
|
|
@ -2575,35 +2677,18 @@ need_secrets (NMSetting *setting)
|
||||||
static gboolean
|
static gboolean
|
||||||
verify_cert (GBytes *bytes, const char *prop_name, GError **error)
|
verify_cert (GBytes *bytes, const char *prop_name, GError **error)
|
||||||
{
|
{
|
||||||
gconstpointer data;
|
GError *local = NULL;
|
||||||
gsize length;
|
|
||||||
|
|
||||||
if (!bytes)
|
if ( !bytes
|
||||||
|
|| get_cert_scheme (bytes, &local) != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
switch (get_cert_scheme (bytes)) {
|
g_set_error (error,
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
NM_CONNECTION_ERROR,
|
||||||
return TRUE;
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
_("certificate is invalid: %s"), local->message);
|
||||||
/* For path-based schemes, verify that the path is zero-terminated */
|
|
||||||
data = g_bytes_get_data (bytes, &length);
|
|
||||||
if (((const guchar *)data)[length - 1] == '\0') {
|
|
||||||
/* And ensure it's UTF-8 valid too so we can pass it through
|
|
||||||
* D-Bus and stuff like that.
|
|
||||||
*/
|
|
||||||
if (g_utf8_validate ((const char *)data + strlen (SCHEME_PATH), -1, NULL))
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_set_error_literal (error,
|
|
||||||
NM_CONNECTION_ERROR,
|
|
||||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
|
||||||
_("property is invalid"));
|
|
||||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
|
g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
|
||||||
|
g_error_free (local);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH "file://"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NMSetting8021xCKFormat:
|
* NMSetting8021xCKFormat:
|
||||||
* @NM_SETTING_802_1X_CK_FORMAT_UNKNOWN: unknown file format
|
* @NM_SETTING_802_1X_CK_FORMAT_UNKNOWN: unknown file format
|
||||||
|
|
@ -147,6 +149,9 @@ GType nm_setting_802_1x_get_type (void);
|
||||||
|
|
||||||
NMSetting *nm_setting_802_1x_new (void);
|
NMSetting *nm_setting_802_1x_new (void);
|
||||||
|
|
||||||
|
NM_AVAILABLE_IN_1_2
|
||||||
|
NMSetting8021xCKScheme nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error);
|
||||||
|
|
||||||
guint32 nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting);
|
guint32 nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting);
|
||||||
const char * nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i);
|
const char * nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i);
|
||||||
gboolean nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap);
|
gboolean nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <netinet/ether.h>
|
#include <netinet/ether.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
@ -1939,6 +1940,8 @@ nm_utils_ip_routes_from_variant (GVariant *value,
|
||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_utils_uuid_generate:
|
* nm_utils_uuid_generate:
|
||||||
*
|
*
|
||||||
|
|
@ -2011,6 +2014,50 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _nm_utils_uuid_generate_from_strings:
|
||||||
|
* @string1: a variadic list of strings. Must be NULL terminated.
|
||||||
|
*
|
||||||
|
* Returns a variant3 UUID based on the concatenated C strings.
|
||||||
|
* It does not simply concatenate them, but also includes the
|
||||||
|
* terminating '\0' character. For example "a", "b", gives
|
||||||
|
* "a\0b\0".
|
||||||
|
*
|
||||||
|
* This has the advantage, that the following invocations
|
||||||
|
* all give different UUIDs: (NULL), (""), ("",""), ("","a"), ("a",""),
|
||||||
|
* ("aa"), ("aa", ""), ("", "aa"), ...
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
_nm_utils_uuid_generate_from_strings (const char *string1, ...)
|
||||||
|
{
|
||||||
|
GString *str;
|
||||||
|
va_list args;
|
||||||
|
const char *s;
|
||||||
|
char *uuid;
|
||||||
|
|
||||||
|
if (!string1)
|
||||||
|
return nm_utils_uuid_generate_from_string (NULL, 0, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
|
||||||
|
|
||||||
|
str = g_string_sized_new (120); /* effectively allocates power of 2 (128)*/
|
||||||
|
|
||||||
|
g_string_append_len (str, string1, strlen (string1) + 1);
|
||||||
|
|
||||||
|
va_start (args, string1);
|
||||||
|
s = va_arg (args, const char *);
|
||||||
|
while (s) {
|
||||||
|
g_string_append_len (str, s, strlen (s) + 1);
|
||||||
|
s = va_arg (args, const char *);
|
||||||
|
}
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
uuid = nm_utils_uuid_generate_from_string (str->str, str->len, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
|
||||||
|
|
||||||
|
g_string_free (str, TRUE);
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_utils_rsa_key_encrypt:
|
* nm_utils_rsa_key_encrypt:
|
||||||
* @data: (array length=len): RSA private key data to be encrypted
|
* @data: (array length=len): RSA private key data to be encrypted
|
||||||
|
|
@ -3278,3 +3325,81 @@ nm_utils_bond_mode_string_to_int (const char *mode)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************/
|
||||||
|
|
||||||
|
/* _nm_utils_ascii_str_to_int64:
|
||||||
|
*
|
||||||
|
* A wrapper for g_ascii_strtoll, that checks whether the whole string
|
||||||
|
* can be successfully converted to a number and is within a given
|
||||||
|
* range. On any error, @fallback will be returned and %errno will be set
|
||||||
|
* to a non-zero value. On success, %errno will be set to zero, check %errno
|
||||||
|
* for errors. Any trailing or leading (ascii) white space is ignored and the
|
||||||
|
* functions is locale independent.
|
||||||
|
*
|
||||||
|
* The function is guaranteed to return a value between @min and @max
|
||||||
|
* (inclusive) or @fallback. Also, the parsing is rather strict, it does
|
||||||
|
* not allow for any unrecognized characters, except leading and trailing
|
||||||
|
* white space.
|
||||||
|
**/
|
||||||
|
gint64
|
||||||
|
_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
|
||||||
|
{
|
||||||
|
gint64 v;
|
||||||
|
size_t len;
|
||||||
|
char buf[64], *s, *str_free = NULL;
|
||||||
|
|
||||||
|
if (str) {
|
||||||
|
while (g_ascii_isspace (str[0]))
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
if (!str || !str[0]) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen (str);
|
||||||
|
if (g_ascii_isspace (str[--len])) {
|
||||||
|
/* backward search the first non-ws character.
|
||||||
|
* We already know that str[0] is non-ws. */
|
||||||
|
while (g_ascii_isspace (str[--len]))
|
||||||
|
;
|
||||||
|
|
||||||
|
/* str[len] is now the last non-ws character... */
|
||||||
|
len++;
|
||||||
|
|
||||||
|
if (len >= sizeof (buf))
|
||||||
|
s = str_free = g_malloc (len + 1);
|
||||||
|
else
|
||||||
|
s = buf;
|
||||||
|
|
||||||
|
memcpy (s, str, len);
|
||||||
|
s[len] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
g_assert (len > 0 && len < strlen (str) && len == strlen (s));
|
||||||
|
g_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len]));
|
||||||
|
g_assert (strncmp (str, s, len) == 0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
str = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
v = g_ascii_strtoll (str, &s, base);
|
||||||
|
|
||||||
|
if (errno != 0)
|
||||||
|
v = fallback;
|
||||||
|
else if (s[0] != 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
v = fallback;
|
||||||
|
} else if (v > max || v < min) {
|
||||||
|
errno = ERANGE;
|
||||||
|
v = fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (str_free))
|
||||||
|
g_free (str_free);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ noinst_PROGRAMS = \
|
||||||
test-compare \
|
test-compare \
|
||||||
test-crypto \
|
test-crypto \
|
||||||
test-general \
|
test-general \
|
||||||
|
test-keyfile \
|
||||||
test-secrets \
|
test-secrets \
|
||||||
test-setting-8021x \
|
test-setting-8021x \
|
||||||
test-setting-dcb \
|
test-setting-dcb \
|
||||||
|
|
@ -38,20 +39,22 @@ endif
|
||||||
# -name "test-pkcs12" \
|
# -name "test-pkcs12" \
|
||||||
# -out test-cert.p12
|
# -out test-cert.p12
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
certs/test_ca_cert.pem \
|
certs/ca-no-ending-newline.pem \
|
||||||
certs/test_ca_cert.der \
|
certs/pkcs8-decrypted.der \
|
||||||
certs/test_key_and_cert.pem \
|
certs/pkcs8-enc-key.pem \
|
||||||
certs/test-cert.p12 \
|
certs/pkcs8-noenc-key.pem \
|
||||||
certs/test2_ca_cert.pem \
|
certs/test2_ca_cert.pem \
|
||||||
certs/test2_key_and_cert.pem \
|
certs/test2-cert.p12 \
|
||||||
certs/test2-cert.p12 \
|
certs/test2_key_and_cert.pem \
|
||||||
certs/ca-no-ending-newline.pem \
|
certs/test-aes-key.pem \
|
||||||
certs/test-key-only.pem \
|
certs/test_ca_cert.der \
|
||||||
certs/test-key-only-decrypted.der \
|
certs/test_ca_cert.pem \
|
||||||
certs/test-key-only-decrypted.pem \
|
certs/test-ca-cert.pem \
|
||||||
certs/pkcs8-enc-key.pem \
|
certs/test-cert.p12 \
|
||||||
certs/pkcs8-noenc-key.pem \
|
certs/test_key_and_cert.pem \
|
||||||
certs/pkcs8-decrypted.der \
|
certs/test-key-and-cert.pem \
|
||||||
certs/test-aes-key.pem
|
certs/test-key-only-decrypted.der \
|
||||||
|
certs/test-key-only-decrypted.pem \
|
||||||
|
certs/test-key-only.pem
|
||||||
|
|
||||||
|
|
|
||||||
27
libnm-core/tests/certs/test-ca-cert.pem
Normal file
27
libnm-core/tests/certs/test-ca-cert.pem
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEjzCCA3egAwIBAgIJAOvnZPt59yIZMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD
|
||||||
|
VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw
|
||||||
|
FQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UE
|
||||||
|
AxMEdGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAzMTAx
|
||||||
|
NTEyMTRaFw0xOTAzMDgxNTEyMTRaMIGLMQswCQYDVQQGEwJVUzESMBAGA1UECBMJ
|
||||||
|
QmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55
|
||||||
|
IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3
|
||||||
|
DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||||
|
ggEBAKot9j+/+CX1/gZLgJHIXCRgCItKLGnf7qGbgqB9T2ACBqR0jllKWwDKrcWU
|
||||||
|
xjXNIc+GF9Wnv+lX6G0Okn4Zt3/uRNobL+2b/yOF7M3Td3/9W873zdkQQX930YZc
|
||||||
|
Rr8uxdRPP5bxiCgtcw632y21sSEbG9mjccAUnV/0jdvfmMNj0i8gN6E0fMBiJ9S3
|
||||||
|
FkxX/KFvt9JWE9CtoyL7ki7UIDq+6vj7Gd5N0B3dOa1y+rRHZzKlJPcSXQSEYUS4
|
||||||
|
HmKDwiKSVahft8c4tDn7KPi0vex91hlgZVd3usL2E/Vq7o5D9FAZ5kZY0AdFXwdm
|
||||||
|
J4lO4Mj7ac7GE4vNERNcXVIX59sCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUuDU3Mr7P
|
||||||
|
T3n1e3Sy8hBauoDFahAwgcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDF
|
||||||
|
ahChgZGkgY4wgYsxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO
|
||||||
|
BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQL
|
||||||
|
EwdUZXN0aW5nMQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl
|
||||||
|
c3QuY29tggkA6+dk+3n3IhkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
|
||||||
|
AQEAVRG4aALIvCXCiKfe7K+iJxjBVRDFPEf7JWA9LGgbFOn6pNvbxonrR+0BETdc
|
||||||
|
JV1ET4ct2xsE7QNFIkp9GKRC+6J32zCo8qtLCD5+v436r8TUG2/t2JRMkb9I2XVT
|
||||||
|
p7RJoot6M0Ltf8KNQUPYh756xmKZ4USfQUwc58MOSDGY8VWEXJOYij9Pf0e0c52t
|
||||||
|
qiCEjXH7uXiS8Pgq9TYm7AkWSOrglYhSa83x0f8mtT8Q15nBESIHZ6o8FAS2bBgn
|
||||||
|
B0BkrKRjtBUkuJG3vTox+bYINh2Gxi1JZHWSV1tN5z3hd4VFcKqanW5OgQwToBqp
|
||||||
|
3nniskIjbH0xjgZf/nVMyLnjxg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
118
libnm-core/tests/certs/test-key-and-cert.pem
Normal file
118
libnm-core/tests/certs/test-key-and-cert.pem
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
Proc-Type: 4,ENCRYPTED
|
||||||
|
DEK-Info: DES-EDE3-CBC,4DE0615F23D82107
|
||||||
|
|
||||||
|
QPNCO5Dobvz9dDhN32KkZRoEifW+HDm2PCbRQhKDiscGwB6LgypvVjHNsZiFKwzz
|
||||||
|
L4R51UqgQeJx7GSGJqE626e9z9J+UNBhop02aOO2X0eSPdvBzr/uJ6Umiyr1xqD7
|
||||||
|
zWf7u9l5kXElDJRhK+87GMBewp4Ie9NeXDjhF8hzC5Kiulen4AH3AYnfH3S7DimU
|
||||||
|
h8GFMg8inrudrTbcjBhCdPeHG2jCygOxw3InRFz7uaN6LIhOaPQvmvpP4Cc1WRnW
|
||||||
|
ZPq9o+eU3fPWPD5t+Op/VzYLvKwgBy/yK1rQXUm6ZMO7MhhRJ94ZCsJv+nVWpJlv
|
||||||
|
QyBlxDKxwfkfYbDELdnnDQdHdMbKatLqa0KhSkgpp8LywBtanPz731tyT0r7b3na
|
||||||
|
eLdra59lRU7ZQLPEdS3lPZd2O/KQvWf8wbg7MjXS9LxQ7R5HOPu6DNJlwXVZBmmo
|
||||||
|
cAfu2q8ubU2IePvWLD1GOrBi6hE9TiGvFJkw+wBK+t72sz3njv9Xm/zlxruaEk5m
|
||||||
|
RW/kybU3FP4PtjriBbskz3/VZaaxuRN7OoOYTkmyHmG1ADgcRUV6fea19qqsBlN8
|
||||||
|
xb+SRtoH28oT/JVWU5neE2dbNzk5LeVO+w70NNdR5s5xqkBhbGGaJxvXwNP4ltFr
|
||||||
|
T06SMh8znOLKwWB00aRtwfU7jOwR3mOleQO4ugIHmau3zp1TqzAHW8XtpuV7qVeI
|
||||||
|
ESZOZuf0vW43BtNzgLXt1+r+bmsMsRwhnyomL9M0TUyyBdVYY9GkzTG9pOESheRo
|
||||||
|
RSvAZ8qKGUliTpgBcbt2v1+NqkszcHa6FxuvS8YU4uo5/GqsgTxHTNIB232hIrrZ
|
||||||
|
EIm6QL9TC5oFXMjy6UNqoCm5Nb8DBJ6aErt7pt7aoktqUW3O3QIzQT3IbZ4nAcTt
|
||||||
|
lVF4d7j29I9t7bcC8GOVU1neilguZUss4ghJg9x4zI5UZdR7hZ8fbFT47TyxB+j5
|
||||||
|
r0YdmjbjVTaSyaN2JGh1wvb4TzawGNVx/U2EJE16HigOtPfsfQRJ3x+FROKBdVa4
|
||||||
|
aIFYXkRBeIPxX6n9pcw0lBCsnXo6/5iTjQSk2VqO3rHO/wyWiEjNczhL33dY2A8W
|
||||||
|
GG5ECMO5SqXZHQQzpABqK94dxe3UC8aEESO5NhEqDuV7qQGol0qPKrUA3wb0jb2e
|
||||||
|
DrejJ9HS2m1SUDmjpvvmEGy6GN7CRibbKt5rNZdJNNvWArOF5d0F6wkixQLl73oE
|
||||||
|
lq5gLQQk9n7ClleKLhlQpBCorxilBbzmSUekkJLi0eaZiBBFWBX9udqnUZloXTgO
|
||||||
|
8qwuO8K/GPR9Jy1/UH2Vh1H+wivaqKTVgEb0NotzgzECgTEFKJafl7rUNs1OZRZ3
|
||||||
|
VBjevi6+iDpxVFgF71kXfdUC4ph0E1XDl0ja2rrKQGivMkUhWJ57+4EV5+hBkAnt
|
||||||
|
G0RV45NwHXLrK2bd8F9PlRk2XHW6mIcFRXsW1DjeBhk/sQjvlO9R01GRSgcXtekJ
|
||||||
|
tmX17FWrMrzXHpvy1IC3fk4RVnSjpzQ8O+17YE8/la9wVaeZZzHyYFmMT7VXjIhW
|
||||||
|
QozJQ0vJ2jxJRh5GYn3tpJzdaeRfvTBik0pChNdUTnWP+BJ35xoCTs8iwJbmgVZ1
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
Certificate:
|
||||||
|
Data:
|
||||||
|
Version: 3 (0x2)
|
||||||
|
Serial Number: 1 (0x1)
|
||||||
|
Signature Algorithm: md5WithRSAEncryption
|
||||||
|
Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=Testing, CN=test/emailAddress=test@test.com
|
||||||
|
Validity
|
||||||
|
Not Before: Mar 10 15:13:16 2009 GMT
|
||||||
|
Not After : Mar 8 15:13:16 2019 GMT
|
||||||
|
Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=Testing, CN=test1/emailAddress=test@test.com
|
||||||
|
Subject Public Key Info:
|
||||||
|
Public Key Algorithm: rsaEncryption
|
||||||
|
RSA Public Key: (2048 bit)
|
||||||
|
Modulus (2048 bit):
|
||||||
|
00:cd:34:b1:2e:b0:04:c6:f4:2b:a2:c0:a0:39:7a:
|
||||||
|
82:ed:96:c4:f7:19:83:91:5c:b4:e7:9c:de:ec:48:
|
||||||
|
ec:2d:e4:51:08:26:42:ac:d3:98:26:7a:72:f7:49:
|
||||||
|
c2:9e:66:05:c6:47:29:fe:3b:ac:6b:af:6f:5e:a8:
|
||||||
|
03:5a:73:33:ba:19:03:00:35:f5:00:bc:a8:be:14:
|
||||||
|
ce:46:69:e3:6d:ed:34:37:85:55:87:62:b3:b7:c9:
|
||||||
|
c0:cc:9a:aa:61:05:5b:cd:a2:17:42:d3:e5:6f:1c:
|
||||||
|
60:8d:c2:15:41:46:f8:12:54:d0:38:57:e1:fd:8d:
|
||||||
|
44:c8:fb:56:b3:b9:6c:e9:f8:9e:21:11:57:1b:8b:
|
||||||
|
f9:cf:e3:17:e7:d8:fd:ac:d1:01:c6:92:30:f3:2d:
|
||||||
|
c9:d6:c1:f0:3d:fd:ca:30:dd:75:74:e7:d1:6b:75:
|
||||||
|
d8:c5:4d:43:61:fe:f6:ad:7e:4c:63:7c:03:17:a2:
|
||||||
|
06:8f:d0:8b:69:d3:7a:07:0f:0b:a2:cf:0c:70:38:
|
||||||
|
ba:cc:55:35:60:84:58:d8:d2:be:1f:ef:76:a9:ba:
|
||||||
|
ae:6a:dc:08:97:80:de:42:00:b7:d4:ce:9a:b0:36:
|
||||||
|
2a:c7:6f:45:04:7c:ea:41:19:d8:b9:19:04:1f:11:
|
||||||
|
a9:22:80:bd:69:08:15:0d:3c:de:cd:7e:88:6c:0f:
|
||||||
|
a3:43
|
||||||
|
Exponent: 65537 (0x10001)
|
||||||
|
X509v3 extensions:
|
||||||
|
X509v3 Basic Constraints:
|
||||||
|
CA:FALSE
|
||||||
|
Netscape Comment:
|
||||||
|
OpenSSL Generated Certificate
|
||||||
|
X509v3 Subject Key Identifier:
|
||||||
|
CE:03:7E:EF:E7:DE:C9:87:BF:DE:56:F4:C8:A3:40:F6:C8:6F:05:8C
|
||||||
|
X509v3 Authority Key Identifier:
|
||||||
|
keyid:B8:35:37:32:BE:CF:4F:79:F5:7B:74:B2:F2:10:5A:BA:80:C5:6A:10
|
||||||
|
DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=Testing/CN=test/emailAddress=test@test.com
|
||||||
|
serial:EB:E7:64:FB:79:F7:22:19
|
||||||
|
|
||||||
|
Signature Algorithm: md5WithRSAEncryption
|
||||||
|
7a:20:93:63:40:73:7d:33:01:2e:c0:13:52:a4:a7:e1:4d:82:
|
||||||
|
f4:fb:b2:7b:d0:2b:5a:3f:0e:3c:28:61:71:ab:01:4d:fe:89:
|
||||||
|
b5:cd:2f:97:59:93:53:9d:51:86:48:dd:b9:e4:73:5e:22:0b:
|
||||||
|
12:0d:25:39:76:16:44:06:0c:40:45:21:6b:a6:b1:e0:bf:76:
|
||||||
|
1b:36:f3:1e:41:82:57:d9:59:b7:60:40:43:1c:1d:79:f6:48:
|
||||||
|
32:5c:4e:e2:06:89:96:41:d2:54:1f:4a:6f:f6:78:a5:3c:02:
|
||||||
|
85:21:e2:65:e1:8a:6d:24:19:95:f8:c0:35:ab:bd:ff:3d:f1:
|
||||||
|
fb:50:2d:30:1e:67:a6:7c:50:f9:d5:77:66:77:5a:14:0f:5c:
|
||||||
|
cd:21:09:9b:a3:92:57:19:dd:01:a4:18:c5:f9:70:e4:17:43:
|
||||||
|
8d:b1:e6:61:e9:50:89:83:4f:ce:a4:57:68:58:40:70:ae:71:
|
||||||
|
1c:47:66:d2:30:54:50:ea:3a:87:32:64:3b:18:42:fe:5a:19:
|
||||||
|
07:64:f7:f1:b1:10:07:fd:a7:d2:a7:a8:05:79:5b:25:ba:69:
|
||||||
|
7b:1a:3e:b1:3e:e4:17:17:01:ba:eb:54:ae:83:00:ed:66:62:
|
||||||
|
8d:c0:3e:8a:b4:27:5f:e9:01:ce:20:c3:34:a9:28:c0:6f:c7:
|
||||||
|
3b:65:fe:f9
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEojCCA4qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCVVMx
|
||||||
|
EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO
|
||||||
|
TXkgQ29tcGFueSBMdGQxEDAOBgNVBAsTB1Rlc3RpbmcxDTALBgNVBAMTBHRlc3Qx
|
||||||
|
HDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMzEwMTUxMzE2WhcN
|
||||||
|
MTkwMzA4MTUxMzE2WjB6MQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJl
|
||||||
|
MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzEOMAwG
|
||||||
|
A1UEAxMFdGVzdDExHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wggEiMA0G
|
||||||
|
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNNLEusATG9CuiwKA5eoLtlsT3GYOR
|
||||||
|
XLTnnN7sSOwt5FEIJkKs05gmenL3ScKeZgXGRyn+O6xrr29eqANaczO6GQMANfUA
|
||||||
|
vKi+FM5GaeNt7TQ3hVWHYrO3ycDMmqphBVvNohdC0+VvHGCNwhVBRvgSVNA4V+H9
|
||||||
|
jUTI+1azuWzp+J4hEVcbi/nP4xfn2P2s0QHGkjDzLcnWwfA9/cow3XV059FrddjF
|
||||||
|
TUNh/vatfkxjfAMXogaP0Itp03oHDwuizwxwOLrMVTVghFjY0r4f73apuq5q3AiX
|
||||||
|
gN5CALfUzpqwNirHb0UEfOpBGdi5GQQfEakigL1pCBUNPN7NfohsD6NDAgMBAAGj
|
||||||
|
ggEfMIIBGzAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy
|
||||||
|
YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUzgN+7+feyYe/3lb0yKNA9shvBYww
|
||||||
|
gcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDFahChgZGkgY4wgYsxCzAJ
|
||||||
|
BgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkx
|
||||||
|
FzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQLEwdUZXN0aW5nMQ0wCwYD
|
||||||
|
VQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA6+dk+3n3
|
||||||
|
IhkwDQYJKoZIhvcNAQEEBQADggEBAHogk2NAc30zAS7AE1Kkp+FNgvT7snvQK1o/
|
||||||
|
DjwoYXGrAU3+ibXNL5dZk1OdUYZI3bnkc14iCxINJTl2FkQGDEBFIWumseC/dhs2
|
||||||
|
8x5BglfZWbdgQEMcHXn2SDJcTuIGiZZB0lQfSm/2eKU8AoUh4mXhim0kGZX4wDWr
|
||||||
|
vf898ftQLTAeZ6Z8UPnVd2Z3WhQPXM0hCZujklcZ3QGkGMX5cOQXQ42x5mHpUImD
|
||||||
|
T86kV2hYQHCucRxHZtIwVFDqOocyZDsYQv5aGQdk9/GxEAf9p9KnqAV5WyW6aXsa
|
||||||
|
PrE+5BcXAbrrVK6DAO1mYo3APoq0J1/pAc4gwzSpKMBvxztl/vk=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
@ -4038,6 +4038,184 @@ test_nm_utils_uuid_generate_from_string (void)
|
||||||
_test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "002a0ada-f547-375a-bab5-896a11d1927e", "a\0b", 3, UUID_NS_DNS);
|
_test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "002a0ada-f547-375a-bab5-896a11d1927e", "a\0b", 3, UUID_NS_DNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
__test_uuid (const char *expected_uuid, const char *str, gssize slen, char *uuid_test)
|
||||||
|
{
|
||||||
|
g_assert (uuid_test);
|
||||||
|
g_assert (nm_utils_is_uuid (uuid_test));
|
||||||
|
|
||||||
|
if (strcmp (uuid_test, expected_uuid)) {
|
||||||
|
g_error ("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s",
|
||||||
|
str, (long long) slen, expected_uuid, uuid_test);
|
||||||
|
}
|
||||||
|
g_free (uuid_test);
|
||||||
|
|
||||||
|
uuid_test = nm_utils_uuid_generate_from_string (str, slen, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
|
||||||
|
|
||||||
|
g_assert (uuid_test);
|
||||||
|
g_assert (nm_utils_is_uuid (uuid_test));
|
||||||
|
|
||||||
|
if (strcmp (uuid_test, expected_uuid)) {
|
||||||
|
g_error ("UUID test failed (2): text=%s; len=%lld, expected=%s, uuid2=%s",
|
||||||
|
str, (long long) slen, expected_uuid, uuid_test);
|
||||||
|
}
|
||||||
|
g_free (uuid_test);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _test_uuid(expected_uuid, str, strlen, ...) __test_uuid (expected_uuid, str, strlen, _nm_utils_uuid_generate_from_strings(__VA_ARGS__, NULL))
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nm_utils_uuid_generate_from_strings (void)
|
||||||
|
{
|
||||||
|
_test_uuid ("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL);
|
||||||
|
_test_uuid ("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, "");
|
||||||
|
_test_uuid ("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a");
|
||||||
|
_test_uuid ("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0", 3, "aa");
|
||||||
|
_test_uuid ("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0", 2, "", "");
|
||||||
|
_test_uuid ("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0", 3, "a", "");
|
||||||
|
_test_uuid ("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0", 4, "aa", "");
|
||||||
|
_test_uuid ("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0", 3, "", "a");
|
||||||
|
_test_uuid ("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0", 4, "a", "a");
|
||||||
|
_test_uuid ("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0", 5, "aa", "a");
|
||||||
|
_test_uuid ("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0", 4, "", "aa");
|
||||||
|
_test_uuid ("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0", 5, "a", "aa");
|
||||||
|
_test_uuid ("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa");
|
||||||
|
_test_uuid ("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b");
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nm_utils_ascii_str_to_int64_check (const char *str, guint base, gint64 min,
|
||||||
|
gint64 max, gint64 fallback, int exp_errno,
|
||||||
|
gint64 exp_val)
|
||||||
|
{
|
||||||
|
gint64 v;
|
||||||
|
|
||||||
|
errno = 1;
|
||||||
|
v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
|
||||||
|
g_assert_cmpint (errno, ==, exp_errno);
|
||||||
|
g_assert_cmpint (v, ==, exp_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
|
||||||
|
gint64 max, gint64 fallback, int exp_errno,
|
||||||
|
gint64 exp_val)
|
||||||
|
{
|
||||||
|
const char *sign = "";
|
||||||
|
const char *val;
|
||||||
|
static const char *whitespaces[] = {
|
||||||
|
"",
|
||||||
|
" ",
|
||||||
|
"\r\n\t",
|
||||||
|
" \r\n\t ",
|
||||||
|
" \r\n\t \t\r\n\t",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
static const char *nulls[] = {
|
||||||
|
"",
|
||||||
|
"0",
|
||||||
|
"00",
|
||||||
|
"0000",
|
||||||
|
"0000000000000000",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
const char **ws_pre, **ws_post, **null;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (str == NULL || exp_errno != 0) {
|
||||||
|
test_nm_utils_ascii_str_to_int64_check (str, base, min, max, fallback, exp_errno, exp_val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp (str, "-", 1) == 0)
|
||||||
|
sign = "-";
|
||||||
|
|
||||||
|
val = str + strlen (sign);
|
||||||
|
|
||||||
|
for (ws_pre = whitespaces; *ws_pre; ws_pre++) {
|
||||||
|
for (ws_post = whitespaces; *ws_post; ws_post++) {
|
||||||
|
for (null = nulls; *null; null++) {
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
char *s;
|
||||||
|
const char *str_base = "";
|
||||||
|
|
||||||
|
if (base == 16) {
|
||||||
|
if (i == 1)
|
||||||
|
str_base = "0x";
|
||||||
|
else if (i > 1)
|
||||||
|
break;
|
||||||
|
} else if (base == 8) {
|
||||||
|
if (i == 1)
|
||||||
|
str_base = "0";
|
||||||
|
else if (i > 1)
|
||||||
|
break;
|
||||||
|
} else if (base == 0) {
|
||||||
|
if (i > 0)
|
||||||
|
break;
|
||||||
|
/* with base==0, a leading zero would be interpreted as octal. Only test without *null */
|
||||||
|
if ((*null)[0])
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (i > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = g_strdup_printf ("%s%s%s%s%s%s", *ws_pre, sign, str_base, *null, val, *ws_post);
|
||||||
|
|
||||||
|
test_nm_utils_ascii_str_to_int64_check (s, base, min, max, fallback, exp_errno, exp_val);
|
||||||
|
g_free (s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nm_utils_ascii_str_to_int64 (void)
|
||||||
|
{
|
||||||
|
test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("1x", 10, 0, 10000, -1, EINVAL, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("10000", 10, 0, 10000, -1, 0, 10000);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("10001", 10, 0, 10000, -1, ERANGE, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("FF", 16, 0, 10000, -1, 0, 255);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("FF", 10, 0, 10000, -2, EINVAL, -2);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("9223372036854775807", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64, 0, -2, 0, G_MININT64);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64+1, 0, -2, ERANGE, -2);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("1.0", 10, 1, 1, -1, EINVAL, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("1x0", 16, -10, 10, -100, EINVAL, -100);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("0", 16, -10, 10, -100, 0, 0);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("10001111", 2, -1000, 1000, -100000, 0, 0x8F);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("-10001111", 2, -1000, 1000, -100000, 0, -0x8F);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFF);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("11111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFF);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, 0x4000000000000000);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("1000000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, ERANGE, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7*8);
|
||||||
|
test_nm_utils_ascii_str_to_int64_do ("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
NMTST_DEFINE ();
|
NMTST_DEFINE ();
|
||||||
|
|
@ -4137,6 +4315,9 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
|
g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
|
||||||
g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
|
g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
|
||||||
|
g_test_add_func ("/core/general/_nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings);
|
||||||
|
|
||||||
|
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
512
libnm-core/tests/test-keyfile.c
Normal file
512
libnm-core/tests/test-keyfile.c
Normal file
|
|
@ -0,0 +1,512 @@
|
||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "nm-utils-internal.h"
|
||||||
|
#include "nm-keyfile-utils.h"
|
||||||
|
#include "nm-keyfile-internal.h"
|
||||||
|
|
||||||
|
#include "nm-simple-connection.h"
|
||||||
|
#include "nm-setting-connection.h"
|
||||||
|
#include "nm-setting-wired.h"
|
||||||
|
#include "nm-setting-8021x.h"
|
||||||
|
|
||||||
|
#include "nm-test-utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST_WIRED_TLS_CA_CERT TEST_CERT_DIR"/test-ca-cert.pem"
|
||||||
|
#define TEST_WIRED_TLS_PRIVKEY TEST_CERT_DIR"/test-key-and-cert.pem"
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#define CLEAR(con, keyfile) \
|
||||||
|
G_STMT_START { \
|
||||||
|
NMConnection **_con = (con); \
|
||||||
|
GKeyFile **_keyfile = (keyfile); \
|
||||||
|
\
|
||||||
|
g_clear_object (_con); \
|
||||||
|
g_clear_pointer (_keyfile, g_key_file_unref); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
static void
|
||||||
|
_assert_gbytes (GBytes *bytes, gconstpointer data, gssize len)
|
||||||
|
{
|
||||||
|
g_assert ((data && len > 0) || !len || (data && len == -1));
|
||||||
|
|
||||||
|
if (len == -1)
|
||||||
|
len = strlen (data);
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
g_assert (!bytes);
|
||||||
|
else {
|
||||||
|
g_assert_cmpint (g_bytes_get_size (bytes), ==, len);
|
||||||
|
g_assert (memcmp (g_bytes_get_data (bytes, NULL), data, len) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GKeyFile *
|
||||||
|
_keyfile_load_from_data (const char *str)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean success;
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
|
||||||
|
g_assert (str);
|
||||||
|
|
||||||
|
keyfile = g_key_file_new ();
|
||||||
|
success = g_key_file_load_from_data (keyfile, str, strlen (str), G_KEY_FILE_NONE, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
|
||||||
|
return keyfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b)
|
||||||
|
{
|
||||||
|
gs_strfreev char **groups = NULL;
|
||||||
|
guint i, j;
|
||||||
|
|
||||||
|
if (kf_a == kf_b)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
groups = g_key_file_get_groups (kf_a, NULL);
|
||||||
|
for (i = 0; groups && groups[i]; i++) {
|
||||||
|
gs_strfreev char **keys = NULL;
|
||||||
|
|
||||||
|
keys = g_key_file_get_keys (kf_a, groups[i], NULL, NULL);
|
||||||
|
if (keys) {
|
||||||
|
for (j = 0; keys[j]; j++) {
|
||||||
|
gs_free char *key_a = g_key_file_get_value (kf_a, groups[i], keys[j], NULL);
|
||||||
|
gs_free char *key_b = g_key_file_get_value (kf_b, groups[i], keys[j], NULL);
|
||||||
|
|
||||||
|
if (g_strcmp0 (key_a, key_b) != 0)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_keyfile_equals (GKeyFile *kf_a, GKeyFile *kf_b)
|
||||||
|
{
|
||||||
|
return _keyfile_a_contains_all_in_b (kf_a, kf_b) && _keyfile_a_contains_all_in_b (kf_b, kf_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_keyfile_convert (NMConnection **con,
|
||||||
|
GKeyFile **keyfile,
|
||||||
|
const char *keyfile_name,
|
||||||
|
const char *base_dir,
|
||||||
|
NMKeyfileReadHandler read_handler,
|
||||||
|
void *read_data,
|
||||||
|
NMKeyfileWriteHandler write_handler,
|
||||||
|
void *write_data,
|
||||||
|
gboolean needs_normalization)
|
||||||
|
{
|
||||||
|
NMConnection *c, *c2;
|
||||||
|
GKeyFile *k, *k2;
|
||||||
|
GError *error = NULL;
|
||||||
|
NMSetting8021x *s1, *s2;
|
||||||
|
|
||||||
|
/* convert from @con to @keyfile and check that we can make
|
||||||
|
* full round trips and obtaining the same result. */
|
||||||
|
|
||||||
|
g_assert (con);
|
||||||
|
g_assert (keyfile);
|
||||||
|
g_assert (*con || *keyfile);
|
||||||
|
|
||||||
|
if (!*keyfile) {
|
||||||
|
k = nm_keyfile_write (*con, write_handler, read_data, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (k);
|
||||||
|
*keyfile = k;
|
||||||
|
} else
|
||||||
|
k = *keyfile;
|
||||||
|
if (!*con) {
|
||||||
|
c = nm_keyfile_read (*keyfile, keyfile_name, base_dir, read_handler, read_data, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (c);
|
||||||
|
if (needs_normalization)
|
||||||
|
nmtst_assert_connection_verifies_after_normalization (c, 0, 0);
|
||||||
|
else
|
||||||
|
nmtst_assert_connection_verifies_without_normalization (c);
|
||||||
|
*con = c;
|
||||||
|
} else
|
||||||
|
c = *con;
|
||||||
|
|
||||||
|
k2 = nm_keyfile_write (c, write_handler, read_data, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (k2);
|
||||||
|
|
||||||
|
c2 = nm_keyfile_read (k, keyfile_name, base_dir, read_handler, read_data, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (c2);
|
||||||
|
if (needs_normalization)
|
||||||
|
nmtst_assert_connection_verifies_after_normalization (c2, 0, 0);
|
||||||
|
else
|
||||||
|
nmtst_assert_connection_verifies_without_normalization (c2);
|
||||||
|
|
||||||
|
s1 = nm_connection_get_setting_802_1x (*con);
|
||||||
|
s2 = nm_connection_get_setting_802_1x (c2);
|
||||||
|
if (s1 || s2) {
|
||||||
|
g_assert_cmpint (nm_setting_802_1x_get_ca_cert_scheme (s1), ==, nm_setting_802_1x_get_ca_cert_scheme (s2));
|
||||||
|
switch (nm_setting_802_1x_get_ca_cert_scheme (s1)) {
|
||||||
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
|
nmtst_assert_resolve_relative_path_equals (nm_setting_802_1x_get_ca_cert_path (s1), nm_setting_802_1x_get_ca_cert_path (s2));
|
||||||
|
break;
|
||||||
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB: {
|
||||||
|
GBytes *b1, *b2;
|
||||||
|
|
||||||
|
b1 = nm_setting_802_1x_get_ca_cert_blob (s1);
|
||||||
|
b2 = nm_setting_802_1x_get_ca_cert_blob (s2);
|
||||||
|
g_assert_cmpint (g_bytes_get_size (b1), ==, g_bytes_get_size (b2));
|
||||||
|
g_assert (memcmp (g_bytes_get_data (b1, NULL), g_bytes_get_data (b2, NULL), g_bytes_get_size (b1)) == 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nmtst_assert_connection_equals (c2, FALSE, *con, FALSE);
|
||||||
|
_keyfile_equals (k2, *keyfile);
|
||||||
|
|
||||||
|
g_object_unref (c2);
|
||||||
|
g_key_file_unref (k2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_test_8021x_cert_check (NMConnection *con,
|
||||||
|
NMSetting8021xCKScheme expected_scheme,
|
||||||
|
const void *value,
|
||||||
|
gssize val_len)
|
||||||
|
{
|
||||||
|
GKeyFile *keyfile = NULL;
|
||||||
|
NMSetting8021x *s_8021x;
|
||||||
|
gs_free char *kval = NULL;
|
||||||
|
|
||||||
|
_keyfile_convert (&con, &keyfile, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
|
||||||
|
|
||||||
|
s_8021x = nm_connection_get_setting_802_1x (con);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == expected_scheme);
|
||||||
|
|
||||||
|
if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||||
|
const char *path = nm_setting_802_1x_get_ca_cert_path (s_8021x);
|
||||||
|
|
||||||
|
g_assert_cmpstr (path, ==, value);
|
||||||
|
g_assert (val_len == -1 || strlen (path) == val_len);
|
||||||
|
|
||||||
|
kval = g_key_file_get_string (keyfile, "802-1x", "ca-cert", NULL);
|
||||||
|
g_assert (kval);
|
||||||
|
g_assert_cmpstr (kval, ==, value);
|
||||||
|
} else if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
|
GBytes *blob = nm_setting_802_1x_get_ca_cert_blob (s_8021x);
|
||||||
|
gs_free char *file_blob = NULL;
|
||||||
|
|
||||||
|
if (val_len == -1) {
|
||||||
|
gsize l;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
success = g_file_get_contents (value, &file_blob, &l, NULL);
|
||||||
|
g_assert (success);
|
||||||
|
|
||||||
|
value = file_blob;
|
||||||
|
val_len = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (blob);
|
||||||
|
g_assert_cmpint (g_bytes_get_size (blob), ==, val_len);
|
||||||
|
g_assert (!memcmp (g_bytes_get_data (blob, NULL), value, val_len));
|
||||||
|
|
||||||
|
kval = g_key_file_get_string (keyfile, "802-1x", "ca-cert", NULL);
|
||||||
|
g_assert (kval);
|
||||||
|
g_assert (g_str_has_prefix (kval, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_key_file_unref (keyfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_test_8021x_cert_check_blob_full (NMConnection *con, const void *data, gsize len)
|
||||||
|
{
|
||||||
|
GBytes *bytes;
|
||||||
|
NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x (con);
|
||||||
|
|
||||||
|
bytes = g_bytes_new (data, len);
|
||||||
|
g_object_set (s_8021x,
|
||||||
|
NM_SETTING_802_1X_CA_CERT,
|
||||||
|
bytes,
|
||||||
|
NULL);
|
||||||
|
_test_8021x_cert_check (con, NM_SETTING_802_1X_CK_SCHEME_BLOB, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
}
|
||||||
|
#define _test_8021x_cert_check_blob(con, data) _test_8021x_cert_check_blob_full(con, data, STRLEN (data))
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_8021x_cert (void)
|
||||||
|
{
|
||||||
|
NMSetting8021x *s_8021x;
|
||||||
|
gs_unref_object NMConnection *con = nmtst_create_minimal_connection ("test-cert", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean success;
|
||||||
|
NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH;
|
||||||
|
gs_free char *full_TEST_WIRED_TLS_CA_CERT = nmtst_file_resolve_relative_path (TEST_WIRED_TLS_CA_CERT, NULL);
|
||||||
|
gs_free char *full_TEST_WIRED_TLS_PRIVKEY = nmtst_file_resolve_relative_path (TEST_WIRED_TLS_PRIVKEY, NULL);
|
||||||
|
|
||||||
|
/* test writing/reading of certificates of NMSetting8021x */
|
||||||
|
|
||||||
|
/* create a valid connection with NMSetting8021x */
|
||||||
|
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
|
||||||
|
nm_setting_802_1x_add_eap_method (s_8021x, "tls");
|
||||||
|
g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL);
|
||||||
|
success = nm_setting_802_1x_set_ca_cert (s_8021x,
|
||||||
|
full_TEST_WIRED_TLS_CA_CERT,
|
||||||
|
scheme,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
success = nm_setting_802_1x_set_client_cert (s_8021x,
|
||||||
|
full_TEST_WIRED_TLS_CA_CERT,
|
||||||
|
scheme,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
success = nm_setting_802_1x_set_private_key (s_8021x,
|
||||||
|
full_TEST_WIRED_TLS_PRIVKEY,
|
||||||
|
"test1",
|
||||||
|
scheme,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
|
||||||
|
|
||||||
|
/* test reseting ca-cert to different values and see whether we can write/read. */
|
||||||
|
|
||||||
|
nm_connection_add_setting (con, NM_SETTING (s_8021x));
|
||||||
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
||||||
|
|
||||||
|
|
||||||
|
_test_8021x_cert_check (con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1);
|
||||||
|
|
||||||
|
scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
||||||
|
success = nm_setting_802_1x_set_ca_cert (s_8021x,
|
||||||
|
full_TEST_WIRED_TLS_CA_CERT,
|
||||||
|
scheme,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
_test_8021x_cert_check (con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1);
|
||||||
|
|
||||||
|
_test_8021x_cert_check_blob (con, "a");
|
||||||
|
_test_8021x_cert_check_blob (con, "\0");
|
||||||
|
_test_8021x_cert_check_blob (con, "10");
|
||||||
|
_test_8021x_cert_check_blob (con, "data:;base64,a");
|
||||||
|
_test_8021x_cert_check_blob_full (con, "data:;base64,a", STRLEN ("data:;base64,a") + 1);
|
||||||
|
_test_8021x_cert_check_blob (con, "data:;base64,file://a");
|
||||||
|
_test_8021x_cert_check_blob (con, "123");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_8021x_cert_read (void)
|
||||||
|
{
|
||||||
|
GKeyFile *keyfile = NULL;
|
||||||
|
gs_unref_object NMConnection *con = NULL;
|
||||||
|
NMSetting8021x *s_8021x;
|
||||||
|
|
||||||
|
con = nmtst_create_connection_from_keyfile (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=ethernet",
|
||||||
|
"/test_8021x_cert_read/test0", NULL);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
|
||||||
|
|
||||||
|
keyfile = _keyfile_load_from_data (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=ethernet"
|
||||||
|
);
|
||||||
|
_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test1", NULL, NULL, NULL, NULL, NULL, TRUE);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
|
||||||
|
keyfile = _keyfile_load_from_data (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=802-3-ethernet\n"
|
||||||
|
|
||||||
|
"[802-1x]\n"
|
||||||
|
"eap=tls;\n"
|
||||||
|
"identity=Bill Smith\n"
|
||||||
|
"ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;128;124;252;80;\n"
|
||||||
|
"client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;\n"
|
||||||
|
"private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;\n"
|
||||||
|
"private-key-password=12345testing\n"
|
||||||
|
);
|
||||||
|
_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
|
||||||
|
|
||||||
|
keyfile = _keyfile_load_from_data (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=802-3-ethernet\n"
|
||||||
|
|
||||||
|
"[802-1x]\n"
|
||||||
|
"eap=tls;\n"
|
||||||
|
"identity=Bill Smith\n"
|
||||||
|
/* unqualified strings are only recognized as path up to 500 chars*/
|
||||||
|
"ca-cert=" "/111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
"/111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
"/111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
"/111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
"/11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\n"
|
||||||
|
"client-cert=/222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221"
|
||||||
|
"/222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221"
|
||||||
|
"/222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221"
|
||||||
|
"/222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221"
|
||||||
|
"/222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222\n"
|
||||||
|
"private-key=file://"
|
||||||
|
"/333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333331"
|
||||||
|
"/333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333331"
|
||||||
|
"/333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333331"
|
||||||
|
"/333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333331"
|
||||||
|
"/33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333111111\n"
|
||||||
|
"private-key-password=12345testing\n"
|
||||||
|
);
|
||||||
|
_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
|
||||||
|
s_8021x = nm_connection_get_setting_802_1x (con);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||||
|
g_assert (g_str_has_prefix (nm_setting_802_1x_get_ca_cert_path (s_8021x), "/111111111111"));
|
||||||
|
g_assert_cmpint (strlen (nm_setting_802_1x_get_ca_cert_path (s_8021x)), ==, 499);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_client_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||||
|
g_assert (g_str_has_prefix (g_bytes_get_data (nm_setting_802_1x_get_client_cert_blob (s_8021x), NULL), "/2222222222"));
|
||||||
|
g_assert_cmpint (g_bytes_get_size (nm_setting_802_1x_get_client_cert_blob (s_8021x)), ==, 500 + 1 /* keyfile reader adds a trailing NUL */);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||||
|
g_assert (g_str_has_prefix (nm_setting_802_1x_get_private_key_path (s_8021x), "/333333333"));
|
||||||
|
g_assert_cmpint (strlen (nm_setting_802_1x_get_private_key_path (s_8021x)), ==, 505);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
|
||||||
|
|
||||||
|
keyfile = _keyfile_load_from_data (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=802-3-ethernet\n"
|
||||||
|
|
||||||
|
"[802-1x]\n"
|
||||||
|
"eap=tls;\n"
|
||||||
|
"identity=Bill Smith\n"
|
||||||
|
"ca-cert=/\n"
|
||||||
|
"client-cert=a.pem\n"
|
||||||
|
"private-key=data:;base64,aGFsbG8=\n" // hallo
|
||||||
|
"private-key-password=12345testing\n"
|
||||||
|
);
|
||||||
|
_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
|
||||||
|
s_8021x = nm_connection_get_setting_802_1x (con);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||||
|
g_assert_cmpstr (nm_setting_802_1x_get_ca_cert_path (s_8021x), ==, "/");
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_client_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||||
|
g_assert_cmpstr (nm_setting_802_1x_get_client_cert_path (s_8021x), ==, "/test_8021x_cert_read/a.pem");
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||||
|
_assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "hallo", -1);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
|
||||||
|
|
||||||
|
keyfile = _keyfile_load_from_data (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=802-3-ethernet\n"
|
||||||
|
|
||||||
|
"[802-1x]\n"
|
||||||
|
"eap=tls;\n"
|
||||||
|
"identity=Bill Smith\n"
|
||||||
|
"ca-cert=file://data:;base64,x\n"
|
||||||
|
"client-cert=abc.der\n"
|
||||||
|
"private-key=abc.deR\n"
|
||||||
|
"private-key-password=12345testing\n"
|
||||||
|
);
|
||||||
|
_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
|
||||||
|
s_8021x = nm_connection_get_setting_802_1x (con);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||||
|
g_assert_cmpstr (nm_setting_802_1x_get_ca_cert_path (s_8021x), ==, "data:;base64,x");
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_client_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||||
|
g_assert_cmpstr (nm_setting_802_1x_get_client_cert_path (s_8021x), ==, "/test_8021x_cert_read/abc.der");
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||||
|
_assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "abc.deR\0", 8);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
|
||||||
|
|
||||||
|
keyfile = _keyfile_load_from_data (
|
||||||
|
"[connection]\n"
|
||||||
|
"type=802-3-ethernet\n"
|
||||||
|
|
||||||
|
"[802-1x]\n"
|
||||||
|
"eap=tls;\n"
|
||||||
|
"identity=Bill Smith\n"
|
||||||
|
"ca-cert=104;97;108;108;111;\n" /* "hallo" without trailing NUL */
|
||||||
|
"client-cert=104;097;108;108;111;0;\n"
|
||||||
|
"private-key=hallo\n"
|
||||||
|
"private-key-password=12345testing\n"
|
||||||
|
);
|
||||||
|
_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
|
||||||
|
s_8021x = nm_connection_get_setting_802_1x (con);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||||
|
_assert_gbytes (nm_setting_802_1x_get_ca_cert_blob (s_8021x), "hallo", 5);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_client_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||||
|
_assert_gbytes (nm_setting_802_1x_get_client_cert_blob (s_8021x), "hallo\0", 6);
|
||||||
|
|
||||||
|
g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||||
|
_assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "hallo\0", 6);
|
||||||
|
CLEAR (&con, &keyfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
NMTST_DEFINE ();
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
nmtst_init (&argc, &argv, TRUE);
|
||||||
|
|
||||||
|
g_test_add_func ("/core/keyfile/test_8021x_cert", test_8021x_cert);
|
||||||
|
g_test_add_func ("/core/keyfile/test_8021x_cert_read", test_8021x_cert_read);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -57,15 +57,13 @@ compare_blob_data (const char *test,
|
||||||
g_free (contents);
|
g_free (contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SCHEME_PATH "file://"
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
check_scheme_path (GBytes *value, const char *path)
|
check_scheme_path (GBytes *value, const char *path)
|
||||||
{
|
{
|
||||||
const guint8 *p = g_bytes_get_data (value, NULL);
|
const guint8 *p = g_bytes_get_data (value, NULL);
|
||||||
|
|
||||||
g_assert (memcmp (p, SCHEME_PATH, strlen (SCHEME_PATH)) == 0);
|
g_assert (memcmp (p, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0);
|
||||||
p += strlen (SCHEME_PATH);
|
p += strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||||||
g_assert (memcmp (p, path, strlen (path)) == 0);
|
g_assert (memcmp (p, path, strlen (path)) == 0);
|
||||||
p += strlen (path);
|
p += strlen (path);
|
||||||
g_assert (*p == '\0');
|
g_assert (*p == '\0');
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "nm-utils-private.h"
|
#include "nm-utils-private.h"
|
||||||
#include "nm-setting-private.h"
|
#include "nm-setting-private.h"
|
||||||
|
#include "nm-utils-internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:nm-setting-8021x
|
* SECTION:nm-setting-8021x
|
||||||
|
|
@ -430,13 +431,52 @@ get_cert_scheme (GByteArray *array)
|
||||||
if (!array || !array->len)
|
if (!array || !array->len)
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
|
||||||
if ( (array->len > strlen (SCHEME_PATH))
|
/* interpret the blob as PATH if it starts with "file://". */
|
||||||
&& !memcmp (array->data, SCHEME_PATH, strlen (SCHEME_PATH)))
|
if ( array->len >= STRLEN (SCHEME_PATH)
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_PATH;
|
&& !memcmp (array->data, SCHEME_PATH, STRLEN (SCHEME_PATH))) {
|
||||||
|
/* But it must also be NUL terminated, contain at least
|
||||||
|
* one non-NUL character, and contain only one trailing NUL
|
||||||
|
* chracter.
|
||||||
|
* And ensure it's UTF-8 valid too so we can pass it through
|
||||||
|
* D-Bus and stuff like that. */
|
||||||
|
if ( array->len > STRLEN (SCHEME_PATH) + 1
|
||||||
|
&& array->data[array->len - 1] == '\0'
|
||||||
|
&& g_utf8_validate ((const char *) &array->data[STRLEN (SCHEME_PATH)], array->len - (STRLEN (SCHEME_PATH) + 1), NULL))
|
||||||
|
return NM_SETTING_802_1X_CK_SCHEME_PATH;
|
||||||
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
return NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
return NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GByteArray *
|
||||||
|
load_and_verify_certificate (const char *cert_path,
|
||||||
|
NMSetting8021xCKScheme scheme,
|
||||||
|
NMCryptoFileFormat *out_file_format,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||||
|
GByteArray *array;
|
||||||
|
|
||||||
|
array = crypto_load_and_verify_certificate (cert_path, &format, error);
|
||||||
|
|
||||||
|
if (!array || !array->len || format == NM_CRYPTO_FILE_FORMAT_UNKNOWN)
|
||||||
|
format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||||
|
else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
|
/* If we load the file as blob, we must ensure that the binary data does not
|
||||||
|
* start with file://. NMSetting8021x cannot represent blobs that start with
|
||||||
|
* file://.
|
||||||
|
* If that's the case, coerce the format to UNKNOWN. The callers will take care
|
||||||
|
* of that and not set the blob. */
|
||||||
|
if (get_cert_scheme (array) != NM_SETTING_802_1X_CK_SCHEME_BLOB)
|
||||||
|
format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_file_format)
|
||||||
|
*out_file_format = format;
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_setting_802_1x_get_ca_cert_scheme:
|
* nm_setting_802_1x_get_ca_cert_scheme:
|
||||||
* @setting: the #NMSetting8021x
|
* @setting: the #NMSetting8021x
|
||||||
|
|
@ -511,14 +551,16 @@ static GByteArray *
|
||||||
path_to_scheme_value (const char *path)
|
path_to_scheme_value (const char *path)
|
||||||
{
|
{
|
||||||
GByteArray *array;
|
GByteArray *array;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
g_return_val_if_fail (path != NULL, NULL);
|
g_return_val_if_fail (path != NULL && path[0], NULL);
|
||||||
|
|
||||||
/* Add the path scheme tag to the front, then the fielname */
|
len = strlen (path);
|
||||||
array = g_byte_array_sized_new (strlen (path) + strlen (SCHEME_PATH) + 1);
|
|
||||||
g_assert (array);
|
/* Add the path scheme tag to the front, then the filename */
|
||||||
|
array = g_byte_array_sized_new (len + strlen (SCHEME_PATH) + 1);
|
||||||
g_byte_array_append (array, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
g_byte_array_append (array, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
||||||
g_byte_array_append (array, (const guint8 *) path, strlen (path));
|
g_byte_array_append (array, (const guint8 *) path, len);
|
||||||
g_byte_array_append (array, (const guint8 *) "\0", 1);
|
g_byte_array_append (array, (const guint8 *) "\0", 1);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
@ -578,7 +620,7 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
/* wpa_supplicant can only use raw x509 CA certs */
|
/* wpa_supplicant can only use raw x509 CA certs */
|
||||||
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
||||||
|
|
@ -894,7 +936,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
gboolean valid = FALSE;
|
gboolean valid = FALSE;
|
||||||
|
|
||||||
|
|
@ -1159,7 +1201,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
/* wpa_supplicant can only use raw x509 CA certs */
|
/* wpa_supplicant can only use raw x509 CA certs */
|
||||||
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
|
||||||
|
|
@ -1479,7 +1521,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = crypto_load_and_verify_certificate (cert_path, &format, error);
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||||||
if (data) {
|
if (data) {
|
||||||
gboolean valid = FALSE;
|
gboolean valid = FALSE;
|
||||||
|
|
||||||
|
|
@ -2604,26 +2646,10 @@ need_secrets (NMSetting *setting)
|
||||||
static gboolean
|
static gboolean
|
||||||
verify_cert (GByteArray *array, const char *prop_name, GError **error)
|
verify_cert (GByteArray *array, const char *prop_name, GError **error)
|
||||||
{
|
{
|
||||||
if (!array)
|
if ( !array
|
||||||
|
|| get_cert_scheme (array) != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
switch (get_cert_scheme (array)) {
|
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
|
||||||
return TRUE;
|
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
|
||||||
/* For path-based schemes, verify that the path is zero-terminated */
|
|
||||||
if (array->data[array->len - 1] == '\0') {
|
|
||||||
/* And ensure it's UTF-8 valid too so we can pass it through
|
|
||||||
* D-Bus and stuff like that.
|
|
||||||
*/
|
|
||||||
if (g_utf8_validate ((const char *) (array->data + strlen (SCHEME_PATH)), -1, NULL))
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
NM_SETTING_802_1X_ERROR,
|
NM_SETTING_802_1X_ERROR,
|
||||||
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
|
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
|
||||||
|
|
|
||||||
|
|
@ -847,6 +847,7 @@ local:
|
||||||
|
|
||||||
libnm_1_2_0 {
|
libnm_1_2_0 {
|
||||||
global:
|
global:
|
||||||
|
nm_setting_802_1x_check_cert_scheme;
|
||||||
nm_setting_bridge_get_multicast_snooping;
|
nm_setting_bridge_get_multicast_snooping;
|
||||||
nm_setting_wireless_get_powersave;
|
nm_setting_wireless_get_powersave;
|
||||||
nm_utils_bond_mode_int_to_string;
|
nm_utils_bond_mode_int_to_string;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ libnm-core/crypto.c
|
||||||
libnm-core/crypto_gnutls.c
|
libnm-core/crypto_gnutls.c
|
||||||
libnm-core/crypto_nss.c
|
libnm-core/crypto_nss.c
|
||||||
libnm-core/nm-connection.c
|
libnm-core/nm-connection.c
|
||||||
|
libnm-core/nm-keyfile-reader.c
|
||||||
|
libnm-core/nm-keyfile-writer.c
|
||||||
libnm-core/nm-setting-8021x.c
|
libnm-core/nm-setting-8021x.c
|
||||||
libnm-core/nm-setting-adsl.c
|
libnm-core/nm-setting-adsl.c
|
||||||
libnm-core/nm-setting-bluetooth.c
|
libnm-core/nm-setting-bluetooth.c
|
||||||
|
|
|
||||||
|
|
@ -1798,123 +1798,6 @@ nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nm_utils_ascii_str_to_int64:
|
|
||||||
*
|
|
||||||
* A wrapper for g_ascii_strtoll, that checks whether the whole string
|
|
||||||
* can be successfully converted to a number and is within a given
|
|
||||||
* range. On any error, @fallback will be returned and %errno will be set
|
|
||||||
* to a non-zero value. On success, %errno will be set to zero, check %errno
|
|
||||||
* for errors. Any trailing or leading (ascii) white space is ignored and the
|
|
||||||
* functions is locale independent.
|
|
||||||
*
|
|
||||||
* The function is guaranteed to return a value between @min and @max
|
|
||||||
* (inclusive) or @fallback. Also, the parsing is rather strict, it does
|
|
||||||
* not allow for any unrecognized characters, except leading and trailing
|
|
||||||
* white space.
|
|
||||||
**/
|
|
||||||
gint64
|
|
||||||
nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
|
|
||||||
{
|
|
||||||
gint64 v;
|
|
||||||
size_t len;
|
|
||||||
char buf[64], *s, *str_free = NULL;
|
|
||||||
|
|
||||||
if (str) {
|
|
||||||
while (g_ascii_isspace (str[0]))
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
if (!str || !str[0]) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = strlen (str);
|
|
||||||
if (g_ascii_isspace (str[--len])) {
|
|
||||||
/* backward search the first non-ws character.
|
|
||||||
* We already know that str[0] is non-ws. */
|
|
||||||
while (g_ascii_isspace (str[--len]))
|
|
||||||
;
|
|
||||||
|
|
||||||
/* str[len] is now the last non-ws character... */
|
|
||||||
len++;
|
|
||||||
|
|
||||||
if (len >= sizeof (buf))
|
|
||||||
s = str_free = g_malloc (len + 1);
|
|
||||||
else
|
|
||||||
s = buf;
|
|
||||||
|
|
||||||
memcpy (s, str, len);
|
|
||||||
s[len] = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
g_assert (len > 0 && len < strlen (str) && len == strlen (s));
|
|
||||||
g_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len]));
|
|
||||||
g_assert (strncmp (str, s, len) == 0);
|
|
||||||
*/
|
|
||||||
|
|
||||||
str = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
v = g_ascii_strtoll (str, &s, base);
|
|
||||||
|
|
||||||
if (errno != 0)
|
|
||||||
v = fallback;
|
|
||||||
else if (s[0] != 0) {
|
|
||||||
errno = EINVAL;
|
|
||||||
v = fallback;
|
|
||||||
} else if (v > max || v < min) {
|
|
||||||
errno = ERANGE;
|
|
||||||
v = fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (str_free))
|
|
||||||
g_free (str_free);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* nm_utils_uuid_generate_from_strings:
|
|
||||||
* @string1: a variadic list of strings. Must be NULL terminated.
|
|
||||||
*
|
|
||||||
* Returns a variant3 UUID based on the concatenated C strings.
|
|
||||||
* It does not simply concatenate them, but also includes the
|
|
||||||
* terminating '\0' character. For example "a", "b", gives
|
|
||||||
* "a\0b\0".
|
|
||||||
*
|
|
||||||
* This has the advantage, that the following invocations
|
|
||||||
* all give different UUIDs: (NULL), (""), ("",""), ("","a"), ("a",""),
|
|
||||||
* ("aa"), ("aa", ""), ("", "aa"), ...
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
nm_utils_uuid_generate_from_strings (const char *string1, ...)
|
|
||||||
{
|
|
||||||
GString *str;
|
|
||||||
va_list args;
|
|
||||||
const char *s;
|
|
||||||
char *uuid;
|
|
||||||
|
|
||||||
if (!string1)
|
|
||||||
return nm_utils_uuid_generate_from_string (NULL, 0, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
|
|
||||||
|
|
||||||
str = g_string_sized_new (120); /* effectively allocates power of 2 (128)*/
|
|
||||||
|
|
||||||
g_string_append_len (str, string1, strlen (string1) + 1);
|
|
||||||
|
|
||||||
va_start (args, string1);
|
|
||||||
s = va_arg (args, const char *);
|
|
||||||
while (s) {
|
|
||||||
g_string_append_len (str, s, strlen (s) + 1);
|
|
||||||
s = va_arg (args, const char *);
|
|
||||||
}
|
|
||||||
va_end (args);
|
|
||||||
|
|
||||||
uuid = nm_utils_uuid_generate_from_string (str->str, str->len, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
|
|
||||||
|
|
||||||
g_string_free (str, TRUE);
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
static gint64 monotonic_timestamp_offset_sec;
|
static gint64 monotonic_timestamp_offset_sec;
|
||||||
|
|
|
||||||
|
|
@ -163,12 +163,6 @@ int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnect
|
||||||
|
|
||||||
void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
|
void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
|
||||||
|
|
||||||
gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
|
|
||||||
|
|
||||||
#define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905"
|
|
||||||
|
|
||||||
char *nm_utils_uuid_generate_from_strings (const char *string1, ...) G_GNUC_NULL_TERMINATED;
|
|
||||||
|
|
||||||
#define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000)
|
#define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000)
|
||||||
gint64 nm_utils_get_monotonic_timestamp_ns (void);
|
gint64 nm_utils_get_monotonic_timestamp_ns (void);
|
||||||
gint64 nm_utils_get_monotonic_timestamp_us (void);
|
gint64 nm_utils_get_monotonic_timestamp_us (void);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "nm-dhcp-listener.h"
|
#include "nm-dhcp-listener.h"
|
||||||
|
#include "nm-core-internal.h"
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
#include "nm-dbus-manager.h"
|
#include "nm-dbus-manager.h"
|
||||||
#include "nm-dbus-glib-types.h"
|
#include "nm-dbus-glib-types.h"
|
||||||
|
|
@ -132,7 +133,7 @@ handle_event (DBusGProxy *proxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_str = get_option (options, "pid");
|
pid_str = get_option (options, "pid");
|
||||||
pid = nm_utils_ascii_str_to_int64 (pid_str, 10, 0, G_MAXINT32, -1);
|
pid = _nm_utils_ascii_str_to_int64 (pid_str, 10, 0, G_MAXINT32, -1);
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
nm_log_warn (LOGD_DHCP, "DHCP event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)");
|
nm_log_warn (LOGD_DHCP, "DHCP event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)");
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "gsystem-local-alloc.h"
|
#include "gsystem-local-alloc.h"
|
||||||
|
#include "nm-core-internal.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
#include "nm-linux-platform.h"
|
#include "nm-linux-platform.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
|
|
@ -3025,7 +3026,7 @@ tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *
|
||||||
val = nm_platform_sysctl_get (path);
|
val = nm_platform_sysctl_get (path);
|
||||||
g_free (path);
|
g_free (path);
|
||||||
if (val) {
|
if (val) {
|
||||||
props->owner = nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
|
props->owner = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
|
||||||
if (errno)
|
if (errno)
|
||||||
success = FALSE;
|
success = FALSE;
|
||||||
g_free (val);
|
g_free (val);
|
||||||
|
|
@ -3036,7 +3037,7 @@ tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *
|
||||||
val = nm_platform_sysctl_get (path);
|
val = nm_platform_sysctl_get (path);
|
||||||
g_free (path);
|
g_free (path);
|
||||||
if (val) {
|
if (val) {
|
||||||
props->group = nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
|
props->group = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
|
||||||
if (errno)
|
if (errno)
|
||||||
success = FALSE;
|
success = FALSE;
|
||||||
g_free (val);
|
g_free (val);
|
||||||
|
|
@ -3049,7 +3050,7 @@ tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *
|
||||||
if (val) {
|
if (val) {
|
||||||
gint64 flags;
|
gint64 flags;
|
||||||
|
|
||||||
flags = nm_utils_ascii_str_to_int64 (val, 16, 0, G_MAXINT64, 0);
|
flags = _nm_utils_ascii_str_to_int64 (val, 16, 0, G_MAXINT64, 0);
|
||||||
if (!errno) {
|
if (!errno) {
|
||||||
#ifndef IFF_MULTI_QUEUE
|
#ifndef IFF_MULTI_QUEUE
|
||||||
const int IFF_MULTI_QUEUE = 0x0100;
|
const int IFF_MULTI_QUEUE = 0x0100;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
#include "nm-enum-types.h"
|
#include "nm-enum-types.h"
|
||||||
|
#include "nm-core-internal.h"
|
||||||
|
|
||||||
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
||||||
|
|
||||||
|
|
@ -322,7 +323,7 @@ nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gi
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nm_utils_ascii_str_to_int64 (value, base, min, max, fallback);
|
ret = _nm_utils_ascii_str_to_int64 (value, base, min, max, fallback);
|
||||||
g_free (value);
|
g_free (value);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -397,13 +397,13 @@ connection_setting_add (const GPtrArray *block,
|
||||||
prefix ? prefix : "",
|
prefix ? prefix : "",
|
||||||
iface);
|
iface);
|
||||||
|
|
||||||
uuid = nm_utils_uuid_generate_from_strings ("ibft",
|
uuid = _nm_utils_uuid_generate_from_strings ("ibft",
|
||||||
s_hwaddr,
|
s_hwaddr,
|
||||||
s_vlanid ? "V" : "v",
|
s_vlanid ? "V" : "v",
|
||||||
s_vlanid ? s_vlanid : "",
|
s_vlanid ? s_vlanid : "",
|
||||||
s_ip4addr ? "A" : "DHCP",
|
s_ip4addr ? "A" : "DHCP",
|
||||||
s_ip4addr ? s_ip4addr : "",
|
s_ip4addr ? s_ip4addr : "",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
s_con = nm_setting_connection_new ();
|
s_con = nm_setting_connection_new ();
|
||||||
g_object_set (s_con,
|
g_object_set (s_con,
|
||||||
|
|
@ -431,7 +431,7 @@ is_ibft_vlan_device (const GPtrArray *block)
|
||||||
/* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it
|
/* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it
|
||||||
* means "no VLAN".
|
* means "no VLAN".
|
||||||
*/
|
*/
|
||||||
if (nm_utils_ascii_str_to_int64 (s_vlan_id, 10, 1, 4095, -1) != -1)
|
if (_nm_utils_ascii_str_to_int64 (s_vlan_id, 10, 1, 4095, -1) != -1)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
@ -458,7 +458,7 @@ vlan_setting_add_from_block (const GPtrArray *block,
|
||||||
g_assert (vlan_id_str);
|
g_assert (vlan_id_str);
|
||||||
|
|
||||||
/* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it means "no VLAN" */
|
/* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it means "no VLAN" */
|
||||||
vlan_id = nm_utils_ascii_str_to_int64 (vlan_id_str, 10, 1, 4095, -1);
|
vlan_id = _nm_utils_ascii_str_to_int64 (vlan_id_str, 10, 1, 4095, -1);
|
||||||
if (vlan_id == -1) {
|
if (vlan_id == -1) {
|
||||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||||
"Invalid VLAN_ID '%s'", vlan_id_str);
|
"Invalid VLAN_ID '%s'", vlan_id_str);
|
||||||
|
|
|
||||||
|
|
@ -503,7 +503,7 @@ read_one_ip4_route (shvarFile *ifcfg,
|
||||||
/* Metric */
|
/* Metric */
|
||||||
value = svGetValue (ifcfg, metric_tag, FALSE);
|
value = svGetValue (ifcfg, metric_tag, FALSE);
|
||||||
if (value) {
|
if (value) {
|
||||||
metric = nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1);
|
metric = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1);
|
||||||
if (metric < 0) {
|
if (metric < 0) {
|
||||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||||
"Invalid IP4 route metric '%s'", value);
|
"Invalid IP4 route metric '%s'", value);
|
||||||
|
|
@ -3344,7 +3344,7 @@ make_wireless_setting (shvarFile *ifcfg,
|
||||||
value = svGetValue (ifcfg, "CHANNEL", FALSE);
|
value = svGetValue (ifcfg, "CHANNEL", FALSE);
|
||||||
if (value) {
|
if (value) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
chan = nm_utils_ascii_str_to_int64 (value, 10, 1, 196, 0);
|
chan = _nm_utils_ascii_str_to_int64 (value, 10, 1, 196, 0);
|
||||||
if (errno || (chan == 0)) {
|
if (errno || (chan == 0)) {
|
||||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||||
"Invalid wireless channel '%s'", value);
|
"Invalid wireless channel '%s'", value);
|
||||||
|
|
@ -4889,7 +4889,7 @@ devtimeout_from_file (const char *filename)
|
||||||
|
|
||||||
devtimeout_str = svGetValue (ifcfg, "DEVTIMEOUT", FALSE);
|
devtimeout_str = svGetValue (ifcfg, "DEVTIMEOUT", FALSE);
|
||||||
if (devtimeout_str) {
|
if (devtimeout_str) {
|
||||||
devtimeout = nm_utils_ascii_str_to_int64 (devtimeout_str, 10, 0, G_MAXUINT, 0);
|
devtimeout = _nm_utils_ascii_str_to_int64 (devtimeout_str, 10, 0, G_MAXUINT, 0);
|
||||||
g_free (devtimeout_str);
|
g_free (devtimeout_str);
|
||||||
} else
|
} else
|
||||||
devtimeout = 0;
|
devtimeout = 0;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
#include "shvar.h"
|
#include "shvar.h"
|
||||||
|
|
||||||
#include "NetworkManagerUtils.h"
|
#include "nm-core-internal.h"
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
|
|
||||||
#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg)
|
#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg)
|
||||||
|
|
@ -321,7 +321,7 @@ svTrueValue (shvarFile *s, const char *key, gboolean def)
|
||||||
* @max: the maximum for range-check
|
* @max: the maximum for range-check
|
||||||
* @fallback: the fallback value in any error case
|
* @fallback: the fallback value in any error case
|
||||||
*
|
*
|
||||||
* Reads a value @key and converts it to an integer using nm_utils_ascii_str_to_int64().
|
* Reads a value @key and converts it to an integer using _nm_utils_ascii_str_to_int64().
|
||||||
* In case of error, @errno will be set and @fallback returned. */
|
* In case of error, @errno will be set and @fallback returned. */
|
||||||
gint64
|
gint64
|
||||||
svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback)
|
svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback)
|
||||||
|
|
@ -336,7 +336,7 @@ svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 m
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = nm_utils_ascii_str_to_int64 (tmp, base, min, max, fallback);
|
result = _nm_utils_ascii_str_to_int64 (tmp, base, min, max, fallback);
|
||||||
errsv = errno;
|
errsv = errno;
|
||||||
if (errsv != 0)
|
if (errsv != 0)
|
||||||
PARSE_WARNING ("Error reading '%s' value '%s' as integer (%d)", key, tmp, errsv);
|
PARSE_WARNING ("Error reading '%s' value '%s' as integer (%d)", key, tmp, errsv);
|
||||||
|
|
|
||||||
|
|
@ -706,13 +706,13 @@ make_ip4_setting (NMConnection *connection,
|
||||||
GError *local = NULL;
|
GError *local = NULL;
|
||||||
|
|
||||||
if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
|
if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
|
||||||
metric = nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
metric = _nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
||||||
} else {
|
} else {
|
||||||
metric_str = ifnet_get_global_data ("metric");
|
metric_str = ifnet_get_global_data ("metric");
|
||||||
if (metric_str) {
|
if (metric_str) {
|
||||||
stripped = g_strdup (metric_str);
|
stripped = g_strdup (metric_str);
|
||||||
strip_string (stripped, '"');
|
strip_string (stripped, '"');
|
||||||
metric = nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
metric = _nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
||||||
g_free (stripped);
|
g_free (stripped);
|
||||||
} else
|
} else
|
||||||
metric = -1;
|
metric = -1;
|
||||||
|
|
@ -846,13 +846,13 @@ make_ip6_setting (NMConnection *connection,
|
||||||
/* metric is not per routes configuration right now
|
/* metric is not per routes configuration right now
|
||||||
* global metric is also supported (metric="x") */
|
* global metric is also supported (metric="x") */
|
||||||
if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL)
|
if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL)
|
||||||
metric = nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
metric = _nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
||||||
else {
|
else {
|
||||||
metric_str = ifnet_get_global_data ("metric");
|
metric_str = ifnet_get_global_data ("metric");
|
||||||
if (metric_str) {
|
if (metric_str) {
|
||||||
stripped = g_strdup (metric_str);
|
stripped = g_strdup (metric_str);
|
||||||
strip_string (stripped, '"');
|
strip_string (stripped, '"');
|
||||||
metric = nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
metric = _nm_utils_ascii_str_to_int64 (metric_str, 10, 0, G_MAXUINT32, -1);
|
||||||
g_free (stripped);
|
g_free (stripped);
|
||||||
} else
|
} else
|
||||||
metric = 1;
|
metric = 1;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,5 @@
|
||||||
|
|
||||||
#define KEYFILE_DIR NMCONFDIR "/system-connections"
|
#define KEYFILE_DIR NMCONFDIR "/system-connections"
|
||||||
|
|
||||||
#define VPN_SECRETS_GROUP "vpn-secrets"
|
|
||||||
|
|
||||||
#endif /* __COMMON_H__ */
|
#endif /* __COMMON_H__ */
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -8,8 +8,8 @@ type=802-3-ethernet
|
||||||
eap=tls;
|
eap=tls;
|
||||||
identity=Bill Smith
|
identity=Bill Smith
|
||||||
ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;128;124;252;80;
|
ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;128;124;252;80;
|
||||||
client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
client-cert=102;105;108;101;58;47;47;47;67;65;83;65;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
||||||
private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
private-key=102;105;108;101;58;47;47;47;67;65;83;65;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
||||||
private-key-password=12345testing
|
private-key-password=12345testing
|
||||||
|
|
||||||
[ipv4]
|
[ipv4]
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ type=802-3-ethernet
|
||||||
[802-1x]
|
[802-1x]
|
||||||
eap=tls;
|
eap=tls;
|
||||||
identity=Bill Smith
|
identity=Bill Smith
|
||||||
ca-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;67;65;47;101;97;112;116;101;115;116;95;99;97;95;99;101;114;116;46;112;101;109;0;
|
ca-cert=102;105;108;101;58;47;47;47;67;65;83;65;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;67;65;47;101;97;112;116;101;115;116;95;99;97;95;99;101;114;116;46;112;101;109;0;
|
||||||
client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
client-cert=102;105;108;101;58;47;47;47;67;65;83;65;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
||||||
private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
private-key=102;105;108;101;58;47;47;47;67;65;83;65;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
|
||||||
private-key-password=12345testing
|
private-key-password=12345testing
|
||||||
|
|
||||||
[ipv4]
|
[ipv4]
|
||||||
|
|
|
||||||
|
|
@ -100,33 +100,33 @@ test_read_valid_wired_connection (void)
|
||||||
const char *expected6_dnssearch3 = "gnu.org";
|
const char *expected6_dnssearch3 = "gnu.org";
|
||||||
|
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.addresses1*semicolon at the end*");
|
"*ipv4.addresses:*semicolon at the end*addresses1*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.addresses2*semicolon at the end*");
|
"*ipv4.addresses:*semicolon at the end*addresses2*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
"*Missing prefix length*ipv4.address4*");
|
"*missing prefix length*address4*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
"*Missing prefix length*ipv4.address5*");
|
"*missing prefix length*address5*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.routes2*semicolon at the end*");
|
"*ipv4.routes*semicolon at the end*routes2*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.routes3*semicolon at the end*");
|
"*ipv4.routes*semicolon at the end*routes3*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.routes5*semicolon at the end*");
|
"*ipv4.routes*semicolon at the end*routes5*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.routes8*semicolon at the end*");
|
"*ipv4.routes*semicolon at the end*routes8*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
"*Missing prefix length*ipv6.address4*");
|
"*missing prefix length*address4*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv6.address5*semicolon at the end*");
|
"*ipv6.address*semicolon at the end*address5*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
"*Missing prefix length*ipv6.address5*");
|
"*missing prefix length*address5*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv6.address7*semicolon at the end*");
|
"*ipv6.address*semicolon at the end*address7*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv6.routes1*semicolon at the end*");
|
"*ipv6.routes*semicolon at the end*routes1*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv6.route6*semicolon at the end*");
|
"*ipv6.route*semicolon at the end*route6*");
|
||||||
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_FILE, NULL);
|
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_FILE, NULL);
|
||||||
g_test_assert_expected_messages ();
|
g_test_assert_expected_messages ();
|
||||||
ASSERT (connection != NULL,
|
ASSERT (connection != NULL,
|
||||||
|
|
@ -773,11 +773,11 @@ test_read_wired_mac_case (void)
|
||||||
const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
|
const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
|
||||||
|
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.addresses1*semicolon at the end*");
|
"*ipv4.addresses*semicolon at the end*addresses1*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv4.addresses2*semicolon at the end*");
|
"*ipv4.addresses*semicolon at the end*addresses2*");
|
||||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
|
||||||
"*ipv6.routes1*semicolon at the end*");
|
"*ipv6.routes*semicolon at the end*routes1*");
|
||||||
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_MAC_CASE_FILE, NULL);
|
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_MAC_CASE_FILE, NULL);
|
||||||
g_test_assert_expected_messages ();
|
g_test_assert_expected_messages ();
|
||||||
ASSERT (connection != NULL,
|
ASSERT (connection != NULL,
|
||||||
|
|
@ -2127,6 +2127,10 @@ test_read_wired_8021x_tls_blob_connection (void)
|
||||||
gboolean success;
|
gboolean success;
|
||||||
GBytes *blob;
|
GBytes *blob;
|
||||||
|
|
||||||
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
|
"*<warn> keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
|
||||||
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
|
"*<warn> keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
|
||||||
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_BLOB_FILE, &error);
|
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_BLOB_FILE, &error);
|
||||||
if (connection == NULL) {
|
if (connection == NULL) {
|
||||||
g_assert (error);
|
g_assert (error);
|
||||||
|
|
@ -2174,10 +2178,10 @@ test_read_wired_8021x_tls_blob_connection (void)
|
||||||
g_assert_cmpint (g_bytes_get_size (blob), ==, 568);
|
g_assert_cmpint (g_bytes_get_size (blob), ==, 568);
|
||||||
|
|
||||||
tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
|
tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
|
||||||
g_assert_cmpstr (tmp, ==, "/home/dcbw/Desktop/certinfra/client.pem");
|
g_assert_cmpstr (tmp, ==, "/CASA/dcbw/Desktop/certinfra/client.pem");
|
||||||
|
|
||||||
tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
|
tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
|
||||||
g_assert_cmpstr (tmp, ==, "/home/dcbw/Desktop/certinfra/client.pem");
|
g_assert_cmpstr (tmp, ==, "/CASA/dcbw/Desktop/certinfra/client.pem");
|
||||||
|
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
|
|
@ -2259,6 +2263,12 @@ test_read_wired_8021x_tls_old_connection (void)
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
|
"*<warn> keyfile: 802-1x.ca-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem' does not exist*");
|
||||||
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
|
"*<warn> keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
|
||||||
|
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
|
||||||
|
"*<warn> keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
|
||||||
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_OLD_FILE, &error);
|
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_OLD_FILE, &error);
|
||||||
if (connection == NULL) {
|
if (connection == NULL) {
|
||||||
g_assert (error);
|
g_assert (error);
|
||||||
|
|
@ -2292,13 +2302,13 @@ test_read_wired_8021x_tls_old_connection (void)
|
||||||
g_assert (g_strcmp0 (tmp, "12345testing") == 0);
|
g_assert (g_strcmp0 (tmp, "12345testing") == 0);
|
||||||
|
|
||||||
tmp = nm_setting_802_1x_get_ca_cert_path (s_8021x);
|
tmp = nm_setting_802_1x_get_ca_cert_path (s_8021x);
|
||||||
g_assert (g_strcmp0 (tmp, "/home/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem") == 0);
|
g_assert (g_strcmp0 (tmp, "/CASA/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem") == 0);
|
||||||
|
|
||||||
tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
|
tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
|
||||||
g_assert (g_strcmp0 (tmp, "/home/dcbw/Desktop/certinfra/client.pem") == 0);
|
g_assert (g_strcmp0 (tmp, "/CASA/dcbw/Desktop/certinfra/client.pem") == 0);
|
||||||
|
|
||||||
tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
|
tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
|
||||||
g_assert (g_strcmp0 (tmp, "/home/dcbw/Desktop/certinfra/client.pem") == 0);
|
g_assert (g_strcmp0 (tmp, "/CASA/dcbw/Desktop/certinfra/client.pem") == 0);
|
||||||
|
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,178 +146,3 @@ nm_keyfile_plugin_utils_escape_filename (const char *filename)
|
||||||
return g_string_free (str, FALSE);;
|
return g_string_free (str, FALSE);;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *setting;
|
|
||||||
const char *alias;
|
|
||||||
} SettingAlias;
|
|
||||||
|
|
||||||
static const SettingAlias alias_list[] = {
|
|
||||||
{ NM_SETTING_WIRED_SETTING_NAME, "ethernet" },
|
|
||||||
{ NM_SETTING_WIRELESS_SETTING_NAME, "wifi" },
|
|
||||||
{ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-security" },
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *
|
|
||||||
nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name)
|
|
||||||
{
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
g_return_val_if_fail (setting_name != NULL, NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (alias_list); i++) {
|
|
||||||
if (strcmp (setting_name, alias_list[i].setting) == 0)
|
|
||||||
return alias_list[i].alias;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
nm_keyfile_plugin_get_setting_name_for_alias (const char *alias)
|
|
||||||
{
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
g_return_val_if_fail (alias != NULL, NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (alias_list); i++) {
|
|
||||||
if (strcmp (alias, alias_list[i].alias) == 0)
|
|
||||||
return alias_list[i].setting;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************/
|
|
||||||
|
|
||||||
/* List helpers */
|
|
||||||
#define DEFINE_KF_LIST_WRAPPER(stype, get_ctype, set_ctype) \
|
|
||||||
get_ctype \
|
|
||||||
nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
gsize *out_length, \
|
|
||||||
GError **error) \
|
|
||||||
{ \
|
|
||||||
get_ctype list; \
|
|
||||||
const char *alias; \
|
|
||||||
GError *local = NULL; \
|
|
||||||
\
|
|
||||||
list = g_key_file_get_##stype##_list (kf, group, key, out_length, &local); \
|
|
||||||
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \
|
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
|
||||||
if (alias) { \
|
|
||||||
g_clear_error (&local); \
|
|
||||||
list = g_key_file_get_##stype##_list (kf, alias, key, out_length, &local); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
if (local) \
|
|
||||||
g_propagate_error (error, local); \
|
|
||||||
return list; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void \
|
|
||||||
nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
set_ctype list[], \
|
|
||||||
gsize length) \
|
|
||||||
{ \
|
|
||||||
const char *alias; \
|
|
||||||
\
|
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
|
||||||
g_key_file_set_##stype##_list (kf, alias ? alias : group, key, list, length); \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_KF_LIST_WRAPPER(integer, gint*, gint);
|
|
||||||
DEFINE_KF_LIST_WRAPPER(string, gchar **, const gchar* const);
|
|
||||||
|
|
||||||
/* Single value helpers */
|
|
||||||
#define DEFINE_KF_WRAPPER(stype, get_ctype, set_ctype) \
|
|
||||||
get_ctype \
|
|
||||||
nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
GError **error) \
|
|
||||||
{ \
|
|
||||||
get_ctype val; \
|
|
||||||
const char *alias; \
|
|
||||||
GError *local = NULL; \
|
|
||||||
\
|
|
||||||
val = g_key_file_get_##stype (kf, group, key, &local); \
|
|
||||||
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \
|
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
|
||||||
if (alias) { \
|
|
||||||
g_clear_error (&local); \
|
|
||||||
val = g_key_file_get_##stype (kf, alias, key, &local); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
if (local) \
|
|
||||||
g_propagate_error (error, local); \
|
|
||||||
return val; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void \
|
|
||||||
nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
set_ctype value) \
|
|
||||||
{ \
|
|
||||||
const char *alias; \
|
|
||||||
\
|
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \
|
|
||||||
g_key_file_set_##stype (kf, alias ? alias : group, key, value); \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_KF_WRAPPER(string, gchar*, const gchar*);
|
|
||||||
DEFINE_KF_WRAPPER(integer, gint, gint);
|
|
||||||
DEFINE_KF_WRAPPER(uint64, guint64, guint64);
|
|
||||||
DEFINE_KF_WRAPPER(boolean, gboolean, gboolean);
|
|
||||||
DEFINE_KF_WRAPPER(value, gchar*, const gchar*);
|
|
||||||
|
|
||||||
|
|
||||||
gchar **
|
|
||||||
nm_keyfile_plugin_kf_get_keys (GKeyFile *kf,
|
|
||||||
const char *group,
|
|
||||||
gsize *out_length,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
gchar **keys;
|
|
||||||
const char *alias;
|
|
||||||
GError *local = NULL;
|
|
||||||
|
|
||||||
keys = g_key_file_get_keys (kf, group, out_length, &local);
|
|
||||||
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
|
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (group);
|
|
||||||
if (alias) {
|
|
||||||
g_clear_error (&local);
|
|
||||||
keys = g_key_file_get_keys (kf, alias, out_length, &local);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (local)
|
|
||||||
g_propagate_error (error, local);
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
nm_keyfile_plugin_kf_has_key (GKeyFile *kf,
|
|
||||||
const char *group,
|
|
||||||
const char *key,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
gboolean has;
|
|
||||||
const char *alias;
|
|
||||||
GError *local = NULL;
|
|
||||||
|
|
||||||
has = g_key_file_has_key (kf, group, key, &local);
|
|
||||||
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
|
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (group);
|
|
||||||
if (alias) {
|
|
||||||
g_clear_error (&local);
|
|
||||||
has = g_key_file_has_key (kf, alias, key, &local);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (local)
|
|
||||||
g_propagate_error (error, local);
|
|
||||||
return has;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#define _UTILS_H_
|
#define _UTILS_H_
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "common.h"
|
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
|
|
||||||
#define NM_KEYFILE_CONNECTION_LOG_PATH(path) str_if_set (path,"in-memory")
|
#define NM_KEYFILE_CONNECTION_LOG_PATH(path) str_if_set (path,"in-memory")
|
||||||
|
|
@ -35,55 +34,5 @@ gboolean nm_keyfile_plugin_utils_should_ignore_file (const char *filename);
|
||||||
|
|
||||||
char *nm_keyfile_plugin_utils_escape_filename (const char *filename);
|
char *nm_keyfile_plugin_utils_escape_filename (const char *filename);
|
||||||
|
|
||||||
const char *nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name);
|
|
||||||
|
|
||||||
const char *nm_keyfile_plugin_get_setting_name_for_alias (const char *alias);
|
|
||||||
|
|
||||||
/*********************************************************/
|
|
||||||
|
|
||||||
/* List helpers */
|
|
||||||
#define DEFINE_KF_LIST_WRAPPER_PROTO(stype, get_ctype, set_ctype) \
|
|
||||||
get_ctype nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
gsize *out_length, \
|
|
||||||
GError **error); \
|
|
||||||
\
|
|
||||||
void nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
set_ctype list[], \
|
|
||||||
gsize length);
|
|
||||||
DEFINE_KF_LIST_WRAPPER_PROTO(integer, gint*, gint)
|
|
||||||
DEFINE_KF_LIST_WRAPPER_PROTO(string, gchar**, const gchar* const)
|
|
||||||
|
|
||||||
/* Single-value helpers */
|
|
||||||
#define DEFINE_KF_WRAPPER_PROTO(stype, get_ctype, set_ctype) \
|
|
||||||
get_ctype nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
GError **error); \
|
|
||||||
\
|
|
||||||
void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
|
|
||||||
const char *group, \
|
|
||||||
const char *key, \
|
|
||||||
set_ctype value);
|
|
||||||
DEFINE_KF_WRAPPER_PROTO(string, gchar*, const gchar*)
|
|
||||||
DEFINE_KF_WRAPPER_PROTO(integer, gint, gint)
|
|
||||||
DEFINE_KF_WRAPPER_PROTO(uint64, guint64, guint64)
|
|
||||||
DEFINE_KF_WRAPPER_PROTO(boolean, gboolean, gboolean)
|
|
||||||
DEFINE_KF_WRAPPER_PROTO(value, gchar*, const gchar*)
|
|
||||||
|
|
||||||
/* Misc */
|
|
||||||
gchar ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf,
|
|
||||||
const char *group,
|
|
||||||
gsize *out_length,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean nm_keyfile_plugin_kf_has_key (GKeyFile *kf,
|
|
||||||
const char *group,
|
|
||||||
const char *key,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
#endif /* _UTILS_H_ */
|
#endif /* _UTILS_H_ */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Novell, Inc.
|
* Copyright (C) 2008 Novell, Inc.
|
||||||
* Copyright (C) 2008 - 2012 Red Hat, Inc.
|
* Copyright (C) 2008 - 2015 Red Hat, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -24,407 +24,20 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <nm-setting.h>
|
|
||||||
#include <nm-setting-connection.h>
|
|
||||||
#include <nm-setting-ip4-config.h>
|
|
||||||
#include <nm-setting-ip6-config.h>
|
|
||||||
#include <nm-setting-vpn.h>
|
|
||||||
#include <nm-setting-wired.h>
|
|
||||||
#include <nm-setting-wireless.h>
|
|
||||||
#include <nm-setting-ip4-config.h>
|
|
||||||
#include <nm-setting-bluetooth.h>
|
|
||||||
#include <nm-setting-8021x.h>
|
|
||||||
#include <nm-utils.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include "nm-glib-compat.h"
|
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
#include "writer.h"
|
#include "writer.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "nm-keyfile-internal.h"
|
||||||
|
|
||||||
/* Some setting properties also contain setting names, such as
|
|
||||||
* NMSettingConnection's 'type' property (which specifies the base type of the
|
|
||||||
* connection, eg ethernet or wifi) or the 802-11-wireless setting's
|
|
||||||
* 'security' property which specifies whether or not the AP requires
|
|
||||||
* encrpytion. This function handles translating those properties' values
|
|
||||||
* from the real setting name to the more-readable alias.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
setting_alias_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
const char *str, *alias;
|
|
||||||
|
|
||||||
str = g_value_get_string (value);
|
typedef struct {
|
||||||
alias = nm_keyfile_plugin_get_alias_for_setting_name (str);
|
const char *keyfile_dir;
|
||||||
nm_keyfile_plugin_kf_set_string (file,
|
} WriteInfo;
|
||||||
nm_setting_get_name (setting),
|
|
||||||
key,
|
|
||||||
alias ? alias : str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
write_array_of_uint (GKeyFile *file,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
GArray *array;
|
|
||||||
int i;
|
|
||||||
int *tmp_array;
|
|
||||||
|
|
||||||
array = (GArray *) g_value_get_boxed (value);
|
|
||||||
if (!array || !array->len)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
tmp_array = g_new (gint, array->len);
|
|
||||||
for (i = 0; i < array->len; i++)
|
|
||||||
tmp_array[i] = g_array_index (array, int, i);
|
|
||||||
|
|
||||||
nm_keyfile_plugin_kf_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len);
|
|
||||||
g_free (tmp_array);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dns_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
char **list;
|
|
||||||
|
|
||||||
list = g_value_get_boxed (value);
|
|
||||||
if (list && list[0]) {
|
|
||||||
nm_keyfile_plugin_kf_set_string_list (file, nm_setting_get_name (setting), key,
|
|
||||||
(const char **) list, g_strv_length (list));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_ip_values (GKeyFile *file,
|
|
||||||
const char *setting_name,
|
|
||||||
GPtrArray *array,
|
|
||||||
const char *gateway,
|
|
||||||
gboolean is_route)
|
|
||||||
{
|
|
||||||
GString *output;
|
|
||||||
int family, i;
|
|
||||||
const char *addr, *gw;
|
|
||||||
guint32 plen, metric;
|
|
||||||
char key_name[30], *key_name_idx;
|
|
||||||
|
|
||||||
if (!array->len)
|
|
||||||
return;
|
|
||||||
|
|
||||||
family = !strcmp (setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6;
|
|
||||||
|
|
||||||
strcpy (key_name, is_route ? "route" : "address");
|
|
||||||
key_name_idx = key_name + strlen (key_name);
|
|
||||||
|
|
||||||
output = g_string_sized_new (2*INET_ADDRSTRLEN + 10);
|
|
||||||
for (i = 0; i < array->len; i++) {
|
|
||||||
if (is_route) {
|
|
||||||
NMIPRoute *route = array->pdata[i];
|
|
||||||
|
|
||||||
addr = nm_ip_route_get_dest (route);
|
|
||||||
plen = nm_ip_route_get_prefix (route);
|
|
||||||
gw = nm_ip_route_get_next_hop (route);
|
|
||||||
metric = MAX (0, nm_ip_route_get_metric (route));
|
|
||||||
} else {
|
|
||||||
NMIPAddress *address = array->pdata[i];
|
|
||||||
|
|
||||||
addr = nm_ip_address_get_address (address);
|
|
||||||
plen = nm_ip_address_get_prefix (address);
|
|
||||||
gw = i == 0 ? gateway : NULL;
|
|
||||||
metric = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_set_size (output, 0);
|
|
||||||
g_string_append_printf (output, "%s/%u", addr, plen);
|
|
||||||
if (metric || gw) {
|
|
||||||
/* Older versions of the plugin do not support the form
|
|
||||||
* "a.b.c.d/plen,,metric", so, we always have to write the
|
|
||||||
* gateway, even if there isn't one.
|
|
||||||
* The current version supports reading of the above form.
|
|
||||||
*/
|
|
||||||
if (!gw) {
|
|
||||||
if (family == AF_INET)
|
|
||||||
gw = "0.0.0.0";
|
|
||||||
else
|
|
||||||
gw = "::";
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_append_printf (output, ",%s", gw);
|
|
||||||
if (metric)
|
|
||||||
g_string_append_printf (output, ",%lu", (unsigned long) metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf (key_name_idx, "%d", i + 1);
|
|
||||||
nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str);
|
|
||||||
}
|
|
||||||
g_string_free (output, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
addr_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
GPtrArray *array;
|
|
||||||
const char *setting_name = nm_setting_get_name (setting);
|
|
||||||
const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
|
|
||||||
|
|
||||||
array = (GPtrArray *) g_value_get_boxed (value);
|
|
||||||
if (array && array->len)
|
|
||||||
write_ip_values (file, setting_name, array, gateway, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ip4_addr_label_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
/* skip */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gateway_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
/* skip */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
route_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
GPtrArray *array;
|
|
||||||
const char *setting_name = nm_setting_get_name (setting);
|
|
||||||
|
|
||||||
array = (GPtrArray *) g_value_get_boxed (value);
|
|
||||||
if (array && array->len)
|
|
||||||
write_ip_values (file, setting_name, array, NULL, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_hash_of_string (GKeyFile *file,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
GHashTableIter iter;
|
|
||||||
const char *property = NULL, *data = NULL;
|
|
||||||
const char *group_name = nm_setting_get_name (setting);
|
|
||||||
gboolean vpn_secrets = FALSE;
|
|
||||||
|
|
||||||
/* Write VPN secrets out to a different group to keep them separate */
|
|
||||||
if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) {
|
|
||||||
group_name = VPN_SECRETS_GROUP;
|
|
||||||
vpn_secrets = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value));
|
|
||||||
while (g_hash_table_iter_next (&iter, (gpointer *) &property, (gpointer *) &data)) {
|
|
||||||
gboolean write_item = TRUE;
|
|
||||||
|
|
||||||
/* Handle VPN secrets specially; they are nested in the property's hash;
|
|
||||||
* we don't want to write them if the secret is not saved, not required,
|
|
||||||
* or owned by a user's secret agent.
|
|
||||||
*/
|
|
||||||
if (vpn_secrets) {
|
|
||||||
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
||||||
|
|
||||||
nm_setting_get_secret_flags (setting, property, &secret_flags, NULL);
|
|
||||||
if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
|
|
||||||
write_item = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write_item)
|
|
||||||
nm_keyfile_plugin_kf_set_string (file, group_name, property, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ssid_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
GBytes *bytes;
|
|
||||||
const guint8 *ssid_data;
|
|
||||||
gsize ssid_len;
|
|
||||||
const char *setting_name = nm_setting_get_name (setting);
|
|
||||||
gboolean new_format = TRUE;
|
|
||||||
unsigned int semicolons = 0;
|
|
||||||
int i, *tmp_array;
|
|
||||||
char *ssid;
|
|
||||||
|
|
||||||
g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
|
|
||||||
|
|
||||||
bytes = g_value_get_boxed (value);
|
|
||||||
if (!bytes)
|
|
||||||
return;
|
|
||||||
ssid_data = g_bytes_get_data (bytes, &ssid_len);
|
|
||||||
if (ssid_len == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Check whether each byte is printable. If not, we have to use an
|
|
||||||
* integer list, otherwise we can just use a string.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ssid_len; i++) {
|
|
||||||
char c = ssid_data[i] & 0xFF;
|
|
||||||
if (!g_ascii_isprint (c)) {
|
|
||||||
new_format = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c == ';')
|
|
||||||
semicolons++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_format) {
|
|
||||||
ssid = g_malloc0 (ssid_len + semicolons + 1);
|
|
||||||
if (semicolons == 0)
|
|
||||||
memcpy (ssid, ssid_data, ssid_len);
|
|
||||||
else {
|
|
||||||
/* Escape semicolons with backslashes to make strings
|
|
||||||
* containing ';', such as '16;17;' unambiguous */
|
|
||||||
int j = 0;
|
|
||||||
for (i = 0; i < ssid_len; i++) {
|
|
||||||
if (ssid_data[i] == ';')
|
|
||||||
ssid[j++] = '\\';
|
|
||||||
ssid[j++] = ssid_data[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nm_keyfile_plugin_kf_set_string (file, setting_name, key, ssid);
|
|
||||||
g_free (ssid);
|
|
||||||
} else {
|
|
||||||
tmp_array = g_new (gint, ssid_len);
|
|
||||||
for (i = 0; i < ssid_len; i++)
|
|
||||||
tmp_array[i] = (int) ssid_data[i];
|
|
||||||
nm_keyfile_plugin_kf_set_integer_list (file, setting_name, key, tmp_array, ssid_len);
|
|
||||||
g_free (tmp_array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
password_raw_writer (GKeyFile *file,
|
|
||||||
const char *keyfile_dir,
|
|
||||||
const char *uuid,
|
|
||||||
NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value)
|
|
||||||
{
|
|
||||||
const char *setting_name = nm_setting_get_name (setting);
|
|
||||||
GBytes *array;
|
|
||||||
int *tmp_array;
|
|
||||||
gsize i, len;
|
|
||||||
const char *data;
|
|
||||||
|
|
||||||
g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
|
|
||||||
|
|
||||||
array = (GBytes *) g_value_get_boxed (value);
|
|
||||||
if (!array)
|
|
||||||
return;
|
|
||||||
data = g_bytes_get_data (array, &len);
|
|
||||||
if (!data || !len)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tmp_array = g_new (gint, len);
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
tmp_array[i] = (int) data[i];
|
|
||||||
nm_keyfile_plugin_kf_set_integer_list (file, setting_name, key, tmp_array, len);
|
|
||||||
g_free (tmp_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct ObjectType {
|
|
||||||
const char *key;
|
|
||||||
const char *suffix;
|
|
||||||
const char *privkey_pw_prop;
|
|
||||||
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
|
|
||||||
NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
|
|
||||||
const char * (*path_func) (NMSetting8021x *setting);
|
|
||||||
GBytes * (*blob_func) (NMSetting8021x *setting);
|
|
||||||
} ObjectType;
|
|
||||||
|
|
||||||
static const ObjectType objtypes[10] = {
|
|
||||||
{ NM_SETTING_802_1X_CA_CERT,
|
|
||||||
"ca-cert",
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_ca_cert_scheme,
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_ca_cert_path,
|
|
||||||
nm_setting_802_1x_get_ca_cert_blob },
|
|
||||||
|
|
||||||
{ NM_SETTING_802_1X_PHASE2_CA_CERT,
|
|
||||||
"inner-ca-cert",
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_phase2_ca_cert_scheme,
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_phase2_ca_cert_path,
|
|
||||||
nm_setting_802_1x_get_phase2_ca_cert_blob },
|
|
||||||
|
|
||||||
{ NM_SETTING_802_1X_CLIENT_CERT,
|
|
||||||
"client-cert",
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_client_cert_scheme,
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_client_cert_path,
|
|
||||||
nm_setting_802_1x_get_client_cert_blob },
|
|
||||||
|
|
||||||
{ NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
|
||||||
"inner-client-cert",
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_phase2_client_cert_scheme,
|
|
||||||
NULL,
|
|
||||||
nm_setting_802_1x_get_phase2_client_cert_path,
|
|
||||||
nm_setting_802_1x_get_phase2_client_cert_blob },
|
|
||||||
|
|
||||||
{ NM_SETTING_802_1X_PRIVATE_KEY,
|
|
||||||
"private-key",
|
|
||||||
NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
|
|
||||||
nm_setting_802_1x_get_private_key_scheme,
|
|
||||||
nm_setting_802_1x_get_private_key_format,
|
|
||||||
nm_setting_802_1x_get_private_key_path,
|
|
||||||
nm_setting_802_1x_get_private_key_blob },
|
|
||||||
|
|
||||||
{ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
|
||||||
"inner-private-key",
|
|
||||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
|
|
||||||
nm_setting_802_1x_get_phase2_private_key_scheme,
|
|
||||||
nm_setting_802_1x_get_phase2_private_key_format,
|
|
||||||
nm_setting_802_1x_get_phase2_private_key_path,
|
|
||||||
nm_setting_802_1x_get_phase2_private_key_blob },
|
|
||||||
|
|
||||||
{ NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
write_cert_key_file (const char *path,
|
write_cert_key_file (const char *path,
|
||||||
|
|
@ -490,61 +103,75 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cert_writer (GKeyFile *file,
|
cert_writer (NMConnection *connection,
|
||||||
const char *keyfile_dir,
|
GKeyFile *file,
|
||||||
const char *uuid,
|
NMKeyfileWriteTypeDataCert *cert_data,
|
||||||
NMSetting *setting,
|
WriteInfo *info,
|
||||||
const char *key,
|
GError **error)
|
||||||
const GValue *value)
|
|
||||||
{
|
{
|
||||||
const char *setting_name = nm_setting_get_name (setting);
|
const char *setting_name = nm_setting_get_name (NM_SETTING (cert_data->setting));
|
||||||
NMSetting8021xCKScheme scheme;
|
NMSetting8021xCKScheme scheme;
|
||||||
NMSetting8021xCKFormat format;
|
NMSetting8021xCKFormat format;
|
||||||
const char *path = NULL, *ext = "pem";
|
const char *path = NULL, *ext = "pem";
|
||||||
const ObjectType *objtype = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (objtypes) && objtypes[i].key; i++) {
|
scheme = cert_data->scheme_func (cert_data->setting);
|
||||||
if (g_strcmp0 (objtypes[i].key, key) == 0) {
|
|
||||||
objtype = &objtypes[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!objtype) {
|
|
||||||
g_return_if_fail (objtype);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
scheme = objtype->scheme_func (NM_SETTING_802_1X (setting));
|
|
||||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||||
path = objtype->path_func (NM_SETTING_802_1X (setting));
|
char *tmp = NULL;
|
||||||
|
const char *accepted_path = NULL;
|
||||||
|
|
||||||
|
path = cert_data->path_func (cert_data->setting);
|
||||||
g_assert (path);
|
g_assert (path);
|
||||||
|
|
||||||
/* If the path is rooted in the keyfile directory, just use a
|
if (g_str_has_prefix (path, info->keyfile_dir)) {
|
||||||
* relative path instead of an absolute one.
|
const char *p = path + strlen (info->keyfile_dir);
|
||||||
*/
|
|
||||||
if (g_str_has_prefix (path, keyfile_dir)) {
|
/* If the path is rooted in the keyfile directory, just use a
|
||||||
path += strlen (keyfile_dir);
|
* relative path instead of an absolute one.
|
||||||
while (*path == '/')
|
*/
|
||||||
path++;
|
if (*p == '/') {
|
||||||
|
while (*p == '/')
|
||||||
|
p++;
|
||||||
|
if (p[0]) {
|
||||||
|
/* If @p looks like an integer list, the following detection will fail too and
|
||||||
|
* we will file:// qualify the path below. We thus avoid writing a path string
|
||||||
|
* that would be interpreted as legacy binary format by reader. */
|
||||||
|
tmp = nm_keyfile_detect_unqualified_path_scheme (info->keyfile_dir, p, -1, FALSE, NULL);
|
||||||
|
if (tmp) {
|
||||||
|
g_clear_pointer (&tmp, g_free);
|
||||||
|
accepted_path = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!accepted_path) {
|
||||||
|
/* What we are about to write, must also be understood by the reader.
|
||||||
|
* Otherwise, add a file:// prefix */
|
||||||
|
tmp = nm_keyfile_detect_unqualified_path_scheme (info->keyfile_dir, path, -1, FALSE, NULL);
|
||||||
|
if (tmp) {
|
||||||
|
g_clear_pointer (&tmp, g_free);
|
||||||
|
accepted_path = path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_keyfile_plugin_kf_set_string (file, setting_name, key, path);
|
if (!accepted_path)
|
||||||
|
accepted_path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL);
|
||||||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, accepted_path);
|
||||||
|
g_free (tmp);
|
||||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||||
GBytes *blob;
|
GBytes *blob;
|
||||||
const guint8 *blob_data;
|
const guint8 *blob_data;
|
||||||
gsize blob_len;
|
gsize blob_len;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
GError *error = NULL;
|
GError *local = NULL;
|
||||||
char *new_path;
|
char *new_path;
|
||||||
|
|
||||||
blob = objtype->blob_func (NM_SETTING_802_1X (setting));
|
blob = cert_data->blob_func (cert_data->setting);
|
||||||
g_assert (blob);
|
g_assert (blob);
|
||||||
blob_data = g_bytes_get_data (blob, &blob_len);
|
blob_data = g_bytes_get_data (blob, &blob_len);
|
||||||
|
|
||||||
if (objtype->format_func) {
|
if (cert_data->format_func) {
|
||||||
/* Get the extension for a private key */
|
/* Get the extension for a private key */
|
||||||
format = objtype->format_func (NM_SETTING_802_1X (setting));
|
format = cert_data->format_func (cert_data->setting);
|
||||||
if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
|
if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
|
||||||
ext = "p12";
|
ext = "p12";
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -556,226 +183,46 @@ cert_writer (GKeyFile *file,
|
||||||
/* Write the raw data out to the standard file so that we can use paths
|
/* Write the raw data out to the standard file so that we can use paths
|
||||||
* from now on instead of pushing around the certificate data.
|
* from now on instead of pushing around the certificate data.
|
||||||
*/
|
*/
|
||||||
new_path = g_strdup_printf ("%s/%s-%s.%s", keyfile_dir, uuid, objtype->suffix, ext);
|
new_path = g_strdup_printf ("%s/%s-%s.%s", info->keyfile_dir, nm_connection_get_uuid (connection),
|
||||||
g_assert (new_path);
|
cert_data->suffix, ext);
|
||||||
|
|
||||||
success = write_cert_key_file (new_path, blob_data, blob_len, &error);
|
success = write_cert_key_file (new_path, blob_data, blob_len, &local);
|
||||||
if (success) {
|
if (success) {
|
||||||
/* Write the path value to the keyfile */
|
/* Write the path value to the keyfile.
|
||||||
nm_keyfile_plugin_kf_set_string (file, setting_name, key, new_path);
|
* We know, that basename(new_path) starts with a UUID, hence no conflict with "data:;base64," */
|
||||||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, strrchr (new_path, '/') + 1);
|
||||||
} else {
|
} else {
|
||||||
nm_log_warn (LOGD_SETTINGS, "Failed to write certificate/key %s: %s",
|
nm_log_warn (LOGD_SETTINGS, "keyfile: %s.%s: failed to write certificate to file %s: %s",
|
||||||
new_path, error->message);
|
setting_name, cert_data->property_name, new_path, local->message);
|
||||||
g_error_free (error);
|
g_error_free (local);
|
||||||
}
|
}
|
||||||
g_free (new_path);
|
g_free (new_path);
|
||||||
} else
|
} else {
|
||||||
g_assert_not_reached ();
|
/* scheme_func() returns UNKNOWN in all other cases. The only valid case
|
||||||
|
* where a scheme is allowed to be UNKNOWN, is unsetting the value. In this
|
||||||
|
* case, we don't expect the writer to be called, because the default value
|
||||||
|
* will not be serialized.
|
||||||
|
* The only other reason for the scheme to be UNKNOWN is an invalid cert.
|
||||||
|
* But our connection verifies, so that cannot happen either. */
|
||||||
|
g_return_if_reached ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
static gboolean
|
||||||
const char *setting_name;
|
_handler_write (NMConnection *connection,
|
||||||
const char *key;
|
GKeyFile *keyfile,
|
||||||
void (*writer) (GKeyFile *keyfile,
|
NMKeyfileWriteType type,
|
||||||
const char *keyfile_dir,
|
void *type_data,
|
||||||
const char *uuid,
|
void *user_data,
|
||||||
NMSetting *setting,
|
GError **error)
|
||||||
const char *key,
|
|
||||||
const GValue *value);
|
|
||||||
} KeyWriter;
|
|
||||||
|
|
||||||
/* A table of keys that require further parsing/conversion because they are
|
|
||||||
* stored in a format that can't be automatically read using the key's type.
|
|
||||||
* i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are
|
|
||||||
* stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored
|
|
||||||
* in struct in6_addr internally, but as string in keyfiles.
|
|
||||||
*/
|
|
||||||
static KeyWriter key_writers[] = {
|
|
||||||
{ NM_SETTING_CONNECTION_SETTING_NAME,
|
|
||||||
NM_SETTING_CONNECTION_TYPE,
|
|
||||||
setting_alias_writer },
|
|
||||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_ADDRESSES,
|
|
||||||
addr_writer },
|
|
||||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
||||||
"address-labels",
|
|
||||||
ip4_addr_label_writer },
|
|
||||||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_ADDRESSES,
|
|
||||||
addr_writer },
|
|
||||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
|
||||||
gateway_writer },
|
|
||||||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
|
||||||
gateway_writer },
|
|
||||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_ROUTES,
|
|
||||||
route_writer },
|
|
||||||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_ROUTES,
|
|
||||||
route_writer },
|
|
||||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_DNS,
|
|
||||||
dns_writer },
|
|
||||||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
||||||
NM_SETTING_IP_CONFIG_DNS,
|
|
||||||
dns_writer },
|
|
||||||
{ NM_SETTING_WIRELESS_SETTING_NAME,
|
|
||||||
NM_SETTING_WIRELESS_SSID,
|
|
||||||
ssid_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_PASSWORD_RAW,
|
|
||||||
password_raw_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_CA_CERT,
|
|
||||||
cert_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_CLIENT_CERT,
|
|
||||||
cert_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_PRIVATE_KEY,
|
|
||||||
cert_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_PHASE2_CA_CERT,
|
|
||||||
cert_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
|
||||||
cert_writer },
|
|
||||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
|
||||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
|
||||||
cert_writer },
|
|
||||||
{ NULL, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GKeyFile *keyfile;
|
|
||||||
const char *keyfile_dir;
|
|
||||||
const char *uuid;
|
|
||||||
} WriteInfo;
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_setting_value (NMSetting *setting,
|
|
||||||
const char *key,
|
|
||||||
const GValue *value,
|
|
||||||
GParamFlags flag,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
WriteInfo *info = user_data;
|
if (type == NM_KEYFILE_WRITE_TYPE_CERT) {
|
||||||
const char *setting_name;
|
cert_writer (connection, keyfile,
|
||||||
GType type = G_VALUE_TYPE (value);
|
(NMKeyfileWriteTypeDataCert *) type_data,
|
||||||
KeyWriter *writer = &key_writers[0];
|
(WriteInfo *) user_data, error);
|
||||||
GParamSpec *pspec;
|
return TRUE;
|
||||||
|
|
||||||
/* Setting name gets picked up from the keyfile's section name instead */
|
|
||||||
if (!strcmp (key, NM_SETTING_NAME))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Don't write the NMSettingConnection object's 'read-only' property */
|
|
||||||
if ( NM_IS_SETTING_CONNECTION (setting)
|
|
||||||
&& !strcmp (key, NM_SETTING_CONNECTION_READ_ONLY))
|
|
||||||
return;
|
|
||||||
|
|
||||||
setting_name = nm_setting_get_name (setting);
|
|
||||||
|
|
||||||
/* If the value is the default value, remove the item from the keyfile */
|
|
||||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
|
|
||||||
if (pspec) {
|
|
||||||
if (g_param_value_defaults (pspec, (GValue *) value)) {
|
|
||||||
g_key_file_remove_key (info->keyfile, setting_name, key, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't write secrets that are owned by user secret agents or aren't
|
|
||||||
* supposed to be saved. VPN secrets are handled specially though since
|
|
||||||
* the secret flags there are in a third-level hash in the 'secrets'
|
|
||||||
* property.
|
|
||||||
*/
|
|
||||||
if (pspec && (pspec->flags & NM_SETTING_PARAM_SECRET) && !NM_IS_SETTING_VPN (setting)) {
|
|
||||||
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
||||||
|
|
||||||
if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL))
|
|
||||||
g_assert_not_reached ();
|
|
||||||
if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look through the list of handlers for non-standard format key values */
|
|
||||||
while (writer->setting_name) {
|
|
||||||
if (!strcmp (writer->setting_name, setting_name) && !strcmp (writer->key, key)) {
|
|
||||||
(*writer->writer) (info->keyfile, info->keyfile_dir, info->uuid, setting, key, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
writer++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == G_TYPE_STRING) {
|
|
||||||
const char *str;
|
|
||||||
|
|
||||||
str = g_value_get_string (value);
|
|
||||||
if (str)
|
|
||||||
nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str);
|
|
||||||
} else if (type == G_TYPE_UINT)
|
|
||||||
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value));
|
|
||||||
else if (type == G_TYPE_INT)
|
|
||||||
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, g_value_get_int (value));
|
|
||||||
else if (type == G_TYPE_UINT64) {
|
|
||||||
char *numstr;
|
|
||||||
|
|
||||||
numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value));
|
|
||||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
|
||||||
g_free (numstr);
|
|
||||||
} else if (type == G_TYPE_INT64) {
|
|
||||||
char *numstr;
|
|
||||||
|
|
||||||
numstr = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (value));
|
|
||||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
|
||||||
g_free (numstr);
|
|
||||||
} else if (type == G_TYPE_BOOLEAN) {
|
|
||||||
nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value));
|
|
||||||
} else if (type == G_TYPE_CHAR) {
|
|
||||||
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value));
|
|
||||||
} else if (type == G_TYPE_BYTES) {
|
|
||||||
GBytes *bytes;
|
|
||||||
const guint8 *data;
|
|
||||||
gsize len = 0;
|
|
||||||
|
|
||||||
bytes = g_value_get_boxed (value);
|
|
||||||
data = bytes ? g_bytes_get_data (bytes, &len) : NULL;
|
|
||||||
|
|
||||||
if (data != NULL && len > 0) {
|
|
||||||
int *tmp_array;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
tmp_array = g_new (gint, len);
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
tmp_array[i] = (int) data[i];
|
|
||||||
|
|
||||||
nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, len);
|
|
||||||
g_free (tmp_array);
|
|
||||||
}
|
|
||||||
} else if (type == G_TYPE_STRV) {
|
|
||||||
char **array;
|
|
||||||
|
|
||||||
array = (char **) g_value_get_boxed (value);
|
|
||||||
nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array));
|
|
||||||
} else if (type == G_TYPE_HASH_TABLE) {
|
|
||||||
write_hash_of_string (info->keyfile, setting, key, value);
|
|
||||||
} else if (type == G_TYPE_ARRAY) {
|
|
||||||
if (!write_array_of_uint (info->keyfile, setting, key, value)) {
|
|
||||||
nm_log_warn (LOGD_SETTINGS, "Unhandled setting property type (write) '%s/%s' : '%s'",
|
|
||||||
setting_name, key, g_type_name (type));
|
|
||||||
}
|
|
||||||
} else if (G_VALUE_HOLDS_FLAGS (value)) {
|
|
||||||
/* Flags are guint but GKeyFile has no uint reader, just uint64 */
|
|
||||||
nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value));
|
|
||||||
} else if (G_VALUE_HOLDS_ENUM (value))
|
|
||||||
nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value));
|
|
||||||
else {
|
|
||||||
nm_log_warn (LOGD_SETTINGS, "Unhandled setting property type (write) '%s/%s' : '%s'",
|
|
||||||
setting_name, key, g_type_name (type));
|
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -793,10 +240,11 @@ _internal_write_connection (NMConnection *connection,
|
||||||
gboolean success = FALSE;
|
gboolean success = FALSE;
|
||||||
char *path;
|
char *path;
|
||||||
const char *id;
|
const char *id;
|
||||||
WriteInfo info;
|
WriteInfo info = { 0 };
|
||||||
GError *local_err = NULL;
|
GError *local_err = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (!out_path || !*out_path, FALSE);
|
g_return_val_if_fail (!out_path || !*out_path, FALSE);
|
||||||
|
g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE);
|
||||||
|
|
||||||
if (!nm_connection_verify (connection, error))
|
if (!nm_connection_verify (connection, error))
|
||||||
g_return_val_if_reached (FALSE);
|
g_return_val_if_reached (FALSE);
|
||||||
|
|
@ -804,14 +252,15 @@ _internal_write_connection (NMConnection *connection,
|
||||||
id = nm_connection_get_id (connection);
|
id = nm_connection_get_id (connection);
|
||||||
g_assert (id && *id);
|
g_assert (id && *id);
|
||||||
|
|
||||||
info.keyfile = key_file = g_key_file_new ();
|
|
||||||
info.keyfile_dir = keyfile_dir;
|
info.keyfile_dir = keyfile_dir;
|
||||||
info.uuid = nm_connection_get_uuid (connection);
|
|
||||||
g_assert (info.uuid);
|
key_file = nm_keyfile_write (connection, _handler_write, &info, error);
|
||||||
nm_connection_for_each_setting_value (connection, write_setting_value, &info);
|
if (!key_file)
|
||||||
|
return FALSE;
|
||||||
data = g_key_file_to_data (key_file, &len, error);
|
data = g_key_file_to_data (key_file, &len, error);
|
||||||
|
g_key_file_unref (key_file);
|
||||||
if (!data)
|
if (!data)
|
||||||
goto out;
|
return FALSE;
|
||||||
|
|
||||||
/* If we have existing file path, use it. Else generate one from
|
/* If we have existing file path, use it. Else generate one from
|
||||||
* connection's ID.
|
* connection's ID.
|
||||||
|
|
@ -910,7 +359,6 @@ _internal_write_connection (NMConnection *connection,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_free (data);
|
g_free (data);
|
||||||
g_key_file_free (key_file);
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#ifndef _KEYFILE_PLUGIN_WRITER_H
|
#ifndef _KEYFILE_PLUGIN_WRITER_H
|
||||||
#define _KEYFILE_PLUGIN_WRITER_H
|
#define _KEYFILE_PLUGIN_WRITER_H
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <nm-connection.h>
|
#include <nm-connection.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,135 +30,6 @@
|
||||||
|
|
||||||
#include "nm-test-utils.h"
|
#include "nm-test-utils.h"
|
||||||
|
|
||||||
static void
|
|
||||||
test_nm_utils_ascii_str_to_int64_check (const char *str, guint base, gint64 min,
|
|
||||||
gint64 max, gint64 fallback, int exp_errno,
|
|
||||||
gint64 exp_val)
|
|
||||||
{
|
|
||||||
gint64 v;
|
|
||||||
|
|
||||||
errno = 1;
|
|
||||||
v = nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
|
|
||||||
g_assert_cmpint (errno, ==, exp_errno);
|
|
||||||
g_assert_cmpint (v, ==, exp_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
|
|
||||||
gint64 max, gint64 fallback, int exp_errno,
|
|
||||||
gint64 exp_val)
|
|
||||||
{
|
|
||||||
const char *sign = "";
|
|
||||||
const char *val;
|
|
||||||
static const char *whitespaces[] = {
|
|
||||||
"",
|
|
||||||
" ",
|
|
||||||
"\r\n\t",
|
|
||||||
" \r\n\t ",
|
|
||||||
" \r\n\t \t\r\n\t",
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
static const char *nulls[] = {
|
|
||||||
"",
|
|
||||||
"0",
|
|
||||||
"00",
|
|
||||||
"0000",
|
|
||||||
"0000000000000000",
|
|
||||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
const char **ws_pre, **ws_post, **null;
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (str == NULL || exp_errno != 0) {
|
|
||||||
test_nm_utils_ascii_str_to_int64_check (str, base, min, max, fallback, exp_errno, exp_val);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp (str, "-", 1) == 0)
|
|
||||||
sign = "-";
|
|
||||||
|
|
||||||
val = str + strlen (sign);
|
|
||||||
|
|
||||||
for (ws_pre = whitespaces; *ws_pre; ws_pre++) {
|
|
||||||
for (ws_post = whitespaces; *ws_post; ws_post++) {
|
|
||||||
for (null = nulls; *null; null++) {
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
char *s;
|
|
||||||
const char *str_base = "";
|
|
||||||
|
|
||||||
if (base == 16) {
|
|
||||||
if (i == 1)
|
|
||||||
str_base = "0x";
|
|
||||||
else if (i > 1)
|
|
||||||
break;
|
|
||||||
} else if (base == 8) {
|
|
||||||
if (i == 1)
|
|
||||||
str_base = "0";
|
|
||||||
else if (i > 1)
|
|
||||||
break;
|
|
||||||
} else if (base == 0) {
|
|
||||||
if (i > 0)
|
|
||||||
break;
|
|
||||||
/* with base==0, a leading zero would be interpreted as octal. Only test without *null */
|
|
||||||
if ((*null)[0])
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (i > 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = g_strdup_printf ("%s%s%s%s%s%s", *ws_pre, sign, str_base, *null, val, *ws_post);
|
|
||||||
|
|
||||||
test_nm_utils_ascii_str_to_int64_check (s, base, min, max, fallback, exp_errno, exp_val);
|
|
||||||
g_free (s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_nm_utils_ascii_str_to_int64 (void)
|
|
||||||
{
|
|
||||||
test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("1x", 10, 0, 10000, -1, EINVAL, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("10000", 10, 0, 10000, -1, 0, 10000);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("10001", 10, 0, 10000, -1, ERANGE, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("FF", 16, 0, 10000, -1, 0, 255);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("FF", 10, 0, 10000, -2, EINVAL, -2);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("9223372036854775807", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64, 0, -2, 0, G_MININT64);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64+1, 0, -2, ERANGE, -2);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("1.0", 10, 1, 1, -1, EINVAL, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("1x0", 16, -10, 10, -100, EINVAL, -100);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("0", 16, -10, 10, -100, 0, 0);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("10001111", 2, -1000, 1000, -100000, 0, 0x8F);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("-10001111", 2, -1000, 1000, -100000, 0, -0x8F);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFF);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("11111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFF);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, 0x4000000000000000);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("1000000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, ERANGE, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7*8);
|
|
||||||
test_nm_utils_ascii_str_to_int64_do ("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reference implementation for nm_utils_ip6_address_clear_host_address.
|
/* Reference implementation for nm_utils_ip6_address_clear_host_address.
|
||||||
* Taken originally from set_address_masked(), src/rdisc/nm-lndp-rdisc.c
|
* Taken originally from set_address_masked(), src/rdisc/nm-lndp-rdisc.c
|
||||||
**/
|
**/
|
||||||
|
|
@ -727,53 +598,6 @@ test_connection_sort_autoconnect_priority (void)
|
||||||
|
|
||||||
/*******************************************/
|
/*******************************************/
|
||||||
|
|
||||||
static void
|
|
||||||
__test_uuid (const char *expected_uuid, const char *str, gssize slen, char *uuid_test)
|
|
||||||
{
|
|
||||||
g_assert (uuid_test);
|
|
||||||
g_assert (nm_utils_is_uuid (uuid_test));
|
|
||||||
|
|
||||||
if (strcmp (uuid_test, expected_uuid)) {
|
|
||||||
g_error ("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s",
|
|
||||||
str, (long long) slen, expected_uuid, uuid_test);
|
|
||||||
}
|
|
||||||
g_free (uuid_test);
|
|
||||||
|
|
||||||
uuid_test = nm_utils_uuid_generate_from_string (str, slen, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
|
|
||||||
|
|
||||||
g_assert (uuid_test);
|
|
||||||
g_assert (nm_utils_is_uuid (uuid_test));
|
|
||||||
|
|
||||||
if (strcmp (uuid_test, expected_uuid)) {
|
|
||||||
g_error ("UUID test failed (2): text=%s; len=%lld, expected=%s, uuid2=%s",
|
|
||||||
str, (long long) slen, expected_uuid, uuid_test);
|
|
||||||
}
|
|
||||||
g_free (uuid_test);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define _test_uuid(expected_uuid, str, strlen, ...) __test_uuid (expected_uuid, str, strlen, nm_utils_uuid_generate_from_strings(__VA_ARGS__, NULL))
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_nm_utils_uuid_generate_from_strings (void)
|
|
||||||
{
|
|
||||||
_test_uuid ("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL);
|
|
||||||
_test_uuid ("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, "");
|
|
||||||
_test_uuid ("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a");
|
|
||||||
_test_uuid ("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0", 3, "aa");
|
|
||||||
_test_uuid ("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0", 2, "", "");
|
|
||||||
_test_uuid ("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0", 3, "a", "");
|
|
||||||
_test_uuid ("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0", 4, "aa", "");
|
|
||||||
_test_uuid ("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0", 3, "", "a");
|
|
||||||
_test_uuid ("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0", 4, "a", "a");
|
|
||||||
_test_uuid ("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0", 5, "aa", "a");
|
|
||||||
_test_uuid ("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0", 4, "", "aa");
|
|
||||||
_test_uuid ("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0", 5, "a", "aa");
|
|
||||||
_test_uuid ("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa");
|
|
||||||
_test_uuid ("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************/
|
|
||||||
|
|
||||||
static const char *_test_match_spec_all[] = {
|
static const char *_test_match_spec_all[] = {
|
||||||
"e",
|
"e",
|
||||||
"em",
|
"em",
|
||||||
|
|
@ -893,7 +717,6 @@ main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
nmtst_init_with_logging (&argc, &argv, NULL, "ALL");
|
nmtst_init_with_logging (&argc, &argv, NULL, "ALL");
|
||||||
|
|
||||||
g_test_add_func ("/general/nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
|
||||||
g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
|
g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
|
||||||
g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);
|
g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);
|
||||||
|
|
||||||
|
|
@ -908,7 +731,6 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
|
g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
|
||||||
|
|
||||||
g_test_add_func ("/general/nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings);
|
|
||||||
g_test_add_func ("/general/nm_match_spec_interface_name", test_nm_match_spec_interface_name);
|
g_test_add_func ("/general/nm_match_spec_interface_name", test_nm_match_spec_interface_name);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue