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.
31 #define BUFFERSIZE 4096
35 int minlength
, maxlength
;
37 { "/dev/random", 16, 16 }, /* 16 bytes = 128 bits suffice */
38 { "/proc/interrupts", 0, 0 },
39 { "/proc/slabinfo", 0, 0 },
40 { "/proc/stat", 0, 0 },
41 { "/dev/urandom", 32, 64 },
43 #define RNGS (sizeof(rngs)/sizeof(struct rngs))
47 /* The basic function to hash a file */
49 hash_file(struct MD5Context
*ctx
, int fd
)
53 unsigned char buf
[BUFFERSIZE
];
55 while ((r
= read(fd
, buf
, sizeof(buf
))) > 0) {
56 MD5Update(ctx
, buf
, r
);
59 /* Separate files with a null byte */
61 MD5Update(ctx
, buf
, 1);
65 static void __attribute__ ((__noreturn__
)) usage(FILE * out
)
67 fprintf(out
, _("Usage: %s [options]\n"),
68 program_invocation_short_name
);
70 fprintf(out
, _("\nOptions:\n"
71 " -f, --file=FILE use file as a cookie seed\n"
72 " -v, --verbose explain what is being done\n"
73 " -V, --version output version information and exit\n"
74 " -h, --help display this help and exit\n"));
76 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
78 int main( int argc
, char **argv
)
81 struct MD5Context ctx
;
82 unsigned char digest
[16];
83 unsigned char buf
[BUFFERSIZE
];
92 static const struct option longopts
[] = {
93 {"file", required_argument
, NULL
, 'f'},
94 {"verbose", no_argument
, NULL
, 'v'},
95 {"version", no_argument
, NULL
, 'V'},
96 {"help", no_argument
, NULL
, 'h'},
100 setlocale(LC_ALL
, "");
101 bindtextdomain(PACKAGE
, LOCALEDIR
);
104 while ((c
= getopt_long(argc
, argv
, "f:vVh", longopts
, NULL
)) != -1)
113 printf(_("%s from %s\n"), program_invocation_short_name
,
123 gettimeofday( &tv
, &tz
);
124 MD5Update( &ctx
, (unsigned char *)&tv
, sizeof( tv
) );
127 MD5Update( &ctx
, (unsigned char *)&pid
, sizeof( pid
));
129 MD5Update( &ctx
, (unsigned char *)&pid
, sizeof( pid
));
134 if (file
[0] == '-' && !file
[1])
137 fd
= open( file
, O_RDONLY
);
140 warn( _("Could not open %s"), file
);
142 count
= hash_file( &ctx
, fd
);
144 fprintf( stderr
, _("Got %d bytes from %s\n"), count
, file
);
146 if (fd
!= STDIN_FILENO
)
148 err(EXIT_FAILURE
, _("closing %s failed"), file
);
152 for (i
= 0; i
< RNGS
; i
++) {
153 if ((fd
= open( rngs
[i
].path
, O_RDONLY
|O_NONBLOCK
)) >= 0) {
154 int count
= sizeof(buf
);
156 if (rngs
[i
].maxlength
&& count
> rngs
[i
].maxlength
)
157 count
= rngs
[i
].maxlength
;
158 r
= read( fd
, buf
, count
);
160 MD5Update( &ctx
, buf
, r
);
165 fprintf( stderr
, _("Got %d bytes from %s\n"), r
, rngs
[i
].path
);
166 if (rngs
[i
].minlength
&& r
>= rngs
[i
].minlength
)
169 warn( _("Could not open %s"), rngs
[i
].path
);
172 MD5Final( digest
, &ctx
);
173 for (i
= 0; i
< 16; i
++) printf( "%02x", digest
[i
] );
177 * The following is important for cases like disk full, so shell scripts
178 * can bomb out properly rather than think they succeeded.
180 if (fflush(stdout
) < 0 || fclose(stdout
) < 0)