g13: Implement --umount for dm-crypt.
[gnupg.git] / g13 / g13.c
index a6fddd0..7744855 100644 (file)
--- a/g13/g13.c
+++ b/g13/g13.c
 #include "runner.h"
 #include "create.h"
 #include "mount.h"
+#include "suspend.h"
 #include "mountinfo.h"
+#include "backend.h"
+#include "call-syshelp.h"
 
 
 enum cmd_and_opt_values {
@@ -56,7 +59,10 @@ enum cmd_and_opt_values {
   aCreate,
   aMount,
   aUmount,
+  aSuspend,
+  aResume,
   aServer,
+  aFindDevice,
 
   oOptions,
   oDebug,
@@ -73,6 +79,7 @@ enum cmd_and_opt_values {
 
   oAgentProgram,
   oGpgProgram,
+  oType,
 
   oDisplay,
   oTTYname,
@@ -106,7 +113,10 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aCreate, "create", N_("Create a new file system container")),
   ARGPARSE_c (aMount,  "mount",  N_("Mount a file system container") ),
   ARGPARSE_c (aUmount, "umount", N_("Unmount a file system container") ),
+  ARGPARSE_c (aSuspend, "suspend", N_("Suspend a file system container") ),
+  ARGPARSE_c (aResume,  "resume",  N_("Resume a file system container") ),
   ARGPARSE_c (aServer, "server", N_("Run in server mode")),
+  ARGPARSE_c (aFindDevice, "find-device", "@"),
 
   ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
   ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
@@ -114,6 +124,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_group (301, N_("@\nOptions:\n ")),
 
   ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
+  ARGPARSE_s_s (oType, "type", N_("|NAME|use container format NAME")),
 
   ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
   ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
@@ -186,10 +197,6 @@ static struct debug_flags_s debug_flags [] =
 /* The timer tick interval used by the idle task.  */
 #define TIMERTICK_INTERVAL_SEC     (1)
 
-
-/* Global variable to keep an error count. */
-int g13_errors_seen = 0;
-
 /* It is possible that we are currently running under setuid permissions.  */
 static int maybe_setuid = 1;
 
@@ -204,11 +211,14 @@ static int shutdown_pending;
 static npth_t idle_task_thread;
 
 
+/* The container type as specified on the command line.  */
+static int cmdline_conttype;
+
+
 \f
 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
                      enum cmd_and_opt_values new_cmd );
 
-static void emergency_cleanup (void);
 static void start_idle_task (void);
 static void join_idle_task (void);
 
@@ -239,7 +249,7 @@ my_strusage( int level )
       break;
 
     case 31: p = "\nHome: "; break;
-    case 32: p = opt.homedir; break;
+    case 32: p = gnupg_homedir (); break;
 
     default: p = NULL; break;
     }
@@ -356,7 +366,7 @@ main ( int argc, char **argv)
   set_strusage (my_strusage);
   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
 
-  log_set_prefix (G13_NAME, 1);
+  log_set_prefix (G13_NAME, GPGRT_LOG_WITH_PREFIX);
 
   /* Make sure that our subsystems are ready.  */
   i18n_init ();
@@ -364,17 +374,12 @@ main ( int argc, char **argv)
 
   npth_init ();
 
-  /* Check that the Libgcrypt is suitable.  */
-  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
-    log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
-               NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
-
   /* Take extra care of the random pool.  */
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
   may_coredump = disable_core_dumps ();
 
-  gnupg_init_signals (0, emergency_cleanup);
+  g13_init_signals ();
 
   dotlock_create (NULL, 0); /* Register locking cleanup.  */
 
@@ -383,8 +388,6 @@ main ( int argc, char **argv)
     log_fatal ("error allocating session environment block: %s\n",
                strerror (errno));
 
-  opt.homedir = default_homedir ();
-
   /* First check whether we have a config file on the commandline.  */
   orig_argc = argc;
   orig_argv = argv;
@@ -404,7 +407,7 @@ main ( int argc, char **argv)
       else if (pargs.r_opt == oNoOptions)
         default_config = 0; /* --no-options */
       else if (pargs.r_opt == oHomedir)
-        opt.homedir = pargs.r.ret_str;
+        gnupg_set_homedir (pargs.r.ret_str);
     }
 
   /* Initialize the secure memory. */
@@ -438,7 +441,7 @@ main ( int argc, char **argv)
 
   /* Set the default option file */
   if (default_config )
-    configname = make_filename (opt.homedir, G13_NAME".conf", NULL);
+    configname = make_filename (gnupg_homedir (), G13_NAME".conf", NULL);
 
   argc        = orig_argc;
   argv        = orig_argv;
