Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

TIL: vCenter inherited permissions are not cumulative

Say you are part of two groups. Group A has full rights on the vCenter. Group B has limited rights on a cluster.

You would imagine that since you are a member of Group A and that has full rights on vCenter itself, your rights on the cluster in question won’t be limited. But nope, you are wrong. Since you are a member of Group B and that has limited rights on the cluster, your rights too are restricted. Bummer if you are a member of multiple groups and some of these groups have limited rights on child objects! :o)

Workaround is to add yourself or Group A explicitly on that cluster, with full rights. Then the permissions become cumulative.

Use SetACL if you want to overcome the 260 character limit when setting ACLs

I had to set folder & file permissions (basically, take ownership and enable inheritance) for a bunch of Windows folders the other day. Thing is the folders had levels and levels of sub-folders so Windows Explorer kept failing when applying permissions. I tried to use takeown and icacls via the command prompt but these too kept failing.

One workaround I had in mind was use subst or make junctions but these didn’t work either. When I mapped part of the folder name to a drive letter using subst the command line tools kept complaining that it wasn’t a file system that supported ACLs. Junctions didn’t do that well either. Mainly coz once you map part of a folder to a path/ drive letter, there’s no way to select the multiple sub-folders in there and assign permissions – when you select multiple folders, the security tab is missing.

Anyhoo, long story short, I came across this Server Fault thread from where I learnt the following –

In the Windows API, there is an infamous constant known as MAX_PATH. MAX_PATH is 260 characters. The NTFS file system actually supports file paths of up to 32,767 characters. And you can still use 32,767 character long path names by accessing the Unicode (or “wide”) versions of the Windows API functions, and also by prefixing the path with \\?\.

MAX_PATH was set in stone a very long time ago in the Windows world. I think it has something to do with ANSI standards at the time… but it’s one of those things that’s very difficult for Microsoft to change now, as now we have thousands of programs and applications, including some written by Microsoft themselves, that use MAX_PATH and would fail in strange new ways if the constant were suddenly changed. (Buffer overflows, heap corruption, etc.)

See this MSDN page too.

So what I needed was a tool that made use of the Unicode versions of the Windows API functions. A quick Google search bought me to SetACL – an amazing command-line tool that is able to set ACLs without the path limitations and that also has a nice syntax (I don’t know why, but icacls and even PowerShell has such obscure syntax for setting file ACLs). Check out this example page to get started. In my case all I really needed to do was run a command like this to (1) enable permissions inheritance and (2) set the ownership, and the command would do it recursively for all the files and folders in that path. Amazing!

The only gotcha I encountered was that I got the following error message after a while with the above command:

SetACL error message: The call to SetNamedSecurityInfo () failed Operating system error message: Access is denied.

Thankfully a forum post from the SetACL forums sorted that out for me. Trick is to do the take ownership first, and then the permission inheritance – apparently doing both together causes the above error.

So I did this first:

Followed by this:

SetACL is free but but command-line oriented. If you want a GUI version there’s SetACL Studio. That’s a paid product with a 30-day trial. I haven’t tried it yet. There is a SetACL t-shirt I might buy coz I was quite pleased with this tool yesterday. :)

Batch file to add BUILTIN\Administrators group to a folder of roaming profiles

Based on the idea I elaborated in my previous post

Latest version can be found on GitHub

I will explain the Batch file in detail later.

To view a file or folder owner use dir /q

Yup, you can’t use icacls or any of those tools to view who owns a file/ folder. Got to use the dir command with a /q switch. 

Can run it against a particular file/ folder too to get the permissions of just that. 

Weird! I mean, why not make this a part of the usual ACLs tools??

Beware of takeown and recursively operating

takeown is an in-built Windows tool that lets you take ownership of files and folders. Unlike other tools (e.g. icacls) which only let you give someone the right to take ownership of a file or folder, takeown seems to actually let you become the owner. And not just yourself, you can run it under a different context and that user account can be made the owner.

But it has a quirk which isn’t obvious until it turns around and bites you!

