]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/mcookie.c
textual: spell and encode the name of Arkadiusz Miśkiewicz correctly
[thirdparty/util-linux.git] / misc-utils / mcookie.c
CommitLineData
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
36struct 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 50static 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
66static 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
81int 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}