~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/cryptsetup/cryptsetup-generator.c

Tags: upstream-202
ImportĀ upstreamĀ versionĀ 202

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
static const char *arg_dest = "/tmp";
35
35
static bool arg_enabled = true;
36
36
static bool arg_read_crypttab = true;
37
 
static char **arg_proc_cmdline_disks = NULL;
38
37
 
39
38
static bool has_option(const char *haystack, const char *needle) {
40
39
        const char *f = haystack;
71
70
                const char *password,
72
71
                const char *options) {
73
72
 
74
 
        char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
75
 
        int r;
76
 
        FILE *f = NULL;
 
73
        _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
 
74
        _cleanup_fclose_ FILE *f = NULL;
77
75
        bool noauto, nofail;
78
76
 
79
77
        assert(name);
83
81
        nofail = has_option(options, "nofail");
84
82
 
85
83
        n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
86
 
        if (!n) {
87
 
                r = log_oom();
88
 
                goto fail;
89
 
        }
 
84
        if (!n)
 
85
                return log_oom();
90
86
 
91
87
        p = strjoin(arg_dest, "/", n, NULL);
92
 
        if (!p) {
93
 
                r = log_oom();
94
 
                goto fail;
95
 
        }
 
88
        if (!p)
 
89
                return log_oom();
96
90
 
97
91
        u = fstab_node_to_udev_node(device);
98
 
        if (!u) {
99
 
                r = log_oom();
100
 
                goto fail;
101
 
        }
 
92
        if (!u)
 
93
                return log_oom();
102
94
 
103
95
        d = unit_name_from_path(u, ".device");
104
 
        if (!d) {
105
 
                r = log_oom();
106
 
                goto fail;
107
 
        }
 
96
        if (!d)
 
97
                return log_oom();
108
98
 
109
99
        f = fopen(p, "wxe");
110
100
        if (!f) {
111
 
                r = -errno;
112
101
                log_error("Failed to create unit file %s: %m", p);
113
 
                goto fail;
 
102
                return -errno;
114
103
        }
115
104
 
116
 
        fprintf(f,
 
105
        fputs(
117
106
                "# Automatically generated by systemd-cryptsetup-generator\n\n"
118
107
                "[Unit]\n"
119
 
                "Description=Cryptography Setup for %%I\n"
 
108
                "Description=Cryptography Setup for %I\n"
120
109
                "Documentation=man:systemd-cryptsetup@.service(8) man:crypttab(5)\n"
121
110
                "SourcePath=/etc/crypttab\n"
122
111
                "Conflicts=umount.target\n"
123
112
                "DefaultDependencies=no\n"
124
 
                "BindsTo=%s dev-mapper-%%i.device\n"
125
 
                "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
126
 
                "Before=umount.target\n",
127
 
                d, d);
 
113
                "BindsTo=dev-mapper-%i.device\n"
 
114
                "After=systemd-readahead-collect.service systemd-readahead-replay.service\n",
 
115
                f);
128
116
 
129
117
        if (!nofail)
130
118
                fprintf(f,
131
119
                        "Before=cryptsetup.target\n");
132
120
 
133
 
        if (password && (streq(password, "/dev/urandom") ||
134
 
                         streq(password, "/dev/random") ||
135
 
                         streq(password, "/dev/hw_random")))
136
 
                fputs("After=systemd-random-seed-load.service\n", f);
 
121
        if (password) {
 
122
                if (streq(password, "/dev/urandom") ||
 
123
                    streq(password, "/dev/random") ||
 
124
                    streq(password, "/dev/hw_random"))
 
125
                        fputs("After=systemd-random-seed-load.service\n", f);
 
126
                else if (!streq(password, "-") &&
 
127
                         !streq(password, "none"))
 
128
                        fprintf(f,
 
129
                                "RequiresMountsFor=%s\n",
 
130
                                password);
 
131
        }
 
132
 
 
133
        if (is_device_path(u))
 
134
                fprintf(f,
 
135
                        "BindsTo=%s\n"
 
136
                        "After=%s\n"
 
137
                        "Before=umount.target\n",
 
138
                        d, d);
137
139
        else
138
 
                fputs("Before=local-fs.target\n", f);
 
140
                fprintf(f,
 
141
                        "RequiresMountsFor=%s\n",
 
142
                        u);
139
143
 
140
144
        fprintf(f,
141
145
                "\n[Service]\n"
160
164
        fflush(f);
161
165
 
162
166
        if (ferror(f)) {
163
 
                r = -errno;
164
167
                log_error("Failed to write file %s: %m", p);
165
 
                goto fail;
 
168
                return -errno;
166
169
        }
167
170
 
168
 
        if (asprintf(&from, "../%s", n) < 0) {
169
 
                r = log_oom();
170
 
                goto fail;
171
 
        }
 
171
        if (asprintf(&from, "../%s", n) < 0)
 
172
                return log_oom();
172
173
 
173
174
        if (!noauto) {
174
175
 
175
176
                to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
176
 
                if (!to) {
177
 
                        r = log_oom();
178
 
                        goto fail;
179
 
                }
 
177
                if (!to)
 
178
                        return log_oom();
180
179
 
181
180
                mkdir_parents_label(to, 0755);
182
181
                if (symlink(from, to) < 0) {
183
182
                        log_error("Failed to create symlink '%s' to '%s': %m", from, to);
184
 
                        r = -errno;
185
 
                        goto fail;
 
183
                        return -errno;
186
184
                }
187
185
 
188
186
                free(to);
189
 
 
190
187
                if (!nofail)
191
188
                        to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
192
189
                else
193
190
                        to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
194
 
                if (!to) {
195
 
                        r = log_oom();
196
 
                        goto fail;
197
 
                }
 
191
                if (!to)
 
192
                        return log_oom();
198
193
 
199
194
                mkdir_parents_label(to, 0755);
200
195
                if (symlink(from, to) < 0) {
201
196
                        log_error("Failed to create symlink '%s' to '%s': %m", from, to);
202
 
                        r = -errno;
203
 
                        goto fail;
 
197
                        return -errno;
204
198
                }
205
 
 
206
 
                free(to);
207
 
                to = NULL;
208
199
        }
209
200
 
210
201
        e = unit_name_escape(name);
 
202
        if (!e)
 
203
                return log_oom();
 
204
 
 
205
        free(to);
211
206
        to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
212
 
        if (!to) {
213
 
                r = log_oom();
214
 
                goto fail;
215
 
        }
 
207
        if (!to)
 
208
                return log_oom();
216
209
 
217
210
        mkdir_parents_label(to, 0755);
218
211
        if (symlink(from, to) < 0) {
219
212
                log_error("Failed to create symlink '%s' to '%s': %m", from, to);
220
 
                r = -errno;
221
 
                goto fail;
222
 
        }
223
 
 
224
 
        r = 0;
225
 
 
226
 
fail:
227
 
        free(p);
228
 
        free(n);
229
 
        free(d);
230
 
        free(e);
231
 
 
232
 
        free(from);
233
 
        free(to);
234
 
 
235
 
        if (f)
236
 
                fclose(f);
237
 
 
238
 
        return r;
 
213
                return -errno;
 
214
        }
 
215
 
 
216
        if (!noauto && !nofail) {
 
217
                int r;
 
218
                free(p);
 
219
                p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
 
220
                if (!p)
 
221
                        return log_oom();
 
222
 
 
223
                mkdir_parents_label(p, 0755);
 
224
 
 
225
                r = write_string_file(p,
 
226
                                "# Automatically generated by systemd-cryptsetup-generator\n\n"
 
227
                                "[Unit]\n"
 
228
                                "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
 
229
                if (r)
 
230
                        return r;
 
231
        }
 
232
 
 
233
        return 0;
239
234
}
240
235
 
241
 
static int parse_proc_cmdline(void) {
242
 
        char *line, *w, *state;
 
236
static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cmdline_keyfile) {
 
237
        _cleanup_free_ char *line = NULL;
 
238
        char *w = NULL, *state = NULL;
243
239
        int r;
244
240
        size_t l;
245
241
 
253
249
        }
254
250
 
255
251
        FOREACH_WORD_QUOTED(w, l, line, state) {
256
 
                char *word;
 
252
                _cleanup_free_ char *word = NULL;
257
253
 
258
254
                word = strndup(w, l);
259
 
                if (!word) {
260
 
                        r = log_oom();
261
 
                        goto finish;
262
 
                }
 
255
                if (!word)
 
256
                        return log_oom();
263
257
 
264
258
                if (startswith(word, "luks=")) {
265
259
                        r = parse_boolean(word + 5);
296
290
                        }
297
291
 
298
292
                } else if (startswith(word, "luks.uuid=")) {
299
 
                        char **t;
300
 
 
301
 
                        t = strv_append(arg_proc_cmdline_disks, word + 10);
302
 
                        if (!t) {
303
 
                                r = log_oom();
304
 
                                goto finish;
305
 
                        }
306
 
                        strv_free(arg_proc_cmdline_disks);
307
 
                        arg_proc_cmdline_disks = t;
 
293
                        if (strv_extend(arg_proc_cmdline_disks, word + 10) < 0)
 
294
                                return log_oom();
308
295
 
309
296
                } else if (startswith(word, "rd.luks.uuid=")) {
310
297
 
311
298
                        if (in_initrd()) {
312
 
                                char **t;
313
 
 
314
 
                                t = strv_append(arg_proc_cmdline_disks, word + 13);
315
 
                                if (!t) {
316
 
                                        r = log_oom();
317
 
                                        goto finish;
318
 
                                }
319
 
                                strv_free(arg_proc_cmdline_disks);
320
 
                                arg_proc_cmdline_disks = t;
 
299
                                if (strv_extend(arg_proc_cmdline_disks, word + 13) < 0)
 
300
                                        return log_oom();
 
301
                        }
 
302
 
 
303
                } else if (startswith(word, "luks.key=")) {
 
304
                        *arg_proc_cmdline_keyfile = strdup(word + 9);
 
305
                        if (! arg_proc_cmdline_keyfile)
 
306
                                return log_oom();
 
307
 
 
308
                } else if (startswith(word, "rd.luks.key=")) {
 
309
 
 
310
                        if (in_initrd()) {
 
311
                                if (*arg_proc_cmdline_keyfile)
 
312
                                        free(*arg_proc_cmdline_keyfile);
 
313
                                *arg_proc_cmdline_keyfile = strdup(word + 12);
 
314
                                if (!arg_proc_cmdline_keyfile)
 
315
                                        return log_oom();
321
316
                        }
322
317
 
323
318
                } else if (startswith(word, "luks.") ||
325
320
 
326
321
                        log_warning("Unknown kernel switch %s. Ignoring.", word);
327
322
                }
328
 
 
329
 
                free(word);
330
323
        }
