summaryrefslogtreecommitdiffstats
path: root/usr.bin/passwd
diff options
context:
space:
mode:
authorbrandon <brandon@FreeBSD.org>1999-01-22 15:33:54 +0000
committerbrandon <brandon@FreeBSD.org>1999-01-22 15:33:54 +0000
commit24e41a8a156cc336679e4b22276e466118597b18 (patch)
tree1bad1b7bca108ae1c5e6d261934e31ce46668d85 /usr.bin/passwd
parent8a9d1470cd895fc3626f64d5f6ba59a550ef85ad (diff)
downloadFreeBSD-src-24e41a8a156cc336679e4b22276e466118597b18.zip
FreeBSD-src-24e41a8a156cc336679e4b22276e466118597b18.tar.gz
Added support for multiple hash formats, and new salt generation code.
It selects which hash format to use by checking /etc/auth.conf for auth_default. Leaving auth_default disabled will give the current behaviour (use the same format as is currently used in the password, or if a new password default to what crypt likes best--des if it exists). Now you can set it to one of: des, best, md5 or sha1. best is a synonym for sha1, currently.
Diffstat (limited to 'usr.bin/passwd')
-rw-r--r--usr.bin/passwd/local_passwd.c173
-rw-r--r--usr.bin/passwd/passwd.112
2 files changed, 154 insertions, 31 deletions
diff --git a/usr.bin/passwd/local_passwd.c b/usr.bin/passwd/local_passwd.c
index 6269d1e..5ad7b6b 100644
--- a/usr.bin/passwd/local_passwd.c
+++ b/usr.bin/passwd/local_passwd.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: local_passwd.c,v 1.19 1998/03/07 21:42:07 ache Exp $
+ * $Id: local_passwd.c,v 1.20 1998/05/19 03:48:07 jkoshy Exp $
*/
#ifndef lint
@@ -49,6 +49,7 @@ static const char sccsid[] = "@(#)local_passwd.c 8.3 (Berkeley) 4/2/94";
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <libutil.h>
#include <pw_copy.h>
#include <pw_util.h>
@@ -89,6 +90,146 @@ to64(s, v, n)
}
}
+/*
+** used in generating new salt
+*/
+char * gen_des_salt(char * salt, int htype, struct timeval * tvp);
+char * gen_mcf_salt(char * salt, int htype, struct timeval * tvp);
+
+#define DES_CRYPT 0 /* which index is the 'des' crypt. Do not change */
+#define BEST_CRYPT 1 /* which index is the 'best' crypt. Do not change
+ the index, change the crypt_token for the index */
+#define DEFAULT_CRYPT BEST_CRYPT /* or 0 for old behaviour */
+struct hash_type {
+ char * auth_token;
+ char * crypt_token;
+ char * (*gensalt)(char *, int, struct timeval *);
+} hash_types[] = {
+ { "des", "", gen_des_salt },
+ { "best", "SHA1", gen_mcf_salt },
+ { "md5", "MD5", gen_mcf_salt },
+ { "sha1", "SHA1", gen_mcf_salt },
+ { NULL, NULL, NULL }
+};
+
+char * gen_long_salt(char * salt, struct timeval * tvp) {
+ char * s, * p;
+ int r, x;
+
+ s = p = salt;
+
+ to64(s, random(), 2);
+ to64(s+2, tvp->tv_usec, 2);
+ s += 4;
+ for (x = 0; x < 3; x++) {
+ to64(s, random(), 4);
+ s+=4;
+ }
+ r = (random()%9) + 8;
+ p[r] = '\0';
+
+ return &salt[0];
+}
+
+char * gen_des_salt(char * salt, int htype, struct timeval * tvp) {
+#ifdef NEWSALT
+ salt[0] = _PASSWORD_EFMT1;
+ to64(&salt[1], (long)(29 * 25), 4);
+ to64(&salt[5], random(), 4);
+ salt[9] = '\0';
+ return &salt[0];
+#else
+ return gen_long_salt(salt, tvp);
+#endif
+}
+
+/*
+** Make a good size salt for algoritms that can use it,
+** infact randomize it from 8 to 16 chars in length too
+*/
+char * gen_mcf_salt(char * salt, int htype, struct timeval * tvp) {
+ char * s;
+
+ sprintf(salt, "$%s$", hash_types[htype].crypt_token);
+ s = &salt[strlen(salt)];
+ gen_long_salt(s, tvp);
+ return salt;
+}
+
+char * generate_salt(char * salt, char * curpwd) {
+ int x;
+ char * p, *s;
+ char * v = auth_getval("auth_default");
+ char sbuf[32];
+ short descrypt = 0;
+ struct timeval tv;
+
+ if (!randinit) {
+ randinit = 1;
+ srandomdev();
+ }
+ gettimeofday(&tv,0);
+
+ /* see if DES crypt is crypt()'s default */
+ p = crypt("a", "bc");
+ if (p[0] != '$')
+ descrypt = 1;
+
+ /* nothing defined, default to old behaviour */
+ if (v == NULL) {
+ if (curpwd && curpwd[0] == '$') {
+ salt[0] = '$';
+ s = &salt[1];
+ p = &curpwd[1];
+ for (;*p && isalnum(*p); s++, p++) {
+ *s = *p;
+ }
+ *s++ = '$';
+ } else {
+ s = &salt[0];
+ }
+ gen_long_salt(s, &tv);
+ return salt;
+ }
+
+ /* cleanup the auth token */
+ for (p = &v[strlen(v) - 1]; p >= v; p--) {
+ if (isalnum(*p))
+ break;
+ *p = (char) NULL;
+ }
+
+ for (x = 0; hash_types[x].crypt_token != NULL; x++) {
+ if (strcasecmp(v, hash_types[x].auth_token) == 0) {
+ if (x == DES_CRYPT && !descrypt) {
+ if (strlen(hash_types[DEFAULT_CRYPT].crypt_token))
+ x = DEFAULT_CRYPT;
+ else
+ x = BEST_CRYPT;
+ printf("WARNING: DES crypt specified in /etc/auth.conf, but crypt(3) library does\nnot have DES hash support installed. Will use default (%s) instead!\n", hash_types[x].crypt_token);
+ return (hash_types[x].gensalt)(salt, x, &tv);
+ }
+
+ /* we have a match, verify it is valid */
+ if (!strlen(hash_types[x].crypt_token))
+ return (hash_types[x].gensalt)(salt, x, &tv);
+
+ sprintf(sbuf, "$%s$", hash_types[x].crypt_token);
+ p = crypt(hash_types[x].auth_token, sbuf);
+ if (strncmp(&p[1], hash_types[x].crypt_token,
+ strlen(hash_types[x].crypt_token)))
+ {
+ printf("WARNING: Specified auth default (%s) in /etc/auth.conf is not supported\nby crypt(3) library, using best (%s) instead.\n",
+hash_types[x].auth_token, hash_types[BEST_CRYPT].crypt_token);
+ return (hash_types[BEST_CRYPT].gensalt)(salt, BEST_CRYPT, &tv);
+ }
+ return (hash_types[x].gensalt)(salt, x, &tv);
+ }
+ }
+ printf("WARNING: Specified auth default (%s) in /etc/auth.conf is not recognized.\nUsing best type (%s) instead.\n", v, hash_types[BEST_CRYPT].crypt_token);
+ return (hash_types[BEST_CRYPT].gensalt)(salt, BEST_CRYPT, &tv);
+}
+
char *
getnewpasswd(pw, nis)
struct passwd *pw;
@@ -100,7 +241,6 @@ getnewpasswd(pw, nis)
login_cap_t * lc;
#endif
char buf[_PASSWORD_LEN+1], salt[10];
- struct timeval tv;
if (!nis)
(void)printf("Changing local password for %s.\n", pw->pw_name);
@@ -152,34 +292,7 @@ getnewpasswd(pw, nis)
break;
(void)printf("Mismatch; try again, EOF to quit.\n");
}
- /* grab a random printable character that isn't a colon */
- if (!randinit) {
- randinit = 1;
- srandomdev();
- }
-#ifdef NEWSALT
- salt[0] = _PASSWORD_EFMT1;
- to64(&salt[1], (long)(29 * 25), 4);
- to64(&salt[5], random(), 4);
- salt[9] = '\0';
-#else
- /* Make a good size salt for algoritms that can use it. */
- gettimeofday(&tv,0);
- if (strncmp(pw->pw_passwd, "$1$", 3)) {
- /* DES Salt */
- to64(&salt[0], random(), 3);
- to64(&salt[3], tv.tv_usec, 3);
- to64(&salt[6], tv.tv_sec, 2);
- salt[8] = '\0';
- }
- else {
- /* MD5 Salt */
- strncpy(&salt[0], "$1$", 3);
- to64(&salt[3], random(), 3);
- to64(&salt[6], tv.tv_usec, 3);
- salt[8] = '\0';
- }
-#endif
+ generate_salt(salt, pw->pw_passwd);
return (crypt(buf, salt));
}
diff --git a/usr.bin/passwd/passwd.1 b/usr.bin/passwd/passwd.1
index 9628811..25a699a 100644
--- a/usr.bin/passwd/passwd.1
+++ b/usr.bin/passwd/passwd.1
@@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)passwd.1 8.1 (Berkeley) 6/6/93
-.\" $Id: passwd.1,v 1.10 1998/10/09 06:38:33 markm Exp $
+.\" $Id: passwd.1,v 1.11 1998/11/30 22:41:58 billf Exp $
.\"
.Dd June 6, 1993
.Dt PASSWD 1
@@ -173,6 +173,14 @@ Do not automatically override the password authentication checks for the
super-user on the NIS master server; assume 'old' mode instead. This
flag is of limited practical use but is useful for testing.
.El
+.Sh PASSWORD HASH FORMATS
+.Pp
+The type of password hash which is stored is configured through the file
+.Pa /etc/auth.conf
+using the variable auth_default. Furthermore, passwd can only support
+hash formats which are supported by your
+.Xr crypt 3
+library.
.Sh FILES
.Bl -tag -width /etc/master.passwd -compact
.It Pa /etc/master.passwd
@@ -191,6 +199,8 @@ configure authentication services
.Xr kerberos 1 ,
.Xr kinit 1 ,
.Xr login 1 ,
+.Xr crypt 3 ,
+.Xr auth.conf 5 ,
.Xr login.conf 5 ,
.Xr passwd 5 ,
.Xr kpasswdd 8 ,
OpenPOWER on IntegriCloud