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.

514 lines
14 KiB

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