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