1 /* libsecret - GLib wrapper for Secret Service
3 * Copyright 2011 Collabora Ltd.
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.
10 * See the included COPYING file for more information.
12 * Author: Stef Walter <stefw@gnome.org>
17 #include "secret-private.h"
18 #include "secret-value.h"
20 #include "egg/egg-secure-memory.h"
25 * SECTION:secret-value
27 * @short_description: a value containing a secret
29 * A #SecretValue contains a password or other secret value.
31 * Use secret_value_get() to get the actual secret data, such as a password.
32 * The secret data is not necessarily null-terminated, unless the content type
35 * Each #SecretValue has a content type. For passwords, this is "text/plain".
36 * Use secret_value_get_content_type() to look at the content type.
38 * #SecretValue is reference counted and immutable. The secret data is only
39 * freed when all references have been released via secret_value_unref().
41 * These functions have an unstable API and may change across versions. Use
42 * <literal>libsecret-unstable</literal> package to access them.
47 static gboolean is_password_value (SecretValue *value);
52 * A secret value, like a password or other binary secret.
55 EGG_SECURE_DECLARE (secret_value);
61 GDestroyNotify destroy;
66 secret_value_get_type (void)
68 static gsize initialized = 0;
69 static GType type = 0;
71 if (g_once_init_enter (&initialized)) {
72 type = g_boxed_type_register_static ("SecretValue",
73 (GBoxedCopyFunc)secret_value_ref,
74 (GBoxedFreeFunc)secret_value_unref);
75 g_once_init_leave (&initialized, 1);
83 * @secret: the secret data
84 * @length: the length of the data
85 * @content_type: the content type of the data
87 * Create a #SecretValue for the secret data passed in. The secret data is
88 * copied into non-pageable 'secure' memory.
90 * If the length is less than zero, then @secret is assumed to be
93 * Returns: (transfer full): the new #SecretValue
96 secret_value_new (const gchar *secret,
98 const gchar *content_type)
102 g_return_val_if_fail (length == 0 || secret != NULL, NULL);
103 g_return_val_if_fail (content_type, NULL);
106 length = strlen (secret);
108 copy = egg_secure_alloc (length + 1);
110 memcpy (copy, secret, length);
112 return secret_value_new_full (copy, length, content_type, egg_secure_free);
116 * secret_value_new_full:
117 * @secret: the secret data
118 * @length: the length of the data
119 * @content_type: the content type of the data
120 * @destroy: function to call to free the secret data
122 * Create a #SecretValue for the secret data passed in. The secret data is
123 * not copied, and will later be freed with the @destroy function.
125 * If the length is less than zero, then @secret is assumed to be
128 * Returns: (transfer full): the new #SecretValue
131 secret_value_new_full (gchar *secret,
133 const gchar *content_type,
134 GDestroyNotify destroy)
138 g_return_val_if_fail (content_type, NULL);
141 length = strlen (secret);
143 value = g_slice_new0 (SecretValue);
145 value->content_type = g_strdup (content_type);
146 value->destroy = destroy;
147 value->length = length;
148 value->secret = secret;
156 * @length: the length of the secret
158 * Get the secret data in the #SecretValue. The value is not necessarily
159 * null-terminated unless it was created with secret_value_new() or a
160 * null-terminated string was passed to secret_value_new_full().
162 * Returns: (array length=length) (element-type guint8): the secret data
165 secret_value_get (SecretValue *value,
168 g_return_val_if_fail (value, NULL);
170 *length = value->length;
171 return value->secret;
175 * secret_value_get_text:
178 * Get the secret data in the #SecretValue if it contains a textual
179 * value. The content type must be <literal>text/plain</literal>.
181 * Returns: (allow-none): the content type
184 secret_value_get_text (SecretValue *value)
186 g_return_val_if_fail (value, NULL);
188 if (!is_password_value (value))
191 return value->secret;
195 * secret_value_get_content_type:
198 * Get the content type of the secret value, such as
199 * <literal>text/plain</literal>.
201 * Returns: the content type
204 secret_value_get_content_type (SecretValue *value)
206 g_return_val_if_fail (value, NULL);
207 return value->content_type;
212 * @value: value to reference
214 * Add another reference to the #SecretValue. For each reference
215 * secret_value_unref() should be called to unreference the value.
217 * Returns: (transfer full): the value
220 secret_value_ref (SecretValue *value)
222 g_return_val_if_fail (value, NULL);
223 g_atomic_int_inc (&value->refs);
228 * secret_value_unref:
229 * @value: (type SecretUnstable.Value) (allow-none): value to unreference
231 * Unreference a #SecretValue. When the last reference is gone, then
232 * the value will be freed.
235 secret_value_unref (gpointer value)
237 SecretValue *val = value;
239 g_return_if_fail (value != NULL);
241 if (g_atomic_int_dec_and_test (&val->refs)) {
242 g_free (val->content_type);
244 (val->destroy) (val->secret);
245 g_slice_free (SecretValue, val);
250 is_password_value (SecretValue *value)
252 if (value->content_type && g_str_equal (value->content_type, "text/plain"))
255 /* gnome-keyring-daemon used to return passwords like this, so support this, but validate */
256 if (!value->content_type || g_str_equal (value->content_type, "application/octet-stream"))
257 return g_utf8_validate (value->secret, value->length, NULL);
263 _secret_value_unref_to_password (SecretValue *value)
265 SecretValue *val = value;
268 g_return_val_if_fail (value != NULL, NULL);
270 if (!is_password_value (value)) {
271 secret_value_unref (value);
275 if (g_atomic_int_dec_and_test (&val->refs)) {
276 if (val->destroy == egg_secure_free) {
277 result = val->secret;
280 result = egg_secure_strndup (val->secret, val->length);
282 (val->destroy) (val->secret);
284 g_free (val->content_type);
285 g_slice_free (SecretValue, val);
288 result = egg_secure_strndup (val->secret, val->length);
295 _secret_value_unref_to_string (SecretValue *value)
297 SecretValue *val = value;
300 g_return_val_if_fail (value != NULL, NULL);
302 if (!is_password_value (value)) {
303 secret_value_unref (value);
307 if (g_atomic_int_dec_and_test (&val->refs)) {
308 if (val->destroy == g_free) {
309 result = val->secret;
312 result = g_strndup (val->secret, val->length);
314 (val->destroy) (val->secret);
316 g_free (val->content_type);
317 g_slice_free (SecretValue, val);
320 result = g_strndup (val->secret, val->length);