@@ -456,7 +459,7 @@ main ( int argc, char **argv)
           if (default_config)
             {
               if (parse_debug)
-                log_info (_("NOTE: no default option file '%s'\n"), configname);
+                log_info (_("Note: no default option file '%s'\n"), configname);
             }
           else
             {
@@ -487,8 +490,10 @@ main ( int argc, char **argv)
         case aServer:
         case aMount:
         case aUmount:
-          /* nokeysetup = 1; */
+        case aSuspend:
+        case aResume:
         case aCreate:
+        case aFindDevice:
           set_cmd (&cmd, pargs.r_opt);
           break;
 
@@ -543,7 +548,7 @@ main ( int argc, char **argv)
            }
           break;
 
-        case oHomedir: opt.homedir = pargs.r.ret_str; break;
+        case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
 
         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
         case oGpgProgram: opt.gpg_program = pargs.r.ret_str;  break;
@@ -571,6 +576,19 @@ main ( int argc, char **argv)
           add_to_strlist (&recipients, pargs.r.ret_str);
           break;
 
+        case oType:
+          if (!strcmp (pargs.r.ret_str, "help"))
+            {
+              be_parse_conttype_name (NULL);
+              g13_exit (0);
+            }
+          cmdline_conttype = be_parse_conttype_name (pargs.r.ret_str);
+          if (!cmdline_conttype)
+            {
+              pargs.r_opt = ARGPARSE_INVALID_ARG;
+              pargs.err = ARGPARSE_PRINT_ERROR;
+            }
+          break;
 
         default:
           pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
@@ -578,6 +596,16 @@ main ( int argc, char **argv)
        }
     }
 
+  /* XXX Construct GPG arguments.  */
+  {
+    strlist_t last;
+    last = append_to_strlist (&opt.gpg_arguments, "-z");
+    last = append_to_strlist (&last, "0");
+    last = append_to_strlist (&last, "--trust-model");
+    last = append_to_strlist (&last, "always");
+    (void) last;
+  }
+
   if (configfp)
     {
       fclose (configfp);
@@ -591,7 +619,8 @@ main ( int argc, char **argv)
   configname = NULL;
 
   if (!opt.config_filename)
-    opt.config_filename = make_filename (opt.homedir, G13_NAME".conf", NULL);
+    opt.config_filename = make_filename (gnupg_homedir (),
+                                         G13_NAME".conf", NULL);
 
   if (log_get_errorcount(0))
     g13_exit(2);
@@ -599,6 +628,8 @@ main ( int argc, char **argv)
   /* Now that we have the options parsed we need to update the default
      control structure.  */
   g13_init_default_ctrl (&ctrl);
+  ctrl.recipients = recipients;
+  recipients = NULL;
 
   if (nogreeting)
     greeting = 0;
@@ -620,14 +651,14 @@ main ( int argc, char **argv)
 
       for (i=0; i < argc; i++)
         if (argv[i][0] == '-' && argv[i][1] == '-')
-          log_info (_("NOTE: '%s' is not considered an option\n"), argv[i]);
+          log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
     }
 
 
   if (logfile)
     {
       log_set_file (logfile);
-      log_set_prefix (NULL, 1|2|4);
+      log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
     }
 
   if (gnupg_faked_time_p ())
@@ -646,13 +677,8 @@ main ( int argc, char **argv)
   /* Setup the debug flags for all subsystems.  */
   set_debug ();
 
-  /* Install a regular exit handler to make real sure that the secure
-     memory gets wiped out.  */
-  if (atexit (emergency_cleanup))
-    {
-      log_error ("atexit failed\n");
-      g13_exit (2);
-    }
+  /* Install emergency cleanup handler.  */
+  g13_install_emergency_cleanup ();
 
   /* Terminate if we found any error until now.  */
   if (log_get_errorcount(0))
@@ -661,7 +687,7 @@ main ( int argc, char **argv)
   /* Set the standard GnuPG random seed file.  */
   if (use_random_seed)
     {
-      char *p = make_filename (opt.homedir, "random_seed", NULL);
+      char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
       xfree(p);
     }
@@ -677,7 +703,7 @@ main ( int argc, char **argv)
       strlist_t sl;
       int failed = 0;
 
-      for (sl = recipients; sl; sl = sl->next)
+      for (sl = ctrl->recipients; sl; sl = sl->next)
         if (check_encryption_key ())
           failed = 1;
       if (failed)
@@ -717,7 +743,23 @@ main ( int argc, char **argv)
           log_error ("server exited with error: %s <%s>\n",
                      gpg_strerror (err), gpg_strsource (err));
         else
