Remmina - The GTK+ Remote Desktop Client  v1.4.2
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
glibsecret_plugin.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * In addition, as a special exception, the copyright holders give
22  * permission to link the code of portions of this program with the
23  * OpenSSL library under certain conditions as described in each
24  * individual source file, and distribute linked combinations
25  * including the two.
26  * You must obey the GNU General Public License in all respects
27  * for all of the code used other than OpenSSL. * If you modify
28  * file(s) with this exception, you may extend this exception to your
29  * version of the file(s), but you are not obligated to do so. * If you
30  * do not wish to do so, delete this exception statement from your
31  * version. * If you delete this exception statement from all source
32  * files in the program, then also delete it here.
33  *
34  */
35 
36 #include "config.h"
37 #include "glibsecret_plugin.h"
38 #include <gtk/gtk.h>
39 #include <glib.h>
40 #include <glib/gi18n-lib.h>
41 #include <glib/gstdio.h>
42 #include <libsecret/secret.h>
43 #include <remmina/plugin.h>
44 
46 
47 static SecretSchema remmina_file_secret_schema =
48 { "org.remmina.Password", SECRET_SCHEMA_NONE,
49  {
50  { "filename", SECRET_SCHEMA_ATTRIBUTE_STRING },
51  { "key", SECRET_SCHEMA_ATTRIBUTE_STRING },
52  { NULL, 0 }
53  } };
54 
55 
56 #ifdef LIBSECRET_VERSION_0_18
57 static SecretService* secretservice;
58 static SecretCollection* defaultcollection;
59 #endif
60 
61 
63 {
64 #ifdef LIBSECRET_VERSION_0_18
66  return TRUE;
67  else
68  return FALSE;
69 #else
70  return FALSE;
71 #endif
72 }
73 
75 {
76  TRACE_CALL(__func__);
77 
78 #ifdef LIBSECRET_VERSION_0_18
79 
80  GError *error = NULL;
81  GList *objects, *ul;
82  gchar* lbl;
83 
85  if (secret_collection_get_locked(defaultcollection)) {
86  lbl = secret_collection_get_label(defaultcollection);
87  remmina_plugin_service->debug("Requesting unlock of the default '%s' collection", lbl);
88  objects = g_list_append(NULL, defaultcollection);
89  secret_service_unlock_sync(secretservice, objects, NULL, &ul, &error);
90  g_list_free(objects);
91  g_list_free(ul);
92  }
93  }
94 #endif
95  return;
96 }
97 
98 void remmina_plugin_glibsecret_store_password(RemminaFile *remminafile, const gchar *key, const gchar *password)
99 {
100  TRACE_CALL(__func__);
101  GError *r = NULL;
102  const gchar *path;
103  gchar *s;
104 
105  path = remmina_plugin_service->file_get_path(remminafile);
106  s = g_strdup_printf("Remmina: %s - %s", remmina_plugin_service->file_get_string(remminafile, "name"), key);
107  secret_password_store_sync(&remmina_file_secret_schema, SECRET_COLLECTION_DEFAULT, s, password,
108  NULL, &r, "filename", path, "key", key, NULL);
109  g_free(s);
110  if (r == NULL) {
111  remmina_plugin_service->debug("Password \"%s\" saved for file %s\n", key, path);
112  }else {
113  remmina_plugin_service->debug("Password \"%s\" cannot be saved for file %s\n", key, path);
114  g_error_free(r);
115  }
116 }
117 
118 gchar*
120 {
121  TRACE_CALL(__func__);
122  GError *r = NULL;
123  const gchar *path;
124  gchar *password;
125  gchar *p;
126 
127  path = remmina_plugin_service->file_get_path(remminafile);
128  password = secret_password_lookup_sync(&remmina_file_secret_schema, NULL, &r, "filename", path, "key", key, NULL);
129  if (r == NULL) {
130  p = g_strdup(password);
131  secret_password_free(password);
132  return p;
133  }else {
134  remmina_plugin_service->debug("Password cannot be found for file %s\n", path);
135  return NULL;
136  }
137 }
138 
139 void remmina_plugin_glibsecret_delete_password(RemminaFile *remminafile, const gchar *key)
140 {
141  TRACE_CALL(__func__);
142  GError *r = NULL;
143  const gchar *path;
144 
145  path = remmina_plugin_service->file_get_path(remminafile);
146  secret_password_clear_sync(&remmina_file_secret_schema, NULL, &r, "filename", path, "key", key, NULL);
147  if (r == NULL)
148  remmina_plugin_service->debug("password \"%s\" deleted for file %s", key, path);
149  else
150  remmina_plugin_service->debug("password \"%s\" cannot be deleted for file %s", key, path);
151 }
152 
154 {
155 #ifdef LIBSECRET_VERSION_0_18
156  GError *error;
157  error = NULL;
158  secretservice = secret_service_get_sync(SECRET_SERVICE_LOAD_COLLECTIONS, NULL, &error);
159  if (error) {
160  g_print("[glibsecret] unable to get secret service: %s\n", error->message);
161  return FALSE;
162  }
163  if (secretservice == NULL) {
164  g_print("[glibsecret] unable to get secret service: Unknown error.\n");
165  return FALSE;
166  }
167 
168  defaultcollection = secret_collection_for_alias_sync(secretservice, SECRET_COLLECTION_DEFAULT, SECRET_COLLECTION_NONE, NULL, &error);
169  if (error) {
170  g_print("[glibsecret] unable to get secret service default collection: %s\n", error->message);
171  return FALSE;
172  }
173 
175  return TRUE;
176 
177 #else
178  g_print("Libsecret was too old during compilation, disabling secret service.\n");
179  return FALSE;
180 #endif
181 }
182 
185  "glibsecret",
186  N_("Secured password storage in the GNOME keyring"),
187  NULL,
188  VERSION,
189  2000,
195 };
196 
197 G_MODULE_EXPORT gboolean
199 {
200  TRACE_CALL(__func__);
201 
202  /* This function should only register the secret plugin. No init action
203  * should be performed here. Initialization will be done later
204  * with remmina_plugin_xxx_init() . */
205 
206  remmina_plugin_service = service;
207 
208  if (!service->register_plugin((RemminaPlugin*)&remmina_plugin_glibsecret)) {
209  return FALSE;
210  }
211 
212  return TRUE;
213 
214 }
215 
void(* debug)(const gchar *fmt,...)
Definition: plugin.h:214
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:41
static SecretService * secretservice
static RemminaSecretPlugin remmina_plugin_glibsecret
G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
static SecretSchema remmina_file_secret_schema
gboolean(* register_plugin)(RemminaPlugin *plugin)
Definition: plugin.h:148
gboolean remmina_plugin_glibsecret_init()
static RemminaPluginService * remmina_plugin_service
void remmina_plugin_glibsecret_store_password(RemminaFile *remminafile, const gchar *key, const gchar *password)
static void remmina_plugin_glibsecret_unlock_secret_service()
const gchar *(* file_get_path)(RemminaFile *remminafile)
Definition: plugin.h:198
gboolean remmina_plugin_glibsecret_is_service_available()
gchar * remmina_plugin_glibsecret_get_password(RemminaFile *remminafile, const gchar *key)
void remmina_plugin_glibsecret_delete_password(RemminaFile *remminafile, const gchar *key)
static SecretCollection * defaultcollection
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
Definition: plugin.h:200
N_("Unable to connect to VNC server")
Definition: vnc_plugin.c:907