]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/mcookie.c
autotools: add missing dist_noinst_DATA
[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 5 * This program comes with ABSOLUTELY NO WARRANTY.
2bb3aa36 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 24#include "closestream.h"
0720d60c 25#include "randutils.h"
f7bac573 26#include "strutils.h"
cdf0c325 27#include "xalloc.h"
f7bac573 28#include "all-io.h"
c05a80ca 29
e6ebab66
SK
30#include <fcntl.h>
31#include <getopt.h>
32#include <stddef.h>
6dbe3af9
KZ
33#include <stdio.h>
34#include <stdlib.h>
6dbe3af9
KZ
35#include <sys/time.h>
36#include <unistd.h>
6dbe3af9 37
0720d60c
SK
38enum {
39 BUFFERSIZE = 4096,
40 RAND_BYTES = 128
726f69e2 41};
726f69e2 42
46ae163a 43struct mcookie_control {
42dea85c 44 struct UL_MD5Context ctx;
46ae163a
SK
45 char **files;
46 size_t nfiles;
f7bac573 47 uint64_t maxsz;
46ae163a
SK
48
49 unsigned int verbose:1;
50};
51
7eda085c 52/* The basic function to hash a file */
f7bac573 53static uint64_t hash_file(struct mcookie_control *ctl, int fd)
7eda085c 54{
e6ebab66 55 unsigned char buf[BUFFERSIZE];
f7bac573 56 uint64_t wanted, count;
e6ebab66 57
f7bac573
SK
58 wanted = ctl->maxsz ? ctl->maxsz : sizeof(buf);
59
60 for (count = 0; count < wanted; ) {
61 size_t rdsz = sizeof(buf);
62 ssize_t r;
63
64 if (wanted - count < rdsz)
65 rdsz = wanted - count;
66
67 r = read_all(fd, (char *) buf, rdsz);
60e5bb73 68 if (r <= 0)
f7bac573 69 break;
42dea85c 70 ul_MD5Update(&ctl->ctx, buf, r);
e6ebab66
SK
71 count += r;
72 }
73 /* Separate files with a null byte */
74 buf[0] = '\0';
42dea85c 75 ul_MD5Update(&ctl->ctx, buf, 1);
e6ebab66 76 return count;
7eda085c
KZ
77}
78
86be6a32 79static void __attribute__((__noreturn__)) usage(void)
e40f84b9 80{
86be6a32 81 FILE *out = stdout;
46ae163a
SK
82 fputs(USAGE_HEADER, out);
83 fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
e40f84b9 84
451dbcfa
BS
85 fputs(USAGE_SEPARATOR, out);
86 fputs(_("Generate magic cookies for xauth.\n"), out);
87
46ae163a
SK
88 fputs(USAGE_OPTIONS, out);
89 fputs(_(" -f, --file <file> use file as a cookie seed\n"), out);
f7bac573 90 fputs(_(" -m, --max-size <num> limit how much is read from seed files\n"), out);
46ae163a
SK
91 fputs(_(" -v, --verbose explain what is being done\n"), out);
92
93 fputs(USAGE_SEPARATOR, out);
bad4c729 94 fprintf(out, USAGE_HELP_OPTIONS(23));
f1970cc5
KZ
95
96 fputs(USAGE_ARGUMENTS, out);
bad4c729 97 fprintf(out, USAGE_ARG_SIZE(_("<num>")));
f1970cc5 98
bad4c729 99 fprintf(out, USAGE_MAN_TAIL("mcookie(1)"));
e40f84b9 100
86be6a32 101 exit(EXIT_SUCCESS);
e40f84b9 102}
e6ebab66 103
46ae163a 104static void randomness_from_files(struct mcookie_control *ctl)
cdf0c325 105{
46ae163a
SK
106 size_t i;
107
108 for (i = 0; i < ctl->nfiles; i++) {
109 const char *fname = ctl->files[i];
110 size_t count;
111 int fd;
cdf0c325 112
46ae163a 113 if (*fname == '-' && !*(fname + 1))
cdf0c325
SK
114 fd = STDIN_FILENO;
115 else
46ae163a 116 fd = open(fname, O_RDONLY);
cdf0c325
SK
117
118 if (fd < 0) {
46ae163a 119 warn(_("cannot open %s"), fname);
cdf0c325 120 } else {
46ae163a
SK
121 count = hash_file(ctl, fd);
122 if (ctl->verbose)
cdf0c325 123 fprintf(stderr,
a3030b8a
SK
124 P_("Got %zu byte from %s\n",
125 "Got %zu bytes from %s\n", count),
46ae163a 126 count, fname);
cdf0c325 127
74ce680a
SK
128 if (fd != STDIN_FILENO && close(fd))
129 err(EXIT_FAILURE, _("closing %s failed"), fname);
cdf0c325
SK
130 }
131 }
132}
133
e6ebab66 134int main(int argc, char **argv)
6dbe3af9 135{
46ae163a 136 struct mcookie_control ctl = { .verbose = 0 };
e6ebab66 137 size_t i;
42dea85c 138 unsigned char digest[UL_MD5LENGTH];
0720d60c 139 unsigned char buf[RAND_BYTES];
e6ebab66 140 int c;
e6ebab66
SK
141
142 static const struct option longopts[] = {
143 {"file", required_argument, NULL, 'f'},
f7bac573 144 {"max-size", required_argument, NULL, 'm'},
e6ebab66
SK
145 {"verbose", no_argument, NULL, 'v'},
146 {"version", no_argument, NULL, 'V'},
147 {"help", no_argument, NULL, 'h'},
148 {NULL, 0, NULL, 0}
149 };
150
151 setlocale(LC_ALL, "");
152 bindtextdomain(PACKAGE, LOCALEDIR);
153 textdomain(PACKAGE);
2c308875 154 close_stdout_atexit();
e6ebab66 155
f7bac573 156 while ((c = getopt_long(argc, argv, "f:m:vVh", longopts, NULL)) != -1) {
e6ebab66
SK
157 switch (c) {
158 case 'v':
46ae163a 159 ctl.verbose = 1;
e6ebab66
SK
160 break;
161 case 'f':
dd8dac19
KZ
162 if (!ctl.files)
163 ctl.files = xmalloc(sizeof(char *) * argc);
46ae163a 164 ctl.files[ctl.nfiles++] = optarg;
e6ebab66 165 break;
f7bac573
SK
166 case 'm':
167 ctl.maxsz = strtosize_or_err(optarg,
168 _("failed to parse length"));
169 break;
2c308875 170
e6ebab66 171 case 'V':
2c308875 172 print_version(EXIT_SUCCESS);
e6ebab66 173 case 'h':
86be6a32 174 usage();
e6ebab66 175 default:
677ec86c 176 errtryhelp(EXIT_FAILURE);
e6ebab66 177 }
46ae163a 178 }
e6ebab66 179
f7bac573 180 if (ctl.maxsz && ctl.nfiles == 0)
09af3db4 181 warnx(_("--max-size ignored when used without --file"));
f7bac573 182
856d856a 183 ul_MD5Init(&ctl.ctx);
46ae163a
SK
184 randomness_from_files(&ctl);
185 free(ctl.files);
e6ebab66 186
364de8f4 187 ul_random_get_bytes(&buf, RAND_BYTES);
42dea85c 188 ul_MD5Update(&ctl.ctx, buf, RAND_BYTES);
46ae163a 189 if (ctl.verbose)
ada74f3f
BV
190 fprintf(stderr, P_("Got %d byte from %s\n",
191 "Got %d bytes from %s\n", RAND_BYTES),
09af3db4 192 RAND_BYTES, random_tell_source());
e6ebab66 193
42dea85c
KZ
194 ul_MD5Final(digest, &ctl.ctx);
195 for (i = 0; i < UL_MD5LENGTH; i++)
e6ebab66
SK
196 printf("%02x", digest[i]);
197 putchar('\n');
198
e6ebab66 199 return EXIT_SUCCESS;
6dbe3af9 200}