Here’s what I am using takeown for. I have a bunch of roaming profile folders that my admin account can’t view because only the user has full access to it. If I were using the GUI I would have opened the security tab of these folders, changed ownership to myself or the Administrators group, set that to propogate to all the child folders, and then add myself to the ACLs of this folder setting it to replace the ACLs of this folder and its children.

I have a large number of such folders, however, and I want to create a batch file to do this easily.

The obvious solution is to use takeown.

But this only sets the ownership of the parent folder. Not a problem, there’s a switch /R which tells takeown to recurse, so let’s try that:

Note that harmless question: do you want to replace the directory permissions with ones granting us full control? Harmless, because that’s what you would do via the GUI too. Gaining ownership of a folder doesn’t give you any permissions. That’s a separate step, so it seems like the command is only being helpful and offering to do this for you (so it can peek inside the sub-folders and give you ownership there too). And there-in lies the quirk which turned around and bit me. If you answer YES to this question (or use a switch /D Y to answer YES by default) it replaces the existing permissions with a new set. Yes, replace, not append as the GUI would have done. The net result of this is that once you run the takeown command as above only the Administrators group has any permissions, even the user loses their rights!

That’s definitely not what we want!

The right approach here seems to be to use a mix of takeown and icacls.

First use takeown to get ownership to the parent folder:

Then use icacls to recursively grant Full Control to the parent folder and sub-folders. Note that this only appends to the ACLs, it doesn’t replace. (This takes a few minutes and there’s plenty of output).

I don’t know why AppData failed above. It did for all the profiles I tested with and I didn’t investigate further. Could be an icacls limitation I suppose.

At this point the roaming profile is owned by Administrators, and the ACLs have an entry for the Administrators group in addition to the existing ACEs.

Now I run takeown again, recursively, but this time I target only the sub-folders (i.e. not the parent folder, only the ones below it).

takeown doesn’t have limitions like icacls. It’s ruthless! It will change ownership of all the sub-folders – including AppData – and replace the ACEs granting Administrators full access.

Now I run icacls on all the sub-folders, enabling inheritance on them. (This too takes a few minutes, but there’s no output except towards the end). The result of this step is that the botched ACEs set by takeown are fixed by icacls as it enables inheritance.

And that’s it. That’s how to properly use takeown and icacls to take ownership and reset permissions on a folder and its children.

Start Menu and other directory junctions access denied

Here’s a screenshot of my c:\Users\UserName folder. Notice the “Start Menu” folder:

users-folder

It is a directory junction to another folder, left behind for compatibility purposes. If I double click the folder though I get an access denied:

access-denied

 

The actual target to which this points is accessible, but the junction itself isn’t. Every time I encounter this I think I must make a note of “why” this is so, but I forget. Today I intend to note it down once and for all. 

Remember from an earlier post: there are hard links and there are soft links. The former points to the data itself, and so only work for files. The latter points to the folder/ file containing the data. Soft links are an evolution of directory junctions (there are directory junctions and volume junctions). While directory junctions make use of something called reparse points and were introduced in Windows 2000, soft links were introduced in Vista and are baked into the kernel itself. Microsoft uses directory junctions – as we saw above – to redirect some of its special folders.

The important thing with both directory junctions and soft links is that they can have their own ACLs. So while a user might have full permissions to the target folder, the directory junction or soft link itself may not grant the user permissions and so the contents cannot be accessed via the directory junction or soft link. That’s what happening here too. 

First, from the command prompt note that this is a junction and that I can enter the directory junction but cannot see any files:

The files exist, however, as I can directly browse the target:

Compare the ACLs of the target and directory junction and we see the problem:

(I could have used the Explorer GUI here but I prefer icacls. In the GUI we have to dig down a bit more to see the relevant ACEs).

Notice a DENY entry for Everyone on the directory junction for listing the contents (RD). That’s why I can’t list the junction contents (in Explorer double clicking results in trying to list the contents, while in Command Prompt entering a junction and listing are two separate tasks – that’s why entering the junction worked, but listing the contents failed). 

What the above tells us is that only listing the junction contents is prohibited. If we know the names of some folders in there – as older software for whom this directory junction is present would know – we can go to those locations using the directory junction. Thus the following works:

