Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Nov 1997 09:52:37 -0500 (EST)
From:      Bill Paul <wpaul@skynet.ctr.columbia.edu>
To:        perhaps@yes.no (Eivind Eklund)
Cc:        hackers@freebsd.org, perhaps@yes.no
Subject:   Re: Password verification (Was: cvs commit: ports/x11/kdebase - Imported sources)
Message-ID:  <199711031452.JAA24127@skynet.ctr.columbia.edu>
In-Reply-To: <199711031005.LAA21994@bitbox.follo.net> from "Eivind Eklund" at Nov 3, 97 11:05:19 am

next in thread | previous in thread | raw e-mail | index | archive | help
Of all the gin joints in all the towns in all the world, Eivind Eklund 
had to walk into mine and say:
 
> > 
> > On Sun, 2 Nov 1997, Joao Carlos Mendes Luis wrote: 
> > 
> > ...
> > > But, how to allow users check only their own password, and still
> > > have the added security of shadow passwords ?  I can only think
> > > in a kind of password checking daemon that would accept commands
> > > on a AF_UNIX socket and some patches to libc pw commands.
> > 
> >   You can always use the pwcheck daemon from the Cyrus module (see ports).
> > It opens a unix socket at /var/pwcheck/pwcheck.  Permissions on the
> > /var/pwcheck directory can be used to determine who can check passwords.

Gee, this sounds familiar. I wonder why that is. Could it be that I
agonized over _exactly_ _this_ _problem_ for a couple of months and
went stark raving bananas trying to find a solution before finally
breaking down and resorting to a kernel hack to do it?

Nah, couldn't be that.
 
> Is it restricted to only let a user check his own password?  Or could
> we make it only check a users own password fairly easily?

Take a close look at the SCM_CREDS stuff in -current. Right now, only
a few RPC programs use it (keyserv, rpc.yppasswdd, passwd, chpass and
src/lib/libc/rpc/clnt_unix.c) but it can be used for something like this.

> The simplest solution I can see is to create a /usr/bin/checkpw which
> takes in a username/password on stdin, and checks that the username
> has the same ID as the users real ID, and exits with OK/failure.  (And
> I don't care about the expense of exec'ing a program to check a password
> - checking passwords are supposed to be expensive.)

You've just described the evil and bletcherous keyenvoy program, only 
without a set-uid bit.
 
> How is the feeling about this kind of program - too much bloat?
> Security problem?  Personally, I want it - less security problem than
> making other programs setuid.
> 
> Eivind.

The SCM_CREDS hack will work better. For those who don't know, SCM_CREDS
is an additional type of ancillary data that you can transmit with
sendmsg()/recvmsg() via an AF_UNIX socket. It's similar to SCM_RIGHTS
which, in 4.4BSD, is used to transfer a file descriptor between processes.
The idea is that the calling process does a sendmsg() with the SCM_CREDS
flag set and an empty controll emssage buffer, and when the kernel sees 
this in unp_internalize(), it fills in the empty buffer with the sending
process's credentials (UID, EUID, GID, other GIDS). When the receiving
process does a recvmsg(), it gets a copy of the filled-in buffer and
can use the credential info to determine the identity of the sending
process and do access checks. If the sender does not set the SCM_CREDS flag
when it transmits, the receiver can tell and refuse to do business with
the sender.

Keyserv uses this trick to learn the identity of the user talking to it so
it can protect its secret keys: each user stores his own secret key with 
keyserv, and keyserv wants to make sure that can only get at his key and 
no one else's. Sun originally did this using a program called keyenvoy, which
was set-uid root. Keyserv was set up to only accept requests from reserved
ports on the loopback address. The key_call.c module in the RPC library
would talk to keyserv by vfork()ing and exec()ing keyenvoy and passing
it things on the command line. In the context of RPC, the performace hit
sucked: any program doing lots of Secure RPC transactions (like NIS+) would 
crawl.

In Solaris 2.x, Sun got rid of keyenvoy and switched to a different
scheme involing STREAMS/TLI. Turns out there's a way in SysV to learn
the identity of a process on the other side of a transport endpoint
using t_getinfo(). This is all well and good for Sun, but we don't have
STREAMS, nor are we likely to get it anytime soon, so I needed another
solution when I adapted keyenvoy for FreeBSD. After much hair-pulling,
I realized that the sockets API had nothing equivalent to t_getinfo(),
hence I was forced to invent my own.

Now, all that aside, you could use the SCM_CREDS hack and AF_UNIX sockets
to create a 'password database access' daemon and fix it so that a user
can see his own encrypted password and noone else's. But consider the
following:

- If the system uses this daemon for login authentication and the daemon
  crashes, noone will be able to log in.

- You have to code it in such a way that it won't fall apart in the face
  of heavy (and possibly concurrent) access by clients.

- Consider getpwent(3). You have to make the daemon be able to handle
  things like enumerating the passwd database, not just retrieving
  arbitrary records.

This is starting to sound suspiciously like ypserv(8).

-Bill

-- 
=============================================================================
-Bill Paul            (212) 854-6020 | System Manager, Master of Unix-Fu
Work:         wpaul@ctr.columbia.edu | Center for Telecommunications Research
Home:  wpaul@skynet.ctr.columbia.edu | Columbia University, New York City
=============================================================================
 "It is not I who am crazy; it is I who am mad!" - Ren Hoek, "Space Madness"
=============================================================================



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711031452.JAA24127>