From gnb@itga.com.au  Tue Jul 10 17:25:27 2001
Return-Path: <gnb@itga.com.au>
Received: from ns.itga.com.au (ns.itga.com.au [202.53.40.210])
	by hub.freebsd.org (Postfix) with ESMTP id 1C72237B40C
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 10 Jul 2001 17:25:26 -0700 (PDT)
	(envelope-from gnb@itga.com.au)
Received: from lightning.itga.com.au (lightning.itga.com.au [192.168.71.20])
	by ns.itga.com.au (8.9.3/8.9.3) with ESMTP id KAA95953
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 11 Jul 2001 10:25:24 +1000 (EST)
	(envelope-from gnb@itga.com.au)
Received: from hellcat.itga.com.au (hellcat.itga.com.au [192.168.71.163])
	by lightning.itga.com.au (8.9.3/8.9.3) with ESMTP id KAA26489;
	Wed, 11 Jul 2001 10:24:08 +1000 (EST)
Received: (from gnb@localhost)
	by hellcat.itga.com.au (8.11.4/8.11.4) id f6B0O8P03091;
	Wed, 11 Jul 2001 10:24:08 +1000 (EST)
	(envelope-from gnb)
Message-Id: <200107110024.f6B0O8P03091@hellcat.itga.com.au>
Date: Wed, 11 Jul 2001 10:24:08 +1000 (EST)
From: Gregory Bond <gnb@itga.com.au>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] enhance makekey to check/generate MD5 passwords
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         28885
>Category:       bin
>Synopsis:       [patch] enhance makekey to check/generate MD5 passwords
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 10 17:30:02 PDT 2001
>Closed-Date:    Sun Jul 15 04:24:43 PDT 2001
>Last-Modified:  Sun Jul 15 04:24:56 PDT 2001
>Originator:     Gregory Bond
>Release:        FreeBSD 4.3-STABLE i386
>Organization:
ITG Australia Limited
>Environment:
System: FreeBSD hellcat.itga.com.au 4.3-STABLE FreeBSD 4.3-STABLE #21: Mon Jun 18 13:41:36 EST 2001 toor@hellcat.itga.com.au:/usr/obj/usr/src/sys/Hellcat i386


>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.

>How-To-Repeat:

Examine makekey manual page. Attempt to use it from a shell script!

>Fix:

Index: makekey/makekey.8
===================================================================
RCS file: /usr/ncvs/src/libexec/makekey/makekey.8,v
retrieving revision 1.9.2.1
diff -u -r1.9.2.1 makekey.8
--- makekey/makekey.8	2000/12/08 13:52:29	1.9.2.1
+++ makekey/makekey.8	2001/07/11 00:09:05
@@ -37,24 +37,97 @@
 .Os
 .Sh NAME
 .Nm makekey
-.Nd make encrypted keys or passwords
+.Nd make and check encrypted keys or passwords
 .Sh SYNOPSIS
 .Nm
+.Op Fl m | Fl d | Fl u
+.Op Fl p Ar password
+.Op Fl s Ar salt
+.Op Fl n
 .Sh DESCRIPTION
-.Nm Makekey
-encrypts a key and salt which it reads from the standard input
-and writes the result to the standard output.
-The key is expected to be
-eight bytes; the salt is expected to be two bytes.
+When called with no arguments,
+.Nm 
+runs in compatibility mode.  It reads exactly 8 bytes of key and 2
+bytes of salt from standard input, and produces exactly 13 bytes of
+DES encrypted password on standard out (with no trailing newline).
+.Pp
+When called with arguments,
+.Nm
+encrypts a password and prints it on standard
+output, followed by a newline.
+.Pp
 See
 .Xr crypt 3
 for more information on what characters the key and salt can contain
 and how the encrypted value is calculated.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl m
+Encrypt the password using the MD5 password algorithm.
+.Pp
+.It Fl d
+Encrypt the password using the DES password algorithm (if available).
+.Pp
+.It Fl u
+Encrypt the password using the default algorithm as specified by the 
+.Cm crypt_default
+entry in the
+.Pa /etc/auth.conf
+file.  This is the default if neither 
+.Fl m
+nor 
+.Fl d
+are specified.
+.Pp
+.It Fl s Ar salt
+Use the supplied salt rather than a new randomly-generated salt.
+.Pp
+.It Fl n
+Rather than print the encrypted password on standard out, compare it
+to the version passed in via the 
+.Fl s Ar salt
+argument, and exit with return status of 0 if they compare equal, else
+1.
+.Pp
+.It Fl p Ar password
+Use 
+.Ar password
+as the plaintext password.  If
+.Fl p
+is not specified, 
+.Nm
+will prompt for a passord using the
+.Xr getpass 3
+function.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+$ makekey -p secret -m
+$1$V6VfDBZZ$GM2ZBo0c5bh1HG0etveAq.
+$ makekey -p secret -d -s 3D
+3DzkIA460ybsA
+$ makekey -p secret -s 3DzkIA460ybsA -n
+$ echo $?
+0
+$ makekey -p wrong -s 3DzkIA460ybsA -n
+$ echo $?
+1
+$ makekey -u
+Enter password: <password>
+l9hDu91z3G1rY
+$
+.Ed
+.Sh FILES
+.Bl -tag -compact
+.It Pa /etc/auth.conf
 .Sh SEE ALSO
 .Xr login 1 ,
