# other guestfish files.
SHARED_SOURCE_FILES = \
inspect.c \
+ keys.c \
options.h \
options.c \
virt.c
#include <sys/wait.h>
#include <locale.h>
#include <langinfo.h>
-#include <termios.h>
#ifdef HAVE_LIBREADLINE
#include <readline/readline.h>
}
return ret;
}
-
-/* Read a passphrase ('Key') from /dev/tty with echo off.
- * The caller (cmds.c) will call free on the string afterwards.
- * Based on the code in cryptsetup file lib/utils.c.
- */
-char *
-read_key (const char *param)
-{
- FILE *infp, *outfp;
- struct termios orig, temp;
- char *ret = NULL;
-
- /* Read and write to /dev/tty if available. */
- if (keys_from_stdin ||
- (infp = outfp = fopen ("/dev/tty", "w+")) == NULL) {
- infp = stdin;
- outfp = stdout;
- }
-
- /* Print the prompt and set no echo. */
- int tty = isatty (fileno (infp));
- int tcset = 0;
- if (tty) {
- fprintf (outfp, _("Enter key or passphrase (\"%s\"): "), param);
-
- if (!echo_keys) {
- if (tcgetattr (fileno (infp), &orig) == -1) {
- perror ("tcgetattr");
- goto error;
- }
- memcpy (&temp, &orig, sizeof temp);
- temp.c_lflag &= ~ECHO;
-
- tcsetattr (fileno (infp), TCSAFLUSH, &temp);
- tcset = 1;
- }
- }
-
- size_t n = 0;
- ssize_t len;
- len = getline (&ret, &n, infp);
- if (len == -1) {
- perror ("getline");
- ret = NULL;
- goto error;
- }
-
- /* Remove the terminating \n if there is one. */
- if (len > 0 && ret[len-1] == '\n')
- ret[len-1] = '\0';
-
- error:
- /* Restore echo, close file descriptor. */
- if (tty && tcset) {
- printf ("\n");
- tcsetattr (fileno (infp), TCSAFLUSH, &orig);
- }
-
- if (infp != stdin)
- fclose (infp); /* outfp == infp, so this is closed also */
-
- return ret;
-}
extern void free_file_in (char *s);
extern char *file_out (const char *arg);
extern void extended_help_message (void);
-extern char *read_key (const char *param);
/* in cmds.c (auto-generated) */
extern void list_commands (void);
#include <stdlib.h>
#include <string.h>
+#include "c-ctype.h"
+
#include "guestfs.h"
#include "options.h"
+static void do_decrypt (void);
+
/* Global that saves the root device between inspect_mount and
* print_inspect_prompt.
*/
void
inspect_mount (void)
{
+ do_decrypt ();
+
char **roots = guestfs_inspect_os (g);
if (roots == NULL)
exit (EXIT_FAILURE);
free_strings (mountpoints);
}
+
+/* Make a LUKS map name from the partition name,
+ * eg "/dev/vda2" => "luksvda2"
+ */
+static void
+make_mapname (const char *device, char *mapname, size_t len)
+{
+ size_t i = 0;
+
+ if (len < 5)
+ abort ();
+ strcpy (mapname, "luks");
+ mapname += 4;
+ len -= 4;
+
+ if (STRPREFIX (device, "/dev/"))
+ i = 5;
+
+ for (; device[i] != '\0' && len >= 1; ++i) {
+ if (c_isalnum (device[i])) {
+ *mapname++ = device[i];
+ len--;
+ }
+ }
+
+ *mapname = '\0';
+}
+
+/* Simple implementation of decryption: look for any crypto_LUKS
+ * partitions and decrypt them, then rescan for VGs. This only works
+ * for Fedora whole-disk encryption. WIP to make this work for other
+ * encryption schemes.
+ */
+static void
+do_decrypt (void)
+{
+ char **partitions = guestfs_list_partitions (g);
+ if (partitions == NULL)
+ exit (EXIT_FAILURE);
+
+ int need_rescan = 0;
+ size_t i;
+ for (i = 0; partitions[i] != NULL; ++i) {
+ char *type = guestfs_vfs_type (g, partitions[i]);
+ if (type && STREQ (type, "crypto_LUKS")) {
+ char mapname[32];
+ make_mapname (partitions[i], mapname, sizeof mapname);
+
+ char *key = read_key (partitions[i]);
+ /* XXX Should we call guestfs_luks_open_ro if readonly flag
+ * is set? This might break 'mount_ro'.
+ */
+ if (guestfs_luks_open (g, partitions[i], key, mapname) == -1)
+ exit (EXIT_FAILURE);
+
+ free (key);
+
+ need_rescan = 1;
+ }
+ }
+
+ free_strings (partitions);
+
+ if (need_rescan) {
+ if (guestfs_vgscan (g) == -1)
+ exit (EXIT_FAILURE);
+ if (guestfs_vg_activate_all (g, 1) == -1)
+ exit (EXIT_FAILURE);
+ }
+}
--- /dev/null
+/* libguestfs - guestfish and guestmount shared option parsing
+ * Copyright (C) 2010 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+
+#include "guestfs.h"
+
+#include "options.h"
+
+/* Read a passphrase ('Key') from /dev/tty with echo off.
+ * The caller (cmds.c) will call free on the string afterwards.
+ * Based on the code in cryptsetup file lib/utils.c.
+ */
+char *
+read_key (const char *param)
+{
+ FILE *infp, *outfp;
+ struct termios orig, temp;
+ char *ret = NULL;
+
+ /* Read and write to /dev/tty if available. */
+ if (keys_from_stdin ||
+ (infp = outfp = fopen ("/dev/tty", "w+")) == NULL) {
+ infp = stdin;
+ outfp = stdout;
+ }
+
+ /* Print the prompt and set no echo. */
+ int tty = isatty (fileno (infp));
+ int tcset = 0;
+ if (tty) {
+ fprintf (outfp, _("Enter key or passphrase (\"%s\"): "), param);
+
+ if (!echo_keys) {
+ if (tcgetattr (fileno (infp), &orig) == -1) {
+ perror ("tcgetattr");
+ goto error;
+ }
+ memcpy (&temp, &orig, sizeof temp);
+ temp.c_lflag &= ~ECHO;
+
+ tcsetattr (fileno (infp), TCSAFLUSH, &temp);
+ tcset = 1;
+ }
+ }
+
+ size_t n = 0;
+ ssize_t len;
+ len = getline (&ret, &n, infp);
+ if (len == -1) {
+ perror ("getline");
+ ret = NULL;
+ goto error;
+ }
+
+ /* Remove the terminating \n if there is one. */
+ if (len > 0 && ret[len-1] == '\n')
+ ret[len-1] = '\0';
+
+ error:
+ /* Restore echo, close file descriptor. */
+ if (tty && tcset) {
+ printf ("\n");
+ tcsetattr (fileno (infp), TCSAFLUSH, &orig);
+ }
+
+ if (infp != stdin)
+ fclose (infp); /* outfp == infp, so this is closed also */
+
+ return ret;
+}
extern int read_only;
extern int verbose;
extern int inspector;
+extern int keys_from_stdin;
+extern int echo_keys;
extern const char *libvirt_uri;
extern const char *program_name;
extern void inspect_mount (void);
extern void print_inspect_prompt (void);
+/* in key.c */
+extern char *read_key (const char *param);
+
/* in options.c */
extern char add_drives (struct drv *drv, char next_drive);
extern void mount_mps (struct mp *mp);
# between guestfish and guestmount.
SHARED_SOURCE_FILES = \
../fish/inspect.c \
+ ../fish/keys.c \
../fish/options.h \
../fish/options.c \
../fish/virt.c
int read_only = 0;
int verbose = 0;
int inspector = 0;
+int keys_from_stdin = 0;
+int echo_keys = 0;
const char *libvirt_uri;
int dir_cache_timeout = 60;
" -c|--connect uri Specify libvirt URI for -d option\n"
" --dir-cache-timeout Set readdir cache timeout (default 5 sec)\n"
" -d|--domain guest Add disks from libvirt guest\n"
+ " --echo-keys Don't turn off echo for passphrases\n"
" --format[=raw|..] Force disk format for -a option\n"
" --fuse-help Display extra FUSE options\n"
" -i|--inspector Automatically mount filesystems\n"
" --help Display help message and exit\n"
+ " --keys-from-stdin Read passphrases from stdin\n"
" -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n"
" -n|--no-sync Don't autosync\n"
" -o|--option opt Pass extra option to FUSE\n"
{ "connect", 1, 0, 'c' },
{ "dir-cache-timeout", 1, 0, 0 },
{ "domain", 1, 0, 'd' },
+ { "echo-keys", 0, 0, 0 },
{ "format", 2, 0, 0 },
{ "fuse-help", 0, 0, 0 },
{ "help", 0, 0, HELP_OPTION },
{ "inspector", 0, 0, 'i' },
+ { "keys-from-stdin", 0, 0, 0 },
{ "mount", 1, 0, 'm' },
{ "no-sync", 0, 0, 'n' },
{ "option", 1, 0, 'o' },
format = NULL;
else
format = optarg;
- }
- else {
+ } else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
+ keys_from_stdin = 1;
+ } else if (STREQ (long_options[option_index].name, "echo-keys")) {
+ echo_keys = 1;
+ } else {
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
program_name, long_options[option_index].name, option_index);
exit (EXIT_FAILURE);
(see the FUSE option I<-o attr_timeout>), but the FUSE cache
does not anticipate future requests, only cache existing ones.
+=item B<--echo-keys>
+
+When prompting for keys and passphrases, guestfish normally turns
+echoing off so you cannot see what you are typing. If you are not
+worried about Tempest attacks and there is no one else in the room
+you can specify this flag to see what you are typing.
+
=item B<--format=raw|qcow2|..> | B<--format>
The default for the I<-a> option is to auto-detect the format of the
an operating system and mount filesystems as they would be
mounted on the real virtual machine.
+=item B<--keys-from-stdin>
+
+Read key or passphrase parameters from stdin. The default is
+to try to read passphrases from the user by opening C</dev/tty>.
+
=item B<-m dev[:mnt]> | B<--mount dev[:mnt]>
Mount the named partition or logical volume on the given mountpoint
pr "#include \"full-write.h\"\n";
pr "#include \"xstrtol.h\"\n";
pr "#include \"fish.h\"\n";
+ pr "#include \"options.h\"\n";
pr "#include \"cmds_gperf.h\"\n";
pr "\n";
pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
fish/help.c
fish/hexedit.c
fish/inspect.c
+fish/keys.c
fish/lcd.c
fish/man.c
fish/more.c