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); }
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); }