"Fossies" - the Fresh Open Source Software Archive

Member "darktable-3.6.1/src/common/pwstorage/backend_libsecret.c" (10 Sep 2021, 7525 Bytes) of package /linux/misc/darktable-3.6.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "backend_libsecret.c" see the Fossies "Dox" file reference documentation.

    1 // This file is part of darktable
    2 //
    3 // Copyright (c) 2014 Moritz Lipp <mlq@pwmt.org>.
    4 // Copyright (c) 2016 tobias ellinghaus <me@houz.org>.
    5 //
    6 // Permission is hereby granted, free of charge, to any person obtaining a copy
    7 // of this software and associated documentation files (the "Software"), to deal
    8 // in the Software without restriction, including without limitation the rights
    9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10 // copies of the Software, and to permit persons to whom the Software is
   11 // furnished to do so, subject to the following conditions:
   12 //
   13 // The above copyright notice and this permission notice shall be included in
   14 // all copies or substantial portions of the Software.
   15 //
   16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22 // THE SOFTWARE.
   23 
   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 
   36 static const SecretSchema *secret_darktable_get_schema(void) G_GNUC_CONST;
   37 #define SECRET_SCHEMA_DARKTABLE secret_darktable_get_schema()
   38 
   39 static GHashTable *secret_to_attributes(gchar *value);
   40 static gchar *attributes_to_secret(GHashTable *attributes);
   41 
   42 static 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 
   55 const backend_libsecret_context_t *dt_pwstorage_libsecret_new()
   56 {
   57   GError *error = NULL;
   58   backend_libsecret_context_t *context = calloc(1, sizeof(backend_libsecret_context_t));
   59   if(context == NULL)
   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);
   70     dt_pwstorage_libsecret_destroy(context);
   71     return NULL;
   72   }
   73 
   74   if(secret_service)
   75     g_object_unref(secret_service);
   76 
   77   return context;
   78 }
   79 
   80 void dt_pwstorage_libsecret_destroy(const backend_libsecret_context_t *context)
   81 {
   82   free((backend_libsecret_context_t *)context);
   83 }
   84 
   85 gboolean dt_pwstorage_libsecret_set(const backend_libsecret_context_t *context, const gchar *slot,
   86                                     GHashTable *attributes)
   87 {
   88   GError *error = NULL;
   89   if(context == NULL || slot == NULL || EMPTY_STRING(slot) || attributes == NULL)
   90   {
   91     return FALSE;
   92   }
   93 
   94   /* Convert attributes to secret */
   95   char *secret_value = attributes_to_secret(attributes);
   96   if(secret_value == NULL)
   97   {
   98     return FALSE;
   99   }
  100 
  101   gchar *label = g_strdup_printf("darktable@%s", slot);
  102   if(!label)
  103   {
  104     g_free(secret_value);
  105     return FALSE;
  106   }
  107 
  108   gboolean res = secret_password_store_sync(SECRET_SCHEMA_DARKTABLE,
  109                                             SECRET_COLLECTION_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   g_free(secret_value);
  124   g_free(label);
  125 
  126   return res;
  127 }
  128 
  129 GHashTable *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(context == NULL || slot == NULL || 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(attributes == NULL)
  156   {
  157     goto error;
  158   }
  159 
  160   goto end;
  161 
  162 error:
  163   attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
  164 
  165 end:
  166   g_free(secret_value);
  167   return attributes;
  168 }
  169 
  170 static 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 
  178 static 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 
  197 static GHashTable *secret_to_attributes(gchar *secret)
  198 {
  199   if(secret == NULL || 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, g_free, g_free);
  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 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
  243 // vim: shiftwidth=2 expandtab tabstop=2 cindent
  244 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;