From b57f55321295846d47144bd6b39fbbcac0127421 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 13 Aug 2016 12:49:54 +0200 Subject: [PATCH] g13: New command --find-device. * common/status.h (STATUS_BLOCKDEV: New. * g13/call-syshelp.c: Include "call-syshelp.h". (finddevice_status_cb, call_syshelp_find_device): New. * g13/g13.c (aFindDevice): New. (opts): Add "--find-device". (main): Implement --find-device. * g13/sh-cmd.c (cmd_finddevice): New. (register_commands): Register new command. -- This might be useful for scripting. Signed-off-by: Werner Koch --- common/status.h | 1 + g13/call-syshelp.c | 63 +++++++++++++++++++++++++++++++++++++ g13/call-syshelp.h | 2 ++ g13/g13.c | 19 ++++++++++++ g13/sh-cmd.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+) diff --git a/common/status.h b/common/status.h index f9771c208..079a04ac6 100644 --- a/common/status.h +++ b/common/status.h @@ -142,6 +142,7 @@ enum STATUS_TRUNCATED, STATUS_MOUNTPOINT, + STATUS_BLOCKDEV, STATUS_PINENTRY_LAUNCHED, diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c index bc93d2014..d0f1b0070 100644 --- a/g13/call-syshelp.c +++ b/g13/call-syshelp.c @@ -33,6 +33,7 @@ #include "keyblob.h" #include "membuf.h" #include "create.h" +#include "call-syshelp.h" /* Local data for this module. A pointer to this is stored in the @@ -172,6 +173,68 @@ call_syshelp_release (ctrl_t ctrl) } + +/* Staus callback for call_syshelp_find_device. */ +static gpg_error_t +finddevice_status_cb (void *opaque, const char *line) +{ + char **r_blockdev = opaque; + char *p; + + if ((p = has_leading_keyword (line, "BLOCKDEV")) && *p && !*r_blockdev) + { + *r_blockdev = xtrystrdup (p); + if (!*r_blockdev) + return gpg_error_from_syserror (); + } + + return 0; +} + + +/* Send the FINDDEVICE command to the syshelper. On success the name + * of the block device is stored at R_BLOCKDEV. */ +gpg_error_t +call_syshelp_find_device (ctrl_t ctrl, const char *name, char **r_blockdev) +{ + gpg_error_t err; + assuan_context_t ctx; + char *line = NULL; + char *blockdev = NULL; /* The result. */ + + *r_blockdev = NULL; + + err = start_syshelp (ctrl, &ctx); + if (err) + goto leave; + + line = xtryasprintf ("FINDDEVICE %s", name); + if (!line) + { + err = gpg_error_from_syserror (); + goto leave; + } + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, + finddevice_status_cb, &blockdev); + if (err) + goto leave; + if (!blockdev) + { + log_error ("status line for successful FINDDEVICE missing\n"); + err = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } + *r_blockdev = blockdev; + blockdev = NULL; + + leave: + xfree (blockdev); + xfree (line); + return err; +} + + + /* Send the DEVICE command to the syshelper. FNAME is the name of the device. */ gpg_error_t diff --git a/g13/call-syshelp.h b/g13/call-syshelp.h index c2578f241..14deb7d18 100644 --- a/g13/call-syshelp.h +++ b/g13/call-syshelp.h @@ -23,6 +23,8 @@ #include "g13tuple.h" 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_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/g13.c b/g13/g13.c index 7c6e2e367..799fd6651 100644 --- a/g13/g13.c +++ b/g13/g13.c @@ -62,6 +62,7 @@ enum cmd_and_opt_values { aSuspend, aResume, aServer, + aFindDevice, oOptions, oDebug, @@ -115,6 +116,7 @@ static ARGPARSE_OPTS opts[] = { 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", "@"), @@ -491,6 +493,7 @@ main ( int argc, char **argv) case aSuspend: case aResume: case aCreate: + case aFindDevice: set_cmd (&cmd, pargs.r_opt); break; @@ -744,6 +747,22 @@ main ( int argc, char **argv) } 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; + case aCreate: /* Create a new container. */ { if (argc != 1) diff --git a/g13/sh-cmd.c b/g13/sh-cmd.c index fe596f460..e00bb774c 100644 --- a/g13/sh-cmd.c +++ b/g13/sh-cmd.c @@ -157,6 +157,82 @@ reset_notify (assuan_context_t ctx, char *line) } +static const char hlp_finddevice[] = + "FINDDEVICE \n" + "\n" + "Find the device matching NAME. NAME be any identifier from\n" + "g13tab permissable for the user. The corresponding block\n" + "device is retruned using a status line."; +static gpg_error_t +cmd_finddevice (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err = 0; + tab_item_t ti; + const char *s; + const char *name; + + name = skip_options (line); + + /* Are we allowed to use the given device? We check several names: + * 1. The full block device + * 2. The label + * 3. The final part of the block device if NAME does not have a slash. + * 4. The mountpoint + */ + for (ti=ctrl->client.tab; ti; ti = ti->next) + if (!strcmp (name, ti->blockdev)) + break; + if (!ti) + { + for (ti=ctrl->client.tab; ti; ti = ti->next) + if (ti->label && !strcmp (name, ti->label)) + break; + } + if (!ti && !strchr (name, '/')) + { + for (ti=ctrl->client.tab; ti; ti = ti->next) + { + s = strrchr (ti->blockdev, '/'); + if (s && s[1] && !strcmp (name, s+1)) + break; + } + } + if (!ti) + { + for (ti=ctrl->client.tab; ti; ti = ti->next) + if (ti->mountpoint && !strcmp (name, ti->mountpoint)) + break; + } + + if (!ti) + { + err = set_error (GPG_ERR_NOT_FOUND, "device not configured for user"); + goto leave; + } + + /* Check whether we have permissions to open the device. */ + { + estream_t fp = es_fopen (ti->blockdev, "rb"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error ("error opening '%s': %s\n", + ti->blockdev, gpg_strerror (err)); + goto leave; + } + es_fclose (fp); + } + + err = g13_status (ctrl, STATUS_BLOCKDEV, ti->blockdev, NULL); + if (err) + return err; + + leave: + return leave_cmd (ctx, err); +} + + static const char hlp_device[] = "DEVICE \n" "\n" @@ -588,6 +664,7 @@ register_commands (assuan_context_t ctx, int fail_all) assuan_handler_t handler; const char * const help; } table[] = { + { "FINDDEVICE", cmd_finddevice, hlp_finddevice }, { "DEVICE", cmd_device, hlp_device }, { "CREATE", cmd_create, hlp_create }, { "MOUNT", cmd_mount, hlp_mount },