]>
Commit | Line | Data |
---|---|---|
6dbe3af9 KZ |
1 | /* mcookie.c -- Generates random numbers for xauth |
2 | * Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu | |
7eda085c KZ |
3 | * Revised: Fri Mar 19 07:48:01 1999 by faith@acm.org |
4 | * Public Domain 1995, 1999 Rickard E. Faith (faith@acm.org) | |
6dbe3af9 KZ |
5 | * This program comes with ABSOLUTELY NO WARRANTY. |
6 | * | |
726f69e2 KZ |
7 | * This program gathers some random bits of data and used the MD5 |
8 | * message-digest algorithm to generate a 128-bit hexadecimal number for | |
9 | * use with xauth(1). | |
10 | * | |
11 | * NOTE: Unless /dev/random is available, this program does not actually | |
12 | * gather 128 bits of random information, so the magic cookie generated | |
13 | * will be considerably easier to guess than one might expect. | |
7eda085c | 14 | * |
b50945d4 | 15 | * 1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL> |
7eda085c KZ |
16 | * - added Native Language Support |
17 | * 1999-03-21 aeb: Added some fragments of code from Colin Plumb. | |
18 | * | |
6dbe3af9 KZ |
19 | */ |
20 | ||
e6ebab66 SK |
21 | #include "c.h" |
22 | #include "md5.h" | |
23 | #include "nls.h" | |
c05a80ca SK |
24 | #include "closestream.h" |
25 | ||
e6ebab66 SK |
26 | #include <fcntl.h> |
27 | #include <getopt.h> | |
28 | #include <stddef.h> | |
6dbe3af9 KZ |
29 | #include <stdio.h> |
30 | #include <stdlib.h> | |
6dbe3af9 KZ |
31 | #include <sys/time.h> |
32 | #include <unistd.h> | |
6dbe3af9 | 33 | |
e6ebab66 | 34 | #define BUFFERSIZE 4096 |
726f69e2 KZ |
35 | |
36 | struct rngs { | |
e6ebab66 SK |
37 | const char *path; |
38 | int minlength, maxlength; | |
726f69e2 | 39 | } rngs[] = { |
e6ebab66 SK |
40 | {"/dev/random", 16, 16}, /* 16 bytes = 128 bits suffice */ |
41 | {"/proc/interrupts", 0, 0}, | |
42 | {"/proc/slabinfo", 0, 0}, | |
43 | {"/proc/stat", 0, 0}, | |
44 | {"/dev/urandom", 32, 64}, | |
726f69e2 | 45 | }; |
726f69e2 | 46 | |
e6ebab66 | 47 | #define RNGS (sizeof(rngs)/sizeof(struct rngs)) |
726f69e2 | 48 | |
7eda085c | 49 | /* The basic function to hash a file */ |
e6ebab66 | 50 | static off_t hash_file(struct MD5Context *ctx, int fd) |
7eda085c | 51 | { |
e6ebab66 SK |
52 | off_t count = 0; |
53 | ssize_t r; | |
54 | unsigned char buf[BUFFERSIZE]; | |
55 | ||
56 | while ((r = read(fd, buf, sizeof(buf))) > 0) { | |
57 | MD5Update(ctx, buf, r); | |
58 | count += r; | |
59 | } | |
60 | /* Separate files with a null byte */ | |
61 | buf[0] = '\0'; | |
62 | MD5Update(ctx, buf, 1); | |
63 | return count; | |
7eda085c KZ |
64 | } |
65 | ||
e40f84b9 SK |
66 | static void __attribute__ ((__noreturn__)) usage(FILE * out) |
67 | { | |
b417b1ee KZ |
68 | fputs(_("\nUsage:\n"), out); |
69 | fprintf(out, | |
70 | _(" %s [options]\n"), program_invocation_short_name); | |
e40f84b9 | 71 | |
b417b1ee KZ |
72 | fputs(_("\nOptions:\n"), out); |
73 | fputs(_(" -f, --file <file> use file as a cookie seed\n" | |
74 | " -v, --verbose explain what is being done\n" | |
75 | " -V, --version output version information and exit\n" | |
76 | " -h, --help display this help and exit\n\n"), out); | |
e40f84b9 | 77 | |
e6ebab66 | 78 | exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); |
e40f84b9 | 79 | } |
e6ebab66 SK |
80 | |
81 | int main(int argc, char **argv) | |
6dbe3af9 | 82 | { |
e6ebab66 SK |
83 | size_t i; |
84 | struct MD5Context ctx; | |
e429d141 | 85 | unsigned char digest[MD5LENGTH]; |
e6ebab66 SK |
86 | unsigned char buf[BUFFERSIZE]; |
87 | int fd; | |
88 | int c; | |
89 | pid_t pid; | |
90 | char *file = NULL; | |
91 | int verbose = 0; | |
92 | int r; | |
93 | struct timeval tv; | |
94 | struct timezone tz; | |
95 | ||
96 | static const struct option longopts[] = { | |
97 | {"file", required_argument, NULL, 'f'}, | |
98 | {"verbose", no_argument, NULL, 'v'}, | |
99 | {"version", no_argument, NULL, 'V'}, | |
100 | {"help", no_argument, NULL, 'h'}, | |
101 | {NULL, 0, NULL, 0} | |
102 | }; | |
103 | ||
104 | setlocale(LC_ALL, ""); | |
105 | bindtextdomain(PACKAGE, LOCALEDIR); | |
106 | textdomain(PACKAGE); | |
c05a80ca | 107 | atexit(close_stdout); |
e6ebab66 SK |
108 | |
109 | while ((c = | |
110 | getopt_long(argc, argv, "f:vVh", longopts, NULL)) != -1) | |
111 | switch (c) { | |
112 | case 'v': | |
113 | verbose = 1; | |
114 | break; | |
115 | case 'f': | |
116 | file = optarg; | |
117 | break; | |
118 | case 'V': | |
e421313d | 119 | printf(UTIL_LINUX_VERSION); |
e6ebab66 SK |
120 | return EXIT_SUCCESS; |
121 | case 'h': | |
122 | usage(stdout); | |
123 | default: | |
124 | usage(stderr); | |
125 | } | |
126 | ||
127 | MD5Init(&ctx); | |
128 | gettimeofday(&tv, &tz); | |
129 | MD5Update(&ctx, (unsigned char *) &tv, sizeof(tv)); | |
130 | ||
131 | pid = getppid(); | |
132 | MD5Update(&ctx, (unsigned char *) &pid, sizeof(pid)); | |
133 | pid = getpid(); | |
134 | MD5Update(&ctx, (unsigned char *) &pid, sizeof(pid)); | |
135 | ||
136 | if (file) { | |
137 | int count = 0; | |
138 | ||
139 | if (file[0] == '-' && !file[1]) | |
140 | fd = STDIN_FILENO; | |
141 | else | |
142 | fd = open(file, O_RDONLY); | |
143 | ||
144 | if (fd < 0) { | |
289dcc90 | 145 | warn(_("cannot open %s"), file); |
e6ebab66 SK |
146 | } else { |
147 | count = hash_file(&ctx, fd); | |
148 | if (verbose) | |
149 | fprintf(stderr, | |
150 | _("Got %d bytes from %s\n"), count, | |
151 | file); | |
152 | ||
153 | if (fd != STDIN_FILENO) | |
154 | if (close(fd)) | |
155 | err(EXIT_FAILURE, | |
156 | _("closing %s failed"), file); | |
157 | } | |
158 | } | |
159 | ||
160 | for (i = 0; i < RNGS; i++) { | |
161 | if ((fd = open(rngs[i].path, O_RDONLY | O_NONBLOCK)) >= 0) { | |
162 | int count = sizeof(buf); | |
163 | ||
164 | if (rngs[i].maxlength && count > rngs[i].maxlength) | |
165 | count = rngs[i].maxlength; | |
166 | r = read(fd, buf, count); | |
167 | if (r > 0) | |
168 | MD5Update(&ctx, buf, r); | |
169 | else | |
170 | r = 0; | |
171 | close(fd); | |
172 | if (verbose) | |
173 | fprintf(stderr, | |
174 | _("Got %d bytes from %s\n"), r, | |
175 | rngs[i].path); | |
176 | if (rngs[i].minlength && r >= rngs[i].minlength) | |
177 | break; | |
178 | } else if (verbose) | |
289dcc90 | 179 | warn(_("cannot open %s"), rngs[i].path); |
e6ebab66 SK |
180 | } |
181 | ||
182 | MD5Final(digest, &ctx); | |
e429d141 | 183 | for (i = 0; i < MD5LENGTH; i++) |
e6ebab66 SK |
184 | printf("%02x", digest[i]); |
185 | putchar('\n'); | |
186 | ||
e6ebab66 | 187 | return EXIT_SUCCESS; |
6dbe3af9 | 188 | } |