2012-03-11 08:06:40 +00:00
|
|
|
/* libsecret - GLib wrapper for Secret Service
|
|
|
|
*
|
|
|
|
* Copyright 2011 Collabora Ltd.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
|
|
* by the Free Software Foundation; either version 2 of the licence or (at
|
|
|
|
* your option) any later version.
|
|
|
|
*
|
|
|
|
* See the included COPYING file for more information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "secret-enum-types.h"
|
|
|
|
#include "secret-password.h"
|
|
|
|
#include "secret-private.h"
|
|
|
|
#include "secret-value.h"
|
|
|
|
|
|
|
|
#include <egg/egg-secure-memory.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SECTION:secret-schema
|
|
|
|
* @title: SecretSchema
|
|
|
|
* @short_description: Schema for defining which attributes are on items
|
|
|
|
*
|
|
|
|
* Each password is associated with a set of attributes. Attribute values can
|
|
|
|
* be either strings, integers or booleans.
|
|
|
|
*
|
|
|
|
* The names and types of allowed attributes for a given password are defined
|
2012-03-18 18:04:44 +00:00
|
|
|
* with a schema.
|
2012-03-11 08:06:40 +00:00
|
|
|
*
|
|
|
|
* Additional schemas can be defined via the %SecretSchema structure like this:
|
|
|
|
*
|
2012-03-18 18:04:44 +00:00
|
|
|
* <informalexample><programlisting language="c">
|
|
|
|
* /<!-- -->* in a header: *<!-- -->/
|
|
|
|
*
|
|
|
|
* const SecretSchema * example_get_schema (void) G_GNUC_CONST;
|
|
|
|
*
|
|
|
|
* #define EXAMPLE_SCHEMA example_get_schema ()
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* /<!-- -->* in a .c file: *<!-- -->/
|
|
|
|
*
|
|
|
|
* const SecretSchema *
|
|
|
|
* example_get_schema (void)
|
|
|
|
* {
|
|
|
|
* static const SecretSchema the_schema = {
|
|
|
|
* "org.example.Password", SECRET_SCHEMA_NONE,
|
|
|
|
* {
|
|
|
|
* { "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
|
|
|
|
* { "string", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
|
|
* { "even", SECRET_SCHEMA_ATTRIBUTE_BOOLEAN },
|
|
|
|
* { "NULL", 0 },
|
|
|
|
* }
|
|
|
|
* };
|
|
|
|
* return &the_schema;
|
|
|
|
* }
|
2012-03-24 06:52:12 +00:00
|
|
|
* </programlisting></informalexample>
|
|
|
|
*
|
|
|
|
* @stability: Stable
|
2012-03-11 08:06:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SecretSchema:
|
2012-03-18 18:04:44 +00:00
|
|
|
* @name: the dotted name of the schema
|
2012-03-17 13:25:50 +00:00
|
|
|
* @flags: flags for the schema
|
2012-03-11 08:06:40 +00:00
|
|
|
* @attributes: the attribute names and types of those attributes
|
|
|
|
*
|
|
|
|
* Represents a set of attributes that are stored with an item. These schemas
|
|
|
|
* are used for interoperability between various services storing the same types
|
|
|
|
* of items.
|
|
|
|
*
|
2012-03-18 18:04:44 +00:00
|
|
|
* Each schema has a name like "org.gnome.keyring.NetworkPassword", and defines
|
2012-03-11 08:06:40 +00:00
|
|
|
* a set of attributes, and types (string, integer, boolean) for those attributes.
|
|
|
|
*
|
|
|
|
* Attributes are stored as strings in the Secret Service, and the attribute
|
|
|
|
* types simply define standard ways to store integer and boolean values as strings.
|
2012-03-17 13:25:50 +00:00
|
|
|
*
|
2012-03-18 18:04:44 +00:00
|
|
|
* Schemas are handled entirely on the client side by this library. The name of the
|
|
|
|
* schema is automatically stored as an attribute on the item.
|
|
|
|
*
|
|
|
|
* Normally when looking up passwords only those with matching schema names are
|
|
|
|
* returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
|
|
|
|
* then lookups will not check that the schema name matches that on the item, only
|
|
|
|
* the schema's attributes are matched. This is useful when you are looking up items
|
|
|
|
* that are not stored by the libsecret library. Other libraries such as libgnome-keyring
|
|
|
|
* don't store the schema name.
|
2012-03-24 06:52:12 +00:00
|
|
|
*
|
|
|
|
* @stability: Stable
|
2012-03-17 13:25:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SecretSchemaFlags:
|
|
|
|
* @SECRET_SCHEMA_NONE: no flags for the schema
|
2012-03-18 18:04:44 +00:00
|
|
|
* @SECRET_SCHEMA_DONT_MATCH_NAME: don't match the schema name when looking up or
|
|
|
|
* removing passwords
|
2012-03-17 13:25:50 +00:00
|
|
|
*
|
|
|
|
* Flags for a #SecretSchema definition.
|
2012-03-11 08:06:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SecretSchemaAttribute:
|
|
|
|
* @name: name of the attribute
|
|
|
|
* @type: the type of the attribute
|
|
|
|
*
|
|
|
|
* An attribute in a #SecretSchema.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2012-03-17 13:25:50 +00:00
|
|
|
* SecretSchemaAttributeType:
|
|
|
|
* @SECRET_SCHEMA_ATTRIBUTE_BOOLEAN: a boolean attribute, stored as 'true' or 'false'
|
|
|
|
* @SECRET_SCHEMA_ATTRIBUTE_INTEGER: an integer attribute, stored as a decimal
|
|
|
|
* @SECRET_SCHEMA_ATTRIBUTE_STRING: a utf-8 string attribute
|
2012-03-11 08:06:40 +00:00
|
|
|
*
|
|
|
|
* The type of an attribute in a #SecretSchema. Attributes are stored as strings
|
|
|
|
* in the Secret Service, and the attribute types simply define standard ways
|
|
|
|
* to store integer and boolean values as strings.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static SecretSchemaAttribute *
|
|
|
|
schema_attribute_copy (SecretSchemaAttribute *attribute)
|
|
|
|
{
|
|
|
|
SecretSchemaAttribute *copy;
|
|
|
|
|
|
|
|
copy = g_slice_new0 (SecretSchemaAttribute);
|
|
|
|
copy->name = g_strdup (attribute->name);
|
|
|
|
copy->type = attribute->type;
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
schema_attribute_free (SecretSchemaAttribute *attribute)
|
|
|
|
{
|
|
|
|
g_free ((gchar *)attribute->name);
|
|
|
|
g_slice_free (SecretSchemaAttribute, attribute);
|
|
|
|
}
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE (SecretSchemaAttribute, secret_schema_attribute,
|
|
|
|
schema_attribute_copy, schema_attribute_free);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* secret_schema_new:
|
2012-03-18 18:04:44 +00:00
|
|
|
* @name: the dotted name of the schema
|
2012-03-17 13:25:50 +00:00
|
|
|
* @flags: the flags for the schema
|
2012-03-11 08:06:40 +00:00
|
|
|
* @attributes: (element-type utf8 Secret.SchemaAttributeType): the attribute names and types of those attributes
|
|
|
|
*
|
|
|
|
* Using this function is not normally necessary from C code. This is useful
|
|
|
|
* for constructing #SecretSchema structures in bindings.
|
|
|
|
*
|
|
|
|
* A schema represents a set of attributes that are stored with an item. These
|
|
|
|
* schemas are used for interoperability between various services storing the
|
|
|
|
* same types of items.
|
|
|
|
*
|
2012-03-18 18:04:44 +00:00
|
|
|
* Each schema has an @name like "org.gnome.keyring.NetworkPassword", and
|
2012-03-11 08:06:40 +00:00
|
|
|
* defines a set of attributes names, and types (string, integer, boolean) for
|
|
|
|
* those attributes.
|
|
|
|
*
|
|
|
|
* Each key in the @attributes table should be a attribute name strings, and
|
2012-03-17 13:25:50 +00:00
|
|
|
* the values in the table should be integers from the #SecretSchemaAttributeType
|
2012-03-11 08:06:40 +00:00
|
|
|
* enumeration, representing the attribute type for each attribute name.
|
|
|
|
*
|
2012-03-18 18:04:44 +00:00
|
|
|
* Normally when looking up passwords only those with matching schema names are
|
|
|
|
* returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
|
|
|
|
* then lookups will not check that the schema name matches that on the item, only
|
|
|
|
* the schema's attributes are matched. This is useful when you are looking up items
|
|
|
|
* that are not stored by the libsecret library. Other libraries such as libgnome-keyring
|
|
|
|
* don't store the schema name.
|
2012-03-17 13:25:50 +00:00
|
|
|
*
|
2012-03-11 08:06:40 +00:00
|
|
|
* Returns: (transfer full): the new schema, which should be unreferenced with
|
|
|
|
* secret_schema_unref() when done
|
|
|
|
*/
|
|
|
|
SecretSchema *
|
2012-03-18 18:04:44 +00:00
|
|
|
secret_schema_new (const gchar *name,
|
2012-03-11 08:06:40 +00:00
|
|
|
SecretSchemaFlags flags,
|
|
|
|
GHashTable *attributes)
|
|
|
|
{
|
|
|
|
SecretSchema *schema;
|
|
|
|
GHashTableIter iter;
|
|
|
|
GEnumClass *enumc;
|
|
|
|
gpointer value;
|
|
|
|
gpointer key;
|
|
|
|
gint type;
|
|
|
|
gint ind = 0;
|
|
|
|
|
2012-03-18 18:04:44 +00:00
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
2012-03-11 08:06:40 +00:00
|
|
|
|
|
|
|
schema = g_slice_new0 (SecretSchema);
|
2012-03-18 18:04:44 +00:00
|
|
|
schema->name = g_strdup (name);
|
2012-03-11 08:06:40 +00:00
|
|
|
schema->flags = flags;
|
|
|
|
schema->reserved = 1;
|
|
|
|
|
|
|
|
if (attributes) {
|
|
|
|
g_hash_table_iter_init (&iter, attributes);
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
|
|
|
|
|
|
if (ind >= G_N_ELEMENTS (schema->attributes)) {
|
|
|
|
g_warning ("too many attributes for schema, max %d",
|
|
|
|
(gint) G_N_ELEMENTS (schema->attributes));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = GPOINTER_TO_INT (value);
|
|
|
|
|
|
|
|
enumc = G_ENUM_CLASS (g_type_class_ref (SECRET_TYPE_SCHEMA_ATTRIBUTE_TYPE));
|
|
|
|
if (!g_enum_get_value (enumc, type)) {
|
|
|
|
g_warning ("invalid type for attribute %s", (gchar *)key);
|
|
|
|
type = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_type_class_unref (enumc);
|
|
|
|
|
|
|
|
if (type >= 0) {
|
|
|
|
schema->attributes[ind].name = g_strdup (key);
|
|
|
|
schema->attributes[ind].type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
ind++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return schema;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* secret_schema_ref:
|
|
|
|
* @schema: the schema to reference
|
|
|
|
*
|
|
|
|
* Adds a reference to the #SecretSchema.
|
|
|
|
*
|
|
|
|
* It is not normally necessary to call this function from C code, and is
|
|
|
|
* mainly present for the sake of bindings. If the @schema was statically
|
|
|
|
* allocated, then this function will copy the schema.
|
|
|
|
*
|
|
|
|
* Returns: (transfer full): the referenced schema, which should be later
|
|
|
|
* unreferenced with secret_schema_unref()
|
|
|
|
*/
|
|
|
|
SecretSchema *
|
|
|
|
secret_schema_ref (SecretSchema *schema)
|
|
|
|
{
|
|
|
|
SecretSchema *result;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
g_return_val_if_fail (schema != NULL, NULL);
|
|
|
|
|
|
|
|
/* If it's static, then copy it */
|
|
|
|
if (g_atomic_int_get (&schema->reserved) > 0) {
|
|
|
|
g_atomic_int_inc (&schema->reserved);
|
|
|
|
result = schema;
|
|
|
|
} else {
|
|
|
|
result = g_slice_new0 (SecretSchema);
|
|
|
|
result->reserved = 1;
|
2012-03-18 18:04:44 +00:00
|
|
|
result->name = g_strdup (schema->name);
|
2012-03-11 08:06:40 +00:00
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++) {
|
|
|
|
result->attributes[i].name = g_strdup (schema->attributes[i].name);
|
|
|
|
result->attributes[i].type = schema->attributes[i].type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-03-11 08:41:13 +00:00
|
|
|
const SecretSchema *
|
|
|
|
_secret_schema_ref_if_nonstatic (const SecretSchema *schema)
|
|
|
|
{
|
|
|
|
if (schema && g_atomic_int_get (&schema->reserved) > 0)
|
|
|
|
secret_schema_ref ((SecretSchema *)schema);
|
|
|
|
|
|
|
|
return schema;
|
|
|
|
}
|
|
|
|
|
2012-03-11 08:06:40 +00:00
|
|
|
/**
|
|
|
|
* secret_schema_unref:
|
|
|
|
* @schema: the schema to reference
|
|
|
|
*
|
|
|
|
* Releases a reference to the #SecretSchema. If the last reference is
|
|
|
|
* released then the schema will be freed.
|
|
|
|
*
|
|
|
|
* It is not normally necessary to call this function from C code, and is
|
|
|
|
* mainly present for the sake of bindings. It is an error to call this for
|
|
|
|
* a @schema that was statically allocated.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
secret_schema_unref (SecretSchema *schema)
|
|
|
|
{
|
|
|
|
gint refs;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
g_return_if_fail (schema != NULL);
|
|
|
|
|
|
|
|
refs = g_atomic_int_add (&schema->reserved, -1);
|
|
|
|
if (refs < 0) {
|
|
|
|
g_warning ("should not unreference a static or invalid SecretSchema");
|
|
|
|
|
|
|
|
} else if (refs == 0) {
|
2012-03-18 18:04:44 +00:00
|
|
|
g_free ((gpointer)schema->name);
|
2012-03-11 08:06:40 +00:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++)
|
|
|
|
g_free ((gpointer)schema->attributes[i].name);
|
|
|
|
g_slice_free (SecretSchema, schema);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-11 08:41:13 +00:00
|
|
|
void
|
|
|
|
_secret_schema_unref_if_nonstatic (const SecretSchema *schema)
|
|
|
|
{
|
|
|
|
if (schema && g_atomic_int_get (&schema->reserved) > 0)
|
|
|
|
secret_schema_unref ((SecretSchema *)schema);
|
|
|
|
}
|
|
|
|
|
2012-03-11 08:06:40 +00:00
|
|
|
G_DEFINE_BOXED_TYPE (SecretSchema, secret_schema, secret_schema_ref, secret_schema_unref);
|