diff options
Diffstat (limited to 'misc-utils/mcookie.c')
-rw-r--r-- | misc-utils/mcookie.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/misc-utils/mcookie.c b/misc-utils/mcookie.c new file mode 100644 index 0000000..be5c34a --- /dev/null +++ b/misc-utils/mcookie.c @@ -0,0 +1,200 @@ +/* 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. + * + * 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 MiĆkiewicz <misiek@pld.ORG.PL> + * - added Native Language Support + * 1999-03-21 aeb: Added some fragments of code from Colin Plumb. + * + */ + +#include "c.h" +#include "md5.h" +#include "nls.h" +#include "closestream.h" +#include "randutils.h" +#include "strutils.h" +#include "xalloc.h" +#include "all-io.h" + +#include <fcntl.h> +#include <getopt.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <unistd.h> + +enum { + BUFFERSIZE = 4096, + RAND_BYTES = 128 +}; + +struct mcookie_control { + struct UL_MD5Context ctx; + char **files; + size_t nfiles; + uint64_t maxsz; + + unsigned int verbose:1; +}; + +/* The basic function to hash a file */ +static uint64_t hash_file(struct mcookie_control *ctl, int fd) +{ + unsigned char buf[BUFFERSIZE]; + uint64_t wanted, count; + + wanted = ctl->maxsz ? ctl->maxsz : sizeof(buf); + + for (count = 0; count < wanted; ) { + size_t rdsz = sizeof(buf); + ssize_t r; + + if (wanted - count < rdsz) + rdsz = wanted - count; + + r = read_all(fd, (char *) buf, rdsz); + if (r <= 0) + break; + ul_MD5Update(&ctl->ctx, buf, r); + count += r; + } + /* Separate files with a null byte */ + buf[0] = '\0'; + ul_MD5Update(&ctl->ctx, buf, 1); + return count; +} + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fputs(USAGE_HEADER, out); + fprintf(out, _(" %s [options]\n"), program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Generate magic cookies for xauth.\n"), out); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -f, --file <file> use file as a cookie seed\n"), out); + fputs(_(" -m, --max-size <num> limit how much is read from seed files\n"), out); + fputs(_(" -v, --verbose explain what is being done\n"), out); + + fputs(USAGE_SEPARATOR, out); + printf(USAGE_HELP_OPTIONS(23)); + + fputs(USAGE_ARGUMENTS, out); + printf(USAGE_ARG_SIZE(_("<num>"))); + + printf(USAGE_MAN_TAIL("mcookie(1)")); + + exit(EXIT_SUCCESS); +} + +static void randomness_from_files(struct mcookie_control *ctl) +{ + size_t i; + + for (i = 0; i < ctl->nfiles; i++) { + const char *fname = ctl->files[i]; + size_t count; + int fd; + + if (*fname == '-' && !*(fname + 1)) + fd = STDIN_FILENO; + else + fd = open(fname, O_RDONLY); + + if (fd < 0) { + warn(_("cannot open %s"), fname); + } else { + count = hash_file(ctl, fd); + if (ctl->verbose) + fprintf(stderr, + P_("Got %zu byte from %s\n", + "Got %zu bytes from %s\n", count), + count, fname); + + if (fd != STDIN_FILENO && close(fd)) + err(EXIT_FAILURE, _("closing %s failed"), fname); + } + } +} + +int main(int argc, char **argv) +{ + struct mcookie_control ctl = { .verbose = 0 }; + size_t i; + unsigned char digest[UL_MD5LENGTH]; + unsigned char buf[RAND_BYTES]; + int c; + + static const struct option longopts[] = { + {"file", required_argument, NULL, 'f'}, + {"max-size", required_argument, NULL, 'm'}, + {"verbose", no_argument, NULL, 'v'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + close_stdout_atexit(); + + while ((c = getopt_long(argc, argv, "f:m:vVh", longopts, NULL)) != -1) { + switch (c) { + case 'v': + ctl.verbose = 1; + break; + case 'f': + if (!ctl.files) + ctl.files = xmalloc(sizeof(char *) * argc); + ctl.files[ctl.nfiles++] = optarg; + break; + case 'm': + ctl.maxsz = strtosize_or_err(optarg, + _("failed to parse length")); + break; + + case 'V': + print_version(EXIT_SUCCESS); + case 'h': + usage(); + default: + errtryhelp(EXIT_FAILURE); + } + } + + if (ctl.maxsz && ctl.nfiles == 0) + warnx(_("--max-size ignored when used without --file")); + + ul_MD5Init(&ctl.ctx); + randomness_from_files(&ctl); + free(ctl.files); + + ul_random_get_bytes(&buf, RAND_BYTES); + ul_MD5Update(&ctl.ctx, buf, RAND_BYTES); + if (ctl.verbose) + fprintf(stderr, P_("Got %d byte from %s\n", + "Got %d bytes from %s\n", RAND_BYTES), + RAND_BYTES, random_tell_source()); + + ul_MD5Final(digest, &ctl.ctx); + for (i = 0; i < UL_MD5LENGTH; i++) + printf("%02x", digest[i]); + putchar('\n'); + + return EXIT_SUCCESS; +} |