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);
+ + ]
|