diff options
author | Werner Koch <wk@gnupg.org> | 2016-02-13 17:01:45 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2016-02-13 17:06:54 +0100 |
commit | b0e6ab1109d05fc664f46e17d721fe9b01d38115 (patch) | |
tree | 70cf20d908523ef099962ee90730fd053082b5cf /g13/call-syshelp.c | |
parent | g13: Improve dump_keyblob. (diff) | |
download | gnupg2-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.c | 319 |
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; } |