Re: Mapping between POSIX and NT ACLs

2002-10-15 Thread Andreas Gruenbacher

On Tuesday 15 October 2002 12:26, Stefan (metze) Metzmacher wrote:
> HI Andreas,
>
> can you send me a link to our latest patches, please

I'm not finished with adding yesterday's changes; the other versions are at 
.

--Andreas.



Re: Mapping between POSIX and NT ACLs

2002-09-09 Thread Andreas Gruenbacher

Hello,

here is an improved version of the patch.

--Andreas.

--- samba-2.2.5.orig/source/smbd/posix_acls.c   2002-06-19 03:13:48.0 
+0200
+++ samba-2.2.5/source/smbd/posix_acls.c2002-09-09 16:23:54.0 +0200
@@ -346,7 +346,23 @@
if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) {
nt_mask = UNIX_ACCESS_RWX;
} else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) {
+#ifdef OLD_MAPPING
+   /* Windows NT refuses to display ACEs with no permissions in them (but
+  they are perfectly legal with Windows 2000). If the ACE has empty
+  permissions we cannot use 0, so we map UNIX_ACCESS_NONE to 
+WRITE_OWNER
+  which we ignore when set an ACL. */
nt_mask = UNIX_ACCESS_NONE;
+#else
+   /* With the new mapping it has become feasible to convert the entry to
+  DENY/.../FULL, which isn't so wrong anymore since we drop
+  ALLOW/Everone/NONE ACEs anyway. The only problem: This will mask off
+  permissions from the owner if he is member of the group with no
+  permissions. Perhaps it's better to fix the code that does that
+  masking off? */
+   *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED;
+   nt_mask = UNIX_ACCESS_RWX | GENERIC_ALL_ACCESS;
+   
+#endif
} else {
nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
@@ -678,6 +694,43 @@
return True;
 }
 
+static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, 
DOM_SID *pfile_grp_sid)
+{
+   BOOL got_user_obj, got_group_obj;
+   canon_ace *current_ace;
+   int i, entries;
+   
+   entries = count_canon_ace_list(ace);
+   got_user_obj = False;
+   got_group_obj = False;
+
+   for (i=0, current_ace = ace; i < entries; i++, current_ace = 
current_ace->next) {
+   if (current_ace->type == SMB_ACL_USER_OBJ)
+   got_user_obj = True;
+   else if (current_ace->type == SMB_ACL_GROUP_OBJ)
+   got_group_obj = True;
+   }
+   if (got_user_obj && got_group_obj) {
+   print_canon_ace_list( "ACL had owning user/group entries", ace);
+   return;
+   } else {
+   print_canon_ace_list( "Faking owning user/group entries", ace);
+   }
+
+   for (i=0, current_ace = ace; i < entries; i++, current_ace = 
current_ace->next) {
+   if (!got_user_obj && current_ace->owner_type == UID_ACE &&
+   sid_equal(¤t_ace->trustee, pfile_owner_sid)) {
+   current_ace->type = SMB_ACL_USER_OBJ;
+   got_user_obj = True;
+   }
+   if (!got_group_obj && current_ace->owner_type == GID_ACE &&
+   sid_equal(¤t_ace->trustee, pfile_grp_sid)) {
+   current_ace->type = SMB_ACL_GROUP_OBJ;
+   got_group_obj = True;
+   }
+   }
+}
+
 /
  Unpack a SEC_DESC into two canonical ace lists.
 /
@@ -688,6 +741,8 @@
canon_ace **ppfile_ace, 
canon_ace **ppdir_ace,
SEC_ACL *dacl)
 {
+   extern DOM_SID global_sid_Creator_Owner;
+   extern DOM_SID global_sid_Creator_Group;
extern DOM_SID global_sid_World;
extern struct generic_mapping file_generic_mapping;
BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False);
@@ -805,15 +860,27 @@
/*
 * Try and work out if the SID is a user or group
 * as we need to flag these differently for POSIX.
+* Note what kind of a POSIX ACL this should map to.
 */
 
