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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/* 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.
*
*/
#ifdef __linux__
#define HAVE_GETTIMEOFDAY 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "md5.h"
#if HAVE_GETTIMEOFDAY
#include <sys/time.h>
#include <unistd.h>
#endif
#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;
#if HAVE_GETTIMEOFDAY
struct timeval tv;
struct timezone tz;
#else
long int t;
#endif
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 );
#if HAVE_GETTIMEOFDAY
gettimeofday( &tv, &tz );
MD5Update( &ctx, (unsigned char *)&tv, sizeof( tv ) );
#else
time( &t );
MD5Update( &ctx, (unsigned char *)&t, sizeof( t ) );
#endif
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;
}
|