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