Beispiel #1
0
static NMConnection *
build_edit_connection (NMConnection *orig_connection)
{
	NMConnection *edit_connection;
	GHashTable *settings, *secrets;
	GHashTableIter iter;
	const char *setting_name;
	NmtSyncOp op;

	edit_connection = nm_connection_duplicate (orig_connection);

	if (!NM_IS_REMOTE_CONNECTION (orig_connection))
		return edit_connection;

	settings = nm_connection_to_hash (orig_connection, NM_SETTING_HASH_FLAG_NO_SECRETS);
	g_hash_table_iter_init (&iter, settings);
	while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, NULL)) {
		nmt_sync_op_init (&op);
		nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (orig_connection),
		                                  setting_name, got_secrets, &op);
		/* FIXME: error handling */
		secrets = nmt_sync_op_wait_pointer (&op, NULL);
		if (secrets)
			(void) nm_connection_update_secrets (edit_connection, setting_name, secrets, NULL);
	}
	g_hash_table_unref (settings);

	return edit_connection;
}
static void
vpn_export_get_secrets_cb (GObject *object,
                           GAsyncResult *result,
                           gpointer user_data)
{
	NMConnection *tmp;
	GVariant *secrets;
	GError *error = NULL;

	secrets = nm_remote_connection_get_secrets_finish (NM_REMOTE_CONNECTION (object),
	                                                   result, &error);

	/* We don't really care about errors; if the user couldn't authenticate
	 * then just let them export everything except secrets.  Duplicate the
	 * connection so that we don't let secrets sit around in the original
	 * one.
	 */
	tmp = nm_simple_connection_new_clone (NM_CONNECTION (object));
	g_assert (tmp);
	if (secrets)
		nm_connection_update_secrets (tmp, NM_SETTING_VPN_SETTING_NAME, secrets, NULL);
	vpn_export (tmp);
	g_object_unref (tmp);
	if (secrets)
		g_variant_ref (secrets);
	g_clear_error (&error);
}
static void
get_secrets_cb (AppletAgent *self,
                GHashTable *secrets,
                GError *error,
                gpointer user_data)
{
	Request *r = user_data;

	/* 'secrets' shouldn't be valid if there was an error */
	if (error) {
		g_warn_if_fail (secrets == NULL);
		secrets = NULL;
	}

	if (!g_cancellable_is_cancelled (r->cancellable)) {
		/* Save updated secrets as long as user-interaction was allowed; otherwise
		 * we'd be saving secrets we just pulled out of the keyring which is somewhat
		 * redundant.
		 */
		if (secrets && (r->flags != NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE)) {
			NMConnection *dupl;
			GHashTableIter iter;
			const char *setting_name;

			/* Copy the existing connection and update its secrets */
			dupl = nm_connection_duplicate (r->connection);
			g_hash_table_iter_init (&iter, secrets);
			while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, NULL))
				nm_connection_update_secrets (dupl, setting_name, secrets, NULL);

			/* And save updated secrets to the keyring */
			nm_secret_agent_save_secrets (NM_SECRET_AGENT (self), dupl, get_save_cb, NULL);
			g_object_unref (dupl);
		}

		r->get_callback (NM_SECRET_AGENT (r->agent), r->connection, secrets, error, r->callback_data);
	}
	request_free (r);
}
static void
test_update_secrets_wifi (void)
{
	NMConnection *connection;
	NMSettingConnection *s_con;
	NMSettingWireless *s_wifi;
	NMSettingWirelessSecurity *s_wsec;
	unsigned char tmpssid[] = { 0x31, 0x33, 0x33, 0x37 };
	const char *wepkey = "11111111111111111111111111";
	GHashTable *secrets;
	GError *error = NULL;
	char *uuid;
	GByteArray *ssid;
	gboolean success;

	connection = nm_connection_new ();
	g_assert (connection);

	/* Connection setting */
	s_con = (NMSettingConnection *) nm_setting_connection_new ();
	g_assert (s_con);

	uuid = nm_utils_uuid_generate ();
	g_object_set (s_con,
	              NM_SETTING_CONNECTION_ID, "Test Wireless",
	              NM_SETTING_CONNECTION_UUID, uuid,
	              NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
	              NULL);
	g_free (uuid);
	nm_connection_add_setting (connection, NM_SETTING (s_con));

	/* Wireless setting */
	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
	g_assert (s_wifi);

	ssid = g_byte_array_sized_new (sizeof (tmpssid));
	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
	g_object_set (s_wifi,
	              NM_SETTING_WIRELESS_SSID, ssid,
	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
	              NULL);
	g_byte_array_free (ssid, TRUE);
	nm_connection_add_setting (connection, NM_SETTING (s_wifi));

	/* Wifi security */
	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
	g_assert (s_wsec);

	g_object_set (G_OBJECT (s_wsec),
	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
	              NULL);
	nm_connection_add_setting (connection, NM_SETTING (s_wsec));

	/* Build up the secrets hash */
	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, value_destroy);
	g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, string_to_gvalue (wepkey));
	g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, uint_to_gvalue (NM_WEP_KEY_TYPE_KEY));

	success = nm_connection_update_secrets (connection,
	                                        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
	                                        secrets,
	                                        &error);
	if (!success) {
		/* Print the warning message before we assert success */
		g_assert (error);
		g_warning ("Error updating connection secrets: %s", error->message);
		g_clear_error (&error);
	}
	g_assert (success);
}
static void
keyring_find_secrets_cb (GObject *source,
                         GAsyncResult *result,
                         gpointer user_data)
{
	Request *r = user_data;
	GError *error = NULL;
	GError *search_error = NULL;
	const char *connection_id = NULL;
	GHashTable *secrets = NULL, *settings = NULL;
	GList *list = NULL;
	GList *iter;
	gboolean hint_found = FALSE, ask = FALSE;

	r->keyring_calls--;
	if (g_cancellable_is_cancelled (r->cancellable)) {
		/* Callback already called by NM or dispose */
		request_free (r);
		return;
	}

	list = secret_service_search_finish (NULL, result, &search_error);
	connection_id = nm_connection_get_id (r->connection);

	if (g_error_matches (search_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
		error = g_error_new_literal (NM_SECRET_AGENT_ERROR,
		                             NM_SECRET_AGENT_ERROR_USER_CANCELED,
		                             "The secrets request was canceled by the user");
		g_error_free (search_error);
		goto done;
	} else if (search_error) {
		error = g_error_new (NM_SECRET_AGENT_ERROR,
		                     NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
		                     "%s.%d - failed to read secrets from keyring (%s)",
		                     __FILE__, __LINE__, search_error->message);
		g_error_free (search_error);
		goto done;
	}

	/* Only ask if we're allowed to, so that eg a connection editor which
	 * requests secrets for its UI, for a connection which doesn't have any
	 * secrets yet, doesn't trigger the applet secrets dialog.
	 */
	if (   (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
	    && g_list_length (list) == 0) {
		g_message ("No keyring secrets found for %s/%s; asking user.", connection_id, r->setting_name);
		ask_for_secrets (r);
		return;
	}

	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);

	/* Extract the secrets from the list of matching keyring items */
	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
		SecretItem *item = iter->data;
		SecretValue *secret;
		const char *key_name;
		GHashTable *attributes;

		secret = secret_item_get_secret (item);
		if (secret) {
			attributes = secret_item_get_attributes (item);
			key_name = g_hash_table_lookup (attributes, KEYRING_SK_TAG);
			if (!key_name) {
				g_hash_table_unref (attributes);
				secret_value_unref (secret);
				continue;
			}

			g_hash_table_insert (secrets, g_strdup (key_name),
			                     string_to_gvalue (secret_value_get (secret, NULL)));

			/* See if this property matches a given hint */
			if (r->hints && r->hints[0]) {
				if (!g_strcmp0 (r->hints[0], key_name) || !g_strcmp0 (r->hints[1], key_name))
					hint_found = TRUE;
			}

			g_hash_table_unref (attributes);
			secret_value_unref (secret);
			break;
		}
	}

	/* If there were hints, and none of the hints were returned by the keyring,
	 * get some new secrets.
	 */
	if (r->flags) {
		if (r->hints && r->hints[0] && !hint_found)
			ask = TRUE;
		else if (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) {
			g_message ("New secrets for %s/%s requested; ask the user", connection_id, r->setting_name);
			ask = TRUE;
		} else if (   (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
			       && is_connection_always_ask (r->connection))
			ask = TRUE;
	}

	/* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
	 * will contain all the individual settings hashes.
	 */
	settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
	g_hash_table_insert (settings, g_strdup (r->setting_name), secrets);

done:
	g_list_free_full (list, g_object_unref);
	if (ask) {
		GHashTableIter hash_iter;
		const char *setting_name;
		GHashTable *setting_hash;

		/* Stuff all the found secrets into the connection for the UI to use */
		g_hash_table_iter_init (&hash_iter, settings);
		while (g_hash_table_iter_next (&hash_iter,
		                               (gpointer *) &setting_name,
		                               (gpointer *) &setting_hash)) {
			nm_connection_update_secrets (r->connection,
				                          setting_name,
				                          setting_hash,
				                          NULL);
		}

		ask_for_secrets (r);
	} else {
		/* Otherwise send the secrets back to NetworkManager */
		r->get_callback (NM_SECRET_AGENT (r->agent), r->connection, error ? NULL : settings, error, r->callback_data);
		request_free (r);
	}

	if (settings)
		g_hash_table_destroy (settings);
	g_clear_error (&error);
}
Beispiel #6
0
static void
keyring_find_secrets_cb (GnomeKeyringResult result,
                         GList *list,
                         gpointer user_data)
{
	KeyringCall *call = user_data;
	Request *r = call->r;
	GError *error = NULL;
	const char *connection_id = NULL;
	GHashTable *secrets = NULL, *settings = NULL;
	GList *iter;
	gboolean hint_found = FALSE, ask = FALSE;

	r->keyring_calls = g_slist_remove (r->keyring_calls, call);
	if (r->canceled) {
		/* Callback already called by NM or dispose */
		request_free (r);
		return;
	}

	connection_id = nm_connection_get_id (r->connection);

	if (result == GNOME_KEYRING_RESULT_CANCELLED) {
		error = g_error_new_literal (NM_SECRET_AGENT_ERROR,
		                             NM_SECRET_AGENT_ERROR_USER_CANCELED,
		                             "The secrets request was canceled by the user");
		goto done;
	} else if (   result != GNOME_KEYRING_RESULT_OK
	           && result != GNOME_KEYRING_RESULT_NO_MATCH) {
		error = g_error_new (NM_SECRET_AGENT_ERROR,
		                     NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
		                     "%s.%d - failed to read secrets from keyring (result %d)",
		                     __FILE__, __LINE__, result);
		goto done;
	}

	/* Only ask if we're allowed to, ie if flags != NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE */
	if (r->flags && g_list_length (list) == 0) {
		g_message ("No keyring secrets found for %s/%s; asking user.", connection_id, r->setting_name);
		ask_for_secrets (r);
		return;
	}

	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);

	/* Extract the secrets from the list of matching keyring items */
	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
		GnomeKeyringFound *found = iter->data;
		GnomeKeyringAttribute *attr;
		const char *key_name = NULL;
		int i;

		for (i = 0; i < found->attributes->len; i++) {
			attr = &(gnome_keyring_attribute_list_index (found->attributes, i));
			if (   (strcmp (attr->name, KEYRING_SK_TAG) == 0)
			    && (attr->type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING)) {

				key_name = attr->value.string;
				g_hash_table_insert (secrets, g_strdup (key_name), string_to_gvalue (found->secret));

				/* See if this property matches a given hint */
				if (r->hints && r->hints[0]) {
					if (!g_strcmp0 (r->hints[0], key_name) || !g_strcmp0 (r->hints[1], key_name))
						hint_found = TRUE;
				}
				break;
			}
		}
	}

	/* If there were hints, and none of the hints were returned by the keyring,
	 * get some new secrets.
	 */
	if (r->flags) {
		if (r->hints && r->hints[0] && !hint_found)
			ask = TRUE;
		else if (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) {
			g_message ("New secrets for %s/%s requested; ask the user", connection_id, r->setting_name);
			ask = TRUE;
		} else if (   (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
			       && is_connection_always_ask (r->connection))
			ask = TRUE;
	}

	/* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
	 * will contain all the individual settings hashes.
	 */
	settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
	g_hash_table_insert (settings, g_strdup (r->setting_name), secrets);

done:
	if (ask) {
		GHashTableIter hash_iter;
		const char *setting_name;
		GHashTable *setting_hash;

		/* Stuff all the found secrets into the connection for the UI to use */
		g_hash_table_iter_init (&hash_iter, settings);
		while (g_hash_table_iter_next (&hash_iter,
		                               (gpointer *) &setting_name,
		                               (gpointer *) &setting_hash)) {
			nm_connection_update_secrets (r->connection,
				                          setting_name,
				                          setting_hash,
				                          NULL);
		}

		ask_for_secrets (r);
	} else {
		/* Otherwise send the secrets back to NetworkManager */
		r->get_callback (NM_SECRET_AGENT (r->agent), r->connection, error ? NULL : settings, error, r->callback_data);
		request_free (r);
	}

	if (settings)
		g_hash_table_destroy (settings);
	g_clear_error (&error);
}
void
ce_page_complete_init (CEPage *self,
                       const char *setting_name,
                       GVariant *secrets,
                       GError *error)
{
	GError *update_error = NULL;
	GVariant *setting_dict;
	char *dbus_err;
	gboolean ignore_error = FALSE;

	g_return_if_fail (self != NULL);
	g_return_if_fail (CE_IS_PAGE (self));

	if (error) {
		dbus_err = g_dbus_error_get_remote_error (error);
		ignore_error =    !g_strcmp0 (dbus_err, "org.freedesktop.NetworkManager.Settings.InvalidSetting")
		               || !g_strcmp0 (dbus_err, "org.freedesktop.NetworkManager.Settings.Connection.SettingNotFound")
		               || !g_strcmp0 (dbus_err, "org.freedesktop.NetworkManager.AgentManager.NoSecrets");
		g_free (dbus_err);
	}

	/* Ignore missing settings errors */
	if (error && !ignore_error) {
		emit_initialized (self, error);
		return;
	} else if (!setting_name || !secrets || g_variant_n_children (secrets) == 0) {
		/* Success, no secrets */
		emit_initialized (self, NULL);
		return;
	}

	g_assert (setting_name);
	g_assert (secrets);

	setting_dict = g_variant_lookup_value (secrets, setting_name, NM_VARIANT_TYPE_SETTING);
	if (!setting_dict) {
		/* Success, no secrets */
		emit_initialized (self, NULL);
		return;
	}
	g_variant_unref (setting_dict);

	/* Update the connection with the new secrets */
	if (nm_connection_update_secrets (self->connection,
	                                  setting_name,
	                                  secrets,
	                                  &update_error)) {
		/* Success */
		emit_initialized (self, NULL);
		return;
	}

	if (!update_error) {
		g_set_error_literal (&update_error, NMA_ERROR, NMA_ERROR_GENERIC,
		                     _("Failed to update connection secrets due to an unknown error."));
	}

	emit_initialized (self, update_error);
	g_clear_error (&update_error);
}