{"id":95545,"date":"2017-02-23T07:00:00","date_gmt":"2017-02-23T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=95545"},"modified":"2019-03-13T01:06:54","modified_gmt":"2019-03-13T08:06:54","slug":"20170223-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170223-00\/?p=95545","title":{"rendered":"How to create a folder that inherits its parent&#8217;s ACL, and then overrides part of it"},"content":{"rendered":"<p>A customer wants to create a folder that inherits its parent&#8217;s ACL but then overrides part of it. Specifically, the customer wanted to disallow the creation of subfolders. The customer reported that when they used the <code>SH&shy;Create&shy;Directory<\/code> function to create the folder, the folder did not inherit any ACLs at all from its parent. The only thing it got was the &#8220;deny creation of subfolders&#8221; part. <\/p>\n<p>The customer provided this sample code to demonstrate what they were doing. <\/p>\n<pre>\nint main()\n{\n  PSECURITY_DESCRIPTOR pSD;\n  ULONG ulSDDL;\n  LPTSTR pszPath = L\"C:\\\\my\\\\test\\\\directory\";\n  LPTSTR pszDacl = L\"D:(D;;0x4;;;WD)\";\n\n  if (ConvertStringSecurityDescriptorToSecurityDescriptor(\n    pszDacl, SDDL_REVISION_1, &amp;pSD, &amp;ulSDDL))\n  {\n    wprintf(L\"Created security descriptor\\n\");\n    SECURITY_ATTRIBUTES sa;\n    sa.lpSecurityDescriptor = pSD;\n    sa.nLength = sizeof(sa);\n    sa.bInheritHandle = TRUE;\n    if (SUCCEEDED(SHCreateDirectoryEx(nullptr, pszPath, &amp;sa)))\n    {\n        wprintf(L\"Created folder %s\\n\", pszPath);\n    }\n  }\n  return 0;\n}\n<\/pre>\n<p>Notice the importance of <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20131018-00\/?p=2893\">reduction<\/a>, simplifying the problem to the smallest program that still demonstrates the issue. This boils the problem down to its essence, thereby allowing the development team to focus on the issue and not have to wade through (and possibly debug) unrelated code. Reduction is also a useful exercise on the part of the person reporting the problem, in order to verify that the problem really is what you think it is, rather than being a side effect of some other part of the program. <\/p>\n<p>The customer added, &#8220;The ACL we are using <code>D:(D;;0x4;;;WD)<\/code> denies folder creation to everyone. We tried adding flags like <code>P<\/code>, <code>AI<\/code>, <code>OICI<\/code>, <i>etc<\/i>., but none of them seem to work.&#8221; <\/p>\n<p>The shell takes the security descriptor passed to the <code>SH&shy;Create&shy;Directory&shy;Ex<\/code> function and passes it through to the <code>Create&shy;Directory<\/code> function, so any issues you have with the security descriptor are really issues with the <code>Create&shy;Directory<\/code> function. The shell is just the middle man. <\/p>\n<p>But even though this wasn&#8217;t really the expertise of the shell team, we were able to figure out the problem. <\/p>\n<p>First off, we have a red herring: The <code>bInherit&shy;Handle<\/code> member controls handle inheritance, not ACL inheritance. Setting it to <code>TRUE<\/code> causes the handle to be inherited by child processes. But that has no effect on the ACL. And since the <code>Create&shy;Directory<\/code> function doesn&#8217;t return a handle at all, fiddling with the <code>bInherit&shy;Handle<\/code> means nothing since there is no handle in the first place. It&#8217;s a double red herring. <\/p>\n<p>When you specify an explicit security descriptor to the <code>Create&shy;Directory<\/code> function, that establishes the security descriptor on the newly-created object. There is no inheritance from the parent. Inheritance rules are applied at creation only when you create the object with the default security attributes:&sup1; <\/p>\n<blockquote CLASS=\"q\"><p><a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa363855(v=vs.85).aspx\">If <i>lpSecurityAttributes<\/i> is <b>NULL<\/b><\/a>, the directory gets a default security descriptor. The ACLs in the default security descriptor for a directory are inherited from its parent directory. <\/p><\/blockquote>\n<p>Passing an explicit security descriptor overrides the default behvaior. <\/p>\n<p>If you want a blend of default behavior and custom behavior, then you have a few options available. <\/p>\n<p>One option is to read the security descriptor of the parent object and propagate the inheritable ACEs to the child in the appropriate manner. This is a complicated endeavor and probably is best left to the experts. It&#8217;s not a simple matter of copying them from the parent to the child. You also have to  to adapt the ACEs based on flags like &#8220;inherit only&#8221; and &#8220;container inherit&#8221;. <\/p>\n<p>The second option is to create the directory without an explicit security descriptor and let the experts create it with the default security descriptor, which takes into account all the inheritance rules. And then modify the security descriptor post-creation to include the new ACE you want. Fortunately, <a HREF=\"http:\/\/msdn.microsoft.com\/library\/aa379283(v=vs.85).aspx\">MSDN has sample code<\/a> for how to add an ACE to an existing security descriptor. <\/p>\n<p>The customer  reported that they adapted the code from MSDN and it worked perfectly. <\/p>\n<p>&sup1; Inheritance rules are also applied when you use functions like <a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa376326(v=vs.85).aspx\"><code>Set&shy;Named&shy;Security&shy;Info<\/code> and <code>Set&shy;Security&shy;Info<\/code><\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating it with a custom security descriptor isn&#8217;t working.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-95545","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Creating it with a custom security descriptor isn&#8217;t working.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95545","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=95545"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95545\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=95545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=95545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=95545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}