Add working and easy crypt(3)-switching. Yes, we need a whole new API

for crypt(3) by now.  In any case:

Add crypt_set_format(3) + documentation to -lcrypt.
Add login_setcryptfmt(3) + documentation to -lutil.
Support for switching crypt formats in passwd(8).
Support for switching crypt formats in pw(8).

The simple synopsis is:
edit login.conf; add a passwd_format field set to "des" or "md5"; go nuts :)

Reviewed by:	peter
This commit is contained in:
Brian Feldman 2000-08-22 02:15:54 +00:00
parent ac951e620c
commit 04c9749ff0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64918
13 changed files with 167 additions and 36 deletions

View File

@ -120,6 +120,8 @@ char *brk __P((const char *));
int chroot __P((const char *));
size_t confstr __P((int, char *, size_t));
char *crypt __P((const char *, const char *));
const char *crypt_get_format __P((void));
int crypt_set_format __P((const char *));
int des_cipher __P((const char *, char *, long, int));
int des_setkey __P((const char *key));
int encrypt __P((char *, int));

View File

@ -17,9 +17,10 @@ SONAME= ${LCRYPTSO}
.PATH: ${.CURDIR}/../libmd
SRCS= crypt.c crypt-md5.c misc.c
STATICSRCS= md5c.c
STATICSRCS= md5c.c sha1c.c
STATICOBJS= ${STATICSRCS:S/.c/.o/g}
MAN3= crypt.3
MLINKS= crypt.3 crypt_get_format.3 crypt.3 crypt_set_format.3
CFLAGS+= -I${.CURDIR}/../libmd
CFLAGS+= -DLIBC_SCCS -Wall
PRECIOUSLIB= yes

View File

@ -43,6 +43,10 @@
.Fd #include <unistd.h>
.Ft char *
.Fn crypt "const char *key" "const char *salt"
.Ft const char *
.Fn crypt_get_format "void"
.Ft int
.Fn crypt_set_format "const char *string"
.Sh DESCRIPTION
The
.Fn crypt
@ -59,10 +63,12 @@ Currently these include the
.Tn Data Encryption Standard (DES) ,
and
.Tn MD5 .
The algorithm used will depend upon the format of the Salt--following
the Modular Crypt Format (MCF)--and if
The algorithm used will depend upon the format of the Salt (following
the Modular Crypt Format (MCF)), if
.Tn DES
is installed or not.
is installed or not, and whether
.Fn crypt_set_format
has been called to change the default.
.Pp
The first argument to
.Nm
@ -177,10 +183,15 @@ Other crypt formats may be easilly added. An example salt would be:
.Ss "Traditional" crypt:
.Pp
The algorithm used will depend upon whether
.Fn crypt_set_format
has been called and whether
.Tn DES
is installed or not. If it is,
is installed or not. If
.Tn DES
will be used. Otherwise, the best algorithm is used, which is currently
is installed and
.Fn crypt_set_format
has not set the format to something else, it will be used.
Otherwise, the best algorithm is used, which is currently
.\"
.\" NOTICE: Also make sure to update this
.\"
@ -188,6 +199,23 @@ MD5.
.Pp
How the salt is used will depend upon the algorithm for the hash. For
best results, specify at least two characters of salt.
.Pp
The
.Fn crypt_get_format
function returns a constant string that represents the name of the
algorithm currently used.
Valid values are
.\"
.\" NOTICE: Also make sure to update this, too, as well
.\"
.Ql des
and
.Ql md5 .
.Pp
The
.Fn crypt_set_format
function sets the default encoding format according to the supplied
.Fa string .
.Sh RETURN VALUES
.Pp
.Fn crypt
@ -195,6 +223,10 @@ returns a pointer to the encrypted value on success, and NULL on failure.
Note: this is not a standard behaviour, AT&T
.Fn crypt
will always return a pointer to a string.
.Pp
.Fn crypt_set_format
will return 1 if the supplied encoding format was valid.
Otherwise, a value of 0 is returned.
.Sh SEE ALSO
.Xr login 1 ,
.Xr passwd 1 ,
@ -206,7 +238,9 @@ The
.Fn crypt
function returns a pointer to static data, and subsequent calls to
.Fn crypt
will modify the same data.
will modify the same data. Likewise,
.Fn crypt_set_format
modifies static data.
.Sh HISTORY
A rotor-based
.Fn crypt
@ -230,6 +264,7 @@ Originally written by
.An David Burren Aq davidb@werj.com.au ,
later additions and changes by
.An Poul-henning Kamp ,
.An Mark R V Murray
and
.An Mark R V Murray ,
.An Kris Kennaway .
and
.An Brian Feldman .

