Note that this was done by selective patching from diffs, to not conflict
with the 4.4bsd base code.. This was *not* a trivial task.. I have been
testing this code (apart from cosmetic changes) in my libc for a while now.
Obtained from: Paul Vixie <paul@vix.com>
/usr/include/ufs/ufs/quota (#include <ufs/ufs/quota.h>) that seems to work
ok though.
Closes PR # docs/670: quotactl man page incorr...
Submitted by: evans@scnc.k12.mi.us (Jeffrey Evans)
Fix for PR #510. The original problem was that __ivaliduser() was
failing to grant access to a machine listed in a +@netgroup specified
in /etc/hosts.equiv, even though the host being checked was most
certainly in the +@netgroup.
The /etc/hosts.equiv file in question looked like this:
localhost
+@netgroup
The reason for the failure was had to do with gethostbyaddr(). Inside
the __ivaliduser() routine, we need to do a gethostbyaddr() in order
to get back the actual name of the host we're trying to validate since
we're only passed its IP address. The hostname returned by gethostbyaddr()
is later passed as an argument to innetgr(). The problem is that
__icheckhost() later does a gethostbyname() of its own, which clobbers
the buffer returned by gethostbyaddr().
The fix is just to copy the hostname into a private buffer and use
_that_ as the 'host' argument that gets passed to innetgr().
And here I was crawling all over the innetgr() code thinking the
problem was there. *sigh*
bump it again if something else is added before 2.2.
The xdr_* functions are enabled only in the 2.2 (-current) branch
so far. If that modification is moved to the 2.1 (-stable) branch,
this one should, too.
Reviewed by: the mailing lists
- getnetgrent.c: address some NIS compatibility problems. We really need
to use the netgroup.byuser and netgroup.byhost maps to speed up innetgr()
when using NIS. Also, change the NIS interaction in the following way:
If /etc/netgroup does not exist or is empty (or contains only the
NIS '+' token), we now use NIS exclusively. This lets us use the
'reverse netgroup' maps and is more or less the behavior of other
platforms.
If /etc/netgroup exists and contains local netgroup data (but no '+').
we use only lthe local stuff and ignore NIS.
If /etc/netgroup exists and contains both local data and the '+',
we use the local data nd the netgroup map as a single combined
database (which, unfortunately, can be slow when the netgroup
database is large). This is what we have been doing up until now.
Head off a potential NULL pointer dereference in the old innetgr()
matching code.
Also fix the way the NIS netgroup map is incorporated into things:
adding the '+' is supposed to make it seem as though the netgroup
database is 'inserted' wherever the '+' is placed. We didn't quite
do it that way before.
(The NetBSD people apparently use a real, honest-to-gosh, netgroup.db
database that works just like the password database. This is
actually a neat idea since netgroups is the sort of thing that
can really benefit from having multi-key search capability,
particularly since reverse lookups require more than a trivial
amount of processing. Should we do something like this too?)
- netgroup.5: document all this stuff.
- rcmd.c: some sleuthing with some test programs linked with my own
version of innetgr() has revealed that SunOS always passes the NIS
domain name to innetgr() in the 'domain' argument. We might as well
do the same (if YP is defined).
- ether_addr.c: also fix the NIS interaction so that placing the
'+' token in the /etc/ethers file makes it seem like the NIS
ethers data is 'inserted' at that point. (Chances are nobody will
notice the effect of this change, which is just te way I like it. :)
specified in the top level Makefiles.
Previously I missed dozens of Makefiles that skip the install after
using `cmp -s' to decide that the install isn't necessary.
changeover, so we have to extend the format of timezone files (in a backward-
compatible way, of course). This probably means that libc needs a minor
version number bump before 2.2 is released (or maybe not).
by me). This probably loses for multibyte characters, but I have no
way of telling. I'll let ache decide whether to add this support to
startup_setlocale. Note that for this to make any sense at all, the
symlinks in /usr/share/locale must go. (For the moment, this doesn't
make any difference since there are no locales supplied.)
Obtained from: Arthur David Olson <ado@elsie.nci.nih.gov>
Back out the 'help NIS rebind faster' hack. This change used a
connect()/send() pair rather than the original sendto() to allow
RPC to pass ICMP host unreachable and similar errors up to RPC
programs that use UDP. This is not a terrible thing by itself, but it can
cause trouble in environments with multi-homed hosts: if the portmapper
on the multi-homed machine sends a reply with a source address
that's different than the one associated with the connection by
connect(), the kernel will send a port unreachable message and
drop the reply. For the sake of compatibility with everybody else
on the planet, it's best to revert to the old behavior.
*long, heavy sigh*
like 38400<any 8bit char, isalpha> it not detect this stuff and
produce very big number instead. Fixed by operating with unsigned char
and checking for isascii. (secure/telnetd hits by it f.e.)
the comment before checking for long lines, so there was a possibility
that the wrap-around might be used as an exploitable hostname.
Reviewed by:
Submitted by:
Obtained from:
Strange as it sounds, it should map to YPERR_DOMAIN instead.
The YP_NODOM protocol error code is generally returned by ypserv when you
ask it for data from a domain that it doesn't support. By contrast,
the YPERR_NODOM error code means 'local domain name not set.'
Consequently, this incorrect mapping leads to yperr_string() generating
a very confusing error message. YPERR_DOMAIN says 'couldn't
bind to a server which serves this domain' which is much closer
to the truth.
_gr_breakout_yp(): if we encounter a NULL pointer generated as the
result of a badly formatted NIS passwd entry (e.g. missing fields),
we punt and return an error code, thereby silently skipping the
bad entry.
last night:
_gr_breakout_yp() doesn't check for badly formatted NIS group entries.
For example, a bogus entry like this:
bootp::user1,user2,user3
will lead to a null pointer dereference and a SEGV (note that the GID
field is missing -- this results in one of the strsep(&result, ":")
returning NULL). The symtpom of this problem is programs dumping
core left and right the moment you add a + entry to /etc/group.
Note that while this is similar to an earlier bug, it's caused by a
different set of circumstances.
The fix is to check for the NULL pointers and have _gr_breakout_yp()
punt and return a failure code if it catches one. This is more or
less the behavior of SunOS: if a bad NIS group entry is encountered,
it's silently ignored. I don't think our standard (non-NIS) group
parsing code behaves the same way. It doesn't crash though, so I'm
citing the 'it ain't broken, don't fix it' rule and leaving it alone.
I'll probably have to add similar checks to _pw_breakout_yp() in
getpwent.c to ward off the same problems. It's rare that bad NIS
map entries like this occur, but we should handle them gracefully
when they do.
'cycle in netgroup check too greedy').
PR #508 is apparently due to an inconsistency in the way the 4.4BSD
netgroup code deals with bad netgroups. When 4.4BSD code encounters
a badly formed netgroup entry (e.g. (somehost,-somedomain), which,
because of the missing comma between the '-' and 'somedomain,' has
only 2 fields instead of 3), it generates an error message and
then bails out without doing any more processing on the netgroup
containing the bad entry. Conversely, every other *NIX in the world
that usees netgroups just tries to parse the entry as best it can
and then silently continues on its way.
The result is that two bad things happen: 1) we ignore other valid entries
within the netgroup containing the bogus entry, which prevents
us from interoperating with other systems that don't behave this way,
and 2) by printing an error to stderr from inside libc, we hose certain
programs, in this case rlogind. In the problem report, Bill Fenner
noted that the 'B' from 'Bad' was missing, and that rlogind exited
immediately after generating the error. The missing 'B' is apparently
not caused by any problem in getnetgrent.c; more likely it's getting
swallowed up by rlogind somehow, and the error message itself causes
rlogind to become confused. I was able to duplicate this problem and
discovered that running a simple test program on my FreeBSD system
resulted in a properly formatted (if confusing) error, whereas triggering
the error by trying to rlogin to the machine yielded the missing 'B'
problem.
Anyway, the fixes for this are as follows:
- The error message has been reformatted so that it prints out more useful
information (e.g. Bad entry (somehost,-somedomain) in netgroup "foo").
We check for NULL entries so that we don't print '(null)' anymore too. :)
- Rearranged things in parse_netgrp() so that we make a best guess at
what bad entries are supposed to look like and then continue processing
instead of bailing out.
- Even though the error message has been cleaned up, it's wrapped inside
a #ifdef DEBUG. This way we match the behavior of other systems. Since we
now handle the error condition better anyway, this error message becomes
less important.
PR #507 is another case of inconsistency. The code that handles
duplicate/circular netgroup entries isn't really 'too greedy; -- it's
just too noisy. If you have a netgroup containing duplicate entries,
the code actually does the right thing, but it also generates an error
message. As with the 'Bad netgroup' message, spewing this out from
inside libc can also hose certain programs (like rlogind). Again, no
other system generates an error message in this case.
The only change here is to hide the error message inside an #ifdef DEBUG.
Like the other message, it's largely superfluous since the code handles
the condition correctly.
Note that PR #510 (+@netgroup host matching in /etc/hosts.equiv) is still
being investigated. I haven't been able to duplicate it myself, and I
strongly suspect it to be a configuration problem of some kind. However,
I'm leaving all three PRs open until I get 510 resolved just for the
sake of paranoia.
ypbind.c:
Make fewer assumtions about the state of the dom_alive and dom_broadcasting
flags in roc_received().
If select() fails, use syslog() to report the error rather than perror().
Check that all our malloc()s succeed. Report malloc() failure in
ypbindproc_setdom_2() to callers.
yplib.c:
Use #defined constants in ypbinderr_string() rather than hard-coded values.
- If you take the wheel entry out of /etc/group and turn on NIS,
the '+:*::' line is incorrectly flagged as the entry for wheel (the
empty gid section is translated to 0), hence getgrgid() returns '+'
as the name of the group instead of 'wheel.'
- Using just '+:' as the 'turn on NIS' switch in /etc/group makes
getgrgid() dump core because of a null pointer dereference. (Last
time I was in here, I foolishly assumed that fixing the core dump
problems with getgrnam() and getgrent() would fix getgrgid() too.
Silly me.)
- Moved to a more client-driven model. We aggressively attempt to keep
the default domain bound (as before) but we give up on non-default
domains if we lose contact with a server and fail to get a response
after one round of broadcasting. This helps drastically reduce the
amount of network bandwitdh that ypbind consumes: if a client references
the secondary domain at some later point, this will prod ypbind into
establishing a new binding anyway, so continuously broadcasting without
need is pointless.
Note that we still actively seek out a binding for our default domain
even if no client program has queried us yet. I'm not exactly sure if
this matches SunOS's behavior or not, but I decided to do it this way
since we can get into all sorts of trouble if our default domain comes
unbound. Even so, we're still much quieter than we used to be.
- Removed a bunch of no-longer pertinent comments and a couple of
chunks of #ifdef 0'ed code that no longer fit in to the new layout.
- Theo deRaadt must have become frustrated with the callback mechanism
in clnt_broadcast(), because he shamelessly stole the clnt_broadcast()
code right out of the RPC library and hacked it up to suit his needs.
(Comments and all! :)
I can understand why: clnt_broadcast() blocks while awaiting replies.
Changing this behavior requires surgery. However, you can work around
this: fork the broadcast into a child process and relay the results
back to the parent via a pipe. (Careful obervation has shown that the
SunOS ypbind forks children for broadcasting too, though I can only
guess what sort of interprocess communication it uses. pipe() seems to
do the job well enough.)
This may seem like the long way around, but it's not really that
hard to implement, and I'd prefer to use documented RPC library functions
wherever possible. We're careful to limit the number of simultaneous
broadcasters to avoid swamping the system (the current limit is 5).
Each clnt_broadcast() call only sends out a small number of packets
at increasing intervals. We're also careful not to spawn more than one
bradcaster for a given domain.
- Used clntudp_bufcreate() and clnt_call() to implement a ping()
function for directly querying a particular server so that we can
check if it's still alive. This lets me completely remove the old
bradcasting code and use actual RPC library calls instead, at the
cost of more than a few handfulls of torn-out hair. (Make no mistake
folks: I *HATE* RPC.) Currently, the ping interval is one minute.
- Fixed another potential 'nfds too big for select()' bug: use
_rpc_dtablesize() instead of getdtablesize().
- Quieted gcc -Wall a bit.
- Probably a bunch of other stuff that I've forgotten.
ypbind.8:
- Updated man page to reflect modifications.
ypwhich.c:
- Small mind-o fix from last time: decode error results from
ypbind correctly (*groan*)
yplib.c:
- same as above
- Change behavior of _yp_dobind() a little: if we get back a 'Domain
not bound' error for a given domain, retry a few times before giving
up and passing the error back to the caller. We have to sleep for a
few seconds between tries since the 'Domain not bound' error comes
back immediately (by repeatedly looping, we end up pounding on ypbind).
We retry at most 20 times at 5 second intervals. This gives us a full
minute to get a response. This seems to deviate a bit from SunOS
behavior -- it appears to wait forever -- but I don't like the idea
of perpetually hanging inside a library call.
Note that this should fix the problems some people have with bindings
not being established fast enough at boot time; sometimes amd is started
in /etc/rc after ypbind has run but before it gets a binding set up. The
automounter gets annoyed at this and tends to exit. By pausing ther YP
calls until a binding is ready, we avoid this situation.
- Another _yp_dobind() change: if we determine that our binding files
are unlocked or nonexistent, jump directly to code that pokes ypbind
into restablishing the binding. Again, if it fails, we'll time out
eventually and return.