LCOV - code coverage report
Current view: top level - libsecret - secret-attributes.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 94 132 71.2 %
Date: 2024-02-08 14:44:34 Functions: 6 7 85.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 58 86 67.4 %

           Branch data     Line data    Source code
       1                 :            : /* libsecret - GLib wrapper for Secret Service
       2                 :            :  *
       3                 :            :  * Copyright 2011 Collabora Ltd.
       4                 :            :  *
       5                 :            :  * This program is free software: you can redistribute it and/or modify
       6                 :            :  * it under the terms of the GNU Lesser General Public License as published
       7                 :            :  * by the Free Software Foundation; either version 2.1 of the licence or (at
       8                 :            :  * your option) any later version.
       9                 :            :  *
      10                 :            :  * See the included COPYING file for more information.
      11                 :            :  *
      12                 :            :  * Author: Stef Walter <stefw@gnome.org>
      13                 :            :  */
      14                 :            : 
      15                 :            : #include "config.h"
      16                 :            : 
      17                 :            : #include "secret-attributes.h"
      18                 :            : #include "secret-private.h"
      19                 :            : 
      20                 :            : #include <string.h>
      21                 :            : 
      22                 :            : GVariant *
      23                 :         90 : _secret_attributes_to_variant (GHashTable *attributes,
      24                 :            :                                const gchar *schema_name)
      25                 :            : {
      26                 :            :         GHashTableIter iter;
      27                 :            :         GVariantBuilder builder;
      28                 :            :         const gchar *name;
      29                 :            :         const gchar *value;
      30                 :            : 
      31         [ -  + ]:         90 :         g_return_val_if_fail (attributes != NULL, NULL);
      32                 :            : 
      33                 :         90 :         g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
      34                 :            : 
      35                 :         90 :         g_hash_table_iter_init (&iter, attributes);
      36         [ +  + ]:        269 :         while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&value)) {
      37   [ +  +  +  - ]:        179 :                 if (!schema_name || !g_str_equal (name, "xdg:schema"))
      38                 :        179 :                         g_variant_builder_add (&builder, "{ss}", name, value);
      39                 :            :         }
      40                 :            : 
      41         [ +  + ]:         90 :         if (schema_name)
      42                 :         83 :                 g_variant_builder_add (&builder, "{ss}", "xdg:schema", schema_name);
      43                 :            : 
      44                 :         90 :         return g_variant_builder_end (&builder);
      45                 :            : }
      46                 :            : 
      47                 :            : GHashTable *
      48                 :          8 : _secret_attributes_for_variant (GVariant *variant)
      49                 :            : {
      50                 :            :         GVariantIter iter;
      51                 :            :         GHashTable *attributes;
      52                 :            :         gchar *value;
      53                 :            :         gchar *key;
      54                 :            : 
      55                 :          8 :         attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
      56                 :            : 
      57                 :          8 :         g_variant_iter_init (&iter, variant);
      58         [ +  + ]:         36 :         while (g_variant_iter_next (&iter, "{ss}", &key, &value))
      59                 :         28 :                 g_hash_table_insert (attributes, key, value);
      60                 :            : 
      61                 :          8 :         return attributes;
      62                 :            : }
      63                 :            : 
      64                 :            : /**
      65                 :            :  * secret_attributes_build: (skip)
      66                 :            :  * @schema: the schema for the attributes
      67                 :            :  * @...: the attribute keys and values, terminated with %NULL
      68                 :            :  *
      69                 :            :  * Build up a hash table of attribute values.
      70                 :            :  *
      71                 :            :  * The variable argument list should contain pairs of a) The attribute name as
      72                 :            :  * a null-terminated string, followed by b) attribute value, either a character
      73                 :            :  * string, an int number, or a gboolean value, as defined in the password
      74                 :            :  * @schema. The list of attributes should be terminated with a %NULL.
      75                 :            :  *
      76                 :            :  * Returns: (transfer full) (element-type utf8 utf8): a new table of
      77                 :            :  *   attributes, to be released with [func@GLib.HashTable.unref]
      78                 :            :  */
      79                 :            : GHashTable *
      80                 :         15 : secret_attributes_build (const SecretSchema *schema,
      81                 :            :                          ...)
      82                 :            : {
      83                 :            :         GHashTable *attributes;
      84                 :            :         va_list va;
      85                 :            : 
      86                 :         15 :         va_start (va, schema);
      87                 :         15 :         attributes = secret_attributes_buildv (schema, va);
      88                 :         15 :         va_end (va);
      89                 :            : 
      90                 :         15 :         return attributes;
      91                 :            : }
      92                 :            : 
      93                 :            : /**
      94                 :            :  * secret_attributes_buildv: (skip)
      95                 :            :  * @schema: the schema for the attributes
      96                 :            :  * @va: the attribute keys and values, terminated with %NULL
      97                 :            :  *
      98                 :            :  * Build up a hash table of attribute values.
      99                 :            :  *
     100                 :            :  * The variable argument list should contain pairs of a) The attribute name as
     101                 :            :  * a null-terminated string, followed by b) attribute value, either a character
     102                 :            :  * string, an int number, or a gboolean value, as defined in the password
     103                 :            :  * @schema. The list of attributes should be terminated with a %NULL.
     104                 :            :  *
     105                 :            :  * Returns: (transfer full) (element-type utf8 utf8): a new table of
     106                 :            :  *   attributes, to be released with [func@GLib.HashTable.unref]
     107                 :            :  */
     108                 :            : GHashTable *
     109                 :         37 : secret_attributes_buildv (const SecretSchema *schema,
     110                 :            :                           va_list va)
     111                 :            : {
     112                 :            :         const gchar *attribute_name;
     113                 :            :         SecretSchemaAttributeType type;
     114                 :            :         GHashTable *attributes;
     115                 :            :         const gchar *string;
     116                 :            :         gboolean type_found;
     117                 :         37 :         gchar *value = NULL;
     118                 :            :         gboolean boolean;
     119                 :            :         gint integer;
     120                 :            :         gint i;
     121                 :            : 
     122         [ -  + ]:         37 :         g_return_val_if_fail (schema != NULL, NULL);
     123                 :            : 
     124                 :         37 :         attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
     125                 :            : 
     126                 :            :         for (;;) {
     127                 :        120 :                 attribute_name = va_arg (va, const gchar *);
     128         [ +  + ]:        120 :                 if (attribute_name == NULL)
     129                 :         37 :                         break;
     130                 :            : 
     131                 :         83 :                 type_found = FALSE;
     132         [ +  - ]:        160 :                 for (i = 0; i < G_N_ELEMENTS (schema->attributes); ++i) {
     133         [ -  + ]:        160 :                         if (!schema->attributes[i].name)
     134                 :          0 :                                 break;
     135         [ +  + ]:        160 :                         if (g_str_equal (schema->attributes[i].name, attribute_name)) {
     136                 :         83 :                                 type_found = TRUE;
     137                 :         83 :                                 type = schema->attributes[i].type;
     138                 :         83 :                                 break;
     139                 :            :                         }
     140                 :            :                 }
     141                 :            : 
     142         [ -  + ]:         83 :                 if (!type_found) {
     143                 :          0 :                         g_critical ("The attribute '%s' was not found in the password schema.", attribute_name);
     144                 :          0 :                         g_hash_table_unref (attributes);
     145                 :          0 :                         return NULL;
     146                 :            :                 }
     147                 :            : 
     148   [ +  +  +  - ]:         83 :                 switch (type) {
     149                 :         24 :                 case SECRET_SCHEMA_ATTRIBUTE_BOOLEAN:
     150                 :         24 :                         boolean = va_arg (va, gboolean);
     151         [ +  + ]:         24 :                         value = g_strdup (boolean ? "true" : "false");
     152                 :         24 :                         break;
     153                 :         29 :                 case SECRET_SCHEMA_ATTRIBUTE_STRING:
     154                 :         29 :                         string = va_arg (va, gchar *);
     155         [ -  + ]:         29 :                         if (string == NULL) {
     156                 :          0 :                                 g_critical ("The value for attribute '%s' was NULL", attribute_name);
     157                 :          0 :                                 return NULL;
     158                 :            :                         }
     159         [ -  + ]:         29 :                         if (!g_utf8_validate (string, -1, NULL)) {
     160                 :          0 :                                 g_critical ("The value for attribute '%s' was not a valid UTF-8 string.", attribute_name);
     161                 :          0 :                                 g_hash_table_unref (attributes);
     162                 :          0 :                                 return NULL;
     163                 :            :                         }
     164                 :         29 :                         value = g_strdup (string);
     165                 :         29 :                         break;
     166                 :         30 :                 case SECRET_SCHEMA_ATTRIBUTE_INTEGER:
     167                 :         30 :                         integer = va_arg (va, gint);
     168                 :         30 :                         value = g_strdup_printf ("%d", integer);
     169                 :         30 :                         break;
     170                 :          0 :                 default:
     171                 :          0 :                         g_critical ("The password attribute '%s' has an invalid type in the password schema.", attribute_name);
     172                 :          0 :                         g_hash_table_unref (attributes);
     173                 :          0 :                         return NULL;
     174                 :            :                 }
     175                 :            : 
     176                 :         83 :                 g_hash_table_insert (attributes, g_strdup (attribute_name), value);
     177                 :            :         }
     178                 :            : 
     179                 :         37 :         return attributes;
     180                 :            : }
     181                 :            : 
     182                 :            : /**
     183                 :            :  * secret_attributes_validate:
     184                 :            :  * @schema: the schema for the attributes
     185                 :            :  * @attributes: the attributes to be validated
     186                 :            :  * @error: place to report errors encountered
     187                 :            :  *
     188                 :            :  * Check if attributes are valid according to the provided schema.
     189                 :            :  *
     190                 :            :  * Verifies schema name if available, attribute names and parsing
     191                 :            :  * of attribute values.
     192                 :            :  *
     193                 :            :  * Returns: whether or not the given attributes table is valid
     194                 :            :  */
     195                 :            : gboolean
     196                 :        181 : secret_attributes_validate (const SecretSchema *schema,
     197                 :            :                             GHashTable *attributes,
     198                 :            :                             GError **error)
     199                 :            : {
     200                 :            :         const SecretSchemaAttribute *attribute;
     201                 :            :         GHashTableIter iter;
     202                 :        181 :         gboolean any = FALSE;
     203                 :            :         gchar *key;
     204                 :            :         gchar *value;
     205                 :            :         gchar *end;
     206                 :            :         gint i;
     207                 :            : 
     208         [ -  + ]:        181 :         g_return_val_if_fail (schema != NULL, FALSE);
     209                 :            : 
     210                 :        181 :         g_hash_table_iter_init (&iter, attributes);
     211         [ +  + ]:        543 :         while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) {
     212                 :        362 :                 any = TRUE;
     213                 :            : 
     214                 :            :                 /* If the 'xdg:schema' meta-attribute is present,
     215                 :            :                    ensure that it is consistent with the schema
     216                 :            :                    name. */
     217         [ +  + ]:        362 :                 if (g_str_equal (key, "xdg:schema")) {
     218         [ -  + ]:          1 :                         if (!g_str_equal (value, schema->name)) {
     219                 :          0 :                                 g_set_error_literal (error,
     220                 :            :                                                      SECRET_ERROR,
     221                 :            :                                                      SECRET_ERROR_MISMATCHED_SCHEMA,
     222                 :            :                                                      "Schema attribute doesn't match schema name");
     223                 :          0 :                                 return FALSE;
     224                 :            :                         }
     225                 :          1 :                         continue;
     226                 :            :                 }
     227                 :            : 
     228                 :            :                 /* Pass through libgnomekeyring specific attributes */
     229   [ +  -  -  +  :        361 :                 if (g_str_has_prefix (key, "gkr:"))
             +  -  +  + ]
     230                 :          1 :                         continue;
     231                 :            : 
     232                 :            :                 /* Find the attribute */
     233                 :        360 :                 attribute = NULL;
     234         [ +  - ]:        656 :                 for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++) {
     235         [ -  + ]:        656 :                         if (schema->attributes[i].name == NULL)
     236                 :          0 :                                 break;
     237         [ +  + ]:        656 :                         if (g_str_equal (schema->attributes[i].name, key)) {
     238                 :        360 :                                 attribute = &schema->attributes[i];
     239                 :        360 :                                 break;
     240                 :            :                         }
     241                 :            :                 }
     242                 :            : 
     243         [ -  + ]:        360 :                 if (attribute == NULL) {
     244                 :          0 :                         g_set_error (error,
     245                 :            :                                      SECRET_ERROR,
     246                 :            :                                      SECRET_ERROR_NO_MATCHING_ATTRIBUTE,
     247                 :            :                                      "Schema does not contain any attributes matching %s",
     248                 :            :                                      key);
     249                 :          0 :                         return FALSE;
     250                 :            :                 }
     251                 :            : 
     252   [ +  +  +  - ]:        360 :                 switch (attribute->type) {
     253                 :         91 :                 case SECRET_SCHEMA_ATTRIBUTE_BOOLEAN:
     254   [ +  +  -  + ]:         91 :                         if (!g_str_equal (value, "true") && !g_str_equal (value, "false")) {
     255                 :          0 :                                 g_set_error (error,
     256                 :            :                                              SECRET_ERROR,
     257                 :            :                                              SECRET_ERROR_WRONG_TYPE,
     258                 :            :                                              "Attribute %s could not be parsed into a boolean",
     259                 :            :                                              key);
     260                 :          0 :                                 return FALSE;
     261                 :            :                         }
     262                 :         91 :                         break;
     263                 :        157 :                 case SECRET_SCHEMA_ATTRIBUTE_INTEGER:
     264                 :        157 :                         end = NULL;
     265                 :        157 :                         g_ascii_strtoll (value, &end, 10);
     266   [ +  -  -  + ]:        157 :                         if (!end || end[0] != '\0') {
     267                 :          0 :                                 g_set_error (error,
     268                 :            :                                              SECRET_ERROR,
     269                 :            :                                              SECRET_ERROR_WRONG_TYPE,
     270                 :            :                                              "Attribute %s could not be parsed into an integer",
     271                 :            :                                              key);
     272                 :          0 :                                 return FALSE;
     273                 :            :                         }
     274                 :        157 :                         break;
     275                 :        112 :                 case SECRET_SCHEMA_ATTRIBUTE_STRING:
     276         [ -  + ]:        112 :                         if (!g_utf8_validate (value, -1, NULL)) {
     277                 :          0 :                                 g_set_error (error,
     278                 :            :                                              SECRET_ERROR,
     279                 :            :                                              SECRET_ERROR_WRONG_TYPE,
     280                 :            :                                              "Attribute %s could not be parsed into a string",
     281                 :            :                                              key);
     282                 :          0 :                                 return FALSE;
     283                 :            :                         }
     284                 :        112 :                         break;
     285                 :          0 :                 default:
     286                 :          0 :                         g_set_error (error,
     287                 :            :                                      SECRET_ERROR,
     288                 :            :                                      SECRET_ERROR_WRONG_TYPE,
     289                 :            :                                      "%s: Invalid attribute type",
     290                 :            :                                      key);
     291                 :          0 :                         return FALSE;
     292                 :            :                 }
     293                 :            :         }
     294                 :            : 
     295                 :            :         /* Nothing to match on, resulting search would match everything :S */
     296   [ +  +  +  + ]:        181 :         if (!any && schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME) {
     297                 :          1 :                 g_set_error_literal (error,
     298                 :            :                                      SECRET_ERROR,
     299                 :            :                                      SECRET_ERROR_EMPTY_TABLE,
     300                 :            :                                      "Must have at least one attribute to check");
     301                 :          1 :                 return FALSE;
     302                 :            :         }
     303                 :            : 
     304                 :        180 :         return TRUE;
     305                 :            : }
     306                 :            : 
     307                 :            : // Private function to be used internally
     308                 :            : gboolean
     309                 :        181 : _secret_attributes_validate (const SecretSchema *schema,
     310                 :            :                              GHashTable *attributes,
     311                 :            :                              const char *pretty_function,
     312                 :            :                              gboolean matching)
     313                 :            : {
     314                 :        181 :         GError *error = NULL;
     315                 :            : 
     316         [ +  + ]:        181 :         if (!secret_attributes_validate (schema, attributes, &error)) {
     317                 :            :                 // if matching is false, an empty table is fine
     318   [ +  -  +  - ]:          1 :                 if ((!matching) && (error->code == SECRET_ERROR_EMPTY_TABLE)) {
     319                 :          1 :                         g_error_free (error);
     320                 :          1 :                         return TRUE;
     321                 :            :                 }
     322                 :            :                 
     323                 :          0 :                 g_warning ("%s: error validating schema: %s", pretty_function, error->message);
     324                 :          0 :                 g_error_free (error);
     325                 :          0 :                 return FALSE;
     326                 :            :         }
     327                 :        180 :         return TRUE;
     328                 :            : }
     329                 :            : 
     330                 :            : 
     331                 :            : GHashTable *
     332                 :          0 : _secret_attributes_copy (GHashTable *attributes)
     333                 :            : {
     334                 :            :         GHashTableIter iter;
     335                 :            :         GHashTable *copy;
     336                 :            :         gchar *key;
     337                 :            :         gchar *value;
     338                 :            : 
     339         [ #  # ]:          0 :         if (attributes == NULL)
     340                 :          0 :                 return NULL;
     341                 :            : 
     342                 :          0 :         copy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
     343                 :            : 
     344                 :          0 :         g_hash_table_iter_init (&iter, attributes);
     345         [ #  # ]:          0 :         while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
     346                 :          0 :                 g_hash_table_insert (copy, g_strdup (key), g_strdup (value));
     347                 :            : 
     348                 :          0 :         return copy;
     349                 :            : }

Generated by: LCOV version 1.14