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));
95 printf(USAGE_MAN_TAIL("mcookie(1)"));
100 static void randomness_from_files(struct mcookie_control
*ctl
)
104 for (i
= 0; i
< ctl
->nfiles
; i
++) {
105 const char *fname
= ctl
->files
[i
];
109 if (*fname
== '-' && !*(fname
+ 1))
112 fd
= open(fname
, O_RDONLY
);
115 warn(_("cannot open %s"), fname
);
117 count
= hash_file(ctl
, fd
);
120 P_("Got %zu byte from %s\n",
121 "Got %zu bytes from %s\n", count
),
124 if (fd
!= STDIN_FILENO
&& close(fd
))
125 err(EXIT_FAILURE
, _("closing %s failed"), fname
);
130 int main(int argc
, char **argv
)
132 struct mcookie_control ctl
= { .verbose
= 0 };
134 unsigned char digest
[UL_MD5LENGTH
];
135 unsigned char buf
[RAND_BYTES
];
138 static const struct option longopts
[] = {
139 {"file", required_argument
, NULL
, 'f'},
140 {"max-size", required_argument
, NULL
, 'm'},
141 {"verbose", no_argument
, NULL
, 'v'},
142 {"version", no_argument
, NULL
, 'V'},
143 {"help", no_argument
, NULL
, 'h'},
147 setlocale(LC_ALL
, "");
148 bindtextdomain(PACKAGE
, LOCALEDIR
);
150 close_stdout_atexit();
152 while ((c
= getopt_long(argc
, argv
, "f:m:vVh", longopts
, NULL
)) != -1) {
159 ctl
.files
= xmalloc(sizeof(char *) * argc
);
160 ctl
.files
[ctl
.nfiles
++] = optarg
;
163 ctl
.maxsz
= strtosize_or_err(optarg
,
164 _("failed to parse length"));
168 print_version(EXIT_SUCCESS
);
172 errtryhelp(EXIT_FAILURE
);
176 if (ctl
.maxsz
&& ctl
.nfiles
== 0)
177 warnx(_("--max-size ignored when used without --file"));
179 ul_MD5Init(&ctl
.ctx
);
180 randomness_from_files(&ctl
);
183 random_get_bytes(&buf
, RAND_BYTES
);
184 ul_MD5Update(&ctl
.ctx
, buf
, RAND_BYTES
);
186 fprintf(stderr
, P_("Got %d byte from %s\n",
187 "Got %d bytes from %s\n", RAND_BYTES
),
188 RAND_BYTES
, random_tell_source());
190 ul_MD5Final(digest
, &ctl
.ctx
);
191 for (i
= 0; i
< UL_MD5LENGTH
; i
++)
192 printf("%02x", digest
[i
]);