331
324
 
332
 
        strv_uniq(arg_proc_cmdline_disks);
333
 
 
334
 
        r = 0;
335
 
 
336
 
finish:
337
 
        free(line);
338
 
        return r;
 
325
        strv_uniq(*arg_proc_cmdline_disks);
 
326
 
 
327
        return 0;
339
328
}
340
329
 
341
330
int main(int argc, char *argv[]) {
342
 
        FILE *f = NULL;
 
331
        _cleanup_fclose_ FILE *f = NULL;
 
332
        unsigned n = 0;
343
333
        int r = EXIT_SUCCESS;
344
 
        unsigned n = 0;
345
334
        char **i;
346
 
        char **arg_proc_cmdline_disks_done = NULL;
 
335
        _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
 
336
        _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
 
337
        _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
347
338
 
348
339
        if (argc > 1 && argc != 4) {
349
340
                log_error("This program takes three or no arguments.");
359
350
 
360
351
        umask(0022);
361
352
 
362
 
        if (parse_proc_cmdline() < 0)
 
353
        if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_keyfile) < 0)
363
354
                return EXIT_FAILURE;
364
355
 
365
 
        if (!arg_enabled) {
366
 
                r = EXIT_SUCCESS;
367
 
                goto finish;
368
 
        }
 
356
        if (!arg_enabled)
 
