]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/mcookie.c
merge coreutils' last GPL2 version of su.c
[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(_("%s from %s\n"),
120 program_invocation_short_name,
121 PACKAGE_STRING);
122 return EXIT_SUCCESS;
123 case 'h':
124 usage(stdout);
125 default:
126 usage(stderr);
127 }
128
129 MD5Init(&ctx);
130 gettimeofday(&tv, &tz);
131 MD5Update(&ctx, (unsigned char *) &tv, sizeof(tv));
132
133 pid = getppid();
134 MD5Update(&ctx, (unsigned char *) &pid, sizeof(pid));
135 pid = getpid();
136 MD5Update(&ctx, (unsigned char *) &pid, sizeof(pid));
137
138 if (file) {
139 int count = 0;
140
141 if (file[0] == '-' && !file[1])
142 fd = STDIN_FILENO;
143 else
144 fd = open(file, O_RDONLY);
145
146 if (fd < 0) {
147 warn(_("Could not open %s"), file);
148 } else {
149 count = hash_file(&ctx, fd);
150 if (verbose)
151 fprintf(stderr,
152 _("Got %d bytes from %s\n"), count,
153 file);
154
155 if (fd != STDIN_FILENO)
156 if (close(fd))
157 err(EXIT_FAILURE,
158 _("closing %s failed"), file);
159 }
160 }
161
162 for (i = 0; i < RNGS; i++) {
163 if ((fd = open(rngs[i].path, O_RDONLY | O_NONBLOCK)) >= 0) {
164 int count = sizeof(buf);
165
166 if (rngs[i].maxlength && count > rngs[i].maxlength)
167 count = rngs[i].maxlength;
168 r = read(fd, buf, count);
169 if (r > 0)
170 MD5Update(&ctx, buf, r);
171 else
172 r = 0;
173 close(fd);
174 if (verbose)
175 fprintf(stderr,
176 _("Got %d bytes from %s\n"), r,
177 rngs[i].path);
178 if (rngs[i].minlength && r >= rngs[i].minlength)
179 break;
180 } else if (verbose)
181 warn(_("Could not open %s"), rngs[i].path);
182 }
183
184 MD5Final(digest, &ctx);
185 for (i = 0; i < MD5LENGTH; i++)
186 printf("%02x", digest[i]);
187 putchar('\n');
188
189 return EXIT_SUCCESS;
190 }