]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/random-seed/random-seed.c
tree-wide: drop {} from one-line if blocks
[thirdparty/systemd.git] / src / random-seed / random-seed.c
CommitLineData
6e200d55
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
6e200d55
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
6e200d55 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
6e200d55
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <string.h>
26#include <sys/stat.h>
27
28#include "log.h"
29#include "util.h"
49e942b2 30#include "mkdir.h"
6e200d55 31
26192dfc
LP
32#define POOL_SIZE_MIN 512
33
6e200d55 34int main(int argc, char *argv[]) {
ce179470
LP
35 _cleanup_close_ int seed_fd = -1, random_fd = -1;
36 _cleanup_free_ void* buf = NULL;
26192dfc 37 size_t buf_size = 0;
ce179470
LP
38 ssize_t k;
39 int r;
26192dfc 40 FILE *f;
1509fb87 41 bool refresh_seed_file = true;
6e200d55
LP
42
43 if (argc != 2) {
44 log_error("This program requires one argument.");
22f4096c 45 return EXIT_FAILURE;
6e200d55
LP
46 }
47
4cfa2c99 48 log_set_target(LOG_TARGET_AUTO);
6e200d55 49 log_parse_environment();
2396fb04 50 log_open();
6e200d55 51
4c12626c
LP
52 umask(0022);
53
26192dfc 54 /* Read pool size, if possible */
ce179470
LP
55 f = fopen("/proc/sys/kernel/random/poolsize", "re");
56 if (f) {
ece174c5 57 if (fscanf(f, "%zu", &buf_size) > 0)
7c2ec009
TG
58 /* poolsize is in bits on 2.6, but we want bytes */
59 buf_size /= 8;
7c2ec009 60
26192dfc
LP
61 fclose(f);
62 }
63
64 if (buf_size <= POOL_SIZE_MIN)
65 buf_size = POOL_SIZE_MIN;
66
ce179470
LP
67 buf = malloc(buf_size);
68 if (!buf) {
69 r = log_oom();
26192dfc
LP
70 goto finish;
71 }
72
ce179470
LP
73 r = mkdir_parents_label(RANDOM_SEED, 0755);
74 if (r < 0) {
da927ba9 75 log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
b56e5747
GSB
76 goto finish;
77 }
78
6e200d55
LP
79 /* When we load the seed we read it and write it to the device
80 * and then immediately update the saved seed with new data,
81 * to make sure the next boot gets seeded differently. */
82
83 if (streq(argv[1], "load")) {
84
ce179470
LP
85 seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
86 if (seed_fd < 0) {
87 seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY);
88 if (seed_fd < 0) {
1509fb87 89 r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
6e200d55
LP
90 goto finish;
91 }
1509fb87
LP
92
93 refresh_seed_file = false;
6e200d55
LP
94 }
95
ce179470
LP
96 random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
97 if (random_fd < 0) {
98 random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600);
99 if (random_fd < 0) {
1509fb87 100 r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
6e200d55
LP
101 goto finish;
102 }
103 }
104
ce179470 105 k = loop_read(seed_fd, buf, buf_size, false);
1509fb87
LP
106 if (k < 0)
107 r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
108 else if (k == 0)
109 log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
110 else {
111 (void) lseek(seed_fd, 0, SEEK_SET);
6e200d55 112
553acb7b
ZJS
113 r = loop_write(random_fd, buf, (size_t) k, false);
114 if (r < 0)
115 log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
6e200d55
LP
116 }
117
118 } else if (streq(argv[1], "save")) {
119
ce179470
LP
120 seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
121 if (seed_fd < 0) {
1509fb87 122 r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
6e200d55
LP
123 goto finish;
124 }
125
ce179470
LP
126 random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
127 if (random_fd < 0) {
1509fb87 128 r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
6e200d55
LP
129 goto finish;
130 }
ce179470 131
6e200d55 132 } else {
1509fb87 133 log_error("Unknown verb '%s'.", argv[1]);
ce179470 134 r = -EINVAL;
6e200d55
LP
135 goto finish;
136 }
137
1509fb87
LP
138 if (refresh_seed_file) {
139
352e2098
CG
140 /* This is just a safety measure. Given that we are root and
141 * most likely created the file ourselves the mode and owner
142 * should be correct anyway. */
1509fb87
LP
143 (void) fchmod(seed_fd, 0600);
144 (void) fchown(seed_fd, 0, 0);
6e200d55 145
352e2098 146 k = loop_read(random_fd, buf, buf_size, false);
1509fb87
LP
147 if (k < 0) {
148 r = log_error_errno(k, "Failed to read new seed from /dev/urandom: %m");
149 goto finish;
352e2098 150 }
1509fb87
LP
151 if (k == 0) {
152 log_error("Got EOF while reading from /dev/urandom.");
153 r = -EIO;
154 goto finish;
155 }
156
157 r = loop_write(seed_fd, buf, (size_t) k, false);
158 if (r < 0)
159 log_error_errno(r, "Failed to write new random seed file: %m");
6e200d55
LP
160 }
161
6e200d55 162finish:
ce179470 163 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
6e200d55 164}