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:
parent
ac951e620c
commit
04c9749ff0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64918
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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 .
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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 ,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
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';
|
||||
}
|
||||
else {
|
||||
/* MD5 Salt */
|
||||
strncpy(&salt[0], "$1$", 3);
|
||||
to64(&salt[3], random(), 3);
|
||||
to64(&salt[6], tv.tv_usec, 3);
|
||||
salt[8] = '\0';
|
||||
}
|
||||
#endif
|
||||
return (crypt(buf, salt));
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user