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