Posts
48
Comments
32
Trackbacks
0
Web Config Changes Security Issue
Hi all ,
 I recently was working with a client that implemented a telerik navigation control as a quicklaunch. They decided to split up all the sub-sites into their own site collection. They wanted to place quotas on subs sites, and if you don't know, you can only set quotas on site collections and not sub sites.
  This switch or splitting of sites posed some interesting problems.
       1) Telerik Control now needed to be added to each sub site for navigation. The control specifics were added to a master page. So this master page needed to be uploaded to the site collection (each one) and set as default master page.
       2) Because code is running on page, a web config entry needs to be added to allow the control to work on the master page. The entry looks like the following:

<PageParserPaths>
        <PageParserPath VirtualPath="/_catalogs/masterpage/customdefault.master" CompilationMode="Auto"                             
                        AllowServerSideScript="True" />
 </PageParserPaths>


Now the problem is not too bad except you have to do this for hundreds if not, over a thousdand sites. So I figured there was a way to upload the master page and set the default master page in code. What I was having issues with was writting the entry to web.config. I was pointed toward a blog post that outlined the entire feature that I needed to implement.

I was thinking great! it's all done for me, my client just wants me to re-write it, and test it properly and then i will send it their way! Well, I was half way there, I still needed to write to web config. I wrote the following code to write to web config. The 'owner' object is a string that is the complete url to the master page.

               SPWebConfigModification webConfig = new SPWebConfigModification("PageParserPath",
                                                                                "configuration/SharePoint/SafeMode/PageParserPaths");

                webConfig.Owner = string.Format("{0}{1}", siteCollection.ServerRelativeUrl,
                                                owner);
                webConfig.Sequence = 0;
                webConfig.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
                webConfig.Value = string.Format(
                    "<PageParserPath VirtualPath=\"{0}{1}\" CompilationMode=\"Auto\" AllowServerSideScript=\"True\" />",
                    siteCollection.ServerRelativeUrl, owner);

                siteCollection.WebApplication.WebConfigModifications.Add(webConfig);
                siteCollection.WebApplication.Farm.Servers.GetValue<SPWebService>().ApplyWebConfigModifications();
                siteCollection.WebApplication.Update();

This is all great except that, not just anyeone can edit the Web.Config. You need elevated permissions to do this. So I decided to run the code under elevated priveledges. But I got unexpected results.
 
 You can google around and find out all the issues with eleveated priveleges and how it impersonates the System account. It just turns out that this code worked fine in my test environment, but not in production. The only difference is my web applications run under the network service, and the production environment runs under a windows account. When debugging I had my instance of Visual Studio 2008 freeze on me and this is the error message that I got: 
         

A Zombie state!!! I had never ever heard of this!! I'm assuming that the proccess that I was attachedu to during debugging was stuck, I assume it was stuck trying to sort out credentials. In my test environment I would get weird prompts for credentails once in a while, and sometimes it did not work at all. In production environment, it simply did not work. These are the methods  in the feature.cs.

private void WriteToConfig(string owner)
        {
            using (SPSite siteCollection = SPContext.Current.Site)
            {
                SPWebConfigModification webConfig = new SPWebConfigModification("PageParserPath",
                                                                                "configuration/SharePoint/SafeMode/PageParserPaths");

                webConfig.Owner = string.Format("{0}{1}", siteCollection.ServerRelativeUrl,
                                                owner);
                webConfig.Sequence = 0;
                webConfig.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
                webConfig.Value = string.Format(
                    "<PageParserPath VirtualPath=\"{0}{1}\" CompilationMode=\"Auto\" AllowServerSideScript=\"True\" />",
                    siteCollection.ServerRelativeUrl, owner);

                siteCollection.WebApplication.WebConfigModifications.Add(webConfig);
                siteCollection.WebApplication.Farm.Servers.GetValue<SPWebService>().ApplyWebConfigModifications();
                siteCollection.WebApplication.Update();
            }
        }



        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {

            var newmaster = properties.Feature.Properties["MasterPage"].Value;
            if (!string.IsNullOrEmpty(newmaster))
            {
                using (var curSite = (SPSite)properties.Feature.Parent)
                {
                    using (var curWeb = curSite.OpenWeb())
                    {
                        curWeb.CustomMasterUrl = curWeb.MasterUrl.Replace(curWeb.MasterUrl, newmaster);
                        curWeb.MasterUrl = curWeb.CustomMasterUrl;
                        SPSecurity.RunWithElevatedPrivileges(this.WriteToConfig(curSite.ServerRelativeUrl+curWeb.MasterUrl));
                        curWeb.Update();
                    }
                }
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            var defmaster = properties.Feature.Properties["DefaultPage"].Value;
            using (var curSite = (SPSite)properties.Feature.Parent)
            {
                using (var curWeb = curSite.OpenWeb())
                {
                    curWeb.CustomMasterUrl = curWeb.MasterUrl.Replace(curWeb.MasterUrl, defmaster);
                    curWeb.MasterUrl = curWeb.CustomMasterUrl;
                    SPSecurity.RunWithElevatedPrivileges(this.DeleteWebConfig());
                    curWeb.Update();
                   
                }
            }
        }

        private void DeleteWebConfig()
        {
            using (SPSite siteCollection = SPContext.Current.Site)
            {
                Collection<SPWebConfigModification> collection = siteCollection.WebApplication.WebConfigModifications;
                string owner = string.Format("{0}{1}", siteCollection.ServerRelativeUrl,
                                             siteCollection.RootWeb.CustomMasterUrl);
                int iStartCount = collection.Count;

                for (int c = iStartCount - 1; c >= 0; c--)
                {
                    SPWebConfigModification configmod = collection[c];
                    if (configmod.Owner.Equals(owner))
                    {
                        collection.Remove(configmod);
                    }

                }

                siteCollection.WebApplication.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                siteCollection.WebApplication.Update();
            }
        }

I had run into problems with the elevated previledges and blogged about it. So I'm going to chalk this up under the same thread.

Another thing I tried was making sure the windows accounts associated with the web application had the right permissions but it still did not work.

I ended up removing the control and editing the quicklauch navigation and allow for accordian style type navigation with some hover over color changes. I tried to re-create all the features that the control added. My next post will describe what and how I edited to re-create the navigation. It involved, CSS changes, Master Page changes, QuickLaunch navigation control changes, and JQuery!!!  Stay tuned.

If anyone figures this out or can shed some light please let me know.

Good luck

Juan Larios
posted on Tuesday, July 14, 2009 9:32 PM Print
Comments
Gravatar
# re: Web Config Changes Security Issue
k.thomys
10/6/2009 4:56 AM
HI

You got this error because the app-pool user has no rights on the web.config file to modify it. Either you give the rights to the user or U take the app-pool user to the admin-group of your AD (local). Be aware of the security.

Best Regards

k.thomys
Gravatar
#  re: Web Config Changes Security Issue
Juan Larios
10/6/2009 9:05 AM
I agree with you , the problem was that I added the app pool user to admin-group in ad. The only thing I did not do was give, the app pool account rights to the web.config file. I assumed that adding them to admin group would do the trick, since the admin group has full access to everything on the machine. I understand the security risk of that but it was a test environment and just wanted to see if that was the issue.

Post Comment

Title *
Name *
Email
Comment *  
 
Tag Cloud