Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.mira.net.au!vic.news.telstra.net!act.news.telstra.net!imci3!imci2!news.internetMCI.com!newsfeed.internetmci.com!news.msfc.nasa.gov!sol.ctr.columbia.edu!startide.ctr.columbia.edu!wpaul From: wpaul@ctr.columbia.edu (Bill Paul) Newsgroups: comp.unix.bsd.freebsd.misc Subject: Re: NIS client setup Date: 8 May 1996 14:35:59 GMT Organization: Columbia University Center for Telecommunications Research Lines: 177 Message-ID: <4mqbgg$29n@sol.ctr.columbia.edu> References: <3189E69E.727C@arrakis.comm.pub.ro> <4ml84l$3nf@plains.nodak.edu> <4mnh4i$s7p@picard.cistron.nl> NNTP-Posting-Host: startide.ctr.columbia.edu X-Newsreader: TIN [version 1.2 PL2] Daring to challenge the will of the almighty Leviam00se, Miquel van Smoorenburg (miquels@cistron.nl) had the courage to say: : In article <4ml84l$3nf@plains.nodak.edu>, : Mark Tinguely <tinguely@plains.nodak.edu> wrote: : >we should x-or the password record coming from NIS server (and x-or on : >client), because NIS defeats a shadowed password. Looking at the network : >text showed one of our students another NIS bug that I need to document : >and send to the NIS maintainers. The 'bug' you're thinking of (I got your mail) is not a bug, but a misfeature. Let me address something else first: you don't have to put any magic information in the NIS '+' entries that go in /etc/master.passwd in order for users to be able to change their passwords. Ideally, you should do nothing at all except add a line to /etc/master.passwd that says: +::::::::: That's it. Nothing else. (Well, and add +::: to /etc/group.) IF you read the passwd(5) man page, it says that in FreeBSD, _ALL_ fields can be remapped. So if you do this: +:*:0:0:::::: Then what you'll be doing is remapping all NIS users' passwords to '*' and all UIDs and GIDs to 0. This is not what you want. The man page warns quite strenuously not to do this. As for the misfeature, you're wondering why FreeBSD NIS clients always seem to request the first record from the master.passwd map whenever they make a request. (Note that in your mail, you claimed that this could be triggered by calling getuid(). This is wrong: getuid() is a system call. System calls never use NIS. I think you meant getpwuid(3).) Okay, to understand what's going on here, consider that we're trying to shoehorn the BSD password database system into NIS. There are actually two databases: master.passwd, which contains real encrypted passwords and has extra fields in it compared to the standard UNIX /etc/passwd format, and passwd, which has * in the passwords fields and is in standard format for compatibility with other systems. A FreeBSD NIS client wants the server to have both master.passwd maps and passwd maps so that it can use a shadow password scheme similar to the one it uses for the local databases. The way the system works, if a non-root user on the NIS client calls one of the getpwent(3) functions, the library code just looks for the passwd.byname maps (the 'safe' database, with no real password data). If invoked by the superuser, they try to find the master.passwd maps first and use those instead if they're available. All of the user authentication programs in BSD run with root privilege, so they will be able to read the correct password data, while normal users will only get to see the passwd maps, which have no password info in them. To enforce the restriction, the FreeBSD ypserv will refuse to serve the master.passwd maps to a client unless it receives an RPC from a reserved port. Since only the superuser can bind to a reserved port, ypserv can tell that a request is coming from the superuser on a client and honor it. If a non-privileged user tries to do, for example, 'ypcat master.passwd.byname,' all they'll get is a 'YP server error.' But supposing you're using a FreeBSD client with a non-FreeBSD NIS server which doesn't have any master.passwd maps on it (or supposing you configure a FreeBSD NIS server not to have any master.passwd maps). In order to maintain compatibility, the client must fall back on using the standard passwd maps. This means it must make due with the old format, and the shadowing system is defeated: any user can grab the password file, complete with encrypted passwords. So: in order for this scheme to work, the client code must test for the presence of the master.passwd maps. The only way to do this is to ask the NIS server to do some operation on one of the maps and see if it gets an error. (Note that this test is only done if you're superuser: there's no point in doing it for non-root users since ypserv won't let them access the master.passwd maps anyway.) Originally, I did this test by trying to do a yp_order() on one of the master.passwd maps. Unfortunately, I later discovered that the Solaris rpc.nisd (the NIS+ server) in 'NIS v2 compat mode' doesn't support the YPPROC_ORDER procedure. This broke FreeBSD clients when used with NIS+ servers. (The reason they don't support it any more probably has to do with the fact tha YPPROC_ORDER is used mostly when doing map transfers between NIS master and slave servers, and NIS+ doesn't use the same scheme for that anymore.) So I decided to change it from yp_order() to yp_first(), since yp_first() doesn't require me to know any of the keys in the map. Take a look at src/lib/libc/gen/getpwent.c and search for the function called _havemaster(). This is the function that tests for the presence of the master.passwd map. Yes, this is a kludge. Yes it's ugly. Yes I wish I could do it better. I could have made _havemaster() read a local configutation file that tells whether or not to use the master.passwd maps, but I didn't want to put Yet Another Configuration File (tm) in /etc. The code is supposed to be smart enough to figure this out by itself. As for encryption, don't think I haven't thought of that. The trouble is that both the client and the server have to agree on a key (even if you use a simple XOR scheme). Having the key hardcoded into ypserv and libc seems silly. I do have a Cunning Plan (tm) to actually impliment encryption (at least for the master.passwd maps) but I have to find time to actually sit down and make it work. Also, this will result in yet another system-specific shadow password scheme that won't work with anyone else. And last, bear in mind that NIS transactions are supposed to be fast; if you add encryption to the mix and don't do it right, you can wreck performance. (The system call overhead is already murder once you start using very large maps with very small records. Calling sendto() and recvfrom() a few thousand times over can consume a lot of cycles, you know.) : You could check the port the request is originating from and xxx out : the password field if it is > 1024 (ie insecure). The standard RPC libs : always try to bind to a reserved port, so root processes will get the : password but user processes won't. Ofcourse this will only work if the : slave servers behave the same (and bind to a reserved port during ypxfr). The problem with this trick is that a) it's easy to spoof, and b) it won't work with some systems. If you have access to a Solaris machine, do an rpcinfo -p on it and check the output. You'll notice that except for the portmap service itself, everything is bound to a non-privileged port. I attribute this to a bug in the Solaris RPC library. (Note that Solaris uses TI-RPC, which is based on STREAMS rather than RPC 4.0, which is based on sockets). I call it a bug because I've tried to write RPC programs using the TCP and UDP transports and I can't get them to use a reserved port even on purpose; the bindresvport() function doesn't work. (I've pawed through the source code from TI-RPC 2.3 and I've discovered why: bindresvport() is supposed to accept a socket and bind it to a reserved port, but since TI-RPC uses STREAMS, it tries to convert the socket to a TLI endpoint and it gets it wrong. On socket based systems it works fine.) Anyway, Solaris doesn't worry about reserved ports with RPC since it has Secure RPC. This is in fact what NIS+ uses to prevent giving out information to unauthorized clients. The point though is that using a Solaris machine as an NIS client with a server that enforces the 'only honor requests from reserved ports' rule won't work: the Solaris machine will neve be able to use a reserved port, so its requests will always go unanswered. The fact that it works with FreeBSD is just a happy coincidence, and I put up with it for now because it's marginally better than nothing. (There's one other OS that I've encountered which gets this wrong too: Sony NEWS-OS 3.33. This is a BSD 4.3 variant and it does use standard sockets-based RPC, yet for some reason it still doesn't use reserved ports correctly.) : I've helped developing something like this in the Linux NIS server : (ypserv-0.18), it actually works quite nice. I already added this feature to the Linux NIS server when ported it to FreeBSD. :) Note however that this particular ypserv won't be in FreeBSD 2.2: I've replaced it with one that I wrote myself. (Ditto for rpc.yppasswdd, yppush, ypxfr and yp_mkdb.) At one point I ported the GNU ypserv to IRIX for use in a lab here on campus (50 Indys and one Challenge M server) and did a variation on the privileged port trick. (Fortunately, the IRIX RPC library binds root-owned processes to reserved ports correctly.) In this case, I added an extra function to mangle the password field in the passwd maps for all requests made by non-privileged users. So if, for example, a user does 'ypcat passwd' on one of the machines, the password fields in the data they get back are all overwritten with asterixes. (Asteri?) If root does it, then the correct information is returned. I wanted to impliment this scheme with my own network, unfortunately I have Solaris clients (and Sony NEWS-OS clients). -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 ============================================================================= "If you're ever in trouble, go to the CTR. Ask for Bill. He will help you." =============================================================================