]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/mcookie.c
remove CVS keywords
[thirdparty/util-linux.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 }