mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-02 15:50:13 +01:00
"nm-cloud-setup" is supposed to work without configuration.
However, it (obviously) fetches data from the network you are connected to (which
might be untrusted or controlled by somebody malicious). The tool cannot
protect you against that, also because the meta data services uses HTTP and not
HTTPS. It means, you should run the tool only when it's suitable for your
environment, that is: in the right cloud.
Usually, the user/admin/distributor would know for which cloud the enable the tool.
It's also wasteful to repeatedly probe for the unavailable cloud.
So, instead disable all providers by default and require to opt-in by setting an
environment variable.
This can be conveniently done via `systemctl edit nm-cloud-provider.service` to
set Environment=. Of course, a image can also pre-deploy such am override file.
(cherry picked from commit ff816dec17)
245 lines
6.9 KiB
C
245 lines
6.9 KiB
C
// SPDX-License-Identifier: LGPL-2.1+
|
|
|
|
#include "nm-default.h"
|
|
|
|
#include "nmcs-provider.h"
|
|
|
|
#include "nm-cloud-setup-utils.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
|
PROP_HTTP_CLIENT,
|
|
);
|
|
|
|
typedef struct _NMCSProviderPrivate {
|
|
NMHttpClient *http_client;
|
|
} NMCSProviderPrivate;
|
|
|
|
G_DEFINE_TYPE (NMCSProvider, nmcs_provider, G_TYPE_OBJECT);
|
|
|
|
#define NMCS_PROVIDER_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMCSProvider, NMCS_IS_PROVIDER)
|
|
|
|
/*****************************************************************************/
|
|
|
|
const char *
|
|
nmcs_provider_get_name (NMCSProvider *self)
|
|
{
|
|
NMCSProviderClass *klass;
|
|
|
|
g_return_val_if_fail (NMCS_IS_PROVIDER (self), NULL);
|
|
|
|
klass = NMCS_PROVIDER_GET_CLASS (self);
|
|
nm_assert (klass->_name);
|
|
return klass->_name;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
NMHttpClient *
|
|
nmcs_provider_get_http_client (NMCSProvider *self)
|
|
{
|
|
g_return_val_if_fail (NMCS_IS_PROVIDER (self), NULL);
|
|
|
|
return NMCS_PROVIDER_GET_PRIVATE (self)->http_client;
|
|
}
|
|
|
|
GMainContext *
|
|
nmcs_provider_get_main_context (NMCSProvider *self)
|
|
{
|
|
g_return_val_if_fail (NMCS_IS_PROVIDER (self), NULL);
|
|
|
|
return nm_http_client_get_main_context (NMCS_PROVIDER_GET_PRIVATE (self)->http_client);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
nmcs_provider_detect (NMCSProvider *self,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
gs_unref_object GTask *task = NULL;
|
|
const char *env;
|
|
|
|
g_return_if_fail (NMCS_IS_PROVIDER (self));
|
|
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
|
|
|
task = nm_g_task_new (self, cancellable, nmcs_provider_detect, callback, user_data);
|
|
|
|
nmcs_wait_for_objects_register (task);
|
|
|
|
env = g_getenv (NMCS_PROVIDER_GET_CLASS (self)->_env_provider_enabled);
|
|
if (!_nm_utils_ascii_str_to_bool (env, FALSE)) {
|
|
g_task_return_error (task,
|
|
nm_utils_error_new (NM_UTILS_ERROR_UNKNOWN,
|
|
"provider is disabled"));
|
|
return;
|
|
}
|
|
|
|
NMCS_PROVIDER_GET_CLASS (self)->detect (self,
|
|
g_steal_pointer (&task));
|
|
}
|
|
|
|
gboolean
|
|
nmcs_provider_detect_finish (NMCSProvider *self,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail (NMCS_IS_PROVIDER (self), FALSE);
|
|
g_return_val_if_fail (nm_g_task_is_valid (result, self, nmcs_provider_detect), FALSE);
|
|
|
|
return g_task_propagate_boolean (G_TASK (result), error);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
NMCSProviderGetConfigIfaceData *
|
|
nmcs_provider_get_config_iface_data_new (gboolean was_requested)
|
|
{
|
|
NMCSProviderGetConfigIfaceData *iface_data;
|
|
|
|
iface_data = g_slice_new (NMCSProviderGetConfigIfaceData);
|
|
*iface_data = (NMCSProviderGetConfigIfaceData) {
|
|
.iface_idx = -1,
|
|
.was_requested = was_requested,
|
|
};
|
|
return iface_data;
|
|
}
|
|
|
|
static void
|
|
_iface_data_free (gpointer data)
|
|
{
|
|
NMCSProviderGetConfigIfaceData *iface_data = data;
|
|
|
|
g_free (iface_data->ipv4s_arr);
|
|
|
|
nm_g_slice_free (iface_data);
|
|
}
|
|
|
|
static void
|
|
_get_config_data_free (gpointer data)
|
|
{
|
|
NMCSProviderGetConfigTaskData *get_config_data = data;
|
|
|
|
if (get_config_data->extra_destroy)
|
|
get_config_data->extra_destroy (get_config_data->extra_data);
|
|
|
|
nm_clear_pointer (&get_config_data->result_dict, g_hash_table_unref);
|
|
|
|
nm_g_slice_free (get_config_data);
|
|
}
|
|
|
|
void
|
|
nmcs_provider_get_config (NMCSProvider *self,
|
|
gboolean any,
|
|
const char *const*hwaddrs,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
NMCSProviderGetConfigTaskData *get_config_data;
|
|
|
|
g_return_if_fail (NMCS_IS_PROVIDER (self));
|
|
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
|
|
|
get_config_data = g_slice_new (NMCSProviderGetConfigTaskData);
|
|
*get_config_data = (NMCSProviderGetConfigTaskData) {
|
|
.task = nm_g_task_new (self, cancellable, nmcs_provider_get_config, callback, user_data),
|
|
.any = any,
|
|
.result_dict = g_hash_table_new_full (nm_str_hash,
|
|
g_str_equal,
|
|
g_free,
|
|
_iface_data_free),
|
|
};
|
|
|
|
g_task_set_task_data (get_config_data->task, get_config_data, _get_config_data_free);
|
|
|
|
nmcs_wait_for_objects_register (get_config_data->task);
|
|
|
|
for (; hwaddrs && hwaddrs[0]; hwaddrs++) {
|
|
g_hash_table_insert (get_config_data->result_dict,
|
|
g_strdup (hwaddrs[0]),
|
|
nmcs_provider_get_config_iface_data_new (TRUE));
|
|
}
|
|
|
|
_LOGD ("get-config: starting");
|
|
|
|
NMCS_PROVIDER_GET_CLASS (self)->get_config (self, get_config_data);
|
|
}
|
|
|
|
GHashTable *
|
|
nmcs_provider_get_config_finish (NMCSProvider *self,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail (NMCS_IS_PROVIDER (self), FALSE);
|
|
g_return_val_if_fail (nm_g_task_is_valid (result, self, nmcs_provider_get_config), FALSE);
|
|
|
|
return g_task_propagate_pointer (G_TASK (result), error);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
NMCSProviderPrivate *priv = NMCS_PROVIDER_GET_PRIVATE (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_HTTP_CLIENT:
|
|
priv->http_client = g_value_dup_object (value);
|
|
g_return_if_fail (NM_IS_HTTP_CLIENT (priv->http_client));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
nmcs_provider_init (NMCSProvider *self)
|
|
{
|
|
NMCSProviderPrivate *priv;
|
|
|
|
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NMCS_TYPE_PROVIDER, NMCSProviderPrivate);
|
|
|
|
self->_priv = priv;
|
|
}
|
|
|
|
static void
|
|
dispose (GObject *object)
|
|
{
|
|
NMCSProvider *self = NMCS_PROVIDER (object);
|
|
NMCSProviderPrivate *priv = NMCS_PROVIDER_GET_PRIVATE (self);
|
|
|
|
g_clear_object (&priv->http_client);
|
|
|
|
G_OBJECT_CLASS (nmcs_provider_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
nmcs_provider_class_init (NMCSProviderClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
g_type_class_add_private (object_class, sizeof (NMCSProviderPrivate));
|
|
|
|
object_class->set_property = set_property;
|
|
object_class->dispose = dispose;
|
|
|
|
obj_properties[PROP_HTTP_CLIENT] =
|
|
g_param_spec_object (NMCS_PROVIDER_HTTP_CLIENT, "", "",
|
|
NM_TYPE_HTTP_CLIENT,
|
|
G_PARAM_WRITABLE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
|
}
|