diff -Naur util-linux-2.11r-o/mount/lomount.c util-linux-2.11r/mount/lomount.c --- util-linux-2.11r-o/mount/lomount.c Mon Jul 9 16:10:58 2001 +++ util-linux-2.11r/mount/lomount.c Mon Jul 9 16:19:24 2001 @@ -6,6 +6,11 @@ * - added Native Language Support * Sun Mar 21 1999 - Arnaldo Carvalho de Melo * - fixed strerr(errno) in gettext calls + * 2000-09-24 Marc Mutz + * - added long option names and the --pass-fd option to pass + * passphrases via fd's to losetup/mount. Used for encryption in + * non-interactive environments. The idea behind xgetpass() is stolen + * from GnuPG, v.1.0.3 (http://www.gnupg.org/). */ #define PROC_DEVICES "/proc/devices" @@ -206,12 +211,50 @@ 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) +{ + if (pfd < 0) /* terminal */ + return (getpass(prompt)); + else { /* file descriptor */ + char *pass = NULL; + int buflen, i; + + 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 _now_. */ + error("not enough 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; + } + } +} + #define HASHLENGTH 20 #define PASSWDBUFFLEN 130 /* getpass returns only max. 128 bytes, see man getpass */ int set_loop (const char *device, const char *file, int offset, - const char *encryption, int *loopro) { + const char *encryption, int pfd, int *loopro) { struct loop_info loopinfo; int fd, ffd, mode, i; int keylength; @@ -262,17 +305,19 @@ loopinfo.lo_encrypt_key_size = 0; break; case LO_CRYPT_XOR: - pass = getpass (_("Password: ")); + /* WARNING: xgetpass() can return massive amounts of data, + * not only 128 bytes like the original getpass(3) */ + pass = xgetpass (pfd,_("Password: ")); xstrncpy (loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE); loopinfo.lo_encrypt_key_size = strlen(loopinfo.lo_encrypt_key); break; case LO_CRYPT_DES: printf(_("WARNING: Use of DES is depreciated.\n")); - pass = getpass (_("Password: ")); + pass = xgetpass (pfd,_("Password: ")); strncpy (loopinfo.lo_encrypt_key, pass, 8); loopinfo.lo_encrypt_key[8] = 0; loopinfo.lo_encrypt_key_size = 8; - pass = getpass (_("Init (up to 16 hex digits): ")); + pass = xgetpass (pfd,_("Init (up to 16 hex digits): ")); for (i = 0; i < 16 && pass[i]; i++) if (isxdigit (pass[i])) { loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ? @@ -293,7 +338,7 @@ case LO_CRYPT_RC6: case LO_CRYPT_DES_EDE3: case LO_CRYPT_DFC: - pass = getpass("Password :"); + pass = xgetpass(pfd,"Password :"); strncpy(passwdbuff+1,pass,PASSWDBUFFLEN-1); passwdbuff[0] = 'A'; rmd160_hash_buffer(keybits,pass,strlen(pass)); @@ -361,7 +406,7 @@ int set_loop (const char *device, const char *file, int offset, - const char *encryption, int *loopro) { + const char *encryption, int pfd, int *loopro) { mutter(); return 1; } @@ -390,20 +435,34 @@ int verbose = 0; static char *progname; +static struct option longopts[] = { + { "delete", 0, 0, 'd' }, + { "detach", 0, 0, 'd' }, + { "encryption", 1, 0, 'e' }, + { "help", 0, 0, 'h' }, + { "offset", 1, 0, 'o' }, + { "pass-fd", 1, 0, 'p' }, + { "verbose", 0, 0, 'v' }, + { NULL, 0, 0, 0 } +}; + + static void usage(void) { - struct crypt_type_struct *c; fprintf(stderr, _("usage:\n\ %s loop_device # give info\n\ %s -d loop_device # delete\n\ - %s [ -e encryption ] [ -o offset ] loop_device file # setup\n"), + %s [ options ] loop_device file # setup\n\ + where options include\n\ + --offset , -o \n\ + start at offset into file.\n\ + --pass-fd , -p \n\ + read passphrase from file descriptor \n\ + instead of the terminal.\n\ + --encryption , -e \n\ + encrypt with .\n\ + Check /proc/crypto/cipher for available ciphers.\n"), progname, progname, progname); - fprintf(stderr, " where encryption is one of:\n"); - c = &crypt_type_tbl[0]; - while(c->name) { - fprintf(stderr, " %s\n", c->name); - c++; - } exit(1); } @@ -436,8 +495,9 @@ int main(int argc, char **argv) { - char *offset, *encryption; + char *offset, *encryption, *passfd; int delete,off,c; + int pfd = -1; int res = 0; int ro = 0; @@ -446,9 +506,10 @@ textdomain(PACKAGE); delete = off = 0; - offset = encryption = NULL; + offset = encryption = passfd = NULL; progname = argv[0]; - while ((c = getopt(argc,argv,"de:o:v")) != -1) { + while ((c = getopt_long(argc,argv,"de:ho:p:v", + longopts, NULL)) != -1) { switch (c) { case 'd': delete = 1; @@ -459,6 +520,9 @@ case 'o': offset = optarg; break; + case 'p': + passfd = optarg; + break; case 'v': verbose = 1; break; @@ -467,7 +531,7 @@ } } if (argc == 1) usage(); - if ((delete && (argc != optind+1 || encryption || offset)) || + if ((delete && (argc != optind+1 || encryption || offset || passfd)) || (!delete && (argc < optind+1 || argc > optind+2))) usage(); if (argc == optind+1) { @@ -478,7 +542,9 @@ } else { if (offset && sscanf(offset,"%d",&off) != 1) usage(); - res = set_loop(argv[optind],argv[optind+1],off,encryption,&ro); + if (passfd && sscanf(passfd,"%d",&pfd) != 1) + usage(); + res = set_loop(argv[optind],argv[optind+1],off,encryption,pfd,&ro); } return res; } diff -Naur util-linux-2.11g-o/mount/lomount.h util-linux-2.11g/mount/lomount.h --- util-linux-2.11g-o/mount/lomount.h Fri Dec 8 19:08:02 2000 +++ util-linux-2.11g/mount/lomount.h Mon Jul 9 16:11:38 2001 @@ -1,5 +1,5 @@ extern int verbose; -extern int set_loop (const char *, const char *, int, const char *, int *); +extern int set_loop (const char *, const char *, int, const char *, int, int *); extern int del_loop (const char *); extern int is_loop_device (const char *); extern char * find_unused_loop_device (void); diff -Naur util-linux-2.11g-o/mount/losetup.8 util-linux-2.11g/mount/losetup.8 --- util-linux-2.11g-o/mount/losetup.8 Mon Jul 9 16:10:58 2001 +++ util-linux-2.11g/mount/losetup.8 Mon Jul 9 16:11:38 2001 @@ -10,6 +10,9 @@ ] [ .B \-o .I offset +] [ +.B \-p +.I num ] .I loop_device file .br @@ -26,9 +29,9 @@ \fIloop_device\fP argument is given, the status of the corresponding loop device is shown. .SH OPTIONS -.IP \fB\-d\fP +.IP "\fB\-\-delete, \-\-detach, \-d\fP" detach the file or device associated with the specified loop device. -.IP "\fB\-e \fIencryption\fP" +.IP "\fB\-\-encryption, \-e \fIencryption\fP" .RS enable data encryption. The following keywords are recognized: .IP \fBNONE\fP @@ -79,9 +82,12 @@ enabled in the Crypto API. .PD .RE -.IP "\fB\-o \fIoffset\fP" +.IP "\fB\-\-offset, \-o \fIoffset\fP" the data start is moved \fIoffset\fP bytes into the specified file or device. +.IP "\fB\-\-pass-fd, \-p \fInum\fP" +read the passphrase from file descriptor \fInum\fP instead of the +terminal. .SH RETURN VALUE .B losetup returns 0 on success, nonzero on failure. When diff -Naur util-linux-2.11g-o/mount/mount.8 util-linux-2.11g/mount/mount.8 --- util-linux-2.11g-o/mount/mount.8 Wed Jun 27 01:19:12 2001 +++ util-linux-2.11g/mount/mount.8 Mon Jul 9 16:11:38 2001 @@ -248,6 +248,12 @@ .B \-v Verbose mode. .TP +.B \-p "\fInum\fP" +If the mount requires a passphrase to be entered, read it from file +descriptor +.IR num\fP +instead of from the terminal. +.TP .B \-a Mount all filesystems (of the given types) mentioned in .IR fstab . @@ -1475,7 +1481,10 @@ .BR loop ", " offset " and " encryption , that are really options to .BR losetup (8). -If no explicit loop device is mentioned +If the mount requires a passphrase, you will be prompted for one unless +you specify a file descriptor to read from instead with the +.BR \-\-pass-fd +option. If no explicit loop device is mentioned (but just an option `\fB\-o loop\fP' is given), then .B mount will try to find some unused loop device and use that. diff -Naur util-linux-2.11r-o/mount/mount.c util-linux-2.11r/mount/mount.c --- util-linux-2.11r-o/mount/mount.c Fri Jun 8 01:24:28 2001 +++ util-linux-2.11r/mount/mount.c Mon Jul 9 16:22:13 2001 @@ -108,6 +108,9 @@ /* True if ruid != euid. */ static int suid = 0; +/* Contains the fd no. to read the passphrase from, if any */ +static int pfd = -1; + /* Map from -o and fstab option strings to the flag argument to mount(2). */ struct opt_map { const char *opt; /* option name */ @@ -587,7 +590,7 @@ if (verbose) 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, &loopro)) { + if (set_loop (*loopdev, *loopfile, offset, opt_encryption, pfd, &loopro)) { if (verbose) printf(_("mount: failed setting up loop device\n")); return EX_FAIL; @@ -1305,6 +1308,7 @@ { "read-write", 0, 0, 'w' }, { "rw", 0, 0, 'w' }, { "options", 1, 0, 'o' }, + { "pass-fd", 1, 0, 'p' }, { "test-opts", 1, 0, 'O' }, { "types", 1, 0, 't' }, { "bind", 0, 0, 128 }, @@ -1337,7 +1341,7 @@ " mount --bind olddir newdir\n" "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n" "or by label, using -L label or by uuid, using -U uuid .\n" - "Other options: [-nfFrsvw] [-o options].\n" + "Other options: [-nfFrsvw] [-o options] [-p num].\n" "For many more details, say man 8 mount .\n" )); /* @@ -1353,6 +1357,7 @@ int c, result = 0, specseen; char *options = NULL, *spec, *node; char *volumelabel = NULL; + char *passfd = NULL; char *uuid = NULL; char *types = NULL; struct mntentchn *mc; @@ -1374,7 +1379,7 @@ initproctitle(argc, argv); #endif - while ((c = getopt_long (argc, argv, "afFhlL:no:O:rsU:vVwt:", + while ((c = getopt_long (argc, argv, "afFhlL:no:O:p:rsU:vVwt:", longopts, NULL)) != -1) { switch (c) { case 'a': /* mount everything in fstab */ @@ -1408,6 +1413,9 @@ readonly = 1; readwrite = 0; break; + case 'p': /* read passphrase from given fd */ + passfd = optarg; + break; case 's': /* allow sloppy mount options */ sloppy = 1; break; @@ -1491,6 +1499,9 @@ printf(_("mount: mounting %s\n"), spec); } else spec = NULL; /* just for gcc */ + + if (passfd && sscanf(passfd,"%d",&pfd) != 1) + die (EX_USAGE, _("mount: argument to --pass-fd or -p must be a number")); switch (argc+specseen) { case 0: