g13: Consider g13tab for a mount command.
authorWerner Koch <wk@gnupg.org>
Sat, 13 Aug 2016 17:27:28 +0000 (19:27 +0200)
committerWerner Koch <wk@gnupg.org>
Sat, 13 Aug 2016 17:40:32 +0000 (19:40 +0200)
* g13/sh-cmd.c (cmd_getkeyblob): New.
(register_commands): Register it.
* g13/call-syshelp.c (getkeyblob_data_cb): New.
(call_syshelp_get_keyblob): New.
* g13/mount.c: Include callsyshelp.h.
(g13_mount_container): Ask syshelp whether the filename is managed by
g13tab.  Call syshelp to get the encrypted keyblob in this case.

Signed-off-by: Werner Koch <wk@gnupg.org>
g13/call-syshelp.c
g13/call-syshelp.h
g13/mount.c
g13/sh-cmd.c

index d0f1b00..952d8de 100644 (file)
@@ -235,6 +235,52 @@ call_syshelp_find_device (ctrl_t ctrl, const char *name, char **r_blockdev)
 
 
 \f
+static gpg_error_t
+getkeyblob_data_cb (void *opaque, const void *data, size_t datalen)
+{
+  membuf_t *mb = opaque;
+
+  if (data)
+    put_membuf (mb, data, datalen);
+
+  return 0;
+}
+
+
+/* Send the GTEKEYBLOB command to the syshelper.  On success the
+ * encrypted keyblpob is stored at (R_ENCKEYBLOB,R_ENCKEYBLOBLEN).  */
+gpg_error_t
+call_syshelp_get_keyblob (ctrl_t ctrl,
+                          void **r_enckeyblob, size_t *r_enckeybloblen)
+{
+  gpg_error_t err;
+  assuan_context_t ctx;
+  membuf_t mb;
+
+  *r_enckeyblob = NULL;
+  *r_enckeybloblen = 0;
+  init_membuf (&mb, 512);
+
+  err = start_syshelp (ctrl, &ctx);
+  if (err)
+    goto leave;
+
+  err = assuan_transact (ctx, "GETKEYBLOB",
+                         getkeyblob_data_cb, &mb,
+                         NULL, NULL, NULL, NULL);
+  if (err)
+    goto leave;
+  *r_enckeyblob = get_membuf (&mb, r_enckeybloblen);
+  if (!*r_enckeyblob)
+    err = gpg_error_from_syserror ();
+
+ leave:
+  xfree (get_membuf (&mb, NULL));
+  return err;
+}
+
+
+\f
 /* Send the DEVICE command to the syshelper.  FNAME is the name of the
    device.  */
 gpg_error_t
index 14deb7d..aa4b692 100644 (file)
@@ -25,6 +25,9 @@
 void call_syshelp_release (ctrl_t ctrl);
 gpg_error_t call_syshelp_find_device (ctrl_t ctrl,
                                       const char *name, char **r_blockdev);
