Bug 28885

Summary: [patch] enhance makekey to check/generate MD5 passwords
Product: Base System Reporter: Gregory Bond <gnb>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.3-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Gregory Bond 2001-07-11 01:30:02 UTC
Makekey can be used from other programs to encrypt passwords.  But it is
very awkward to use from a script or the command line, and only produces
DES encryptions.

These patches extend makekey to handle MD5 passwords and make it much more
convenient to use from a script or the command line, for example when 
populating passwd-like files for WEB/IRC/whatever servers. It is now also
able to check passwords.

How-To-Repeat: 
Examine makekey manual page. Attempt to use it from a shell script!
Comment 1 dima 2001-07-11 02:40:32 UTC
Gregory Bond <gnb@itga.com.au> writes:
> >Description:
> 
> Makekey can be used from other programs to encrypt passwords.  But it is
> very awkward to use from a script or the command line, and only produces
> DES encryptions.
> 
> These patches extend makekey to handle MD5 passwords and make it much more
> convenient to use from a script or the command line, for example when 
> populating passwd-like files for WEB/IRC/whatever servers. It is now also
> able to check passwords.

I don't think this is desired.  makekey is a very simple program with
a very simple purpose: to take a salt and a string and produce a DES
hash.  You're not *supposed* to use it for MD5; you're not *supposed*
to use it in a script; it isn't supposed to be used to check
passwords.  For an example of how it's supposed to be used, see
src/usr.bin/enigma/enigma.c (and I think your patch even breaks this
case).

What you're looking for is a command-line interface to crypt(3), and
makekey isn't, and shouldn't be, it.  One is, however, quite trivial
to write; I did so a few years ago and my version works great for me.
(I've attached the source for anyone who wants it.)  I think that
something along these lines, perhaps from the ports, is much better
than screwing around with makekey's simple life.

Regards,

					Dima Dorfman
					dima@unixfreak.org

/*
 * Copyright (c) 1999, Dima Dorfman.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Command line interface to the crypt(3) family of routines.
 */

#include <err.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static char *mksalt(void);
static void usage(void);

/*
 * Returns pointer to static buffer.
 */
static char *
mksalt(void)
{
	static char output[33];
	static const char range[] =
	    "abcdefghijklmnopqrstuvwxyz"
	    "0123456789"
	    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	char *p;

	for (p = output; p < output + sizeof(output) - 1; p++)
		*p = range[arc4random() % (sizeof(range) - 1)];
	output[sizeof(output) - 1] = '\0';
	return (output);
}

static void
usage(void)
{

	fprintf(stderr, "Usage: %s [-n] [-f type] [-s salt] [password ...]\n",
	    getprogname());
	exit(1);
}

int
main(int ac, char **av)
{
	int newline, passfree;		/* Output trailing NL?  free() pass? */
	char *salt, *pass;       	/* Arguments to crypt(3). */
	char *sum;			/* crypt(3) result. */
	char c;
	char *p, **xp;
	int passlen, rv;

	newline = 1;
	salt = NULL;
	while ( (c = getopt(ac, av, "f:ns:")) != -1)
		switch (c) {
		case 'f':
			rv = crypt_set_format(optarg);
			if (rv == 0)
				errx(1, "invalid format: %s", optarg);
			break;
		case 'n':
			newline = 0;
			break;
		case 's':
			salt = optarg;
			break;
		default:
			usage();
		}
	ac -= optind;
	av += optind;

	if (salt == NULL)
		salt = mksalt();

	if (ac == 0) {
		pass = getpass("Password: ");
		passfree = 0;
	} else {
		passlen = 0;
		for (xp = av; xp < &av[ac]; xp++)
			passlen += strlen(*xp);
		passlen += ac + 1; /* XXX is this right? */
		pass = malloc(passlen);
		pass[0] = '\0';
		for (xp = av; xp < &av[ac]; xp++) {
			strlcat(pass, *xp, passlen);
			strlcat(pass, " ", passlen);
		}
		p = strchr(pass, '\0');
		*--p = '\0';
		passfree = 1;
	}

	sum = crypt(pass, salt);
	printf("%s%s", sum, newline ? "\n" : "");

	if (passfree)
		free(pass);
	return (0);
}
Comment 2 Gregory Bond 2001-07-11 06:02:42 UTC
>I don't think this is desired.  makekey is a very simple program with
>a very simple purpose: to take a salt and a string and produce a DES
>hash. 

I understand this, but I did ask for suggestions and got none better!  It seems
crazy this function is not available anywhere in the base system, thus forcing
application writers to reinvent this particular wheel, usually in a way that is
not compatible with FreeBSD's evolving crypto infrastructure.  

I can see 6 ways forward:
 1 - Accept the patches to makekey
 2 - Develop equivalent patches to pw(8)
 3 - Produce a new program in the base system for just this job
 4 - Produce a new port for this job
 5 - Ignore the problem and stick with the status quo.
 6 - Decide it's not a problem at all

I've done #1, I'm happy to do either #2 or #3 if TPTB think it is better and it
might get committed, but #4 and #5 don't seem to fill this (perceived?) need.
In particular, #4 won't be widely used by other application writers. I don't
think #6 is true because I was bit by this problem and motivated to produce
this PR!

> For an example of how it's supposed to be used, see
> src/usr.bin/enigma/enigma.c (and I think your patch even breaks this
> case).

It shouldn't.  If no args are present, then the patched version calls the 
exact same code as the original. Quick tests indicate enigma still works as 
expected.

Greg.
Comment 3 Gregory Bond 2001-07-12 00:37:18 UTC
Kris Kennaway has pointed out the "openssl passwd" command that is built in to
the system and will do the job just fine.  Perhaps this pointer could be added
to the SEE ALSO section of makekey?

This PR can be closed.
Comment 4 dd freebsd_committer freebsd_triage 2001-07-15 12:24:43 UTC
State Changed
From-To: open->closed

requested by originator