Exemplo n.º 1
0
static char *
keyring_lookup_secret (const char *uuid, const char *secret_name)
{
	GHashTable *attrs;
	GList *list;
	char *secret = NULL;

	attrs = secret_attributes_build (&network_manager_secret_schema,
	                                 KEYRING_UUID_TAG, uuid,
	                                 KEYRING_SN_TAG, NM_SETTING_VPN_SETTING_NAME,
	                                 KEYRING_SK_TAG, secret_name,
	                                 NULL);

	list = secret_service_search_sync (NULL, &network_manager_secret_schema, attrs,
	                                   SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
	                                   NULL, NULL);
	if (list && list->data) {
		SecretItem *item = list->data;
		SecretValue *value = secret_item_get_secret (item);

		if (value) {
			secret = g_strdup (secret_value_get (value, NULL));
			secret_value_unref (value);
		}
	}

	g_list_free_full (list, g_object_unref);
	g_hash_table_unref (attrs);
	return secret;
}
Exemplo n.º 2
0
static char * keyring_lookup_secret (const char *uuid,
                                     const char *secret_name) {
    #if defined(HAVE_LIBSECRET)
    GHashTable *attrs;
    GList *list;
    #else
    GList *found_list = NULL;
	GnomeKeyringResult ret;
	GnomeKeyringFound *found;
    #endif
	char *secret = NULL;

    #if defined(HAVE_LIBSECRET)
    attrs = secret_attributes_build(&network_manager_secret_schema,
                                    KEYRING_UUID_TAG, uuid,
                                    KEYRING_SN_TAG, NM_SETTING_VPN_SETTING_NAME,
                                    KEYRING_SK_TAG, secret_name,
                                    NULL);

    list = secret_service_search_sync(NULL, &network_manager_secret_schema, attrs,
            SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
            NULL, NULL);
    if (list && list->data) {
        SecretItem *item = list->data;
        SecretValue *value = secret_item_get_secret(item);

        if (value) {
            secret = g_strdup(secret_value_get(value, NULL));
            secret_value_unref(value);
        }
    }

    g_list_free_full(list, g_object_unref);
    g_hash_table_unref(attrs);
    #else
    ret = gnome_keyring_find_itemsv_sync(GNOME_KEYRING_ITEM_GENERIC_SECRET,
                                         &found_list,
                                         KEYRING_UUID_TAG,
                                         GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
                                         uuid,
                                         KEYRING_SN_TAG,
                                         GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
                                         NM_SETTING_VPN_SETTING_NAME,
                                         KEYRING_SK_TAG,
                                         GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
                                         secret_name,
                                         NULL);
	if (ret == GNOME_KEYRING_RESULT_OK && found_list) {
        found = g_list_nth_data(found_list, 0);
        secret = gnome_keyring_memory_strdup(found->secret);
	}

    gnome_keyring_found_list_free(found_list);
    #endif

	return secret;
}
Exemplo n.º 3
0
static gboolean
service_encode_aes_secret (SecretSession *session,
                           SecretValue *value,
                           GVariantBuilder *builder)
{
	gcry_cipher_hd_t cih;
	guchar *padded;
	gsize n_padded, pos;
	gcry_error_t gcry;
	gpointer iv;
	gconstpointer secret;
	gsize n_secret;
	GVariant *child;

	g_variant_builder_add (builder, "o", session->path);

	/* Create the cipher */
	gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
	if (gcry != 0) {
		g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
		return FALSE;
	}

	secret = secret_value_get (value, &n_secret);

	/* Perform the encoding here */
	padded = pkcs7_pad_bytes_in_secure_memory (secret, n_secret, &n_padded);
	g_assert (padded != NULL);

	/* Setup the IV */
	iv = g_malloc0 (16);
	gcry_create_nonce (iv, 16);
	gcry = gcry_cipher_setiv (cih, iv, 16);
	g_return_val_if_fail (gcry == 0, FALSE);

	/* Setup the key */
	gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
	g_return_val_if_fail (gcry == 0, FALSE);

	/* Perform the encryption */
	for (pos = 0; pos < n_padded; pos += 16) {
		gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
		g_return_val_if_fail (gcry == 0, FALSE);
	}

	gcry_cipher_close (cih);

	child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), iv, 16, TRUE, g_free, iv);
	g_variant_builder_add_value (builder, child);

	child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), padded, n_padded, TRUE, egg_secure_free, padded);
	g_variant_builder_add_value (builder, child);

	g_variant_builder_add (builder, "s", secret_value_get_content_type (value));
	return TRUE;
}
Exemplo n.º 4
0
static gboolean
is_password_value (SecretValue *value)
{
    const gchar *content_type;
    const gchar *data;
    gsize length;

    content_type = secret_value_get_content_type (value);
    if (content_type && g_str_equal (content_type, "text/plain"))
        return TRUE;

    data = secret_value_get (value, &length);
    /* gnome-keyring-daemon used to return passwords like this, so support this, but validate */
    if (!content_type || g_str_equal (content_type, "application/octet-stream"))
        return g_utf8_validate (data, length, NULL);

    return FALSE;
}
Exemplo n.º 5
0
static void
write_password_data (SecretValue *value)
{
    const gchar *at;
    gsize length;
    int r;

    at = secret_value_get (value, &length);

    while (length > 0) {
        r = write (1, at, length);
        if (r == -1) {
            if (errno != EAGAIN && errno != EINTR) {
                g_printerr ("%s: couldn't write password: %s\n",
                            g_get_prgname (), g_strerror (errno));
                exit (1);
            }
        } else {
            at += r;
            length -= r;
        }
    }
}
Exemplo n.º 6
0
static gboolean
service_encode_plain_secret (SecretSession *session,
                             SecretValue *value,
                             GVariantBuilder *builder)
{
	gconstpointer secret;
	gsize n_secret;
	GVariant *child;

	g_variant_builder_add (builder, "o", session->path);

	secret = secret_value_get (value, &n_secret);

	child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), "", 0, TRUE, NULL, NULL);
	g_variant_builder_add_value (builder, child);

	child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), secret, n_secret, TRUE,
	                                 secret_value_unref, secret_value_ref (value));
	g_variant_builder_add_value (builder, child);

	g_variant_builder_add (builder, "s", secret_value_get_content_type (value));
	return TRUE;
}
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);
}
Exemplo n.º 8
0
void NetworkStorageSession::getCredentialFromPersistentStorage(const ProtectionSpace& protectionSpace, Function<void (Credential&&)> completionHandler)
{
#if USE(LIBSECRET)
    if (m_sessionID.isEphemeral()) {
        completionHandler({ });
        return;
    }

    const String& realm = protectionSpace.realm();
    if (realm.isEmpty()) {
        completionHandler({ });
        return;
    }

    GRefPtr<GHashTable> attributes = adoptGRef(secret_attributes_build(SECRET_SCHEMA_COMPAT_NETWORK,
        "domain", realm.utf8().data(),
        "server", protectionSpace.host().utf8().data(),
        "port", protectionSpace.port(),
        "protocol", schemeFromProtectionSpaceServerType(protectionSpace.serverType()),
        "authtype", authTypeFromProtectionSpaceAuthenticationScheme(protectionSpace.authenticationScheme()),
        nullptr));
    if (!attributes) {
        completionHandler({ });
        return;
    }

    m_persisentStorageCancellable = adoptGRef(g_cancellable_new());
    m_persisentStorageCompletionHandler = WTFMove(completionHandler);
    secret_service_search(nullptr, SECRET_SCHEMA_COMPAT_NETWORK, attributes.get(),
        static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS), m_persisentStorageCancellable.get(),
        [](GObject* source, GAsyncResult* result, gpointer userData) {
            GUniqueOutPtr<GError> error;
            GUniquePtr<GList> elements(secret_service_search_finish(SECRET_SERVICE(source), result, &error.outPtr()));
            if (g_error_matches (error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
                return;

            NetworkStorageSession* session = static_cast<NetworkStorageSession*>(userData);
            auto completionHandler = std::exchange(session->m_persisentStorageCompletionHandler, nullptr);
            if (error || !elements || !elements->data) {
                completionHandler({ });
                return;
            }

            GRefPtr<SecretItem> secretItem = adoptGRef(static_cast<SecretItem*>(elements->data));
            GRefPtr<GHashTable> attributes = adoptGRef(secret_item_get_attributes(secretItem.get()));
            String user = String::fromUTF8(static_cast<const char*>(g_hash_table_lookup(attributes.get(), "user")));
            if (user.isEmpty()) {
                completionHandler({ });
                return;
            }

            size_t length;
            GRefPtr<SecretValue> secretValue = adoptGRef(secret_item_get_secret(secretItem.get()));
            const char* passwordData = secret_value_get(secretValue.get(), &length);
            completionHandler(Credential(user, String::fromUTF8(passwordData, length), CredentialPersistencePermanent));
    }, this);
#else
    UNUSED_PARAM(protectionSpace);
    completionHandler({ });
#endif
}
static void
keyring_pin_check_cb (GObject *source,
                      GAsyncResult *result,
                      gpointer user_data)
{
	BroadbandDeviceInfo *info = user_data;
	GList *iter;
	GList *list;
	SecretItem *item;
	SecretValue *pin = NULL;
	GHashTable *attributes;
	GError *error = NULL;
	const char *simid;

	list = secret_service_search_finish (NULL, result, &error);

	if (error != NULL) {
		/* No saved PIN, just ask the user */
		unlock_dialog_new (info->device, info);
		g_error_free (error);
		return;
	}

	/* Look for a result with a matching "simid" attribute since that's
	 * better than just using a matching "devid".  The PIN is really tied
	 * to the SIM, not the modem itself.
	 */
	simid = mm_sim_get_identifier (info->mm_sim);
	if (simid) {
		for (iter = list;
		     (pin == NULL) && iter;
		     iter = g_list_next (iter)) {
			item = iter->data;

			/* Look for a matching "simid" attribute */
			attributes = secret_item_get_attributes (item);
			if (g_strcmp0 (simid, g_hash_table_lookup (attributes, "simid")))
				pin = secret_item_get_secret (item);
			else
				pin = NULL;
			g_hash_table_unref (attributes);

			if (pin != NULL)
				break;
		}
	}

	if (pin == NULL) {
		/* Fall back to the first result's PIN if we have one */
		if (list)
			pin = secret_item_get_secret (list->data);
		if (pin == NULL) {
			unlock_dialog_new (info->device, info);
			return;
		}
	}

	/* Send the PIN code to ModemManager */
	mm_sim_send_pin (info->mm_sim,
	                 secret_value_get (pin, NULL),
	                 NULL, /* cancellable */
	                 (GAsyncReadyCallback)autounlock_sim_send_pin_ready,
	                 info);
	secret_value_unref (pin);
}
Exemplo n.º 10
0
gboolean
g_vfs_keyring_lookup_password (const gchar *username,
                               const gchar *host,
                               const gchar *domain,
                               const gchar *protocol,
                               const gchar *object,
                               const gchar *authtype,
                               guint32      port,
                               gchar      **username_out,
                               gchar      **domain_out,
                               gchar      **password_out)
{
#ifdef HAVE_KEYRING
    GHashTable  *attributes;
    SecretItem  *item;
    SecretValue *secret;
    GList       *plist;
    GError      *error = NULL;


    attributes = build_network_attributes (username, host, domain, protocol, object, authtype, port);
    plist = secret_service_search_sync (NULL, SECRET_SCHEMA_COMPAT_NETWORK, attributes,
                                        SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS |
                                        SECRET_SEARCH_ALL,
                                        NULL, &error);
    g_hash_table_unref (attributes);

    if (error != NULL)
    {
        g_error_free (error);
        return FALSE;
    }

    if (plist == NULL)
        return FALSE;

    /* We want the least specific result, so we sort the return values.
       For instance, given both items for ftp://host:port and ftp://host
       in the keyring we always want to use the ftp://host one for
       i.e. ftp://host/some/path. */

    plist = g_list_sort (plist, compare_specificity);

    item = SECRET_ITEM (plist->data);
    secret = secret_item_get_secret (item);
    attributes = secret_item_get_attributes (item);
    g_list_free_full (plist, g_object_unref);

    if (secret == NULL)
    {
        if (attributes)
            g_hash_table_unref (attributes);
        return FALSE;
    }

    *password_out = g_strdup (secret_value_get (secret, NULL));
    secret_value_unref (secret);

    if (username_out)
        *username_out = g_strdup (g_hash_table_lookup (attributes, "user"));

    if (domain_out)
        *domain_out = g_strdup (g_hash_table_lookup (attributes, "domain"));

    g_hash_table_unref (attributes);
    return TRUE;
#else
    return FALSE;
#endif /* HAVE_KEYRING */
}