[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
new patches
New patches here:
The variable key size patch has been touched up a bit but is functionally
identical.
The external program patch has been reworked. The external program
is now specified like this:
mount -o loop,encryption=aes-cbc-128,keygen=hashprog;sha256 \
~sluskyb/testloop /mnt/test
The looped file and the encryption method are passed as additional
arguments, so this would run "hashprog sha256 ~sluskyb/testloop
aes-cbc-128" and read the encryption key from its stdout.
There is no equivalent option in losetup, but then
hashprog sha256 |losetup -e aes-cbc-128 -p 0 /dev/loop/11 \
~sluskyb/testloop
works just fine.
I've cut out xgetpass() entirely. Now that hashing is done outside
losetup, there's no sense in reading any more than LO_KEY_SIZE bytes.
So if we're given an fd or an external program then we do a plain old
read(2), otherwise a plain old getpass(3).
QCF?
--
Ben Slusky | "You think that's air you're
sluskyb@paranoiacs.org | breathing now?"
sluskyb@stwing.org | -Morpheus
PGP keyID ADA44B3B
--- lomount.c-fixed-key-size 2003-07-16 19:56:53.000000000 -0400
+++ lomount.c 2003-08-07 13:34:22.000000000 -0400
@@ -24,12 +24,15 @@
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
+#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/sysmacros.h>
+#include <regex.h>
#include "loop.h"
#include "lomount.h"
@@ -249,7 +252,7 @@
set_loop(const char *device, const char *file, int offset,
const char *encryption, int pfd, int *loopro) {
struct loop_info64 loopinfo64;
- int fd, ffd, mode;
+ int fd, ffd, mode, keysize = 0;
char *pass;
mode = (*loopro ? O_RDONLY : O_RDWR);
@@ -275,9 +278,38 @@
if (digits_only(encryption)) {
loopinfo64.lo_encrypt_type = atoi(encryption);
} else {
+ regex_t keysize_re;
+ regmatch_t keysize_rm;
+ int rerror;
+ char rerror_buf[LINE_MAX+1],
+ *encryption_dup = xstrdup(encryption);
+
loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
+
+ if ((rerror = regcomp(&keysize_re,
+ "-[[:digit:]]+$",
+ REG_EXTENDED)) != 0) {
+ fprintf(stderr, _("regcomp: "));
+ regerror(rerror, &keysize_re, rerror_buf,
+ LINE_MAX);
+ fprintf(stderr, "%s\n", rerror_buf);
+ } else {
+ if (regexec(&keysize_re, encryption_dup,
+ 1, &keysize_rm, 0) == 0) {
+ keysize = atoi(encryption_dup +
+ keysize_rm.rm_so + 1);
+ /* convert #bits to #bytes */
+ keysize /= 8;
+ /* cut the keysize out now */
+ encryption_dup[keysize_rm.rm_so] = '\0';
+ }
+
+ regfree(&keysize_re);
+ }
+
snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE,
- "%s", encryption);
+ "%s", encryption_dup);
+ free(encryption_dup);
}
}
@@ -307,9 +339,14 @@
strlen(loopinfo64.lo_encrypt_key);
break;
default:
+ if (keysize == 0) {
+ fprintf(stderr, _("You must specify a key size (in bits) for use with CryptoAPI encryption.\n"));
+ return -1;
+ }
+ /* FIXME we should be checking keysize against the min/max in /proc/crypto */
pass = xgetpass(pfd, _("Password: "));
xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
- loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
+ loopinfo64.lo_encrypt_key_size = keysize;
}
if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
--- lomount.c-no-reader-prog 2003-08-07 13:48:35.000000000 -0400
+++ lomount.c 2003-08-07 16:32:26.000000000 -0400
@@ -33,6 +33,7 @@
#include <sys/mman.h>
#include <sys/sysmacros.h>
#include <regex.h>
+#include <signal.h>
#include "loop.h"
#include "lomount.h"
@@ -201,45 +202,6 @@
return 0;
}
-/*
- * A function to read the passphrase either from the terminal or from
- * an open file descriptor.
- */
-static char *
-xgetpass(int pfd, const char *prompt) {
- char *pass;
- int buflen, i;
-
- if (pfd < 0) /* terminal */
- return getpass(prompt);
-
- pass = NULL;
- buflen = 0;
- for (i=0; ; i++) {
- if (i >= buflen-1) {
- /* we're running out of space in the buffer.
- * Make it bigger: */
- char *tmppass = pass;
- buflen += 128;
- pass = realloc(tmppass, buflen);
- if (pass == NULL) {
- /* realloc failed. Stop reading. */
- error("Out of memory while reading passphrase");
- pass = tmppass; /* the old buffer hasn't changed */
- break;
- }
- }
- if (read(pfd, pass+i, 1) != 1 || pass[i] == '\n')
- break;
- }
- if (pass == NULL)
- return "";
- else {
- pass[i] = 0;
- return pass;
- }
-}
-
static int
digits_only(const char *s) {
while (*s)
@@ -344,8 +306,26 @@
return -1;
}
/* FIXME we should be checking keysize against the min/max in /proc/crypto */
- pass = xgetpass(pfd, _("Password: "));
- xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
+
+ if (pfd == -1) {
+ pass = getpass(_("Password: "));
+ xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
+ } else {
+ /* If we're reading from an extenral program, *
+ * odds are good that a SIGCHLD will interrupt *
+ * this read(), and ruin our whole day. So we *
+ * must block it. */
+ sigset_t ss, oss;
+ sigemptyset(&ss);
+ sigaddset(&ss, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &ss, &oss);
+ if (read(pfd, loopinfo64.lo_encrypt_key,
+ LO_KEY_SIZE) == -1) {
+ perror("read");
+ fprintf(stderr, _("Error reading encryption key, exiting\n"));
+ }
+ sigprocmask(SIG_SETMASK, &oss, NULL);
+ }
loopinfo64.lo_encrypt_key_size = keysize;
}
--- mount.8-no-reader-prog 2003-08-04 00:26:04.000000000 -0400
+++ mount.8 2003-08-07 17:02:39.000000000 -0400
@@ -1696,6 +1696,11 @@
.BR loop ", " offset " and " encryption ,
that are really options to
.BR losetup (8).
+You can also use the
+.BR keygen
+option to have mount call an external program from, which it will read the
+encryption key. Arguments to this program can be given, separated by semicolons.
+
If no explicit loop device is mentioned
(but just an option `\fB\-o loop\fP' is given), then
.B mount
--- mount.c-no-reader-prog 2003-07-15 17:38:48.000000000 -0400
+++ mount.c 2003-08-07 16:43:12.000000000 -0400
@@ -195,7 +195,7 @@
};
static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
- *opt_speed;
+ *opt_keygen, *opt_speed;
static struct string_opt_map {
char *tag;
@@ -206,6 +206,7 @@
{ "vfs=", 1, &opt_vfstype },
{ "offset=", 0, &opt_offset },
{ "encryption=", 0, &opt_encryption },
+ { "keygen=", 0, &opt_keygen },
{ "speed=", 0, &opt_speed },
{ NULL, 0, NULL }
};
@@ -586,7 +587,7 @@
*type = opt_vfstype;
}
- *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption);
+ *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption || opt_keygen);
*loopfile = *spec;
if (*loop) {
@@ -596,6 +597,11 @@
printf(_("mount: skipping the setup of a loop device\n"));
} else {
int loopro = (*flags & MS_RDONLY);
+ /* Extra args to the keygen program. Right now there are 2: *
+ * - the looped file *
+ * - the encryption type used */
+ char *keygen_args[] = {*loopfile, opt_encryption};
+ const int _n_keygen_args = 2;
if (!*loopdev || !**loopdev)
*loopdev = find_unused_loop_device();
@@ -604,6 +610,8 @@
if (verbose)
printf(_("mount: going to use the loop device %s\n"), *loopdev);
offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0;
+ if (opt_keygen)
+ pfd = use_keygen_prog(opt_keygen, keygen_args, _n_keygen_args);
if (set_loop(*loopdev, *loopfile, offset,
opt_encryption, pfd, &loopro)) {
if (verbose)
--- sundries.c-no-reader-prog 2003-08-04 00:24:47.000000000 -0400
+++ sundries.c 2003-08-07 16:53:40.000000000 -0400
@@ -12,6 +12,8 @@
#include <stdio.h>
#include <string.h>
#include <mntent.h> /* for MNTTYPE_SWAP */
+#include <sys/types.h>
+#include <sys/wait.h>
#include "fstab.h"
#include "sundries.h"
#include "realpath.h"
@@ -285,3 +287,101 @@
free(canonical);
return xstrdup(path);
}
+
+static volatile pid_t keygen_pid = -1;
+
+/* Handle a SIGCHLD -- wait for the child process */
+static void
+child_handler (int i) {
+ int status;
+ if (keygen_pid != -1 && wait(&status) == keygen_pid) {
+ keygen_pid = -1;
+ if (WEXITSTATUS(status) != 0)
+ exit(WEXITSTATUS(status));
+ }
+}
+
+/* Make sure we clean up after the child */
+static void
+child_cleanup (void) {
+ /* "Clean up" means wait. So we let child_handler do all the work */
+ while (keygen_pid != -1)
+ sleep(1);
+}
+
+/* Split a string into pieces, using delim as the delimiter. *
+ * Returns the number of pieces. */
+static int
+split_args (char *args[], const char *str, const char *delim, int nargs) {
+ int i=0;
+ char *s = xstrdup(str);
+ args[0] = strtok(s, delim);
+ if (args[0] == NULL)
+ return 0;
+
+ while (++i < nargs) {
+ if ((args[i] = strtok(NULL, delim)) == NULL)
+ break;
+ }
+
+ return i;
+}
+
+#define KEYGEN_MAX_ARGS 64 /* more than anyone will need, right? */
+
+/* Call an external program to give us the encryption key for an *
+ * encrypted device. We split the string s into a command and args on *
+ * semicolons ('cuz you can't put spaces in the fs_mntopts field), then *
+ * add some specific args (eg. the looped file or device, the *
+ * encryption method used; check the caller to see the actual list). *
+ * Returns a file descriptor from which we read the key. */
+int
+use_keygen_prog (const char *s, const char *addl_args[], int naddl_args) {
+ int fd[2];
+
+ struct sigaction sa = {
+ .sa_handler = child_handler,
+ .sa_flags = SA_NOCLDSTOP
+ };
+
+ if (pipe(fd) == -1) {
+ perror("pipe");
+ exit(EX_SYSERR);
+ }
+ if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+ perror("sigaction");
+ exit(EX_SYSERR);
+ }
+ if ((keygen_pid = fork()) == -1) {
+ perror("fork");
+ exit(EX_SYSERR);
+ } else if (keygen_pid) { /* parent */
+ atexit(child_cleanup);
+ close(fd[1]);
+ return fd[0];
+ } else { /* child */
+ char *args[KEYGEN_MAX_ARGS+1];
+ int i, n = split_args(args, s, ";", KEYGEN_MAX_ARGS - naddl_args);
+ if (!n) {
+ fprintf(stderr, _("Invalid keygen program, exiting\n"));
+ exit(EX_USAGE);
+ }
+ for(i=0; i < naddl_args; i++)
+ args[n+i] = addl_args[i];
+ args[n+naddl_args] = NULL;
+
+ close(fd[0]);
+ if (dup2(fd[1], STDOUT_FILENO) == -1) {
+ perror("dup2");
+ exit(EX_SYSERR);
+ }
+ setuid(getuid()); /* set euid to ruid */
+ if (execvp(args[0], args) == -1) {
+ perror(args[0]);
+ exit(EX_USAGE);
+ }
+ }
+
+ return 0; /* so gcc will shut up */
+}
+
--- sundries.h-no-reader-prog 2002-10-31 20:00:50.000000000 -0500
+++ sundries.h 2003-08-07 17:07:52.000000000 -0400
@@ -25,6 +25,7 @@
void error (const char *fmt, ...);
int matching_type (const char *type, const char *types);
int matching_opts (const char *options, const char *test_opts);
+int use_keygen_prog (const char *s, const char *addl_args[], int naddl_args);
void *xmalloc (size_t size);
char *xstrdup (const char *s);
char *xstrndup (const char *s, int n);