357
                return EXIT_SUCCESS;
369
358
 
370
359
        if (arg_read_crypttab) {
371
360
                f = fopen("/etc/crypttab", "re");
377
366
                                r = EXIT_FAILURE;
378
367
                                log_error("Failed to open /etc/crypttab: %m");
379
368
                        }
380
 
 
381
 
                        goto finish;
382
 
                }
383
 
 
384
 
                for (;;) {
 
369
                } else for (;;) {
385
370
                        char line[LINE_MAX], *l;
386
 
                        char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
 
371
                        _cleanup_free_ char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
387
372
                        int k;
388
373
 
389
374
                        if (!fgets(line, sizeof(line), f))
399
384
                        if (k < 2 || k > 4) {
400
385
                                log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
401
386
                                r = EXIT_FAILURE;
402
 
                                goto next;
 
387
                                continue;
403
388
                        }
404
389
 
405
390
                        if (arg_proc_cmdline_disks) {
408
393
                                  for /etc/crypttab and only generate units for those.
409
394
                                */
410
395
                                STRV_FOREACH(i, arg_proc_cmdline_disks) {
411
 
                                        char *proc_device, *proc_name;
 
396
                                        _cleanup_free_ char *proc_device = NULL, *proc_name = NULL;
412
397
                                        const char *p = *i;
413
398
 
414
399
                                        if (startswith(p, "luks-"))
417
402
                                        proc_name = strappend("luks-", p);
418
403
                                        proc_device = strappend("UUID=", p);
419
404
 
420
 
                                        if (!proc_name || !proc_device) {
421
 
                                                log_oom();
422
 
                                                r = EXIT_FAILURE;
423
 
                                                free(proc_name);
424
 
                                                free(proc_device);
425
 
                                                goto finish;
426
 
                                        }
 
405
                                        if (!proc_name || !proc_device)
 
406
                                                return log_oom();
 
407
 
427
408
                                        if (streq(proc_device, device) || streq(proc_name, name)) {
428
 
                                                char **t;
429
 
 
430
409
                                                if (create_disk(name, device, password, options) < 0)
431
410
                                                        r = EXIT_FAILURE;
432
411
 
433
 
                                                t = strv_append(arg_proc_cmdline_disks_done, p);
434
 
                                                if (!t) {
435
 
                                                        r = log_oom();
436
 
                                                        goto finish;
437
 
                                                }
438
 
                                                strv_free(arg_proc_cmdline_disks_done);
439
 
                                                arg_proc_cmdline_disks_done = t;
 
412
                                                if (strv_extend(&arg_proc_cmdline_disks_done, p) < 0)
 
413
                                                        return log_oom();
440
414
                                        }
441
 
 
442
 
                                        free(proc_device);
443
 
                                        free(proc_name);
444
415
                                }
445
416
                        } else {
446
417
                                if (create_disk(name, device, password, options) < 0)
447
418
                                        r = EXIT_FAILURE;
448
419
                        }
449
 
 
450
 
                next:
451
 
                        free(name);
452
 
                        free(device);
453
 
                        free(password);
454
 
                        free(options);
455
420
                }
