1 // This file is part of darktable
2 // Copyright (c) 2010-2016 Tobias Ellinghaus <me@houz.org>.
3 
4 // darktable is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // darktable is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with darktable.  If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "pwstorage.h"
22 
23 #ifdef HAVE_LIBSECRET
24 #include "backend_libsecret.h"
25 #endif
26 
27 #ifdef HAVE_KWALLET
28 #include "backend_kwallet.h"
29 #endif
30 
31 #include "control/conf.h"
32 #include "control/control.h"
33 
34 #include <glib.h>
35 #include <string.h>
36 
37 /** Initializes a new pwstorage context. */
dt_pwstorage_new()38 const dt_pwstorage_t *dt_pwstorage_new()
39 {
40 /* add password storage capabilities */
41 #ifdef HAVE_LIBSECRET
42   dt_capabilities_add("libsecret");
43 #endif
44 #ifdef HAVE_KWALLET
45   dt_capabilities_add("kwallet");
46 #endif
47 
48   dt_pwstorage_t *pwstorage = g_malloc(sizeof(dt_pwstorage_t));
49   dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] Creating new context %p\n", pwstorage);
50 
51   if(pwstorage == NULL) return NULL;
52 
53   const char *_backend_str = dt_conf_get_string_const("plugins/pwstorage/pwstorage_backend");
54   gint _backend = PW_STORAGE_BACKEND_NONE;
55 
56   if(strcmp(_backend_str, "auto") == 0)
57   {
58     const gchar *desktop = getenv("XDG_CURRENT_DESKTOP");
59     if(g_strcmp0(desktop, "KDE") == 0)
60       _backend = PW_STORAGE_BACKEND_KWALLET;
61     else if(g_strcmp0(desktop, "GNOME") == 0)
62       _backend = PW_STORAGE_BACKEND_LIBSECRET;
63     else if(g_strcmp0(desktop, "Unity") == 0)
64       _backend = PW_STORAGE_BACKEND_LIBSECRET;
65     else if(g_strcmp0(desktop, "XFCE") == 0)
66       _backend = PW_STORAGE_BACKEND_LIBSECRET;
67 
68     dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] autodetected storage backend.\n");
69   }
70   else if(strcmp(_backend_str, "none") == 0)
71     _backend = PW_STORAGE_BACKEND_NONE;
72 #ifdef HAVE_LIBSECRET
73   else if(strcmp(_backend_str, "libsecret") == 0)
74     _backend = PW_STORAGE_BACKEND_LIBSECRET;
75 #endif
76 #ifdef HAVE_KWALLET
77   else if(strcmp(_backend_str, "kwallet") == 0)
78     _backend = PW_STORAGE_BACKEND_KWALLET;
79 #endif
80   else if(strcmp(_backend_str, "gnome keyring") == 0)
81   {
82     fprintf(stderr, "[pwstorage_new] GNOME Keyring backend is no longer supported.\n");
83     dt_control_log(_("GNOME Keyring backend is no longer supported. configure a different one"));
84     _backend = PW_STORAGE_BACKEND_NONE;
85   }
86 
87   switch(_backend)
88   {
89     default:
90       dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] unknown storage backend. Using none.\n");
91     case PW_STORAGE_BACKEND_NONE:
92       pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_NONE;
93       pwstorage->backend_context = NULL;
94       dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] no storage backend. not storing username/password. "
95                                    "please change in preferences, core tab.\n");
96       break;
97     case PW_STORAGE_BACKEND_LIBSECRET:
98 #ifdef HAVE_LIBSECRET
99       dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] using libsecret backend for username/password storage.\n");
100       pwstorage->backend_context = (void *)dt_pwstorage_libsecret_new();
101       if(pwstorage->backend_context == NULL)
102       {
103         dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] error starting libsecret. using no storage backend.\n");
104         pwstorage->backend_context = NULL;
105         pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_NONE;
106       }
107       else
108       {
109         pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_LIBSECRET;
110       }
111       break;
112 #else
113       dt_print(DT_DEBUG_PWSTORAGE,
114                "[pwstorage_new] libsecret backend not available. using no storage backend.\n");
115       pwstorage->backend_context = NULL;
116       pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_NONE;
117 #endif
118     case PW_STORAGE_BACKEND_KWALLET:
119 #ifdef HAVE_KWALLET
120       dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] using kwallet backend for username/password storage.\n");
121       pwstorage->backend_context = (void *)dt_pwstorage_kwallet_new();
122       if(pwstorage->backend_context == NULL)
123       {
124         dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] error starting kwallet. using no storage backend.\n");
125         pwstorage->backend_context = NULL;
126         pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_NONE;
127       }
128       else
129       {
130         pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_KWALLET;
131       }
132       dt_print(DT_DEBUG_PWSTORAGE, "  done.\n");
133       break;
134 #else
135       dt_print(DT_DEBUG_PWSTORAGE,
136                "[pwstorage_new] kwallet backend not available. using no storage backend.\n");
137       pwstorage->backend_context = NULL;
138       pwstorage->pw_storage_backend = PW_STORAGE_BACKEND_NONE;
139 #endif
140   }
141 
142   switch(pwstorage->pw_storage_backend)
143   {
144     case PW_STORAGE_BACKEND_NONE:
145       dt_conf_set_string("plugins/pwstorage/pwstorage_backend", "none");
146       break;
147     case PW_STORAGE_BACKEND_LIBSECRET:
148       dt_conf_set_string("plugins/pwstorage/pwstorage_backend", "libsecret");
149       break;
150     case PW_STORAGE_BACKEND_KWALLET:
151       dt_conf_set_string("plugins/pwstorage/pwstorage_backend", "kwallet");
152       break;
153   }
154 
155   return pwstorage;
156 }
157 
158 /** Cleanup and destroy pwstorage context. \remarks After this point pointer at pwstorage is invalid. */
dt_pwstorage_destroy(const dt_pwstorage_t * pwstorage)159 void dt_pwstorage_destroy(const dt_pwstorage_t *pwstorage)
160 {
161   dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_new] Destroying context %p\n", pwstorage);
162   switch(darktable.pwstorage->pw_storage_backend)
163   {
164     case PW_STORAGE_BACKEND_NONE:
165       // nothing to be done
166       break;
167     case PW_STORAGE_BACKEND_LIBSECRET:
168 #ifdef HAVE_LIBSECRET
169       dt_pwstorage_libsecret_destroy(pwstorage->backend_context);
170 #endif
171       break;
172     case PW_STORAGE_BACKEND_KWALLET:
173 #ifdef HAVE_KWALLET
174       dt_pwstorage_kwallet_destroy(pwstorage->backend_context);
175 #endif
176       break;
177   }
178 }
179 
180 /** Store (key,value) pairs. */
dt_pwstorage_set(const gchar * slot,GHashTable * table)181 gboolean dt_pwstorage_set(const gchar *slot, GHashTable *table)
182 {
183   switch(darktable.pwstorage->pw_storage_backend)
184   {
185     case PW_STORAGE_BACKEND_NONE:
186       dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_set] no backend. not storing anything.\n");
187       break;
188     case PW_STORAGE_BACKEND_LIBSECRET:
189 #if HAVE_LIBSECRET
190       return dt_pwstorage_libsecret_set((backend_libsecret_context_t *)darktable.pwstorage->backend_context,
191                                         slot, table);
192 #endif
193       break;
194     case PW_STORAGE_BACKEND_KWALLET:
195 #ifdef HAVE_KWALLET
196       return dt_pwstorage_kwallet_set((backend_kwallet_context_t *)darktable.pwstorage->backend_context, slot,
197                                       table);
198 #endif
199       break;
200   }
201   return FALSE;
202 }
203 
204 /** Load (key,value) pairs. */
dt_pwstorage_get(const gchar * slot)205 GHashTable *dt_pwstorage_get(const gchar *slot)
206 {
207   switch(darktable.pwstorage->pw_storage_backend)
208   {
209     case PW_STORAGE_BACKEND_NONE:
210       dt_print(DT_DEBUG_PWSTORAGE, "[pwstorage_get] no backend. not reading anything.\n");
211       break;
212     case PW_STORAGE_BACKEND_LIBSECRET:
213 #if HAVE_LIBSECRET
214       return dt_pwstorage_libsecret_get((backend_libsecret_context_t *)darktable.pwstorage->backend_context,
215                                         slot);
216 #endif
217       break;
218     case PW_STORAGE_BACKEND_KWALLET:
219 #ifdef HAVE_KWALLET
220       return dt_pwstorage_kwallet_get((backend_kwallet_context_t *)darktable.pwstorage->backend_context, slot);
221 #endif
222       break;
223   }
224 
225   return g_hash_table_new(g_str_hash, g_str_equal);
226 }
227 
228 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
229 // vim: shiftwidth=2 expandtab tabstop=2 cindent
230 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
231