Why does canonical order for ACEs put deny ACEs ahead of allow ACEs?

Date:June 8, 2007 / year-entry #206
Tags:tipssupport
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20070608-00/?p=26503
Comments:    31
Summary:So-called canonical order for ACEs in an access control list places deny ACEs ahead of allow ACEs. Why is this the canonical order? Because it gives results that are sensible. The algorithm for determining whether a user has access to an object protected by an ACL is as follows: let access-still-needed = access-requested for each...

So-called canonical order for ACEs in an access control list places deny ACEs ahead of allow ACEs. Why is this the canonical order?

Because it gives results that are sensible.

The algorithm for determining whether a user has access to an object protected by an ACL is as follows:

let access-still-needed = access-requested
for each ACE in the ACL that applies to the user (in order)
    if it is a deny ACE:
        if (access-still-needed & ace-mask) return access-denied
    if it is an allow ACE:
        access-still-needed &= ~ace-mask
end for loop
if access-still-needed != 0 return access-denied
return access-granted

In words, we go through the ACEs in the ACL in the order they appear, paying attention only to the ones that apply to the user, i.e. the ones whose SIDs are present in the user's token. If a permission is being denied, and the user is still looking for that permission, then access is denied. If a permission is being granted, then those permissions are subtracted from the permissions the user is still looking for. If, at the end of the day, all the permissions the user requests have been granted, then access is granted.

The key detail in the above algorithm is that deny ACEs apply to permissions not yet granted and not to the original set of permissions requested. If you deny write, but an earlier ACE grants it, then the deny has no effect.

Let's look at what happens if we apply this algorithm to an ACL that is not in canonical order. Our ACL is as follows:

  • Grant write access to Alice.
  • Deny read and write access to Users.
  • Grant read access to Users.

Let's say that Alice wants write access. We start with access-still-needed = write, and the first ACE grants it, leaving access-still-needed equal to zero. The second ACE denies read and write, but Alice already got write access thanks to the first rule, and she never asked for read access, so this deny ACE has no effect. The third ACE also has no effect since Alice wasn't looking for read access. Result: Alice gets write access.

On the other hand, suppose Alice wants read access. The first ACE has no effect, since Alice isn't interested in write access. The second ACE then denies access since Alice is being denied read access which she hasn't gotten yet. Alice's request is rejected without even looking at the third ACE.

Notice that if the ACEs are not canonically-ordered, you can't use a simple rule like "deny ACEs take priority over allow ACEs". The rule is "Well, you have to go through each ACE one by one, and you get access if you get all the things you want before somebody denies them." It sort of turns into a game show.

Since graphical ACL editors typically don't show the order of the ACEs, some sort of canonical order needs to be established so that you don't run afoul of this "order of operations" problem. Notice that in the algorithm above, you can swap two adjacent allow ACEs and two adjacent deny ACEs without affecting the result, but you cannot swap the positions of an allow and a deny ACE. Therefore, the canonical ordering must either be "all deny ACEs come before all allow ACEs" or "all allow ACEs come before all deny ACEs".

Note, however, that if you choose to have all allow ACEs come before all deny ACEs, then you don't need deny ACEs at all! If you look at the algorithm above, if there is no ACE that mentions the permission you want, then access is denied. The deny ACEs don't add anything to the picture:

// assuming that all allow ACEs come before all deny ACEs
let access-still-needed = access-requested
for each allow ACE in the ACL that applies to the user (in order)
    access-still-needed &= ~ace-mask
end for loop
for each deny ACE in the ACL that applies to the user (in order)
    if (access-still-needed & ace-mask) return access-denied
end for loop
if access-still-needed != 0 return access-denied
return access-granted

Notice that once you make it out of the first "for" loop, the return value is going to be access-denied if access-still-needed is nonzero. All the deny ACEs give you is another way to say "no". But you were going to say "no" anyway.

Therefore, for deny ACEs to be meaningful, the canonical ordering should place them ahead of allow ACEs. That way, you get three tiers of permission instead of just two:

  • If there is a deny ACE, then it is denied.
  • If there is no deny ACE but there is an allow ACE, then it is allowed.
  • If there is neither a deny ACE or an allow ACE, then it is denied.

