ACL / SDs

Todd Sabin tas at webspan.net
Thu Feb 24 13:39:53 GMT 2000


Luke Kenneth Casson Leighton <lkcl at samba.org> writes:
> > Why? If the SIDs are in the struct they sure haven't mysteriously
> > materialized there, and then someone have already looked them up ...
> > the looked up unix data is as good as the NT data, no gain to
> > relookup. I still think they should be stored in the user_info struct.
> 
> funnily enough, i was thinking of this, too, just now.
> 
> it's a matter of which you want to do.
> 
> do you want: the PDC to tell you what groups the user is in?
> 
> do you want: the local unix system to tell you what groups the user is in?
> 

In the case of NT, both happen actually.  The PDC will determine what
global (domain) groups the user is in and tell that to the
workstation.  The workstation then uses that list (and the user's SID)
to determine what local groups (aka aliases) the user belongs to.
Actually, it's slightly more complicated than that, because there are
the "WellKnownGroups" (Everyone, Network, Interactive, etc.) that can
also affect local group membership.

Not sure if that's relevant, but figured I'd throw it out there.

> > > > objections to throwing them out of the internal access_mask and
> > only
> > > > having them in the NT access_mask?
> > >
> > > yes.  i told you, the minimum _and_ the maximum requirement is for
> > full SD
> > > support.  nothing more is necessary, and anything less will make it
> > > unusable for generic support.
> > 
> > Well, even NT has banned them from ACLs. Don't let the fact that the
> > code is the same in NT hide the fact that the bitmask in ACLs is a
> > different bitmask from that by which you request a set of permissions.

Actually, this isn't true; they're not banned at all, AFAICS.  At the
very least, the SDs for lots of registry keys in NT5 definitely
contain ACEs with some of the GENERIC_* bits set.  They're primarily
in inherit-only ACEs, but they're there, none the less.

> > > > Example of ACL, tell me what MAXIMUM ALLOWED should return (and
> > why):
> > > > ACE allows 0x7FFF
> > > > ACE denies 0x0001
> > > > ACE allows 0x8000
> > > > These three ACEs apply to the user.
> > >
> > > MAXIMUM_ALLOWED is SeAccessCheck specific.  are you implementing
> > this
> > > function?
> > 
> > Yes. If you're correct then 0x7FFF is the right return value. Ok with
> > me.
> 
> ok, then the ACL above is slightly nonsense, becaue i _think_ that the
> forst ACE is encountered and the others, as a result, ignored.
> 
> urr... actually, that's not true.  i think the deny ACE is the one that is
> ignored.  ur...
> 
> interesting exercise!
> 
> i _think_ that 0xffff _should_ be returned, but unfortunately, i bet yu
> that 0xfffe is _actually_ returned.
> 
> request 0x8000.  falls through 1st and 2nd ace, hits 3rd, is granted.
> 
> request 0x0001.  hits 1st ace, is granted.  deny ace _should_ be first in
> the list in this case, your ACL is an example of an ineffective ACL,
> therefore.
> 
> request 0xffff.  hits 1st ace, is denied (too much).  hits 2nd ace, is
> denied (0x0001).
> 
> hey, that's so cool!  it _is_ an effective acl, it's just not obvious
> what's going in, and trying to create a MAXIMUM_ALLOWED is impossible :-)
> :-)

The way I think this works (and I could definitely be wrong) is like
this:

ignoring maximum_allowed and other special flags

{
    int requested = user_request;  // passed in
    int granted;

    for (i=0; requested && i< #aces; i++) {
        if (ace applies to user 
            && ace applies to object /* i.e. isn't inherit only */) {
            if (ace is permit type) {
                granted = ace.mask & requested;
                requested &= ~granted;
            } else if (ace is deny type) {
                if (requested & ace.mask)
                    break;
            }
        }
    }
    if (requested) {
        /* access denied (didn't get granted everything) */
    } else {
        /* access permitted */
    }
}


for computing maximum allowed:

{
    int denied = 0;
    int granted = 0;

    for (i=0; i< #aces; i++) {
        if (ace applies to user 
            && ace applies to object /* i.e. isn't inherit only */) {
            if (ace is permit type) {
                granted |= ace.mask & ~denied;
            } else if (ace is deny type) {
                denied |= ace.mask & ~granted;
            }
        }
    }
    return granted;
}

Again, that's just how I think it works.  Someone really needs to sit
down and run through these possibilites on NT.


Todd


More information about the samba-technical mailing list