Update to upstream 1.0.1
[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 "config.h"
32
33 #include "gsignond/gsignond-log.h"
34 #include "gsignond/gsignond-storage-manager.h"
35 #include "gsignond/gsignond-utils.h"
36
37 /**
38  * SECTION:gsignond-storage-manager
39  * @short_description: manages encrypted disk storage for storing the secret database
40  * @include: gsignond/gsignond-plugin-interface.h
41  *
42  * #GSignondStorageManager manages encrypted disk storage for storing the
43  * databases. The default implementation maintains a simple per-user
44  * directory accessible only to root and gsignond group, but gSSO can be
45  * configured to use a custom extension that provides a subclassed
46  * implementation of #GSignondStorageManager
47  * (see #GSignondExtension for instructions and pointers to examples).
48  */
49 /**
50  * GSignondStorageManager:
51  *
52  * Opaque #GSignondStorageManager data structure.
53  */
54  
55
56 #define GSIGNOND_STORAGE_MANAGER_GET_PRIVATE(obj) \
57     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
58                                   GSIGNOND_TYPE_STORAGE_MANAGER, \
59                                   GSignondStorageManagerPrivate))
60
61 struct _GSignondStorageManagerPrivate
62 {
63 };
64
65 enum
66 {
67     PROP_0,
68     PROP_CONFIG,
69     N_PROPERTIES
70 };
71
72 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
73
74 G_DEFINE_TYPE (GSignondStorageManager, gsignond_storage_manager, G_TYPE_OBJECT);
75
76 static void
77 _set_config (GSignondStorageManager *self, GSignondConfig *config)
78 {
79     g_assert (self->config == NULL);
80     self->config = config;
81
82     gchar *user_dir = g_strdup_printf ("gsignond.%s", g_get_user_name ());
83     const gchar *storage_path = gsignond_config_get_string (
84                                        self->config,
85                                        GSIGNOND_CONFIG_GENERAL_STORAGE_PATH);
86     if (!storage_path) {
87         storage_path = BASE_STORAGE_DIR;
88         DBG ("storage path not configured, using default location");
89     }
90 #   ifdef ENABLE_DEBUG
91     const gchar *env_val = g_getenv("SSO_STORAGE_PATH");
92     if (env_val)
93         storage_path = env_val;
94 #   endif
95     self->location = g_build_filename (storage_path, user_dir, NULL);
96     g_free (user_dir);
97     DBG ("secure dir %s", self->location);
98 }
99
100 static void
101 _set_property (GObject *object, guint prop_id, const GValue *value,
102                GParamSpec *pspec)
103 {
104     GSignondStorageManager *self =
105         GSIGNOND_STORAGE_MANAGER (object);
106
107     switch (prop_id) {
108         case PROP_CONFIG:
109             g_assert (self->config == NULL);
110             _set_config (self, GSIGNOND_CONFIG (g_value_dup_object (value)));
111             break;
112         default:
113             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
114     }
115 }
116
117 static void
118 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
119 {
120     GSignondStorageManager *self =
121         GSIGNOND_STORAGE_MANAGER (object);
122
123     switch (prop_id) {
124         case PROP_CONFIG:
125             g_value_set_object (value, self->config);
126             break;
127         default:
128             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129     }
130 }
131
132 static void
133 _dispose (GObject *object)
134 {
135     GSignondStorageManager *self =
136         GSIGNOND_STORAGE_MANAGER (object);
137
138     /* unmount mounted filesystem */
139     if (gsignond_storage_manager_filesystem_is_mounted (self)) {
140         gsignond_storage_manager_unmount_filesystem (self);
141     }
142
143     if (self->config) {
144         g_object_unref (self->config);
145         self->config = NULL;
146     }
147
148     G_OBJECT_CLASS (gsignond_storage_manager_parent_class)->dispose (object);
149 }
150
151 static void
152 _finalize (GObject *object)
153 {
154     GSignondStorageManager *self = 
155         GSIGNOND_STORAGE_MANAGER (object);
156
157     if (self->location) {
158         g_free (self->location);
159         self->location = NULL;
160     }
161
162     G_OBJECT_CLASS (gsignond_storage_manager_parent_class)->finalize (object);
163 }
164
165 static gboolean
166 _initialize_storage (GSignondStorageManager *self)
167 {
168     g_return_val_if_fail (self != NULL, FALSE);
169     g_return_val_if_fail (self->location, FALSE);
170
171     if (g_access (self->location, R_OK) == 0)
172         return TRUE;
173
174     gboolean res = FALSE;
175
176     uid_t uid = getuid ();
177     if (seteuid (0))
178         WARN ("seteuid() failed");
179
180     if (g_mkdir_with_parents (self->location, S_IRWXU | S_IRWXG))
181         goto init_exit;
182     if (chown (self->location, 0, getegid ()))
183         WARN ("chown() failed");
184     if (chmod (self->location, S_IRWXU | S_IRWXG))
185         WARN ("chmod() failed");
186     res = TRUE;
187
188 init_exit:
189     if (seteuid (uid))
190         WARN ("seteuid failed");
191
192     return res;
193 }
194
195 static gboolean
196 _delete_storage (GSignondStorageManager *self)
197 {
198     g_return_val_if_fail (self != NULL, FALSE);
199     g_return_val_if_fail (self->location, FALSE);
200
201     return gsignond_wipe_directory (self->location);
202 }
203
204 static gboolean
205 _storage_is_initialized (GSignondStorageManager *self)
206 {
207     g_return_val_if_fail (self != NULL, FALSE);
208     g_return_val_if_fail (self->location, FALSE);
209
210     if (g_access (self->location, 0))  /* 0 should equal to F_OK */
211         return FALSE;
212
213     return TRUE;
214 }
215
216 static const gchar *
217 _mount_filesystem (GSignondStorageManager *self)
218 {
219     g_return_val_if_fail (self != NULL, NULL);
220
221     return self->location;
222 }
223
224 static gboolean
225 _unmount_filesystem (GSignondStorageManager *self)
226 {
227     g_return_val_if_fail (self != NULL, FALSE);
228
229     return TRUE;
230 }
231
232 static gboolean
233 _filesystem_is_mounted (GSignondStorageManager *self)
234 {
235     return _storage_is_initialized (self);
236 }
237
238 /**
239  * GSignondStorageManagerClass:
240  * @parent_class: parent class.
241  * @initialize_storage: an implementation of gsignond_storage_manager_initialize_storage()
242  * @delete_storage: an implementation of gsignond_storage_manager_delete_storage()
243  * @storage_is_initialized: an implementation of gsignond_storage_manager_storage_is_initialized()
244  * @mount_filesystem: an implementation of gsignond_storage_manager_mount_filesystem()
245  * @unmount_filesystem: an implementation of gsignond_storage_manager_unmount_filesystem()
246  * @filesystem_is_mounted: an implementation of gsignond_storage_manager_filesystem_is_mounted()
247  * 
248  * #GSignondStorageManagerClass class containing pointers to class methods.
249  */
250 static void
251 gsignond_storage_manager_class_init (GSignondStorageManagerClass *klass)
252 {
253     GObjectClass *base = G_OBJECT_CLASS (klass);
254
255     base->set_property = _set_property;
256     base->get_property = _get_property;
257     base->dispose = _dispose;
258     base->finalize = _finalize;
259     properties[PROP_CONFIG] = g_param_spec_object ("config",
260                                                    "config",
261                                                    "Configuration object",
262                                                    GSIGNOND_TYPE_CONFIG,
263                                                    G_PARAM_CONSTRUCT_ONLY|
264                                                    G_PARAM_READWRITE|
265                                                    G_PARAM_STATIC_STRINGS);
266     g_object_class_install_properties (base, N_PROPERTIES, properties);
267
268     /*g_type_class_add_private (klass, sizeof(GSignondStorageManagerPrivate));*/
269  
270     klass->initialize_storage = _initialize_storage;
271     klass->delete_storage = _delete_storage;
272     klass->storage_is_initialized = _storage_is_initialized;
273     klass->mount_filesystem = _mount_filesystem;
274     klass->unmount_filesystem = _unmount_filesystem;
275     klass->filesystem_is_mounted = _filesystem_is_mounted;
276 }
277
278 static void
279 gsignond_storage_manager_init (GSignondStorageManager *self)
280 {
281     /*self->priv = GSIGNOND_STORAGE_MANAGER_GET_PRIVATE (self);*/
282
283     self->location = NULL;
284     self->config = NULL;
285 }
286
287 /**
288  * gsignond_storage_manager_initialize_storage:
289  * @self: object instance.
290  *
291  * Initialize encryption storage. This means making sure that the 
292  * necessary directories under #GSIGNOND_CONFIG_GENERAL_STORAGE_PATH exist and are accessible.
293  *
294  * Returns: success?
295  */
296 gboolean
297 gsignond_storage_manager_initialize_storage (GSignondStorageManager *self)
298 {
299     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
300         initialize_storage (self);
301 }
302
303 /**
304  * gsignond_storage_manager_delete_storage:
305  * @self: object instance.
306  *
307  * Destroys all the encryption keys and wipes the storage. gsignond_wipe_directory()
308  * is typically used for the latter.
309  *
310  * Returns: success?
311  */
312 gboolean
313 gsignond_storage_manager_delete_storage (GSignondStorageManager *self)
314 {
315     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
316         delete_storage (self);
317 }
318
319 /**
320  * gsignond_storage_manager_storage_is_initialized:
321  * @self: object instance.
322  *
323  * Checks if the storage has been initialized.
324  *
325  * Returns: storage has been initialized?
326  */
327 gboolean
328 gsignond_storage_manager_storage_is_initialized (GSignondStorageManager *self)
329 {
330     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
331         storage_is_initialized (self);
332 }
333
334 /**
335  * gsignond_storage_manager_mount_filesystem:
336  * @self: object instance.
337  *
338  * Mounts an encrypted storage and returns the filesystem path of the storage
339  * mount point. This path will be set in #GSignondConfig as 
340  * #GSIGNOND_CONFIG_GENERAL_SECURE_DIR and used to access the secret database via
341  * #GSignondSecretStorage.
342  * 
343  * The default implemenation does nothing, and immediately returns the path for the 
344  * secret database.
345  *
346  * Returns: (transfer none): path of the storage mount point.
347  */
348 const gchar *
349 gsignond_storage_manager_mount_filesystem (GSignondStorageManager *self)
350 {
351     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
352         mount_filesystem (self);
353 }
354
355 /**
356  * gsignond_storage_manager_unmount_filesystem:
357  * @self: object instance.
358  *
359  * Unmounts a previously mounted encrypted storage filesystem.
360  *
361  * Returns: success?
362  */
363 gboolean
364 gsignond_storage_manager_unmount_filesystem (GSignondStorageManager *self)
365 {
366     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
367         unmount_filesystem (self);
368 }
369
370 /**
371  * gsignond_storage_manager_filesystem_is_mounted:
372  * @self: object instance.
373  *
374  * Checks if the encrypted storage filesystem is currently mounted.
375  *
376  * Returns: filesystem is currently mounted?
377  */
378 gboolean
379 gsignond_storage_manager_filesystem_is_mounted (GSignondStorageManager *self)
380 {
381     return GSIGNOND_STORAGE_MANAGER_GET_CLASS (self)->
382         filesystem_is_mounted (self);
383 }
384