-          shutdown_pending++;
+          g13_request_shutdown ();
+      }
+      break;
+
+    case aFindDevice:
+      {
+        char *blockdev;
+
+        if (argc != 1)
+          wrong_args ("--find-device name");
+
+        err = call_syshelp_find_device (&ctrl, argv[0], &blockdev);
+        if (err)
+          log_error ("error finding device '%s': %s <%s>\n",
+                     argv[0], gpg_strerror (err), gpg_strsource (err));
+        else
+          puts (blockdev);
       }
       break;
 
@@ -726,12 +768,12 @@ main ( int argc, char **argv)
         if (argc != 1)
           wrong_args ("--create filename");
         start_idle_task ();
-        err = g13_create_container (&ctrl, argv[0], recipients);
+        err = g13_create_container (&ctrl, argv[0]);
         if (err)
           log_error ("error creating a new container: %s <%s>\n",
                      gpg_strerror (err), gpg_strsource (err));
         else
-          shutdown_pending++;
+          g13_request_shutdown ();
       }
       break;
 
@@ -747,11 +789,48 @@ main ( int argc, char **argv)
       }
       break;
 
+    case aUmount: /* Unmount a mounted container.  */
+      {
+        if (argc != 1)
+          wrong_args ("--umount filename");
+        err = g13_umount_container (&ctrl, argv[0], NULL);
+        if (err)
+          log_error ("error unmounting container '%s': %s <%s>\n",
+                     *argv, gpg_strerror (err), gpg_strsource (err));
+      }
+      break;
+
+    case aSuspend: /* Suspend a container. */
+      {
+        /* Fixme: Should we add a suspend all container option?  */
+        if (argc != 1)
+          wrong_args ("--suspend filename");
+        err = g13_suspend_container (&ctrl, argv[0]);
+        if (err)
+          log_error ("error suspending container '%s': %s <%s>\n",
+                     *argv, gpg_strerror (err), gpg_strsource (err));
+      }
+      break;
+
+    case aResume: /* Resume a suspended container. */
+      {
+        /* Fixme: Should we add a resume all container option?  */
+        if (argc != 1)
+          wrong_args ("--resume filename");
+        err = g13_resume_container (&ctrl, argv[0]);
+        if (err)
+          log_error ("error resuming container '%s': %s <%s>\n",
+                     *argv, gpg_strerror (err), gpg_strsource (err));
+      }
+      break;
+
     default:
       log_error (_("invalid command (there is no implicit command)\n"));
       break;
     }
 
+  g13_deinit_default_ctrl (&ctrl);
+
   if (!err)
     join_idle_task ();
 
@@ -761,36 +840,29 @@ main ( int argc, char **argv)
 }
 
 
-/* Note: This function is used by signal handlers!. */
-static void
-emergency_cleanup (void)
+/* Store defaults into the per-connection CTRL object.  */
+void
+g13_init_default_ctrl (ctrl_t ctrl)
 {
-  gcry_control (GCRYCTL_TERM_SECMEM );
+  ctrl->conttype = cmdline_conttype? cmdline_conttype : CONTTYPE_ENCFS;
 }
 
 
+/* Release remaining resources allocated in the CTRL object.  */
 void
-g13_exit (int rc)
+g13_deinit_default_ctrl (ctrl_t ctrl)
 {
-  gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
-  if (opt.debug & DBG_MEMSTAT_VALUE)
-    {
-      gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
-      gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
-    }
-  if (opt.debug)
-    gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
-  emergency_cleanup ();
-  rc = rc? rc : log_get_errorcount(0)? 2 : g13_errors_seen? 1 : 0;
-  exit (rc);
+  call_syshelp_release (ctrl);
+  FREE_STRLIST (ctrl->recipients);
 }
 
 
-/* Store defaults into the per-connection CTRL object.  */
+/* Request a shutdown.  This can be used when the process should
+ * finish instead of running the idle task.  */
 void
-g13_init_default_ctrl (struct server_control_s *ctrl)
+g13_request_shutdown (void)
 {
-  ctrl->conttype = CONTTYPE_ENCFS;
+  shutdown_pending++;
 }
 
 
@@ -926,9 +998,11 @@ idle_task (void *dummy_arg)
        }
 
       if (ret <= 0)
-       /* Interrupt or timeout.  Will be handled when calculating the
-          next timeout.  */
-       continue;
+        {
+          /* Interrupt or timeout.  Will be handled when calculating the
+             next timeout.  */
+          continue;
+        }
 
       /* Here one would add processing of file descriptors.  */
     }