Upload Tizen:Base source
[framework/base/util-linux-ng.git] / misc-utils / mcookie.c
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.
6  * 
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
9  * use with xauth(1).
10  *
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.
14  *
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.
18  *
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <fcntl.h>
24 #include "md5.h"
25 #include <sys/time.h>
26 #include <unistd.h>
27 #include "nls.h"
28
29 #define BUFFERSIZE 4096
30
31 struct rngs {
32    const char *path;
33    int minlength, maxlength;
34 } rngs[] = {
35    { "/dev/random",              16,  16 }, /* 16 bytes = 128 bits suffice */
36    { "/proc/interrupts",          0,   0 },
37    { "/proc/slabinfo",            0,   0 },
38    { "/proc/stat",                0,   0 },
39    { "/dev/urandom",             32,  64 },
40 };
41 #define RNGS (sizeof(rngs)/sizeof(struct rngs))
42
43 int Verbose = 0;
44
45 /* The basic function to hash a file */
46 static off_t
47 hash_file(struct MD5Context *ctx, int fd)
48 {
49    off_t count = 0;
50    ssize_t r;
51    unsigned char buf[BUFFERSIZE];
52
53    while ((r = read(fd, buf, sizeof(buf))) > 0) {
54       MD5Update(ctx, buf, r);
55       count += r;
56    }
57    /* Separate files with a null byte */
58    buf[0] = 0;
59    MD5Update(ctx, buf, 1);
60    return count;
61 }
62
63 int main( int argc, char **argv )
64 {
65    int               i;
66    struct MD5Context ctx;
67    unsigned char     digest[16];
68    unsigned char     buf[BUFFERSIZE];
69    int               fd;
70    int               c;
71    pid_t             pid;
72    char              *file = NULL;
73    int               r;
74    struct timeval    tv;
75    struct timezone   tz;
76
77    setlocale(LC_ALL, "");
78    bindtextdomain(PACKAGE, LOCALEDIR);
79    textdomain(PACKAGE);
80
81    while ((c = getopt( argc, argv, "vf:" )) != -1)
82       switch (c) {
83       case 'v': ++Verbose;     break;
84       case 'f': file = optarg; break;
85       }
86
87    MD5Init( &ctx );
88    gettimeofday( &tv, &tz );
89    MD5Update( &ctx, (unsigned char *)&tv, sizeof( tv ) );
90
91    pid = getppid();
92    MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
93    pid = getpid();
94    MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
95
96    if (file) {
97       int count = 0;
98       
99       if (file[0] == '-' && !file[1])
100          fd = fileno(stdin);
101       else
102          fd = open( file, O_RDONLY );
103
104       if (fd < 0) {
105          fprintf( stderr, _("Could not open %s\n"), file );
106       } else {
107          count = hash_file( &ctx, fd );
108          if (Verbose)
109             fprintf( stderr, _("Got %d bytes from %s\n"), count, file );
110
111          if (file[0] != '-' || file[1]) close( fd );
112       }
113    }
114
115    for (i = 0; i < RNGS; i++) {
116       if ((fd = open( rngs[i].path, O_RDONLY|O_NONBLOCK )) >= 0) {
117          int count = sizeof(buf);
118
119          if (rngs[i].maxlength && count > rngs[i].maxlength)
120             count = rngs[i].maxlength;
121          r = read( fd, buf, count );
122          if (r > 0)
123             MD5Update( &ctx, buf, r );
124          else
125             r = 0;
126          close( fd );
127          if (Verbose)
128             fprintf( stderr, _("Got %d bytes from %s\n"), r, rngs[i].path );
129          if (rngs[i].minlength && r >= rngs[i].minlength)
130             break;
131       } else if (Verbose)
132          fprintf( stderr, _("Could not open %s\n"), rngs[i].path );
133    }
134
135    MD5Final( digest, &ctx );
136    for (i = 0; i < 16; i++) printf( "%02x", digest[i] );
137    putchar ( '\n' );
138    
139    /*
140     * The following is important for cases like disk full, so shell scripts
141     * can bomb out properly rather than think they succeeded.
142     */
143    if (fflush(stdout) < 0 || fclose(stdout) < 0)
144       return 1;
145
146    return 0;
147 }