-.Xr crypt 3
+.Xr crypt 3 ,
+.Xr getpass 3 ,
+.Xr auth.conf 5
 .Sh HISTORY
 A
 .Nm
 command appeared in
 .At v7 .
+The handling of arguments was added in 
+.Fx 4.4 .
Index: makekey/makekey.c
===================================================================
RCS file: /usr/ncvs/src/libexec/makekey/makekey.c,v
retrieving revision 1.8
diff -u -r1.8 makekey.c
--- makekey/makekey.c	1999/08/28 00:09:39	1.8
+++ makekey/makekey.c	2001/07/10 23:31:33
@@ -55,9 +55,111 @@
 #include <unistd.h>
 
 static void get __P((char *, int));
+static void olddes __P((void));
+static void usage __P((void));
 
+static char const saltchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
+
 int
-main()
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int c;
+	int opt_d = 0;
+	int opt_m = 0;
+	int opt_n = 0;
+	int opt_u = 0;
+	char *sp = 0;
+	char *pass = 0;
+	char salt[256];
+
+	if (argc == 1)
+		olddes();
+
+	while ((c = getopt(argc, argv, "dmnp:s:u")) != -1) {
+		switch (c) {
+		case 'd':
+			opt_d = 1;
+			break;
+		case 'm':
+			opt_m = 1;
+			break;
+		case 'n':
+			opt_n = 1;
+			break;
+		case 'p':
+			pass = optarg;
+			break;
+		case 's':
+			sp = optarg;
+			break;
+		case 'u':
+			opt_u = 1;
+			break;
+		case '?':
+		default:
+			warn("Unrecognised option %c\n", c);
+			usage();
+		}
+	}
+	if (optind != argc)
+		usage();
+	if (opt_m + opt_d + opt_u > 1)
+		usage();
+
+	if (sp) {
+		char *p, *q;
+
+		for (p = sp, q = salt; *p; p++, q++) {
+			if (*p != '$' && strchr(saltchars, *p) == NULL)
+				errx(2, "Illegal character in salt");
+			if (q >= salt + sizeof(salt)) 
+				errx(2, "Salt too long");
+			*q = *p;
+		}
+		*q = 0;
+	} else {	
+		int i;
+
+		srandomdev();
+
+		for (i = 0; i < 8; i++)
+			salt[i] = saltchars[random() % 64];
+		salt[8] = 0;
+	}
+	
+	if (pass == 0) 
+		pass = getpass("Enter password:");
+
+	if (opt_d || opt_m) 
+		if (!crypt_set_format(opt_m ? "md5" : "des")) 
+			warn("setting crypt(3) format");
+
+	if (opt_n) {
+		if (!sp) 
+			errx(2, "No salt provided with -n");
+		exit(strcmp(salt, crypt(pass, salt)) != 0);
+	} else {
+		printf("%s\n", crypt(pass, salt));
+		exit(0);
+	}
+}
+
+static void
+usage()
+{
+	fprintf(stderr, "usage: makekey [-m|-d|-u] [-s salt] [-p passwd] [-n]\n");
+	exit(1);
+}
+
+/* 
+ * Old behaviour for DES passwords
+ * read exactly 8 bytes of passwd and 2 bytes of salt and print the crypt 
+ * output 
+ */
+static void
+olddes()
 {
 	int len;
 	char *r, key[9], salt[3];
>Release-Note:
>Audit-Trail:

From: Dima Dorfman <dima@unixfreak.org>
To: Gregory Bond <gnb@itga.com.au>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/28885: [patch] enhance makekey to check/generate MD5 passwords 
Date: Tue, 10 Jul 2001 18:40:32 -0700

 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);
 }

From: Gregory Bond <gnb@itga.com.au>
To: Dima Dorfman <dima@unixfreak.org>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/28885: [patch] enhance makekey to check/generate MD5 passwords 
Date: Wed, 11 Jul 2001 15:02:42 +1000

 >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.
 
 

From: Gregory Bond <gnb@itga.com.au>
To: Dima Dorfman <dima@unixfreak.org>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/28885: [patch] enhance makekey to check/generate MD5 passwords 
Date: Thu, 12 Jul 2001 09:37:18 +1000

 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.
 
 
State-Changed-From-To: open->closed 
State-Changed-By: dd 
State-Changed-When: Sun Jul 15 04:24:43 PDT 2001 
State-Changed-Why:  
requested by originator 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=28885 
>Unformatted:
