2 * No copyright is claimed. This code is in the public domain; do with
5 * mcookie.c -- Generates random numbers for xauth
6 * Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu
7 * Revised: Fri Mar 19 07:48:01 1999 by faith@acm.org
8 * Public Domain 1995, 1999 Rickard E. Faith (faith@acm.org)
9 * This program comes with ABSOLUTELY NO WARRANTY.
11 * This program gathers some random bits of data and used the MD5
12 * message-digest algorithm to generate a 128-bit hexadecimal number for
15 * NOTE: Unless /dev/random is available, this program does not actually
16 * gather 128 bits of random information, so the magic cookie generated
17 * will be considerably easier to guess than one might expect.
19 * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL>
20 * - added Native Language Support
21 * 1999-03-21 aeb: Added some fragments of code from Colin Plumb.
28 #include "closestream.h"
29 #include "randutils.h"
48 struct mcookie_control
{
49 struct UL_MD5Context ctx
;
57 /* The basic function to hash a file */
58 static uint64_t hash_file(struct mcookie_control
*ctl
, int fd
)
60 unsigned char buf
[BUFFERSIZE
];
61 uint64_t wanted
, count
;
63 wanted
= ctl
->maxsz
? ctl
->maxsz
: sizeof(buf
);
65 for (count
= 0; count
< wanted
; ) {
66 size_t rdsz
= sizeof(buf
);
69 if (wanted
- count
< rdsz
)
70 rdsz
= wanted
- count
;
72 r
= read_all(fd
, (char *) buf
, rdsz
);
75 ul_MD5Update(&ctl
->ctx
, buf
, r
);
78 /* Separate files with a null byte */
80 ul_MD5Update(&ctl
->ctx
, buf
, 1);
84 static void __attribute__((__noreturn__
)) usage(void)
87 fputs(USAGE_HEADER
, out
);
88 fprintf(out
, _(" %s [options]\n"), program_invocation_short_name
);
90 fputs(USAGE_SEPARATOR
, out
);
91 fputs(_("Generate magic cookies for xauth.\n"), out
);
93 fputs(USAGE_OPTIONS
, out
);
94 fputs(_(" -f, --file <file> use file as a cookie seed\n"), out
);
95 fputs(_(" -m, --max-size <num> limit how much is read from seed files\n"), out
);
96 fputs(_(" -v, --verbose explain what is being done\n"), out
);
98 fputs(USAGE_SEPARATOR
, out
);
99 fprintf(out
, USAGE_HELP_OPTIONS(23));
101 fputs(USAGE_ARGUMENTS
, out
);
102 fprintf(out
, USAGE_ARG_SIZE(_("<num>")));
104 fprintf(out
, USAGE_MAN_TAIL("mcookie(1)"));
109 static void randomness_from_files(struct mcookie_control
*ctl
)
113 for (i
= 0; i
< ctl
->nfiles
; i
++) {
114 const char *fname
= ctl
->files
[i
];
118 if (*fname
== '-' && !*(fname
+ 1))
121 fd
= open(fname
, O_RDONLY
);
124 warn(_("cannot open %s"), fname
);
126 count
= hash_file(ctl
, fd
);
129 P_("Got %zu byte from %s\n",
130 "Got %zu bytes from %s\n", count
),
133 if (fd
!= STDIN_FILENO
&& close(fd
))
134 err(EXIT_FAILURE
, _("closing %s failed"), fname
);
139 int main(int argc
, char **argv
)
141 struct mcookie_control ctl
= { .verbose
= 0 };
143 unsigned char digest
[UL_MD5LENGTH
];
144 unsigned char buf
[RAND_BYTES
];
147 static const struct option longopts
[] = {
148 {"file", required_argument
, NULL
, 'f'},
149 {"max-size", required_argument
, NULL
, 'm'},
150 {"verbose", no_argument
, NULL
, 'v'},
151 {"version", no_argument
, NULL
, 'V'},
152 {"help", no_argument
, NULL
, 'h'},
156 setlocale(LC_ALL
, "");
157 bindtextdomain(PACKAGE
, LOCALEDIR
);
159 close_stdout_atexit();
161 while ((c
= getopt_long(argc
, argv
, "f:m:vVh", longopts
, NULL
)) != -1) {
168 ctl
.files
= xmalloc(sizeof(char *) * argc
);
169 ctl
.files
[ctl
.nfiles
++] = optarg
;
172 ctl
.maxsz
= strtosize_or_err(optarg
,
173 _("failed to parse length"));
177 print_version(EXIT_SUCCESS
);
181 errtryhelp(EXIT_FAILURE
);
185 if (ctl
.maxsz
&& ctl
.nfiles
== 0)
186 warnx(_("--max-size ignored when used without --file"));
188 ul_MD5Init(&ctl
.ctx
);
189 randomness_from_files(&ctl
);
192 ul_random_get_bytes(&buf
, RAND_BYTES
);
193 ul_MD5Update(&ctl
.ctx
, buf
, RAND_BYTES
);
195 fprintf(stderr
, P_("Got %d byte from %s\n",
196 "Got %d bytes from %s\n", RAND_BYTES
),
197 RAND_BYTES
, random_tell_source());
199 ul_MD5Final(digest
, &ctl
.ctx
);
200 for (i
= 0; i
< UL_MD5LENGTH
; i
++)
201 printf("%02x", digest
[i
]);