View File

@ -34,14 +34,57 @@ static char rcsid[] = "$FreeBSD$";
#include <string.h>
#include "crypt.h"
static const struct {
const char *const name;
char *(*const func)(const char *, const char *);
const char *const magic;
} crypt_types[] = {
{
"des",
crypt_des,
NULL
},
{
"md5",
crypt_md5,
"$1$"
},
{
NULL,
NULL
}
};
static int crypt_type = 0;
const char *
crypt_get_format(void) {
return (crypt_types[crypt_type].name);
}
int
crypt_set_format(char *type) {
int i;
for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
if (strcmp(type, crypt_types[i].name) == 0) {
crypt_type = i;
return (1);
}
}
return (0);
}
char *
crypt(char *passwd, char *salt)
{
if (!strncmp(salt, "$1$", 3))
return crypt_md5(passwd, salt);
#ifdef NONEXPORTABLE_CRYPT
return crypt_des(passwd, salt);
#else
return crypt_md5(passwd, salt);
#endif
int i;
for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
if (crypt_types[i].magic != NULL && strncmp(salt,
crypt_types[i].magic, strlen(crypt_types[i].magic)) == 0)
return (crypt_types[i].func(passwd, salt));
}
return (crypt_types[crypt_type].func(passwd, salt));
}

View File

@ -29,7 +29,6 @@
/* magic sizes */
#define MD5_SIZE 16
#define SHS_SIZE 20
char *crypt_des(const char *pw, const char *salt);
char *crypt_md5(const char *pw, const char *salt);

View File

@ -10,6 +10,10 @@ SRCS= login.c login_tty.c logout.c logwtmp.c pty.c setproctitle.c \
login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
_secure_path.c uucplock.c property.c auth.c realhostname.c fparseln.c
INCS= libutil.h login_cap.h
LDADD+= -lcrypt
DPADD+= ${LIBCRYPT}
MAN3+= login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
setproctitle.3 login_cap.3 login_class.3 login_times.3 login_ok.3 \
_secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
@ -25,7 +29,7 @@ MLINKS+=login_cap.3 login_getclassbyname.3 login_cap.3 login_close.3 \
login_cap.3 login_getstyle.3 login_cap.3 login_getcaptime.3 \
login_cap.3 login_getcapnum.3 login_cap.3 login_getcapsize.3 \
login_cap.3 login_getcapbool.3 login_cap.3 login_getpath.3 \
login_cap.3 login_getpwclass.3
login_cap.3 login_getpwclass.3 login_cap.3 login_setcryptfmt.3
MLINKS+=login_class.3 setusercontext.3 login_class.3 setclasscontext.3 \
login_class.3 setclassenvironment.3 login_class.3 setclassresources.3
MLINKS+=login_times.3 parse_lt.3 login_times.3 in_ltm.3 \

View File

@ -34,7 +34,8 @@
.Nm login_getclassbyname ,
.Nm login_getpwclass ,
.Nm login_getstyle ,
.Nm login_getuserclass
.Nm login_getuserclass ,
.Nm login_setcryptfmt
.Nd functions for accessing the login class capabilities database.
.Sh LIBRARY
.Lb libutil
@ -67,6 +68,8 @@
.Fn login_getcapbool "login_cap_t *lc" "const char *cap" "int def"
.Ft char *
.Fn login_getstyle "login_cap_t *lc" "char *style" "const char *auth"
.Ft const char *
.Fn login_setcryptfmt "login_cap_t *lc" "const char *def" "const char *error"
.Sh DESCRIPTION
These functions represent a programming interface to the login
classes database provided in
@ -396,8 +399,25 @@ the authentication method used for access to the system via the
network, and standard methods via direct dialup or console
logins, significantly reducing the risk of password discovery
by "snooping" network packets.
.It Fn login_setcryptfmt
The
.Fn login_setcryptfmt
function is used to set the
.Xr crypt 3
format using the
.Ql passwd_format
configuration entry.
If no entry is found,
.Fa def
is taken to be used as the fallback.
If calling
.Xr crypt_set_format 3
on the specifier fails,
.Fa error
is returned to indicate this.
.El
.Sh SEE ALSO
.Xr crypt 3 ,
.Xr getcap 3 ,
.Xr login_class 3 ,
.Xr login.conf 5 ,

