scd: Fix for large ECC keys.
[gnupg.git] / g13 / mount.c
index 272cd77..dc415b1 100644 (file)
@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -27,7 +27,7 @@
 #include <assert.h>
 
 #include "g13.h"
-#include "i18n.h"
+#include "../common/i18n.h"
 #include "mount.h"
 
 #include "keyblob.h"
 #include "g13tuple.h"
 #include "mountinfo.h"
 #include "runner.h"
-#include "host2net.h"
+#include "../common/host2net.h"
+#include "server.h"  /*(g13_keyblob_decrypt)*/
 #include "../common/sysutils.h"
+#include "call-syshelp.h"
 
 
 /* Mount the container with name FILENAME at MOUNTPOINT.  */
@@ -45,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;
@@ -56,16 +58,27 @@ 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))
-    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);
+  /* Decide whether we need to use the g13-syshelp.  */
+  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;
+    }
+  else
+    {
+      /* A quick check to see whether we can the container exists.  */
+      if (access (filename, R_OK))
+        return gpg_error_from_syserror ();
+    }
 
   if (!mountpoint)
     {
@@ -104,20 +117,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;
 
@@ -185,6 +205,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;
 }
 
@@ -195,26 +216,50 @@ gpg_error_t
 g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
 {
   gpg_error_t err;
-  unsigned int rid;
-  runner_t runner;
-
-  (void)ctrl;
+  char *blockdev;
 
   if (!filename && !mountpoint)
     return gpg_error (GPG_ERR_ENOENT);
-  err = mountinfo_find_mount (filename, mountpoint, &rid);
-  if (err)
-    return err;
 
-  runner = runner_find_by_rid (rid);
-  if (!runner)
+  /* Decide whether we need to use the g13-syshelp.  */
+  err = call_syshelp_find_device (ctrl, filename, &blockdev);
+  if (!err)
     {
-      log_error ("runner %u not found\n", rid);
-      return gpg_error (GPG_ERR_NOT_FOUND);
+      /* Need to employ the syshelper to umount the file system.  */
+      /* FIXME: We should get the CONTTYPE from the blockdev.  */
+      err = be_umount_container (ctrl, CONTTYPE_DM_CRYPT, blockdev);
+      if (!err)
+        {
+          /* if (conttype == CONTTYPE_DM_CRYPT) */
+          g13_request_shutdown ();
+        }
     }
+  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));
+    }
+  else
+    {
+      /* Not in g13tab - kill the runner process for this mount.  */
+      unsigned int rid;
+      runner_t runner;
 
-  runner_cancel (runner);
-  runner_release (runner);
+      err = mountinfo_find_mount (filename, mountpoint, &rid);
+      if (err)
+        return err;
 
-  return 0;
+      runner = runner_find_by_rid (rid);
+      if (!runner)
+        {
+          log_error ("runner %u not found\n", rid);
+          return gpg_error (GPG_ERR_NOT_FOUND);
+        }
+
+      runner_cancel (runner);
+      runner_release (runner);
+    }
+
+  xfree (blockdev);
+  return err;
 }