Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Apr 1998 20:22:51 +0300 (EEST)
From:      Penisoara Adrian <ady@warpnet.ro>
To:        freebsd-security@FreeBSD.ORG
Cc:        freebsd-bugs@FreeBSD.ORG
Subject:   Controlling MD5/DES use for passwd - Resumee
Message-ID:  <Pine.BSF.3.96.980420174045.7675B-100000@ady.warpnet.ro>

next in thread | raw e-mail | index | archive | help
Hi,

  First of all thanks goes to all who shared ideeas on this subject
(wether in private or on the list).


PROBLEM:
    Installing DES distribution changes the default behavior of the
  (non-DES) system to use MD5 for password encryption.

WANTED:
    There should be a way to control which encryption scheme the system
  uses, wether MD5, DES or whatever else.

BACKGROUND:
    The _passwd_ utility uses a crypt(3) call to encrypt the plain-text
  password it is given by the user. The code of this function resides in
  the _libcrypt_ library/libraries found in the /usr/lib directory.
    The standard crypt library which comes with FreeBSD (assuming that the
  "des" distribution is not installed) makes use of the MD5 encryption
  scheme and the code is found in the /usr/lib/libscrypt.* library, with
  libcrypt.* beeing sym-linked to it. Here it is the libscrypt content:

  # ar -t /usr/lib/libscrypt.a
  __.SYMDEF
  crypt.o
  md5c.o

    When the "des" distribution is installed a new _libdescrypt_ library
  appears and the libcrypt.* symlinks are updated to redirect to the new
  libdescrypt.* files. Note that this library contains the MD5 code too
  and the DES crypt() code is MD5 aware, recognisig the "$1$" MD5 
  signature in the salt and calling the MD5 code in that case. Here it is
  the libdescrypt content:

  # ar -t /usr/lib/libdescrypt.a
  __.SYMDEF
  crypt.o
  crypt-md5.o
  md5c.o

    Here it is the crypt() calling sequence in the passwd code found in
  the file usr.bin/passwd/local_passwd.c:

  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  #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
          return (crypt(buf, salt));
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    In the current situation this is the behavior of passwd:
      * Creating a new user/password: uses de DES scheme
      * Changing a password: if the password was MD5 (it had the "$1$"
        signature) the new password will use the MD5 scheme, else will use
        the DES scheme

FIX:
    The easy (& wrong) way: sym-linking the libcrypt.* files back to the
  libscrypt.* files when needing the new/changed passwords to be MD5
  encrypted. This has the side-effect of making the already existing DES
  passwords useless (they will no longer be accepted/work).
    The hard (& good) way: making the passwd code multiple-scheme aware
  with posibility to control (the order of) the scheme(s) to use.

SUGGESTIONS:
    For the config file it would probably make more sense using the
  login.conf database -- the current passwd already checks for two other
  settings (minpasswordlen and passwordperiod) in the login capability.
  Also, this will permit setting different schemes for different/special
  classes/users.
    Another option would be introducing an /etc/passwd.conf file.

    For the source-code implementation: either rely on the crypt() beeing
  multiple-scheme aware (choosing the scheme based on a signature in the
  salt, for example) and use the standard _libcrypt_ library, or try using
  the specific library for each encryption scheme requested -- making use
  of dlopen(3) ?. This depends also on the way password authentication
  will be done -- will it recognise the scheme from the signature
  contained in it or will it try every possible scheme ?
    Also, we should take care for other encryption schemes might appear.
    I believe using a standard crypt() makes the process of adding other
  new encryption schemes pretty hard -- the new crypt() function will have
  to incorporate hooks for every other scheme.
    Using specific libraries will (probably) cause some problems with
  static linked binaries.

    I would go for using specific dynamic libraries and including 
  scheme-specific signatures in the encrypted password -- MD5 already
  makes a precedent. Also, passwd/the authentication routine should decide
  which scheme will be used and not the crypt() function -- you wouldn't
  like to have passwords encoded with not-approved-by-you schemes, would
  you ?

    Please note that currently I'm not in the position to suggest patches,
  I'm not (yet) such a skilled programmer and neither do I know very well
  the FreeBSD internals.


  Thank you,
  Adrian Penisoara
  Ady (@warpnet.ro)
  Warp Net Technologies


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980420174045.7675B-100000>