There you go!

Setting file ACLs via PowerShell

Yesterday I ran WireShark at work with my admin account and saved the results to a file. Later I moved that file (as my admin account) to the desktop of my regular account so I could email it to someone. But as you know moving has the effect that the original permissions are retained so even though the file was now in my regular Desktop I as a regular user couldn’t access it.

Running Explorer as an administrator doesn’t help either. Because of UAC when I right click Explorer and do “Run as administrator” it still runs as me but in an elevated context. This is an Explorer specific quirk. So unless I were to logout and login as my admin account, there seemed to be no way of changing the file ACLs to give my regular account permissions.

But of course there are ways. PowerShell was my first choice (coz I knew it had a Set-ACL cmdlet) but I wasn’t sure how to assign permissions using PowerShell. A quick web search got me to this blog post that summarizes what needs to be done. Up shot of the matter is you do something along these lines:

What you do here is that first you store the current ACLs of the file into a variable. Then you create a new ACE object with the permissions you want. Add that to the previous variable and assign the new ACL to the file.

While the above is useful, it would be good if I could just copy the ACLs from a file with ACEs I like to the file I want to modify. Something like this:

This doesn’t work though.

If I run this in a PowerShell session under my regular account it fails (obviously):

But if I run this under my admin account, then too it fails (though for not an obvious reason):

This is because by default Set-ACL also tries to set the owner ACE, and since the owner is different from the user account under which Set-ACL is running it gives an error. In Windows you can’t assign someone else as an owner unless you have a privilege for doing that (the SeRestorePrivilege privilege, see this MSDN page). All you can do is grant someone a Take Ownership permission and then they have to take ownership. (See this forum post for more info. Another forum post gives a workaround. Also, this blog post from Lee Holmes is useful in the context of the second forum post).

So a simple copy-paste is out of the question …

I still might be able to fix this easily though. Remember the reason the file (in my case) has a different set of permissions is because its ACEs are protected from inheritance. If I had copied the file over instead of moving, then permissions won’t be protected and inheritance would have kicked in. But since I moved the file here its permissions are protected. I can confirm this via Get-ACL too:

So all I need to do here is remove protection. That can be done via the SetAccessRuleProtection method. This takes two parameters – the first determines whether protection is enabled ($true) or not ($false). The second is ignored if protection is disabled; but if protection is enabled then it determines whether the inherited rules are kept ($true) or discarded ($false) . Thus, in my case, all I need to do is the following:

After this the file has both the original ACEs as well as the ones inherited from my home folder (notice the last three rules in the list below):

Now I can just copy the ACLs from another file – with PowerShell running under my account – as I had tried earlier. This is optional, I did it so the permissions are consistent with others.

While on Set-ACL the following snippet too might be useful:

This takes the ACLs from an existing file and adds these to the file I want. Again, this only works if you already have permissions on the file – in case above, I could do this after I have turned off protection.

While on PowerShell and ACLs its worth pointing to this Tip post. That’s where I first learnt about PowerShell and ACLs though I admit I have forgotten most of what I learnt from lack of use. This blog post which I came across today is a good read too. I came across it while searching for how to enable inheritance.

Apart from PowerShell there are other commands which can set/ get ACLs. One of these is ICACLS, which is present in Windows Vista/ Server 2003 SP2 and upwards.

Interestingly ICACLS seems to be able to set the owner to another account even though PowerShell fails. Not sure why that succeeds …

ICACLS can also easily reset the ACLs with inherited ones (i.e. like the PowerShell above it disables protection but also replaces the non-inherited entries with inherited ones).

This is a good post on using ICACLS. Apart from resetting and changing owners, you can also use ICACL to add/ remove ACEs, find files belonging to a particular user, and even substitute an ACE username/ SID with another. You can even save all ACEs of files in a folder and then restore them.

Lastly, if you are an administrator and want to take ownership of a file or directory, the takeown command is useful. It is not as useful as ICACLS which lets you assign someone else as the owner, but is useful if you are an admin and want take ownership.