]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/mcookie.c
mcookie: allow --file option be defined multiple times
[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 #include "randutils.h"
26 #include "xalloc.h"
27
28 #include <fcntl.h>
29 #include <getopt.h>
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <sys/time.h>
34 #include <unistd.h>
35
36 enum {
37 BUFFERSIZE = 4096,
38 RAND_BYTES = 128
39 };
40
41 /* The basic function to hash a file */
42 static off_t hash_file(struct MD5Context *ctx, int fd)
43 {
44 off_t count = 0;
45 ssize_t r;
46 unsigned char buf[BUFFERSIZE];
47
48 while ((r = read(fd, buf, sizeof(buf))) > 0) {
49 MD5Update(ctx, buf, r);
50 count += r;
51 }
52 /* Separate files with a null byte */
53 buf[0] = '\0';
54 MD5Update(ctx, buf, 1);
55 return count;
56 }
57
58 static void __attribute__ ((__noreturn__)) usage(FILE * out)
59 {
60 fputs(_("\nUsage:\n"), out);
61 fprintf(out,
62 _(" %s [options]\n"), program_invocation_short_name);
63
64 fputs(_("\nOptions:\n"), out);
65 fputs(_(" -f, --file <file> use file as a cookie seed\n"
66 " -v, --verbose explain what is being done\n"
67 " -V, --version output version information and exit\n"
68 " -h, --help display this help and exit\n\n"), out);
69
70 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
71 }
72
73 static void randomness_from_files(char **files, int nfiles,
74 struct MD5Context *ctx, int verbose)
75 {
76 int fd, i;
77 int count = 0;
78
79 for (i = 0; i < nfiles; i++) {
80 if (files[i][0] == '-' && !files[i][1])
81 fd = STDIN_FILENO;
82 else
83 fd = open(files[i], O_RDONLY);
84
85 if (fd < 0) {
86 warn(_("cannot open %s"), files[i]);
87 } else {
88 count = hash_file(ctx, fd);
89 if (verbose)
90 fprintf(stderr,
91 P_("Got %d byte from %s\n",
92 "Got %d bytes from %s\n", count),
93 count, files[i]);
94
95 if (fd != STDIN_FILENO)
96 if (close(fd))
97 err(EXIT_FAILURE,
98 _("closing %s failed"), files[i]);
99 }
100 }
101 }
102
103 int main(int argc, char **argv)
104 {
105 size_t i;
106 struct MD5Context ctx;
107 unsigned char digest[MD5LENGTH];
108 unsigned char buf[RAND_BYTES];
109 char **files = NULL;
110 int nfiles;
111 int c;
112 int verbose = 0;
113
114 static const struct option longopts[] = {
115 {"file", required_argument, NULL, 'f'},
116 {"verbose", no_argument, NULL, 'v'},
117 {"version", no_argument, NULL, 'V'},
118 {"help", no_argument, NULL, 'h'},
119 {NULL, 0, NULL, 0}
120 };
121
122 setlocale(LC_ALL, "");
123 bindtextdomain(PACKAGE, LOCALEDIR);
124 textdomain(PACKAGE);
125 atexit(close_stdout);
126
127 MD5Init(&ctx);
128
129 if (2 < argc) {
130 files = xmalloc(sizeof(char *) * argc);
131 nfiles = 0;
132 }
133
134 while ((c =
135 getopt_long(argc, argv, "f:vVh", longopts, NULL)) != -1)
136 switch (c) {
137 case 'v':
138 verbose = 1;
139 break;
140 case 'f':
141 files[nfiles] = optarg;
142 nfiles++;
143 break;
144 case 'V':
145 printf(UTIL_LINUX_VERSION);
146 return EXIT_SUCCESS;
147 case 'h':
148 usage(stdout);
149 default:
150 usage(stderr);
151 }
152
153 randomness_from_files(files, nfiles, &ctx, verbose);
154 free(files);
155
156 random_get_bytes(&buf, RAND_BYTES);
157 MD5Update(&ctx, buf, RAND_BYTES);
158 if (verbose)
159 fprintf(stderr,
160 _("Got %d bytes from %s\n"), RAND_BYTES, random_tell_source());
161
162 MD5Final(digest, &ctx);
163 for (i = 0; i < MD5LENGTH; i++)
164 printf("%02x", digest[i]);
165 putchar('\n');
166
167 return EXIT_SUCCESS;
168 }