LCOV - code coverage report
Current view: top level - libsecret - secret-schema.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 45 76 59.2 %
Date: 2024-02-08 14:44:34 Functions: 9 12 75.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 32 52 61.5 %

           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-password.h"
      18                 :            : #include "secret-private.h"
      19                 :            : #include "secret-value.h"
      20                 :            : 
      21                 :            : #include "libsecret/secret-enum-types.h"
      22                 :            : 
      23                 :            : #include "egg/egg-secure-memory.h"
      24                 :            : 
      25                 :            : /**
      26                 :            :  * SecretSchema:
      27                 :            :  * @name: the dotted name of the schema
      28                 :            :  * @flags: flags for the schema
      29                 :            :  * @attributes:  the attribute names and types of those attributes
      30                 :            :  *
      31                 :            :  * Represents a set of attributes that are stored with an item.
      32                 :            :  *
      33                 :            :  * These schemas are used for interoperability between various services storing
      34                 :            :  * the same types of items.
      35                 :            :  *
      36                 :            :  * Each schema has a name like `org.gnome.keyring.NetworkPassword`, and defines a
      37                 :            :  * set of attributes, and types (string, integer, boolean) for those attributes.
      38                 :            :  *
      39                 :            :  * Attributes are stored as strings in the Secret Service, and the attribute types
      40                 :            :  * simply define standard ways to store integer and boolean values as strings.
      41                 :            :  * Attributes are represented in libsecret via a [struct@GLib.HashTable] with
      42                 :            :  * string keys and values. Even for values that defined as an integer or boolean in
      43                 :            :  * the schema, the attribute values in the [struct@GLib.HashTable] are strings.
      44                 :            :  * Boolean values are stored as the strings 'true' and 'false'. Integer values are
      45                 :            :  * stored in decimal, with a preceding negative sign for negative integers.
      46                 :            :  *
      47                 :            :  * Schemas are handled entirely on the client side by this library. The name of the
      48                 :            :  * schema is automatically stored as an attribute on the item.
      49                 :            :  *
      50                 :            :  * Normally when looking up passwords only those with matching schema names are
      51                 :            :  * returned. If the schema @flags contain the `SECRET_SCHEMA_DONT_MATCH_NAME` flag,
      52                 :            :  * then lookups will not check that the schema name matches that on the item, only
      53                 :            :  * the schema's attributes are matched. This is useful when you are looking up
      54                 :            :  * items that are not stored by the libsecret library. Other libraries such as
      55                 :            :  * libgnome-keyring don't store the schema name.
      56                 :            :  *
      57                 :            :  * Additional schemas can be defined via the [struct@Schema] structure like this:
      58                 :            :  *
      59                 :            :  * ```c
      60                 :            :  * // in a header:
      61                 :            :  *
      62                 :            :  * const SecretSchema * example_get_schema (void) G_GNUC_CONST;
      63                 :            :  *
      64                 :            :  * #define EXAMPLE_SCHEMA  example_get_schema ()
      65                 :            :  *
      66                 :            :  *
      67                 :            :  * // in a .c file
      68                 :            :  *
      69                 :            :  * const SecretSchema *
      70                 :            :  * example_get_schema (void)
      71                 :            :  * {
      72                 :            :  *     static const SecretSchema the_schema = {
      73                 :            :  *         "org.example.Password", SECRET_SCHEMA_NONE,
      74                 :            :  *         {
      75                 :            :  *             {  "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
      76                 :            :  *             {  "string", SECRET_SCHEMA_ATTRIBUTE_STRING },
      77                 :            :  *             {  "even", SECRET_SCHEMA_ATTRIBUTE_BOOLEAN },
      78                 :            :  *             {  NULL, 0 },
      79                 :            :  *         }
      80                 :            :  *     };
      81                 :            :  *     return &the_schema;
      82                 :            :  * }
      83                 :            :  * ```
      84                 :            :  *
      85                 :            :  * Stability: Stable
      86                 :            :  */
      87                 :            : 
      88                 :            : /**
      89                 :            :  * SecretSchemaFlags:
      90                 :            :  * @SECRET_SCHEMA_NONE: no flags for the schema
      91                 :            :  * @SECRET_SCHEMA_DONT_MATCH_NAME: don't match the schema name when looking up or
      92                 :            :  *   removing passwords
      93                 :            :  *
      94                 :            :  * Flags for a #SecretSchema definition.
      95                 :            :  */
      96                 :            : 
      97                 :            : /**
      98                 :            :  * SecretSchemaAttribute:
      99                 :            :  * @name: name of the attribute
     100                 :            :  * @type: the type of the attribute
     101                 :            :  *
     102                 :            :  * An attribute in a #SecretSchema.
     103                 :            :  */
     104                 :            : 
     105                 :            : /**
     106                 :            :  * SecretSchemaAttributeType:
     107                 :            :  * @SECRET_SCHEMA_ATTRIBUTE_BOOLEAN: a boolean attribute, stored as 'true' or 'false'
     108                 :            :  * @SECRET_SCHEMA_ATTRIBUTE_INTEGER: an integer attribute, stored as a decimal
     109                 :            :  * @SECRET_SCHEMA_ATTRIBUTE_STRING: a utf-8 string attribute
     110                 :            :  *
     111                 :            :  * The type of an attribute in a [struct@SecretSchema].
     112                 :            :  *
     113                 :            :  * Attributes are stored as strings in the Secret Service, and the attribute
     114                 :            :  * types simply define standard ways to store integer and boolean values as
     115                 :            :  * strings.
     116                 :            :  */
     117                 :            : 
     118                 :            : static SecretSchemaAttribute *
     119                 :          0 : schema_attribute_copy (SecretSchemaAttribute *attribute)
     120                 :            : {
     121                 :            :         SecretSchemaAttribute *copy;
     122                 :            : 
     123                 :          0 :         copy = g_new0 (SecretSchemaAttribute, 1);
     124                 :          0 :         copy->name = g_strdup (attribute->name);
     125                 :          0 :         copy->type = attribute->type;
     126                 :            : 
     127                 :          0 :         return copy;
     128                 :            : }
     129                 :            : 
     130                 :            : static void
     131                 :          0 : schema_attribute_free (SecretSchemaAttribute *attribute)
     132                 :            : {
     133                 :          0 :         g_free ((gchar *)attribute->name);
     134                 :          0 :         g_free (attribute);
     135                 :          0 : }
     136                 :            : 
     137   [ +  -  +  -  :          2 : G_DEFINE_BOXED_TYPE (SecretSchemaAttribute, secret_schema_attribute,
                   +  - ]
     138                 :            :                      schema_attribute_copy, schema_attribute_free);
     139                 :            : 
     140                 :            : /**
     141                 :            :  * secret_schema_newv: (rename-to secret_schema_new)
     142                 :            :  * @name: the dotted name of the schema
     143                 :            :  * @flags: the flags for the schema
     144                 :            :  * @attribute_names_and_types: (element-type utf8 Secret.SchemaAttributeType): the attribute names and types of those attributes
     145                 :            :  *
     146                 :            :  * Using this function is not normally necessary from C code. This is useful
     147                 :            :  * for constructing #SecretSchema structures in bindings.
     148                 :            :  *
     149                 :            :  * A schema represents a set of attributes that are stored with an item. These
     150                 :            :  * schemas are used for interoperability between various services storing the
     151                 :            :  * same types of items.
     152                 :            :  *
     153                 :            :  * Each schema has an @name like `org.gnome.keyring.NetworkPassword`, and
     154                 :            :  * defines a set of attributes names, and types (string, integer, boolean) for
     155                 :            :  * those attributes.
     156                 :            :  *
     157                 :            :  * Each key in the @attributes table should be a attribute name strings, and
     158                 :            :  * the values in the table should be integers from the [enum@SchemaAttributeType]
     159                 :            :  * enumeration, representing the attribute type for each attribute name.
     160                 :            :  *
     161                 :            :  * Normally when looking up passwords only those with matching schema names are
     162                 :            :  * returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
     163                 :            :  * then lookups will not check that the schema name matches that on the item, only
     164                 :            :  * the schema's attributes are matched. This is useful when you are looking up items
     165                 :            :  * that are not stored by the libsecret library. Other libraries such as libgnome-keyring
     166                 :            :  * don't store the schema name.
     167                 :            :  *
     168                 :            :  * Returns: (transfer full): the new schema, which should be unreferenced with
     169                 :            :  *   [method@Schema.unref] when done
     170                 :            :  */
     171                 :            : SecretSchema *
     172                 :          3 : secret_schema_newv (const gchar *name,
     173                 :            :                     SecretSchemaFlags flags,
     174                 :            :                     GHashTable *attribute_names_and_types)
     175                 :            : {
     176                 :            :         SecretSchema *schema;
     177                 :            :         GHashTableIter iter;
     178                 :            :         GEnumClass *enumc;
     179                 :            :         gpointer value;
     180                 :            :         gpointer key;
     181                 :            :         gint type;
     182                 :          3 :         gint ind = 0;
     183                 :            : 
     184         [ -  + ]:          3 :         g_return_val_if_fail (name != NULL, NULL);
     185         [ -  + ]:          3 :         g_return_val_if_fail (attribute_names_and_types != NULL, NULL);
     186                 :            : 
     187                 :          3 :         schema = g_new0 (SecretSchema, 1);
     188                 :          3 :         schema->name = g_strdup (name);
     189                 :          3 :         schema->flags = flags;
     190                 :          3 :         schema->reserved = 1;
     191                 :            : 
     192         [ +  - ]:          3 :         if (attribute_names_and_types) {
     193                 :          3 :                 g_hash_table_iter_init (&iter, attribute_names_and_types);
     194         [ +  + ]:         12 :                 while (g_hash_table_iter_next (&iter, &key, &value)) {
     195                 :            : 
     196         [ -  + ]:          9 :                         if (ind >= G_N_ELEMENTS (schema->attributes)) {
     197                 :          0 :                                 g_warning ("too many attributes for schema, max %d",
     198                 :            :                                            (gint) G_N_ELEMENTS (schema->attributes));
     199                 :          0 :                                 break;
     200                 :            :                         }
     201                 :            : 
     202                 :          9 :                         type = GPOINTER_TO_INT (value);
     203                 :            : 
     204                 :          9 :                         enumc = G_ENUM_CLASS (g_type_class_ref (SECRET_TYPE_SCHEMA_ATTRIBUTE_TYPE));
     205         [ -  + ]:          9 :                         if (!g_enum_get_value (enumc, type)) {
     206                 :          0 :                                 g_warning ("invalid type for attribute %s", (gchar *)key);
     207                 :          0 :                                 type = -1;
     208                 :            :                         }
     209                 :            : 
     210                 :          9 :                         g_type_class_unref (enumc);
     211                 :            : 
     212         [ +  - ]:          9 :                         if (type >= 0) {
     213                 :          9 :                                 schema->attributes[ind].name = g_strdup (key);
     214                 :          9 :                                 schema->attributes[ind].type = type;
     215                 :            :                         }
     216                 :            : 
     217                 :          9 :                         ind++;
     218                 :            :                 }
     219                 :            :         }
     220                 :            : 
     221                 :          3 :         return schema;
     222                 :            : }
     223                 :            : 
     224                 :            : /**
     225                 :            :  * secret_schema_new: (skip)
     226                 :            :  * @name: the dotted name of the schema
     227                 :            :  * @flags: the flags for the schema
     228                 :            :  * @...: the attribute names and types, terminated with %NULL
     229                 :            :  *
     230                 :            :  * Using this function is not normally necessary from C code.
     231                 :            :  *
     232                 :            :  * A schema represents a set of attributes that are stored with an item. These
     233                 :            :  * schemas are used for interoperability between various services storing the
     234                 :            :  * same types of items.
     235                 :            :  *
     236                 :            :  * Each schema has an @name like `org.gnome.keyring.NetworkPassword`, and
     237                 :            :  * defines a set of attributes names, and types (string, integer, boolean) for
     238                 :            :  * those attributes.
     239                 :            :  *
     240                 :            :  * The variable argument list should contain pairs of a) The attribute name as
     241                 :            :  * a null-terminated string, followed by b) integers from the
     242                 :            :  * [enum@SchemaAttributeType] enumeration, representing the attribute type for
     243                 :            :  * each attribute name. The list of attributes should be terminated with a %NULL.
     244                 :            :  *
     245                 :            :  * Normally when looking up passwords only those with matching schema names are
     246                 :            :  * returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
     247                 :            :  * then lookups will not check that the schema name matches that on the item, only
     248                 :            :  * the schema's attributes are matched. This is useful when you are looking up items
     249                 :            :  * that are not stored by the libsecret library. Other libraries such as libgnome-keyring
     250                 :            :  * don't store the schema name.
     251                 :            :  *
     252                 :            :  * Returns: (transfer full): the new schema, which should be unreferenced with
     253                 :            :  *   [method@Schema.unref] when done
     254                 :            :  */
     255                 :            : SecretSchema *
     256                 :          0 : secret_schema_new (const gchar *name,
     257                 :            :                    SecretSchemaFlags flags,
     258                 :            :                    ...)
     259                 :            : {
     260                 :            :         SecretSchemaAttributeType type;
     261                 :            :         GHashTable *attributes;
     262                 :            :         SecretSchema *schema;
     263                 :            :         const gchar *attribute;
     264                 :            :         va_list va;
     265                 :            : 
     266         [ #  # ]:          0 :         g_return_val_if_fail (name != NULL, NULL);
     267                 :            : 
     268                 :          0 :         va_start (va, flags);
     269                 :          0 :         attributes = g_hash_table_new (g_str_hash, g_str_equal);
     270                 :            : 
     271         [ #  # ]:          0 :         while ((attribute = va_arg (va, const gchar *)) != NULL) {
     272                 :          0 :                 type = va_arg (va, SecretSchemaAttributeType);
     273                 :          0 :                 g_hash_table_insert (attributes, (gpointer *)attribute,
     274                 :          0 :                                      GINT_TO_POINTER (type));
     275                 :            :         }
     276                 :            : 
     277                 :          0 :         schema = secret_schema_newv (name, flags, attributes);
     278                 :            : 
     279                 :          0 :         g_hash_table_unref (attributes);
     280                 :          0 :         va_end (va);
     281                 :            : 
     282                 :          0 :         return schema;
     283                 :            : }
     284                 :            : 
     285                 :            : /**
     286                 :            :  * secret_schema_ref:
     287                 :            :  * @schema: the schema to reference
     288                 :            :  *
     289                 :            :  * Adds a reference to the #SecretSchema.
     290                 :            :  *
     291                 :            :  * It is not normally necessary to call this function from C code, and is
     292                 :            :  * mainly present for the sake of bindings. If the @schema was statically
     293                 :            :  * allocated, then this function will copy the schema.
     294                 :            :  *
     295                 :            :  * Returns: (transfer full): the referenced schema, which should be later
     296                 :            :  *   unreferenced with [method@Schema.unref]
     297                 :            :  */
     298                 :            : SecretSchema *
     299                 :         16 : secret_schema_ref (SecretSchema *schema)
     300                 :            : {
     301                 :            :         SecretSchema *result;
     302                 :            :         gint i;
     303                 :            : 
     304         [ -  + ]:         16 :         g_return_val_if_fail (schema != NULL, NULL);
     305                 :            : 
     306                 :            :         /* If it's static, then copy it */
     307         [ +  - ]:         16 :         if (g_atomic_int_get (&schema->reserved) > 0) {
     308                 :         16 :                 g_atomic_int_inc (&schema->reserved);
     309                 :         16 :                 result = schema;
     310                 :            :         } else {
     311                 :          0 :                 result = g_new0 (SecretSchema, 1);
     312                 :          0 :                 result->reserved = 1;
     313                 :          0 :                 result->name = g_strdup (schema->name);
     314                 :            : 
     315         [ #  # ]:          0 :                 for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++) {
     316                 :          0 :                         result->attributes[i].name = g_strdup (schema->attributes[i].name);
     317                 :          0 :                         result->attributes[i].type = schema->attributes[i].type;
     318                 :            :                 }
     319                 :            :         }
     320                 :            : 
     321                 :         16 :         return result;
     322                 :            : }
     323                 :            : 
     324                 :            : const SecretSchema *
     325                 :         50 : _secret_schema_ref_if_nonstatic (const SecretSchema *schema)
     326                 :            : {
     327   [ +  +  +  + ]:         50 :         if (schema && g_atomic_int_get (&schema->reserved) > 0)
     328                 :         16 :                 secret_schema_ref ((SecretSchema *)schema);
     329                 :            : 
     330                 :         50 :         return schema;
     331                 :            : }
     332                 :            : 
     333                 :            : /**
     334                 :            :  * secret_schema_unref:
     335                 :            :  * @schema: the schema to reference
     336                 :            :  *
     337                 :            :  * Releases a reference to the #SecretSchema.
     338                 :            :  *
     339                 :            :  * If the last reference is released then the schema will be freed.
     340                 :            :  *
     341                 :            :  * It is not normally necessary to call this function from C code, and is
     342                 :            :  * mainly present for the sake of bindings. It is an error to call this for
     343                 :            :  * a @schema that was statically allocated.
     344                 :            :  */
     345                 :            : void
     346                 :         19 : secret_schema_unref (SecretSchema *schema)
     347                 :            : {
     348         [ -  + ]:         19 :         g_return_if_fail (schema != NULL);
     349                 :            :         /* statically-allocated or invalid SecretSchema */
     350         [ -  + ]:         19 :         g_return_if_fail (g_atomic_int_get (&schema->reserved) > 0);
     351                 :            : 
     352         [ +  + ]:         19 :         if (g_atomic_int_dec_and_test (&schema->reserved)) {
     353                 :            :                 gint i;
     354                 :          3 :                 g_free ((gpointer)schema->name);
     355         [ +  + ]:         99 :                 for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++)
     356                 :         96 :                         g_free ((gpointer)schema->attributes[i].name);
     357                 :          3 :                 g_free (schema);
     358                 :            :         }
     359                 :            : }
     360                 :            : 
     361                 :            : void
     362                 :         50 : _secret_schema_unref_if_nonstatic (const SecretSchema *schema)
     363                 :            : {
     364   [ +  +  +  + ]:         50 :         if (schema && g_atomic_int_get (&schema->reserved) > 0)
     365                 :         16 :                 secret_schema_unref ((SecretSchema *)schema);
     366                 :         50 : }
     367                 :            : 
     368   [ +  +  +  -  :         22 : G_DEFINE_BOXED_TYPE (SecretSchema, secret_schema, secret_schema_ref, secret_schema_unref);
                   +  + ]

Generated by: LCOV version 1.14