View File

@ -798,3 +798,16 @@ login_getstyle(login_cap_t *lc, char *style, const char *auth)
return lc->lc_style;
}
const char *
login_setcryptfmt(login_cap_t *lc, const char *def, const char *error)
{
const char *cipher;
cipher = login_getcapstr(lc, "passwd_format", def, NULL);
if (cipher == NULL)
return (error);
if (!crypt_set_format(cipher))
return (error);
return (cipher);
}

View File

@ -110,6 +110,7 @@ rlim_t login_getcapnum __P((login_cap_t *, const char *, rlim_t, rlim_t));
rlim_t login_getcapsize __P((login_cap_t *, const char *, rlim_t, rlim_t));
char *login_getpath __P((login_cap_t *, const char *, char *));
int login_getcapbool __P((login_cap_t *, const char *, int));
const char *login_setcryptfmt __P((login_cap_t *, const char *, const char *));
int setclasscontext __P((const char*, unsigned int));
int setusercontext __P((login_cap_t*, const struct passwd*, uid_t, unsigned int));

View File

@ -21,6 +21,7 @@ STATICSRCS= md5c.c
STATICOBJS= ${STATICSRCS:S/.c/.o/g}
SRCS+= crypt-des.c
MAN3= crypt.3
MLINKS= crypt.3 crypt_get_format.3 crypt.3 crypt_set_format.3
CFLAGS+= -I${.CURDIR}/../../../lib/libmd
CFLAGS+= -I${.CURDIR}/../../../lib/libcrypt
CFLAGS+= -DNONEXPORTABLE_CRYPT

View File

@ -172,20 +172,13 @@ getnewpasswd(pw, nis)
#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';
}
if (login_setcryptfmt(lc, "md5", NULL) == NULL)
pw_error("cannot set password cipher", 1, 1);
/* Salt suitable for anything */
to64(&salt[0], random(), 3);
to64(&salt[3], tv.tv_usec, 3);
to64(&salt[6], tv.tv_sec, 2);
salt[8] = '\0';
#endif
return (crypt(buf, salt));
}

View File

@ -11,8 +11,8 @@ MAN8= pw.8
#RND= -DUSE_MD5RAND
CFLAGS+= -W -Wall $(CDB) $(RND)
LDADD= -lcrypt
DPADD= ${LIBCRYPT}
LDADD= -lcrypt -lutil
DPADD= ${LIBCRYPT} ${LIBUTIL}
BINMODE=0555

View File

@ -42,6 +42,7 @@ static const char rcsid[] =
#include <sys/resource.h>
#include <unistd.h>
#include <utmp.h>
#include <login_cap.h>
#if defined(USE_MD5RAND)
#include <md5.h>
#endif
@ -544,11 +545,19 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
}
if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) {
login_cap_t *lc;
lc = login_getpwclass(pwd);
if (lc == NULL ||
login_setcryptfmt(lc, "md5", NULL) == NULL)
warn("setting crypt(3) format");
login_close(lc);
pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
edited = 1;
}
} else {
login_cap_t *lc;
/*
* Add code
@ -565,13 +574,17 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
pwd = &fakeuser;
pwd->pw_name = a_name->val;
pwd->pw_class = cnf->default_class ? cnf->default_class : "";
pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
pwd->pw_uid = pw_uidpolicy(cnf, args);
pwd->pw_gid = pw_gidpolicy(cnf, args, pwd->pw_name, (gid_t) pwd->pw_uid);
pwd->pw_change = pw_pwdpolicy(cnf, args);
pwd->pw_expire = pw_exppolicy(cnf, args);
pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name);
pwd->pw_shell = pw_shellpolicy(cnf, args, NULL);
lc = login_getpwclass(pwd);
if (lc == NULL || login_setcryptfmt(lc, "md5", NULL) == NULL)
warn("setting crypt(3) format");
login_close(lc);
pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
edited = 1;
if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
@ -600,6 +613,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
int b;
int istty = isatty(fd);
struct termios t;
login_cap_t *lc;
if (istty) {
if (tcgetattr(fd, &t) == -1)
@ -629,6 +643,11 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
*p = '\0';
if (!*line)
errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
lc = login_getpwclass(pwd);
if (lc == NULL ||
login_setcryptfmt(lc, "md5", NULL) == NULL)
warn("setting crypt(3) format");
login_close(lc);
pwd->pw_passwd = pw_pwcrypt(line);
edited = 1;
}