Files
grd/grd-credentials-libsecret.c
2026-02-13 13:06:50 +09:00

253 lines
6.9 KiB
C

/*
* Copyright (C) 2018-2022 Red Hat Inc.
* Copyright (C) 2020 Pascal Nowack
*
* 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 of the
* License, 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#include "config.h"
#include "grd-credentials-libsecret.h"
#include <gio/gio.h>
#include <libsecret/secret.h>
#include <stdio.h>
#define GRD_RDP_CREDENTIALS_SCHEMA (get_rdp_schema ())
#define GRD_VNC_PASSWORD_SCHEMA (get_vnc_schema ())
#define GRD_VNC_LEGACY_PASSWORD_SCHEMA (get_legacy_vnc_schema ())
struct _GrdCredentialsLibsecret
{
GrdCredentials parent;
};
G_DEFINE_TYPE (GrdCredentialsLibsecret,
grd_credentials_libsecret,
GRD_TYPE_CREDENTIALS)
static const SecretSchema *
get_rdp_schema (void)
{
static const SecretSchema grd_rdp_credentials_schema = {
.name = "org.gnome.RemoteDesktop.RdpCredentials",
.flags = SECRET_SCHEMA_NONE,
.attributes = {
{ "credentials", SECRET_SCHEMA_ATTRIBUTE_STRING },
{ "NULL", 0 },
},
};
return &grd_rdp_credentials_schema;
}
static const SecretSchema *
get_legacy_vnc_schema (void)
{
static const SecretSchema grd_vnc_password_schema = {
.name = "org.gnome.RemoteDesktop.VncPassword",
.flags = SECRET_SCHEMA_NONE,
.attributes = {
{ "password", SECRET_SCHEMA_ATTRIBUTE_STRING },
{ "NULL", 0 },
},
};
return &grd_vnc_password_schema;
}
static const SecretSchema *
get_vnc_schema (void)
{
static const SecretSchema grd_vnc_password_schema = {
.name = "org.gnome.RemoteDesktop.VncCredentials",
.flags = SECRET_SCHEMA_NONE,
.attributes = {
{ "password", SECRET_SCHEMA_ATTRIBUTE_STRING },
{ "NULL", 0 },
},
};
return &grd_vnc_password_schema;
}
static const SecretSchema *
schema_from_type (GrdCredentialsType type)
{
switch (type)
{
case GRD_CREDENTIALS_TYPE_RDP:
return GRD_RDP_CREDENTIALS_SCHEMA;
case GRD_CREDENTIALS_TYPE_VNC:
return GRD_VNC_PASSWORD_SCHEMA;
}
g_assert_not_reached ();
}
static const char *
description_from_type (GrdCredentialsType type)
{
switch (type)
{
case GRD_CREDENTIALS_TYPE_RDP:
return "GNOME Remote Desktop RDP credentials";
case GRD_CREDENTIALS_TYPE_VNC:
return "GNOME Remote Desktop VNC password";
}
g_assert_not_reached ();
}
static gboolean
grd_credentials_libsecret_store (GrdCredentials *credentials,
GrdCredentialsType type,
GVariant *variant,
GError **error)
{
g_autofree char *serialized = NULL;
g_variant_ref_sink (variant);
serialized = g_variant_print (variant, TRUE);
g_variant_unref (variant);
return secret_password_store_sync (schema_from_type (type),
SECRET_COLLECTION_DEFAULT,
description_from_type (type),
serialized,
NULL, error,
NULL);
}
static GVariant *
grd_credentials_libsecret_lookup (GrdCredentials *credentials,
GrdCredentialsType type,
GError **error)
{
g_autofree char *serialized = NULL;
serialized = secret_password_lookup_sync (schema_from_type (type),
NULL, error,
NULL);
if (!serialized)
return NULL;
return g_variant_parse (NULL, serialized, NULL, NULL, error);
}
static gboolean
grd_credentials_libsecret_clear (GrdCredentials *credentials,
GrdCredentialsType type,
GError **error)
{
g_autoptr (GError) local_error = NULL;
secret_password_clear_sync (schema_from_type (type),
NULL, &local_error,
NULL);
if (local_error)
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
else
{
return TRUE;
}
}
GrdCredentialsLibsecret *
grd_credentials_libsecret_new (void)
{
return g_object_new (GRD_TYPE_CREDENTIALS_LIBSECRET, NULL);
}
static void
grd_credentials_libsecret_init (GrdCredentialsLibsecret *credentials_libsecret)
{
}
static void
maybe_migrate_legacy_vnc_password (GrdCredentials *credentials)
{
g_autoptr (GError) error = NULL;
g_autofree char *password = NULL;
password = secret_password_lookup_sync (GRD_VNC_LEGACY_PASSWORD_SCHEMA,
NULL, &error,
NULL);
if (!password)
{
if (error)
{
g_printerr ("Failed to lookup legacy VNC password schema: %s\n",
error->message);
}
}
else
{
g_printerr ("Migrating VNC password to new schema... ");
if (!grd_credentials_store (credentials,
GRD_CREDENTIALS_TYPE_VNC,
g_variant_new_string (password),
&error))
{
g_printerr ("Failed to migrate VNC password to new schema: %s\n",
error->message);
}
else
{
if (!secret_password_clear_sync (GRD_VNC_LEGACY_PASSWORD_SCHEMA,
NULL, &error, NULL) &&
error)
{
g_printerr ("Failed to clear VNC password from old schema: %s\n",
error->message);
}
else
{
g_printerr ("OK\n");
}
}
}
}
static void
grd_credentials_libsecret_constructed (GObject *object)
{
GrdCredentials *credentials = GRD_CREDENTIALS (object);
maybe_migrate_legacy_vnc_password (credentials);
G_OBJECT_CLASS (grd_credentials_libsecret_parent_class)->constructed (object);
}
static void
grd_credentials_libsecret_class_init (GrdCredentialsLibsecretClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GrdCredentialsClass *credentials_class = GRD_CREDENTIALS_CLASS (klass);
object_class->constructed = grd_credentials_libsecret_constructed;
credentials_class->store = grd_credentials_libsecret_store;
credentials_class->lookup = grd_credentials_libsecret_lookup;
credentials_class->clear = grd_credentials_libsecret_clear;
}