Date: Mon, 3 Nov 1997 17:56:35 -0500 (EST) From: Bill Paul <wpaul@skynet.ctr.columbia.edu> To: jonny@coppe.ufrj.br (Joao Carlos Mendes Luis) Cc: perhaps@yes.no, hackers@FreeBSD.ORG Subject: Re: Password verification (Was: cvs commit: ports/x11/kdebase - Imported sources) Message-ID: <199711032256.RAA24611@skynet.ctr.columbia.edu> In-Reply-To: <199711032052.SAA09155@gaia.coppe.ufrj.br> from "Joao Carlos Mendes Luis" at Nov 3, 97 06:52:51 pm
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, Joao Carlos Mendes Luis had to walk into mine and say: [...] > // 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. > > Humm... This needs some change from the sender point of view, right ? > Maybe it could be more useful if it messed only with the receiver side. > Is it possible ? Probably not, for datagram stuff. Both the sender and the receiver have to cooperate a bit. The sender must use sendmsg() and the receiver must use recvmsg(). But the receiver is able to enforce the use of credentials: a sender can use send() or write() or whatever, but in this case the receiver will not get any ancillary data and the cmsg_type flag will not be set. The receiver then knows that there aren't any creds to look at so it can return an error to the sender and ignore the unauthenticated message. > // 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. > > I thought about that. Just make the program use this as an option, and > not the default behavior. Maybe, even, not automatic. You would have to fall back to the directly reading the password database. The problem is that this checking to see which method to use incurrs overhead, which is something you'd like to avoid. > // - 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. > > Sure. To make a head start, maybe a very simple forking connection > daemon could work. What if I'm a mean widdle user and I write a program to constantly bombard the 'passwd database daemon' with requests? You have to be careful: this could make the daemon fork() all over the place and eat up system resources. I 'fixed' ypserv so that it can only have a certain number of children going at any one time; if you try to go over the limit, the request fails. (Ypserv only fork()s for YPPROC_ALL requests at this point; the only command that uses the YPPROC_ALL service is ypcat, so it's a reasonable tradeoff.) > Multithreading is always an option, of course. Only if you're into that sort of kinky stuff. > // - Consider getpwent(3). You have to make the daemon be able to handle > // things like enumerating the passwd database, not just retrieving > // arbitrary records. > > Could you please elaborate on this ? I can do pw = getpwnam("wpaul") to retrieve just my record from the passwd database, or I can do: while((pw = getpwent()) != NULL) { if (strcmp(pw->pw_name, "wpaul")) continue; } In the latter case, we start from the 'top' of the database and read every record until we find the one we want. The former case is just a matter of matching a key in the database: you find the record that goes with the key and return it. The latter case is more disgusting: it's not a problem if you're reading from a file or database directly, but when reading from a remote process, it's tough to handle such an 'enumeration' request. It's even thougher if you have several of them going at once: the server has to juggle multiple clients and send each one the right records in the right order. Ypserv handles this in two different ways: for YPPROC_ALL, you're stuffing all the records into a single TCP connection. When you're done, the connection goes away. Because of the strange way this is done with RPC, ypserv fork()s a child process to handle this (this is largely to avoid having the parent block for too long). The other case is a YPPROC_FIRST followed by a series of YPPROC_NEXTs. The NIS support in getpwent.c uses this approach over YPPROC_ALL because YPPROC_FIRST and YPPROC_NEXT are supposed to be idempotent. YPPROC_FIRST is easy to implement in the server. YPPROC_NEXT is hard: the Berkeley DB hash method doesn't implement the 'set cursor location' function (the btree method does). Ypserv does some database handle caching in order to get around this. > // This is starting to sound suspiciously like ypserv(8). > > Like every server daemon... I just thought about inetd. As another example, Solaris has this beast called the Name Service Cache Daemon (/usr/sbin/nscd) which is actually tied in to a great many libc lookup routines, including getpwent(3) and friends. If you use NIS or NIS+, nscd will cache lookups from those services on the local host. Getting the time to live for everything set correctly can be tricky though. Also, nscd uses a special kind of IPC mechanism called doors (not sockets or pipes, but doors). > Do we have something similar for AF_UNIX sockets ? I have made it ridiculously easy to make RPC client/server programs that use AF_UNIX sockets in -current. :) For an example, see keyserv. > I have a question. What's the better approach for this ? > A /etc/master.passwd window daemon, which allows users to > read their own record, or just a username/password verify > daemon ? > In the first case, it can be embedded in libc and apps > will not notice the difference. "Hey, why all passwords > are '*' except mine ?" In the second case, apps should > be modified, but it also allows for other kinds of auth > systems. (Argh, this stinks like PAM). VMS gets by with allowing unprivileged users to see only their password information in the SYSUAF.DAT database. (I'm not entirely sure how this is done: I vaguely remember that there were some library routines for doing authentication checks and that the SYSUAF.DAT file was not readable by normal users. You could only perform authentication checks using the library interface.) I'm not sure how VMS http servers deal with this restriction; perhaps they INSTALL the web server image with a particular privilege bit set that lets it do authentication for any user. In any case, there are arguments for both. The former method is, as you say, more compatible with existing code. The latter allows you isolate the use of the crypt(3) function to a single process, which is handy since it means you'd never have to worry about linking new programs with -lcrypt ever again. I took this approach with _des_crypt() in Secure RPC: keyserv is the only program that actually calls the libdes library; everyone else just calls keyserv. Maybe you could have a server that does both. -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?199711032256.RAA24611>