[comp.bugs.4bsd] getgrnam

rcodi@yabbie.rmit.oz (Ian Donaldson) (05/11/88)

Index:	/usr/src/lib/libc/gen/getgrnam.c 4.3BSD

Description:
	getgrnam(3) fails to read 2nd and subsequent lines of a
	multi-line group specification.

Repeat-By:
	Add 2 lines to /etc/group like this:

		testgroup:*:1234:somebodyelse
		testgroup:*:1234:myself

	then re-login as "myself" and then try to:

		chgrp testgroup anything

	where "anything" is any file or directory that you own.
	You will be greeted by something like this:

		chgrp: You are not a member of the "testgroup" group.

	...but upon doing a groups(1) command it is evident that you are
	in fact a member of the group.

	ie: initgroups(3) used by /bin/login reads the entire group file
	    and looks for all entries, but getgrnam(3) only looks for
	    the first line.
Fix:
	Pretty obvious.  Fix getgrnam(3) to scan the entire group file,
	and include all groups in the list.

	As for chgrp(1) however, the code that calls getgrnam(3) should
	probably be deleted entirely, since this is primarily an
	artifact of the days when chgrp(1) was a setuid root program,
	and needed to check that you were in a group before actually
	using chown(2) to change the file.  The kernel chown(2) function
	will do the checking for non-root callers in 4.3bsd.  Having
	this extra call to getgrnam(3) serves nothing but to provide
	a more explicit reason for failure than errno can give.

Workaround:
	none, if you have as many people in a group that your favourite editor
	won't let fit onto a single line; or if the line exceeds BUFSIZ (1024)
	characters, or if the number of members of a group on a single
	line exceeds 200 (see getgrent.c)

	Maybe some use of malloc(3) and realloc(3) within getgrent(3) is needed
	here...

Also-present-on:
	SunOS 3.3 (4.2bsd-ish)
	Vax 4.3bsd

Ian D

forys@sigi.Colorado.EDU (Jeff Forys) (05/15/88)

In article <762@yabbie.rmit.oz> rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
> Description:
>	getgrnam(3) fails to read 2nd and subsequent lines of a
>	multi-line group specification.

That isnt the way getgrnam(3) is defined to work in either SVID or
BSD UNIX.  "Getgrnam searches from the beginning of the file until
a group name matching `name' is found and returns a pointer to the
particular structure in which it was found."  Each group is separated
from the next by a newline.  I assume POSIX defines getgrnam(3)
similarly (I dont have a draft handy, so correct me if I'm wrong).

>	...but upon doing a groups(1) command it is evident that you are
>	in fact a member of the group.
>
>	ie: initgroups(3) used by /bin/login reads the entire group file
>	    and looks for all entries, but getgrnam(3) only looks for
>	    the first line.

Ah, then BSD groups(1) and initgroups(3) are broken, or at least, more
liberal than they should be.  They are using getgrent() to process thru
the entire file searching for a specific username; it was `easier' to
not remember duplicate group entries and invalidate them.

>	if you have as many people in a group that your favourite editor
>	won't let fit onto a single line;

Use another editor.

>	or if the line exceeds BUFSIZ (1024) characters,
>	or if the number of members of a group on a single line
>	exceeds 200 (see getgrent.c)

Awful static limitations which you arent addressing here.  The BUFSIZ
limitation can be resolved by doing block fread()'s and parsing thru
end-of-line.  The MAXGRP define can be raised if necessary, but if your
group is that big, consider using the gid field in "/etc/passwd".  You
need not match the gid field in "/etc/passwd" with a per user entry in
"/etc/group" for it to be effective.
---
Jeff Forys @ UC/Boulder Engineering Research Comp Cntr (303-492-4991)
forys@boulder.Colorado.EDU  -or-  ..!{ncar|nbires}!boulder!forys

rcodi@yabbie.rmit.oz (Ian Donaldson) (05/17/88)

