generic ACL interface (RFC)

Luke Kenneth Casson Leighton lkcl at switchboard.net
Tue Jul 27 22:13:01 GMT 1999


tim,

i would like to use the same acl interface on "objects" such as pipes,
smbtrans2 requests, individual msrpc calls and even info levels within
smbtrans2 or msrpc calls etc as _well_ as files / directories.

i would like to create static (or even dynamic) ACL objects that i can
reference using a function, to check whether (for example) a user has
sufficient access rights to enumerate a registry key; delete a user from
the SAM database; do a NetShareEnum at info level 102 etc.

this is one of the "other" reasons for keeping the ACL interface, at the
top level as "NT-like" (actually, "VMS-like" :-) as possible.

plus, we already _have_ code in samba that creates / decodes NT security
descriptors (see rpc_parse/parse_sec.c): that's half the battle won
already. all we really need to add is:

BOOL check_security_access(
security_context, /* the SID of the user / process requesting access */
access_rights, /* the access rights (read, enum, write etc) requested */
security_descriptor); /* the list of rights for the action requested */

ACL-instance-implementations (e.g the file / directory one) *may* require
knowledge of unix, but this should not be expected.  for example, what
happens when we implement "appliance mode" fully, and someone installs
this on linux with ntfs-driver support?  the fact that linux is unix then
becomes completely irrelevant at that point!

so, the API you have started is useful - for a specific purpose.  that
specific purpose is as a unix-ACL-file-sytem-support "sub" API.

the "main" API call check_security_access would be used:

- NT file SMBs (which contain security descriptors)

