LCOV - code coverage report
Current view: top level - daemon/dbus - gkd-secret-property.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 65.6 % 244 160
Test Date: 2024-04-08 13:24:42 Functions: 83.3 % 18 15

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2008 Stefan Walter
       5              :  *
       6              :  * This program is free software; you can redistribute it and/or modify
       7              :  * it under the terms of the GNU Lesser General Public License as
       8              :  * published by the Free Software Foundation; either version 2.1 of
       9              :  * the License, or (at your option) any later version.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this program; if not, see
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "gkd-secret-property.h"
      24              : 
      25              : #include "pkcs11/pkcs11i.h"
      26              : 
      27              : #include <string.h>
      28              : 
      29              : 
      30              : typedef enum _DataType {
      31              :         DATA_TYPE_INVALID = 0,
      32              : 
      33              :         /*
      34              :          * The attribute is a CK_BBOOL.
      35              :          * Property is DBUS_TYPE_BOOLEAN
      36              :          */
      37              :         DATA_TYPE_BOOL,
      38              : 
      39              :         /*
      40              :          * The attribute is in the format: "%Y%m%d%H%M%S00"
      41              :          * Property is DBUS_TYPE_UINT64 since 1970 epoch.
      42              :          */
      43              :         DATA_TYPE_TIME,
      44              : 
      45              :         /*
      46              :          * The attribute is a CK_UTF8_CHAR string, not null-terminated
      47              :          * Property is a DBUS_TYPE_STRING
      48              :          */
      49              :         DATA_TYPE_STRING,
      50              : 
      51              :         /*
      52              :          * The attribute is in the format: name\0value\0name2\0value2
      53              :          * Property is dbus dictionary of strings: a{ss}
      54              :          */
      55              :         DATA_TYPE_FIELDS
      56              : } DataType;
      57              : 
      58              : /* -----------------------------------------------------------------------------
      59              :  * INTERNAL
      60              :  */
      61              : 
      62              : static gboolean
      63           57 : property_to_attribute (const gchar *prop_name, const gchar *interface,
      64              :                        CK_ATTRIBUTE_TYPE *attr_type, DataType *data_type)
      65              : {
      66           57 :         g_return_val_if_fail (prop_name, FALSE);
      67           57 :         g_assert (attr_type);
      68           57 :         g_assert (data_type);
      69              : 
      70              :         /* If an interface is desired, check that it matches, and remove */
      71           57 :         if (interface) {
      72            4 :                 if (!g_str_has_prefix (prop_name, interface))
      73            0 :                         return FALSE;
      74              : 
      75            4 :                 prop_name += strlen (interface);
      76            4 :                 if (prop_name[0] != '.')
      77            0 :                         return FALSE;
      78            4 :                 ++prop_name;
      79              :         }
      80              : 
      81           57 :         if (g_str_equal (prop_name, "Label")) {
      82            9 :                 *attr_type = CKA_LABEL;
      83            9 :                 *data_type = DATA_TYPE_STRING;
      84              : 
      85              :         /* Non-standard property for type schema */
      86           48 :         } else if (g_str_equal (prop_name, "Type")) {
      87            1 :                 *attr_type = CKA_G_SCHEMA;
      88            1 :                 *data_type = DATA_TYPE_STRING;
      89              : 
      90           47 :         } else if (g_str_equal (prop_name, "Locked")) {
      91           44 :                 *attr_type = CKA_G_LOCKED;
      92           44 :                 *data_type = DATA_TYPE_BOOL;
      93              : 
      94            3 :         } else if (g_str_equal (prop_name, "Created")) {
      95            1 :                 *attr_type = CKA_G_CREATED;
      96            1 :                 *data_type = DATA_TYPE_TIME;
      97              : 
      98            2 :         } else if (g_str_equal (prop_name, "Modified")) {
      99            1 :                 *attr_type = CKA_G_MODIFIED;
     100            1 :                 *data_type = DATA_TYPE_TIME;
     101              : 
     102            1 :         } else if (g_str_equal (prop_name, "Attributes")) {
     103            1 :                 *attr_type = CKA_G_FIELDS;
     104            1 :                 *data_type = DATA_TYPE_FIELDS;
     105              : 
     106              :         } else {
     107            0 :                 return FALSE;
     108              :         }
     109              : 
     110           57 :         return TRUE;
     111              : }
     112              : 
     113              : static gboolean
     114           49 : attribute_to_property (CK_ATTRIBUTE_TYPE attr_type, const gchar **prop_name, DataType *data_type)
     115              : {
     116           49 :         g_assert (prop_name);
     117           49 :         g_assert (data_type);
     118              : 
     119           49 :         switch (attr_type) {
     120            1 :         case CKA_LABEL:
     121            1 :                 *prop_name = "Label";
     122            1 :                 *data_type = DATA_TYPE_STRING;
     123            1 :                 break;
     124              :         /* Non-standard property for type schema */
     125            1 :         case CKA_G_SCHEMA:
     126            1 :                 *prop_name = "Type";
     127            1 :                 *data_type = DATA_TYPE_STRING;
     128            1 :                 break;
     129           44 :         case CKA_G_LOCKED:
     130           44 :                 *prop_name = "Locked";
     131           44 :                 *data_type = DATA_TYPE_BOOL;
     132           44 :                 break;
     133            1 :         case CKA_G_CREATED:
     134            1 :                 *prop_name = "Created";
     135            1 :                 *data_type = DATA_TYPE_TIME;
     136            1 :                 break;
     137            1 :         case CKA_G_MODIFIED:
     138            1 :                 *prop_name = "Modified";
     139            1 :                 *data_type = DATA_TYPE_TIME;
     140            1 :                 break;
     141            1 :         case CKA_G_FIELDS:
     142            1 :                 *prop_name = "Attributes";
     143            1 :                 *data_type = DATA_TYPE_FIELDS;
     144            1 :                 break;
     145            0 :         default:
     146            0 :                 return FALSE;
     147              :         };
     148              : 
     149           49 :         return TRUE;
     150              : }
     151              : 
     152              : typedef GVariant * (*IterAppendFunc) (const GckAttribute *);
     153              : typedef gboolean (*IterGetFunc) (GVariant *, gulong, GckBuilder *);
     154              : 
     155              : static GVariant *
     156            2 : iter_append_string (const GckAttribute *attr)
     157              : {
     158            2 :         g_assert (attr);
     159              : 
     160            2 :         if (attr->length == 0) {
     161            1 :                 return g_variant_new_string ("");
     162              :         } else {
     163            1 :                 return g_variant_new_take_string (g_strndup ((const gchar*)attr->value, attr->length));
     164              :         }
     165              : }
     166              : 
     167              : static gboolean
     168            6 : iter_get_string (GVariant *variant,
     169              :                  gulong attr_type,
     170              :                  GckBuilder *builder)
     171              : {
     172              :         const char *value;
     173              : 
     174            6 :         g_assert (variant != NULL);
     175            6 :         g_assert (builder != NULL);
     176              : 
     177            6 :         value = g_variant_get_string (variant, NULL);
     178            6 :         if (value == NULL)
     179            0 :                 value = "";
     180            6 :         gck_builder_add_string (builder, attr_type, value);
     181            6 :         return TRUE;
     182              : }
     183              : 
     184              : static GVariant *
     185           44 : iter_append_bool (const GckAttribute *attr)
     186              : {
     187           44 :         g_assert (attr);
     188              : 
     189           44 :         return g_variant_new_boolean (gck_attribute_get_boolean (attr));
     190              : }
     191              : 
     192              : static gboolean
     193            0 : iter_get_bool (GVariant *variant,
     194              :                gulong attr_type,
     195              :                GckBuilder *builder)
     196              : {
     197              :         gboolean value;
     198              : 
     199            0 :         g_assert (variant != NULL);
     200            0 :         g_assert (builder != NULL);
     201              : 
     202            0 :         value = g_variant_get_boolean (variant);
     203            0 :         gck_builder_add_boolean (builder, attr_type, value);
     204            0 :         return TRUE;
     205              : }
     206              : 
     207              : static GVariant *
     208            2 : iter_append_time (const GckAttribute *attr)
     209              : {
     210              :         guint64 value;
     211              :         struct tm tm;
     212              :         gchar buf[15];
     213              :         time_t time;
     214              : 
     215            2 :         g_assert (attr);
     216              : 
     217            2 :         if (attr->length == 0) {
     218            0 :                 value = 0;
     219              : 
     220            2 :         } else if (!attr->value || attr->length != 16) {
     221            0 :                 g_warning ("invalid length of time attribute");
     222            0 :                 value = 0;
     223              : 
     224              :         } else {
     225            2 :                 memset (&tm, 0, sizeof (tm));
     226            2 :                 memcpy (buf, attr->value, 14);
     227            2 :                 buf[14] = 0;
     228              : 
     229            2 :                 if (!strptime(buf, "%Y%m%d%H%M%S", &tm)) {
     230            0 :                         g_warning ("invalid format of time attribute");
     231            0 :                         value = 0;
     232              :                 } else {
     233              :                         /* Convert to seconds since epoch */
     234            2 :                         time = timegm (&tm);
     235            2 :                         if (time < 0) {
     236            0 :                                 g_warning ("invalid time attribute");
     237            0 :                                 value = 0;
     238              :                         } else {
     239            2 :                                 value = time;
     240              :                         }
     241              :                 }
     242              :         }
     243              : 
     244            2 :         return g_variant_new_uint64 (value);
     245              : }
     246              : 
     247              : static gboolean
     248            0 : iter_get_time (GVariant *variant,
     249              :                gulong attr_type,
     250              :                GckBuilder *builder)
     251              : {
     252              :         time_t time;
     253              :         struct tm tm;
     254              :         gchar buf[20];
     255              :         guint64 value;
     256              : 
     257            0 :         g_assert (variant != NULL);
     258            0 :         g_assert (builder != NULL);
     259              : 
     260            0 :         value = g_variant_get_uint64 (variant);
     261            0 :         if (value == 0) {
     262            0 :                 gck_builder_add_empty (builder, attr_type);
     263            0 :                 return TRUE;
     264              :         }
     265              : 
     266            0 :         time = value;
     267            0 :         if (!gmtime_r (&time, &tm))
     268            0 :                 g_return_val_if_reached (FALSE);
     269              : 
     270            0 :         if (!strftime (buf, sizeof (buf), "%Y%m%d%H%M%S00", &tm))
     271            0 :                 g_return_val_if_reached (FALSE);
     272              : 
     273            0 :         gck_builder_add_data (builder, attr_type, (const guchar *)buf, 16);
     274            0 :         return TRUE;
     275              : }
     276              : 
     277              : static GVariant *
     278            1 : iter_append_fields (const GckAttribute *attr)
     279              : {
     280              :         const gchar *ptr;
     281              :         const gchar *last;
     282              :         const gchar *name;
     283              :         gsize n_name;
     284              :         const gchar *value;
     285              :         gsize n_value;
     286              :         gchar *name_string, *value_string;
     287              :         GVariantBuilder builder;
     288              : 
     289            1 :         g_assert (attr);
     290              : 
     291            1 :         ptr = (gchar*)attr->value;
     292            1 :         last = ptr + attr->length;
     293            1 :         g_return_val_if_fail (ptr || last == ptr, NULL);
     294              : 
     295            1 :         g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
     296              : 
     297            1 :         while (ptr && ptr != last) {
     298            0 :                 g_assert (ptr < last);
     299              : 
     300            0 :                 name = ptr;
     301            0 :                 ptr = memchr (ptr, 0, last - ptr);
     302            0 :                 if (ptr == NULL) /* invalid */
     303            0 :                         break;
     304              : 
     305            0 :                 n_name = ptr - name;
     306            0 :                 value = ++ptr;
     307            0 :                 ptr = memchr (ptr, 0, last - ptr);
     308            0 :                 if (ptr == NULL) /* invalid */
     309            0 :                         break;
     310              : 
     311            0 :                 n_value = ptr - value;
     312            0 :                 ++ptr;
     313              : 
     314            0 :                 name_string = g_strndup (name, n_name);
     315            0 :                 value_string = g_strndup (value, n_value);
     316              : 
     317            0 :                 g_variant_builder_add (&builder, "{ss}", name_string, value_string);
     318              : 
     319            0 :                 g_free (name_string);
     320            0 :                 g_free (value_string);
     321              :         }
     322              : 
     323            1 :         return g_variant_builder_end (&builder);
     324              : }
     325              : 
     326              : static gboolean
     327            8 : iter_get_fields (GVariant *variant,
     328              :                  gulong attr_type,
     329              :                  GckBuilder *builder)
     330              : {
     331              :         GString *result;
     332              :         const gchar *key, *value;
     333              :         GVariantIter iter;
     334              : 
     335            8 :         g_assert (variant != NULL);
     336            8 :         g_assert (builder != NULL);
     337              : 
     338            8 :         g_return_val_if_fail (g_variant_type_is_array (g_variant_get_type (variant)), FALSE);
     339              : 
     340            8 :         result = g_string_new ("");
     341            8 :         g_variant_iter_init (&iter, variant);
     342              : 
     343           14 :         while (g_variant_iter_next (&iter, "{&s&s}", &key, &value)) {
     344              :                 /* Key */
     345            6 :                 g_string_append (result, key);
     346              :                 g_string_append_c (result, '\0');
     347              : 
     348              :                 /* Value */
     349            6 :                 g_string_append (result, value);
     350              :                 g_string_append_c (result, '\0');
     351              :         }
     352              : 
     353            8 :         gck_builder_add_data (builder, attr_type, (const guchar *)result->str, result->len);
     354            8 :         g_string_free (result, TRUE);
     355            8 :         return TRUE;
     356              : }
     357              : 
     358              : static GVariant *
     359           49 : iter_append_variant (DataType data_type,
     360              :                      const GckAttribute *attr)
     361              : {
     362           49 :         IterAppendFunc func = NULL;
     363              : 
     364           49 :         g_assert (attr);
     365              : 
     366           49 :         switch (data_type) {
     367            2 :         case DATA_TYPE_STRING:
     368            2 :                 func = iter_append_string;
     369            2 :                 break;
     370           44 :         case DATA_TYPE_BOOL:
     371           44 :                 func = iter_append_bool;
     372           44 :                 break;
     373            2 :         case DATA_TYPE_TIME:
     374            2 :                 func = iter_append_time;
     375            2 :                 break;
     376            1 :         case DATA_TYPE_FIELDS:
     377            1 :                 func = iter_append_fields;
     378            1 :                 break;
     379            0 :         default:
     380            0 :                 g_assert (FALSE);
     381              :                 break;
     382              :         }
     383              : 
     384           49 :         return (func) (attr);
     385              : }
     386              : 
     387              : static gboolean
     388            6 : iter_get_variant (GVariant *variant,
     389              :                   DataType data_type,
     390              :                   gulong attr_type,
     391              :                   GckBuilder *builder)
     392              : {
     393            6 :         IterGetFunc func = NULL;
     394              :         gboolean ret;
     395              :         const GVariantType *sig;
     396              : 
     397            6 :         g_assert (variant != NULL);
     398            6 :         g_assert (builder != NULL);
     399              : 
     400            6 :         switch (data_type) {
     401            6 :         case DATA_TYPE_STRING:
     402            6 :                 func = iter_get_string;
     403            6 :                 sig = G_VARIANT_TYPE_STRING;
     404            6 :                 break;
     405            0 :         case DATA_TYPE_BOOL:
     406            0 :                 func = iter_get_bool;
     407            0 :                 sig = G_VARIANT_TYPE_BOOLEAN;
     408            0 :                 break;
     409            0 :         case DATA_TYPE_TIME:
     410            0 :                 func = iter_get_time;
     411            0 :                 sig = G_VARIANT_TYPE_UINT64;
     412            0 :                 break;
     413            0 :         case DATA_TYPE_FIELDS:
     414            0 :                 func = iter_get_fields;
     415            0 :                 sig = G_VARIANT_TYPE ("a{ss}");
     416            0 :                 break;
     417            0 :         default:
     418            0 :                 g_assert (FALSE);
     419              :                 break;
     420              :         }
     421              : 
     422            6 :         ret = g_variant_type_equal (g_variant_get_type (variant), sig);
     423            6 :         if (ret == FALSE)
     424            0 :                 return FALSE;
     425              : 
     426            6 :         return (func) (variant, attr_type, builder);
     427              : }
     428              : 
     429              : /* -----------------------------------------------------------------------------
     430              :  * PUBLIC
     431              :  */
     432              : 
     433              : gboolean
     434           51 : gkd_secret_property_get_type (const gchar *property, CK_ATTRIBUTE_TYPE *type)
     435              : {
     436              :         DataType data_type;
     437              : 
     438           51 :         g_return_val_if_fail (property, FALSE);
     439           51 :         g_return_val_if_fail (type, FALSE);
     440              : 
     441           51 :         return property_to_attribute (property, NULL, type, &data_type);
     442              : }
     443              : 
     444              : gboolean
     445            4 : gkd_secret_property_parse_all (GVariant *array,
     446              :                                const gchar *interface,
     447              :                                GckBuilder *builder)
     448              : {
     449              :         CK_ATTRIBUTE_TYPE attr_type;
     450              :         const char *name;
     451              :         DataType data_type;
     452              :         GVariantIter iter;
     453              :         GVariant *variant;
     454              : 
     455            4 :         g_return_val_if_fail (array != NULL, FALSE);
     456            4 :         g_return_val_if_fail (builder != NULL, FALSE);
     457              : 
     458            4 :         g_variant_iter_init (&iter, array);
     459              : 
     460            8 :         while (g_variant_iter_next (&iter, "{&sv}", &name, &variant)) {
     461              :                 /* Property interface.name */
     462            4 :                 if (!property_to_attribute (name, interface, &attr_type, &data_type))
     463            0 :                         return FALSE;
     464              : 
     465              :                 /* Property value */
     466            4 :                 if (!iter_get_variant (variant, data_type, attr_type, builder)) {
     467            0 :                         g_variant_unref (variant);
     468            0 :                         return FALSE;
     469              :                 }
     470              : 
     471            4 :                 g_variant_unref (variant);
     472              :         }
     473              : 
     474            4 :         return TRUE;
     475              : }
     476              : 
     477              : GVariant *
     478            0 : gkd_secret_property_append_all (GckAttributes *attrs)
     479              : {
     480              :         const GckAttribute *attr;
     481              :         DataType data_type;
     482              :         const gchar *name;
     483              :         gulong num, i;
     484              :         GVariantBuilder builder;
     485              :         GVariant *variant;
     486              : 
     487            0 :         g_return_val_if_fail (attrs, NULL);
     488              : 
     489            0 :         g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
     490            0 :         num = gck_attributes_count (attrs);
     491              : 
     492            0 :         for (i = 0; i < num; ++i) {
     493            0 :                 attr = gck_attributes_at (attrs, i);
     494            0 :                 if (!attribute_to_property (attr->type, &name, &data_type))
     495            0 :                         g_return_val_if_reached (NULL);
     496              : 
     497            0 :                 variant = iter_append_variant (data_type, attr);
     498            0 :                 g_variant_builder_add (&builder, "{sv}", name, variant);
     499            0 :                 g_variant_unref (variant);
     500              :         }
     501              : 
     502            0 :         return g_variant_builder_end (&builder);
     503              : }
     504              : 
     505              : GVariant *
     506           49 : gkd_secret_property_append_variant (const GckAttribute *attr)
     507              : {
     508              :         const gchar *property;
     509              :         DataType data_type;
     510              : 
     511           49 :         g_return_val_if_fail (attr, NULL);
     512              : 
     513           49 :         if (!attribute_to_property (attr->type, &property, &data_type))
     514            0 :                 return NULL;
     515           49 :         return iter_append_variant (data_type, attr);
     516              : }
     517              : 
     518              : gboolean
     519            2 : gkd_secret_property_parse_variant (GVariant *variant,
     520              :                                    const gchar *property,
     521              :                                    GckBuilder *builder)
     522              : {
     523              :         CK_ATTRIBUTE_TYPE attr_type;
     524              :         DataType data_type;
     525              : 
     526            2 :         g_return_val_if_fail (variant, FALSE);
     527            2 :         g_return_val_if_fail (property, FALSE);
     528            2 :         g_return_val_if_fail (builder != NULL, FALSE);
     529              : 
     530            2 :         if (!property_to_attribute (property, NULL, &attr_type, &data_type))
     531            0 :                 return FALSE;
     532              : 
     533            2 :         return iter_get_variant (variant, data_type, attr_type, builder);
     534              : }
     535              : 
     536              : gboolean
     537            8 : gkd_secret_property_parse_fields (GVariant *variant,
     538              :                                   GckBuilder *builder)
     539              : {
     540            8 :         g_return_val_if_fail (variant != NULL, FALSE);
     541            8 :         g_return_val_if_fail (builder != NULL, FALSE);
     542              : 
     543            8 :         return iter_get_fields (variant, CKA_G_FIELDS, builder);
     544              : }
        

Generated by: LCOV version 2.0-1