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.
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
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.
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.
24 #include "closestream.h"
25 #include "randutils.h"
43 struct mcookie_control
{
44 struct UL_MD5Context ctx
;
49 unsigned int verbose
:1;
52 /* The basic function to hash a file */
53 static uint64_t hash_file(struct mcookie_control
*ctl
, int fd
)
55 unsigned char buf
[BUFFERSIZE
];
56 uint64_t wanted
, count
;
58 wanted
= ctl
->maxsz
? ctl
->maxsz
: sizeof(buf
);
60 for (count
= 0; count
< wanted
; ) {
61 size_t rdsz
= sizeof(buf
);
64 if (wanted
- count
< rdsz
)
65 rdsz
= wanted
- count
;
67 r
= read_all(fd
, (char *) buf
, rdsz
);
70 ul_MD5Update(&ctl
->ctx
, buf
, r
);
73 /* Separate files with a null byte */
75 ul_MD5Update(&ctl
->ctx
, buf
, 1);
79 static void __attribute__((__noreturn__
)) usage(void)
82 fputs(USAGE_HEADER
, out
);
83 fprintf(out
, _(" %s [options]\n"), program_invocation_short_name
);
85 fputs(USAGE_SEPARATOR
, out
);
86 fputs(_("Generate magic cookies for xauth.\n"), out
);
88 fputs(USAGE_OPTIONS
, out
);
89 fputs(_(" -f, --file <file> use file as a cookie seed\n"), out
);
90 fputs(_(" -m, --max-size <num> limit how much is read from seed files\n"), out
);
91 fputs(_(" -v, --verbose explain what is being done\n"), out
);
93 fputs(USAGE_SEPARATOR
, out
);
94 printf(USAGE_HELP_OPTIONS(23));
96 fputs(USAGE_ARGUMENTS
, out
);
97 printf(USAGE_ARG_SIZE(_("<num>")));
99 printf(USAGE_MAN_TAIL("mcookie(1)"));
104 static void randomness_from_files(struct mcookie_control
*ctl
)
108 for (i
= 0; i
< ctl
->nfiles
; i
++) {
109 const char *fname
= ctl
->files
[i
];
113 if (*fname
== '-' && !*(fname
+ 1))
116 fd
= open(fname
, O_RDONLY
);
119 warn(_("cannot open %s"), fname
);
121 count
= hash_file(ctl
, fd
);
124 P_("Got %zu byte from %s\n",
125 "Got %zu bytes from %s\n", count
),
128 if (fd
!= STDIN_FILENO
&& close(fd
))
129 err(EXIT_FAILURE
, _("closing %s failed"), fname
);
134 int main(int argc
, char **argv
)
136 struct mcookie_control ctl
= { .verbose
= 0 };
138 unsigned char digest
[UL_MD5LENGTH
];
139 unsigned char buf
[RAND_BYTES
];
142 static const struct option longopts
[] = {
143 {"file", required_argument
, NULL
, 'f'},
144 {"max-size", required_argument
, NULL
, 'm'},
145 {"verbose", no_argument
, NULL
, 'v'},
146 {"version", no_argument
, NULL
, 'V'},
147 {"help", no_argument
, NULL
, 'h'},
151 setlocale(LC_ALL
, "");
152 bindtextdomain(PACKAGE
, LOCALEDIR
);
154 close_stdout_atexit();
156 while ((c
= getopt_long(argc
, argv
, "f:m:vVh", longopts
, NULL
)) != -1) {
163 ctl
.files
= xmalloc(sizeof(char *) * argc
);
164 ctl
.files
[ctl
.nfiles
++] = optarg
;
167 ctl
.maxsz
= strtosize_or_err(optarg
,
168 _("failed to parse length"));
172 print_version(EXIT_SUCCESS
);
176 errtryhelp(EXIT_FAILURE
);
180 if (ctl
.maxsz
&& ctl
.nfiles
== 0)
181 warnx(_("--max-size ignored when used without --file"));
183 ul_MD5Init(&ctl
.ctx
);
184 randomness_from_files(&ctl
);
187 random_get_bytes(&buf
, RAND_BYTES
);
188 ul_MD5Update(&ctl
.ctx
, buf
, RAND_BYTES
);
190 fprintf(stderr
, P_("Got %d byte from %s\n",
191 "Got %d bytes from %s\n", RAND_BYTES
),
192 RAND_BYTES
, random_tell_source());
194 ul_MD5Final(digest
, &ctl
.ctx
);
195 for (i
= 0; i
< UL_MD5LENGTH
; i
++)
196 printf("%02x", digest
[i
]);