Vulnerability in EPiServer.Forms
I'm playing around and trying to restrict anonymous access to part of a site. I haven't done any changes from the out-of-box EPi configurations so I'm using Windows membership and role provider. If I then remove the "everyone" group from a node in the tree directly below my startpage to restrict access to that part of the site, suddenly I can't access my startpage neither as an anonymous user (I should add that the node where I remove the group is linked from the startpage in the top menu). However, if I remove the "everyone" group one level further down I can access the startpage without problem. Can anyone explain what I'm doing wrong?
Well, this depends on how the templates are coded. Somehow the start page triggers an access denied exception. Most API calls in CMS 5R2 and later ignore access control and leave it to the developer to check access. One exception is direct access to the page in question, when access control is enforced by the framework.
That the page is linked in the start menu isn't necessarily a problem. It is perfectly normal to have pages with restricted access in the menu, but the code to build the menu should (preferably in most situations) filter it's items by access. Still, even if it didn't, this should trigger an access dined only when the user clicks the menu item to load the page.
I suggest you look through/step through the code of your page and controls to find where the exception is triggered.
Thanks for your reply! I followed your advice and sure enough, deeply hidden in the code was a call to EPiServer.UserControlBase.GetPage() which threw the security exception. I found an article that explained that from CMS 5 R2 the DataFactory.GetPage() should no longer throw any AccessDeniedException. So I wonder why EPiServer.UserControlBase.GetPage() still throws it? Anyway, I changed the code to use DataFactory.GetPage() and now it works like a charm.
But this leads me to yet another question. Prior to CMS 5, how would you test access to a page? Im using PageData.ACL.QueryDistinctAccess() right now, but if you cannot get to the PageData object without getting the exception it feels a bit awkward. Did you have to catch that exception only to test access?
Glad I could help :)
In the earlier versions both DataFactory.GetPage and UserControlBase.GetPage (which calls PageBase.GetPage) checked access automatically. But at least DataFactory.GetPage had an overload to which you could pass a flag indicating which Access level you wanted it to check for. You could pass NoAccess to disable access control. I think that overload still remains but it's marked as obsolete because it ignores the AccessLevel parameter.
PageBase.GetPage still checks that the level set by PageBase.RequiredAccess() is met (defaults to Read but is virtual so it is possible to override, though I never encountered a case where I needed to enforce access rights that way).