Author: derrell Date: 2007-08-15 17:40:09 +0000 (Wed, 15 Aug 2007) New Revision: 24465
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=24465 Log: - Sort ACEs according to http://support.microsoft.com/kb/269175 so that Windows Explorer doesn't complain about the order (and so that they get interpreted properly). Derrell Modified: branches/SAMBA_3_2_0/source/libsmb/libsmbclient.c Changeset: Modified: branches/SAMBA_3_2_0/source/libsmb/libsmbclient.c =================================================================== --- branches/SAMBA_3_2_0/source/libsmb/libsmbclient.c 2007-08-15 16:58:29 UTC (rev 24464) +++ branches/SAMBA_3_2_0/source/libsmb/libsmbclient.c 2007-08-15 17:40:09 UTC (rev 24465) @@ -3742,32 +3742,94 @@ } -/* The MSDN is contradictory over the ordering of ACE entries in an ACL. - However NT4 gives a "The information may have been modified by a - computer running Windows NT 5.0" if denied ACEs do not appear before - allowed ACEs. */ +/* + * Sort ACEs according to the documentation at + * http://support.microsoft.com/kb/269175, at least as far as it defines the + * order. + */ static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2) { - if (sec_ace_equal(ace1, ace2)) + BOOL b1; + BOOL b2; + + /* If the ACEs are equal, we have nothing more to do. */ + if (sec_ace_equal(ace1, ace2)) { return 0; + } - if (ace1->type != ace2->type) + /* Inherited follow non-inherited */ + b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); + b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * What shall we do with AUDITs and ALARMs? It's undefined. We'll + * sort them after DENY and ALLOW. + */ + b1 = (ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED && + ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && + ace1->type != SEC_ACE_TYPE_ACCESS_DENIED && + ace1->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + b2 = (ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED && + ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && + ace2->type != SEC_ACE_TYPE_ACCESS_DENIED && + ace2->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* Allowed ACEs follow denied ACEs */ + b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED || + ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); + b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED || + ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * ACEs applying to an entity's object follow those applying to the + * entity itself + */ + b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + ace1->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + ace2->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * If we get this far, the ACEs are similar as far as the + * characteristics we typically care about (those defined by the + * referenced MS document). We'll now sort by characteristics that + * just seems reasonable. + */ + + if (ace1->type != ace2->type) { return ace2->type - ace1->type; + } - if (sid_compare(&ace1->trustee, &ace2->trustee)) + if (sid_compare(&ace1->trustee, &ace2->trustee)) { return sid_compare(&ace1->trustee, &ace2->trustee); + } - if (ace1->flags != ace2->flags) + if (ace1->flags != ace2->flags) { return ace1->flags - ace2->flags; + } - if (ace1->access_mask != ace2->access_mask) + if (ace1->access_mask != ace2->access_mask) { return ace1->access_mask - ace2->access_mask; + } - if (ace1->size != ace2->size) + if (ace1->size != ace2->size) { return ace1->size - ace2->size; + } return memcmp(ace1, ace2, sizeof(SEC_ACE)); }