setgid(), setgid(), getuid(), and getgid() on VMS - Was Re: CVS update: samba/source/srvsvcd

John E. Malmberg wb8tyw at qsl.net
Thu Mar 23 04:24:22 GMT 2000


Luke Kenneth Casson Leighton <lkcl at samba.org> wrote:
Subject: Re: CVS update: samba/source/srvsvcd

I am replying via SAMBA-TECHNICAL as it really is not a CVS issue, more of a
cross platform one.

> On Wed, 22 Mar 2000, John E. Malmberg wrote:
>
> > Luke Leighton <lkcl at samba.org> wrote:
> > >
> > >   why?  because linux/alpha has setresuid but not setresgid!  how many
> > other
> > >   systems have this silly kind of mis-match?
> > >
> > > - cut across andrew's setuid etc mods, removing direct calls to
seteuid
> > etc.
> > >
> > Since you asked:
> >
> > In OpenVMS the native setuid() and setgid() always return success, but
do
> > nothing.
>
> ok, if i recall, the code does a... oh, dear,what about getuid()?

That depends on what compiler options you select and what version of OpenVMS
you are building on.  Messy, Messy, Messy.

The getgid() function always behaves as expected.

The runtime function getuid() in the current version returns a 32 bit
GID/UID pair for the current user.  I think that is how it always has
behaved.

The compiler options select the prototype that can cause the GID part to be
masked off.

If you do not know what version your source code will be compiled on and you
need the full uid/gid pair, you must use a construct similar to the one
below.

    vms_uid = (getuid() & 0xFFFF) | (getgid() * 0x10000);


Some background:

A UID on OpenVMS contains an implied GID.  While there is a UID associated
with a username, it requires the GID portion to make it unique to that user.

For that reason, the setgid() function is not meaningful.  On the other
hand, for a setuid() function to be meaningful, it must also set the GID.

While it is relatively easy to implement a setuid() replacement, it is not
practical to implement setgid().

So the following effective sequence for impersonating a user will work on
OpenVMS:

    setuid(new_user_uid);
    if (new_user_uid == getuid())
    {
        setgid(new_user_gid);
        if (new_user_gid == getgid())
            return true;
    }
    return false;

However this sequence will always fail:

   setgid(new_user_gid);
   if (new_user_gid == getgid())
   {
       setuid(new_user_uid);
       if (new_user_uid == getuid())
             return true;
   }
   return false;

Now a generic Rights Identifier is treated like a UNIX or NT group, and is
32 bits.

So I have a uid_t that is either 16 bits or 32 bits depending on context,
and a gid_t that is either 16 bits or 32 bits depending on context.

For SAMBA, I have ended up with a 32 bit uid_t, and both a short_gid_t and a
long_gid_t.

As an additional rub, there is usually no "root" account with [uid,gid] of
[0,0].  So additional code must alias the UID that the SMBD is really
running under back and forth.

But none of these are insurmountable issues.


OpenVMS having ino_t as a 24 bit structure poses some more interesting
issues.  Fortunately using only the 16 most significant bits seems to be
doing a good enough job for now.

-John
wb8tyw at qsl.net



More information about the samba-technical mailing list