1 /* g13.c - Disk Key management with GnuPG
2 * Copyright (C) 2009 Free Software Foundation, Inc.
3 *
4 * This file is part of GnuPG.
5 *
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GnuPG 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
14 * GNU 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, see <https://www.gnu.org/licenses/>.
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <npth.h>
31
32 #define INCLUDED_BY_MAIN_MODULE 1
33 #include "g13.h"
34
35 #include <gcrypt.h>
36 #include <assuan.h>
37
38 #include "../common/i18n.h"
39 #include "../common/sysutils.h"
40 #include "../common/gc-opt-flags.h"
41 #include "../common/asshelp.h"
42 #include "../common/init.h"
43 #include "keyblob.h"
44 #include "server.h"
45 #include "runner.h"
46 #include "create.h"
47 #include "mount.h"
48 #include "suspend.h"
49 #include "mountinfo.h"
50 #include "backend.h"
51 #include "call-syshelp.h"
52
53
54 enum cmd_and_opt_values {
55 aNull = 0,
56 oQuiet = 'q',
57 oVerbose = 'v',
58 oRecipient = 'r',
59
60 aGPGConfList = 500,
61 aGPGConfTest,
62 aCreate,
63 aMount,
64 aUmount,
65 aSuspend,
66 aResume,
67 aServer,
68 aFindDevice,
69
70 oOptions,
71 oDebug,
72 oDebugLevel,
73 oDebugAll,
74 oDebugNone,
75 oDebugWait,
76 oDebugAllowCoreDump,
77 oLogFile,
78 oNoLogFile,
79 oAuditLog,
80
81 oOutput,
82
83 oAgentProgram,
84 oGpgProgram,
85 oType,
86
87 oDisplay,
88 oTTYname,
89 oTTYtype,
90 oLCctype,
91 oLCmessages,
92 oXauthority,
93
94 oStatusFD,
95 oLoggerFD,
96
97 oNoVerbose,
98 oNoSecmemWarn,
99 oNoGreeting,
100 oNoTTY,
101 oNoOptions,
102 oHomedir,
103 oWithColons,
104 oDryRun,
105 oNoDetach,
106
107 oNoRandomSeedFile,
108 oFakedSystemTime
109 };
110
111
112 static gpgrt_opt_t opts[] = {
113
114 ARGPARSE_group (300, N_("@Commands:\n ")),
115
116 ARGPARSE_c (aCreate, "create", N_("Create a new file system container")),
117 ARGPARSE_c (aMount, "mount", N_("Mount a file system container") ),
118 ARGPARSE_c (aUmount, "umount", N_("Unmount a file system container") ),
119 ARGPARSE_c (aSuspend, "suspend", N_("Suspend a file system container") ),
120 ARGPARSE_c (aResume, "resume", N_("Resume a file system container") ),
121 ARGPARSE_c (aServer, "server", N_("Run in server mode")),
122 ARGPARSE_c (aFindDevice, "find-device", "@"),
123
124 ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
125 ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
126
127 ARGPARSE_group (301, N_("@\nOptions:\n ")),
128
129 ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
130 ARGPARSE_s_s (oType, "type", N_("|NAME|use container format NAME")),
131
132 ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
133 ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
134 ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
135 ARGPARSE_s_n (oNoTTY, "no-tty", N_("don't use the terminal at all")),
136 ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
137 ARGPARSE_s_s (oLogFile, "log-file", N_("|FILE|write log output to FILE")),
138 ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
139 ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
140
141 ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
142
143 ARGPARSE_conffile (oOptions, "options", N_("|FILE|read options from FILE")),
144
145 ARGPARSE_s_s (oDebug, "debug", "@"),
146 ARGPARSE_s_s (oDebugLevel, "debug-level",
147 N_("|LEVEL|set the debugging level to LEVEL")),
148 ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
149 ARGPARSE_s_n (oDebugNone, "debug-none", "@"),
150 ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
151 ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
152
153 ARGPARSE_s_i (oStatusFD, "status-fd",
154 N_("|FD|write status info to this FD")),
155
156 ARGPARSE_group (302, N_(
157 "@\n(See the man page for a complete listing of all commands and options)\n"
158 )),
159
160 ARGPARSE_group (303, N_("@\nExamples:\n\n"
161 " blurb\n"
162 " blurb\n")),
163
164 /* Hidden options. */
165 ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
166 ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"),
167 ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
168 ARGPARSE_noconffile (oNoOptions, "no-options", "@"),
169 ARGPARSE_s_s (oHomedir, "homedir", "@"),
170 ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
171 ARGPARSE_s_s (oGpgProgram, "gpg-program", "@"),
172 ARGPARSE_s_s (oDisplay, "display", "@"),
173 ARGPARSE_s_s (oTTYname, "ttyname", "@"),
174 ARGPARSE_s_s (oTTYtype, "ttytype", "@"),
175 ARGPARSE_s_s (oLCctype, "lc-ctype", "@"),
176 ARGPARSE_s_s (oLCmessages, "lc-messages", "@"),
177 ARGPARSE_s_s (oXauthority, "xauthority", "@"),
178 ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
179 ARGPARSE_s_n (oWithColons, "with-colons", "@"),
180 ARGPARSE_s_n (oNoRandomSeedFile, "no-random-seed-file", "@"),
181
182 /* Command aliases. */
183
184 ARGPARSE_end ()
185 };
186
187
188 /* The list of supported debug flags. */
189 static struct debug_flags_s debug_flags [] =
190 {
191 { DBG_MOUNT_VALUE , "mount" },
192 { DBG_CRYPTO_VALUE , "crypto" },
193 { DBG_MEMORY_VALUE , "memory" },
194 { DBG_MEMSTAT_VALUE, "memstat" },
195 { DBG_IPC_VALUE , "ipc" },
196 { 0, NULL }
197 };
198
199
200 /* The timer tick interval used by the idle task. */
201 #define TIMERTICK_INTERVAL_SEC (1)
202
203 /* It is possible that we are currently running under setuid permissions. */
204 static int maybe_setuid = 1;
205
206 /* Helper to implement --debug-level and --debug. */
207 static const char *debug_level;
208 static unsigned int debug_value;
209
210 /* Flag to indicate that a shutdown was requested. */
211 static int shutdown_pending;
212
213 /* The thread id of the idle task. */
214 static npth_t idle_task_thread;
215
216
217 /* The container type as specified on the command line. */
218 static int cmdline_conttype;
219
220
221
222 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
223 enum cmd_and_opt_values new_cmd );
224
225 static void start_idle_task (void);
226 static void join_idle_task (void);
227
228
229 /* Begin NPth wrapper functions. */
230 ASSUAN_SYSTEM_NPTH_IMPL;
231
232
233 static const char *
my_strusage(int level)234 my_strusage( int level )
235 {
236 const char *p;
237
238 switch (level)
239 {
240 case 9: p = "GPL-3.0-or-later"; break;
241 case 11: p = "@G13@ (@GNUPG@)";
242 break;
243 case 13: p = VERSION; break;
244 case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
245 case 17: p = PRINTABLE_OS_NAME; break;
246 case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
247 break;
248 case 1:
249 case 40: p = _("Usage: @G13@ [options] [files] (-h for help)");
250 break;
251 case 41:
252 p = _("Syntax: @G13@ [options] [files]\n"
253 "Create, mount or unmount an encrypted file system container\n");
254 break;
255
256 case 31: p = "\nHome: "; break;
257 case 32: p = gnupg_homedir (); break;
258
259 default: p = NULL; break;
260 }
261 return p;
262 }
263
264
265 static void
wrong_args(const char * text)266 wrong_args (const char *text)
267 {
268 fprintf (stderr, _("usage: %s [options] "), G13_NAME);
269 fputs (text, stderr);
270 putc ('\n', stderr);
271 g13_exit (2);
272 }
273
274
275 /* Setup the debugging. With a DEBUG_LEVEL of NULL only the active
276 debug flags are propagated to the subsystems. With DEBUG_LEVEL
277 set, a specific set of debug flags is set; and individual debugging
278 flags will be added on top. */
279 static void
set_debug(void)280 set_debug (void)
281 {
282 int numok = (debug_level && digitp (debug_level));
283 int numlvl = numok? atoi (debug_level) : 0;
284
285 if (!debug_level)
286 ;
287 else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
288 opt.debug = 0;
289 else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
290 opt.debug = DBG_IPC_VALUE|DBG_MOUNT_VALUE;
291 else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
292 opt.debug = DBG_IPC_VALUE|DBG_MOUNT_VALUE;
293 else if (!strcmp (debug_level, "expert") || (numok && numlvl <= 8))
294 opt.debug = (DBG_IPC_VALUE|DBG_MOUNT_VALUE|DBG_CRYPTO_VALUE);
295 else if (!strcmp (debug_level, "guru") || numok)
296 {
297 opt.debug = ~0;
298 /* if (numok) */
299 /* opt.debug &= ~(DBG_HASHING_VALUE); */
300 }
301 else
302 {
303 log_error (_("invalid debug-level '%s' given\n"), debug_level);
304 g13_exit(2);
305 }
306
307 opt.debug |= debug_value;
308
309 if (opt.debug && !opt.verbose)
310 opt.verbose = 1;
311 if (opt.debug)
312 opt.quiet = 0;
313
314 if (opt.debug & DBG_CRYPTO_VALUE )
315 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
316 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
317
318 if (opt.debug)
319 parse_debug_flag (NULL, &opt.debug, debug_flags);
320 }
321
322
323
324 static void
set_cmd(enum cmd_and_opt_values * ret_cmd,enum cmd_and_opt_values new_cmd)325 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
326 {
327 enum cmd_and_opt_values cmd = *ret_cmd;
328
329 if (!cmd || cmd == new_cmd)
330 cmd = new_cmd;
331 else
332 {
333 log_error (_("conflicting commands\n"));
334 g13_exit (2);
335 }
336
337 *ret_cmd = cmd;
338 }
339
340
341 int
main(int argc,char ** argv)342 main (int argc, char **argv)
343 {
344 gpgrt_argparse_t pargs;
345 int orig_argc;
346 char **orig_argv;
347 gpg_error_t err = 0;
348 /* const char *fname; */
349 int may_coredump;
350 char *last_configname = NULL;
351 const char *configname = NULL;
352 int debug_argparser = 0;
353 int no_more_options = 0;
354 char *logfile = NULL;
355 int greeting = 0;
356 int nogreeting = 0;
357 /* int debug_wait = 0; */
358 int use_random_seed = 1;
359 /* int nodetach = 0; */
360 /* int nokeysetup = 0; */
361 enum cmd_and_opt_values cmd = 0;
362 struct server_control_s ctrl;
363 strlist_t recipients = NULL;
364
365 /*mtrace();*/
366
367 early_system_init ();
368 gnupg_reopen_std (G13_NAME);
369 gpgrt_set_strusage (my_strusage);
370 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
371
372 log_set_prefix (G13_NAME, GPGRT_LOG_WITH_PREFIX);
373
374 /* Make sure that our subsystems are ready. */
375 i18n_init ();
376 init_common_subsystems (&argc, &argv);
377
378 npth_init ();
379
380 /* Take extra care of the random pool. */
381 gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
382
383 may_coredump = disable_core_dumps ();
384
385 g13_init_signals ();
386
387 dotlock_create (NULL, 0); /* Register locking cleanup. */
388
389 opt.session_env = session_env_new ();
390 if (!opt.session_env)
391 log_fatal ("error allocating session environment block: %s\n",
392 strerror (errno));
393
394 /* First check whether we have a config file on the commandline. */
395 orig_argc = argc;
396 orig_argv = argv;
397 pargs.argc = &argc;
398 pargs.argv = &argv;
399 pargs.flags= (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
400 while (gpgrt_argparse (NULL, &pargs, opts))
401 {
402 switch (pargs.r_opt)
403 {
404 case oDebug:
405 case oDebugAll:
406 debug_argparser++;
407 break;
408
409 case oHomedir:
410 gnupg_set_homedir (pargs.r.ret_str);
411 break;
412 }
413 }
414 /* Reset the flags. */
415 pargs.flags &= ~(ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
416
417 /* Initialize the secure memory. */
418 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
419 maybe_setuid = 0;
420
421 /*
422 * Now we are now working under our real uid
423 */
424
425 /* Setup malloc hooks. */
426 {
427 struct assuan_malloc_hooks malloc_hooks;
428
429 malloc_hooks.malloc = gcry_malloc;
430 malloc_hooks.realloc = gcry_realloc;
431 malloc_hooks.free = gcry_free;
432 assuan_set_malloc_hooks (&malloc_hooks);
433 }
434
435 /* Prepare libassuan. */
436 assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
437 assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
438 setup_libassuan_logging (&opt.debug, NULL);
439
440 /* Setup a default control structure for command line mode. */
441 memset (&ctrl, 0, sizeof ctrl);
442 g13_init_default_ctrl (&ctrl);
443 ctrl.no_server = 1;
444 ctrl.status_fd = -1; /* No status output. */
445
446 /* The configuraton directories for use by gpgrt_argparser. */
447 gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
448 gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
449
450 /* We are re-using the struct, thus the reset flag. We OR the
451 * flags so that the internal intialized flag won't be cleared. */
452 argc = orig_argc;
453 argv = orig_argv;
454 pargs.argc = &argc;
455 pargs.argv = &argv;
456 pargs.flags |= (ARGPARSE_FLAG_RESET
457 | ARGPARSE_FLAG_KEEP
458 | ARGPARSE_FLAG_SYS
459 | ARGPARSE_FLAG_USER);
460
461 while (!no_more_options
462 && gpgrt_argparser (&pargs, opts, G13_NAME EXTSEP_S "conf"))
463 {
464 switch (pargs.r_opt)
465 {
466 case ARGPARSE_CONFFILE:
467 {
468 if (debug_argparser)
469 log_info (_("reading options from '%s'\n"),
470 pargs.r_type? pargs.r.ret_str: "[cmdline]");
471 if (pargs.r_type)
472 {
473 xfree (last_configname);
474 last_configname = xstrdup (pargs.r.ret_str);
475 configname = last_configname;
476 }
477 else
478 configname = NULL;
479 }
480 break;
481
482 case aGPGConfList:
483 case aGPGConfTest:
484 set_cmd (&cmd, pargs.r_opt);
485 nogreeting = 1;
486 /* nokeysetup = 1; */
487 break;
488
489 case aServer:
490 case aMount:
491 case aUmount:
492 case aSuspend:
493 case aResume:
494 case aCreate:
495 case aFindDevice:
496 set_cmd (&cmd, pargs.r_opt);
497 break;
498
499 case oOutput: opt.outfile = pargs.r.ret_str; break;
500
501 case oQuiet: opt.quiet = 1; break;
502 case oNoGreeting: nogreeting = 1; break;
503 case oNoTTY: break;
504
505 case oDryRun: opt.dry_run = 1; break;
506
507 case oVerbose:
508 opt.verbose++;
509 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
510 break;
511 case oNoVerbose:
512 opt.verbose = 0;
513 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
514 break;
515
516 case oLogFile: logfile = pargs.r.ret_str; break;
517 case oNoLogFile: logfile = NULL; break;
518
519 case oNoDetach: /*nodetach = 1; */break;
520
521 case oDebug:
522 if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
523 {
524 pargs.r_opt = ARGPARSE_INVALID_ARG;
525 pargs.err = ARGPARSE_PRINT_ERROR;
526 }
527 break;
528 case oDebugAll: debug_value = ~0; break;
529 case oDebugNone: debug_value = 0; break;
530 case oDebugLevel: debug_level = pargs.r.ret_str; break;
531 case oDebugWait: /*debug_wait = pargs.r.ret_int; */break;
532 case oDebugAllowCoreDump:
533 may_coredump = enable_core_dumps ();
534 break;
535
536 case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
537 case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
538
539 case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
540
541 case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
542 case oGpgProgram: opt.gpg_program = pargs.r.ret_str; break;
543 case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
544 case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
545 case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
546 case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
547 case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
548 case oXauthority: opt.xauthority = xstrdup (pargs.r.ret_str); break;
549
550 case oFakedSystemTime:
551 {
552 time_t faked_time = isotime2epoch (pargs.r.ret_str);
553 if (faked_time == (time_t)(-1))
554 faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
555 gnupg_set_time (faked_time, 0);
556 }
557 break;
558
559 case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;
560
561 case oNoRandomSeedFile: use_random_seed = 0; break;
562
563 case oRecipient: /* Store the encryption key. */
564 add_to_strlist (&recipients, pargs.r.ret_str);
565 break;
566
567 case oType:
568 if (!strcmp (pargs.r.ret_str, "help"))
569 {
570 be_parse_conttype_name (NULL);
571 g13_exit (0);
572 }
573 cmdline_conttype = be_parse_conttype_name (pargs.r.ret_str);
574 if (!cmdline_conttype)
575 {
576 pargs.r_opt = ARGPARSE_INVALID_ARG;
577 pargs.err = ARGPARSE_PRINT_ERROR;
578 }
579 break;
580
581 default:
582 if (configname)
583 pargs.err = ARGPARSE_PRINT_WARNING;
584 else
585 pargs.err = ARGPARSE_PRINT_ERROR;
586 break;
587 }
588 }
589
590 gpgrt_argparse (NULL, &pargs, NULL);
591
592 /* Construct GPG arguments. */
593 {
594 strlist_t last;
595 last = append_to_strlist (&opt.gpg_arguments, "-z");
596 last = append_to_strlist (&last, "0");
597 last = append_to_strlist (&last, "--trust-model");
598 last = append_to_strlist (&last, "always");
599 (void) last;
600 }
601
602 if (!last_configname)
603 opt.config_filename = gpgrt_fnameconcat (gnupg_homedir (),
604 G13_NAME EXTSEP_S "conf",
605 NULL);
606 else
607 {
608 opt.config_filename = last_configname;
609 last_configname = NULL;
610 }
611
612 if (log_get_errorcount(0))
613 g13_exit(2);
614
615 /* Now that we have the options parsed we need to update the default
616 control structure. */
617 g13_init_default_ctrl (&ctrl);
618 ctrl.recipients = recipients;
619 recipients = NULL;
620
621 if (nogreeting)
622 greeting = 0;
623
624 if (greeting)
625 {
626 fprintf (stderr, "%s %s; %s\n",
627 gpgrt_strusage(11), gpgrt_strusage(13), gpgrt_strusage(14) );
628 fprintf (stderr, "%s\n", gpgrt_strusage(15));
629 }
630
631 if (may_coredump && !opt.quiet)
632 log_info (_("WARNING: program may create a core file!\n"));
633
634 /* Print a warning if an argument looks like an option. */
635 if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
636 {
637 int i;
638
639 for (i=0; i < argc; i++)
640 if (argv[i][0] == '-' && argv[i][1] == '-')
641 log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
642 }
643
644
645 if (logfile)
646 {
647 log_set_file (logfile);
648 log_set_prefix (NULL, (GPGRT_LOG_WITH_PREFIX
649 | GPGRT_LOG_WITH_TIME
650 | GPGRT_LOG_WITH_PID));
651 }
652
653 if (gnupg_faked_time_p ())
654 {
655 gnupg_isotime_t tbuf;
656
657 log_info (_("WARNING: running with faked system time: "));
658 gnupg_get_isotime (tbuf);
659 dump_isotime (tbuf);
660 log_printf ("\n");
661 }
662
663 /* Print any pending secure memory warnings. */
664 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
665
666 /* Setup the debug flags for all subsystems. */
667 set_debug ();
668
669 /* Install emergency cleanup handler. */
670 g13_install_emergency_cleanup ();
671
672 /* Terminate if we found any error until now. */
673 if (log_get_errorcount(0))
674 g13_exit (2);
675
676 /* Set the standard GnuPG random seed file. */
677 if (use_random_seed)
678 {
679 char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
680 gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
681 xfree(p);
682 }
683
684 /* Store given filename into FNAME. */
685 /* fname = argc? *argv : NULL; */
686
687 /* Parse all given encryption keys. This does a lookup of the keys
688 and stops if any of the given keys was not found. */
689 #if 0 /* Currently not implemented. */
690 if (!nokeysetup)
691 {
692 strlist_t sl;
693 int failed = 0;
694
695 for (sl = ctrl->recipients; sl; sl = sl->next)
696 if (check_encryption_key ())
697 failed = 1;
698 if (failed)
699 g13_exit (1);
700 }
701 #endif /*0*/
702
703 /* Dispatch command. */
704 err = 0;
705 switch (cmd)
706 {
707 case aGPGConfList:
708 { /* List options and default values in the GPG Conf format. */
709 char *config_filename_esc = percent_escape (opt.config_filename, NULL);
710
711 printf ("gpgconf-g13.conf:%lu:\"%s\n",
712 GC_OPT_FLAG_DEFAULT, config_filename_esc);
713 xfree (config_filename_esc);
714
715 printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
716 printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE);
717 printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
718 printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
719 }
720 break;
721 case aGPGConfTest:
722 /* This is merely a dummy command to test whether the
723 configuration file is valid. */
724 break;
725
726 case aServer:
727 {
728 start_idle_task ();
729 ctrl.no_server = 0;
730 err = g13_server (&ctrl);
731 if (err)
732 log_error ("server exited with error: %s <%s>\n",
733 gpg_strerror (err), gpg_strsource (err));
734 else
735 g13_request_shutdown ();
736 }
737 break;
738
739 case aFindDevice:
740 {
741 char *blockdev;
742
743 if (argc != 1)
744 wrong_args ("--find-device name");
745
746 err = call_syshelp_find_device (&ctrl, argv[0], &blockdev);
747 if (err)
748 log_error ("error finding device '%s': %s <%s>\n",
749 argv[0], gpg_strerror (err), gpg_strsource (err));
750 else
751 puts (blockdev);
752 }
753 break;
754
755 case aCreate: /* Create a new container. */
756 {
757 if (argc != 1)
758 wrong_args ("--create filename");
759 start_idle_task ();
760 err = g13_create_container (&ctrl, argv[0]);
761 if (err)
762 log_error ("error creating a new container: %s <%s>\n",
763 gpg_strerror (err), gpg_strsource (err));
764 else
765 g13_request_shutdown ();
766 }
767 break;
768
769 case aMount: /* Mount a container. */
770 {
771 if (argc != 1 && argc != 2 )
772 wrong_args ("--mount filename [mountpoint]");
773 start_idle_task ();
774 err = g13_mount_container (&ctrl, argv[0], argc == 2?argv[1]:NULL);
775 if (err)
776 log_error ("error mounting container '%s': %s <%s>\n",
777 *argv, gpg_strerror (err), gpg_strsource (err));
778 }
779 break;
780
781 case aUmount: /* Unmount a mounted container. */
782 {
783 if (argc != 1)
784 wrong_args ("--umount filename");
785 err = g13_umount_container (&ctrl, argv[0], NULL);
786 if (err)
787 log_error ("error unmounting container '%s': %s <%s>\n",
788 *argv, gpg_strerror (err), gpg_strsource (err));
789 }
790 break;
791
792 case aSuspend: /* Suspend a container. */
793 {
794 /* Fixme: Should we add a suspend all container option? */
795 if (argc != 1)
796 wrong_args ("--suspend filename");
797 err = g13_suspend_container (&ctrl, argv[0]);
798 if (err)
799 log_error ("error suspending container '%s': %s <%s>\n",
800 *argv, gpg_strerror (err), gpg_strsource (err));
801 }
802 break;
803
804 case aResume: /* Resume a suspended container. */
805 {
806 /* Fixme: Should we add a resume all container option? */
807 if (argc != 1)
808 wrong_args ("--resume filename");
809 err = g13_resume_container (&ctrl, argv[0]);
810 if (err)
811 log_error ("error resuming container '%s': %s <%s>\n",
812 *argv, gpg_strerror (err), gpg_strsource (err));
813 }
814 break;
815
816 default:
817 log_error (_("invalid command (there is no implicit command)\n"));
818 break;
819 }
820
821 g13_deinit_default_ctrl (&ctrl);
822
823 if (!err)
824 join_idle_task ();
825
826 /* Cleanup. */
827 g13_exit (0);
828 return 8; /*NOTREACHED*/
829 }
830
831
832 /* Store defaults into the per-connection CTRL object. */
833 void
g13_init_default_ctrl(ctrl_t ctrl)834 g13_init_default_ctrl (ctrl_t ctrl)
835 {
836 ctrl->conttype = cmdline_conttype? cmdline_conttype : CONTTYPE_ENCFS;
837 }
838
839
840 /* Release remaining resources allocated in the CTRL object. */
841 void
g13_deinit_default_ctrl(ctrl_t ctrl)842 g13_deinit_default_ctrl (ctrl_t ctrl)
843 {
844 call_syshelp_release (ctrl);
845 FREE_STRLIST (ctrl->recipients);
846 }
847
848
849 /* Request a shutdown. This can be used when the process should
850 * finish instead of running the idle task. */
851 void
g13_request_shutdown(void)852 g13_request_shutdown (void)
853 {
854 shutdown_pending++;
855 }
856
857
858 /* This function is called for each signal we catch. It is run in the
859 main context or the one of a NPth thread and thus it is not
860 restricted in what it may do. */
861 static void
handle_signal(int signo)862 handle_signal (int signo)
863 {
864 switch (signo)
865 {
866 #ifndef HAVE_W32_SYSTEM
867 case SIGHUP:
868 log_info ("SIGHUP received - re-reading configuration\n");
869 /* Fixme: Not yet implemented. */
870 break;
871
872 case SIGUSR1:
873 log_info ("SIGUSR1 received - printing internal information:\n");
874 /* Fixme: We need to see how to integrate pth dumping into our
875 logging system. */
876 /* pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); */
877 mountinfo_dump_all ();
878 break;
879
880 case SIGUSR2:
881 log_info ("SIGUSR2 received - no action defined\n");
882 break;
883
884 case SIGTERM:
885 if (!shutdown_pending)
886 log_info ("SIGTERM received - shutting down ...\n");
887 else
888 log_info ("SIGTERM received - still %u runners active\n",
889 runner_get_threads ());
890 shutdown_pending++;
891 if (shutdown_pending > 2)
892 {
893 log_info ("shutdown forced\n");
894 log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13) );
895 g13_exit (0);
896 }
897 break;
898
899 case SIGINT:
900 log_info ("SIGINT received - immediate shutdown\n");
901 log_info( "%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
902 g13_exit (0);
903 break;
904 #endif /*!HAVE_W32_SYSTEM*/
905
906 default:
907 log_info ("signal %d received - no action defined\n", signo);
908 }
909 }
910
911
912 /* This ticker function is called about every TIMERTICK_INTERVAL_SEC
913 seconds. */
914 static void
handle_tick(void)915 handle_tick (void)
916 {
917 /* log_debug ("TICK\n"); */
918 }
919
920
921 /* The idle task. We use a separate thread to do idle stuff and to
922 catch signals. */
923 static void *
idle_task(void * dummy_arg)924 idle_task (void *dummy_arg)
925 {
926 int signo; /* The number of a raised signal is stored here. */
927 int saved_errno;
928 struct timespec abstime;
929 struct timespec curtime;
930 struct timespec timeout;
931 int ret;
932
933 (void)dummy_arg;
934
935 /* Create the event to catch the signals. */
936 #ifndef HAVE_W32_SYSTEM
937 npth_sigev_init ();
938 npth_sigev_add (SIGHUP);
939 npth_sigev_add (SIGUSR1);
940 npth_sigev_add (SIGUSR2);
941 npth_sigev_add (SIGINT);
942 npth_sigev_add (SIGTERM);
943 npth_sigev_fini ();
944 #endif
945
946 npth_clock_gettime (&abstime);
947 abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
948
949 for (;;)
950 {
951 /* The shutdown flag allows us to terminate the idle task. */
952 if (shutdown_pending)
953 {
954 runner_cancel_all ();
955
956 if (!runner_get_threads ())
957 break; /* ready */
958 }
959
960 npth_clock_gettime (&curtime);
961 if (!(npth_timercmp (&curtime, &abstime, <)))
962 {
963 /* Timeout. */
964 handle_tick ();
965 npth_clock_gettime (&abstime);
966 abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
967 }
968 npth_timersub (&abstime, &curtime, &timeout);
969
970 #ifndef HAVE_W32_SYSTEM
971 ret = npth_pselect (0, NULL, NULL, NULL, &timeout, npth_sigev_sigmask());
972 saved_errno = errno;
973
974 while (npth_sigev_get_pending(&signo))
975 handle_signal (signo);
976 #else
977 ret = npth_eselect (0, NULL, NULL, NULL, &timeout, NULL, NULL);
978 saved_errno = errno;
979 #endif
980
981 if (ret == -1 && saved_errno != EINTR)
982 {
983 log_error (_("npth_pselect failed: %s - waiting 1s\n"),
984 strerror (saved_errno));
985 npth_sleep (1);
986 continue;
987 }
988
989 if (ret <= 0)
990 {
991 /* Interrupt or timeout. Will be handled when calculating the
992 next timeout. */
993 continue;
994 }
995
996 /* Here one would add processing of file descriptors. */
997 }
998
999 log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
1000 return NULL;
1001 }
1002
1003
1004 /* Start the idle task. */
1005 static void
start_idle_task(void)1006 start_idle_task (void)
1007 {
1008 npth_attr_t tattr;
1009 npth_t thread;
1010 sigset_t sigs; /* The set of signals we want to catch. */
1011 int err;
1012
1013 #ifndef HAVE_W32_SYSTEM
1014 /* These signals should always go to the idle task, so they need to
1015 be blocked everywhere else. We assume start_idle_task is called
1016 from the main thread before any other threads are created. */
1017 sigemptyset (&sigs);
1018 sigaddset (&sigs, SIGHUP);
1019 sigaddset (&sigs, SIGUSR1);
1020 sigaddset (&sigs, SIGUSR2);
1021 sigaddset (&sigs, SIGINT);
1022 sigaddset (&sigs, SIGTERM);
1023 npth_sigmask (SIG_BLOCK, &sigs, NULL);
1024 #endif
1025
1026 npth_attr_init (&tattr);
1027 npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1028
1029 err = npth_create (&thread, &tattr, idle_task, NULL);
1030 if (err)
1031 {
1032 log_fatal ("error starting idle task: %s\n", strerror (err));
1033 return; /*NOTREACHED*/
1034 }
1035 npth_setname_np (thread, "idle-task");
1036 idle_task_thread = thread;
1037 npth_attr_destroy (&tattr);
1038 }
1039
1040
1041 /* Wait for the idle task to finish. */
1042 static void
join_idle_task(void)1043 join_idle_task (void)
1044 {
1045 int err;
1046
1047 /* FIXME: This assumes that a valid pthread_t is non-null. That is
1048 not guaranteed. */
1049 if (idle_task_thread)
1050 {
1051 err = npth_join (idle_task_thread, NULL);
1052 if (err)
1053 log_error ("waiting for idle task thread failed: %s\n",
1054 strerror (err));
1055 }
1056 }
1057