* obtain file system security_descriptor
* create access_rights depending on file SMB being requested (e.g for an
SMBreadX we set bit SEC_RIGHTS_READ_CONTROL
* obtain security context

call check_security_access(file_sys_sec_des, file_acc_rights, sec_ctx)


implementation of "obtain file system security_descriptor":

- if ordinary unix ugo / rwx permissions in use, go through mapping
function that turns these into a security descriptor

- if unix ACLs are in use, go through tim's ACL api to create security
descriptor

- if linux ntfs driver in use, go direct to disk and read security
descriptor straight off the platters.


implementation of "obtain security context":

- when user logged in, the "password database API" was checked.  maintain
state information of "unix user" (uid / gid) associated with "equivalent
NT user" (user SID / group SID).  from this association, grab the
"equivalent NT SID" that represents the unix process.


for MSRPC calls, call check_security_descriptor() from:

- security descriptor obtained on a per-msrpc-call table and also on a
per-info-level call.

- access rights obtained depending on the msrpc call (e.g SamrDeleteAlias
is SEC_RIGHTS_DELETE).

- obtain security_context in same was as for file system: user logs in on
SMB level or MSRPC level, password database API is checked: at that time a
unix user and "equivalent NT user" are associated with the pipe; SID is
obtained from this.


complaints likely to stem from "inefficiencies" due to use of NT API.
well, i don't think there will be any.  remember, don't knock the NT
security API _just_ because microsoft is using it!

luke

On Wed, 28 Jul 1999, Cole, Timothy D. wrote:

> Here's a very early shot at a header file for a generic internal ACL
> interface for SAMBA.  I _think_ the representation is general enough to
> cover all of the major Unix ACL schemes without losing information (well, at
> least POSIX/Solaris, HP-UX and AFS [I think]).
> 
> --- snip ---
> 
> typedef enum acl_entry_type {
> 	ACL_ENTRY_OTHER=0, /* "World" or "Everyone" */
> 	ACL_ENTRY_USER=1,
> 	ACL_ENTRY_GROUP=2,
> 	ACL_ENTRY_USER_AND_GROUP=(ACL_ENTRY_USER|ACL_ENTRY_GROUP),
> 	ACL_ENTRY_MASK=4
> } ACL_ENTRY_TYPE;
> 
> enum acl_entry_flags {
> 	ACL_ENTRY_IS_OWNER=1,
> 	ACL_ENTRY_IS_OWNING_GROUP=2,
> 	ACL_ENTRY_HAS_VALID_USER_ID=4,
> 	ACL_ENTRY_HAS_VALID_GROUP_ID=8,
> 	ACL_ENTRY_HAS_VALID_USER_SID=16,
> 	ACL_ENTRY_HAS_VALID_GROUP_SID=32,
> 	ACL_ENTRY_IS_DEFAULT=64,
> 	ACL_ENTRY_UNSUPPORTED=128 /* unsupported by client */
> };
> 
> enum acl_entry_permissions {
> 	ACL_PERM_EXECUTE=1,
> 	ACL_PERM_SEARCH=1,
> 	ACL_PERM_WRITE=2,
> 	ACL_PERM_INSERT=2,
> 	ACL_PERM_READ=4,
> 	ACL_PERM_CONTROL=8,
> 	ACL_PERM_DELETE=16,
> 	ACL_PERM_REMOVE=16,
> 	ACL_PERM_LOCK=32
> };
> 
> typedef struct acl_entry_info {
> 	ACL_ENTRY_TYPE type;
> 	int32 flags;
> 	uid_t user_id;
> 	DOM_SID user_sid;
> 	gid_t group_id;
> 	DOM_SID group_sid;
> 	struct {
> 		int32 allow;
> 		int32 deny;
> 	} perms;
> } ACL_ENTRY;
> 
> /* what should the return values mean here? */
> extern int get_acl(files_struct *fsp, ACL_ENTRY **entries, int *n_entries);
> extern int set_acl(files_struct *fsp, const ACL_ENTRY *entries, int
> n_entries);
> extern void free_acl(files_struct *fsp, ACL_ENTRY *entries);
> 
> /* these would be used internally; it may not be worthwhile to expose them:
> */
> extern BOOL client_supports_acl_entry(connection_struct *conn, const
> ACL_ENTRY *entry);
> extern BOOL implementation_supports_acl_entry(connection_struct *conn, const
> ACL_ENTRY *entry);
> 
> --- snip ---
> 
> Hrm; this almost seems kind of overengineered to me, but I do want to be
> able to express as much information as possible before translating it to the
> client's native format (i.e. in smbd/nttrans.c).  I didn't want to use the
> rpc_secdes.h representations since that would mean a lot more special-case
> code for each underlying ACL implementation.
> 
> Some notes on semantics:
> 
> get_acl() allocates its own ACL_ENTRY array, returning a pointer to it in
> *entries, and placing a count in *n_entries.  (the array can be subsequently
> freed with free_acl())  ACL entries that the client (as determined by the
> files_struct's associated connection_struct) does not support will be marked
> with ACL_ENTRY_UNSUPPORTED.
> 
> set_acl() will usually imply a call to get_acl() to compare the existing
> permissions against the desired ones.
> 
>  Entries in the "desired" ACL that do not exist in the "current" ACL will be
> added.
> 
>  Entries in the "current" ACL that do not exist in the "desired" ACL will be
> removed, UNLESS they are marked as ACL_ENTRY_UNSUPPORTED, in which case they
> will be left alone.
> 
>  Entries in the "current" ACL that have corresponding entries in the
> "desired" ACL will be modified to match the permissions expressed in the
> "desired" ACL.
> 
> ACL_ENTRY_UNSUPPORTED entries won't get presented to the client, which might
> be a bad thing -- they don't see the entire ACL.  "A little knowledge is a
> dangerous thing", and that applies especially to security.  OTOH, there is
> no possible way to represent all ACL entries on some systems to some clients
> -- should we not bother with ACLs at all in such cases?
> 
> I dunno.  What do you folks think?
> 
> 

<a href="mailto:lkcl at samba.org"   > Luke Kenneth Casson Leighton    </a>
<a href="http://www.cb1.com/~lkcl"> Samba and Network Development   </a>
<a href="http://samba.org"        > Samba Web site                  </a>
<a href="http://www.iss.net"      > Internet Security Systems, Inc. </a>



More information about the samba-technical mailing list