summaryrefslogtreecommitdiffstats
path: root/g13/call-syshelp.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2016-02-13 17:01:45 +0100
committerWerner Koch <wk@gnupg.org>2016-02-13 17:06:54 +0100
commitb0e6ab1109d05fc664f46e17d721fe9b01d38115 (patch)
tree70cf20d908523ef099962ee90730fd053082b5cf /g13/call-syshelp.c
parentg13: Improve dump_keyblob. (diff)
downloadgnupg2-b0e6ab1109d05fc664f46e17d721fe9b01d38115.tar.xz
gnupg2-b0e6ab1109d05fc664f46e17d721fe9b01d38115.zip
g13: Second chunk of code to support dm-crypt.
* g13/be-dmcrypt.c, g13/be-dmcrypt.h: New. * g13/Makefile.am (g13_SOURCES): Add them. * g13/backend.c: Include be-dmcrypt.h and call-syshelp.h. (no_such_backend): Rename to _no_such_backend and provide replacement macro. (be_is_supported_conttype): Support DM-Crypt. (be_take_lock_for_create): Call set_segvice for DM-Crypt. (be_create_new_keys): Make it a dummy for DM-Crypt. (be_create_container): Call be_dmcrypt_create_container. (be_mount_container): call be_dmcrypt_mount_container. * g13/g13-syshelp.c (main): Enable verbose mode. * g13/g13tuple.c (get_tupledesc_data): New. * g13/g13tuple.h (unref_tupledesc): New. * g13/g13.h (server_control_): Add field "recipients". * g13/g13.c (main): Fix setting of recipients via cmdline. (g13_deinit_default_ctrl): Release recipients list. (g13_request_shutdown): New. Replace all direct update of shutdown_pending by calls this function. * g13/server.c (server_local_s): Remove field recipients which is now part of CTRL. (reset_notify, cmd_recipient, cmd_create): Adjust for this change. * g13/create.c (encrypt_keyblob): Rename to g13_encrypt_keyblob. (g13_create_container): Support DM-Crypt. * g13/mount.c (parse_header): Allow for meta data copies. (g13_mount_container): Support DM-Crypt. * g13/sh-cmd.c (cmd_create): Make it work. (cmd_mount): New. * g13/sh-dmcrypt.c (sh_dmcrypt_create_container): Make it work. (sh_dmcrypt_mount_container): New. -- With this patch we can now create an encrypted partition and partly mount it (i.e. setup keys and create the mapped device). We do not yet create a file system or mount that file system Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'g13/call-syshelp.c')
-rw-r--r--g13/call-syshelp.c319
1 files changed, 297 insertions, 22 deletions
diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c
index 0e227ab16..0e69e9c11 100644
--- a/g13/call-syshelp.c
+++ b/g13/call-syshelp.c
@@ -44,21 +44,56 @@ struct call_syshelp_s
};
-/* Fork off the syshelp tool if this has not already been done. */
+/* Parameter used with the CREATE command. */
+struct create_parm_s
+{
+ assuan_context_t ctx;
+ ctrl_t ctrl;
+ membuf_t plaintext;
+ unsigned int expect_plaintext:1;
+ unsigned int got_plaintext:1;
+};
+
+
+/* Parameter used with the MOUNT command. */
+struct mount_parm_s
+{
+ assuan_context_t ctx;
+ ctrl_t ctrl;
+ const void *keyblob;
+ size_t keybloblen;
+};
+
+
+
+
+
+/* Fork off the syshelp tool if this has not already been done. On
+ success stores the current Assuan context for the syshelp tool at
+ R_CTX. */
static gpg_error_t
-start_syshelp (ctrl_t ctrl)
+start_syshelp (ctrl_t ctrl, assuan_context_t *r_ctx)
{
gpg_error_t err;
assuan_context_t ctx;
assuan_fd_t no_close_list[3];
int i;
- if (ctrl->syshelp_local->assctx)
+ *r_ctx = NULL;
+
+ if (ctrl->syshelp_local && (*r_ctx = ctrl->syshelp_local->assctx))
return 0; /* Already set. */
if (opt.verbose)
log_info ("starting a new syshelp\n");
+ if (!ctrl->syshelp_local)
+ {
+ ctrl->syshelp_local = xtrycalloc (1, sizeof *ctrl->syshelp_local);
+ if (!ctrl->syshelp_local)
+ return gpg_error_from_syserror ();
+ }
+
if (es_fflush (NULL))
{
err = gpg_error_from_syserror ();
@@ -79,38 +114,40 @@ start_syshelp (ctrl_t ctrl)
return err;
}
- /* Call userv to start g13-syshelp. This userv script needs tpo be
- installed under the name "gnupg-g13-syshelp":
-
- if ( glob service-user root
- )
- reset
- suppress-args
- execute /home/wk/b/gnupg/g13/g13-syshelp -v
- else
- error Nothing to do for this service-user
- fi
- quit
- */
+ /* Call userv to start g13-syshelp. This userv script needs to be
+ * installed under the name "gnupg-g13-syshelp":
+ *
+ * if ( glob service-user root
+ * )
+ * reset
+ * suppress-args
+ * execute /home/wk/b/gnupg/g13/g13-syshelp -v
+ * else
+ * error Nothing to do for this service-user
+ * fi
+ * quit
+ */
{
- const char *argv[3];
+ const char *argv[4];
argv[0] = "userv";
- argv[1] = "gnupg-g13-syshelp";
- argv[2] = NULL;
+ argv[1] = "root";
+ argv[2] = "gnupg-g13-syshelp";
+ argv[3] = NULL;
err = assuan_pipe_connect (ctx, "/usr/bin/userv", argv,
no_close_list, NULL, NULL, 0);
}
if (err)
{
- log_error ("can't connect to '%s' - : %s\n",
- "g13-syshelp", gpg_strerror (err));
+ log_error ("can't connect to '%s': %s %s\n",
+ "g13-syshelp", gpg_strerror (err), gpg_strsource (err));
log_info ("(is userv and its gnupg-g13-syshelp script installed?)\n");
assuan_release (ctx);
return err;
}
- ctrl->syshelp_local->assctx = ctx;
+
+ *r_ctx = ctrl->syshelp_local->assctx = ctx;
if (DBG_IPC)
log_debug ("connection to g13-syshelp established\n");
@@ -129,5 +166,243 @@ call_syshelp_release (ctrl_t ctrl)
{
assuan_release (ctrl->syshelp_local->assctx);
ctrl->syshelp_local->assctx = NULL;
+ xfree (ctrl->syshelp_local);
+ ctrl->syshelp_local = NULL;
+ }
+}
+
+
+/* Send the DEVICE command to the syshelper. FNAME is the name of the
+ device. */
+gpg_error_t
+call_syshelp_set_device (ctrl_t ctrl, const char *fname)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ char *line = NULL;
+
+ err = start_syshelp (ctrl, &ctx);
+ if (err)
+ goto leave;
+
+ line = xtryasprintf ("DEVICE %s", fname);
+ if (!line)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ leave:
+ xfree (line);
+ return err;
+}
+
+
+
+static gpg_error_t
+create_status_cb (void *opaque, const char *line)
+{
+ struct create_parm_s *parm = opaque;
+
+ if (has_leading_keyword (line, "PLAINTEXT_FOLLOWS"))
+ parm->expect_plaintext = 1;
+
+ return 0;
+}
+
+
+static gpg_error_t
+create_data_cb (void *opaque, const void *data, size_t datalen)
+{
+ struct create_parm_s *parm = opaque;
+ gpg_error_t err = 0;
+
+ if (!parm->expect_plaintext)
+ {
+ log_error ("status line for data missing\n");
+ err = gpg_error (GPG_ERR_UNEXPECTED);
+ }
+ else if (data)
+ {
+ put_membuf (&parm->plaintext, data, datalen);
+ }
+ else
+ {
+ parm->expect_plaintext = 0;
+ parm->got_plaintext = 1;
+ }
+
+ return err;
+}
+
+
+static gpg_error_t
+create_inq_cb (void *opaque, const char *line)
+{
+ struct create_parm_s *parm = opaque;
+ gpg_error_t err;
+
+ if (has_leading_keyword (line, "ENCKEYBLOB"))
+ {
+ void *plaintext;
+ size_t plaintextlen;
+
+ if (!parm->got_plaintext)
+ err = gpg_error (GPG_ERR_UNEXPECTED);
+ else if (!(plaintext = get_membuf (&parm->plaintext, &plaintextlen)))
+ err = gpg_error_from_syserror ();
+ else
+ {
+ void *ciphertext;
+ size_t ciphertextlen;
+
+ log_printhex ("plain", plaintext, plaintextlen);
+ err = g13_encrypt_keyblob (parm->ctrl,
+ plaintext, plaintextlen,
+ &ciphertext, &ciphertextlen);
+ wipememory (plaintext, plaintextlen);
+ xfree (plaintext);
+ if (err)
+ log_error ("error encrypting keyblob: %s\n", gpg_strerror (err));
+ else
+ {
+ err = assuan_send_data (parm->ctx, ciphertext, ciphertextlen);
+ xfree (ciphertext);
+ if (err)
+ log_error ("sending ciphertext to g13-syshelp failed: %s\n",
+ gpg_strerror (err));
+ }
+ }
}
+ else
+ err = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
+
+ return err;
+}
+
+
+/* Run the CREATE command on the current device. CONTTYPES gives the
+ requested content type for the new container. */
+gpg_error_t
+call_syshelp_run_create (ctrl_t ctrl, int conttype)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct create_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
+
+ err = start_syshelp (ctrl, &ctx);
+ if (err)
+ goto leave;
+
+ /* tty_get ("waiting for debugger"); */
+ /* tty_kill_prompt (); */
+
+ parm.ctx = ctx;
+ parm.ctrl = ctrl;
+ init_membuf (&parm.plaintext, 512);
+ if (conttype == CONTTYPE_DM_CRYPT)
+ {
+ err = assuan_transact (ctx, "CREATE dm-crypt",
+ create_data_cb, &parm,
+ create_inq_cb, &parm,
+ create_status_cb, &parm);
+ }
+ else
+ {
+ log_error ("invalid backend type %d given\n", conttype);
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+
+ leave:
+ xfree (get_membuf (&parm.plaintext, NULL));
+ return err;
+}
+
+
+
+static gpg_error_t
+mount_status_cb (void *opaque, const char *line)
+{
+ struct mount_parm_s *parm = opaque;
+
+ /* Nothing right now. */
+ (void)parm;
+ (void)line;
+
+ return 0;
+}
+
+
+static gpg_error_t
+mount_inq_cb (void *opaque, const char *line)
+{
+ struct mount_parm_s *parm = opaque;
+ gpg_error_t err;
+
+ if (has_leading_keyword (line, "KEYBLOB"))
+ {
+ int setconfidential = !assuan_get_flag (parm->ctx, ASSUAN_CONFIDENTIAL);
+
+ if (setconfidential)
+ assuan_begin_confidential (parm->ctx);
+ err = assuan_send_data (parm->ctx, parm->keyblob, parm->keybloblen);
+ if (setconfidential)
+ assuan_end_confidential (parm->ctx);
+ if (err)
+ log_error ("sending keyblob to g13-syshelp failed: %s\n",
+ gpg_strerror (err));
+ }
+ else
+ err = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
+
+ return err;
+}
+
+
+/* Run the MOUNT command on the current device. CONTTYPES gives the
+ requested content type for the new container. MOUNTPOINT the
+ desired mount point or NULL for default. */
+gpg_error_t
+call_syshelp_run_mount (ctrl_t ctrl, int conttype, const char *mountpoint,
+ tupledesc_t tuples)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct mount_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
+
+ err = start_syshelp (ctrl, &ctx);
+ if (err)
+ goto leave;
+
+ /* tty_get ("waiting for debugger"); */
+ /* tty_kill_prompt (); */
+
+ parm.ctx = ctx;
+ parm.ctrl = ctrl;
+ if (conttype == CONTTYPE_DM_CRYPT)
+ {
+ ref_tupledesc (tuples);
+ parm.keyblob = get_tupledesc_data (tuples, &parm.keybloblen);
+ err = assuan_transact (ctx, "MOUNT dm-crypt",
+ NULL, NULL,
+ mount_inq_cb, &parm,
+ mount_status_cb, &parm);
+ unref_tupledesc (tuples);
+ }
+ else
+ {
+ (void)mountpoint; /* Not used. */
+ log_error ("invalid backend type %d given\n", conttype);
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+
+ leave:
+ return err;
}