456
421
        }
457
422
 
461
426
                  on the kernel command line and not yet written.
462
427
                */
463
428
 
464
 
                char *name, *device;
 
429
                _cleanup_free_ char *name = NULL, *device = NULL;
465
430
                const char *p = *i;
466
431
 
467
432
                if (startswith(p, "luks-"))
473
438
                name = strappend("luks-", p);
474
439
                device = strappend("UUID=", p);
475
440
 
476
 
                if (!name || !device) {
477
 
                        log_oom();
478
 
                        r = EXIT_FAILURE;
479
 
                        free(name);
480
 
                        free(device);
481
 
                        goto finish;
482
 
                }
483
 
 
484
 
                if (create_disk(name, device, NULL, "timeout=0") < 0)
485
 
                        r = EXIT_FAILURE;
486
 
 
487
 
                free(name);
488
 
                free(device);
 
441
                if (!name || !device)
 
442
                        return log_oom();
 
443
 
 
444
                if (create_disk(name, device, arg_proc_cmdline_keyfile, "timeout=0") < 0)
 
445
                        r = EXIT_FAILURE;
489
446
        }
490
447
 
491
 
finish:
492
 
        if (f)
493
 
                fclose(f);
494
 
 
495
 
        strv_free(arg_proc_cmdline_disks);
496
 
        strv_free(arg_proc_cmdline_disks_done);
497
 
 
498
448
        return r;
499
449
}