Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
backend_libsecret.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2014 Moritz Lipp.
4 Copyright (C) 2014, 2016 Roman Lebedev.
5 Copyright (C) 2014, 2016 Tobias Ellinghaus.
6 Copyright (C) 2022 Aurélien PIERRE.
7 Copyright (C) 2022 Martin Bařinka.
8
9 darktable is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 darktable is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with darktable. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "common/darktable.h"
24#include "backend_libsecret.h"
25#include "control/conf.h"
26
27#include <glib.h>
28#include <json-glib/json-glib.h>
29#include <libsecret/secret.h>
30
31// change this to SECRET_COLLECTION_SESSION for non-permanent storage
32#define SECRET_COLLECTION_DARKTABLE SECRET_COLLECTION_DEFAULT
33
34#define EMPTY_STRING(string) !*(string)
35
36static const SecretSchema *secret_darktable_get_schema(void) G_GNUC_CONST;
37#define SECRET_SCHEMA_DARKTABLE secret_darktable_get_schema()
38
39static GHashTable *secret_to_attributes(gchar *value);
40static gchar *attributes_to_secret(GHashTable *attributes);
41
42static const SecretSchema *secret_darktable_get_schema(void)
43{
44 static const SecretSchema darktable_schema = {
45 "org.darktable.Password",
46 SECRET_SCHEMA_NONE,
47 {
48 { "slot", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "magic", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "NULL", 0 },
49 }
50 };
51
52 return &darktable_schema;
53}
54
56{
57 GError *error = NULL;
58 backend_libsecret_context_t *context = calloc(1, sizeof(backend_libsecret_context_t));
59 if(IS_NULL_PTR(context))
60 {
61 return NULL;
62 }
63
64 SecretService *secret_service = secret_service_get_sync(SECRET_SERVICE_LOAD_COLLECTIONS, NULL, &error);
65 if(error)
66 {
67 fprintf(stderr, "[pwstorage_libsecret] error connecting to Secret Service: %s\n", error->message);
68 g_error_free(error);
69 if(secret_service) g_object_unref(secret_service);
71 return NULL;
72 }
73
74 if(secret_service)
75 g_object_unref(secret_service);
76
77 return context;
78}
79
81{
82 dt_free(context);
83}
84
85gboolean dt_pwstorage_libsecret_set(const backend_libsecret_context_t *context, const gchar *slot,
86 GHashTable *attributes)
87{
88 GError *error = NULL;
89 if(IS_NULL_PTR(context) || IS_NULL_PTR(slot) || EMPTY_STRING(slot) || IS_NULL_PTR(attributes))
90 {
91 return FALSE;
92 }
93
94 /* Convert attributes to secret */
95 char *secret_value = attributes_to_secret(attributes);
96 if(IS_NULL_PTR(secret_value))
97 {
98 return FALSE;
99 }
100
101 gchar *label = g_strdup_printf("ansel@%s", slot);
102 if(!label)
103 {
104 dt_free(secret_value);
105 return FALSE;
106 }
107
108 gboolean res = secret_password_store_sync(SECRET_SCHEMA_DARKTABLE,
110 label,
111 secret_value,
112 NULL,
113 &error,
114 "slot", slot,
115 "magic", PACKAGE_NAME,
116 NULL);
117 if(!res)
118 {
119 fprintf(stderr, "[pwstorage_libsecret] error storing password: %s\n", error->message);
120 g_error_free(error);
121 }
122
123 dt_free(secret_value);
124 dt_free(label);
125
126 return res;
127}
128
129GHashTable *dt_pwstorage_libsecret_get(const backend_libsecret_context_t *context, const gchar *slot)
130{
131 GError *error = NULL;
132 GHashTable *attributes;
133 gchar *secret_value = NULL;
134
135 if(IS_NULL_PTR(context) || IS_NULL_PTR(slot) || EMPTY_STRING(slot))
136 {
137 goto error;
138 }
139
140 secret_value = secret_password_lookup_sync(SECRET_SCHEMA_DARKTABLE,
141 NULL,
142 &error,
143 "slot", slot,
144 "magic", PACKAGE_NAME,
145 NULL);
146 if(error)
147 {
148 fprintf(stderr, "[pwstorage_libsecret] error retrieving password: %s\n", error->message);
149 g_error_free(error);
150 goto error;
151 }
152
153 attributes = secret_to_attributes(secret_value);
154
155 if(IS_NULL_PTR(attributes))
156 {
157 goto error;
158 }
159
160 goto end;
161
162error:
163 attributes = g_hash_table_new_full(g_str_hash, g_str_equal, dt_free_gpointer, dt_free_gpointer);
164
165end:
166 dt_free(secret_value);
167 return attributes;
168}
169
170static void append_pair_to_json(gpointer key, gpointer value, gpointer data)
171{
172 JsonBuilder *json_builder = (JsonBuilder *)data;
173
174 json_builder_set_member_name(json_builder, (char *)key);
175 json_builder_add_string_value(json_builder, (char *)value);
176}
177
178static gchar *attributes_to_secret(GHashTable *attributes)
179{
180 /* Build JSON */
181 JsonBuilder *json_builder = json_builder_new();
182 json_builder_begin_object(json_builder);
183 g_hash_table_foreach(attributes, append_pair_to_json, json_builder);
184 json_builder_end_object(json_builder);
185
186 /* Generate JSON */
187 JsonGenerator *json_generator = json_generator_new();
188 json_generator_set_root(json_generator, json_builder_get_root(json_builder));
189 gchar *json_data = json_generator_to_data(json_generator, 0);
190
191 g_object_unref(json_generator);
192 g_object_unref(json_builder);
193
194 return json_data;
195}
196
197static GHashTable *secret_to_attributes(gchar *secret)
198{
199 if(IS_NULL_PTR(secret) || EMPTY_STRING(secret))
200 {
201 return NULL;
202 }
203
204 /* Parse JSON from data */
205 JsonParser *json_parser = json_parser_new();
206
207 if(json_parser_load_from_data(json_parser, secret, -1, NULL) == FALSE)
208 {
209 g_object_unref(json_parser);
210 return NULL;
211 }
212
213 /* Read JSON */
214 JsonNode *json_root = json_parser_get_root(json_parser);
215 JsonReader *json_reader = json_reader_new(json_root);
216
217 GHashTable *attributes = g_hash_table_new_full(g_str_hash, g_str_equal, dt_free_gpointer, dt_free_gpointer);
218
219 /* Save each element as an attribute pair */
220 gint n_attributes = json_reader_count_members(json_reader);
221 for(gint i = 0; i < n_attributes; i++)
222 {
223 if(json_reader_read_element(json_reader, i) == FALSE)
224 {
225 continue;
226 }
227
228 const gchar *key = json_reader_get_member_name(json_reader);
229 const gchar *value = json_reader_get_string_value(json_reader);
230
231 g_hash_table_insert(attributes, (gpointer)g_strdup(key), (gpointer)g_strdup(value));
232
233 json_reader_end_element(json_reader);
234 }
235
236 g_object_unref(json_reader);
237 g_object_unref(json_parser);
238
239 return attributes;
240}
241
242// clang-format off
243// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
244// vim: shiftwidth=2 expandtab tabstop=2 cindent
245// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
246// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define FALSE
Definition ashift_lsd.c:158
gboolean dt_pwstorage_libsecret_set(const backend_libsecret_context_t *context, const gchar *slot, GHashTable *attributes)
const backend_libsecret_context_t * dt_pwstorage_libsecret_new()
static void append_pair_to_json(gpointer key, gpointer value, gpointer data)
static GHashTable * secret_to_attributes(gchar *secret)
static const SecretSchema * secret_darktable_get_schema(void)
#define SECRET_SCHEMA_DARKTABLE
GHashTable * dt_pwstorage_libsecret_get(const backend_libsecret_context_t *context, const gchar *slot)
static gchar * attributes_to_secret(GHashTable *attributes)
#define EMPTY_STRING(string)
#define SECRET_COLLECTION_DARKTABLE
void dt_pwstorage_libsecret_destroy(const backend_libsecret_context_t *context)
char * key
#define PACKAGE_NAME
static void dt_free_gpointer(gpointer ptr)
Definition darktable.h:463
#define dt_free(ptr)
Definition darktable.h:456
static const dt_aligned_pixel_simd_t value
Definition darktable.h:577
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281