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"
47 struct mcookie_control
{
48 struct UL_MD5Context ctx
;
53 unsigned int verbose
:1;
56 /* The basic function to hash a file */
57 static uint64_t hash_file(struct mcookie_control
*ctl
, int fd
)
59 unsigned char buf
[BUFFERSIZE
];
60 uint64_t wanted
, count
;
62 wanted
= ctl
->maxsz
? ctl
->maxsz
: sizeof(buf
);
64 for (count
= 0; count
< wanted
; ) {
65 size_t rdsz
= sizeof(buf
);
68 if (wanted
- count
< rdsz
)
69 rdsz
= wanted
- count
;
71 r
= read_all(fd
, (char *) buf
, rdsz
);
74 ul_MD5Update(&ctl
->ctx
, buf
, r
);
77 /* Separate files with a null byte */
79 ul_MD5Update(&ctl
->ctx
, buf
, 1);
83 static void __attribute__((__noreturn__
)) usage(void)
86 fputs(USAGE_HEADER
, out
);
87 fprintf(out
, _(" %s [options]\n"), program_invocation_short_name
);
89 fputs(USAGE_SEPARATOR
, out
);
90 fputs(_("Generate magic cookies for xauth.\n"), out
);
92 fputs(USAGE_OPTIONS
, out
);
93 fputs(_(" -f, --file <file> use file as a cookie seed\n"), out
);
94 fputs(_(" -m, --max-size <num> limit how much is read from seed files\n"), out
);
95 fputs(_(" -v, --verbose explain what is being done\n"), out
);
97 fputs(USAGE_SEPARATOR
, out
);
98 fprintf(out
, USAGE_HELP_OPTIONS(23));
100 fputs(USAGE_ARGUMENTS
, out
);
101 fprintf(out
, USAGE_ARG_SIZE(_("<num>")));
103 fprintf(out
, USAGE_MAN_TAIL("mcookie(1)"));
108 static void randomness_from_files(struct mcookie_control
*ctl
)
112 for (i
= 0; i
< ctl
->nfiles
; i
++) {
113 const char *fname
= ctl
->files
[i
];
117 if (*fname
== '-' && !*(fname
+ 1))
120 fd
= open(fname
, O_RDONLY
);
123 warn(_("cannot open %s"), fname
);
125 count
= hash_file(ctl
, fd
);
128 P_("Got %zu byte from %s\n",
129 "Got %zu bytes from %s\n", count
),
132 if (fd
!= STDIN_FILENO
&& close(fd
))
133 err(EXIT_FAILURE
, _("closing %s failed"), fname
);
138 int main(int argc
, char **argv
)
140 struct mcookie_control ctl
= { .verbose
= 0 };
142 unsigned char digest
[UL_MD5LENGTH
];
143 unsigned char buf
[RAND_BYTES
];
146 static const struct option longopts
[] = {
147 {"file", required_argument
, NULL
, 'f'},
148 {"max-size", required_argument
, NULL
, 'm'},
149 {"verbose", no_argument
, NULL
, 'v'},
150 {"version", no_argument
, NULL
, 'V'},
151 {"help", no_argument
, NULL
, 'h'},
155 setlocale(LC_ALL
, "");
156 bindtextdomain(PACKAGE
, LOCALEDIR
);
158 close_stdout_atexit();
160 while ((c
= getopt_long(argc
, argv
, "f:m:vVh", longopts
, NULL
)) != -1) {
167 ctl
.files
= xmalloc(sizeof(char *) * argc
);
168 ctl
.files
[ctl
.nfiles
++] = optarg
;
171 ctl
.maxsz
= strtosize_or_err(optarg
,
172 _("failed to parse length"));
176 print_version(EXIT_SUCCESS
);
180 errtryhelp(EXIT_FAILURE
);
184 if (ctl
.maxsz
&& ctl
.nfiles
== 0)
185 warnx(_("--max-size ignored when used without --file"));
187 ul_MD5Init(&ctl
.ctx
);
188 randomness_from_files(&ctl
);
191 ul_random_get_bytes(&buf
, RAND_BYTES
);
192 ul_MD5Update(&ctl
.ctx
, buf
, RAND_BYTES
);
194 fprintf(stderr
, P_("Got %d byte from %s\n",
195 "Got %d bytes from %s\n", RAND_BYTES
),
196 RAND_BYTES
, random_tell_source());
198 ul_MD5Final(digest
, &ctl
.ctx
);
199 for (i
= 0; i
< UL_MD5LENGTH
; i
++)
200 printf("%02x", digest
[i
]);