[comp.sys.hp] cuseid and security in 7.0

pete-d@hpfcmgw.HP.COM (Pete Dubler) (03/10/90)

                              cuserid(3) in 7.0


One of the important features of HP-UX 7.0 is POSIX conformance, and for the
most part this is great.  However, it did introduce a small problem....

If a program needs to find out who is really using it (i.e. who is logged
in on this tty/pty/etc), a good choice in the past has been the cuserid(3)
function.  It used a combination of getlogin(3) and getpwuid(3) to come up
with the name, and was very hard to fool.  This made it a good choice for
"do one command as root" programs, which many system managers install to
keep from having to su(1) often.

The catch is that to conform to POSIX, cuserid(3) was changed in 7.0 to
use the effective user id of the caller, as opposed to the earlier
behavior (trying for the login name via getlogin(3); if that failed,
using the real user id to look up the name in /etc/passwd via
getpwuid(3)).  Thus, with the new 7.0/POSIX behavior, cuserid(3) is
useless for user authentication from within a SUID program.  If someone
has a program that depends on the old behavior and they compile it on
7.0, they may have just opened up a hole (any setuid-root program of the
type mentioned above will report that it is being run by root).  [Note:
POSIX is considering the idea of removing cuserid(3) from its standard
altogether; however, this has *NOT* been decided one way or the other.]

There are some workarounds for this:  1) don't recompile the program on 7.0;
2) change calls to cuserid(3) to use getlogin(3)/getpwuid(3);  3) compile
the program on 7.0 but link it with /lib/cuserid.o.  The preferred solution
is #2; #3 is definitely not recommended, because /lib/cuserid.o is likely
to disappear in 8.0.

What follows is an example of approach #2.  This is not intended to be
complete/perfect/etc; it is just to illustrate the idea:

   
   char *who_am_i(buf)          /*  do a pre-7.0 (pre-POSIX) cuserid(s) */
   char *buf;                   /*  buf needs to point to some space    */
   {
        char *p;
        struct passwd *pwd;
        
        
        if (p = getlogin()) {
                strcpy(buf, p);
                return(buf);
        }
                
        if (pwd = getpwuid(getuid())) {
                strcpy(buf, pwd->pw_name);
                return(buf);
        }
                
        return(NULL);
   }