From article <6076@sigi.Colorado.EDU>, by forys@sigi.Colorado.EDU (Jeff Forys):
> In article <762@yabbie.rmit.oz> rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
>> Description:
>>	getgrnam(3) fails to read 2nd and subsequent lines of a
>>	multi-line group specification.
> 
> That isnt the way getgrnam(3) is defined to work in either SVID or
> BSD UNIX.  "Getgrnam searches from the beginning of the file until
> a group name matching `name' is found and returns a pointer to the
> particular structure in which it was found."  Each group is separated
> from the next by a newline.  I assume POSIX defines getgrnam(3)
> similarly (I dont have a draft handy, so correct me if I'm wrong).

If this is the case, then the definition of the group file is severely
broken, and should be revised.  Having just 1 line per group is a bit
silly in a large user base environment.

>>	if you have as many people in a group that your favourite editor
>>	won't let fit onto a single line;
> 
> Use another editor.

Get serious!  The groups file is meant to be a text file.  It should
be editable by a text editor.  Any text editor!  If it can't be edited
by any text editor then it is seriously in doubt of being a text file.
 
>>	or if the line exceeds BUFSIZ (1024) characters,

not a problem if the file is a text file

>>	or if the number of members of a group on a single line
>>	exceeds 200 (see getgrent.c)

not a problem if the file is a text file

>  group is that big, consider using the gid field in "/etc/passwd". 

It may be possible in some cases to do this, but in lots this would
not be a solution.

For goodness sakes, fixing getgrnam(3) to scan for all possible group
entries is hardly going to break any software is it?  All software
reading the groups file is supposed to use the getgr*(3) routines anyway.

getpwuid(3) and getpwnam(3) already don't do sequential searches of 
/etc/passwd in 4.3bsd, with the advent of the parallel random passwd database.
The only reason that /etc/group hasn't followed suit is probably because
it never gets big enough to warrant the overheads of database lookup.

Ian D

forys@sigi.Colorado.EDU (Jeff Forys) (05/19/88)

In article <769@yabbie.rmit.oz> rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
>> [If your editor cant handle long lines] Use another editor.
>
> Get serious!

Oh... all right.  You can write a script, or program, to make up
for your particular editors' limitations.  In the case of vi(1),
it would take a long line and make lotsa little short lines out
of it.

> The groups file is meant to be a text file.  It should
> be editable by a text editor.  Any text editor!

Is that so?  Consider an editor that limits the length of a line
to 512 characters.  Does it still qualify it as a "text editor"?
I hope so, since ed(1) -- the "standard text editor" -- has just
such a restriction.  Or, does your definition of a "text" file
change to meet an editors' restrictions?  In that case, what do
you call a binary file in the presence of emacs?  Oh oh...

I'd expect a text file to contain data in "human-readable" form.

> getpwuid(3) and getpwnam(3) already don't do sequential searches of 
> /etc/passwd in 4.3bsd, with the advent of the parallel random passwd
> database.  The only reason that /etc/group hasn't followed suit is
> probably because > it never gets big enough to warrant the overheads
> of database lookup.

All true, but irrelevant.  Try adding two entries in your password
file with the same user name, but different user-id's.  What happens
when you log in as that user -- do you have access to files owned
by both user-id's?  Nopers...

> For goodness sakes, fixing getgrnam(3) to scan for all possible group
> entries is hardly going to break any software is it?

Dunno -- I'd have to see all the software.  I can imagine a program
using getgrent() to create a database keyed on group names, or worse,
some home-grown software that automatically manipulates /etc/group...
---
Jeff Forys @ UC/Boulder Engineering Research Comp Cntr (303-492-4991)
forys@boulder.Colorado.EDU  -or-  ..!{ncar|nbires}!boulder!forys

john@frog.UUCP (John Woods) (05/20/88)

In article <769@yabbie.rmit.oz>, rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
> >>	if you have as many people in a group that your favourite editor
> >>	won't let fit onto a single line;
> > Use another editor.
> Get serious!  The groups file is meant to be a text file.  It should
> be editable by a text editor.  Any text editor!  If it can't be edited
> by any text editor then it is seriously in doubt of being a text file.
>  
MY TEXT EDITOR CAN ONLY HANDLE
UPPERCASE FILES OF 40 COLUMNS OR
LESS.  PLEASE MAKE SURE THAT YOU
POST ONLY ARTICLES WHICH ARE TEXT
FILES AS DEFINED BY "ANY" (THEREFORE
MY) TEXT EDITOR.  THANK YOU.

Bleah!  What an offensive notion!  "If it can't be edited by" my favorite
"text editor then it is seriously in doubt of being a text file."

-- 
John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101
...!decvax!frog!john, john@frog.UUCP, ...!mit-eddie!jfw, jfw@eddie.mit.edu

"Cutting the space budget really restores my faith in humanity.  It
eliminates dreams, goals, and ideals and lets us get straight to the
business of hate, debauchery, and self-annihilation."
		-- Johnny Hart

rsalz@bbn.com (Rich Salz) (05/20/88)

Point:
    "It's a bug that getgrnam(3) requires each entry to be on one line."
Counterpoint:
    "Yeah, a bug in your editor; get a new one."
My rebuttal:
    As it comes out of the box, BSD comes with ed and vi.  If reasonable
    tasks force me to create a file that the supplied tools can't create,
    then there's a bug.

There are two solutions:
    1.  Remove the getgrnam(3) one line per entry restriction.
    2.  Ship another editor with BSD.

I believe the first choice is far superior.
	/rich $alz
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.

cball@ishmael (05/23/88)

>/* Written  5:32 am  May 11, 1988 by rcodi@yabbie.UUCP in ishmael:comp.bugs.4bsd */
>/* ---------- "getgrnam(3) bug" ---------- */
>Description:
>	getgrnam(3) fails to read 2nd and subsequent lines of a
>	multi-line group specification.

This is a real headache when you have a large user community.  Leaving default
groups out of the group file helps.  We have locally developed adduser and
chdgrp(change default login group) programs that maintain this configuration.
However, it is entirely possible to exceed max line lenghts with secondary
group memebers.

>Repeat-By:
>		testgroup:*:1234:somebodyelse
>		testgroup:*:1234:myself

This proposed format significantly changes the semantics of the group file.
A more natural extension would be the use of a line continuation character.
I suggest the following:

		testgroup:*:1234:somebody,somebodyelse,\
		myself,yourself

This is a common mechanism that can easily be added as a patch to the
existing code.  Just change grskip() in getgrent.c to fgets() the next
line when it matches a '/'.

	Charles Ball
	Intermetrics, Inc.

rcodi@yabbie.rmit.oz (Ian Donaldson) (05/26/88)

From article <123000002@ishmael>, by cball@ishmael:
>>/* ---------- "getgrnam(3) bug" ---------- */
>>		testgroup:*:1234:somebodyelse
>>		testgroup:*:1234:myself
> 
> This proposed format significantly changes the semantics of the group file.
> A more natural extension would be the use of a line continuation character.
> I suggest the following:
> 
> 		testgroup:*:1234:somebody,somebodyelse,\
> 		myself,yourself

Whilst this sounds a good idea initially, I suspect it would break more
code than its worth.

How many of you use "cut -d: -f1 /etc/group | something" ...

I suspect a lot of maintenance scripts out there would break instantly.
 
Ian D

per@erix.UUCP (06/03/88)

In article <777@yabbie.rmit.oz> rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
>From article <123000002@ishmael>, by cball@ishmael:
>> 		testgroup:*:1234:somebody,somebodyelse,\
>> 		myself,yourself

>Whilst this sounds a good idea initially, I suspect it would break more
>code than its worth.
>How many of you use "cut -d: -f1 /etc/group | something" ...

(I don't...)

>I suspect a lot of maintenance scripts out there would break instantly.

In article <769@yabbie.rmit.oz> rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
>  All software
>reading the groups file is supposed to use the getgr*(3) routines anyway.

Ahem... Well, maybe maintenance scripts don't qualify as "software"...:-)
More seriously, I suppose "something" would have to be modified to handle
multiple entries for the same group too, if that solution were to be adopted.

I fully agree that the "correct" solution is to define a continuation line
format for the group file, whether it be the one suggested above or something
else. This preserves the current semantics, is consistant with getpwnam(3),
and avoids the ambiguites that may arise due to different passwords/gids
if the "multiple entry" solution is used. Precedence can be found in the
aliases file (and other, I'm sure).

>getpwuid(3) and getpwnam(3) already don't do sequential searches of 
>/etc/passwd in 4.3bsd, with the advent of the parallel random passwd database.

I can't see why this is relevant, at least as an argument *for* the multiple
entry solution? Mkpasswd(8) currently silently ignores all occurences after the
first (in the sequential file) of a given name or userid!

--Per Hedeland

root@cca.ucsf.edu (Computer Center) (06/09/88)

In article <777@yabbie.rmit.oz>, rcodi@yabbie.rmit.oz (Ian Donaldson) writes:
> From article <123000002@ishmael>, by cball@ishmael:
> ...
> > A more natural extension would be the use of a line continuation character.
> > I suggest the following:
> > 
> > 		testgroup:*:1234:somebody,somebodyelse,\
> > 		myself,yourself
> 
> Whilst this sounds a good idea initially, I suspect it would break more
> code than its worth.
> ...
> I suspect a lot of maintenance scripts out there would break instantly.

But nothing out there is using it so nothing would break; only if you
want to _use_ the _extension_ would you need to look at local code for
needed mods. Anyone satisfied by the existing facility would not be
affected.

Thos Sumner       (thos@cca.ucsf.edu)   BITNET:  thos@ucsfcca
(The I.G.)        (...ucbvax!ucsfcgl!cca.ucsf!thos)

OS|2 -- an Operating System for puppets.

#include <disclaimer.std>