1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/* mcookie.c -- Generates random numbers for xauth
* Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu
* Revised: Fri Mar 19 07:48:01 1999 by faith@acm.org
* Public Domain 1995, 1999 Rickard E. Faith (faith@acm.org)
* This program comes with ABSOLUTELY NO WARRANTY.
*
* $Id: mcookie.c,v 1.5 1997/07/06 00:13:06 aebr Exp $
*
* This program gathers some random bits of data and used the MD5
* message-digest algorithm to generate a 128-bit hexadecimal number for
* use with xauth(1).
*
* NOTE: Unless /dev/random is available, this program does not actually
* gather 128 bits of random information, so the magic cookie generated
* will be considerably easier to guess than one might expect.
*
* 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
* 1999-03-21 aeb: Added some fragments of code from Colin Plumb.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "md5.h"
#include <sys/time.h>
#include <unistd.h>
#include "nls.h"
#define BUFFERSIZE 4096
struct rngs {
const char *path;
int minlength, maxlength;
} rngs[] = {
{ "/dev/random", 16, 16 }, /* 16 bytes = 128 bits suffice */
{ "/proc/interrupts", 0, 0 },
{ "/proc/slabinfo", 0, 0 },
{ "/proc/stat", 0, 0 },
{ "/dev/urandom", 32, 64 },
};
#define RNGS (sizeof(rngs)/sizeof(struct rngs))
int Verbose = 0;
/* The basic function to hash a file */
static off_t
hash_file(struct MD5Context *ctx, int fd)
{
off_t count = 0;
ssize_t r;
unsigned char buf[BUFFERSIZE];
while ((r = read(fd, buf, sizeof(buf))) > 0) {
MD5Update(ctx, buf, r);
count += r;
}
/* Separate files with a null byte */
buf[0] = 0;
MD5Update(ctx, buf, 1);
return count;
}
int main( int argc, char **argv )
{
int i;
struct MD5Context ctx;
unsigned char digest[16];
unsigned char buf[BUFFERSIZE];
int fd;
int c;
pid_t pid;
char *file = NULL;
int r;
struct timeval tv;
struct timezone tz;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
while ((c = getopt( argc, argv, "vf:" )) != -1)
switch (c) {
case 'v': ++Verbose; break;
case 'f': file = optarg; break;
}
MD5Init( &ctx );
gettimeofday( &tv, &tz );
MD5Update( &ctx, (unsigned char *)&tv, sizeof( tv ) );
pid = getppid();
MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
pid = getpid();
MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
if (file) {
int count = 0;
if (file[0] == '-' && !file[1])
fd = fileno(stdin);
else
fd = open( file, O_RDONLY );
if (fd < 0) {
fprintf( stderr, _("Could not open %s\n"), file );
} else {
count = hash_file( &ctx, fd );
if (Verbose)
fprintf( stderr, _("Got %d bytes from %s\n"), count, file );
if (file[0] != '-' || file[1]) close( fd );
}
}
for (i = 0; i < RNGS; i++) {
if ((fd = open( rngs[i].path, O_RDONLY|O_NONBLOCK )) >= 0) {
int count = sizeof(buf);
if (rngs[i].maxlength && count > rngs[i].maxlength)
count = rngs[i].maxlength;
r = read( fd, buf, count );
if (r > 0)
MD5Update( &ctx, buf, r );
else
r = 0;
close( fd );
if (Verbose)
fprintf( stderr, _("Got %d bytes from %s\n"), r, rngs[i].path );
if (rngs[i].minlength && r >= rngs[i].minlength)
break;
} else if (Verbose)
fprintf( stderr, _("Could not open %s\n"), rngs[i].path );
}
MD5Final( digest, &ctx );
for (i = 0; i < 16; i++) printf( "%02x", digest[i] );
putchar ( '\n' );
/*
* The following is important for cases like disk full, so shell scripts
* can bomb out properly rather than think they succeeded.
*/
if (fflush(stdout) < 0 || fclose(stdout) < 0)
return 1;
return 0;
}
|