From 700920640211168ae1c97d0adef74ba8615d90bb Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 13 Aug 2016 19:27:28 +0200 Subject: [PATCH] g13: Consider g13tab for a mount command. * 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 --- g13/call-syshelp.c | 46 ++++++++++++++++++++++++++++++++++++++++++ g13/call-syshelp.h | 3 +++ g13/mount.c | 50 +++++++++++++++++++++++++++++++++------------- g13/sh-cmd.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 14 deletions(-) diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c index d0f1b0070..952d8de77 100644 --- a/g13/call-syshelp.c +++ b/g13/call-syshelp.c @@ -234,6 +234,52 @@ call_syshelp_find_device (ctrl_t ctrl, const char *name, char **r_blockdev) } + +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; +} + + /* Send the DEVICE command to the syshelper. FNAME is the name of the device. */ diff --git a/g13/call-syshelp.h b/g13/call-syshelp.h index 14deb7d18..aa4b692f4 100644 --- a/g13/call-syshelp.h +++ b/g13/call-syshelp.h @@ -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, diff --git a/g13/mount.c b/g13/mount.c index 951a85917..d6825859d 100644 --- a/g13/mount.c +++ b/g13/mount.c @@ -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; diff --git a/g13/sh-cmd.c b/g13/sh-cmd.c index e00bb774c..10b1ba93b 100644 --- a/g13/sh-cmd.c +++ b/g13/sh-cmd.c @@ -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 \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 },