Postscript: Our sample non-canonical ACL above can easily be converted to an equivalent canonical one:

  • Grant write access to Alice.

Why does this work?

Well, first notice that the second rule ("Deny read and write access to Users") completely overrides the third rule ("Grant read access to Users"), since any attempt by the third rule to grant read access to Users will be thwarted by the second rule, which denies it.

But the second rule itself is unnecessary. We are taking advantage of the test outside the loop in the access algorithm: if access-still-needed != 0 return access-denied. This rule means that the default for all access mode is to deny. Therefore, you don't need to deny anything explicitly unless you have a broader rule later that grants it. (If you have a more narrow rule later that grants it, then that narrower rule is pointless, as we saw in the previous paragraph.) In other words, there's no point denying read and write to Users since merely not saying anything is equivalent to a denial.


Comments (31)
  1. I suppose that it adds flexibility for the API to allow you to specify non-canonical ACE ordering, but I never understood why the API wasn’t designed to just re-order ACEs to the canonical order automatically.

    (I know that non-canonical ACE ordering is used to reproduce the behaviour of MAPI permissions, so I won’t deny that the ability to use non-canonical ACE ordering has some utility, but it sure feels like a hack…)

  2. Ben Cooke says:

    What effect does the inheritance of permissions from parent containers have on all this?

    Does it apply all of the DENY rules for the entire heirarchy and then all of the ALLOWs, or does it do that algorithm separately for each item in the heirarchy?

    I guess this boils down to whether an ALLOW on the parent overrides a DENY on the child or vice-versa… but does anything special happen in this case?

  3. Nawak says:

    I thought I understood and then I actually tried :)

    In my C: root folder (with "Full Access" permission for administrators/SYSTEM and "Read/Execute" access for users), I create a new empty file and then edit its ACL to deny the "remove" permission for Administrators (as I was one during the test).

    Now if I understand correctly this post and this page (http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/distrib/dsce_ctl_hziq.mspx?mfr=true), the inherited permissions come after the explicit ones so my deny remove should apply.

    But it doesn’t… I can delete the file!

    I know it has something to do with the fact that there’s also a "delete file" permission in the parent folder and that this permission is granted for me but then how do I prevent a file to be deleted???

    If I remove the "delete file" permission from the parent folder then I won’t be able to delete any file from folder!!

    PS:

    I’m sorry that I do not use the correct permission names, but I have a french XP and those fields have been badly translated… you can see what happens when I translate them back!

    For instance there’s a interesting confusion made by the translators: What was (I suspect) "Read attributes" has been translated as if it was "Attributes of read"! So you end up wondering what happens when you deny/grant that kind of access! Fortunately, the "Read extended attributes" was correctly translated (since there are no confusion possible) and you are able to deduce what was meant for the previous field…

    Was that a digression? :)

  4. Foolhardy says:

    You can’t have full POSIX mapping of owner/group/world style access using only canonically ordered ACEs.

    For example, rw-r-xrw-, which grants read-write access to the owner, read execute to the group and read write to everyone else can only be represented by having a deny entry in the middle:

    Owner Deny Execute

    Owner Allow Write

    Group Deny Write

    Group Allow Execute

    Everyone Allow Read+Write

    See http://cygwin.com/cygwin-ug-net/ntsec.html#ntsec-mapping

    Unix-over-NT layers like SFU (now SUA) and Cygwin correctly represent such access modes in ACEs but the standard ACL editor will mangle them, given the chance.

    There are other mappings that can only be represented by non-canonical ACE orderings– any time more than two different overlapping layerings or groupings of users and groups need different access.

    Incidentally, SD Edit is a graphical ACL editor that supports explicit ACE ordering.

    http://czwsoft.dyndns.org/sdedit.html

  5. Leo Davidson says:

    The differences between the way ACLs really work and they way they appear to work in the Explorer/RegEdit UI, coupled with the amount of code you have to write to do anything with file or registry permissions, is something that I’d love to see improved by a higher-level API or wrapper.

    Trying to reproduce functionality of those UIs, even when using the same standard dialogs, is a big task. Either you have to spend a lot of time writing complex, error prone, and yet quite boring, code that is already inside Explorer/RegEdit (but not exposed) or, more often, the feature is left out completely on the basis that so few people mess with permissions that it isn’t worth the effort. It’s a shame in both cases.

    An API which took care of canonical ordering, merging, inheritance and, especially, the permissions dialogs would mean that more apps would allow proper permissioning of things. There’s nothing wrong with the existing API — you have to expose the full granularity — but it would really help if there was a higher-level API or wrapper in addition to it.

    Having read up on how to use the permissions dialogs (while I was looking at writing an alternative registry editor) it looked like a hell of a lot of code to write just to duplicate the “set permissions” context menu of RegEdit. I didn’t plan to do anything special with permissions — my planned improvements were in other areas — but I also did not want to provide a tool which did less than RegEdit in any area, else people would have to switch between tools which is nasty.

    When mistakes are made in this kind of code the results can be very confusing to both user and programmer since the other tools (Explorer, RegEdit) show you simplified views of permissions and thus don’t show you what’s really gone wrong. (cacls.exe to the rescue, but not many people know about that.)

    Anyway, this isn’t a complaint and I’m sure there are a million other higher priority APIs and wrappers and examples to write but it’d be great if one day this stuff was made less of a burden on application developers.

    [Explorer and Regedit don’t have ACL-editing UI. They use the common ACL editor in aclui.dll. Is there shame in not exposing that doesn’t exist? -Raymond]
  6. BryanK says:

    Regarding inherited ACEs:

    Aren’t they pushed down to the children "automatically"?  I thought that the ACL-check code only had to look at the ACEs that existed on the object itself, because that’s how the inheritance stuff worked.

    (And I thought it was set up this way to stay more compatible with NT4, which couldn’t inherit permissions, but which had a UI option to push a parent object’s permissions down to its children instead.  IOW, I thought that the ACL-editing APIs took over the job of forcibly pushing down the parent’s inheritable ACEs to any children that are marked inheriting.)

    If all that’s true (and I’m not sure whether it is), then it doesn’t matter when inherited ACEs are checked, because they’re present on the children already.  (I suppose it does matter where the APIs put them on the children in that case, though.  Hmm.)

  7. KJK::Hyperion says:

    Foolhardy: no way, you don’t need the deny entries. Accesses that are not granted are denied by default. They are perfectly supported by the ACL editor, too. Try chmodding a file from Cygwin, and then look at its ACL. This is what a mode of 700 looks like from the Windows point of view:

    C:cygwinhomeHyperionaaa REGULUSHyperion:(accesso speciale:)

                                                STANDARD_RIGHTS_ALL

                                                DELETE

                                                READ_CONTROL

                                                WRITE_DAC

                                                WRITE_OWNER

                                                SYNCHRONIZE

                                                STANDARD_RIGHTS_REQUIRED

                                                FILE_GENERIC_READ

                                                FILE_GENERIC_WRITE

                                                FILE_GENERIC_EXECUTE

                                                FILE_READ_DATA

                                                FILE_WRITE_DATA

                                                FILE_APPEND_DATA

                                                FILE_READ_EA

                                                FILE_WRITE_EA

                                                FILE_EXECUTE

                                                FILE_READ_ATTRIBUTES

                                                FILE_WRITE_ATTRIBUTES

                               REGULUSNessuno:(accesso speciale:)

                                               READ_CONTROL

                                               FILE_READ_EA

                                               FILE_READ_ATTRIBUTES

                               Everyone:(accesso speciale:)

                                        READ_CONTROL

                                        FILE_READ_EA

                                        FILE_READ_ATTRIBUTES

    Note that READ_CONTROL is always allowed (not coincidentally it’s part of STANDARD_RIGHTS_REQUIRED), as are FILE_READ_EA and FILE_READ_ATTRIBUTES (because you can always read file modes and attributes with fstat)

    Windows ACLs were pretty much designed with the express aim to support UNIX file modes

    Leo Davidson: for high-level, canonical form editing of ACLs from code, see the TRUSTEE and EXPLICIT_ACCESS structures and all related functions; for the standard ACL editor UI, see CreateSecurityPage and ISecurityInformation

  8. @Ben Cooke and others:

    The canonical ACE ordering when inheritance is involved is:

    1.  Direct Deny ACEs
    2.  Direct Allow ACEs

    3.  Inherited Deny ACEs

    4.  Inherited Allow ACEs

    @Nawak:

    Deleting a file is really an operation on the containing folder.

    @BryanK:

    If you mean what I think you mean, then yes, you’re right.  When an object inherits an ACL, it actually gets its own copy, with inherited ACEs marked as inherited.

  9. Random Reader says:

    @Nawak: Yes, it is because of the permissions on the folder.  An ACE has two delete permissions, "delete child" (the UI calls it "delete subfolders and files") and "delete" (self).  If you are granted "delete child" permisson on a folder, then you are allowed to delete any files within it.  If not, you must have "delete" permission on the file itself.

    Usually what you would do is have an inheritable ACE on the folder grant the "delete" permission, so any new files created inside it have the "delete" permission already.  Then you remove "delete child" permission from the folder, and remove "delete" from specific files.  (I said "remove", but obviously adding deny ACEs works just as well.)

  10. Random Reader says:

    @KJK::Hyperion: That’s what I thought originally, but it’s not sufficient.  POSIX has 3 permission buckets: owning User, owning Group, and Other.  The key issue is that NT has no concept of "Other"; "Everyone" consists of, well, everyone (except anonymous users in some configurations, but that’s not relevant here) which includes both the owning user and group.  The POSIX "Other" does not.

    Foolhardy’s example denies a permission (Write) to the owning group, while still granting it to everyone else.  This type of exclusion requires a deny ACE, but since the owning user is also part of that group, this ACE cannot come first as canonical order demands.

    Indeed, tests with SUA demonstrate this.  I created a file with an ACL containing one ACE, granting full access to Everyone.  The file was owned by user Administrator, group None.  SUA’s CSH shows:

    -rwxrwxrwx  1 Administrator  None  0 Jun  8 21:00 test.txt*

    …after "chmod u=rw,g=rx,o=rw test.txt":

    -rw-r-xrw-  1 Administrator  None  0 Jun  8 21:00 test.txt*

    …and back in NT land, the ACL now contains 5 ACEs:

    1 allow Administrator <all but execute>

    2 deny Administrator <execute>

    3 allow None <read rights, execute>

    4 deny None <write rights>

    5 allow Everyone <all but execute and write DACL/owner>

    ACE #2 is required under the assumption that the User is part of the Group — and execute permission is granted to the Group.  It could be in canonical order in this particular case though.

    ACE #4 is required to deny write permissions to the Group, since they are allowed for everyone else.  It must be below the allow entry for the User, and not in canonical order, because the User is still allowed these permissions.

    I suppose this is a bad example since the owning group was None in my test, but the logic still works.

  11. Leo Davidson says:

    [Explorer and Regedit don’t have ACL-editing UI. They use the common ACL editor in aclui.dll. Is there shame in not exposing that doesn’t exist? -Raymond]

    I know they don’t contain have the dialog itself, and I know the dialog is exposed, but to use that dialog a lot of APIs and concepts have to be digested, most of which are orthogonal to what an application developer uses. (By which I mean that getting this dialog  to display in their app is the only time they will use most of this knowledge and that makes it more difficult to justify the time and energy, given the amount of reading and fact-digestion involved.)

    That code is presumably in Explorer and RegEdit and I figured it’d be nice to move it into a higher level API that other programs can use.

    I mean, look at the amount of code and understanding required in the CodeProject article that’s also linked in these comments (http://www.codeproject.com/win32/accessctrl4.asp) and keep in mind that is part four and requires an understanding of two of the previous parts. (The third part is about .Net so can be skipped.)

    If all you want to do is to allow someone to modify the permissions on a file or registry item, that’s a lot of work for a feature that is easy to strike off the list. For file’s it’s not so bad since there is an API to display a standard Properties page which gives you the security dialog for free, and there’s also example code on the net for doing it, but for the registry it seemed like you had to do things the hard way.

    Or is there an easy way to use the dialog? I might be wrong.

    Ignoring the dialog for a second, an API for dealing with ACLs in the way which the UI deals with them, supporting inheritance, merging, copying and so on would come in handy. I guess the code to do that is in aclui.dll but I don’t know and I don’t think it is exposed anywhere as a public API.

  12. Foolhardy says:

    @Leo Davidson:

    SetKernelObjectSecurity on a file or key only edits the object in question, with no inheritance.

    SetNamedSecurityInfo, OTOH does implement auto-inheritance for children below the named object.

    TreeResetNamedSecurityInfo also implements auto-inheritance, supports the replace-direct-entries option and gives you the option of status reports and cancel/retry error handling. Presumably, it’s the same function that regedit and the shell use when you click OK.

  13. Norman Diamond says:

    Why is this the canonical order?

    Because it gives results that are sensible.

    The actual order of traversal from beginning to end is sensible.  The canonical order is required as a workaround for broken ACL editing tools, not for the ACL structures themselves.

    Friday, June 08, 2007 8:38 PM by Aaron Margosis

    Deleting a file is really an operation on the

    containing folder.

    "The" containing folder?  Who says there’s only one?  For pedantic reasons we might want to check for write permissions on one or all containing folders, but delete permissions should depend only on the file itself and the credentials of the intending deletor.

  14. BryanK says:

    When an object inherits an ACL, it actually gets its own copy, with inherited ACEs marked as inherited.

    Yeah, that’s how I thought it worked.  That’s much more concise though.  ;-)

  15. @Norman Diamond:  "Who says there’s only one?"  I don’t know whether you’re referring to hard links or to parent/grandparent/greatgrandparent containers, so I’ll answer both.

    With hard links, a file can exist in multiple folders at the same time.  "Deleting a file" deletes the reference to the file from one folder.  You might have permission to delete it from one folder, but not from another.

    Grandparent/etc folder permissions do not matter, unless your token doesn’t have the ChangeNotify (Bypass traverse checking) privilege, which should always be present and enabled.

  16. Norman Diamond says:

    Monday, June 11, 2007 9:22 AM by Aaron Margosis

    With hard links, a file can exist in multiple

    folders at the same time.  "Deleting a file"

    deletes the reference to the file from one

    folder.  You might have permission to delete

    it from one folder, but not from another.

    As described so far, that resembles Unix.  In Unix it is pretty much documented that rm’ing a filename really only removes an inode and the file doesn’t really go away until the counts of inodes that link to it and processes that have it open are both zero.

    In Windows I don’t recall seeing it documented that way.  The MSDN page for DeleteFile doesn’t describe it that way.  Also in the page on File Security and Access Rights, FILE_DELETE_CHILD gives permission to delete the directory and files that it contains, including read-only files.  Does this mean deletion of NTFS equivalents of indoes?  Including read-only NTFS equivalents of inodes?

    Tangent:

    Grandparent/etc folder permissions do not

    matter, unless your token doesn’t have the

    ChangeNotify (Bypass traverse checking)

    privilege, which should always be present and

    enabled.

    If Bypass Traverse Checking should always be present and enabled, why does it even exist?  Meanwhile, surprises don’t hit the owners of processes that have this thing set, surprises hit the owners of directories and files who didn’t want their files to get traversed to by bypassers.  If an administrator created a hard link somewhere else so that persons unknown to the file’s owner can still read the file, well tough, the owner will have to apply for administrative sanctions.  But when persons unknown reach the file when the owner didn’t expect it because Windows provides that privilege, I don’t agree with you about "should".

  17. @Norman:  I believe that the answers to both your comments derive from the fact that NT was built to support Posix and other applications.  I’m sure there are subtle differences wrt inodes, but I’m not expert in UNIX so I couldn’t specify.

    Marking a file "read-only" is just a hint.  NTFS permissions are what really protect them.  Just like "rm -f" can delete "read-only" files in UNIX.

    The reason for "bypass traverse checking" was also to support Posix functionality.  Note that having that privilege doesn’t mean you can scan any folder.  You need to have permissions on the folder and be able to name it before you can perform any operations in it.  What "bypass traverse checking" does is skip the recursive check to parent/grandparent/etc up to the root before determining whether access is granted or denied, which is a performance benefit if nothing else.  But if you have no permissions in the target node, then bypass traverse won’t give you anything.

    My use of the word "should" is because that’s in our recommended guidance.  Here’s what the WinXP Threats and Countermeasures Guide says:

    "The Windows operating systems, as well as many applications, were designed with the expectation that anyone who can legitimately access the computer will have this user right. Therefore, Microsoft recommends that you thoroughly test any changes to assignments of the Bypass traverse checking user right  before you make such changes to production systems. In particular, IIS requires this user right to be assigned to the Network Service, Local Service, IIS_WPG, IUSR_<ComputerName>, and IWAM_<ComputerName> accounts. (It must also be assigned to the ASPNET account through its membership in the Users group.) This guide recommends that you leave this policy setting at its default configuration."

  18. Norman Diamond says:

    Monday, June 11, 2007 9:58 PM by Aaron Margosis

    Marking a file "read-only" is just a hint.

    That is true for users who have (or can acquire) privileges to change the file’s permissions.  If it’s true for other users too then we’re in bigger trouble than I thought.

    What "bypass traverse checking" does is skip

    the recursive check to parent/grandparent/etc

    up to the root

    Yes, which is exactly the reason why it doesn’t surprise the owner of the process that does this traversing and it only surprises the owner of the parent/grandparent/etc.

  19. Norman Diamond says:

    Speaking of Posix semantics, two by-the-ways:

    (1)  In a case that happened a millennium or two ago, the equivalent of “bypass traverse checking” did surprise a Unix user.  A professor had disabled read access to a directory and thought that meant students would be unable to read file in the directory.  Some students turned in assignments containing the professor’s code.  Some even forgot to rename all the variables to prevent us from recognizing it.

    (2)  Windows hard links are still harder to understand than Unix hard links.  This case is on a Windows XP system with Windows Services for Unix and case sensitivity enabled.  I took this screenshot before doing any experimenting, and guess that the differently cased directory was created by some XP security patch in 2006:

    http://www.geocities.jp/hitotsubishi/xp_sfu_casesensitivity.png

    As far as I can tell, both directories are hard links to the same place.  If I try to display either folder in Windows Explorer, the address bar shows the pathname with uppercase P.  If I use the CMD.EXE command prompt to CD into either directory, it CDs into the pathname with uppercase P.  Korn Shell could cd into either directory as directed.  In both directories, ls -l showed identical contents.  Today as an experiment, using Korn Shell, in one directory I created a file (touch diamond.txt) and then cd’d into the other directory and deleted the file (rm diamond.txt).  So I’m pretty sure both folder names really are hard links to the same place.  But now after that experiment, one folder has its last-written timestamp changed to today, and the other folder still has its old timestamp.  How can this be?  File creation in one directory should have done a write on that directory, and file deletion in the other directory should have done a write on that other directory, even though these were done using SFU commands.

    [Hey guys, remember when we were talking about deny ACEs? Me neither. -Raymond]
  20. Random Reader says:

    @Norman Diamond:

    > Marking a file "read-only" is just a hint.

    That is true for users who have (or can acquire) privileges to change the file’s permissions.  If it’s true for other users too then we’re in bigger trouble than I thought.

    "Read-only" is not a permission, it’s just an attribute on the file.  As Aaron said, if you want to declare someone has only read permission, you need to use the actual permission system: the file’s DACL.

    More on "bypass traverse checking": http://blogs.technet.com/markrussinovich/archive/2005/10/19/the-bypass-traverse-checking-or-is-it-the-change-notify-privilege.aspx

  21. @Raymond:  Sorry about that.  Windows authz has some very complex rules, so any discussion of it risks numerous ratholes.

    @Norman Diamond: re – (1) surprising the UNIX user.  I don’t know how UNIX security works beyond the limited 0777 thing, so I don’t have an answer.  In Windows it’s straightforward to get permissions to be inherited, particularly when using the GUI ACL editor.  Like I said, if the user had no permissions to read the file, then bypass-traverse wouldn’t have allowed it either.

    Re (2) your [URL] link must be broken.  I clicked on it and got a picture of a middle-aged Asian woman with bad teeth.  Tried a few more times and got other ads, all in Japanese (I think).  Babelfish didn’t help.

    Links are easy – run MKLINK at a Vista CMD prompt…

  22. Norman Diamond says:

    I put a Deny ACE for my personal account on Pinball, and then was rejected in an attempt to see the contents of pinball.  Korn Shell was prohibited from doing an ls command on both directories too.

  23. Norman Diamond says:

    Tuesday, June 12, 2007 1:35 AM by Aaron Margosis

    Re (2) your [URL] link must be broken.

    It wasn’t broken when I posted it.  Now it says the page is under construction.  I can’t imagine how a png file could be under construction.  Oh it gets weirder:

    Right-click the shortcut, copy the shortcut, open a new instance of Internet Explorer, paste the URL, and my screenshot displays.

    Right-click the shortcut, open the target page in a new window, and Yahoo says my page is under construction.

  24. @Norman:  strange, yes, but when I copy/paste the URL I get the screenshot.  Click on the link and I get the bad teeth.

    Anyway:  I’m not a file system expert, but I *think* that hard links apply only to files, not to folders.  I also think that while the Windows kernel can handle a case-sensitive file system (to support Posix), Win32 is case-preserving but case-insensitive.  Two folders that differ only by case seems like something that likely was done within Services for Unix.

  25. Norman Diamond says:

    Tuesday, June 12, 2007 1:54 AM by Aaron Margosis

    > strange, yes, but when I copy/paste the URL I

    > get the screenshot.  Click on the link and I

    > get the bad teeth.

    So Yahoo is doing the same to you that they do to me.  I wonder why.

    > I’m not a file system expert, but I *think*

    > that hard links apply only to files, not to

    > folders.

    But when I set a Deny ACE on one of them, the ACE affected both of them.

    (The next weird thing is that I was able to delete the Deny ACE.  Since I successfully denied myself access, I thought it would be necessary to use another account to delete that Deny ACE, but no, Windows granted the denied user permission to delete the denial.)

    > I also think that while the Windows kernel

    > can handle a case-sensitive file system (to

    > support Posix), Win32 is case-preserving but

    > case-insensitive.

    Win32’s default is case-preserving but case-insensitive.  Posix support allows changing that to case-sensitive, and I did change that when installing Services for Unix.  (I didn’t know that some XP security patch was going to give me a second pinball directory differing only in case.  And I didn’t know these other weird characteristics were going to arise.)

    [Okay, you’ve been warned. No more discussion of what specific ACEs mean or which ACL editors let you create ACEs in non-canonical order. If you want to continue it, go start your own blog. Today’s topic is why canonical ACE order puts deny ACEs ahead of allow ACEs. -Raymond]
  26. jon says:

    I wonder why you bother having comments enabled at all Raymond. Either it’s people asking the wrong question (“Don’t you dare ask me about this in the comments!”) or talking amongst themselves about the wrong thing (“Don’t you dare talk about this in the comments!”). Why not just turn comments off altogether? What’s the point of having them enabled when you have this sort of attitude?

    [Feel free to start your own blog called “Discussion of things Raymond considers off-topic or off the table.” -Raymond]
  27. rdamiani says:

    This seems like a really complicated way to handle permissions. The way they are described, they seem less like file attributes and more like mailbox rules with unintended effects that result from conditions the ‘standard’ tools are unable to detect, indicate, or correct. What does Windows gain from this complexity that a simpler system would not provide?

    [I’m not sure what you’re looking for. Which simpler system do you want to compare it to? Obviously it provides more expressive power than a simple system like FAT with a single “read-only” flag that anybody can change. -Raymond]
  28. Random Reader says:

    Another point is that this security system applies to many different kinds of objects within NT, not just files.  (Raymond never even mentioned files, it’s just what first came to mind for everyone.)  I would argue that a unified security model is a very important thing to have.

    Perhaps that’s why it’s complex, as there are so many different needs to address.

  29. @rdamiani:  Actually, this is just the tip of the iceberg!  We haven’t even touched on restricting SIDs, deny-only SIDs, the CREATOR OWNER ACE, the new OWNER RIGHTS and WRITE RESTRICTED SIDs, the TakeOwnership, Backup and Restore privileges, SD & ACE inheritance flags, integrity levels/labels, and more.  It is so complex that many of the best books on Windows security don’t get it 100% completely accurate, and some miss pretty badly.

    But:  it is very powerful, and very useful.  *Much* more so than -rwxr-xr-x.  And the basics are not that hard to grasp.

  30. Q-ologues says:

    Intricacies of the NT Filesystem

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index