X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcryptsetup%2Fcryptsetup-generator.c;h=81b770890a170510ad31ff6a5b38e12fb4e66902;hb=97d0e5f83ba4dd713170f802b90149b7325bc992;hp=8959bf51c8c72fb757ac93c14d003d20c5caf170;hpb=e32530cbef746a3d346334a821a7c804f49af4e6;p=elogind.git diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 8959bf51c..81b770890 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -70,8 +70,8 @@ static int create_disk( const char *password, const char *options) { - char _cleanup_free_ *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL; - FILE _cleanup_fclose_ *f = NULL; + _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL; + _cleanup_fclose_ FILE *f = NULL; bool noauto, nofail; assert(name); @@ -102,29 +102,44 @@ static int create_disk( return -errno; } - fprintf(f, + fputs( "# Automatically generated by systemd-cryptsetup-generator\n\n" "[Unit]\n" - "Description=Cryptography Setup for %%I\n" + "Description=Cryptography Setup for %I\n" "Documentation=man:systemd-cryptsetup@.service(8) man:crypttab(5)\n" "SourcePath=/etc/crypttab\n" "Conflicts=umount.target\n" "DefaultDependencies=no\n" - "BindsTo=%s dev-mapper-%%i.device\n" - "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n" - "Before=umount.target\n", - d, d); + "BindsTo=dev-mapper-%i.device\n" + "After=systemd-readahead-collect.service systemd-readahead-replay.service\n", + f); if (!nofail) fprintf(f, "Before=cryptsetup.target\n"); - if (password && (streq(password, "/dev/urandom") || - streq(password, "/dev/random") || - streq(password, "/dev/hw_random"))) - fputs("After=systemd-random-seed-load.service\n", f); + if (password) { + if (streq(password, "/dev/urandom") || + streq(password, "/dev/random") || + streq(password, "/dev/hw_random")) + fputs("After=systemd-random-seed-load.service\n", f); + else if (!streq(password, "-") && + !streq(password, "none")) + fprintf(f, + "RequiresMountsFor=%s\n", + password); + } + + if (is_device_path(u)) + fprintf(f, + "BindsTo=%s\n" + "After=%s\n" + "Before=umount.target\n", + d, d); else - fputs("Before=local-fs.target\n", f); + fprintf(f, + "RequiresMountsFor=%s\n", + u); fprintf(f, "\n[Service]\n" @@ -164,7 +179,7 @@ static int create_disk( mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) { - log_error("Failed to create symlink '%s' to '%s': %m", from, to); + log_error("Failed to create symlink %s: %m", to); return -errno; } @@ -178,7 +193,7 @@ static int create_disk( mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) { - log_error("Failed to create symlink '%s' to '%s': %m", from, to); + log_error("Failed to create symlink %s: %m", to); return -errno; } } @@ -194,15 +209,32 @@ static int create_disk( mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) { - log_error("Failed to create symlink '%s' to '%s': %m", from, to); + log_error("Failed to create symlink %s: %m", to); return -errno; } + if (!noauto && !nofail) { + int r; + free(p); + p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL); + if (!p) + return log_oom(); + + mkdir_parents_label(p, 0755); + + r = write_string_file(p, + "# Automatically generated by systemd-cryptsetup-generator\n\n" + "[Unit]\n" + "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */ + if (r) + return r; + } + return 0; } -static int parse_proc_cmdline(char ***arg_proc_cmdline_disks) { - char _cleanup_free_ *line = NULL; +static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cmdline_keyfile) { + _cleanup_free_ char *line = NULL; char *w = NULL, *state = NULL; int r; size_t l; @@ -217,7 +249,7 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks) { } FOREACH_WORD_QUOTED(w, l, line, state) { - char _cleanup_free_ *word = NULL; + _cleanup_free_ char *word = NULL; word = strndup(w, l); if (!word) @@ -268,6 +300,21 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks) { return log_oom(); } + } else if (startswith(word, "luks.key=")) { + *arg_proc_cmdline_keyfile = strdup(word + 9); + if (!*arg_proc_cmdline_keyfile) + return log_oom(); + + } else if (startswith(word, "rd.luks.key=")) { + + if (in_initrd()) { + if (*arg_proc_cmdline_keyfile) + free(*arg_proc_cmdline_keyfile); + *arg_proc_cmdline_keyfile = strdup(word + 12); + if (!*arg_proc_cmdline_keyfile) + return log_oom(); + } + } else if (startswith(word, "luks.") || (in_initrd() && startswith(word, "rd.luks."))) { @@ -281,12 +328,13 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks) { } int main(int argc, char *argv[]) { - FILE _cleanup_fclose_ *f = NULL; + _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL; + _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL; + _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL; + _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; int r = EXIT_SUCCESS; char **i; - char _cleanup_strv_free_ **arg_proc_cmdline_disks_done = NULL; - char _cleanup_strv_free_ **arg_proc_cmdline_disks = NULL; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); @@ -302,15 +350,16 @@ int main(int argc, char *argv[]) { umask(0022); - if (parse_proc_cmdline(&arg_proc_cmdline_disks) < 0) + if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_keyfile) < 0) return EXIT_FAILURE; if (!arg_enabled) return EXIT_SUCCESS; if (arg_read_crypttab) { - f = fopen("/etc/crypttab", "re"); + struct stat st; + f = fopen("/etc/crypttab", "re"); if (!f) { if (errno == ENOENT) r = EXIT_SUCCESS; @@ -318,9 +367,26 @@ int main(int argc, char *argv[]) { r = EXIT_FAILURE; log_error("Failed to open /etc/crypttab: %m"); } - } else for (;;) { + + goto next; + } + + if (fstat(fileno(f), &st) < 0) { + log_error("Failed to stat /etc/crypttab: %m"); + r = EXIT_FAILURE; + goto next; + } + + /* If we readd support for specifying passphrases + * directly in crypttabe we should upgrade the warning + * below, though possibly only if a passphrase is + * specified directly. */ + if (st.st_mode & 0005) + log_debug("/etc/crypttab is world-readable. This is usually not a good idea."); + + for (;;) { char line[LINE_MAX], *l; - char _cleanup_free_ *name = NULL, *device = NULL, *password = NULL, *options = NULL; + _cleanup_free_ char *name = NULL, *device = NULL, *password = NULL, *options = NULL; int k; if (!fgets(line, sizeof(line), f)) @@ -345,7 +411,7 @@ int main(int argc, char *argv[]) { for /etc/crypttab and only generate units for those. */ STRV_FOREACH(i, arg_proc_cmdline_disks) { - char _cleanup_free_ *proc_device = NULL, *proc_name = NULL; + _cleanup_free_ char *proc_device = NULL, *proc_name = NULL; const char *p = *i; if (startswith(p, "luks-")) @@ -372,13 +438,14 @@ int main(int argc, char *argv[]) { } } +next: STRV_FOREACH(i, arg_proc_cmdline_disks) { /* Generate units for those UUIDs, which were specified on the kernel command line and not yet written. */ - char _cleanup_free_ *name = NULL, *device = NULL; + _cleanup_free_ char *name = NULL, *device = NULL; const char *p = *i; if (startswith(p, "luks-")) @@ -393,7 +460,7 @@ int main(int argc, char *argv[]) { if (!name || !device) return log_oom(); - if (create_disk(name, device, NULL, "timeout=0") < 0) + if (create_disk(name, device, arg_proc_cmdline_keyfile, "timeout=0") < 0) r = EXIT_FAILURE; }