Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2009 Stefan Walter
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "gkm-secret-data.h"
24 :
25 : #include "gkm/gkm-secret.h"
26 : #include "gkm/gkm-transaction.h"
27 : #include "gkm/gkm-util.h"
28 :
29 : #include "egg/egg-secure-memory.h"
30 :
31 : #include <glib/gi18n.h>
32 :
33 : struct _GkmSecretData {
34 : GObject parent;
35 : GHashTable *secrets;
36 : GkmSecret *master;
37 : };
38 :
39 1206 : G_DEFINE_TYPE (GkmSecretData, gkm_secret_data, G_TYPE_OBJECT);
40 :
41 : /* -----------------------------------------------------------------------------
42 : * INTERNAL
43 : */
44 :
45 : typedef struct _set_secret_args {
46 : gchar *identifier;
47 : GkmSecret *old_secret;
48 : } set_secret_args;
49 :
50 : static gboolean
51 9 : complete_set_secret (GkmTransaction *transaction, GObject *obj, gpointer user_data)
52 : {
53 9 : GkmSecretData *self = GKM_SECRET_DATA (obj);
54 9 : set_secret_args *args = user_data;
55 :
56 : /* If the transaction failed, revert */
57 9 : if (gkm_transaction_get_failed (transaction)) {
58 2 : if (!args->old_secret) {
59 1 : g_hash_table_remove (self->secrets, args->identifier);
60 : } else {
61 1 : g_hash_table_replace (self->secrets, args->identifier, args->old_secret);
62 1 : args->identifier = NULL; /* hash table took ownership */
63 1 : args->old_secret = NULL; /* ditto */
64 : }
65 : }
66 :
67 : /* Free up transaction data */
68 9 : g_free (args->identifier);
69 9 : if (args->old_secret)
70 1 : g_object_unref (args->old_secret);
71 9 : g_slice_free (set_secret_args, args);
72 :
73 9 : return TRUE;
74 : }
75 :
76 : static void
77 9 : begin_set_secret (GkmSecretData *self, GkmTransaction *transaction,
78 : const gchar *identifier, GkmSecret *secret)
79 : {
80 : set_secret_args *args;
81 :
82 9 : g_assert (GKM_IS_SECRET_DATA (self));
83 9 : g_assert (!gkm_transaction_get_failed (transaction));
84 9 : g_assert (identifier);
85 9 : g_assert (GKM_IS_SECRET (secret));
86 :
87 9 : args = g_slice_new0 (set_secret_args);
88 :
89 : /* Take ownership of the old data, if present */
90 9 : if (g_hash_table_lookup_extended (self->secrets, identifier,
91 9 : (gpointer*)&args->identifier,
92 9 : (gpointer*)&args->old_secret)) {
93 2 : if (!g_hash_table_steal (self->secrets, args->identifier))
94 0 : g_assert_not_reached ();
95 : } else {
96 7 : args->identifier = g_strdup (identifier);
97 : }
98 :
99 : /* Replace with our new data */
100 18 : g_hash_table_replace (self->secrets, g_strdup (identifier),
101 : g_object_ref (secret));
102 :
103 : /* Track in the transaction */
104 9 : gkm_transaction_add (transaction, self, complete_set_secret, args);
105 9 : }
106 :
107 : /* -----------------------------------------------------------------------------
108 : * OBJECT
109 : */
110 :
111 : static void
112 182 : gkm_secret_data_init (GkmSecretData *self)
113 : {
114 182 : self->secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
115 182 : }
116 :
117 : static void
118 182 : gkm_secret_data_finalize (GObject *obj)
119 : {
120 182 : GkmSecretData *self = GKM_SECRET_DATA (obj);
121 :
122 182 : if (self->secrets)
123 182 : g_hash_table_destroy (self->secrets);
124 182 : self->secrets = NULL;
125 :
126 182 : if (self->master)
127 167 : g_object_unref (self->master);
128 182 : self->master = NULL;
129 :
130 182 : G_OBJECT_CLASS (gkm_secret_data_parent_class)->finalize (obj);
131 182 : }
132 :
133 : static void
134 35 : gkm_secret_data_class_init (GkmSecretDataClass *klass)
135 : {
136 35 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
137 35 : gkm_secret_data_parent_class = g_type_class_peek_parent (klass);
138 35 : gobject_class->finalize = gkm_secret_data_finalize;
139 35 : }
140 :
141 : /* -----------------------------------------------------------------------------
142 : * PUBLIC
143 : */
144 :
145 : GkmSecret*
146 63 : gkm_secret_data_get_secret (GkmSecretData *self, const gchar *identifier)
147 : {
148 63 : g_return_val_if_fail (GKM_IS_SECRET_DATA (self), NULL);
149 63 : g_return_val_if_fail (identifier, NULL);
150 63 : return g_hash_table_lookup (self->secrets, identifier);
151 : }
152 :
153 : const guchar*
154 17 : gkm_secret_data_get_raw (GkmSecretData *self, const gchar *identifier,
155 : gsize *n_result)
156 : {
157 : GkmSecret *secret;
158 :
159 17 : g_return_val_if_fail (GKM_IS_SECRET_DATA (self), NULL);
160 17 : g_return_val_if_fail (identifier, NULL);
161 17 : g_return_val_if_fail (n_result, NULL);
162 :
163 17 : secret = gkm_secret_data_get_secret (self, identifier);
164 17 : if (secret == NULL)
165 8 : return NULL;
166 :
167 9 : return gkm_secret_get (secret, n_result);
168 : }
169 :
170 :
171 : void
172 71 : gkm_secret_data_set_secret (GkmSecretData *self, const gchar *identifier,
173 : GkmSecret *secret)
174 : {
175 71 : g_return_if_fail (GKM_IS_SECRET_DATA (self));
176 71 : g_return_if_fail (identifier);
177 71 : g_return_if_fail (GKM_IS_SECRET (secret));
178 142 : g_hash_table_replace (self->secrets, g_strdup (identifier),
179 : g_object_ref (secret));
180 : }
181 :
182 : void
183 9 : gkm_secret_data_set_transacted (GkmSecretData *self, GkmTransaction *transaction,
184 : const gchar *identifier, GkmSecret *secret)
185 : {
186 9 : g_return_if_fail (GKM_IS_SECRET_DATA (self));
187 9 : g_return_if_fail (GKM_IS_TRANSACTION (transaction));
188 9 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
189 9 : g_return_if_fail (identifier);
190 9 : g_return_if_fail (GKM_IS_SECRET (secret));
191 :
192 9 : begin_set_secret (self, transaction, identifier, secret);
193 : }
194 :
195 : void
196 1 : gkm_secret_data_remove_secret (GkmSecretData *self, const gchar *identifier)
197 : {
198 1 : g_return_if_fail (GKM_IS_SECRET_DATA (self));
199 1 : g_return_if_fail (identifier);
200 1 : g_hash_table_remove (self->secrets, identifier);
201 : }
202 :
203 : GkmSecret*
204 78 : gkm_secret_data_get_master (GkmSecretData *self)
205 : {
206 78 : g_return_val_if_fail (GKM_IS_SECRET_DATA (self), NULL);
207 78 : return self->master;
208 : }
209 :
210 : void
211 173 : gkm_secret_data_set_master (GkmSecretData *self, GkmSecret *master)
212 : {
213 173 : g_return_if_fail (GKM_IS_SECRET_DATA (self));
214 173 : g_return_if_fail (!master || GKM_IS_SECRET (master));
215 :
216 173 : if (master)
217 172 : g_object_ref (master);
218 173 : if (self->master)
219 5 : g_object_unref (self->master);
220 173 : self->master = master;
221 : }
|