1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 *
3 * Copyright (C) 2016 Peter Hatina <phatina@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <ctype.h>
25
26 #include "udiskslogging.h"
27 #include "udisksdaemontypes.h"
28 #include "udisksconfigmanager.h"
29
30 struct _UDisksConfigManager {
31 GObject parent_instance;
32
33 gboolean uninstalled;
34
35 UDisksModuleLoadPreference load_preference;
36
37 const gchar *encryption;
38 gchar *config_dir;
39 };
40
41 struct _UDisksConfigManagerClass {
42 GObjectClass parent_class;
43 };
44
45 G_DEFINE_TYPE (UDisksConfigManager, udisks_config_manager, G_TYPE_OBJECT)
46
47 enum
48 {
49 PROP_0,
50 PROP_UNINSTALLED,
51 PROP_PREFERENCE,
52 PROP_ENCRYPTION,
53 PROP_N
54 };
55
56 #define MODULES_GROUP_NAME PACKAGE_NAME_UDISKS2
57 #define MODULES_KEY "modules"
58 #define MODULES_LOAD_PREFERENCE_KEY "modules_load_preference"
59
60 #define DEFAULTS_GROUP_NAME "defaults"
61 #define DEFAULTS_ENCRYPTION_KEY "encryption"
62
63 static void
udisks_config_manager_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)64 udisks_config_manager_get_property (GObject *object,
65 guint property_id,
66 GValue *value,
67 GParamSpec *pspec)
68 {
69 UDisksConfigManager *manager = UDISKS_CONFIG_MANAGER (object);
70
71 switch (property_id)
72 {
73 case PROP_UNINSTALLED:
74 g_value_set_boolean (value, udisks_config_manager_get_uninstalled (manager));
75 break;
76
77 case PROP_PREFERENCE:
78 g_value_set_int (value, udisks_config_manager_get_load_preference (manager));
79 break;
80
81 case PROP_ENCRYPTION:
82 g_value_set_string (value, udisks_config_manager_get_encryption (manager));
83 break;
84
85 default:
86 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
87 break;
88 }
89 }
90
91 static const gchar *
get_encryption_config(const gchar * encryption)92 get_encryption_config (const gchar *encryption)
93 {
94 if (g_strcmp0 (encryption, UDISKS_ENCRYPTION_LUKS1) == 0)
95 {
96 return UDISKS_ENCRYPTION_LUKS1;
97 }
98 else if (g_strcmp0 (encryption, UDISKS_ENCRYPTION_LUKS2) == 0)
99 {
100 return UDISKS_ENCRYPTION_LUKS2;
101 }
102 else
103 {
104 udisks_warning ("Unknown value used for 'encryption': %s; defaulting to '%s'",
105 encryption, UDISKS_ENCRYPTION_DEFAULT);
106 return UDISKS_ENCRYPTION_DEFAULT;
107 }
108 }
109
110 static void
udisks_config_manager_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)111 udisks_config_manager_set_property (GObject *object,
112 guint property_id,
113 const GValue *value,
114 GParamSpec *pspec)
115 {
116 UDisksConfigManager *manager = UDISKS_CONFIG_MANAGER (object);
117
118 switch (property_id)
119 {
120 case PROP_UNINSTALLED:
121 manager->uninstalled = g_value_get_boolean (value);
122 break;
123
124 case PROP_PREFERENCE:
125 manager->load_preference = g_value_get_int (value);
126 break;
127
128 case PROP_ENCRYPTION:
129 manager->encryption = get_encryption_config (g_value_get_string (value));
130 break;
131
132 default:
133 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
134 break;
135 }
136 }
137
138 static void
parse_config_file(UDisksConfigManager * manager,UDisksModuleLoadPreference * out_load_preference,const gchar ** out_encryption,GList ** out_modules)139 parse_config_file (UDisksConfigManager *manager,
140 UDisksModuleLoadPreference *out_load_preference,
141 const gchar **out_encryption,
142 GList **out_modules)
143 {
144 GKeyFile *config_file;
145 gchar *conf_filename;
146 gchar *load_preference;
147 gchar *encryption;
148 gchar *module_i;
149 gchar **modules;
150 gchar **modules_tmp;
151
152 /* Get modules and means of loading */
153 conf_filename = g_build_filename (G_DIR_SEPARATOR_S,
154 manager->config_dir,
155 PACKAGE_NAME_UDISKS2 ".conf",
156 NULL);
157
158 udisks_debug ("Loading configuration file: %s", conf_filename);
159
160 /* Load config */
161 config_file = g_key_file_new ();
162 g_key_file_set_list_separator (config_file, ',');
163 if (g_key_file_load_from_file (config_file, conf_filename, G_KEY_FILE_NONE, NULL))
164 {
165 if (out_modules != NULL)
166 {
167 modules = g_key_file_get_string_list (config_file, MODULES_GROUP_NAME, MODULES_KEY, NULL, NULL);
168 /* Read the list of modules to load. */
169 if (modules)
170 {
171 modules_tmp = modules;
172 for (module_i = *modules_tmp; module_i; module_i = *++modules_tmp)
173 *out_modules = g_list_append (*out_modules, g_strdup (g_strstrip (module_i)));
174 g_strfreev (modules);
175 }
176 }
177
178 if (out_load_preference != NULL)
179 {
180 /* Read the load preference configuration option. */
181 load_preference = g_key_file_get_string (config_file, MODULES_GROUP_NAME, MODULES_LOAD_PREFERENCE_KEY, NULL);
182 if (load_preference)
183 {
184 /* Check the key value */
185 if (g_ascii_strcasecmp (load_preference, "ondemand") == 0)
186 {
187 *out_load_preference = UDISKS_MODULE_LOAD_ONDEMAND;
188 }
189 else if (g_ascii_strcasecmp (load_preference, "onstartup") == 0)
190 {
191 *out_load_preference = UDISKS_MODULE_LOAD_ONSTARTUP;
192 }
193 else
194 {
195 udisks_warning ("Unknown value used for 'modules_load_preference': %s; defaulting to 'ondemand'",
196 load_preference);
197 }
198
199 g_free (load_preference);
200 }
201 }
202
203 if (out_encryption != NULL)
204 {
205 /* Read the load preference configuration option. */
206 encryption = g_key_file_get_string (config_file, DEFAULTS_GROUP_NAME, DEFAULTS_ENCRYPTION_KEY, NULL);
207 if (encryption)
208 {
209 *out_encryption = get_encryption_config (encryption);
210 g_free (encryption);
211 }
212 }
213 }
214 else
215 {
216 udisks_warning ("Can't load configuration file %s", conf_filename);
217 }
218
219 g_key_file_free (config_file);
220 g_free (conf_filename);
221 }
222
223 static void
udisks_config_manager_constructed(GObject * object)224 udisks_config_manager_constructed (GObject *object)
225 {
226 UDisksConfigManager *manager = UDISKS_CONFIG_MANAGER (object);
227
228 /* Build a path to the config directory */
229 manager->config_dir = g_build_path (G_DIR_SEPARATOR_S,
230 manager->uninstalled ? BUILD_DIR : PACKAGE_SYSCONF_DIR,
231 manager->uninstalled ? "udisks" : PROJECT_SYSCONF_DIR,
232 NULL);
233
234 /* Make sure the config dir exists, UDisksLinuxDrive may store some data there */
235 if (g_mkdir_with_parents (manager->config_dir, 0755) != 0)
236 {
237 /* don't abort the daemon, the config dir may point to a readonly filesystem */
238 udisks_warning ("Error creating directory %s: %m", manager->config_dir);
239 }
240
241 parse_config_file (manager, &manager->load_preference, &manager->encryption, NULL);
242
243 if (G_OBJECT_CLASS (udisks_config_manager_parent_class))
244 G_OBJECT_CLASS (udisks_config_manager_parent_class)->constructed (object);
245 }
246
247 static void
udisks_config_manager_dispose(GObject * object)248 udisks_config_manager_dispose (GObject *object)
249 {
250 if (G_OBJECT_CLASS (udisks_config_manager_parent_class))
251 G_OBJECT_CLASS (udisks_config_manager_parent_class)->dispose (object);
252 }
253
254 static void
udisks_config_manager_finalize(GObject * object)255 udisks_config_manager_finalize (GObject *object)
256 {
257 UDisksConfigManager *manager = UDISKS_CONFIG_MANAGER (object);
258
259 g_free (manager->config_dir);
260
261 if (G_OBJECT_CLASS (udisks_config_manager_parent_class))
262 G_OBJECT_CLASS (udisks_config_manager_parent_class)->finalize (object);
263 }
264
265 static void
udisks_config_manager_class_init(UDisksConfigManagerClass * klass)266 udisks_config_manager_class_init (UDisksConfigManagerClass *klass)
267 {
268 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
269
270 gobject_class->constructed = udisks_config_manager_constructed;
271 gobject_class->get_property = udisks_config_manager_get_property;
272 gobject_class->set_property = udisks_config_manager_set_property;
273 gobject_class->dispose = udisks_config_manager_dispose;
274 gobject_class->finalize = udisks_config_manager_finalize;
275
276 /**
277 * UDisksConfigManager:uninstalled:
278 *
279 * Loads modules from the build directory.
280 */
281 g_object_class_install_property (gobject_class,
282 PROP_UNINSTALLED,
283 g_param_spec_boolean ("uninstalled",
284 "Load modules from the build directory",
285 "Whether the modules should be loaded from the build directory",
286 FALSE,
287 G_PARAM_READABLE |
288 G_PARAM_WRITABLE |
289 G_PARAM_STATIC_STRINGS |
290 G_PARAM_CONSTRUCT_ONLY));
291
292 /**
293 * UDisksConfigManager:preference:
294 *
295 * Module load preference.
296 */
297 g_object_class_install_property (gobject_class,
298 PROP_PREFERENCE,
299 g_param_spec_int ("preference",
300 "Module load preference",
301 "When to load the additional modules",
302 UDISKS_MODULE_LOAD_ONDEMAND,
303 UDISKS_MODULE_LOAD_ONSTARTUP,
304 UDISKS_MODULE_LOAD_ONDEMAND,
305 G_PARAM_READABLE |
306 G_PARAM_WRITABLE |
307 G_PARAM_STATIC_STRINGS |
308 G_PARAM_CONSTRUCT_ONLY));
309
310 /**
311 * UDisksConfigManager:encryption:
312 *
313 * Default encryption technolog.
314 */
315 g_object_class_install_property (gobject_class,
316 PROP_ENCRYPTION,
317 g_param_spec_string ("encryption",
318 "Default encryption technology",
319 "Encryption technology used when creating encrypted filesystems",
320 UDISKS_ENCRYPTION_DEFAULT,
321 G_PARAM_READABLE |
322 G_PARAM_WRITABLE |
323 G_PARAM_STATIC_STRINGS |
324 G_PARAM_CONSTRUCT_ONLY));
325
326 }
327
328 static void
udisks_config_manager_init(UDisksConfigManager * manager)329 udisks_config_manager_init (UDisksConfigManager *manager)
330 {
331 manager->load_preference = UDISKS_MODULE_LOAD_ONDEMAND;
332 manager->encryption = UDISKS_ENCRYPTION_DEFAULT;
333 }
334
335 UDisksConfigManager *
udisks_config_manager_new(void)336 udisks_config_manager_new (void)
337 {
338 return UDISKS_CONFIG_MANAGER (g_object_new (UDISKS_TYPE_CONFIG_MANAGER,
339 "uninstalled", FALSE,
340 NULL));
341 }
342
343 UDisksConfigManager *
udisks_config_manager_new_uninstalled(void)344 udisks_config_manager_new_uninstalled (void)
345 {
346 return UDISKS_CONFIG_MANAGER (g_object_new (UDISKS_TYPE_CONFIG_MANAGER,
347 "uninstalled", TRUE,
348 NULL));
349 }
350
351 gboolean
udisks_config_manager_get_uninstalled(UDisksConfigManager * manager)352 udisks_config_manager_get_uninstalled (UDisksConfigManager *manager)
353 {
354 g_return_val_if_fail (UDISKS_IS_CONFIG_MANAGER (manager), FALSE);
355 return manager->uninstalled;
356 }
357
358 /**
359 * udisks_config_manager_get_modules:
360 * @manager: A #UDisksConfigManager.
361 *
362 * Reads the udisks2.conf file and retrieves a list of module names to load.
363 * A special '*' placeholder may be present as a first item as specified
364 * in the config file.
365 *
366 * Returns: (transfer full) (nullable) (element-type gchar*): A list of strings
367 * or %NULL if no specific configuration has been found in the config file.
368 * Free the elements with g_free().
369 */
370 GList *
udisks_config_manager_get_modules(UDisksConfigManager * manager)371 udisks_config_manager_get_modules (UDisksConfigManager *manager)
372 {
373 GList *modules = NULL;
374
375 g_return_val_if_fail (UDISKS_IS_CONFIG_MANAGER (manager), NULL);
376
377 parse_config_file (manager, NULL, NULL, &modules);
378 return modules;
379 }
380
381 /**
382 * udisks_config_manager_get_modules_all:
383 * @manager: A #UDisksConfigManager.
384 *
385 * Reads the udisks2.conf file and returns whether to load all modules or not.
386 * This corresponds to a special '*' placeholder in the config file.
387 *
388 * Returns: %TRUE when the daemon runs from a source tree, %FALSE otherwise.
389 */
390 gboolean
udisks_config_manager_get_modules_all(UDisksConfigManager * manager)391 udisks_config_manager_get_modules_all (UDisksConfigManager *manager)
392 {
393 GList *modules = NULL;
394 gboolean ret;
395
396 g_return_val_if_fail (UDISKS_IS_CONFIG_MANAGER (manager), FALSE);
397
398 parse_config_file (manager, NULL, NULL, &modules);
399
400 ret = !modules || (g_strcmp0 (modules->data, "*") == 0 && g_list_length (modules) == 1);
401
402 g_list_free_full (modules, (GDestroyNotify) g_free);
403
404 return ret;
405 }
406
407 UDisksModuleLoadPreference
udisks_config_manager_get_load_preference(UDisksConfigManager * manager)408 udisks_config_manager_get_load_preference (UDisksConfigManager *manager)
409 {
410 g_return_val_if_fail (UDISKS_IS_CONFIG_MANAGER (manager),
411 UDISKS_MODULE_LOAD_ONDEMAND);
412 return manager->load_preference;
413 }
414
415 const gchar *
udisks_config_manager_get_encryption(UDisksConfigManager * manager)416 udisks_config_manager_get_encryption (UDisksConfigManager *manager)
417 {
418 g_return_val_if_fail (UDISKS_IS_CONFIG_MANAGER (manager),
419 UDISKS_ENCRYPTION_DEFAULT);
420 return manager->encryption;
421 }
422
423 /**
424 * udisks_config_manager_get_config_dir:
425 * @manager: A #UDisksConfigManager.
426 *
427 * Gets path to the actual directory where global UDisks configuration files are
428 * stored. Takes in account the flag whether the UDisks daemon is running from
429 * a source code tree ("uninstalled") or whether it is a properly installed package.
430 *
431 * Returns: (transfer none): path to the global UDisks configuration directory.
432 */
433 const gchar *
udisks_config_manager_get_config_dir(UDisksConfigManager * manager)434 udisks_config_manager_get_config_dir (UDisksConfigManager *manager)
435 {
436 g_return_val_if_fail (UDISKS_IS_CONFIG_MANAGER (manager), NULL);
437 g_warn_if_fail (manager->config_dir != NULL);
438 return manager->config_dir;
439 }
440