mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

495 lines
14 KiB

  1. --- util-linux-2.12/mount/mount.8.orig 2003-09-21 18:14:26.000000000 -0400
  2. +++ util-linux-2.12/mount/mount.8 2003-09-21 18:16:18.000000000 -0400
  3. @@ -1696,6 +1696,11 @@
  4. .BR loop ", " offset " and " encryption ,
  5. that are really options to
  6. .BR losetup (8).
  7. +You can also use the
  8. +.BR keygen
  9. +option to have mount call an external program from, which it will read the
  10. +encryption key. Arguments to this program can be given, separated by semicolons.
  11. +
  12. If no explicit loop device is mentioned
  13. (but just an option `\fB\-o loop\fP' is given), then
  14. .B mount
  15. --- util-linux-2.12/mount/mount.c.orig 2003-09-21 18:14:27.000000000 -0400
  16. +++ util-linux-2.12/mount/mount.c 2003-09-21 18:16:18.000000000 -0400
  17. @@ -195,7 +195,7 @@
  18. };
  19. static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
  20. - *opt_speed;
  21. + *opt_keygen, *opt_speed;
  22. static struct string_opt_map {
  23. char *tag;
  24. @@ -206,6 +206,7 @@
  25. { "vfs=", 1, &opt_vfstype },
  26. { "offset=", 0, &opt_offset },
  27. { "encryption=", 0, &opt_encryption },
  28. + { "keygen=", 0, &opt_keygen },
  29. { "speed=", 0, &opt_speed },
  30. { NULL, 0, NULL }
  31. };
  32. @@ -586,7 +587,7 @@
  33. *type = opt_vfstype;
  34. }
  35. - *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption);
  36. + *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption || opt_keygen);
  37. *loopfile = *spec;
  38. if (*loop) {
  39. @@ -596,6 +597,11 @@
  40. printf(_("mount: skipping the setup of a loop device\n"));
  41. } else {
  42. int loopro = (*flags & MS_RDONLY);
  43. + /* Extra args to the keygen program. Right now there are 2: *
  44. + * - the looped file *
  45. + * - the encryption type used */
  46. + char *keygen_args[] = {*loopfile, opt_encryption};
  47. + const int _n_keygen_args = 2;
  48. if (!*loopdev || !**loopdev)
  49. *loopdev = find_unused_loop_device();
  50. @@ -604,6 +610,8 @@
  51. if (verbose)
  52. printf(_("mount: going to use the loop device %s\n"), *loopdev);
  53. offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0;
  54. + if (opt_keygen)
  55. + pfd = use_keygen_prog(opt_keygen, keygen_args, _n_keygen_args);
  56. if (set_loop(*loopdev, *loopfile, offset,
  57. opt_encryption, pfd, &loopro)) {
  58. if (verbose)
  59. --- util-linux-2.12/mount/lomount.c.orig 2003-09-21 18:14:26.000000000 -0400
  60. +++ util-linux-2.12/mount/lomount.c 2003-09-21 18:43:27.000000000 -0400
  61. @@ -10,7 +10,6 @@
  62. * 2000-09-24 Marc Mutz <Marc@Mutz.com>
  63. * - added -p option to pass passphrases via fd's to losetup/mount.
  64. * Used for encryption in non-interactive environments.
  65. - * The idea behind xgetpass() is stolen from GnuPG, v.1.0.3.
  66. */
  67. #define LOOPMAJOR 7
  68. @@ -24,12 +23,16 @@
  69. #include <ctype.h>
  70. #include <fcntl.h>
  71. #include <errno.h>
  72. +#include <limits.h>
  73. #include <stdlib.h>
  74. #include <unistd.h>
  75. +#include <sys/types.h>
  76. #include <sys/ioctl.h>
  77. #include <sys/stat.h>
  78. #include <sys/mman.h>
  79. #include <sys/sysmacros.h>
  80. +#include <regex.h>
  81. +#include <signal.h>
  82. #include "loop.h"
  83. #include "lomount.h"
  84. @@ -38,6 +41,7 @@
  85. extern int verbose;
  86. extern char *xstrdup (const char *s); /* not: #include "sundries.h" */
  87. +extern void *xmalloc (size_t size); /* idem */
  88. extern void error (const char *fmt, ...); /* idem */
  89. #ifdef LOOP_SET_FD
  90. @@ -198,43 +202,113 @@
  91. return 0;
  92. }
  93. -/*
  94. - * A function to read the passphrase either from the terminal or from
  95. - * an open file descriptor.
  96. - */
  97. -static char *
  98. -xgetpass(int pfd, const char *prompt) {
  99. - char *pass;
  100. - int buflen, i;
  101. -
  102. - if (pfd < 0) /* terminal */
  103. - return getpass(prompt);
  104. -
  105. - pass = NULL;
  106. - buflen = 0;
  107. - for (i=0; ; i++) {
  108. - if (i >= buflen-1) {
  109. - /* we're running out of space in the buffer.
  110. - * Make it bigger: */
  111. - char *tmppass = pass;
  112. - buflen += 128;
  113. - pass = realloc(tmppass, buflen);
  114. - if (pass == NULL) {
  115. - /* realloc failed. Stop reading. */
  116. - error("Out of memory while reading passphrase");
  117. - pass = tmppass; /* the old buffer hasn't changed */
  118. +/* A function to check the encryption parameters against /proc/crypto. *
  119. + * Returns 1 if everything checks out, 0 if there's any problem. *
  120. + * The purpose of this function is not so much to verify the parameters *
  121. + * before setting up the loop device; that task is made difficult by *
  122. + * the possibility of loadable encryption modules and the necessity of *
  123. + * falling back to the old (kerneli.org) CryptoAPI. Rather the intent *
  124. + * is to come up with a more useful error message after the setup *
  125. + * fails. Thus we return 1 in the event that some system error prevents *
  126. + * us from getting the info we want from /proc/crypto. */
  127. +static int
  128. +check_crypto(struct loop_info64 *loopinfo64) {
  129. + char *s = xmalloc(LINE_MAX), *name = xmalloc(LINE_MAX),
  130. + cipher_name[LO_NAME_SIZE+1];
  131. + int cipher_found = 0, min_size = 0, max_size = 0, retval;
  132. + FILE *fp;
  133. + struct stat st;
  134. +
  135. + if (stat("/proc/crypto", &st) == -1) {
  136. + retval = 1;
  137. + goto end;
  138. + } else if (S_ISDIR(st.st_mode)) {
  139. + /* Hm... must be using the old CryptoAPI. */
  140. + retval = 1;
  141. + goto end;
  142. + } else if ((fp = fopen("/proc/crypto", "r")) == NULL) {
  143. + retval = 1;
  144. + goto end;
  145. + }
  146. +
  147. + xstrncpy(cipher_name, loopinfo64->lo_crypt_name, LO_NAME_SIZE);
  148. + /* Chop off the cipher mode (ie. everything after the dash) */
  149. + cipher_name[strcspn(cipher_name, "-")] = '\0';
  150. +
  151. + while (fgets(s, LINE_MAX, fp) != NULL) {
  152. + if (sscanf(s, "name : %s", name) > 0) {
  153. + if (strcmp(name, cipher_name) == 0)
  154. + cipher_found = 1;
  155. + else if (cipher_found)
  156. break;
  157. - }
  158. + } else {
  159. + sscanf(s, "min keysize : %d", &min_size);
  160. + sscanf(s, "max keysize : %d", &max_size);
  161. }
  162. - if (read(pfd, pass+i, 1) != 1 || pass[i] == '\n')
  163. - break;
  164. - }
  165. - if (pass == NULL)
  166. - return "";
  167. - else {
  168. - pass[i] = 0;
  169. - return pass;
  170. }
  171. + fclose(fp);
  172. +
  173. + if (!cipher_found) {
  174. + fprintf(stderr, _("Invalid cipher \"%s\"\n"), cipher_name);
  175. + retval = 0;
  176. + goto end;
  177. + } else if (loopinfo64->lo_encrypt_key_size < min_size ||
  178. + loopinfo64->lo_encrypt_key_size > max_size) {
  179. + fprintf(stderr, _("Invalid key length (%d) for %s cipher\n"),
  180. + loopinfo64->lo_encrypt_key_size, cipher_name);
  181. + retval = 0;
  182. + goto end;
  183. + }
  184. +
  185. + retval = 1;
  186. +end:
  187. + free(s);
  188. + free(name);
  189. + return retval;
  190. +}
  191. +
  192. +/* Same thing, for the old CryptoAPI. */
  193. +static int
  194. +check_crypto_old(struct loop_info *loopinfo) {
  195. + char *s = xmalloc(LINE_MAX), *name = xmalloc(PATH_MAX+1),
  196. + cipher_name[LO_NAME_SIZE+1];
  197. + int mask = 0, retval;
  198. + FILE *fp;
  199. + struct stat st;
  200. +
  201. + if (stat("/proc/crypto/cipher", &st) == -1) {
  202. + retval = 1;
  203. + goto end;
  204. + } else if (!S_ISDIR(st.st_mode)) {
  205. + retval = 1;
  206. + goto end;
  207. + }
  208. +
  209. + xstrncpy(cipher_name, loopinfo->lo_name, LO_NAME_SIZE);
  210. + snprintf(name, PATH_MAX+1, "/proc/crypto/cipher/%s", cipher_name);
  211. + if ((fp = fopen(name, "r")) == NULL) {
  212. + fprintf(stderr, _("Invalid cipher \"%s\"\n"), cipher_name);
  213. + retval = 0;
  214. + goto end;
  215. + }
  216. +
  217. + while (fgets(s, LINE_MAX, fp) != NULL) {
  218. + sscanf(s, "keysize_mask : %i", &mask);
  219. + }
  220. + fclose(fp);
  221. +
  222. + if (!(mask & (1 << (loopinfo->lo_encrypt_key_size - 1)))) {
  223. + fprintf(stderr, _("Invalid key length (%d) for %s cipher\n"),
  224. + loopinfo->lo_encrypt_key_size, cipher_name);
  225. + retval = 0;
  226. + goto end;
  227. + }
  228. +
  229. + retval = 1;
  230. +end:
  231. + free(s);
  232. + free(name);
  233. + return retval;
  234. }
  235. static int
  236. @@ -275,9 +349,40 @@
  237. if (digits_only(encryption)) {
  238. loopinfo64.lo_encrypt_type = atoi(encryption);
  239. } else {
  240. + regex_t keysize_re;
  241. + regmatch_t keysize_rm;
  242. + int rerror;
  243. + char *rerror_buf, *encryption_dup = xstrdup(encryption);
  244. +
  245. loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
  246. +
  247. + if ((rerror = regcomp(&keysize_re, "-[[:digit:]]+$",
  248. + REG_EXTENDED)) != 0) {
  249. + fprintf(stderr, _("RE error: "));
  250. + rerror_buf = xmalloc(LINE_MAX+1);
  251. + regerror(rerror, &keysize_re, rerror_buf, LINE_MAX);
  252. + fprintf(stderr, "%s\n", rerror_buf);
  253. + free(rerror_buf);
  254. + return -1;
  255. + }
  256. + rerror = regexec(&keysize_re, encryption_dup,
  257. + 1, &keysize_rm, 0);
  258. + regfree(&keysize_re);
  259. + if (rerror) {
  260. + fprintf(stderr,
  261. + _("You must specify a key size (in bits) "
  262. + "for use with CryptoAPI encryption.\n"));
  263. + return -1;
  264. + }
  265. +
  266. + /* convert the key size from #bits to #bytes */
  267. + loopinfo64.lo_encrypt_key_size =
  268. + atoi(encryption_dup + keysize_rm.rm_so + 1) / 8;
  269. + /* now cut off the key size */
  270. + encryption_dup[keysize_rm.rm_so] = '\0';
  271. snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE,
  272. - "%s", encryption);
  273. + "%s", encryption_dup);
  274. + free(encryption_dup);
  275. }
  276. }
  277. @@ -307,9 +412,25 @@
  278. strlen(loopinfo64.lo_encrypt_key);
  279. break;
  280. default:
  281. - pass = xgetpass(pfd, _("Password: "));
  282. - xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
  283. - loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
  284. + if (pfd == -1) {
  285. + pass = getpass(_("Password: "));
  286. + xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
  287. + } else {
  288. + /* If we're reading from an extenral program, *
  289. + * odds are good that a SIGCHLD will interrupt *
  290. + * this read(), and ruin our whole day. So we *
  291. + * must block it. */
  292. + sigset_t ss, oss;
  293. + sigemptyset(&ss);
  294. + sigaddset(&ss, SIGCHLD);
  295. + sigprocmask(SIG_BLOCK, &ss, &oss);
  296. + if (read(pfd, loopinfo64.lo_encrypt_key,
  297. + LO_KEY_SIZE) == -1) {
  298. + perror("read");
  299. + fprintf(stderr, _("Error reading encryption key, exiting\n"));
  300. + }
  301. + sigprocmask(SIG_SETMASK, &oss, NULL);
  302. + }
  303. }
  304. if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
  305. @@ -322,6 +443,14 @@
  306. struct loop_info loopinfo;
  307. int errsv = errno;
  308. + if (errno == EINVAL &&
  309. + loopinfo64.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
  310. + if (!check_crypto(&loopinfo64)) {
  311. + fprintf(stderr,
  312. + _("Error in crypto parameters, exiting\n"));
  313. + goto fail;
  314. + }
  315. +
  316. errno = loop_info64_to_old(&loopinfo64, &loopinfo);
  317. if (errno) {
  318. errno = errsv;
  319. @@ -330,6 +459,17 @@
  320. }
  321. if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
  322. + errsv = errno;
  323. +
  324. + if (errno == EINVAL &&
  325. + loopinfo.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
  326. + if (!check_crypto_old(&loopinfo)) {
  327. + fprintf(stderr,
  328. + _("Error in crypto parameters, exiting\n"));
  329. + goto fail;
  330. + }
  331. +
  332. + errno = errsv;
  333. perror("ioctl: LOOP_SET_STATUS");
  334. goto fail;
  335. }
  336. @@ -416,6 +556,22 @@
  337. exit(1);
  338. }
  339. +void *
  340. +xmalloc (size_t size) {
  341. + void *t;
  342. +
  343. + if (size == 0)
  344. + return NULL;
  345. +
  346. + t = malloc (size);
  347. + if (t == NULL) {
  348. + fprintf(stderr, _("not enough memory"));
  349. + exit(1);
  350. + }
  351. +
  352. + return t;
  353. +}
  354. +
  355. char *
  356. xstrdup (const char *s) {
  357. char *t;
  358. --- util-linux-2.12/mount/sundries.c.orig 2003-09-21 18:14:27.000000000 -0400
  359. +++ util-linux-2.12/mount/sundries.c 2003-09-21 18:16:18.000000000 -0400
  360. @@ -12,6 +12,8 @@
  361. #include <stdio.h>
  362. #include <string.h>
  363. #include <mntent.h> /* for MNTTYPE_SWAP */
  364. +#include <sys/types.h>
  365. +#include <sys/wait.h>
  366. #include "fstab.h"
  367. #include "sundries.h"
  368. #include "realpath.h"
  369. @@ -285,3 +287,100 @@
  370. free(canonical);
  371. return xstrdup(path);
  372. }
  373. +
  374. +static volatile int keygen_wait = 1;
  375. +
  376. +/* Handle a SIGCHLD -- wait for the child process */
  377. +static void
  378. +child_handler (int i) {
  379. + int status;
  380. + if (keygen_wait && wait(&status) != -1) {
  381. + keygen_wait = 0;
  382. + if (WEXITSTATUS(status) != 0)
  383. + exit(WEXITSTATUS(status));
  384. + }
  385. +}
  386. +
  387. +/* Make sure we clean up after the child */
  388. +static void
  389. +child_cleanup (void) {
  390. + /* "Clean up" means wait. So we let child_handler do all the work */
  391. + while (keygen_wait)
  392. + sleep(1);
  393. +}
  394. +
  395. +/* Split a string into pieces, using delim as the delimiter. *
  396. + * Returns the number of pieces. */
  397. +static int
  398. +split_args (char *args[], const char *str, const char *delim, int nargs) {
  399. + int i=0;
  400. + char *s = xstrdup(str);
  401. + args[0] = strtok(s, delim);
  402. + if (args[0] == NULL)
  403. + return 0;
  404. +
  405. + while (++i < nargs) {
  406. + if ((args[i] = strtok(NULL, delim)) == NULL)
  407. + break;
  408. + }
  409. +
  410. + return i;
  411. +}
  412. +
  413. +#define KEYGEN_MAX_ARGS 64 /* more than anyone will need, right? */
  414. +
  415. +/* Call an external program to give us the encryption key for an *
  416. + * encrypted device. We split the string s into a command and args on *
  417. + * semicolons ('cuz you can't put spaces in the fs_mntopts field), then *
  418. + * add some specific args (eg. the looped file or device, the *
  419. + * encryption method used; check the caller to see the actual list). *
  420. + * Returns a file descriptor from which we read the key. */
  421. +int
  422. +use_keygen_prog (const char *s, const char *addl_args[], int naddl_args) {
  423. + int fd[2];
  424. + pid_t keygen_pid;
  425. + struct sigaction sa;
  426. + sa.sa_handler = child_handler;
  427. + sa.sa_flags = SA_NOCLDSTOP;
  428. +
  429. + if (pipe(fd) == -1) {
  430. + perror("pipe");
  431. + exit(EX_SYSERR);
  432. + }
  433. + if (sigaction(SIGCHLD, &sa, NULL) == -1) {
  434. + perror("sigaction");
  435. + exit(EX_SYSERR);
  436. + }
  437. + if ((keygen_pid = fork()) == -1) {
  438. + perror("fork");
  439. + exit(EX_SYSERR);
  440. + } else if (keygen_pid) { /* parent */
  441. + atexit(child_cleanup);
  442. + close(fd[1]);
  443. + return fd[0];
  444. + } else { /* child */
  445. + char *args[KEYGEN_MAX_ARGS+1];
  446. + int i, n = split_args(args, s, ";", KEYGEN_MAX_ARGS - naddl_args);
  447. + if (!n) {
  448. + fprintf(stderr, _("Invalid keygen program, exiting\n"));
  449. + exit(EX_USAGE);
  450. + }
  451. + for(i=0; i < naddl_args && n+i < KEYGEN_MAX_ARGS; i++)
  452. + args[n+i] = (char *) addl_args[i];
  453. + args[n+i] = NULL;
  454. +
  455. + close(fd[0]);
  456. + if (dup2(fd[1], STDOUT_FILENO) == -1) {
  457. + perror("dup2");
  458. + exit(EX_SYSERR);
  459. + }
  460. + setuid(getuid()); /* set euid to ruid */
  461. + if (execvp(args[0], args) == -1) {
  462. + perror(args[0]);
  463. + exit(EX_USAGE);
  464. + }
  465. + }
  466. +
  467. + return 0; /* so gcc will shut up */
  468. +}
  469. +
  470. --- util-linux-2.12/mount/sundries.h.orig 2003-09-21 18:14:27.000000000 -0400
  471. +++ util-linux-2.12/mount/sundries.h 2003-09-21 18:16:18.000000000 -0400
  472. @@ -25,6 +25,7 @@
  473. void error (const char *fmt, ...);
  474. int matching_type (const char *type, const char *types);
  475. int matching_opts (const char *options, const char *test_opts);
  476. +int use_keygen_prog (const char *s, const char *addl_args[], int naddl_args);
  477. void *xmalloc (size_t size);
  478. char *xstrdup (const char *s);
  479. char *xstrndup (const char *s, int n);