7df6c27e997b343901561fdae675420a840507cf
[profile/ivi/gsignond.git] / src / common / gsignond-storage-manager.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2012 Intel Corporation.
7  *
8  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include <unistd.h>
27 #include <sys/stat.h>
28
29 #include <glib/gstdio.h>
30
31 #include "gsignond/gsignond-log.h"
32 #include "gsignond/gsignond-storage-manager.h"
33 #include "gsignond/gsignond-utils.h"
34
35 /**
36  * SECTION:gsignond-storage-manager
37  * @short_description: manages encrypted disk storage for storing the secret database
38  * @include: gsignond/gsignond-plugin-interface.h
39  *
40  * #GSignondStorageManager manages encrypted disk storage for storing the
41  * databases. The default implementation maintains a simple per-user
42  * directory accessible only to root and gsignond group, but gSSO can be
43  * configured to use a custom extension that provides a subclassed
44  * implementation of #GSignondStorageManager
45  * (see #GSignondExtension for instructions and pointers to examples).
46  */
47 /**
48  * GSignondStorageManager:
49  *
50  * Opaque #GSignondStorageManager data structure.
51  */
52  
53
54 #define GSIGNOND_STORAGE_MANAGER_GET_PRIVATE(obj) \
55     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
56                                   GSIGNOND_TYPE_STORAGE_MANAGER, \
57                                   GSignondStorageManagerPrivate))
58
59 struct _GSignondStorageManagerPrivate
60 {
61 };
62
63 enum
64 {
65     PROP_0,
66     PROP_CONFIG,
67     N_PROPERTIES
68 };
69
70 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
71
72 G_DEFINE_TYPE (GSignondStorageManager, gsignond_storage_manager, G_TYPE_OBJECT);
73
74 static void
75 _set_config (GSignondStorageManager *self, GSignondConfig *config)
76 {
77     g_assert (self->config == NULL);
78     self->config = config;
79
80     gchar *user_dir = g_strdup_printf ("gsignond.%s", g_get_user_name ());
81     const gchar *storage_path = gsignond_config_get_string (
82                                        self->config,
83                                        GSIGNOND_CONFIG_GENERAL_STORAGE_PATH);
84     if (storage_path)
85         self->location = g_build_filename (storage_path,
86                                            user_dir,
87                                            NULL);
88     else
89         self->location = g_build_filename ("/var/db",
90                                            user_dir,
91                                            NULL);
92     g_free (user_dir);
93     DBG ("secure dir %s", self->location);
94 }
95
96 static void
97 _set_property (GObject *object, guint prop_id, const GValue *value,
98                GParamSpec *pspec)
99 {
100     GSignondStorageManager *self =
101         GSIGNOND_STORAGE_MANAGER (object);
102
103     switch (prop_id) {
104         case PROP_CONFIG:
105             g_assert (self->config == NULL);
106             _set_config (self, GSIGNOND_CONFIG (g_value_dup_object (value)));
107             break;
108         default:
109             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
110     }
111 }
112
113 static void
114 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
115 {
116     GSignondStorageManager *self =
117         GSIGNOND_STORAGE_MANAGER (object);
118
119     switch (prop_id) {
120         case PROP_CONFIG:
121             g_value_set_object (value, self->config);
122             break;
123         default:
124             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
125     }
126 }
127
128 static void
129 _dispose (GObject *object)
130 {
131     GSignondStorageManager *self =
132         GSIGNOND_STORAGE_MANAGER (object);
133
134     /* unmount mounted filesystem */
135     if (gsignond_storage_manager_filesystem_is_mounted (self)) {
136         gsignond_storage_manager_unmount_filesystem (self);
137     }
138
139     if (self->config) {
140         g_object_unref (self->config);
141         self->config = NULL;
142     }
143
144     G_OBJECT_CLASS (gsignond_storage_manager_parent_class)->dispose (object);
145 }
146
147 static void
148 _finalize (GObject *object)
149 {
150     GSignondStorageManager *self = 
151         GSIGNOND_STORAGE_MANAGER (object);
152
153     if (self->location) {
154         g_free (self->location);
155         self->location = NULL;
156     }
157
158     G_OBJECT_CLASS (gsignond_storage_manager_parent_class)->finalize (object);
159 }
160
161 static gboolean
162 _initialize_storage (GSignondStorageManager *self)
163 {
164     g_return_val_if_fail (self != NULL, FALSE);
165     g_return_val_if_fail (self->location, FALSE);
166
167     if (g_access (self->location, R_OK) == 0)
168         return TRUE;
169
170     gboolean res = FALSE;
171
172     uid_t uid = getuid ();
173     if (seteuid (0))
174         WARN ("seteuid() failed");
175
176     if (g_mkdir_with_parents (self->location, S_IRWXU | S_IRWXG))
177         goto init_exit;
178     if (chown (self->location, 0, getegid ()))
179         WARN ("chown() failed");
180     if (chmod (self->location, S_IRWXU | S_IRWXG))
181         WARN ("chmod() failed");
182     res = TRUE;
183
184 init_exit:
185     if (seteuid (uid))
186         WARN ("seteuid failed");
187
188     return res;
189 }
190
191 static gboolean
192 _delete_storage (GSignondStorageManager *self)
193 {
194     g_return_val_if_fail (self != NULL, FALSE);
195     g_return_val_if_fail (self->location, FALSE);
196
197     return gsignond_wipe_directory (self->location);
198 }
199
200 static gboolean
201 _storage_is_initialized (GSignondStorageManager *self)
202 {
203     g_return_val_if_fail (self != NULL, FALSE);
204     g_return_val_if_fail (self->location, FALSE);
205
206     if (g_access (self->location, 0))  /* 0 should equal to F_OK */
207         return FALSE;
208
209     return TRUE;
210 }
211
212 static const gchar *
213 _mount_filesystem (GSignondStorageManager *self)
214 {
215     g_return_val_if_fail (self != NULL, NULL);
216
217     return self->location;
218 }
219
220 static gboolean
221 _unmount_filesystem (GSignondStorageManager *self)
222 {
223     g_return_val_if_fail (self != NULL, FALSE);
224
225     return TRUE;
226 }
227
228 static gboolean
229 _filesystem_is_mounted (GSignondStorageManager *self)
230 {
231     return _storage_is_initialized (self);
232 }
233
234 /**
235  * GSignondStorageManagerClass:
236  * @parent_class: parent class.
237  * @initialize_storage: an implementation of gsignond_storage_manager_initialize_storage()
238  * @delete_storage: an implementation of gsignond_storage_manager_delete_storage()
239  * @storage_is_initialized: an implementation of gsignond_storage_manager_storage_is_initialized()
240  * @mount_filesystem: an implementation of gsignond_storage_manager_mount_filesystem()
241  * @unmount_filesystem: an implementation of gsignond_storage_manager_unmount_filesystem()
242  * @filesystem_is_mounted: an implementation of gsignond_storage_manager_filesystem_is_mounted()
243  * 
244  * #GSignondStorageManagerClass class containing pointers to class methods.
245  */
246 static void
247 gsignond_storage_manager_class_init (GSignondStorageManagerClass *klass)
248 {
249     GObjectClass *base = G_OBJECT_CLASS (klass);
250
251     base->set_property = _set_property;
252     base->get_property = _get_property;
253     base->dispose = _dispose;
254     base->finalize = _finalize;
255     properties[PROP_CONFIG] = g_param_spec_object ("config",
256                                                    "config",
257                                                    "Configuration object",
258                                                    GSIGNOND_TYPE_CONFIG,
259                                                    G_PARAM_CONSTRUCT_ONLY|
260                                                    G_PARAM_READWRITE|
261                                                    G_PARAM_STATIC_STRINGS);
262     g_object_class_install_properties (base, N_PROPERTIES, properties);
263
264     /*g_type_class_add_private (klass, sizeof(GSignondStorageManagerPrivate));*/
265  
266     klass->initialize_storage = _initialize_storage;
267     klass->delete_storage = _delete_storage;
268     klass->storage_is_initialized = _storage_is_initialized;
269     klass->mount_filesystem = _mount_filesystem;
270     klass->unmount_filesystem = _unmount_filesystem;
271     klass->filesystem_is_mounted = _filesystem_is_mounted;
272 }
273
274 static void
275 gsignond_storage_manager_init (GSignondStorageManager *self)
276 {
277     /*self->priv = GSIGNOND_STORAGE_MANAGER_GET_PRIVATE (self);*/
278
279     self->location = NULL;
280     self->config = NULL;
281 }
282
283 /**
284  * gsignond_storage_manager_initialize_storage:
285  * @self: object instance.
286  *
287  * Initialize encryption storage. This means making sure that the 
288  * necessary directories exist and are accessible.
289  *
290  * Returns: success?
291  */
292 gboolean
293 gsignond_storage_manager_initialize_storage (GSignondStorageManager *self)
294 {
295     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
296         initialize_storage (self);
297 }
298
299 /**
300  * gsignond_storage_manager_delete_storage:
301  * @self: object instance.
302  *
303  * Destroys all the encryption keys and wipes the storage. gsignond_wipe_directory()
304  * is typically used for the latter.
305  *
306  * Returns: success?
307  */
308 gboolean
309 gsignond_storage_manager_delete_storage (GSignondStorageManager *self)
310 {
311     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
312         delete_storage (self);
313 }
314
315 /**
316  * gsignond_storage_manager_storage_is_initialized:
317  * @self: object instance.
318  *
319  * Checks if the storage has been initialized.
320  *
321  * Returns: storage has been initialized?
322  */
323 gboolean
324 gsignond_storage_manager_storage_is_initialized (GSignondStorageManager *self)
325 {
326     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
327         storage_is_initialized (self);
328 }
329
330 /**
331  * gsignond_storage_manager_mount_filesystem:
332  * @self: object instance.
333  *
334  * Mounts an encrypted storage and returns the filesystem path of the storage
335  * mount point. This path will be used to access the secret database via
336  * #GSignondSecretStorage.
337  * 
338  * The default implemenation does nothing, and immediately returns the path for the 
339  * secret database.
340  *
341  * Returns: (transfer none): path of the storage mount point.
342  */
343 const gchar *
344 gsignond_storage_manager_mount_filesystem (GSignondStorageManager *self)
345 {
346     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
347         mount_filesystem (self);
348 }
349
350 /**
351  * gsignond_storage_manager_unmount_filesystem:
352  * @self: object instance.
353  *
354  * Unmounts a previously mounted encrypted storage filesystem.
355  *
356  * Returns: success?
357  */
358 gboolean
359 gsignond_storage_manager_unmount_filesystem (GSignondStorageManager *self)
360 {
361     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
362         unmount_filesystem (self);
363 }
364
365 /**
366  * gsignond_storage_manager_filesystem_is_mounted:
367  * @self: object instance.
368  *
369  * Checks if the encrypted storage filesystem is currently mounted.
370  *
371  * Returns: filesystem is currently mounted?
372  */
373 gboolean
374 gsignond_storage_manager_filesystem_is_mounted (GSignondStorageManager *self)
375 {
376     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
377         filesystem_is_mounted (self);
378 }
379