I created this command because I was trying to debug an issue I was having. If you go through the central admin and remove a site permission for a web app (central admin > app management > user permissions for web applications) certain functionality that should work regardless of what setting you’ve removed no longer functions. For example – I removed “Apply Themes and Borders” for my intranet app:
I then went to site settings for one of my site collections and clicked the “Related Links Scope Settings” under Site Administration. The result is that I get an access denied error. The reason is that the code for this feature is checking whether the user's Effective Base Permissions match the FullMask permission:
“0x7fffffffffffffffL” corresponds to the SPEffectiveBasePermissions.FullMask permission. In my case my account is a site collection administrator and site owner so I should always have full control over the site but because I’ve denied the apply themes and borders permission the permissions that come back for my user are as follows:
C:\>stsadm -o gl-enumeffectivebaseperms -url "http://intranet/hr" ViewListItems, AddListItems, EditListItems, DeleteListItems, ApproveItems, OpenItems, ViewVersions, DeleteVersions, CancelCheckout, ManagePersonalViews, ManageLists, ViewFormPages, Open, ViewPages, AddAndCustomizePages, ApplyStyleSheets, ViewUsageData, CreateSSCSite, ManageSubwebs, CreateGroups, ManagePermissions, BrowseDirectories, BrowseUserInfo, AddDelPrivateWebParts, UpdatePersonalWebParts, ManageWeb, UseClientIntegration, UseRemoteAPIs, ManageAlerts, CreateAlerts, EditMyUserInfo, EnumeratePermissionsIf I invert to see what permissions I’m missing I get the following:
C:\>stsadm -o gl-enumeffectivebaseperms -url "http://intranet/hr" -invert ApplyThemeAndBorder, FullMask
The gl-enumeffectivebaseperms command is something I threw together to help debug this particular issue. If I go back to the central admin and add the apply themes and borders permission and run the commands above again then I’ll get back that my account now has everything but the FullMask associated with it and I still cannot get into the related links scope settings.
It seems like if I've got everything then the FullMask should kick in - unfortunately not. Fortunately I had another command in my toolkit which allowed me to solve the problem. I had long ago created the gl-enableuserpermissionforwebapp command - all I had to do was to run this command passing in the FullMask parameter:
C:\>stsadm -o gl-enableuserpermissionforwebapp -fullmask -url http://webapp
After running this I can now get into the pages. This is basically all the above command is doing:
1: SPWebApplication wa = SPWebApplication.Lookup(new Uri(url));
2: wa.RightsMask = wa.RightsMask | SPBasePermissions.FullMask;
3: wa.Update()
When reassigning the permissions via the browser it's not considering the case in which all items are selected and therefore the FullMask permission should be added back. There's no way to fix this via the browser but this custom command that I’d created some time ago does the trick.
This smells very much like a bug to me – the code should not be relying on that FullMask or the check should at least consider whether I have access to all permissions that are available and not whether I have all permissions. Because of this issue I'm unable to get into certain parts of the site collection administration without temporarily changing the user rights settings. The only other item I've come across is the site collection policies which has the same issue.
I'm not sure if there are others beyond these two - reflector won’t let me search for the 0x7ff…L string so I’m not sure of the scope of the problem. If anyone out there knows of something that I'm missing I'd love to hear it.
I'm not really sure how useful this command will be to others out there - I originally was just going to delete it once I was done with it but then changed my mind last minute - mainly because I know others must have bumped up against this same issue so hopefully this post, if not the command itself, will save someone some time.
The code is pretty simple - getting the permissions for the current user is real easy - just call the EffectiveBasePermissions property on an SPWeb object. To get the same for a user other than the one logged in is a bit more tricky. I had to use some reflection to call SPUtility.GetPermissions() method - it's the only method that I could find that would allow me to pass in a login (of course I had to call another internal method in order to get the SPUserToken object to pass into this method). If anyone knows of a simpler way, again, please let me know.
1: public override int Run(string command, StringDictionary keyValues, out string output)
2: {
3: output = string.Empty;
4:
5: InitParameters(keyValues);
6:
7: string url = Params["url"].Value;
8: if (url != null)
9: url = url.TrimEnd('/');
10:
11: SPBasePermissions perms;
12:
13: using (SPSite site = new SPSite(url))
14: using (SPWeb web = site.AllWebs[Utilities.GetServerRelUrlFromFullUrl(url)])
15: {
16: if (Params["user"].UserTypedIn)
17: {
18: PropertyInfo requestProp = web.GetType().GetProperty("Request",
19: BindingFlags.NonPublic |
20: BindingFlags.Instance |
21: BindingFlags.InvokeMethod |
22: BindingFlags.GetProperty);
23: object request = requestProp.GetValue(web, null);
24:
25: MethodInfo getUserToken =
26: request.GetType().GetMethod("GetUserToken",
27: BindingFlags.NonPublic | BindingFlags.Public |
28: BindingFlags.Instance | BindingFlags.InvokeMethod);
29:
30: try
31: {
32: SPUserToken token = new SPUserToken((byte[])getUserToken.Invoke(request, new object[] { web.Url, Params["user"].Value }));
33:
34: MethodInfo getPermissions =
35: typeof(SPUtility).GetMethod("GetPermissions",
36: BindingFlags.NonPublic |
37: BindingFlags.Public |
38: BindingFlags.Instance |
39: BindingFlags.InvokeMethod |
40: BindingFlags.Static);
41:
42: perms = (SPBasePermissions)getPermissions.Invoke(null, new object[] { token, web });
43: }
44: catch (TargetInvocationException ex)
45: {
46: throw ex.InnerException;
47: }
48: }
49: else
50: {
51: perms = web.EffectiveBasePermissions;
52: }
53: }
54:
55: if (!Params["invert"].UserTypedIn)
56: output += perms.ToString();
57: else
58: {
59: List<string> permsInverted = new List<string>();
60:
61: foreach (SPBasePermissions perm in Enum.GetValues(typeof(SPBasePermissions)))
62: {
63: if ((perms & perm) != perm)
64: {
65: permsInverted.Add(perm.ToString());
66: }
67: }
68: output += string.Join(", ", permsInverted.ToArray());
69: }
70: if (output == string.Empty)
71: {
72: output += "No permissions were found.";
73: }
74:
75: return 1;
76: }
C:\>stsadm -help gl-enumeffectivebaseperms
stsadm -o gl-enumeffectivebaseperms
Lists the effective base permissions for a user.
Parameters:
-url <web url>
[-user <DOMAIN\name>]
[-invert (shows what base permissions the user is missing)]
Here's an example of how to return the effective base permissions for the currently logged in user:
The results of running this command are shown above.stsadm –o gl-enumeffectivebaseperms -url "http://intranet/hr"