if( sid_equal(¤t_ace->trustee, &global_sid_World)) {
current_ace->owner_type = WORLD_ACE;
current_ace->unix_ug.world = -1;
+   current_ace->type = SMB_ACL_OTHER;
+   } else if (sid_equal(¤t_ace->trustee, 
+&global_sid_Creator_Owner)) {
+   current_ace->owner_type = UID_ACE;
+   current_ace->unix_ug.world = -1;
+   current_ace->type = SMB_ACL_USER_OBJ;
+   } else if (sid_equal(¤t_ace->trustee, 
+&global_sid_Creator_Group)) {
+   current_ace->owner_type = GID_ACE;
+   current_ace->unix_ug.world = -1;
+   current_ace->type = SMB_ACL_GROUP_OBJ;
} else if (sid_to_uid( ¤t_ace->trustee, 
¤t_ace->unix_ug.uid, 
&sid_type)) {
 

Mapping between POSIX and NT ACLs

2002-09-08 Thread Andreas Gruenbacher

Hi Jeremy and all,

as recently discussed on #samba-techical the mapping between POSIX ACLs and 
Windows NT ACLs is not ideal. A perfect mapping probably cannot be achieved, 
but the current mapping can still be improved. Attached is a patch that I 
post with request for comment. (Apologies for the unusually long posting.)

I have tested the changes on Windows NT as well as Windows 2000; it seems to 
work as expected.

The previous version of the mapping had to return ACL entries for the file 
owner, group, and others no matter if these entries contained any permissions 
or not. The reason for this (if I understand correctly) was that there was no 
way to add an ACL entry for Everyone as such an entity could be selected. The 
user database browsing functionality has been implemented/improved since, so 
this now works. So it is now possible to leave out ACL entries.

It's (still) important to support Windows NT as well as newer Windows systems. 
Windows NT refuses to display ACL entries that have no permissions in them 
(while Windows 2000 accepts them happily). Therefore the old mapping abused 
the Take Ownership (O) permission to mark ACL entries which have neither 
read, write nor execute permission. This probably was the best we could do 
when the current mapping was designed/implemented.

Windows also knows DENY ACL entries in addition to ALLOW entries. We could 
also use DENY ACL entries to indicate that a user has no access. 
Unfortunately DENY ACL entries take precedence over all other ACL entries in 
the Windows ACL semantics (if I understand this correctly), so the 
ALLOW/Everyone/NONE entry, which would become DENY/Everyone/ALL, would 
indicate no access for anybody. Since we can now simply leave out empty ACL 
entries we can drop the ALLOW/Everyone/NONE entry, and don't need a hack for 
this common case.

There are still situations in which we would like to indicate that a party has 
no access (e.g., the owning group for a file with `rwr--' permissions, 
something rather obscure to have). We could either still map this to 
`ALLOW/Group/O', or to `DENY/Group/ALL'. The latter now seems preferable (and 
is also displayed correctly in Windows NT/2000), with one minor drawback: 
When such an ACL is read back in by Samba, Samba follows Windows ACL 
semantics as closely as possible, so if the file owner is also member in the 
owning group (which is the usual case) Samba removes the owner's read and 
write permissions. *Ouch!*

I think it would make more sense to make Samba not follow Windows ACL 
semantics that closely to avoid such effects. What do you think?


There are still a few problems to overcome:

(1) The ACL_MASK POSIX ACL entry is not mapped at all. I currently have no 
good idea.

(2) POSIX ACLs have the following form (textual representation):
u::rw-
u:joe:rw-
g::r--
m::rw-
o::---
If the file has a different owner, the u:joe:rw- entry applies for joe. If a 
file is owned by user joe, the u::rw- entry applies for joe, and the 
u:joe:rw- entry has no effect. The same can happen with a named group/owning 
group.

Windows only allows one ACL entry for each identity, so we cannot represent 
this in Access ACLs.

For directories there is a special identity CREATOR_OWNER, so we could map the 
u::rwx entry of a Default ACL to the CREATOR_OWNER identity. Unfortunately 
there is nothing similar for the owning group (Windows doesn't have this 
concept). Also CREATOR_OWNER cannot be used for files, so the merging of ACL 
entries from a file's Access ACL and Default ACL, which Windows requires us 
to do to correctly map the ACL entry inheritance flags, would be tricky.


Regards,
Andreas.

----------
 Andreas GruenbacherSuSE Linux AG
 mailto:[EMAIL PROTECTED] Deutschherrnstr. 15-19
 http://www.suse.de/   D-90429 Nuernberg, Germany


--- samba-2.2.5.orig/source/smbd/posix_acls.c   2002-06-19 03:13:48.0 
+0200
+++ samba-2.2.5/source/smbd/posix_acls.c2002-09-08 23:17:18.0 +0200
@@ -346,7 +346,23 @@
if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) {
nt_mask = UNIX_ACCESS_RWX;
} else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) {
+#ifdef OLD_MAPPING
+   /* Windows NT refuses to display ACEs with no permissions in them (but
+  they are perfectly legal with Windows 2000). If the ACE has empty
+  permissions we cannot use 0, so we map UNIX_ACCESS_NONE to 
+WRITE_OWNER
+  which we ignore when set an ACL. */
nt_mask = UNIX_ACCESS_NONE;
+#else
+   /* With the new mapping it has become feasible to convert the entry to
+  DENY/.../FULL, which isn't so wrong anymore since we drop
+  ALLOW/Eve