]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/mcookie.c
textual: use UTIL_LINUX_VERSION everywhere
[thirdparty/util-linux.git] / misc-utils / mcookie.c
1 /* mcookie.c -- Generates random numbers for xauth
2 * Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu
3 * Revised: Fri Mar 19 07:48:01 1999 by faith@acm.org
4 * Public Domain 1995, 1999 Rickard E. Faith (faith@acm.org)
5 * This program comes with ABSOLUTELY NO WARRANTY.
6 *
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.
14 *
15 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
16 * - added Native Language Support
17 * 1999-03-21 aeb: Added some fragments of code from Colin Plumb.
18 *
19 */
20
21 #include "c.h"
22 #include "md5.h"
23 #include "nls.h"
24 #include "closestream.h"
25
26 #include <fcntl.h>
27 #include <getopt.h>
28 #include <stddef.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/time.h>
32 #include <unistd.h>
33
34 #define BUFFERSIZE 4096
35
36 struct rngs {
37 const char *path;
38 int minlength, maxlength;
39 } rngs[] = {
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},
45 };
46
47 #define RNGS (sizeof(rngs)/sizeof(struct rngs))
48
49 /* The basic function to hash a file */
50 static off_t hash_file(struct MD5Context *ctx, int fd)
51 {
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;
64 }
65
66 static void __attribute__ ((__noreturn__)) usage(FILE * out)
67 {
68 fputs(_("\nUsage:\n"), out);
69 fprintf(out,
70 _(" %s [options]\n"), program_invocation_short_name);
71
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);
77
78 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
79 }
80
81 int main(int argc, char **argv)
82 {
83 size_t i;
84 struct MD5Context ctx;
85 unsigned char digest[MD5LENGTH];
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);
107 atexit(close_stdout);
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':
119 printf(UTIL_LINUX_VERSION);
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) {
145 warn(_("cannot open %s"), file);
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)
179 warn(_("cannot open %s"), rngs[i].path);
180 }
181
182 MD5Final(digest, &ctx);
183 for (i = 0; i < MD5LENGTH; i++)
184 printf("%02x", digest[i]);
185 putchar('\n');
186
187 return EXIT_SUCCESS;
188 }