diff -Nur util-linux-2.12.orig/mount/cryptsetup.c util-linux-2.12/mount/cryptsetup.c --- util-linux-2.12.orig/mount/cryptsetup.c 1970-01-01 01:00:00.000000000 +0100 +++ util-linux-2.12/mount/cryptsetup.c 2004-03-10 00:54:10.977381704 +0100 @@ -0,0 +1,216 @@ +/* + * cryptsetup.c - setup and control encrypted devices + */ + +#include +#include +#include + +#include + +#include "cryptsetup.h" +#include "nls.h" + +extern int verbose; +extern char *xstrdup (const char *s); /* not: #include "sundries.h" */ +extern void *xmalloc (size_t size); /* idem */ +extern void error (const char *fmt, ...); /* idem */ + +#ifdef CRYPT_FLAG_READONLY + +#define BUFFER_SIZE 128 +#define DEFAULT_HASH "ripemd160" +#define DEFAULT_KEYSIZE 256 + +static char * +xstrtok(char *s, char delim) { + static char *p; + + if (!s) + s = p; + if (s) { + p = strchr(s, delim); + if (p) + *p++ = '\0'; + } + return s; +} + +int +set_crypt(char **cryptdev, const char *realdev, int offset, + char **encryption, int pfd, int *cryptro) { + struct crypt_options options; + char buffer[BUFFER_SIZE]; + const char *dir = crypt_get_dir(); + const char *name = NULL; + char *p, *q; + int ret; + + if (!dir) { + error(_("mount: crypt engine not ready")); + return 1; + } + + if (**encryption == '@') { + int len = strlen(dir); + p = *encryption + 1; + if (strncmp(dir, p, len) == 0 && p[len] == '/') + p += len + 1; + q = strchr(p, ':'); + if (q) + *q++ = '\0'; + else + q = p + strlen(p); + + name = p; + *encryption = q; + } + + if (!name) { + p = (char *)realdev; + if (*p == '/') + p++; + if (strncmp(p, "dev/", 4) == 0) + p += 4; + for(q = buffer; *p && q < &buffer[BUFFER_SIZE - 2]; p++) + switch(*p) { + case ':': + case '/': + *q++ = '-'; + break; + case '-': + *q++ = '-'; + *q++ = '-'; + break; + default: + *q++ = *p; + } + strncpy(q, "-crypt", BUFFER_SIZE - (q - buffer)); + buffer[BUFFER_SIZE - 1] = '\0'; + name = buffer; + } + + p = xstrdup(*encryption); + + memset(&options, 0, sizeof options); + options.name = name; + options.device = realdev; + options.cipher = xstrtok(p, ':'); + q = xstrtok(NULL, ':'); + options.key_size = q ? strtoul(q, NULL, 0) : 0; + if (!options.key_size) + options.key_size = DEFAULT_KEYSIZE; + options.hash = xstrtok(NULL, ':'); + if (!(options.hash && *options.hash)) + options.hash = DEFAULT_HASH; + options.key_file = xstrtok(NULL, ':'); + if (!(options.key_file && *options.key_file)) + options.key_file = NULL; + options.passphrase_fd = (pfd >= 0) ? pfd : 0; + options.flags = 0; + if (!options.key_file) + options.flags |= CRYPT_FLAG_PASSPHRASE; + if (*cryptro) + options.flags |= CRYPT_FLAG_READONLY; + options.offset = offset; + + if (options.offset % 512) { + error(_("mount: offset must be a multiple of 512 bytes")); + return 1; + } + options.offset >>= 9; + + if (options.key_size % 8) { + error(_("mount: key size must be a multiple of 8 bits")); + return 1; + } + options.key_size /= 8; + + ret = crypt_create_device(&options); + + free(p); + + if (ret < 0) { + /* use dev as buffer */ + char *errorstr = buffer; + crypt_get_error(errorstr, BUFFER_SIZE); + if (!verbose) + errorstr = strerror(-ret); + + error(_("mount: cryptsetup failed with: %s"), errorstr); + return 1; + } + + *cryptdev = (char *)xmalloc(strlen(dir) + strlen(name) + 2); + sprintf(*cryptdev, "%s/%s", dir, name); + + if (options.flags & CRYPT_FLAG_READONLY) + *cryptro = 1; + + return 0; +} + +int +del_crypt (const char *device) { + struct crypt_options options; + const char *dir = crypt_get_dir(); + int len = strlen(dir); + int ret; + + if (!dir) { + error(_("mount: crypt engine not ready")); + return 1; + } + + if (*device == '@') { + char *p; + device++; + p = strchr(device, ':'); + if (p) + *p = '\0'; + } + + if (strncmp(dir, device, len) == 0 && device[len] == '/') + device += len + 1; + + memset(&options, 0, sizeof options); + options.name = device; + + ret = crypt_remove_device(&options); + if (ret < 0) { + char buffer[BUFFER_SIZE]; + char *errorstr = buffer; + crypt_get_error(errorstr, BUFFER_SIZE); + if (!verbose) + errorstr = strerror(-ret); + + error(_("mount: cryptsetup failed with: %s"), errorstr); + return 1; + } + + return 0; +} + +#else /* without CRYPT_FLAG_READONLY */ + +static void +mutter(void) { + fprintf(stderr, + _("This mount was compiled without cryptsetup support. " + "Please recompile.\n")); +} + +int +set_crypt(char **cryptdev, const char *realdev, int offset, + char **encryption, int pfd, int *cryptro) { + mutter(); + return 1; +} + +int +del_crypt (const char *device) { + mutter(); + return 1; +} + +#endif diff -Nur util-linux-2.12.orig/mount/cryptsetup.h util-linux-2.12/mount/cryptsetup.h --- util-linux-2.12.orig/mount/cryptsetup.h 1970-01-01 01:00:00.000000000 +0100 +++ util-linux-2.12/mount/cryptsetup.h 2004-03-10 00:07:48.000000000 +0100 @@ -0,0 +1,4 @@ +extern int verbose; +extern int set_crypt(char **, const char *, int, char **, + int, int *); +extern int del_crypt(const char *); diff -Nur util-linux-2.12.orig/mount/Makefile util-linux-2.12/mount/Makefile --- util-linux-2.12.orig/mount/Makefile 2003-07-16 22:07:27.000000000 +0200 +++ util-linux-2.12/mount/Makefile 2004-03-10 00:07:48.000000000 +0100 @@ -25,6 +25,7 @@ MAYBE = pivot_root swapoff LO_OBJS = lomount.o $(LIB)/xstrncpy.o +CRYPT_OBJS = cryptsetup.o -lcryptsetup NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o GEN_FILES = nfsmount.h nfsmount_xdr.c nfsmount_clnt.c @@ -44,11 +45,11 @@ mount: mount.o fstab.o sundries.o realpath.o mntent.o version.o \ mount_guess_fstype.o get_label_uuid.o mount_by_label.o getusername.o \ - $(LIB)/setproctitle.o $(LIB)/env.o $(NFS_OBJS) $(LO_OBJS) + $(LIB)/setproctitle.o $(LIB)/env.o $(NFS_OBJS) $(LO_OBJS) $(CRYPT_OBJS) $(LINK) $^ -o $@ umount: umount.o fstab.o sundries.o realpath.o mntent.o getusername.o \ - get_label_uuid.o version.o $(LIB)/env.o $(LO_OBJS) + get_label_uuid.o version.o $(LIB)/env.o $(LO_OBJS) $(CRYPT_OBJS) $(LINK) $^ -o $@ swapon: swapon.o version.o diff -Nur util-linux-2.12.orig/mount/mount.c util-linux-2.12/mount/mount.c --- util-linux-2.12.orig/mount/mount.c 2003-07-15 23:38:48.000000000 +0200 +++ util-linux-2.12/mount/mount.c 2004-03-10 00:28:34.619477080 +0100 @@ -62,6 +62,7 @@ #include "mntent.h" #include "fstab.h" #include "lomount.h" +#include "cryptsetup.h" #include "loop.h" #include "linux_fs.h" /* for BLKGETSIZE */ #include "mount_guess_rootdev.h" @@ -130,6 +131,7 @@ #define MS_USERS 0x40000000 #define MS_USER 0x20000000 #define MS_OWNER 0x10000000 +#define MS_CRYPT 0x00040000 #define MS_NETDEV 0x00020000 #define MS_LOOP 0x00010000 @@ -206,7 +208,7 @@ { "vfs=", 1, &opt_vfstype }, { "offset=", 0, &opt_offset }, { "encryption=", 0, &opt_encryption }, - { "speed=", 0, &opt_speed }, + { "speed=", 0, &opt_speed }, { NULL, 0, NULL } }; @@ -586,7 +588,7 @@ *type = opt_vfstype; } - *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption); + *loop = ((*flags & MS_LOOP) || *loopdev || (opt_offset && !opt_encryption)); *loopfile = *spec; if (*loop) { @@ -605,7 +607,7 @@ printf(_("mount: going to use the loop device %s\n"), *loopdev); offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0; if (set_loop(*loopdev, *loopfile, offset, - opt_encryption, pfd, &loopro)) { + NULL /* opt_encryption */, pfd, &loopro)) { if (verbose) printf(_("mount: failed setting up loop device\n")); return EX_FAIL; @@ -615,6 +617,42 @@ *spec = *loopdev; if (loopro) *flags |= MS_RDONLY; + /* set offset to 0 so that crypto setup doesn't add an offset too */ + opt_offset = 0; + } + } + + return 0; +} + +static int +crypt_check(char **spec, char **type, int *flags, + int *crypt, char **cryptdev, char **realdev) { + int offset; + + *crypt = ((*flags & MS_CRYPT) || opt_encryption); + *realdev = *spec; + + if (*crypt) { + *flags |= MS_CRYPT; + if (fake) { + if (verbose) + printf(_("mount: skipping the setup of an encrypted device\n")); + } else { + int cryptro = (*flags & MS_RDONLY); + + offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0; + if (set_crypt(cryptdev, *realdev, offset, + &opt_encryption, pfd, &cryptro)) { + if (verbose) + printf(_("mount: failed setting up encrypted device\n")); + return EX_FAIL; + } + if (verbose > 1) + printf(_("mount: setup crypt device successfully\n")); + *spec = *cryptdev; + if (cryptro) + *flags |= MS_RDONLY; } } @@ -765,7 +803,9 @@ char *spec, *node, *types; char *user = 0; int loop = 0; + int crypt = 0; char *loopdev = 0, *loopfile = 0; + char *cryptdev = 0, *realdev = 0; struct stat statbuf; int nfs_mount_version = 0; /* any version */ @@ -796,6 +836,10 @@ res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile); if (res) return res; + + res = crypt_check(&spec, &types, &flags, &crypt, &cryptdev, &realdev); + if (res) + return res; } /* @@ -832,8 +876,13 @@ /* Mount succeeded, report this (if verbose) and write mtab entry. */ if (loop) opt_loopdev = loopdev; + if (crypt) { + char *tmp = xmalloc(strlen(cryptdev) + strlen(opt_encryption) + 3); + sprintf(tmp, "@%s:%s", cryptdev, opt_encryption); + opt_encryption = tmp; + } - update_mtab_entry(loop ? loopfile : spec, + update_mtab_entry(loop ? loopfile : crypt ? realdev : spec, node, types ? types : "unknown", fix_opts_string (flags & ~MS_NOMTAB, extra_opts, user), @@ -847,6 +896,8 @@ mnt_err = errno; + if (crypt) + del_crypt(spec); if (loop) del_loop(spec); diff -Nur util-linux-2.12.orig/mount/umount.c util-linux-2.12/mount/umount.c --- util-linux-2.12.orig/mount/umount.c 2003-07-15 23:19:22.000000000 +0200 +++ util-linux-2.12/mount/umount.c 2004-03-10 00:07:48.000000000 +0100 @@ -41,6 +41,7 @@ #include "sundries.h" #include "getusername.h" #include "lomount.h" +#include "cryptsetup.h" #include "loop.h" #include "fstab.h" #include "env.h" @@ -249,6 +250,7 @@ int isroot; int res; const char *loopdev; + const char *cryptdev; /* Special case for root. As of 0.99pl10 we can (almost) unmount root; the kernel will remount it readonly so that we can carry on running @@ -331,12 +333,33 @@ } } - loopdev = 0; if (res >= 0) { /* Umount succeeded */ if (verbose) printf (_("%s umounted\n"), spec); + } + + cryptdev = 0; + if (res >= 0) { + /* Free any encrypted devices that we allocated ourselves */ + if (mc) { + char *optl; + + optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : ""; + for (optl = strtok (optl, ","); optl; + optl = strtok (NULL, ",")) { + if (!strncmp(optl, "encryption=", 11)) { + cryptdev = optl+11; + break; + } + } + } + } + if (cryptdev) + del_crypt(cryptdev); + loopdev = 0; + if (res >= 0) { /* Free any loop devices that we allocated ourselves */ if (mc) { char *optl;