--- util-linux-2.13-pre6/config.h.in.cryptsetup 2005-10-16 14:20:17.000000000 +0200 +++ util-linux-2.13-pre6/config.h.in 2006-02-06 17:31:52.000000000 +0100 @@ -49,6 +49,9 @@ /* Define to 1 if you have the `blkid' library (-lblkid). */ #undef HAVE_LIBBLKID +/* Define to 1 if you have the `cryptsetup' library (-lcryptsetup). */ +#undef HAVE_LIBCRYPTSETUP + /* Define to 1 if you have the `selinux' library (-lselinux). */ #undef HAVE_LIBSELINUX --- util-linux-2.13-pre6/configure.ac.cryptsetup 2005-10-16 14:09:54.000000000 +0200 +++ util-linux-2.13-pre6/configure.ac 2006-02-06 17:31:52.000000000 +0100 @@ -59,6 +59,8 @@ AC_CHECK_LIB(blkid, blkid_known_fstype) AM_CONDITIONAL(HAVE_BLKID, test x$ac_cv_lib_blkid_blkid_known_fstype = xyes) +AC_CHECK_LIB(cryptsetup, crypt_isLuks) +AM_CONDITIONAL(HAVE_CRYPTSETUP, test x$ac_cv_lib_cryptsetup_crypt_isLuks = xyes) AM_GNU_GETTEXT([external]) --- util-linux-2.13-pre6/mount/umount.c.cryptsetup 2005-09-23 21:55:55.000000000 +0200 +++ util-linux-2.13-pre6/mount/umount.c 2006-02-06 17:31:52.000000000 +0100 @@ -20,6 +20,10 @@ #include "env.h" #include "nls.h" +#ifdef HAVE_LIBCRYPTSETUP +#include "cryptsetup.h" +#endif + #include #include #include @@ -270,7 +274,9 @@ int res; int status; const char *loopdev; - +#ifdef HAVE_LIBCRYPTSETUP + const char *cryptdev = NULL; +#endif /* 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 afterwards. The readonly remount is illegal if any files are opened @@ -366,25 +372,31 @@ if (verbose) printf (_("%s umounted\n"), spec); - /* Free any loop devices that we allocated ourselves */ + /* Free any loop devices that we allocated ourselves or + * unmap encrypted devices + */ if (mc) { char *optl; /* old style mtab line? */ - if (streq(mc->m.mnt_type, "loop")) { + if (streq(mc->m.mnt_type, "loop")) loopdev = spec; - goto gotloop; - } /* new style mtab line? */ optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : ""; for (optl = strtok (optl, ","); optl; optl = strtok (NULL, ",")) { - if (!strncmp(optl, "loop=", 5)) { + if (loopdev==NULL && + strncmp(optl, "loop=", 5)==0) loopdev = optl+5; - goto gotloop; - } +#ifdef HAVE_LIBCRYPTSETUP + if (cryptdev==NULL && + strcmp(optl, "crypt")==0) + cryptdev = mc->m.mnt_fsname; +#endif } + if (loopdev) + goto gotloop; } else { /* * If option "-o loop=spec" occurs in mtab, @@ -399,6 +411,13 @@ loopdev = spec; } gotloop: + +#ifdef HAVE_LIBCRYPTSETUP + if (cryptdev) { + cryptdev = loopdev ? loopdev : cryptdev; /* mount -o loop,crypt */ + mntcrypt_close(cryptdev); + } +#endif if (loopdev) del_loop(loopdev); --- /dev/null 2006-01-27 17:27:48.496582000 +0100 +++ util-linux-2.13-pre6/mount/cryptsetup.h 2006-02-06 17:31:52.000000000 +0100 @@ -0,0 +1,28 @@ +#ifndef _MOUNT_CRYPTSETUP_H +#define _MOUNT_CRYPTSETUP_H + +#define DEV_DIR "/dev" +#define DEV_DIR_L 4 + +/* Error codes + * -- libcryptsetup uses codes less than 0 and our private error codes are greater than 10000 + */ +#define ERR_MNTCRYPT_DIR 10001 +#define ERR_MNTCRYPT_DEVICE 10002 +#define ERR_MNTCRYPT_NAME 10003 +#define ERR_MNTCRYPT_KEYSIZE 10004 +#define ERR_MNTCRYPT_OFFSET 10005 +#define ERR_MNTCRYPT_SKIP 10006 + +extern void mntcrypt_get_error(int code, char *buf, size_t bufsiz); + +extern int mntcrypt_open(char **spec, int *flags, const char *device, + const char *keyfile, const char *keysize, const char *cipher, + const char *hash, const char *skip, const char *offset); + +extern int mntcrypt_close(const char *name); + +extern int mntcrypt_status(char **spec, const char *device, int *err); + +#endif /* _MOUNT_CRYPTSETUP_H */ + --- util-linux-2.13-pre6/mount/swapon.c.cryptsetup 2005-09-12 22:37:07.000000000 +0200 +++ util-linux-2.13-pre6/mount/swapon.c 2006-02-06 17:31:52.000000000 +0100 @@ -18,6 +18,10 @@ #include "mount_blkid.h" #include "mount_by_label.h" +#ifdef HAVE_LIBCRYPTSETUP +#include "cryptsetup.h" +#endif + #define streq(s, t) (strcmp ((s), (t)) == 0) #define _PATH_FSTAB "/etc/fstab" @@ -53,20 +57,36 @@ static void swapon_usage(FILE *fp, int n) { - fprintf(fp, _("usage: %s [-hV]\n" - " %s -a [-e] [-v]\n" - " %s [-v] [-p priority] special|LABEL=volume_name ...\n" - " %s [-s]\n"), - progname, progname, progname, progname); + fprintf(fp, _("usage: %1$s [-hV]\n" + " %1$s -a [-e] [-v]\n" + " %1$s [-v] [-p priority] special|LABEL=volume_name ...\n" + " %1$s [-s]\n" +#ifdef HAVE_LIBCRYPTSETUP + " %1$s -C device=path[,cryptsetup_options,...]\n\n" + " cryptsetup options:\n" + " device=encrypted_device (required)\n" + " keyfile=path\n" + " keysize=num\n" + " cipher=name\n" + " hash=name\n" + " skip=num\n" + " offset=num\n" +#endif + ), + progname); exit(n); } static void swapoff_usage(FILE *fp, int n) { - fprintf(fp, _("usage: %s [-hV]\n" - " %s -a [-v]\n" - " %s [-v] special ...\n"), - progname, progname, progname); + fprintf(fp, _("usage: %1$s [-hV]\n" + " %1$s -a [-v]\n" + " %1$s [-v] special ...\n" +#ifdef HAVE_LIBCRYPTSETUP + " %1$s -C encrypted_device | mapped_device\n" +#endif + ), + progname); exit(n); } @@ -92,6 +112,67 @@ #include #endif +/* + * string options from -C or from fstab + * -- it's same like mount options parsing. + */ +static const char *opt_pri, *opt_noauto; + +#ifdef HAVE_LIBCRYPTSETUP +/* note: cryptsetup uses the "offsett" option too */ +static const char *opt_device, *opt_keyfile, *opt_keysize, *opt_cipher, + *opt_hash, *opt_skip, *opt_crypt, *opt_offset; +#endif + +static struct string_opt_map { + char *tag; + const char **valptr; +} string_opt_map[] = { + { "pri=", &opt_pri }, + { "noauto", &opt_noauto }, +#ifdef HAVE_LIBCRYPTSETUP + { "crypt", &opt_crypt }, + { "device=", &opt_device }, /* cryptsetup device */ + { "keyfile=", &opt_keyfile }, + { "keysize=", &opt_keysize }, + { "cipher=", &opt_cipher }, + { "hash=", &opt_hash }, + { "skip=", &opt_skip }, + { "offset=", &opt_offset }, +#endif + { NULL, NULL } +}; + +static void +parse_string_opts (const char *options) { + static int init = 0; + struct string_opt_map *m; + char *opts, *opt; + + /* initialize or free options values */ + for (m = &string_opt_map[0]; m->tag; m++) { + if (init && *m->valptr) + free((void *) *m->valptr); + else + *m->valptr = NULL; + } + init = 1; + + if (!options) + return; + opts = strdup(options); + + /* search options by map */ + for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ",")) { + for (m = &string_opt_map[0]; m->tag; m++) { + int lth = strlen(m->tag); + if (!strncmp(opt, m->tag, lth)) { + *m->valptr = strdup(opt + lth); + break; + } + } + } +} /* * contents of /proc/swaps @@ -257,6 +338,28 @@ return special ? do_swapon(special, prio) : cannot_find(uuid); } +#ifdef HAVE_LIBCRYPTSETUP +static int +swapon_by_crypt(const char *opts, int prio, char *special) { + int r; + + if (opts) + parse_string_opts(opts); + + /*fprintf(stderr, "CRYPT: spec=%s, dev=%s\n", special, opt_device); */ + + if ((r = mntcrypt_open(&special, NULL, opt_device, opt_keyfile, + opt_keysize, opt_cipher, opt_hash, opt_skip, opt_offset))) + { + char buf[BUFSIZ]; + mntcrypt_get_error(r, buf, sizeof buf); + fprintf(stderr, _("%s: %s\n"), progname, buf); + return -1; + } + return do_swapon(special, prio); +} +#endif + static int do_swapoff(const char *orig_special, int quiet) { const char *special; @@ -294,6 +397,43 @@ const char *special = mount_get_devname_by_uuid(uuid); return special ? do_swapoff(special, quiet) : cannot_find(uuid); } +#ifdef HAVE_LIBCRYPTSETUP +static int +swapoff_by_crypt(const char *name, int quiet) { + char *spec = (char *) name; + int status; + + if (!name) + return -1; + if (strncmp(name, DEV_DIR, DEV_DIR_L)) { + if (!quiet) + fprintf(stderr, _("%s: unsupported option: %s\n"), progname, name); + return -1; + } + /* try it as a path to mapped device (e.g. /dev/mapper/foo */ + if (mntcrypt_status(&spec, NULL, NULL)==0) { + spec = NULL; + /* try it as path to encrypted device (e.g. /dev/foo) */ + if (mntcrypt_status(&spec, name, NULL)==0) { + if (!quiet) + fprintf(stderr, _("%s: %s: cannot determine encrypted or mapped.\n"), + progname, name); + return -1; + } + } + /* fprintf(stderr, "CRYPT: swapoff: %s\n", spec); */ + if ((status = do_swapoff(spec, quiet))==0) { + int r = mntcrypt_close(spec); + if (r && !quiet) { + char buf[BUFSIZ]; + mntcrypt_get_error(r, buf, sizeof buf); + fprintf(stderr, _("%s: %s\n"), progname, buf); + return -1; + } + } + return status; +} +#endif static int swapon_all(void) { @@ -314,30 +454,35 @@ while ((fstab = getmntent(fp)) != NULL) { const char *orig_special = fstab->mnt_fsname; const char *special; - int skip = 0; int pri = priority; if (!streq(fstab->mnt_type, MNTTYPE_SWAP)) continue; - - special = mount_get_devname(orig_special); + parse_string_opts(fstab->mnt_opts); +#ifdef HAVE_LIBCRYPTSETUP + if (opt_crypt) + { + special = orig_special; + if (mntcrypt_status((char **) &special, opt_device, NULL)) + continue; /* already active partition */ + } else +#endif + special = mount_get_devname(orig_special); + if (!special) continue; if (!is_in_proc_swaps(special) && (!ifexists || !access(special, R_OK))) { - /* parse mount options; */ - char *opt, *opts = strdup(fstab->mnt_opts); - - for (opt = strtok(opts, ","); opt != NULL; - opt = strtok(NULL, ",")) { - if (strncmp(opt, "pri=", 4) == 0) - pri = atoi(opt+4); - if (strcmp(opt, "noauto") == 0) - skip = 1; - } - if (!skip) + if (opt_pri && isdigit(*opt_pri)) + pri = atoi(opt_pri); + if (!opt_noauto) +#ifdef HAVE_LIBCRYPTSETUP + status |= opt_crypt ? swapon_by_crypt(NULL, pri, (char *)special) : + do_swapon(special, pri); +#else status |= do_swapon(special, pri); +#endif } } fclose(fp); @@ -360,17 +505,35 @@ ulist[ulct-1] = uuid; } +#ifdef HAVE_LIBCRYPTSETUP +static const char **clist = NULL; +static int clct = 0; + +static void addc(const char *opts) { + clist = (const char **) xrealloc(clist, (++clct) * sizeof(char *)); + clist[clct-1] = opts; +} +# define SWAPON_OPTIONS "ahep:svVL:U:C:" +#else /* !HAVE_LIBCRYPTSETUP */ +# define SWAPON_OPTIONS "ahep:svVL:U:" +#endif + static int main_swapon(int argc, char *argv[]) { int status = 0; int c, i; - while ((c = getopt_long(argc, argv, "ahep:svVL:U:", + while ((c = getopt_long(argc, argv, SWAPON_OPTIONS, longswaponopts, NULL)) != -1) { switch (c) { case 'a': /* all */ ++all; break; +#ifdef HAVE_LIBCRYPTSETUP + case 'C': + addc(optarg); + break; +#endif case 'h': /* help */ swapon_usage(stdout, 0); break; @@ -403,8 +566,12 @@ } } argv += optind; - + +#ifdef HAVE_LIBCRYPTSETUP + if (!all && !llct && !ulct && !clct && *argv == NULL) +#else if (!all && !llct && !ulct && *argv == NULL) +#endif swapon_usage(stderr, 2); if (ifexists && (!all || strcmp(progname, "swapon"))) @@ -418,13 +585,22 @@ for (i = 0; i < ulct; i++) status |= swapon_by_uuid(ulist[i], priority); - +#ifdef HAVE_LIBCRYPTSETUP + for (i = 0; i < clct; i++) + status |= swapon_by_crypt(clist[i], priority, NULL); +#endif while (*argv != NULL) status |= do_swapon(*argv++, priority); return status; } +#ifdef HAVE_LIBCRYPTSETUP +#define SWAPOFF_OPTIONS "ahvVL:U:C:" +#else +#define SWAPOFF_OPTIONS "ahvVL:U:" +#endif + static int main_swapoff(int argc, char *argv[]) { FILE *fp; @@ -432,12 +608,17 @@ int status = 0; int c, i; - while ((c = getopt_long(argc, argv, "ahvVL:U:", + while ((c = getopt_long(argc, argv, SWAPOFF_OPTIONS, longswapoffopts, NULL)) != -1) { switch (c) { case 'a': /* all */ ++all; break; +#ifdef HAVE_LIBCRYPTSETUP + case 'C': + addc(optarg); + break; +#endif case 'h': /* help */ swapoff_usage(stdout, 0); break; @@ -462,9 +643,12 @@ } argv += optind; +#ifdef HAVE_LIBCRYPTSETUP + if (!all && !llct && !ulct && !clct && *argv == NULL) +#else if (!all && !llct && !ulct && *argv == NULL) swapoff_usage(stderr, 2); - +#endif /* * swapoff any explicitly given arguments. * Complain in case the swapoff call fails. @@ -474,7 +658,10 @@ for (i = 0; i < ulct; i++) status |= swapoff_by_uuid(ulist[i], !QUIET); - +#ifdef HAVE_LIBCRYPTSETUP + for (i = 0; i < clct; i++) + status |= swapoff_by_crypt(clist[i], !QUIET); +#endif while (*argv != NULL) status |= do_swapoff(*argv++, !QUIET); @@ -502,10 +689,32 @@ progname, _PATH_FSTAB, strerror(errsv)); exit(2); } + while ((fstab = getmntent(fp)) != NULL) { - if (streq(fstab->mnt_type, MNTTYPE_SWAP) && - !is_in_proc_swaps(fstab->mnt_fsname)) + const char *orig_special = fstab->mnt_fsname; + const char *special; + + if (!streq(fstab->mnt_type, MNTTYPE_SWAP)) + continue; + parse_string_opts(fstab->mnt_opts); +#ifdef HAVE_LIBCRYPTSETUP + if (opt_crypt) + { + special = orig_special; + if (!mntcrypt_status((char **) &special, opt_device, NULL)) + continue; /* already inactive partition */ + } else +#endif + special = mount_get_devname(orig_special); + if (!special) + continue; + if (!is_in_proc_swaps(fstab->mnt_fsname)) do_swapoff(fstab->mnt_fsname, QUIET); +#ifdef HAVE_LIBCRYPTSETUP + if (opt_crypt) + mntcrypt_close(special); +#endif + } fclose(fp); } --- /dev/null 2006-01-27 17:27:48.496582000 +0100 +++ util-linux-2.13-pre6/mount/cryptsetup.c 2006-02-06 17:31:52.000000000 +0100 @@ -0,0 +1,270 @@ + +/* + * cryptsetup [u]mount routines + * + * 18-Aug-2005 Karel Zak + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cryptsetup.h" +#include "nls.h" + +#define DEFAULT_CIPHER "aes" +#define DEFAULT_HASH "ripemd160" +#define DEFAULT_KEY_SIZE 256 + + +void +mntcrypt_get_error(int code, char *buf, size_t bufsiz) +{ + char *err = NULL; + + switch(code) + { + case ERR_MNTCRYPT_DIR: + err = _("cannot determine mapper directory"); + break; + case ERR_MNTCRYPT_DEVICE: + err = _("cannot determine device name"); + break; + case ERR_MNTCRYPT_NAME: + err = _("cannot determine name for mapping"); + break; + case ERR_MNTCRYPT_KEYSIZE: + err = _("unexpected keysize value"); + break; + case ERR_MNTCRYPT_OFFSET: + err = _("unexpected offset value"); + break; + case ERR_MNTCRYPT_SKIP: + err = _("unexpected skip value"); + break; + default: + break; + } + if (err) + strncpy(buf, err, bufsiz); + else + crypt_get_error(buf, bufsiz); +} + +static const char * +mntcrypt_determine_device(const char *dir, const char *spec, const char *device) +{ + struct stat st; + char *dev; + + if (!device) + { + int ssz, dsz = strlen(dir); + if (!spec) + /* no way how determine your wish */ + return NULL; + if (strncmp(dir, spec, dsz)) + /* useless things in spec -- LABEL=, UUID=, ... */ + return NULL; + + ssz = strlen(spec)-dsz+sizeof(DEV_DIR)+1; + dev = malloc(ssz); + snprintf(dev, ssz, "%s%s", DEV_DIR, spec+dsz); + } + else + dev = strdup(device); + + if (dev && stat(dev, &st)==0 && S_ISBLK(st.st_mode)) + return (const char *) dev; + + free((void *) dev); + return NULL; +} + +/* + * determine the name: + * - user defined by spec (spec: /dev/mapper/) + * - or define new name by device (device: /dev/), + */ +static const char * +mntcrypt_determine_name(const char *dir, const char *spec, const char *device) +{ + int len = strlen(dir); + char *p; + + if (spec && strncmp(dir, spec, len)==0 && *(spec+len)=='/') + { + spec+=len+1; + if (*spec) + return (const char *) strdup(spec); /* user defined */ + } + if ((p = strrchr(device, '/'))==NULL || *(++p)=='\0') + return NULL; + return (const char *) strdup(p); +} + +/* + * returns: 1 (active partition) or 0 (inactive partition) + * and fills correct path to *spec and error code to *err + */ +int +mntcrypt_status(char **spec, const char *device, int *err) +{ + int e = 0, status = 0, sz; + const char *dir = crypt_get_dir(); + struct crypt_options opt; + + memset(&opt, 0, sizeof(struct crypt_options)); + if (!dir) + e = ERR_MNTCRYPT_DIR; + + if (e==0 && (opt.device = mntcrypt_determine_device(dir, *spec, device))==NULL) + e = ERR_MNTCRYPT_DEVICE; + + if (e==0 && (opt.name = mntcrypt_determine_name(dir, *spec, device))==NULL) + e = ERR_MNTCRYPT_NAME; + + if (e==0) + { + /* libcryptsetup: error: < 0, inactive: 0, active: > 0 */ + int r = crypt_query_device(&opt); + + if (r < 0) + e = r; /* error */ + else if (r==0) + status = 0; /* inactive */ + else + status = 1; /* active */ + } + if (spec && opt.name) + { + sz = strlen(dir)+strlen(opt.name)+2; + *spec = (char *) malloc(sz); + snprintf(*spec, sz, "%s/%s", dir, opt.name); + } + if (opt.device) + free((void *) opt.device); + if (opt.name) + free((void *) opt.name); + if (err) + *err = e; + return status; +} + +/* + * creates mapped device from encrypted device + * returns: 1=succes, 0=error + */ +int +mntcrypt_open(char **spec, int *flags, const char *device, + const char *keyfile, const char *keysize, const char *cipher, + const char *hash, const char *skip, const char *offset) +{ + int r = 0, isLuks, sz; + struct crypt_options opt; + const char *dir = crypt_get_dir(); + + if (!dir) + return ERR_MNTCRYPT_DIR; + + memset(&opt, 0, sizeof(struct crypt_options)); + + if (!(opt.device = mntcrypt_determine_device(dir, *spec, (char *) device))) + return ERR_MNTCRYPT_DEVICE; + + isLuks = !crypt_isLuks(&opt); + + opt.key_file = keyfile; + + if (flags && (*flags & MS_RDONLY)) + opt.flags |= CRYPT_FLAG_READONLY; + + if (!(opt.name = mntcrypt_determine_name(dir, *spec, device))) + r = ERR_MNTCRYPT_NAME; + else if (isLuks) + r = crypt_luksOpen(&opt); + else + { + opt.cipher = cipher ? : DEFAULT_CIPHER; + opt.hash = hash ? : DEFAULT_HASH; + opt.key_size = DEFAULT_KEY_SIZE / 8; + + if ((opt.hash && strcmp(opt.hash, "plain") == 0) || opt.key_file) + opt.hash = NULL; + if (keysize) + { + if (!isdigit(*keysize)) + r = ERR_MNTCRYPT_KEYSIZE; + else + { + opt.key_size = atoi(keysize); + opt.key_size = (opt.key_size ? : DEFAULT_KEY_SIZE) / 8; + } + } + if (offset) + { + if (!isdigit(*offset)) + r = ERR_MNTCRYPT_OFFSET; + else + opt.offset = atoi(offset); + } + if (skip) + { + if (!isdigit(*skip)) + r = ERR_MNTCRYPT_SKIP; + else + opt.skip = atoi(skip); + } + if (!r) + r = crypt_create_device(&opt); + } + if (spec && opt.name) + { + sz = strlen(dir)+strlen(opt.name)+2; + *spec = (char *) malloc(sz); + snprintf(*spec, sz, "%s/%s", dir, opt.name); + } + if (opt.device) + free((void *) opt.device); + if (opt.name) + free((void *) opt.name); + return r; +} + +/* + * remove mapped device + * note: "name" is full path mapped device or name of mapping only. + */ +int +mntcrypt_close(const char *name) +{ + struct crypt_options opt; + const char *dir = crypt_get_dir(); + int len; + + if (!dir) + return ERR_MNTCRYPT_DIR; + len = strlen(dir); + memset(&opt, 0, sizeof(struct crypt_options)); + + if (strncmp(dir, name, len)==0 && *(name+len)=='/') + /* /dev/mapper/ */ + opt.name = name+len+1; + else if (strncmp("/dev/", name, 5)==0 && strrchr(name, '/')==(name+4)) + /* /dev/ */ + opt.name = name+5; + else if (strchr(name, '/')) + /* any strange path */ + return ERR_MNTCRYPT_NAME; + else + /* alone name of mapping */ + opt.name = name; + + return crypt_remove_device(&opt); +} + --- util-linux-2.13-pre6/mount/mount.c.cryptsetup 2005-08-14 17:16:33.000000000 +0200 +++ util-linux-2.13-pre6/mount/mount.c 2006-02-06 17:35:12.000000000 +0100 @@ -44,6 +44,10 @@ #include "setproctitle.h" #endif +#ifdef HAVE_LIBCRYPTSETUP +#include "cryptsetup.h" +#endif + /* True for fake mount (-f). */ static int fake = 0; @@ -97,6 +101,9 @@ #define MS_USERS 0x40000000 #define MS_USER 0x20000000 #define MS_OWNER 0x10000000 +#ifdef HAVE_LIBCRYPTSETUP +# define MS_CRYPT 0x00040000 +#endif #define MS_GROUP 0x08000000 #define MS_COMMENT 0x00020000 #define MS_LOOP 0x00010000 @@ -164,12 +171,21 @@ { "diratime", 0, 1, MS_NODIRATIME }, /* Update dir access times */ { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */ #endif +#ifdef HAVE_LIBCRYPTSETUP + { "crypt", 0, 0, MS_CRYPT }, /* Cryptsetup */ +#endif { NULL, 0, 0, 0 } }; static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption, *opt_speed, *opt_comment; +#ifdef HAVE_LIBCRYPTSETUP +/* note: cryptsetup uses the "offsett" option too */ +static const char *opt_device, *opt_keyfile, *opt_keysize, *opt_cipher, + *opt_hash, *opt_skip; +#endif + static struct string_opt_map { char *tag; int skip; @@ -178,9 +194,17 @@ { "loop=", 0, &opt_loopdev }, { "vfs=", 1, &opt_vfstype }, { "offset=", 0, &opt_offset }, - { "encryption=", 0, &opt_encryption }, + { "encryption=", 0, &opt_encryption }, /* cryptoloop -- deprecated */ { "speed=", 0, &opt_speed }, { "comment=", 1, &opt_comment }, +#ifdef HAVE_LIBCRYPTSETUP + { "device=", 0, &opt_device }, /* cryptsetup device */ + { "keyfile=", 1, &opt_keyfile }, + { "keysize=", 1, &opt_keysize }, + { "cipher=", 1, &opt_cipher }, + { "hash=", 1, &opt_hash }, + { "skip=", 1, &opt_skip }, +#endif { NULL, 0, NULL } }; @@ -642,6 +666,42 @@ return 0; } +#ifdef HAVE_LIBCRYPTSETUP +static int +crypt_check(const char **spec, int *flags, int loop) +{ + const char *device = opt_device; + int r; + + if (!(*flags & MS_CRYPT)) + return 0; + + if (loop) { + if (opt_device) { + /* mount -o loop,crypt,device=/dev/foo */ + free((void *) opt_device); + opt_device = NULL; + } + device = *spec; /* in the spec is initialized loop device name */ + } + + if ((r = mntcrypt_open((char **) spec, flags, device, opt_keyfile, + opt_keysize, opt_cipher, opt_hash, opt_skip, opt_offset))) + { + char buf[BUFSIZ]; + mntcrypt_get_error(r, buf, sizeof buf); + error(buf); + if (verbose) + printf(_("mount: failed setting up encrypted device\n")); + return EX_FAIL; + } + if (verbose) + printf(_("mount: setup crypt device successfully\n")); + + return 0; +} +#endif + static void update_mtab_entry(const char *spec, const char *node, const char *type, const char *opts, int flags, int freq, int pass) { @@ -791,7 +851,6 @@ const char *loopdev = 0, *loopfile = 0; struct stat statbuf; int nfs_mount_version = 0; /* any version */ - /* copies for freeing on exit */ const char *opts1, *spec1, *node1, *types1, *extra_opts1; @@ -820,9 +879,18 @@ * stale assignments of files to loop devices. Nasty when used for * encryption. */ +#ifdef HAVE_LIBCRYPTSETUP res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile); + if (res==0) { + res = crypt_check(&spec, &flags, loop); + if (res && loop) + del_loop(spec); + } +#else + res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile); +#endif if (res) - goto out; + goto out; } /* @@ -874,6 +942,14 @@ mnt_err = errno; +#ifdef HAVE_LIBCRYPTSETUP + if ((flags & MS_CRYPT) && spec) + { + if (verbose) + printf(_("mount: unmapping encrypted device due mount error.\n")); + mntcrypt_close(spec); + } +#endif if (loop) del_loop(spec); --- util-linux-2.13-pre6/mount/Makefile.am.cryptsetup 2005-09-12 22:41:11.000000000 +0200 +++ util-linux-2.13-pre6/mount/Makefile.am 2006-02-06 17:31:52.000000000 +0100 @@ -37,6 +37,18 @@ man_MANS += pivot_root.8 endif +if HAVE_CRYPTSETUP +mount_SOURCES += cryptsetup.c +umount_SOURCES += cryptsetup.c +swapon_SOURCES += cryptsetup.c +mount_LDADD += -lcryptsetup +umount_LDADD += -lcryptsetup +if HAVE_BLKID +swapon_LDADD += -lcryptsetup +else +swapon_LDADD = -lcryptsetup +endif +endif swapon.c: swapargs.h