13 comments:
Very cool. Just linked to this from my recent post on permissions and roles. http://blogs.msdn.com/joelo
I've also given support a heads up.
Yep - we discovered that issue a few months back. It should be officially bugged in the PSS database
Yes - we ran into this same issue a couple months ago. It is offically bugged in the PSS database.
Great! I wait for the stsadm extension zip update :)
I fixed a minor bug which resulted in the display sometimes coming back as the numerical mask rather than the actual names of the permissions.
I've downloaded the stsadm extension zip but I haven't found this new command. Is it normal?
Sorry for not getting back to you sooner (had an issue where I wasn't getting any comments). Normally I try to post the code before adding the post but sometimes my script that does the upload fails for one reason or another and I don't always pay close enough attention to that. I usually detect the problem pretty quickly though so if it happens again just check back shortly and I'll have it up there. Sorry for the confusion.
I am having an issue accessing Related Links Scope and Site Collection Polices. I am using the Site Collection administration which also has full control account.
These links work fine in our other web application with client integration turned on. But this web application has client integration turned off.
When I run the -enumeffectivebaseperms on the web application I get Full Mask
When I use the -invert flag I get UseClientIntegration, FullMask
Any ideas how to resolve this?
Make sure you are running at least the August Cumulative Update - there's a fix in that update (best to install SP2 if you can).
Hi Gary,
I have downloaded and installed a new wss server hotfix from here :
http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=971538
and got a message "Ambigous match found." when i execute this command
It seems that the following part doesn't work anymore with this hotfix ...
MethodInfo getPermissions =
typeof(SPUtility).GetMethod("GetPermissions",
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.InvokeMethod |
BindingFlags.Static);
Do you have any idea to fix this ? Thanks
Unfortunately they've changed the signature of that method so my code is breaking. I'm not currently at a point where I can deploy the update myself to fix the issue but will try to get to it when I can.
Try
MethodInfo getPermissions =
typeof(SPUtility).GetMethod("GetPermissions",
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.InvokeMethod |
BindingFlags.Static,
null,
new Type[] {typeof(SPUserToken), typeof( ISecurableObject)},
null);
This happens because getPermissions() now has some overloads and you need to tell GetMethod which one you would like.
Came across this post when investigating option to disable permissions for Theme and Border in SP2010.
Looks like this is fixed in SP2010. (Probably earlier too).
Post a Comment