+gpg_error_t call_syshelp_get_keyblob (ctrl_t ctrl,
+                                      void **r_enckeyblob,
+                                      size_t *r_enckeybloblen);
 gpg_error_t call_syshelp_set_device (ctrl_t ctrl, const char *fname);
 gpg_error_t call_syshelp_run_create (ctrl_t ctrl, int conttype);
 gpg_error_t call_syshelp_run_mount (ctrl_t ctrl, int conttype,
index 951a859..d682585 100644 (file)
@@ -38,6 +38,7 @@
 #include "host2net.h"
 #include "server.h"  /*(g13_keyblob_decrypt)*/
 #include "../common/sysutils.h"
+#include "call-syshelp.h"
 
 
 /* Mount the container with name FILENAME at MOUNTPOINT.  */
@@ -46,7 +47,7 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
 {
   gpg_error_t err;
   dotlock_t lock;
-  int needs_syshelp;
+  int needs_syshelp = 0;
   void *enckeyblob = NULL;
   size_t enckeybloblen;
   void *keyblob = NULL;
@@ -57,16 +58,28 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
   int conttype;
   unsigned int rid;
   char *mountpoint_buffer = NULL;
+  char *blockdev_buffer = NULL;
 
   /* A quick check to see whether the container exists.  */
-  if (access (filename, R_OK))
+  if (access (filename, F_OK))
     return gpg_error_from_syserror ();
 
   /* Decide whether we need to use the g13-syshelp because we can't
      use lock files for them.  This is most likely the case for device
      files; thus we test for this.  FIXME: The correct solution would
      be to call g13-syshelp to match the file against the g13tab.  */
-  needs_syshelp = !strncmp (filename, "/dev/", 5);
+  err = call_syshelp_find_device (ctrl, filename, &blockdev_buffer);
+  if (!err)
+    {
+      needs_syshelp = 1;
+      filename = blockdev_buffer;
+    }
+  else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
+    {
+      log_error ("error finding device '%s': %s <%s>\n",
+                 filename, gpg_strerror (err), gpg_strsource (err));
+      return err;
+    }
 
   if (!mountpoint)
     {
@@ -105,20 +118,27 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
     }
 
   /* Check again that the file exists.  */
-  {
-    struct stat sb;
+  if (!needs_syshelp)
+    {
+      struct stat sb;
 
-    if (stat (filename, &sb))
-      {
-        err = gpg_error_from_syserror ();
-        goto leave;
-      }
-  }
+      if (stat (filename, &sb))
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+    }
 
   /* Read the encrypted keyblob.  */
-  /* Fixme: Should we move this to syshelp for dm-crypt or do we
-     assume that the encrypted device is world readable?  */
-  err = g13_keyblob_read (filename, &enckeyblob, &enckeybloblen);
+  if (needs_syshelp)
+    {
+      err = call_syshelp_set_device (ctrl, filename);
+      if (err)
+        goto leave;
+      err = call_syshelp_get_keyblob (ctrl, &enckeyblob, &enckeybloblen);
+    }
+  else
+    err = g13_keyblob_read (filename, &enckeyblob, &enckeybloblen);
   if (err)
     goto leave;
 
@@ -186,6 +206,7 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
   xfree (enckeyblob);
   dotlock_destroy (lock);
   xfree (mountpoint_buffer);
+  xfree (blockdev_buffer);
   return err;
 }
 
@@ -203,6 +224,7 @@ g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
 
   if (!filename && !mountpoint)
     return gpg_error (GPG_ERR_ENOENT);
+
   err = mountinfo_find_mount (filename, mountpoint, &rid);
   if (err)
     return err;
index e00bb77..10b1ba9 100644 (file)
@@ -383,6 +383,52 @@ cmd_create (assuan_context_t ctx, char *line)
 }
 
 
+static const char hlp_getkeyblob[] =
+  "GETKEYBLOB\n"
+  "\n"
+  "Return the encrypted keyblob of the current device.";
+static gpg_error_t
+cmd_getkeyblob (assuan_context_t ctx, char *line)
+{
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;
+  void *enckeyblob = NULL;
+  size_t enckeybloblen;
+
+  line = skip_options (line);
+
+  if (!ctrl->server_local->devicename
+      || !ctrl->server_local->devicefp
+      || !ctrl->devti)
+    {
+      err = set_error (GPG_ERR_ENOENT, "No device has been set");
+      goto leave;
+    }
+
+  err = sh_is_empty_partition (ctrl->server_local->devicename);
+  if (!err)
+    {
+      err = gpg_error (GPG_ERR_ENODEV);
+      assuan_set_error (ctx, err, "Partition is empty");
+      goto leave;
+    }
+  err = 0;
+
+  err = g13_keyblob_read (ctrl->server_local->devicename,
+                          &enckeyblob, &enckeybloblen);
+  if (err)
+    goto leave;
+
+  err = assuan_send_data (ctx, enckeyblob, enckeybloblen);
+  if (!err)
+    err = assuan_send_data (ctx, NULL, 0); /* Flush  */
+
+ leave:
+  xfree (enckeyblob);
+  return leave_cmd (ctx, err);
+}
+
+
 static const char hlp_mount[] =
   "MOUNT <type>\n"
   "\n"
@@ -667,6 +713,7 @@ register_commands (assuan_context_t ctx, int fail_all)
     { "FINDDEVICE",    cmd_finddevice, hlp_finddevice },
     { "DEVICE",        cmd_device, hlp_device },
     { "CREATE",        cmd_create, hlp_create },
+    { "GETKEYBLOB",    cmd_getkeyblob,  hlp_getkeyblob },
     { "MOUNT",         cmd_mount,  hlp_mount  },
     { "SUSPEND",       cmd_suspend,hlp_suspend},
     { "RESUME",        cmd_resume, hlp_resume },