Update to upstream 1.0.1
[profile/ivi/gsignond.git] / src / extensions / tizen / tizen-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) 2013 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 <errno.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/mount.h>
31 #include <glib.h>
32 #include <glib/gstdio.h>
33 #include <mntent.h>
34 #include <ecryptfs.h>
35
36 #include "config.h"
37
38 #include "tizen-storage-manager.h"
39 #include "gsignond/gsignond-log.h"
40 #include "gsignond/gsignond-utils.h"
41
42 #define EXTENSION_TIZEN_STORAGE_MANAGER_GET_PRIVATE(obj) \
43     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
44                                   EXTENSION_TYPE_TIZEN_STORAGE_MANAGER, \
45                                   ExtensionTizenStorageManagerPrivate))
46
47 /* these are limited by ecryptfs */
48 #define KEY_BYTES 16
49 #define KEY_CIPHER "aes"
50
51 struct _ExtensionTizenStorageManagerPrivate
52 {
53     gchar *cdir;
54     gchar fekey[ECRYPTFS_MAX_PASSPHRASE_BYTES + 1];
55     gchar fesalt[ECRYPTFS_SALT_SIZE + 1];
56     gchar ksig[ECRYPTFS_SIG_SIZE_HEX + 1];
57 };
58
59 enum
60 {
61     PROP_0,
62     PROP_FEKEY,
63     PROP_FESALT,
64     N_PROPERTIES,
65     PROP_CONFIG
66 };
67
68 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
69
70 G_DEFINE_TYPE (ExtensionTizenStorageManager,
71                extension_tizen_storage_manager,
72                GSIGNOND_TYPE_STORAGE_MANAGER);
73
74 static void
75 _set_config (ExtensionTizenStorageManager *self, GSignondConfig *config)
76 {
77     GSignondStorageManager *parent = GSIGNOND_STORAGE_MANAGER (self);
78     g_assert (parent->config == NULL);
79     g_assert (self->priv->cdir == NULL);
80     parent->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                                        parent->config,
85                                        GSIGNOND_CONFIG_GENERAL_STORAGE_PATH);
86     if (!storage_path)
87         storage_path = BASE_STORAGE_DIR;
88 #   ifdef ENABLE_DEBUG
89     const gchar *env_val = g_getenv("SSO_STORAGE_PATH");
90     if (env_val)
91         storage_path = env_val;
92 #   endif
93     parent->location = g_build_filename (storage_path, user_dir, NULL);
94     g_free (user_dir);
95     self->priv->cdir = g_strdup_printf ("%s.efs", parent->location);
96     DBG ("location %s encryption point %s", parent->location, self->priv->cdir);
97 }
98
99 static void
100 _set_property (GObject *object, guint prop_id, const GValue *value,
101                GParamSpec *pspec)
102 {
103     ExtensionTizenStorageManager *self =
104         EXTENSION_TIZEN_STORAGE_MANAGER (object);
105     ExtensionTizenStorageManagerPrivate *priv = self->priv;
106
107     switch (prop_id) {
108         case PROP_CONFIG:
109             _set_config (self, GSIGNOND_CONFIG (g_value_dup_object (value)));
110             break;
111         case PROP_FEKEY:
112             g_strlcpy (priv->fekey,
113                        g_value_get_string (value),
114                        sizeof(priv->fekey));
115             break;
116         case PROP_FESALT:
117             g_strlcpy (priv->fesalt,
118                        g_value_get_string (value),
119                        sizeof(priv->fesalt));
120             break;
121         default:
122             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
123     }
124 }
125
126 static void
127 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
128 {
129     ExtensionTizenStorageManager *self =
130         EXTENSION_TIZEN_STORAGE_MANAGER (object);
131     ExtensionTizenStorageManagerPrivate *priv = self->priv;
132
133     switch (prop_id) {
134         case PROP_CONFIG:
135             g_value_set_object (value,
136                                 GSIGNOND_STORAGE_MANAGER (self)->config);
137             break;
138         case PROP_FEKEY:
139             g_value_set_string (value, priv->fekey);
140             break;
141         case PROP_FESALT:
142             g_value_set_string (value, priv->fesalt);
143             break;
144         default:
145             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
146     }
147 }
148
149 static void
150 _dispose (GObject *object)
151 {
152     G_OBJECT_CLASS (extension_tizen_storage_manager_parent_class)->dispose (object);
153 }
154
155 static void
156 _finalize (GObject *object)
157 {
158     ExtensionTizenStorageManager *self =
159         EXTENSION_TIZEN_STORAGE_MANAGER (object);
160     ExtensionTizenStorageManagerPrivate *priv = self->priv;
161
162     if (priv)
163         memset(priv->ksig, 0x00, sizeof(priv->ksig));
164     g_free (priv->cdir);
165
166     G_OBJECT_CLASS (extension_tizen_storage_manager_parent_class)->finalize (object);
167 }
168
169 static gboolean
170 _initialize_storage (GSignondStorageManager *parent)
171 {
172     ExtensionTizenStorageManager *self =
173         EXTENSION_TIZEN_STORAGE_MANAGER (parent);
174     ExtensionTizenStorageManagerPrivate *priv = self->priv;
175
176     g_return_val_if_fail (parent->location, FALSE);
177     g_return_val_if_fail (priv->cdir, FALSE);
178
179     if (g_access (parent->location, R_OK) == 0 &&
180         g_access (priv->cdir, R_OK) == 0)
181         return TRUE;
182
183     gboolean res = FALSE;
184
185     uid_t uid = getuid ();
186     if (seteuid (0))
187         WARN ("seteuid() failed");
188
189     DBG ("create mount point %s", parent->location);
190     if (g_mkdir_with_parents (parent->location, S_IRWXU | S_IRWXG))
191         goto init_exit;
192
193     DBG ("create storage point %s", priv->cdir);
194     if (g_mkdir_with_parents (priv->cdir, S_IRWXU | S_IRWXG))
195         goto init_exit;
196
197     if (chown (parent->location, 0, getegid ()))
198         WARN ("chown() failed");
199     if (chmod (parent->location, S_IRWXU | S_IRWXG))
200         WARN ("chmod() failed");
201     if (chown (priv->cdir, 0, getegid ()))
202         WARN ("chown() failed");
203     if (chmod (priv->cdir, S_IRWXU | S_IRWXG))
204         WARN ("chmod() failed");
205     res = TRUE;
206
207 init_exit:
208     if (seteuid (uid))
209         WARN ("seteuid() failed");
210
211     return res;
212 }
213
214 static gboolean
215 _storage_is_initialized (GSignondStorageManager *parent)
216 {
217     ExtensionTizenStorageManager *self =
218         EXTENSION_TIZEN_STORAGE_MANAGER (parent);
219     ExtensionTizenStorageManagerPrivate *priv = self->priv;
220
221     g_return_val_if_fail (priv->cdir, FALSE);
222
223     if (g_access (priv->cdir, 0) || g_access (parent->location, 0))
224         return FALSE;
225
226     return TRUE;
227 }
228
229 static const gchar *
230 _mount_filesystem (GSignondStorageManager *parent)
231 {
232     gchar *retval = NULL;
233     ExtensionTizenStorageManager *self =
234         EXTENSION_TIZEN_STORAGE_MANAGER (parent);
235     ExtensionTizenStorageManagerPrivate *priv = self->priv;
236
237     DBG ("add passphrase to kernel keyring");
238     if (ecryptfs_add_passphrase_key_to_keyring (priv->ksig,
239                                                 priv->fekey,
240                                                 priv->fesalt) < 0)
241         return NULL;
242
243     gchar *mntopts = g_strdup_printf (
244                                       "ecryptfs_check_dev_ruid" \
245                                       ",ecryptfs_cipher=%s" \
246                                       ",ecryptfs_key_bytes=%d" \
247                                       ",ecryptfs_unlink_sigs" \
248                                       ",ecryptfs_sig=%s",
249                                       KEY_CIPHER, KEY_BYTES,
250                                       priv->ksig);
251     DBG ("mount options: %s", mntopts);
252     uid_t uid = getuid ();
253     if (seteuid (0))
254         WARN ("seteuid() failed");
255     DBG ("perform mount %s -> %s", priv->cdir, parent->location);
256     if (mount (priv->cdir, parent->location,
257                "ecryptfs", MS_NOSUID | MS_NODEV, mntopts)) {
258         INFO ("mount failed %d: %s", errno, strerror(errno));
259         goto _mount_exit;
260     }
261
262     DBG ("mount succeeded at %s", parent->location);
263     retval = parent->location;
264
265 _mount_exit:
266     g_free (mntopts);
267     if (seteuid (uid))
268         WARN ("seteuid() failed");
269
270     return retval;
271 }
272
273 static gboolean
274 _unmount_filesystem (GSignondStorageManager *parent)
275 {
276     g_return_val_if_fail (parent != NULL, FALSE);
277
278     uid_t uid = getuid ();
279     if (seteuid (0))
280         WARN ("seteuid() failed");
281     umount (parent->location);
282     if (seteuid (uid))
283         WARN ("seteuid() failed");
284
285     return TRUE;
286 }
287
288 static gboolean
289 _filesystem_is_mounted (GSignondStorageManager *parent)
290 {
291     gboolean retval = FALSE;
292     FILE *mntf = setmntent("/proc/mounts", "r");
293     g_return_val_if_fail (mntf != NULL, FALSE);
294     
295     struct mntent *me;
296     while ((me = getmntent(mntf))) {
297         if (g_strcmp0 (parent->location, me->mnt_dir) == 0) {
298             retval = TRUE;
299             break;
300         }
301     }
302
303     endmntent(mntf);
304
305     return retval;
306 }
307
308 static gboolean
309 _delete_storage (GSignondStorageManager *parent)
310 {
311     ExtensionTizenStorageManager *self =
312         EXTENSION_TIZEN_STORAGE_MANAGER (parent);
313     ExtensionTizenStorageManagerPrivate *priv = self->priv;
314
315     g_return_val_if_fail (priv->cdir, FALSE);
316     g_return_val_if_fail (!_filesystem_is_mounted(parent), FALSE);
317
318     return (gsignond_wipe_directory (priv->cdir) &&
319             gsignond_wipe_directory (parent->location));
320 }
321
322 static void
323 extension_tizen_storage_manager_class_init (
324                                       ExtensionTizenStorageManagerClass *klass)
325 {
326     GObjectClass *base = G_OBJECT_CLASS (klass);
327
328     base->set_property = _set_property;
329     base->get_property = _get_property;
330     base->dispose = _dispose;
331     base->finalize = _finalize;
332
333     properties[PROP_FEKEY] = g_param_spec_string ("fekey",
334                                                   "fekey",
335                                                   "File encryption key",
336                                                   "0123456789",
337                                                   G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
338     properties[PROP_FESALT] = g_param_spec_string ("fesalt",
339                                                    "fesalt",
340                                                    "File encryption salt",
341                                                    "9876543210",
342                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
343     g_object_class_install_properties (base, N_PROPERTIES, properties);
344     g_object_class_override_property (base, PROP_CONFIG, "config");
345
346     g_type_class_add_private (klass,
347                               sizeof(ExtensionTizenStorageManagerPrivate));
348
349     GSignondStorageManagerClass *parent_class =
350         GSIGNOND_STORAGE_MANAGER_CLASS (klass);
351     parent_class->initialize_storage = _initialize_storage;
352     parent_class->delete_storage = _delete_storage;
353     parent_class->storage_is_initialized = _storage_is_initialized;
354     parent_class->mount_filesystem = _mount_filesystem;
355     parent_class->unmount_filesystem = _unmount_filesystem;
356     parent_class->filesystem_is_mounted = _filesystem_is_mounted;
357 }
358
359 static void
360 extension_tizen_storage_manager_init (ExtensionTizenStorageManager *self)
361 {
362     ExtensionTizenStorageManagerPrivate *priv =
363         EXTENSION_TIZEN_STORAGE_MANAGER_GET_PRIVATE (self);
364     self->priv = priv;
365
366     g_strlcpy (priv->fekey, "1234567890", sizeof(priv->fekey));
367     g_strlcpy (priv->fesalt, "0987654321", sizeof(priv->fesalt));
368 }
369