Line data Source code
1 : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 : /* gnome-keyring-daemon.c - main keyring daemon code.
3 :
4 : Copyright (C) 2003 Red Hat, Inc
5 :
6 : Gnome keyring is free software; you can redistribute it and/or
7 : modify it under the terms of the GNU General Public License as
8 : published by the Free Software Foundation; either version 2 of the
9 : License, or (at your option) any later version.
10 :
11 : Gnome keyring is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program; if not, write to the Free Software
18 : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 :
20 : Author: Alexander Larsson <alexl@redhat.com>
21 : Author: Stef Walter <stef@memberwebs.com>
22 : */
23 :
24 : #include "config.h"
25 :
26 : #include "gkd-glue.h"
27 : #include "gkd-main.h"
28 : #include "gkd-capability.h"
29 : #include "gkd-pkcs11.h"
30 : #include "gkd-util.h"
31 :
32 : #include "control/gkd-control.h"
33 :
34 : #include "dbus/gkd-dbus.h"
35 :
36 : #include "egg/egg-cleanup.h"
37 : #include "egg/egg-error.h"
38 : #include "egg/egg-libgcrypt.h"
39 : #include "egg/egg-secure-memory.h"
40 : #include "egg/egg-unix-credentials.h"
41 :
42 : #include "login/gkd-login.h"
43 :
44 : #include <errno.h>
45 : #include <fcntl.h>
46 : #include <pthread.h>
47 : #include <stdlib.h>
48 : #include <stdio.h>
49 : #include <string.h>
50 : #include <signal.h>
51 : #include <locale.h>
52 : #include <syslog.h>
53 : #include <unistd.h>
54 :
55 : #include <sys/types.h>
56 : #include <sys/socket.h>
57 : #include <sys/un.h>
58 : #include <sys/stat.h>
59 : #include <sys/wait.h>
60 :
61 : #include <gio/gunixinputstream.h>
62 : #include <gio/gunixoutputstream.h>
63 : #include <glib.h>
64 : #include <glib/gi18n.h>
65 : #include <glib-object.h>
66 : #include <glib-unix.h>
67 :
68 : #include <gcrypt.h>
69 :
70 : /* preset file descriptors */
71 : #define STDIN 0
72 : #define STDOUT 1
73 : #define STDERR 2
74 :
75 : #ifndef HAVE_SOCKLEN_T
76 : typedef int socklen_t;
77 : #endif
78 :
79 : #define GKD_COMP_KEYRING "keyring"
80 : #define GKD_COMP_PKCS11 "pkcs11"
81 : #define GKD_COMP_SECRETS "secrets"
82 : #define GKD_COMP_SSH "ssh"
83 :
84 0 : EGG_SECURE_DECLARE (daemon_main);
85 :
86 : /* -----------------------------------------------------------------------------
87 : * COMMAND LINE
88 : */
89 :
90 : /* All the components to run on startup if not specified on command line */
91 : #ifdef WITH_SSH
92 : # ifdef WITH_GPG
93 : # define DEFAULT_COMPONENTS GKD_COMP_PKCS11 "," GKD_COMP_SECRETS "," GKD_COMP_SSH "," GKD_COMP_GPG
94 : # else
95 : # define DEFAULT_COMPONENTS GKD_COMP_PKCS11 "," GKD_COMP_SECRETS "," GKD_COMP_SSH
96 : # endif
97 : #else
98 : # ifdef WITH_GPG
99 : # define DEFAULT_COMPONENTS GKD_COMP_PKCS11 "," GKD_COMP_SECRETS "," GKD_COMP_GPG
100 : # else
101 : # define DEFAULT_COMPONENTS GKD_COMP_PKCS11 "," GKD_COMP_SECRETS
102 : # endif
103 : #endif
104 :
105 : /*
106 : * If --login is used and then daemon is not initialized within LOGIN_TIMEOUT
107 : * seconds, then we exit. See on_login_timeout() below.
108 : */
109 :
110 : #define LOGIN_TIMEOUT 120
111 :
112 : static gchar* run_components = DEFAULT_COMPONENTS;
113 : static gboolean pkcs11_started = FALSE;
114 : static gboolean secrets_started = FALSE;
115 : static gboolean dbus_started = FALSE;
116 :
117 : static gboolean run_foreground = FALSE;
118 : static gboolean run_daemonized = FALSE;
119 : static gboolean run_version = FALSE;
120 : static gboolean run_for_login = FALSE;
121 : static gboolean perform_unlock = FALSE;
122 : static gboolean run_for_start = FALSE;
123 : static gboolean run_for_replace = FALSE;
124 : static gchar* login_password = NULL;
125 : static gchar* control_directory = NULL;
126 : static guint timeout_id = 0;
127 : static gboolean initialization_completed = FALSE;
128 : static GMainLoop *loop = NULL;
129 : static int parent_wakeup_fd = -1;
130 : static GDBusConnection *system_bus_connection = NULL;
131 :
132 : static GOptionEntry option_entries[] = {
133 : { "start", 's', 0, G_OPTION_ARG_NONE, &run_for_start,
134 : "Start a dameon or initialize an already running daemon." },
135 : { "replace", 'r', 0, G_OPTION_ARG_NONE, &run_for_replace,
136 : "Replace the daemon for this desktop login environment." },
137 : { "foreground", 'f', 0, G_OPTION_ARG_NONE, &run_foreground,
138 : "Run in the foreground", NULL },
139 : { "daemonize", 'd', 0, G_OPTION_ARG_NONE, &run_daemonized,
140 : "Run as a daemon", NULL },
141 : { "login", 'l', 0, G_OPTION_ARG_NONE, &run_for_login,
142 : "Run by PAM for a user login. Read login password from stdin", NULL },
143 : { "unlock", 0, 0, G_OPTION_ARG_NONE, &perform_unlock,
144 : "Prompt for login keyring password, or read from stdin", NULL },
145 : { "components", 'c', 0, G_OPTION_ARG_STRING, &run_components,
146 : "The optional components to run", DEFAULT_COMPONENTS },
147 : { "control-directory", 'C', 0, G_OPTION_ARG_FILENAME, &control_directory,
148 : "The directory for sockets and control data", NULL },
149 : { "version", 'V', 0, G_OPTION_ARG_NONE, &run_version,
150 : "Show the version number and exit.", NULL },
151 : { NULL }
152 : };
153 :
154 : static void
155 27 : parse_arguments (int *argc, char** argv[])
156 : {
157 27 : GError *err = NULL;
158 : GOptionContext *context;
159 :
160 27 : context = g_option_context_new ("- The Gnome Keyring Daemon");
161 27 : g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE);
162 :
163 27 : if (!g_option_context_parse (context, argc, argv, &err)) {
164 0 : g_printerr ("gnome-keyring-daemon: %s\n", egg_error_message (err));
165 0 : g_clear_error (&err);
166 : }
167 :
168 27 : if (!run_components || !run_components[0]) {
169 7 : run_components = DEFAULT_COMPONENTS;
170 : } else {
171 20 : run_components = g_strdup (run_components);
172 20 : egg_cleanup_register (g_free, run_components);
173 : }
174 :
175 : /* Check the arguments */
176 27 : if (run_for_login && run_for_start) {
177 0 : g_printerr ("gnome-keyring-daemon: The --start option is incompatible with --login\n");
178 0 : run_for_login = FALSE;
179 : }
180 :
181 27 : if (run_for_login && run_for_replace) {
182 0 : g_printerr ("gnome-keyring-daemon: The --replace option is incompatible with --login\n");
183 0 : run_for_login = FALSE;
184 : }
185 :
186 27 : if (run_for_start && run_for_replace) {
187 0 : g_printerr ("gnome-keyring-daemon: The --replace option is incompatible with --start\n");
188 0 : run_for_start = FALSE;
189 : }
190 :
191 27 : if (run_for_start && perform_unlock) {
192 0 : g_printerr ("gnome-keyring-daemon: The --start option is incompatible with --unlock");
193 0 : perform_unlock = FALSE;
194 : }
195 :
196 27 : if (run_for_login)
197 0 : perform_unlock = TRUE;
198 :
199 27 : g_option_context_free (context);
200 27 : }
201 :
202 : /* -----------------------------------------------------------------------------
203 : * MEMORY
204 : */
205 :
206 : static gboolean do_warning = TRUE;
207 : #define WARNING "couldn't allocate secure memory to keep passwords " \
208 : "and or keys from being written to the disk"
209 :
210 : #define ABORTMSG "The GNOME_KEYRING_PARANOID environment variable was set. " \
211 : "Exiting..."
212 :
213 :
214 : /*
215 : * These are called from gkr-secure-memory.c to provide appropriate
216 : * locking for memory between threads
217 : */
218 :
219 : G_LOCK_DEFINE_STATIC (memory_mutex);
220 :
221 : static void
222 2017 : egg_memory_lock (void)
223 : {
224 2017 : G_LOCK (memory_mutex);
225 2017 : }
226 :
227 : static void
228 2017 : egg_memory_unlock (void)
229 : {
230 2017 : G_UNLOCK (memory_mutex);
231 2017 : }
232 :
233 : static void *
234 357 : egg_memory_fallback (void *p, size_t sz)
235 : {
236 : const gchar *env;
237 :
238 : /* We were asked to free memory */
239 357 : if (!sz) {
240 354 : g_free (p);
241 354 : return NULL;
242 : }
243 :
244 : /* We were asked to allocate */
245 3 : if (!p) {
246 0 : if (do_warning) {
247 0 : g_message (WARNING);
248 0 : do_warning = FALSE;
249 : }
250 :
251 0 : env = g_getenv ("GNOME_KEYRING_PARANOID");
252 0 : if (env && *env)
253 0 : g_error (ABORTMSG);
254 :
255 0 : return g_malloc0 (sz);
256 : }
257 :
258 : /*
259 : * Reallocation is a bit of a gray area, as we can be asked
260 : * by external libraries (like libgcrypt) to reallocate a
261 : * non-secure block into secure memory. We cannot satisfy
262 : * this request (as we don't know the size of the original
263 : * block) so we just try our best here.
264 : */
265 :
266 3 : return g_realloc (p, sz);
267 : }
268 :
269 : EGG_SECURE_DEFINE_GLOBALS (egg_memory_lock, egg_memory_unlock, egg_memory_fallback);
270 :
271 : /* -----------------------------------------------------------------------------
272 : * LOGS
273 : */
274 :
275 : static void
276 427 : log_handler (const gchar *log_domain, GLogLevelFlags log_level,
277 : const gchar *message, gpointer user_data)
278 : {
279 : int level;
280 :
281 : /* Note that crit and err are the other way around in syslog */
282 :
283 427 : switch (G_LOG_LEVEL_MASK & log_level) {
284 0 : case G_LOG_LEVEL_ERROR:
285 0 : level = LOG_CRIT;
286 0 : break;
287 0 : case G_LOG_LEVEL_CRITICAL:
288 0 : level = LOG_ERR;
289 0 : break;
290 0 : case G_LOG_LEVEL_WARNING:
291 0 : level = LOG_WARNING;
292 0 : break;
293 4 : case G_LOG_LEVEL_MESSAGE:
294 4 : level = LOG_NOTICE;
295 4 : break;
296 0 : case G_LOG_LEVEL_INFO:
297 0 : level = LOG_INFO;
298 0 : break;
299 423 : case G_LOG_LEVEL_DEBUG:
300 423 : level = -1;
301 423 : break;
302 0 : default:
303 0 : level = LOG_ERR;
304 0 : break;
305 : }
306 :
307 : /* Log to syslog first */
308 427 : if (level != -1) {
309 4 : if (log_domain)
310 0 : syslog (level, "%s: %s", log_domain, message);
311 : else
312 4 : syslog (level, "%s", message);
313 : }
314 :
315 : /* And then to default handler for aborting and stuff like that */
316 427 : g_log_default_handler (log_domain, log_level, message, user_data);
317 427 : }
318 :
319 : static void
320 1 : printerr_handler (const gchar *string)
321 : {
322 : /* Print to syslog and stderr */
323 1 : syslog (LOG_WARNING, "%s", string);
324 1 : fprintf (stderr, "%s", string);
325 1 : }
326 :
327 : static void
328 54 : prepare_logging ()
329 : {
330 54 : GLogLevelFlags flags = G_LOG_FLAG_FATAL | G_LOG_LEVEL_ERROR |
331 : G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING |
332 : G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO;
333 :
334 54 : openlog ("gnome-keyring-daemon", LOG_PID, LOG_AUTH);
335 :
336 54 : g_log_set_handler (NULL, flags, log_handler, NULL);
337 54 : g_log_set_handler ("Glib", flags, log_handler, NULL);
338 54 : g_log_set_handler ("Gtk", flags, log_handler, NULL);
339 54 : g_log_set_handler ("Gnome", flags, log_handler, NULL);
340 54 : g_log_set_default_handler (log_handler, NULL);
341 54 : g_set_printerr_handler (printerr_handler);
342 54 : }
343 :
344 : #ifdef WITH_DEBUG
345 :
346 : static void
347 0 : dump_diagnostics (void)
348 : {
349 : egg_secure_rec *records;
350 : egg_secure_rec *rec;
351 : unsigned int count, i;
352 : GHashTable *table;
353 : GHashTableIter iter;
354 0 : gsize request = 0;
355 0 : gsize block = 0;
356 :
357 0 : g_printerr ("------------------- Secure Memory --------------------\n");
358 0 : g_printerr (" Tag Used Space\n");
359 0 : g_printerr ("------------------------------------------------------\n");
360 :
361 0 : records = egg_secure_records (&count);
362 0 : table = g_hash_table_new (g_str_hash, g_str_equal);
363 0 : for (i = 0; i < count; i++) {
364 0 : if (!records[i].tag)
365 0 : records[i].tag = "<unused>";
366 0 : rec = g_hash_table_lookup (table, records[i].tag);
367 0 : if (rec == NULL)
368 0 : g_hash_table_insert (table, (gchar *)records[i].tag, &records[i]);
369 : else {
370 0 : rec->block_length += records[i].block_length;
371 0 : rec->request_length += records[i].request_length;
372 : }
373 0 : block += records[i].block_length;
374 0 : request += records[i].request_length;
375 : }
376 :
377 0 : g_hash_table_iter_init (&iter, table);
378 0 : while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&rec))
379 0 : g_printerr (" %-20s %12lu %16lu\n", rec->tag,
380 0 : (unsigned long)rec->request_length,
381 0 : (unsigned long)rec->block_length);
382 :
383 0 : if (count > 0)
384 0 : g_printerr ("------------------------------------------------------\n");
385 :
386 0 : g_printerr (" %-20s %12lu %16lu\n", "Total",
387 : (unsigned long)request, (unsigned long)block);
388 0 : g_printerr ("------------------------------------------------------\n");
389 :
390 0 : g_hash_table_destroy (table);
391 0 : free (records);
392 0 : }
393 :
394 : #endif /* WITH_DEBUG */
395 :
396 : /* -----------------------------------------------------------------------------
397 : * SIGNALS
398 : */
399 :
400 : void
401 27 : gkd_main_quit (void)
402 : {
403 : /* Always stop accepting control connections immediately */
404 27 : gkd_control_stop ();
405 27 : g_main_loop_quit (loop);
406 27 : }
407 :
408 : static gboolean
409 23 : on_signal_term (gpointer user_data)
410 : {
411 23 : gkd_main_quit ();
412 23 : g_debug ("received signal, terminating");
413 23 : return FALSE;
414 : }
415 :
416 : static gboolean
417 0 : on_signal_usr1 (gpointer user_data)
418 : {
419 : #ifdef WITH_DEBUG
420 0 : dump_diagnostics ();
421 : #endif
422 0 : return TRUE;
423 : }
424 :
425 : /* -----------------------------------------------------------------------------
426 : * STARTUP
427 : */
428 :
429 : static int
430 0 : sane_dup2 (int fd1, int fd2)
431 : {
432 : int ret;
433 :
434 0 : retry:
435 0 : ret = dup2 (fd1, fd2);
436 0 : if (ret < 0 && errno == EINTR)
437 0 : goto retry;
438 :
439 0 : return ret;
440 : }
441 :
442 : static gchar*
443 0 : read_login_password (int fd)
444 : {
445 : /* We only accept a max of 8K as the login password */
446 : #define MAX_LENGTH 8192
447 : #define MAX_BLOCK 256
448 :
449 : /*
450 : * When --login is specified then the login password is passed
451 : * in on stdin. All data (including newlines) are part of the
452 : * password. A zero length password is no password.
453 : */
454 :
455 0 : gchar *buf = egg_secure_alloc (MAX_BLOCK);
456 0 : gchar *ret = NULL;
457 0 : int r, len = 0;
458 :
459 : for (;;) {
460 0 : r = read (fd, buf, MAX_BLOCK);
461 0 : if (r < 0) {
462 0 : if (errno == EAGAIN)
463 0 : continue;
464 0 : egg_secure_free (ret);
465 0 : egg_secure_free (buf);
466 0 : return NULL;
467 :
468 0 : } else if (r == 0 || len > MAX_LENGTH) {
469 : break;
470 :
471 : } else {
472 0 : ret = egg_secure_realloc (ret, len + r + 1);
473 0 : memset (ret + len, 0, r + 1);
474 0 : len = len + r;
475 0 : strncat (ret, buf, r);
476 : }
477 : }
478 :
479 0 : egg_secure_free (buf);
480 0 : return ret;
481 : }
482 :
483 : static void
484 0 : cleanup_and_exit (int code)
485 : {
486 0 : egg_cleanup_perform ();
487 0 : exit (code);
488 : }
489 :
490 : static void
491 0 : clear_login_password (void)
492 : {
493 0 : if(login_password)
494 0 : egg_secure_strfree (login_password);
495 0 : login_password = NULL;
496 0 : }
497 :
498 : static void
499 27 : print_environment (void)
500 : {
501 : const gchar **env;
502 49 : for (env = gkd_util_get_environment (); *env; ++env)
503 22 : printf ("%s\n", *env);
504 27 : fflush (stdout);
505 27 : }
506 :
507 : static gboolean
508 0 : initialize_daemon_at (const gchar *directory)
509 : {
510 : gchar **ourenv, **daemonenv, **e;
511 :
512 : /* Exchange environment variables, and try to initialize daemon */
513 0 : ourenv = gkd_util_build_environment (GKD_UTIL_IN_ENVIRONMENT);
514 0 : daemonenv = gkd_control_initialize (directory, run_components,
515 : (const gchar**)ourenv);
516 0 : g_strfreev (ourenv);
517 :
518 : /* Initialization failed, start this process up as a daemon */
519 0 : if (!daemonenv)
520 0 : return FALSE;
521 :
522 : /* Setup all the environment variables we were passed */
523 0 : for (e = daemonenv; *e; ++e)
524 0 : gkd_util_push_environment_full (*e);
525 0 : g_strfreev (daemonenv);
526 :
527 0 : return TRUE;
528 : }
529 :
530 : static gboolean
531 1 : replace_daemon_at (const gchar *directory)
532 : {
533 : gboolean ret;
534 :
535 : /*
536 : * The first control_directory is the environment one, always
537 : * prefer that since it's the one that ssh will connect to
538 : */
539 1 : if (control_directory == NULL)
540 1 : control_directory = g_strdup (directory);
541 :
542 1 : ret = gkd_control_quit (directory, GKD_CONTROL_QUIET_IF_NO_PEER);
543 :
544 : /*
545 : * If we quit, wait a short time before initializing so the other
546 : * daemon can quit completely
547 : */
548 1 : if (ret == TRUE)
549 1 : g_usleep (200 * 1000); /* 200 ms in us */
550 :
551 : /*
552 : * Note that we don't return TRUE, since we want to quit all the
553 : * running daemons (for this session) that may have been started
554 : * by dbus or elsewhere.
555 : */
556 :
557 1 : return FALSE;
558 : }
559 :
560 : typedef gboolean (*DiscoverFunc) (const gchar *control_directory);
561 :
562 : static gboolean
563 1 : discover_other_daemon (DiscoverFunc callback, gboolean acquire)
564 : {
565 : const gchar *control_env;
566 1 : gchar *control = NULL;
567 1 : gboolean acquired = FALSE;
568 : gboolean ret;
569 :
570 : /* A pre-specified directory to control at, don't try anything else */
571 1 : if (control_directory)
572 0 : return (callback) (control_directory);
573 :
574 : /* An environment variable from an already running daemon */
575 1 : control_env = g_getenv (GKD_UTIL_ENV_CONTROL);
576 1 : if (control_env && control_env[0]) {
577 0 : if ((callback)(control_env))
578 0 : return TRUE;
579 : }
580 :
581 : /* Or the default location when no evironment variable */
582 1 : control_env = g_getenv ("XDG_RUNTIME_DIR");
583 1 : if (control_env) {
584 1 : control = g_build_filename (control_env, "keyring", NULL);
585 1 : ret = (callback) (control);
586 1 : g_free (control);
587 1 : g_printerr ("discover_other_daemon: %d", ret);
588 1 : if (ret == TRUE)
589 0 : return TRUE;
590 : }
591 :
592 : /* See if we can contact a daemon running, that didn't set an env variable */
593 1 : if (acquire && !gkd_dbus_singleton_acquire (&acquired))
594 0 : return FALSE;
595 :
596 : /* We're the main daemon */
597 1 : if (acquired)
598 0 : return FALSE;
599 :
600 1 : control = gkd_dbus_singleton_control ();
601 1 : if (control) {
602 0 : ret = (callback) (control);
603 0 : g_free (control);
604 0 : if (ret == TRUE)
605 0 : return TRUE;
606 : }
607 :
608 1 : return FALSE;
609 : }
610 :
611 : static void
612 0 : redirect_fds_after_fork (void)
613 : {
614 : int fd, i;
615 :
616 0 : for (i = 0; i < 3; ++i) {
617 0 : fd = open ("/dev/null", O_RDONLY);
618 0 : sane_dup2 (fd, i);
619 0 : close (fd);
620 : }
621 0 : }
622 :
623 : static void
624 0 : block_on_fd (int fd)
625 : {
626 : unsigned char dummy;
627 0 : read (fd, &dummy, 1);
628 0 : }
629 :
630 : static int
631 27 : fork_and_print_environment (void)
632 : {
633 : int status;
634 : pid_t pid;
635 27 : int wakeup_fds[2] = { -1, -1 };
636 :
637 27 : if (run_foreground) {
638 27 : return -1;
639 : }
640 :
641 0 : if (!g_unix_open_pipe (wakeup_fds, FD_CLOEXEC, NULL))
642 0 : exit (1);
643 :
644 0 : pid = fork ();
645 :
646 0 : if (pid != 0) {
647 : /* Here we are in the initial process */
648 0 : close (wakeup_fds[1]);
649 :
650 0 : if (run_daemonized) {
651 :
652 : /* Initial process, waits for intermediate child */
653 0 : if (pid == -1)
654 0 : exit (1);
655 :
656 0 : waitpid (pid, &status, 0);
657 0 : if (WEXITSTATUS (status) != 0)
658 0 : exit (WEXITSTATUS (status));
659 :
660 : } else {
661 : /* Not double forking, wait for child */
662 0 : block_on_fd (wakeup_fds[0]);
663 : }
664 :
665 : /* The initial process exits successfully */
666 0 : exit (0);
667 : }
668 :
669 0 : if (run_daemonized) {
670 :
671 : /*
672 : * Become session leader of a new session, process group leader of a new
673 : * process group, and detach from the controlling TTY, so that SIGHUP is
674 : * not sent to this process when the previous session leader dies
675 : */
676 0 : setsid ();
677 :
678 : /* Double fork if need to daemonize properly */
679 0 : pid = fork ();
680 :
681 0 : if (pid != 0) {
682 0 : close (wakeup_fds[1]);
683 :
684 : /* Here we are in the intermediate child process */
685 :
686 : /*
687 : * This process exits, so that the final child will inherit
688 : * init as parent to avoid zombies
689 : */
690 0 : if (pid == -1)
691 0 : exit (1);
692 :
693 : /* We've done two forks. */
694 0 : block_on_fd (wakeup_fds[0]);
695 :
696 : /* The intermediate child exits */
697 0 : exit (0);
698 : }
699 :
700 : }
701 :
702 : /* Here we are in the resulting daemon or background process. */
703 0 : return wakeup_fds[1];
704 : }
705 :
706 : static gboolean
707 27 : gkr_daemon_startup_steps (const gchar *components)
708 : {
709 27 : g_assert (components);
710 :
711 : /*
712 : * Startup that must run before forking.
713 : * Note that we set initialized flags early so that two
714 : * initializations don't overlap
715 : */
716 :
717 : #ifdef WITH_SSH
718 : static gboolean ssh_started = FALSE;
719 :
720 : if (strstr (components, GKD_COMP_SSH)) {
721 : if (ssh_started) {
722 : g_message ("The SSH agent was already initialized");
723 : } else {
724 : ssh_started = TRUE;
725 : if (!gkd_daemon_startup_ssh ()) {
726 : ssh_started = FALSE;
727 : return FALSE;
728 : }
729 : }
730 : }
731 : #endif
732 :
733 27 : return TRUE;
734 : }
735 :
736 : static gboolean
737 27 : gkr_daemon_initialize_steps (const gchar *components)
738 : {
739 27 : g_assert (components);
740 :
741 : /*
742 : * Startup that can run after forking.
743 : * Note that we set initialized flags early so that two
744 : * initializations don't overlap
745 : */
746 :
747 27 : if (!initialization_completed) {
748 :
749 : /* The LANG environment variable may have changed */
750 27 : setlocale (LC_ALL, "");
751 :
752 27 : initialization_completed = TRUE;
753 27 : if (timeout_id)
754 0 : g_source_remove (timeout_id);
755 :
756 : /* Initialize new style PKCS#11 components */
757 27 : if (!gkd_pkcs11_initialize ())
758 0 : return FALSE;
759 :
760 : /*
761 : * Unlock the login keyring if we were given a password on STDIN.
762 : * If it does not exist. We create it.
763 : */
764 27 : if (login_password) {
765 0 : if (!gkd_login_unlock (login_password))
766 0 : g_message ("failed to unlock login keyring on startup");
767 0 : egg_secure_strclear (login_password);
768 : }
769 :
770 27 : dbus_started = TRUE;
771 27 : if (!gkd_dbus_setup ())
772 0 : dbus_started = FALSE;
773 : }
774 :
775 : /* The Secret Service API */
776 27 : if (strstr (components, GKD_COMP_SECRETS) || strstr (components, GKD_COMP_KEYRING)) {
777 25 : if (secrets_started) {
778 0 : g_message ("The Secret Service was already initialized");
779 : } else {
780 25 : if (!dbus_started) {
781 0 : dbus_started = TRUE;
782 0 : if (!gkd_dbus_setup ())
783 0 : dbus_started = FALSE;
784 : }
785 25 : if (dbus_started) {
786 25 : secrets_started = TRUE;
787 25 : if (!gkd_dbus_secrets_startup ()) {
788 0 : secrets_started = FALSE;
789 0 : return FALSE;
790 : }
791 : }
792 : }
793 : }
794 :
795 : /* The PKCS#11 remoting */
796 27 : if (strstr (components, GKD_COMP_PKCS11)) {
797 11 : if (pkcs11_started) {
798 0 : g_message ("The PKCS#11 component was already initialized");
799 : } else {
800 11 : pkcs11_started = TRUE;
801 11 : if (!gkd_pkcs11_startup_pkcs11 ()) {
802 0 : pkcs11_started = FALSE;
803 0 : return FALSE;
804 : }
805 : }
806 : }
807 :
808 27 : return TRUE;
809 : }
810 :
811 : void
812 0 : gkd_main_complete_initialization (const gchar *components)
813 : {
814 0 : g_assert (components);
815 :
816 : /*
817 : * Sometimes we don't initialize the full daemon right on
818 : * startup. When run with --login is one such case.
819 : */
820 :
821 0 : gkr_daemon_startup_steps (components);
822 0 : gkr_daemon_initialize_steps (components);
823 0 : }
824 :
825 : static gboolean
826 0 : on_login_timeout (gpointer data)
827 : {
828 0 : if (!initialization_completed)
829 0 : cleanup_and_exit (0);
830 0 : return FALSE;
831 : }
832 :
833 : static void
834 0 : on_vanished_quit_loop (GDBusConnection *connection,
835 : const gchar *name,
836 : gpointer user_data)
837 : {
838 0 : g_main_loop_quit (user_data);
839 0 : }
840 :
841 0 : static void on_logind_session_property_get (GObject *connection,
842 : GAsyncResult *res,
843 : gpointer user_data G_GNUC_UNUSED)
844 : {
845 0 : GError *error = NULL;
846 : GVariant *result, *resultv;
847 : const gchar *state;
848 : gboolean should_quit;
849 :
850 0 : result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (connection), res, &error);
851 :
852 0 : if (error) {
853 0 : if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
854 0 : g_critical ("%s Couldn't get session state: %s", G_STRLOC, error->message);
855 0 : g_error_free (error);
856 0 : return;
857 : }
858 :
859 0 : g_variant_get (result, "(v)", &resultv, NULL);
860 0 : state = g_variant_get_string (resultv, NULL);
861 :
862 0 : should_quit = g_strcmp0 (state, "closing") == 0;
863 :
864 0 : g_clear_pointer (&result, g_variant_unref);
865 0 : g_clear_pointer (&resultv, g_variant_unref);
866 :
867 : /* yes, the session is closing, so we'll quit now */
868 0 : if (should_quit)
869 0 : cleanup_and_exit (0);
870 : }
871 :
872 0 : static void on_logind_session_properties_changed (GDBusConnection *connection,
873 : const gchar *sender_name G_GNUC_UNUSED,
874 : const gchar *object_path,
875 : const gchar *interface_name G_GNUC_UNUSED,
876 : const gchar *signal_name G_GNUC_UNUSED,
877 : GVariant *parameters,
878 : gpointer user_data G_GNUC_UNUSED)
879 : {
880 : const gchar *prop_iface;
881 : gboolean active;
882 : GVariant* changed_properties;
883 :
884 0 : g_variant_get (parameters, "(&s@a{sv}^as)", &prop_iface, &changed_properties, NULL);
885 :
886 0 : if (g_variant_lookup (changed_properties, "Active", "b", &active, NULL)) {
887 0 : if (!active) {
888 : /* ok, the session went inactive, let's see if that is because
889 : * it is closing */
890 0 : g_dbus_connection_call (
891 : connection,
892 : "org.freedesktop.login1",
893 : object_path,
894 : "org.freedesktop.DBus.Properties",
895 : "Get",
896 : g_variant_new ("(ss)", prop_iface, "State"),
897 : G_VARIANT_TYPE ("(v)"),
898 : G_DBUS_CALL_FLAGS_NONE,
899 : -1,
900 : NULL,
901 : on_logind_session_property_get,
902 : NULL
903 : );
904 : }
905 : }
906 :
907 0 : g_variant_unref (changed_properties);
908 0 : }
909 :
910 : static void
911 0 : on_logind_object_path_get (GObject *connection,
912 : GAsyncResult *res,
913 : gpointer user_data G_GNUC_UNUSED)
914 : {
915 0 : GError *error = NULL;
916 : GVariant *result;
917 : const gchar *object_path;
918 : gchar *remote_error;
919 : gboolean is_cancelled, is_name_has_no_owner;
920 :
921 0 : result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (connection), res, &error);
922 :
923 : /* If there's an error we always want to quit - but we only tell the
924 : * user about it if something went wrong. Cancelling the operation or
925 : * not having logind available are okay. */
926 0 : if (error) {
927 0 : is_cancelled = g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
928 :
929 0 : remote_error = g_dbus_error_get_remote_error (error);
930 0 : is_name_has_no_owner = g_strcmp0 (remote_error, "org.freedesktop.DBus.Error.NameHasNoOwner") == 0;
931 :
932 0 : if (!is_cancelled && !is_name_has_no_owner)
933 0 : g_critical ("%s Couldn't get object path: %s", G_STRLOC, error->message);
934 :
935 0 : g_free (remote_error);
936 0 : g_error_free (error);
937 0 : return;
938 : }
939 :
940 : /* now we know which object path to look on, watch for
941 : * PropertiesChanged. Note that, per logind's documentation, we only
942 : * get notified for 'Active' changing */
943 0 : g_variant_get (result, "(&o)", &object_path, NULL);
944 :
945 0 : g_dbus_connection_signal_subscribe (
946 0 : G_DBUS_CONNECTION (connection),
947 : "org.freedesktop.login1",
948 : "org.freedesktop.DBus.Properties",
949 : "PropertiesChanged",
950 : object_path,
951 : NULL,
952 : G_DBUS_SIGNAL_FLAGS_NONE,
953 : on_logind_session_properties_changed,
954 : NULL,
955 : NULL
956 : );
957 :
958 0 : g_clear_pointer (&result, g_variant_unref);
959 : }
960 :
961 : static void
962 0 : start_watching_logind_for_session_closure ()
963 : {
964 0 : g_return_if_fail (system_bus_connection != NULL);
965 :
966 : const gchar *xdg_session_id;
967 :
968 0 : xdg_session_id = g_getenv ("XDG_SESSION_ID");
969 :
970 0 : if (!xdg_session_id)
971 0 : return;
972 :
973 : /* get the right object path */
974 0 : g_dbus_connection_call (
975 : system_bus_connection,
976 : "org.freedesktop.login1",
977 : "/org/freedesktop/login1",
978 : "org.freedesktop.login1.Manager",
979 : "GetSession",
980 : g_variant_new ("(s)", xdg_session_id, NULL),
981 : G_VARIANT_TYPE ("(o)"),
982 : G_DBUS_CALL_FLAGS_NO_AUTO_START,
983 : -1,
984 : NULL,
985 : on_logind_object_path_get,
986 : NULL
987 : );
988 : }
989 :
990 : int
991 27 : main (int argc, char *argv[])
992 : {
993 : /*
994 : * The gnome-keyring startup is not as simple as I wish it could be.
995 : *
996 : * It's often started in the primordial stages of a session, where
997 : * there's no DBus, and no proper X display. This is the strange world
998 : * of PAM.
999 : *
1000 : * When started with the --login option, we do as little initialization
1001 : * as possible. We expect a login password on the stdin, and unlock
1002 : * or create the login keyring.
1003 : *
1004 : * Then later we expect gnome-keyring-dameon to be run again with the
1005 : * --start option. This second gnome-keyring-daemon will hook the
1006 : * original daemon up with environment variables necessary to initialize
1007 : * itself and bring it into the session. This second daemon usually exits.
1008 : *
1009 : * Without either of these options, we follow a more boring and
1010 : * predictable startup.
1011 : */
1012 :
1013 27 : GDBusConnection *connection = NULL;
1014 27 : GError *error = NULL;
1015 :
1016 : /*
1017 : * Before we do ANYTHING, we drop privileges so we don't become
1018 : * a security issue ourselves.
1019 : */
1020 27 : gkd_capability_obtain_capability_and_drop_privileges ();
1021 :
1022 : #ifdef WITH_STRICT
1023 : g_setenv ("DBUS_FATAL_WARNINGS", "1", FALSE);
1024 : if (!g_getenv ("G_DEBUG"))
1025 : g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
1026 : #endif
1027 :
1028 : #if !GLIB_CHECK_VERSION(2,35,0)
1029 : g_type_init ();
1030 : #endif
1031 :
1032 : /* internationalisation */
1033 27 : setlocale (LC_ALL, "");
1034 :
1035 : #ifdef HAVE_GETTEXT
1036 27 : bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
1037 27 : textdomain (GETTEXT_PACKAGE);
1038 27 : bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1039 : #endif
1040 :
1041 27 : egg_libgcrypt_initialize ();
1042 :
1043 : /* Send all warning or error messages to syslog */
1044 27 : prepare_logging ();
1045 :
1046 27 : parse_arguments (&argc, &argv);
1047 :
1048 : /* The --version option. This is machine parseable output */
1049 27 : if (run_version) {
1050 0 : g_print ("gnome-keyring-daemon: %s\n", VERSION);
1051 0 : g_print ("testing: %s\n",
1052 : #ifdef WITH_DEBUG
1053 : "enabled");
1054 : #else
1055 : "disabled");
1056 : #endif
1057 0 : exit (0);
1058 : }
1059 :
1060 27 : if (perform_unlock) {
1061 0 : login_password = read_login_password (STDIN);
1062 0 : atexit (clear_login_password);
1063 : }
1064 :
1065 : /* The whole forking and daemonizing dance starts here. */
1066 27 : parent_wakeup_fd = fork_and_print_environment();
1067 :
1068 : /* The --start option */
1069 27 : if (run_for_start) {
1070 0 : if (discover_other_daemon (initialize_daemon_at, TRUE)) {
1071 : /*
1072 : * Another daemon was initialized, print out environment,
1073 : * tell parent we're done, and quit or go comatose.
1074 : */
1075 0 : print_environment ();
1076 0 : close (parent_wakeup_fd);
1077 0 : if (run_foreground) {
1078 0 : connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1079 0 : if (error) {
1080 0 : g_warning ("Couldn't connect to session bus: %s", error->message);
1081 0 : g_clear_error (&error);
1082 : }
1083 0 : loop = g_main_loop_new (NULL, FALSE);
1084 0 : g_bus_watch_name (G_BUS_TYPE_SESSION, "org.gnome.keyring",
1085 : G_BUS_NAME_WATCHER_FLAGS_NONE,
1086 : NULL, on_vanished_quit_loop, loop, NULL);
1087 0 : g_main_loop_run (loop);
1088 0 : g_clear_pointer (&loop, g_main_loop_unref);
1089 0 : g_clear_object (&connection);
1090 : }
1091 0 : cleanup_and_exit (0);
1092 : }
1093 :
1094 : /* The --replace option */
1095 27 : } else if (run_for_replace) {
1096 1 : discover_other_daemon (replace_daemon_at, FALSE);
1097 1 : if (control_directory)
1098 1 : g_message ("Replacing daemon, using directory: %s", control_directory);
1099 : else
1100 0 : g_message ("Could not find daemon to replace, staring normally");
1101 : }
1102 :
1103 : /* Initialize the main directory */
1104 27 : gkd_util_init_master_directory (control_directory);
1105 :
1106 : /* Initialize our daemon main loop and threading */
1107 27 : loop = g_main_loop_new (NULL, FALSE);
1108 :
1109 : /* Initialize our control socket */
1110 27 : if (!gkd_control_listen ())
1111 0 : return FALSE;
1112 :
1113 : /* The --login option. Delayed initialization */
1114 27 : if (run_for_login) {
1115 0 : timeout_id = g_timeout_add_seconds (LOGIN_TIMEOUT, (GSourceFunc) on_login_timeout, NULL);
1116 :
1117 : /* Not a login daemon. Startup stuff now.*/
1118 : } else {
1119 : /* These are things that can run before forking */
1120 27 : if (!gkr_daemon_startup_steps (run_components))
1121 0 : cleanup_and_exit (1);
1122 : }
1123 :
1124 : /* if we can get a connection to the system bus, watch it and then kill
1125 : * ourselves when our session closes */
1126 :
1127 27 : system_bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
1128 :
1129 27 : if (system_bus_connection)
1130 0 : start_watching_logind_for_session_closure ();
1131 :
1132 27 : signal (SIGPIPE, SIG_IGN);
1133 :
1134 : /* Print the environment and tell the parent we're done */
1135 27 : print_environment ();
1136 :
1137 27 : if (!run_foreground) {
1138 0 : close (parent_wakeup_fd);
1139 0 : redirect_fds_after_fork ();
1140 : }
1141 :
1142 27 : g_unix_signal_add (SIGTERM, on_signal_term, loop);
1143 27 : g_unix_signal_add (SIGHUP, on_signal_term, loop);
1144 27 : g_unix_signal_add (SIGUSR1, on_signal_usr1, loop);
1145 :
1146 : /* Prepare logging a second time, since we may be in a different process */
1147 27 : prepare_logging();
1148 :
1149 : /* Remainder initialization after forking, if initialization not delayed */
1150 27 : if (!run_for_login) {
1151 27 : gkr_daemon_initialize_steps (run_components);
1152 :
1153 : /*
1154 : * Close stdout and so that the caller knows that we're
1155 : * all initialized, (when run in foreground mode).
1156 : *
1157 : * However since some logging goes to stdout, redirect that
1158 : * to stderr. We don't want the caller confusing that with
1159 : * valid output anyway.
1160 : */
1161 27 : if (dup2 (2, 1) < 1)
1162 0 : g_warning ("couldn't redirect stdout to stderr");
1163 :
1164 27 : g_debug ("initialization complete");
1165 : }
1166 :
1167 27 : g_main_loop_run (loop);
1168 :
1169 : /* This wraps everything up in order */
1170 27 : egg_cleanup_perform ();
1171 :
1172 27 : g_free (control_directory);
1173 :
1174 27 : g_debug ("exiting cleanly");
1175 27 : return 0;
1176 : }
|