]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/mcookie.c
misc: consolidate version printing and close_stdout()
[thirdparty/util-linux.git] / misc-utils / mcookie.c
CommitLineData
6dbe3af9
KZ
1/* mcookie.c -- Generates random numbers for xauth
2 * Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu
7eda085c
KZ
3 * Revised: Fri Mar 19 07:48:01 1999 by faith@acm.org
4 * Public Domain 1995, 1999 Rickard E. Faith (faith@acm.org)
6dbe3af9
KZ
5 * This program comes with ABSOLUTELY NO WARRANTY.
6 *
726f69e2
KZ
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.
7eda085c 14 *
b50945d4 15 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
7eda085c
KZ
16 * - added Native Language Support
17 * 1999-03-21 aeb: Added some fragments of code from Colin Plumb.
18 *
6dbe3af9
KZ
19 */
20
e6ebab66
SK
21#include "c.h"
22#include "md5.h"
23#include "nls.h"
c05a80ca 24#include "closestream.h"
0720d60c 25#include "randutils.h"
f7bac573 26#include "strutils.h"
cdf0c325 27#include "xalloc.h"
f7bac573 28#include "all-io.h"
c05a80ca 29
e6ebab66
SK
30#include <fcntl.h>
31#include <getopt.h>
32#include <stddef.h>
6dbe3af9
KZ
33#include <stdio.h>
34#include <stdlib.h>
6dbe3af9
KZ
35#include <sys/time.h>
36#include <unistd.h>
6dbe3af9 37
0720d60c
SK
38enum {
39 BUFFERSIZE = 4096,
40 RAND_BYTES = 128
726f69e2 41};
726f69e2 42
46ae163a 43struct mcookie_control {
42dea85c 44 struct UL_MD5Context ctx;
46ae163a
SK
45 char **files;
46 size_t nfiles;
f7bac573 47 uint64_t maxsz;
46ae163a
SK
48
49 unsigned int verbose:1;
50};
51
7eda085c 52/* The basic function to hash a file */
f7bac573 53static uint64_t hash_file(struct mcookie_control *ctl, int fd)
7eda085c 54{
e6ebab66 55 unsigned char buf[BUFFERSIZE];
f7bac573 56 uint64_t wanted, count;
e6ebab66 57
f7bac573
SK
58 wanted = ctl->maxsz ? ctl->maxsz : sizeof(buf);
59
60 for (count = 0; count < wanted; ) {
61 size_t rdsz = sizeof(buf);
62 ssize_t r;
63
64 if (wanted - count < rdsz)
65 rdsz = wanted - count;
66
67 r = read_all(fd, (char *) buf, rdsz);
68 if (r < 0)
69 break;
42dea85c 70 ul_MD5Update(&ctl->ctx, buf, r);
e6ebab66
SK
71 count += r;
72 }
73 /* Separate files with a null byte */
74 buf[0] = '\0';
42dea85c 75 ul_MD5Update(&ctl->ctx, buf, 1);
e6ebab66 76 return count;
7eda085c
KZ
77}
78
86be6a32 79static void __attribute__((__noreturn__)) usage(void)
e40f84b9 80{
86be6a32 81 FILE *out = stdout;
46ae163a
SK
82 fputs(USAGE_HEADER, out);
83 fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
e40f84b9 84
451dbcfa
BS
85 fputs(USAGE_SEPARATOR, out);
86 fputs(_("Generate magic cookies for xauth.\n"), out);
87
46ae163a
SK
88 fputs(USAGE_OPTIONS, out);
89 fputs(_(" -f, --file <file> use file as a cookie seed\n"), out);
f7bac573 90 fputs(_(" -m, --max-size <num> limit how much is read from seed files\n"), out);
46ae163a
SK
91 fputs(_(" -v, --verbose explain what is being done\n"), out);
92
93 fputs(USAGE_SEPARATOR, out);
f45f3ec3
RM
94 printf(USAGE_HELP_OPTIONS(23));
95 printf(USAGE_MAN_TAIL("mcookie(1)"));
e40f84b9 96
86be6a32 97 exit(EXIT_SUCCESS);
e40f84b9 98}
e6ebab66 99
46ae163a 100static void randomness_from_files(struct mcookie_control *ctl)
cdf0c325 101{
46ae163a
SK
102 size_t i;
103
104 for (i = 0; i < ctl->nfiles; i++) {
105 const char *fname = ctl->files[i];
106 size_t count;
107 int fd;
cdf0c325 108
46ae163a 109 if (*fname == '-' && !*(fname + 1))
cdf0c325
SK
110 fd = STDIN_FILENO;
111 else
46ae163a 112 fd = open(fname, O_RDONLY);
cdf0c325
SK
113
114 if (fd < 0) {
46ae163a 115 warn(_("cannot open %s"), fname);
cdf0c325 116 } else {
46ae163a
SK
117 count = hash_file(ctl, fd);
118 if (ctl->verbose)
cdf0c325 119 fprintf(stderr,
a3030b8a
SK
120 P_("Got %zu byte from %s\n",
121 "Got %zu bytes from %s\n", count),
46ae163a 122 count, fname);
cdf0c325 123
74ce680a
SK
124 if (fd != STDIN_FILENO && close(fd))
125 err(EXIT_FAILURE, _("closing %s failed"), fname);
cdf0c325
SK
126 }
127 }
128}
129
e6ebab66 130int main(int argc, char **argv)
6dbe3af9 131{
46ae163a 132 struct mcookie_control ctl = { .verbose = 0 };
e6ebab66 133 size_t i;
42dea85c 134 unsigned char digest[UL_MD5LENGTH];
0720d60c 135 unsigned char buf[RAND_BYTES];
e6ebab66 136 int c;
e6ebab66
SK
137
138 static const struct option longopts[] = {
139 {"file", required_argument, NULL, 'f'},
f7bac573 140 {"max-size", required_argument, NULL, 'm'},
e6ebab66
SK
141 {"verbose", no_argument, NULL, 'v'},
142 {"version", no_argument, NULL, 'V'},
143 {"help", no_argument, NULL, 'h'},
144 {NULL, 0, NULL, 0}
145 };
146
147 setlocale(LC_ALL, "");
148 bindtextdomain(PACKAGE, LOCALEDIR);
149 textdomain(PACKAGE);
2c308875 150 close_stdout_atexit();
e6ebab66 151
f7bac573 152 while ((c = getopt_long(argc, argv, "f:m:vVh", longopts, NULL)) != -1) {
e6ebab66
SK
153 switch (c) {
154 case 'v':
46ae163a 155 ctl.verbose = 1;
e6ebab66
SK
156 break;
157 case 'f':
dd8dac19
KZ
158 if (!ctl.files)
159 ctl.files = xmalloc(sizeof(char *) * argc);
46ae163a 160 ctl.files[ctl.nfiles++] = optarg;
e6ebab66 161 break;
f7bac573
SK
162 case 'm':
163 ctl.maxsz = strtosize_or_err(optarg,
164 _("failed to parse length"));
165 break;
2c308875 166
e6ebab66 167 case 'V':
2c308875 168 print_version(EXIT_SUCCESS);
e6ebab66 169 case 'h':
86be6a32 170 usage();
e6ebab66 171 default:
677ec86c 172 errtryhelp(EXIT_FAILURE);
e6ebab66 173 }
46ae163a 174 }
e6ebab66 175
f7bac573 176 if (ctl.maxsz && ctl.nfiles == 0)
09af3db4 177 warnx(_("--max-size ignored when used without --file"));
f7bac573 178
856d856a 179 ul_MD5Init(&ctl.ctx);
46ae163a
SK
180 randomness_from_files(&ctl);
181 free(ctl.files);
e6ebab66 182
0720d60c 183 random_get_bytes(&buf, RAND_BYTES);
42dea85c 184 ul_MD5Update(&ctl.ctx, buf, RAND_BYTES);
46ae163a 185 if (ctl.verbose)
ada74f3f
BV
186 fprintf(stderr, P_("Got %d byte from %s\n",
187 "Got %d bytes from %s\n", RAND_BYTES),
09af3db4 188 RAND_BYTES, random_tell_source());
e6ebab66 189
42dea85c
KZ
190 ul_MD5Final(digest, &ctl.ctx);
191 for (i = 0; i < UL_MD5LENGTH; i++)
e6ebab66
SK
192 printf("%02x", digest[i]);
193 putchar('\n');
194
e6ebab66 195 return EXIT_SUCCESS;
6dbe3af9 196}