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.

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