(root)/
util-linux-2.39/
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 "c.h"
      22  #include "md5.h"
      23  #include "nls.h"
      24  #include "closestream.h"
      25  #include "randutils.h"
      26  #include "strutils.h"
      27  #include "xalloc.h"
      28  #include "all-io.h"
      29  
      30  #include <fcntl.h>
      31  #include <getopt.h>
      32  #include <stddef.h>
      33  #include <stdio.h>
      34  #include <stdlib.h>
      35  #include <sys/time.h>
      36  #include <unistd.h>
      37  
      38  enum {
      39  	BUFFERSIZE = 4096,
      40  	RAND_BYTES = 128
      41  };
      42  
      43  struct mcookie_control {
      44  	struct	UL_MD5Context ctx;
      45  	char	**files;
      46  	size_t	nfiles;
      47  	uint64_t maxsz;
      48  
      49  	unsigned int verbose:1;
      50  };
      51  
      52  /* The basic function to hash a file */
      53  static uint64_t hash_file(struct mcookie_control *ctl, int fd)
      54  {
      55  	unsigned char buf[BUFFERSIZE];
      56  	uint64_t wanted, count;
      57  
      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;
      70  		ul_MD5Update(&ctl->ctx, buf, r);
      71  		count += r;
      72  	}
      73  	/* Separate files with a null byte */
      74  	buf[0] = '\0';
      75  	ul_MD5Update(&ctl->ctx, buf, 1);
      76  	return count;
      77  }
      78  
      79  static void __attribute__((__noreturn__)) usage(void)
      80  {
      81  	FILE *out = stdout;
      82  	fputs(USAGE_HEADER, out);
      83  	fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
      84  
      85  	fputs(USAGE_SEPARATOR, out);
      86  	fputs(_("Generate magic cookies for xauth.\n"), out);
      87  
      88  	fputs(USAGE_OPTIONS, out);
      89  	fputs(_(" -f, --file <file>     use file as a cookie seed\n"), out);
      90  	fputs(_(" -m, --max-size <num>  limit how much is read from seed files\n"), out);
      91  	fputs(_(" -v, --verbose         explain what is being done\n"), out);
      92  
      93  	fputs(USAGE_SEPARATOR, out);
      94  	printf(USAGE_HELP_OPTIONS(23));
      95  
      96  	fputs(USAGE_ARGUMENTS, out);
      97  	printf(USAGE_ARG_SIZE(_("<num>")));
      98  
      99  	printf(USAGE_MAN_TAIL("mcookie(1)"));
     100  
     101  	exit(EXIT_SUCCESS);
     102  }
     103  
     104  static void randomness_from_files(struct mcookie_control *ctl)
     105  {
     106  	size_t i;
     107  
     108  	for (i = 0; i < ctl->nfiles; i++) {
     109  		const char *fname = ctl->files[i];
     110  		size_t count;
     111  		int fd;
     112  
     113  		if (*fname == '-' && !*(fname + 1))
     114  			fd = STDIN_FILENO;
     115  		else
     116  			fd = open(fname, O_RDONLY);
     117  
     118  		if (fd < 0) {
     119  			warn(_("cannot open %s"), fname);
     120  		} else {
     121  			count = hash_file(ctl, fd);
     122  			if (ctl->verbose)
     123  				fprintf(stderr,
     124  					P_("Got %zu byte from %s\n",
     125  					   "Got %zu bytes from %s\n", count),
     126  					count, fname);
     127  
     128  			if (fd != STDIN_FILENO && close(fd))
     129  				err(EXIT_FAILURE, _("closing %s failed"), fname);
     130  		}
     131  	}
     132  }
     133  
     134  int main(int argc, char **argv)
     135  {
     136  	struct mcookie_control ctl = { .verbose = 0 };
     137  	size_t i;
     138  	unsigned char digest[UL_MD5LENGTH];
     139  	unsigned char buf[RAND_BYTES];
     140  	int c;
     141  
     142  	static const struct option longopts[] = {
     143  		{"file", required_argument, NULL, 'f'},
     144  		{"max-size", required_argument, NULL, 'm'},
     145  		{"verbose", no_argument, NULL, 'v'},
     146  		{"version", no_argument, NULL, 'V'},
     147  		{"help", no_argument, NULL, 'h'},
     148  		{NULL, 0, NULL, 0}
     149  	};
     150  
     151  	setlocale(LC_ALL, "");
     152  	bindtextdomain(PACKAGE, LOCALEDIR);
     153  	textdomain(PACKAGE);
     154  	close_stdout_atexit();
     155  
     156  	while ((c = getopt_long(argc, argv, "f:m:vVh", longopts, NULL)) != -1) {
     157  		switch (c) {
     158  		case 'v':
     159  			ctl.verbose = 1;
     160  			break;
     161  		case 'f':
     162  			if (!ctl.files)
     163  				ctl.files = xmalloc(sizeof(char *) * argc);
     164  			ctl.files[ctl.nfiles++] = optarg;
     165  			break;
     166  		case 'm':
     167  			ctl.maxsz = strtosize_or_err(optarg,
     168  						     _("failed to parse length"));
     169  			break;
     170  
     171  		case 'V':
     172  			print_version(EXIT_SUCCESS);
     173  		case 'h':
     174  			usage();
     175  		default:
     176  			errtryhelp(EXIT_FAILURE);
     177  		}
     178  	}
     179  
     180  	if (ctl.maxsz && ctl.nfiles == 0)
     181  		warnx(_("--max-size ignored when used without --file"));
     182  
     183  	ul_MD5Init(&ctl.ctx);
     184  	randomness_from_files(&ctl);
     185  	free(ctl.files);
     186  
     187  	ul_random_get_bytes(&buf, RAND_BYTES);
     188  	ul_MD5Update(&ctl.ctx, buf, RAND_BYTES);
     189  	if (ctl.verbose)
     190  		fprintf(stderr, P_("Got %d byte from %s\n",
     191  				   "Got %d bytes from %s\n", RAND_BYTES),
     192  				RAND_BYTES, random_tell_source());
     193  
     194  	ul_MD5Final(digest, &ctl.ctx);
     195  	for (i = 0; i < UL_MD5LENGTH; i++)
     196  		printf("%02x", digest[i]);
     197  	putchar('\n');
     198  
     199  	return EXIT_SUCCESS;
     200  }