mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-23 03:04:18 +00:00
keyfile: support writing certificates as blob inside the keyfile
keyfile should become our main import/export format. It is desirable, that a keyfile can contain every aspect of a connection. For blob certificates, the writer in core daemon would always write them to a file and convert the scheme to path. This behavior is not great for a (hyptetical) `nmcli connection export` command because it would have to export them somehow outside of keyfile, e.g. by writing them to temporary files. Instead, if the write handler does not handle a certificate, use a default implementation in nm_keyfile_write() which adds the blob inside the keyfile. Interestingly, keyfile reader already supported reading certificate blobs. But this legacy format accepts the blob as arbitrary binary without marking the format and without scheme prefix. Instead of writing the binary data directly, write it with a new uri scheme "data:;base64," and encode it in base64. Also go through some lengths to make sure that whatever path keyfile plugin writes, can be read back again. That is, because keyfile writer preferably writes relative paths without prefix. Add nm_keyfile_detect_unqualified_path_scheme() to encapsulate the detection of pathnames without file:// prefix and use it to check whether the path name must be fully qualified.
This commit is contained in:
parent
a49680dacd
commit
c9a8764ad2
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -143,6 +143,7 @@ valgrind-*.log
|
|||
/libnm-core/tests/test-crypto
|
||||
/libnm-core/tests/test-settings-defaults
|
||||
/libnm-core/tests/test-general
|
||||
/libnm-core/tests/test-keyfile
|
||||
/libnm-core/tests/test-need-secrets
|
||||
/libnm-core/tests/test-secrets
|
||||
/libnm-core/tests/test-setting-8021x
|
||||
|
|
|
@ -34,6 +34,12 @@
|
|||
#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;
|
||||
|
@ -58,6 +64,7 @@ typedef gboolean (*NMKeyfileReadHandler) (GKeyFile *keyfile,
|
|||
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;
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-utils-internal.h"
|
||||
#include "gsystem-local-alloc.h"
|
||||
#include "nm-glib-compat.h"
|
||||
#include "nm-keyfile-internal.h"
|
||||
|
@ -838,23 +839,179 @@ has_cert_ext (const char *path)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
handle_as_scheme (GBytes *bytes, NMSetting *setting, const char *key)
|
||||
handle_as_scheme (KeyfileReaderInfo *info, GBytes *bytes, NMSetting *setting, const char *key)
|
||||
{
|
||||
const guint8 *data;
|
||||
gsize data_len;
|
||||
const char *data;
|
||||
gsize data_len, bin_len;
|
||||
|
||||
data = g_bytes_get_data (bytes, &data_len);
|
||||
|
||||
/* It's the PATH scheme, can just set plain data */
|
||||
if ( (data_len > strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH))
|
||||
&& g_str_has_prefix ((const char *) data, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)
|
||||
&& (data[data_len - 1] == '\0')) {
|
||||
g_object_set (setting, key, bytes, NULL);
|
||||
g_return_val_if_fail (data && data_len > 0, FALSE);
|
||||
|
||||
/* to be a scheme, @data must be a zero terminated string, which is counted by @data_len */
|
||||
if (data[data_len - 1] != '\0')
|
||||
return FALSE;
|
||||
data_len--;
|
||||
|
||||
/* It's the PATH scheme, can just set plain data.
|
||||
* In this case, @data_len includes */
|
||||
if ( data_len >= STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)
|
||||
&& g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) {
|
||||
if (nm_setting_802_1x_check_cert_scheme (data, data_len + 1, NULL) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
const char *path = &data[STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)];
|
||||
gs_free char *path_free = NULL;
|
||||
|
||||
if (path[0] != '/') {
|
||||
/* we want to read absolute paths because we use keyfile as exchange
|
||||
* between different processes which might not have the same cwd. */
|
||||
path = path_free = get_cert_path (info->base_dir, (const guint8 *) path,
|
||||
data_len - STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
|
||||
}
|
||||
|
||||
g_object_set (setting, key, bytes, NULL);
|
||||
if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
|
||||
_("certificate or key file '%s' does not exist"),
|
||||
path);
|
||||
}
|
||||
} else {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid key/cert value path \"%s\""), data);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
if ( data_len > STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)
|
||||
&& g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) {
|
||||
const char *cdata = data + STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB);
|
||||
guchar *bin;
|
||||
GBytes *bytes2;
|
||||
gsize i;
|
||||
gboolean valid_base64;
|
||||
|
||||
data_len -= STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB);
|
||||
|
||||
/* Let's be strict here. We expect valid base64, no funny stuff!!
|
||||
* We didn't write such invalid data ourselfes and refuse to read it as blob. */
|
||||
if ((valid_base64 = (data_len % 4 == 0))) {
|
||||
for (i = 0; i < data_len; i++) {
|
||||
char c = cdata[i];
|
||||
|
||||
if (!( (c >= 'a' && c <= 'z')
|
||||
|| (c >= 'A' && c <= 'Z')
|
||||
|| (c >= '0' && c <= '9')
|
||||
|| (c == '+' || c == '/'))) {
|
||||
if (c != '=' || i < data_len - 2)
|
||||
valid_base64 = FALSE;
|
||||
else {
|
||||
for (; i < data_len; i++) {
|
||||
if (cdata[i] != '=')
|
||||
valid_base64 = FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!valid_base64) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid key/cert value data:;base64, is not base64"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bin = g_base64_decode (cdata, &bin_len);
|
||||
|
||||
g_return_val_if_fail (bin_len > 0, FALSE);
|
||||
if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
/* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x.
|
||||
* In fact this is a limitation of NMSetting8021x which does not support setting blobs that start
|
||||
* with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */
|
||||
g_free (bin);
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid key/cert value data:;base64,file://"));
|
||||
} else {
|
||||
bytes2 = g_bytes_new_take (bin, bin_len);
|
||||
g_object_set (setting, key, bytes2, NULL);
|
||||
g_bytes_unref (bytes2);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char *
|
||||
nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
|
||||
gconstpointer pdata,
|
||||
gsize data_len,
|
||||
gboolean consider_exists,
|
||||
gboolean *out_exists)
|
||||
{
|
||||
const char *data = pdata;
|
||||
gboolean exists = FALSE;
|
||||
gboolean success = FALSE;
|
||||
gsize validate_len;
|
||||
char *path;
|
||||
GByteArray *tmp;
|
||||
|
||||
g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL);
|
||||
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
if (data_len == -1)
|
||||
data_len = strlen (data);
|
||||
if (data_len > 500 || data_len < 1)
|
||||
return NULL;
|
||||
|
||||
/* If there's a trailing zero tell g_utf8_validate() to validate until the zero */
|
||||
if (data[data_len - 1] == '\0') {
|
||||
/* setting it to -1, would mean we accept data to contain NUL characters before the
|
||||
* end. Don't accept any NUL in [0 .. data_len-1[ . */
|
||||
validate_len = data_len - 1;
|
||||
} else
|
||||
validate_len = data_len;
|
||||
if ( validate_len == 0
|
||||
|| g_utf8_validate ((const char *) data, validate_len, NULL) == FALSE)
|
||||
return NULL;
|
||||
|
||||
/* Might be a bare path without the file:// prefix; in that case
|
||||
* if it's an absolute path, use that, otherwise treat it as a
|
||||
* relative path to the current directory.
|
||||
*/
|
||||
|
||||
path = get_cert_path (base_dir, (const guint8 *) data, data_len);
|
||||
if ( !memchr (data, '/', data_len)
|
||||
&& !has_cert_ext (path)) {
|
||||
if (!consider_exists)
|
||||
goto out;
|
||||
exists = g_file_test (path, G_FILE_TEST_EXISTS);
|
||||
if (!exists)
|
||||
goto out;
|
||||
} else if (out_exists)
|
||||
exists = g_file_test (path, G_FILE_TEST_EXISTS);
|
||||
|
||||
/* Construct the proper value as required for the PATH scheme */
|
||||
tmp = g_byte_array_sized_new (strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + strlen (path) + 1);
|
||||
g_byte_array_append (tmp, (const guint8 *) NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
|
||||
g_byte_array_append (tmp, (const guint8 *) path, strlen (path) + 1);
|
||||
if (nm_setting_802_1x_check_cert_scheme (tmp->data, tmp->len, NULL) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
g_free (path);
|
||||
path = (char *) g_byte_array_free (tmp, FALSE);
|
||||
/* when returning TRUE, we must also be sure that @data_len does not look like
|
||||
* the deprecated format of list of integers. With this implementation that is the
|
||||
* case, as long as @consider_exists is FALSE. */
|
||||
success = TRUE;
|
||||
} else
|
||||
g_byte_array_unref (tmp);
|
||||
|
||||
out:
|
||||
if (!success) {
|
||||
g_free (path);
|
||||
return NULL;
|
||||
}
|
||||
if (out_exists)
|
||||
*out_exists = exists;
|
||||
return path;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_as_path (KeyfileReaderInfo *info,
|
||||
GBytes *bytes,
|
||||
|
@ -863,89 +1020,67 @@ handle_as_path (KeyfileReaderInfo *info,
|
|||
{
|
||||
const guint8 *data;
|
||||
gsize data_len;
|
||||
gsize validate_len;
|
||||
char *path;
|
||||
gboolean exists, success = FALSE;
|
||||
gboolean exists = FALSE;
|
||||
GBytes *val;
|
||||
|
||||
data = g_bytes_get_data (bytes, &data_len);
|
||||
if (data_len > 500 || data_len < 1)
|
||||
|
||||
path = nm_keyfile_detect_unqualified_path_scheme (info->base_dir, data, data_len, TRUE, &exists);
|
||||
if (!path)
|
||||
return FALSE;
|
||||
|
||||
/* If there's a trailing zero tell g_utf8_validate() to validate until the zero */
|
||||
if (data[data_len - 1] == '\0') {
|
||||
/* setting it to -1, would mean we accept data to contain NUL characters before the
|
||||
* end. Don't accept any NUL in [0 .. data_len-1[ . */
|
||||
validate_len = data_len - 1;
|
||||
} else
|
||||
validate_len = data_len;
|
||||
/* Construct the proper value as required for the PATH scheme */
|
||||
val = g_bytes_new_take (path, strlen (path) + 1);
|
||||
g_object_set (setting, key, val, NULL);
|
||||
|
||||
if ( validate_len == 0
|
||||
|| g_utf8_validate ((const char *) data, validate_len, NULL) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
/* Might be a bare path without the file:// prefix; in that case
|
||||
* if it's an absolute path, use that, otherwise treat it as a
|
||||
* relative path to the current directory.
|
||||
*/
|
||||
|
||||
path = get_cert_path (info->base_dir, data, data_len);
|
||||
exists = g_file_test (path, G_FILE_TEST_EXISTS);
|
||||
if ( exists
|
||||
|| memchr (data, '/', data_len)
|
||||
|| has_cert_ext (path)) {
|
||||
GByteArray *tmp;
|
||||
GBytes *val;
|
||||
|
||||
/* Construct the proper value as required for the PATH scheme */
|
||||
tmp = g_byte_array_sized_new (strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + strlen (path) + 1);
|
||||
g_byte_array_append (tmp, (const guint8 *) NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
|
||||
g_byte_array_append (tmp, (const guint8 *) path, strlen (path));
|
||||
g_byte_array_append (tmp, (const guint8 *) "\0", 1);
|
||||
val = g_byte_array_free_to_bytes (tmp);
|
||||
g_object_set (setting, key, val, NULL);
|
||||
g_bytes_unref (val);
|
||||
success = TRUE;
|
||||
|
||||
/* Warn if the certificate didn't exist */
|
||||
if (exists == FALSE)
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("certificate or key '%s' does not exist"),
|
||||
path);
|
||||
/* Warn if the certificate didn't exist */
|
||||
if (!exists) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
|
||||
_("certificate or key file '%s' does not exist"),
|
||||
path);
|
||||
}
|
||||
g_free (path);
|
||||
g_bytes_unref (val);
|
||||
|
||||
return success;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cert_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||
{
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
GBytes *bytes;
|
||||
gboolean success = FALSE;
|
||||
gs_unref_bytes GBytes *bytes = NULL;
|
||||
gsize bin_len;
|
||||
const char *bin;
|
||||
|
||||
bytes = get_bytes (info, setting_name, key, TRUE, FALSE);
|
||||
if (bytes) {
|
||||
/* Try as a path + scheme (ie, starts with "file://") */
|
||||
success = handle_as_scheme (bytes, setting, key);
|
||||
if (handle_as_scheme (info, bytes, setting, key))
|
||||
return;
|
||||
if (info->error)
|
||||
return;
|
||||
|
||||
/* If not, it might be a plain path */
|
||||
if (success == FALSE)
|
||||
success = handle_as_path (info, bytes, setting, key);
|
||||
if (handle_as_path (info, bytes, setting, key))
|
||||
return;
|
||||
if (info->error)
|
||||
goto out_error;
|
||||
return;
|
||||
|
||||
/* If neither of those two, assume blob with certificate data */
|
||||
if (success == FALSE)
|
||||
bin = g_bytes_get_data (bytes, &bin_len);
|
||||
if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
/* The blob probably starts with "file://" but contains invalid characters for a path.
|
||||
* Setting the cert data will confuse NMSetting8021x.
|
||||
* In fact, NMSetting8021x does not support setting such binary data, so just warn and
|
||||
* continue. */
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid key/cert value is not a valid blob"));
|
||||
} else
|
||||
g_object_set (setting, key, bytes, NULL);
|
||||
} else if (!info->error) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid key/cert value"));
|
||||
}
|
||||
|
||||
out_error:
|
||||
if (bytes)
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#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"
|
||||
|
@ -410,6 +411,76 @@ static const ObjectType objtypes[10] = {
|
|||
{ 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,
|
||||
|
@ -429,9 +500,6 @@ cert_writer (KeyfileWriterInfo *info,
|
|||
if (!objtype)
|
||||
g_return_if_reached ();
|
||||
|
||||
if (!info->handler)
|
||||
goto out_unhandled;
|
||||
|
||||
type_data.setting = NM_SETTING_802_1X (setting);
|
||||
type_data.property_name = key;
|
||||
type_data.suffix = objtype->suffix;
|
||||
|
@ -440,30 +508,23 @@ cert_writer (KeyfileWriterInfo *info,
|
|||
type_data.path_func = objtype->path_func;
|
||||
type_data.blob_func = objtype->blob_func;
|
||||
|
||||
if (info->handler (info->connection,
|
||||
info->keyfile,
|
||||
NM_KEYFILE_WRITE_TYPE_CERT,
|
||||
&type_data,
|
||||
info->user_data,
|
||||
&info->error))
|
||||
return;
|
||||
|
||||
out_unhandled:
|
||||
|
||||
/* scheme_func() would not return UNKNOWN, because UNKNOWN happens only
|
||||
* if the cert is unset (1) or if the cert is invalid (2).
|
||||
* (1) cannot happen, because we only reach cert_writer() for non-default
|
||||
* properties. (2) cannot happen, because we verified the connection.
|
||||
*
|
||||
* Hence, at this point we do have a certifiacte, but no default implementation
|
||||
* to write it. The handler *must* do something with these certifications. */
|
||||
if (!info->error) {
|
||||
g_set_error (&info->error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
|
||||
_("Failed to write unhandled certificate property %s.%s"),
|
||||
nm_setting_get_name (setting), key);
|
||||
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;
|
||||
|
|
|
@ -15,6 +15,7 @@ noinst_PROGRAMS = \
|
|||
test-compare \
|
||||
test-crypto \
|
||||
test-general \
|
||||
test-keyfile \
|
||||
test-secrets \
|
||||
test-setting-8021x \
|
||||
test-setting-dcb \
|
||||
|
@ -49,8 +50,10 @@ EXTRA_DIST = \
|
|||
certs/test-aes-key.pem \
|
||||
certs/test_ca_cert.der \
|
||||
certs/test_ca_cert.pem \
|
||||
certs/test-ca-cert.pem \
|
||||
certs/test-cert.p12 \
|
||||
certs/test_key_and_cert.pem \
|
||||
certs/test-key-and-cert.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-----
|
505
libnm-core/tests/test-keyfile.c
Normal file
505
libnm-core/tests/test-keyfile.c
Normal file
|
@ -0,0 +1,505 @@
|
|||
/* -*- 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;
|
||||
|
||||
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 ();
|
||||
}
|
||||
|
|
@ -70,6 +70,8 @@ _handler_read (GKeyFile *keyfile,
|
|||
level = LOGL_ERR;
|
||||
else if (warn_data->severity >= NM_KEYFILE_WARN_SEVERITY_WARN)
|
||||
level = LOGL_WARN;
|
||||
else if (warn_data->severity == NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE)
|
||||
level = LOGL_WARN;
|
||||
else
|
||||
level = LOGL_INFO;
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ type=802-3-ethernet
|
|||
eap=tls;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;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
|
||||
|
||||
[ipv4]
|
||||
|
|
|
@ -7,9 +7,9 @@ type=802-3-ethernet
|
|||
[802-1x]
|
||||
eap=tls;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;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;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
|
||||
|
||||
[ipv4]
|
||||
|
|
|
@ -2127,6 +2127,10 @@ test_read_wired_8021x_tls_blob_connection (void)
|
|||
gboolean success;
|
||||
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);
|
||||
if (connection == NULL) {
|
||||
g_assert (error);
|
||||
|
@ -2174,10 +2178,10 @@ test_read_wired_8021x_tls_blob_connection (void)
|
|||
g_assert_cmpint (g_bytes_get_size (blob), ==, 568);
|
||||
|
||||
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);
|
||||
g_assert_cmpstr (tmp, ==, "/home/dcbw/Desktop/certinfra/client.pem");
|
||||
g_assert_cmpstr (tmp, ==, "/CASA/dcbw/Desktop/certinfra/client.pem");
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
@ -2259,6 +2263,12 @@ test_read_wired_8021x_tls_old_connection (void)
|
|||
const char *tmp;
|
||||
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);
|
||||
if (connection == NULL) {
|
||||
g_assert (error);
|
||||
|
@ -2292,13 +2302,13 @@ test_read_wired_8021x_tls_old_connection (void)
|
|||
g_assert (g_strcmp0 (tmp, "12345testing") == 0);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -116,24 +116,47 @@ cert_writer (NMConnection *connection,
|
|||
|
||||
scheme = cert_data->scheme_func (cert_data->setting);
|
||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
char *tmp = NULL;
|
||||
const char *accepted_path = NULL;
|
||||
|
||||
path = cert_data->path_func (cert_data->setting);
|
||||
g_assert (path);
|
||||
|
||||
/* If the path is rooted in the keyfile directory, just use a
|
||||
* relative path instead of an absolute one.
|
||||
*/
|
||||
if (g_str_has_prefix (path, info->keyfile_dir)) {
|
||||
const char *p = path + strlen (info->keyfile_dir);
|
||||
|
||||
/* If the path is rooted in the keyfile directory, just use a
|
||||
* relative path instead of an absolute one.
|
||||
*/
|
||||
if (*p == '/') {
|
||||
while (*p == '/')
|
||||
p++;
|
||||
if (p[0])
|
||||
path = 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, cert_data->property_name, 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) {
|
||||
GBytes *blob;
|
||||
const guint8 *blob_data;
|
||||
|
@ -165,8 +188,9 @@ cert_writer (NMConnection *connection,
|
|||
|
||||
success = write_cert_key_file (new_path, blob_data, blob_len, &local);
|
||||
if (success) {
|
||||
/* Write the path value to the keyfile */
|
||||
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, new_path);
|
||||
/* Write the path value to the keyfile.
|
||||
* 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 {
|
||||
nm_log_warn (LOGD_SETTINGS, "keyfile: %s.%s: failed to write certificate to file %s: %s",
|
||||
setting_name, cert_data->property_name, new_path, local->message);
|
||||
|
|
Loading…
Reference in a new issue