Subject: Re: crypt(3)
To: None <firstname.lastname@example.org>
From: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
Date: 11/17/1994 07:42:04
>> What about modifying the programs which do login-related password
>> checking to use an intermediate interface, such that crypt() itself
>> did not have to be replaced, but rather the "intermediate interface"
>> could be re-written to use another crypt-like function?
This is the tack I have taken for now on the NetBSD/sparc machine I'm
doing this on. The intermediate interface is in libcrypt (called
crypt_crypt()), but it's there.
> this requires modifying every single program that does user
There aren't many. I tried blowing away libcrypt entirely, doing a
make in /usr/src, and seeing what failed. There are only about eight
of them, some of which (eg, ed) probably are using the DES functions
from libcrypt rather than crypt(3).
>> For example, I do not like the idea that login(1) must know about
>> what particular encryption algorithm I am using, [...]
> The authentication is not hard coded into the login program. crypt()
> can be replaced with any module that takes two arguments which are
> the user entered response to the password prompt and the password
> entry in the password file and returns a string suitable for the
> password file.
This is the interface crypt_crypt() provides, but it makes fewer
guarantees than crypt(3) does about its returned string. In
particular, it makes no promises about its length or content (I should
change the docs, since it is careful, for example, to ensure it doesn't
include any colons :-).
> The athentication method is somewhat hard-coded into the passwd
> program in that it must know the format of the salt.
I also added a crypt_makesalt() function (which produces a suitable
salt string), and documented crypt_crypt() as being capable of taking
nearly arbitrary salt strings. Both the docs and the code need to be
updated to ensure compatability with older DES-style passwords, but
this borders on trivial.
> All programs that behave as:
> guess = users supplied password string;
> pwentry = password field from password file
> res = crypt(guess, pwentry);
> if(strcmp(res, pwentry) == 0) then success
> will work fine even if the crypt(3) function is replaced with some
> other function.
True, and the programs I've fixed (su, login, passwd, init, lock) all
do behave that way. The danger is programs that, for example, are
built around traditional DES-style passwords and assume, for example,
that the hashed password is 13 characters long. Since NetBSD already
has a second hash method that produces a longer string, I would hope
most of these already break on NetBSD and I therefore don't have to
concern myself with them. :-)
I now intend to change around my code. I will make crypt() the generic
authentication function, keep crypt_makesalt(), and add code and
matching docs so that if you pass a old-style hashed password to
crypt() it will do the corresponding old-style hashing, assuming you
have DEScrypt available.
Probably not today, though. :-/