Anonymous access in SQL RS 2008


So what happened to the good old anonymous authentication is RS 2005? The short answer is that it is no longer supported. There were good technical reasons: anonymous accounts (the IUSER_* and IWAM_* accounts) are managed by windows security system. We decided not to trot into that space, nor did we want to add a new configuration setting for anonymous accounts, and having to manage the username and password of the anonymous user account. This may seem like a flop, but think about it from another angle: why would you want everyone on the internet to be able to view/update/overwrite your stuff on the report server?


With so little said about best practices, I shouldn’t really be telling people how to enable anonymous authentication. So here is the disclaimer again:


DO NOT USE ANONYMOUS AUTH!


NEVER USE IT IN PRODUCTION ENVIRONMENT!


But if you are still undeterred, thinking you have a super secure environment and your servers are never exposed to malicious users, here is the solution for the reckless :). This is an adaptation of the RS Forms auth sample, so the easiest thing to do is to replace code in the sample with the code at the bottom of this blog post.


·         Change authentication mode in rereportserver.config to “Custom”:


                <Authentication>


                                <AuthenticationTypes>


                                                <Custom/>


                                </AuthenticationTypes>


                                <EnableAuthPersistence>true</EnableAuthPersistence>


                </Authentication>


·         Change auth mode in report server and report manager web.config file to “None”. Set impersonation property to “false”:


    <authentication mode=”None” />


    <identity impersonate=”false”/>


·         Compile the code below into Microsoft.Samples.ReportingServices.AnonymousSecurity.dll .


·         Drop Microsoft.Samples.ReportingServices.AnonymousSecurity.dll into report server bin folder (e.g. D:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\ReportServer\bin)


·         Add the extension to rereportserver.config file:


                                <Security>


                                                <Extension Name=”None” Type=”Microsoft.Samples.ReportingServices.AnonymousSecurity.Authorization, Microsoft.Samples.ReportingServices.AnonymousSecurity” />


                                </Security>


                                <Authentication>


                                                <Extension Name=”None” Type=”Microsoft.Samples.ReportingServices.AnonymousSecurity.AuthenticationExtension, Microsoft.Samples.ReportingServices.AnonymousSecurity” />


                                </Authentication>


·         Configure code access security. Add the following into rssrvpolicy.config. Since my project had no strong name, I used url membership:


                            <CodeGroup


                                    class=”UnionCodeGroup”


                                    version=”1″


                                    PermissionSetName=”FullTrust”


                                    Name=”Private_assembly”


                                    Description=”This code group grants custom code full trust. “>


                                <IMembershipCondition


                                        class=”UrlMembershipCondition”


                                        version=”1″


                                        Url=”D:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\ReportServer\bin\Microsoft.Samples.ReportingServices.AnonymousSecurity.dll”


                                />


                            </CodeGroup>


·         Restart report server and now you have anonymous authentication.


 


Code:


 


namespace Microsoft.Samples.ReportingServices.AnonymousSecurity


{


    public class AuthenticationExtension : IAuthenticationExtension


    {


        /// <summary>


        /// You must implement SetConfiguration as required by IExtension


        /// </summary>


        /// <param name=”configuration”>Configuration data as an XML


        /// string that is stored along with the Extension element in


        /// the configuration file.</param>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public void SetConfiguration(String configuration)


        {


            // No configuration data is needed for this extension


        }


 


        /// <summary>


        /// You must implement LocalizedName as required by IExtension


        /// </summary>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public string LocalizedName


        {


            get


            {


                return null;


            }


        }


 


        /// <summary>


        /// Indicates whether a supplied username and password are valid.


        /// </summary>


        /// <param name=”userName”>The supplied username</param>


        /// <param name=”password”>The supplied password</param>


        /// <param name=”authority”>Optional. The specific authority to use to


        /// authenticate a user. For example, in Windows it would be a Windows


        /// Domain</param>


        /// <returns>true when the username and password are valid</returns>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public bool LogonUser(string userName, string password, string authority)


        {


            return true;


        }


 


        /// <summary>


        /// Required by IAuthenticationExtension. The report server calls the


        /// GetUserInfo methodfor each request to retrieve the current user


        /// identity.


        /// </summary>


        /// <param name=”userIdentity”>represents the identity of the current


        /// user. The value of IIdentity may appear in a user interface and


        /// should be human readable</param>


        /// <param name=”userId”>represents a pointer to a unique user identity


        /// </param>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)


        {


            userIdentity = new GenericIdentity(“dummy user”);


            userId = IntPtr.Zero;


        }


 


        /// <summary>


        /// The IsValidPrincipalName method is called by the report server when


        /// the report server sets security on an item. This method validates


        /// that the user name is valid for Windows.The principal name needs to


        /// be a user, group, or builtin account name.


        /// </summary>


        /// <param name=”principalName”>A user, group, or built-in account name


        /// </param>


        /// <returns>true when the principle name is valid</returns>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public bool IsValidPrincipalName(string principalName)


        {


            return true;


        }


    }


}


 


namespace Microsoft.Samples.ReportingServices.AnonymousSecurity


{


    public class Authorization : IAuthorizationExtension


    {


        static Authorization()


        {


            InitializeMaps();


        }


 


        /// <summary>


        /// Returns a security descriptor that is stored with an individual


        /// item in the report server database.


        /// </summary>


        /// <param name=”acl”>The access code list (ACL) created by the report


        /// server for the item. It contains a collection of access code entry


        /// (ACE) structures.</param>


        /// <param name=”itemType”>The type of item for which the security


        /// descriptor is created.</param>


        /// <param name=”stringSecDesc”>Optional. A user-friendly description


        /// of the security descriptor, used for debugging. This is not stored


        /// by the report server.</param>


        /// <returns>Should be implemented to return a serialized access code


        /// list for the item.</returns>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public byte[] CreateSecurityDescriptor(


            AceCollection acl,


            SecurityItemType itemType,


            out string stringSecDesc)


        {


            stringSecDesc = null;


            return null;


        }


 


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            ModelItemOperation modelItemOperation)


        {


            return true;


        }


 


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            ModelOperation modelOperation)


        {


            return true;


        }


 


        /// <summary>


        /// Indicates whether a given user is authorized to access the item


        /// for a given catalog operation.


        /// </summary>


        /// <param name=”userName”>The name of the user as returned by the


        /// GetUserInfo method.</param>


        /// <param name=”userToken”>Pointer to the user ID returned by


        /// GetUserInfo.</param>


        /// <param name=”secDesc”>The security descriptor returned by


        /// CreateSecurityDescriptor.</param>


        /// <param name=”requiredOperation”>The operation being requested by


        /// the report server for a given user.</param>


        /// <returns>True if the user is authorized.</returns>


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            CatalogOperation requiredOperation)


        {


            return true;


        }


 


        // Overload for array of catalog operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            CatalogOperation[] requiredOperations)


        {


            return true;


        }


 


        // Overload for Report operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            ReportOperation requiredOperation)


        {


            return true;


        }


 


        // Overload for Folder operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            FolderOperation requiredOperation)


        {


            return true;


        }


 


        // Overload for an array of Folder operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            FolderOperation[] requiredOperations)


        {


            return true;


        }


 


        // Overload for Resource operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            ResourceOperation requiredOperation)


        {


            return true;


        }


 


        // Overload for an array of Resource operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            ResourceOperation[] requiredOperations)


        {


            return true;


        }


 


        // Overload for Datasource operations


        public bool CheckAccess(


            string userName,


            IntPtr userToken,


            byte[] secDesc,


            DatasourceOperation requiredOperation)


        {


            return true;


        }


 


        /// <summary>


        /// Returns the set of permissions a specific user has for a specific


        /// item managed in the report server database. This provides underlying


        /// support for the Web service method GetPermissions().


        /// </summary>


        /// <param name=”userName”>The name of the user as returned by the


        /// GetUserInfo method.</param>


        /// <param name=”userToken”>Pointer to the user ID returned by


        /// GetUserInfo.</param>


        /// <param name=”itemType”>The type of item for which the permissions


        /// are returned.</param>


        /// <param name=”secDesc”>The security descriptor associated with the


        /// item.</param>


        /// <returns></returns>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Maintainability”, “CA1502:AvoidExcessiveComplexity”)]


        public StringCollection GetPermissions(string userName, IntPtr userToken,


         SecurityItemType itemType, byte[] secDesc)


        {


            return m_fullPermissions;


        }


 


        private static Hashtable m_ModelItemOperNames;


        private static Hashtable m_ModelOperNames;


        private static Hashtable m_CatOperNames;


        private static Hashtable m_FldOperNames;


        private static Hashtable m_RptOperNames;


        private static Hashtable m_ResOperNames;


        private static Hashtable m_DSOperNames;


        private static StringCollection m_fullPermissions = new StringCollection();


 


        private const int NrRptOperations = 27;


        private const int NrFldOperations = 10;


        private const int NrResOperations = 7;


        private const int NrDSOperations = 7;


        private const int NrCatOperations = 16;


        private const int NrModelOperations = 11;


        private const int NrModelItemOperations = 1;


 


        // Utility method used to create mappings to the various


        // operations in Reporting Services. These mappings support


        // the implementation of the GetPermissions method.


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”)]


        private static void InitializeMaps()


        {


            // create model operation names data


            m_ModelItemOperNames = new Hashtable();


            m_ModelItemOperNames.Add(ModelItemOperation.ReadProperties,


               OperationNames.OperReadProperties);


 


            if (m_ModelItemOperNames.Count != NrModelItemOperations)


            {


                //Model item name mismatch


                throw new Exception(“Model item name mismatch”);


            }


 


            // create model operation names data


            m_ModelOperNames = new Hashtable();


            m_ModelOperNames.Add(ModelOperation.Delete,


               OperationNames.OperDelete);


            m_ModelOperNames.Add(ModelOperation.ReadAuthorizationPolicy,


              OperationNames.OperReadAuthorizationPolicy);


            m_ModelOperNames.Add(ModelOperation.ReadContent,


              OperationNames.OperReadContent);


            m_ModelOperNames.Add(ModelOperation.ReadDatasource,


              OperationNames.OperReadDatasources);


            m_ModelOperNames.Add(ModelOperation.ReadModelItemAuthorizationPolicies,


              OperationNames.OperReadModelItemSecurityPolicies);


            m_ModelOperNames.Add(ModelOperation.ReadProperties,


              OperationNames.OperReadProperties);


            m_ModelOperNames.Add(ModelOperation.UpdateContent,


              OperationNames.OperUpdateContent);


            m_ModelOperNames.Add(ModelOperation.UpdateDatasource,


              OperationNames.OperUpdateDatasources);


            m_ModelOperNames.Add(ModelOperation.UpdateDeleteAuthorizationPolicy,


              OperationNames.OperUpdateDeleteAuthorizationPolicy);


            m_ModelOperNames.Add(ModelOperation.UpdateModelItemAuthorizationPolicies,


              OperationNames.OperUpdateModelItemSecurityPolicies);


            m_ModelOperNames.Add(ModelOperation.UpdateProperties,


              OperationNames.OperUpdatePolicy);


 


            if (m_ModelOperNames.Count != NrModelOperations)


            {


                //Model name mismatch


                throw new Exception(“Model name mismatch”);


            }


 


            // create operation names data


            m_CatOperNames = new Hashtable();


            m_CatOperNames.Add(CatalogOperation.CreateRoles,


               OperationNames.OperCreateRoles);


            m_CatOperNames.Add(CatalogOperation.DeleteRoles,


               OperationNames.OperDeleteRoles);


            m_CatOperNames.Add(CatalogOperation.ReadRoleProperties,


               OperationNames.OperReadRoleProperties);


            m_CatOperNames.Add(CatalogOperation.UpdateRoleProperties,


               OperationNames.OperUpdateRoleProperties);


            m_CatOperNames.Add(CatalogOperation.ReadSystemProperties,


               OperationNames.OperReadSystemProperties);


            m_CatOperNames.Add(CatalogOperation.UpdateSystemProperties,


               OperationNames.OperUpdateSystemProperties);


            m_CatOperNames.Add(CatalogOperation.GenerateEvents,


               OperationNames.OperGenerateEvents);


            m_CatOperNames.Add(CatalogOperation.ReadSystemSecurityPolicy,


               OperationNames.OperReadSystemSecurityPolicy);


            m_CatOperNames.Add(CatalogOperation.UpdateSystemSecurityPolicy,


               OperationNames.OperUpdateSystemSecurityPolicy);


            m_CatOperNames.Add(CatalogOperation.CreateSchedules,


               OperationNames.OperCreateSchedules);


            m_CatOperNames.Add(CatalogOperation.DeleteSchedules,


               OperationNames.OperDeleteSchedules);


            m_CatOperNames.Add(CatalogOperation.ReadSchedules,


               OperationNames.OperReadSchedules);


            m_CatOperNames.Add(CatalogOperation.UpdateSchedules,


               OperationNames.OperUpdateSchedules);


            m_CatOperNames.Add(CatalogOperation.ListJobs,


               OperationNames.OperListJobs);


            m_CatOperNames.Add(CatalogOperation.CancelJobs,


               OperationNames.OperCancelJobs);


            m_CatOperNames.Add(CatalogOperation.ExecuteReportDefinition,


             OperationNames.ExecuteReportDefinition);


            if (m_CatOperNames.Count != NrCatOperations)


            {


                //Catalog name mismatch


                throw new Exception(“Catalog name mismatch”);


            }


 


            m_FldOperNames = new Hashtable();


            m_FldOperNames.Add(FolderOperation.CreateFolder,


               OperationNames.OperCreateFolder);


            m_FldOperNames.Add(FolderOperation.Delete,


               OperationNames.OperDelete);


            m_FldOperNames.Add(FolderOperation.ReadProperties,


               OperationNames.OperReadProperties);


            m_FldOperNames.Add(FolderOperation.UpdateProperties,


               OperationNames.OperUpdateProperties);


            m_FldOperNames.Add(FolderOperation.CreateReport,


               OperationNames.OperCreateReport);


            m_FldOperNames.Add(FolderOperation.CreateResource,


               OperationNames.OperCreateResource);


            m_FldOperNames.Add(FolderOperation.ReadAuthorizationPolicy,


               OperationNames.OperReadAuthorizationPolicy);


            m_FldOperNames.Add(FolderOperation.UpdateDeleteAuthorizationPolicy,


               OperationNames.OperUpdateDeleteAuthorizationPolicy);


            m_FldOperNames.Add(FolderOperation.CreateDatasource,


               OperationNames.OperCreateDatasource);


            m_FldOperNames.Add(FolderOperation.CreateModel,


               OperationNames.OperCreateModel);


            if (m_FldOperNames.Count != NrFldOperations)


            {


                //Folder name mismatch


                throw new Exception(“Folder name mismatch”);


            }


 


            m_RptOperNames = new Hashtable();


            m_RptOperNames.Add(ReportOperation.Delete,


               OperationNames.OperDelete);


            m_RptOperNames.Add(ReportOperation.ReadProperties,


               OperationNames.OperReadProperties);


            m_RptOperNames.Add(ReportOperation.UpdateProperties,


               OperationNames.OperUpdateProperties);


            m_RptOperNames.Add(ReportOperation.UpdateParameters,


               OperationNames.OperUpdateParameters);


            m_RptOperNames.Add(ReportOperation.ReadDatasource,


               OperationNames.OperReadDatasources);


            m_RptOperNames.Add(ReportOperation.UpdateDatasource,


               OperationNames.OperUpdateDatasources);


            m_RptOperNames.Add(ReportOperation.ReadReportDefinition,


               OperationNames.OperReadReportDefinition);


            m_RptOperNames.Add(ReportOperation.UpdateReportDefinition,


               OperationNames.OperUpdateReportDefinition);


            m_RptOperNames.Add(ReportOperation.CreateSubscription,


               OperationNames.OperCreateSubscription);


            m_RptOperNames.Add(ReportOperation.DeleteSubscription,


               OperationNames.OperDeleteSubscription);


            m_RptOperNames.Add(ReportOperation.ReadSubscription,


               OperationNames.OperReadSubscription);


            m_RptOperNames.Add(ReportOperation.UpdateSubscription,


               OperationNames.OperUpdateSubscription);


            m_RptOperNames.Add(ReportOperation.CreateAnySubscription,


               OperationNames.OperCreateAnySubscription);


            m_RptOperNames.Add(ReportOperation.DeleteAnySubscription,


               OperationNames.OperDeleteAnySubscription);


            m_RptOperNames.Add(ReportOperation.ReadAnySubscription,


               OperationNames.OperReadAnySubscription);


            m_RptOperNames.Add(ReportOperation.UpdateAnySubscription,


               OperationNames.OperUpdateAnySubscription);


            m_RptOperNames.Add(ReportOperation.UpdatePolicy,


               OperationNames.OperUpdatePolicy);


            m_RptOperNames.Add(ReportOperation.ReadPolicy,


               OperationNames.OperReadPolicy);


            m_RptOperNames.Add(ReportOperation.DeleteHistory,


               OperationNames.OperDeleteHistory);


            m_RptOperNames.Add(ReportOperation.ListHistory,


               OperationNames.OperListHistory);


            m_RptOperNames.Add(ReportOperation.ExecuteAndView,


               OperationNames.OperExecuteAndView);


            m_RptOperNames.Add(ReportOperation.CreateResource,


               OperationNames.OperCreateResource);


            m_RptOperNames.Add(ReportOperation.CreateSnapshot,


               OperationNames.OperCreateSnapshot);


            m_RptOperNames.Add(ReportOperation.ReadAuthorizationPolicy,


               OperationNames.OperReadAuthorizationPolicy);


            m_RptOperNames.Add(ReportOperation.UpdateDeleteAuthorizationPolicy,


               OperationNames.OperUpdateDeleteAuthorizationPolicy);


            m_RptOperNames.Add(ReportOperation.Execute,


               OperationNames.OperExecute);


            m_RptOperNames.Add(ReportOperation.CreateLink,


               OperationNames.OperCreateLink);


 


            if (m_RptOperNames.Count != NrRptOperations)


            {


                //Report name mismatch


                throw new Exception(“Report name mismatch”);


            }


 


            m_ResOperNames = new Hashtable();


            m_ResOperNames.Add(ResourceOperation.Delete,


               OperationNames.OperDelete);


            m_ResOperNames.Add(ResourceOperation.ReadProperties,


               OperationNames.OperReadProperties);


            m_ResOperNames.Add(ResourceOperation.UpdateProperties,


               OperationNames.OperUpdateProperties);


            m_ResOperNames.Add(ResourceOperation.ReadContent,


               OperationNames.OperReadContent);


            m_ResOperNames.Add(ResourceOperation.UpdateContent,


               OperationNames.OperUpdateContent);


            m_ResOperNames.Add(ResourceOperation.ReadAuthorizationPolicy,


               OperationNames.OperReadAuthorizationPolicy);


            m_ResOperNames.Add(ResourceOperation.UpdateDeleteAuthorizationPolicy,


               OperationNames.OperUpdateDeleteAuthorizationPolicy);


 


            if (m_ResOperNames.Count != NrResOperations)


            {


                //Resource name mismatch


                throw new Exception(“Resource name mismatch”);


            }


 


            m_DSOperNames = new Hashtable();


            m_DSOperNames.Add(DatasourceOperation.Delete,


               OperationNames.OperDelete);


            m_DSOperNames.Add(DatasourceOperation.ReadProperties,


               OperationNames.OperReadProperties);


            m_DSOperNames.Add(DatasourceOperation.UpdateProperties,


               OperationNames.OperUpdateProperties);


            m_DSOperNames.Add(DatasourceOperation.ReadContent,


               OperationNames.OperReadContent);


            m_DSOperNames.Add(DatasourceOperation.UpdateContent,


               OperationNames.OperUpdateContent);


            m_DSOperNames.Add(DatasourceOperation.ReadAuthorizationPolicy,


               OperationNames.OperReadAuthorizationPolicy);


            m_DSOperNames.Add(DatasourceOperation.UpdateDeleteAuthorizationPolicy,


               OperationNames.OperUpdateDeleteAuthorizationPolicy);


 


            if (m_DSOperNames.Count != NrDSOperations)


            {


                //Datasource name mismatch


                throw new Exception(“Datasource name mismatch”);


            }


 


            // Initialize permission collection.


            foreach (CatalogOperation oper in m_CatOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_CatOperNames[oper]))


                    m_fullPermissions.Add((string)m_CatOperNames[oper]);


            }


            foreach (ModelItemOperation oper in m_ModelItemOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_ModelItemOperNames[oper]))


                    m_fullPermissions.Add((string)m_ModelItemOperNames[oper]);


            }


            foreach (ModelOperation oper in m_ModelOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_ModelOperNames[oper]))


                    m_fullPermissions.Add((string)m_ModelOperNames[oper]);


            }


            foreach (CatalogOperation oper in m_CatOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_CatOperNames[oper]))


                    m_fullPermissions.Add((string)m_CatOperNames[oper]);


            }


            foreach (ReportOperation oper in m_RptOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_RptOperNames[oper]))


                    m_fullPermissions.Add((string)m_RptOperNames[oper]);


            }


            foreach (FolderOperation oper in m_FldOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_FldOperNames[oper]))


                    m_fullPermissions.Add((string)m_FldOperNames[oper]);


            }


            foreach (ResourceOperation oper in m_ResOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_ResOperNames[oper]))


                    m_fullPermissions.Add((string)m_ResOperNames[oper]);


            }


            foreach (DatasourceOperation oper in m_DSOperNames.Keys)


            {


                if (!m_fullPermissions.Contains((string)m_DSOperNames[oper]))


                    m_fullPermissions.Add((string)m_DSOperNames[oper]);


            }


        }


 


        /// <summary>


        /// You must implement SetConfiguration as required by IExtension


        /// </summary>


        /// <param name=”configuration”>Configuration data as an XML


        /// string that is stored along with the Extension element in


        /// the configuration file.</param>


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”), System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA2201:DoNotRaiseReservedExceptionTypes”)]


        public void SetConfiguration(string configuration)


        {


        }


 


        [System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Security”, “CA2123:OverrideLinkDemandsShouldBeIdenticalToBase”)]


        public string LocalizedName


        {


            get


            {


                // Return a localized name for this extension


                return null;


            }


        }


    }


}


 

Comments (73)

  1. I read somewhere that Report Builder requires anonymous access if configured for external (extranet) deployments… has this changed in SQL 2008?

  2. frzJalali says:

    Excellent !!!

    I just have a question ( which may save my life today !!! )

    I see for every XML change you mentionaed the file name such as rereportserver.config

    But You didn’t mention for C# code.

    so I have two question:

    May I ask you please in which file and which location I have to type the C# Code?

    Should I compile it ? if yes, where should I put DLL file?

    Thanks a lot,

    frz

  3. jameswu says:

    Hi kskistab,

    Sorry for the late reply. Report Builder is a click-once application, and can only handle windows authentication. If your server is configured to use Basic auth, Report Builder needs to be anonymous auth. This hasn’t changed in 2008, although it is configured in a different way via IsReportBuilderAnonymousAccessEnabled property: http://msdn.microsoft.com/en-us/library/cc281309.aspx.

  4. jameswu says:

    Hi frz,

    Sorry for the late reply. I should have checked for comments more frequently :P. You need to compile the C# code. See these instructions I posted in the blog:

    ·         Compile the code below into Microsoft.Samples.ReportingServices.AnonymousSecurity.dll .

    ·         Drop Microsoft.Samples.ReportingServices.AnonymousSecurity.dll into report server bin folder (e.g. D:Program FilesMicrosoft SQL ServerMSRS10.MSSQLSERVERReporting ServicesReportServerbin)

  5. bpatin@magloclen.riss.net says:

    I discovered on another blog that one must enable "Modify" access for the Reporting Services Server Account to "C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files".

    That worked.

    Now, I also have anonymous access to Report Manager, which is too much,

    and I need to go over the custom code and discover how to tighten up the security.

  6. danmason says:

    Hi James, I am having trouble compiling the code (having not compiled a dll before). I pasted your code into Visual C# but when I try to Build I get a string of error messages such as:

    " The type or namespace name ‘IAuthenticationExtension’ could not be found (are you missing a using directive or an assembly reference?) "

    Should I be adding something at the top of the code perhaps?

    Thanks, Dan

  7. bpatin@magloclen.riss.net says:

    I discovered that both the Report Services Server account and the Execution account need "Modify" permission for two directories: "C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files". and "C:Program FilesMicrosoft SQL ServerMSRS10.MSSQLSERVERReporting ServicesRSTempFiles" in order to work reliably.  This sort of thing needs to be documented.

  8. bpatin@magloclen.riss.net says:

    I am trying to get custom authentication to work, because the default is simply not applicable to our environment, and have tried two ways, but am stopped by errors out of my control:

    1. I got the Anonymous authentication in this blog to work, and have been trying to use that as a starting point and tighten security, but, whenever I try to get the user identity in the function GetUserInfo in AuthenticationExtension.cs, using the following code:

               if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.User.Identity != null)

               {

                   userIdentity = System.Web.HttpContext.Current.User.Identity;

               }

    I get error:

    "Client found response content type of ‘text/html; charset=utf-8’, but expected ‘text/xml’. "

    2. I downloaded the latest Forms authentication sample for 2008 from MSDN, and converted it successfully to Visual Studio 2008 (instructions said it was only compatible with VS 2005, but that is not a reasonable requirement, since I am working on Windows 2008 with Visual Studio 2008 and SQL Server 2008, and am expected to get a license for an old VS 2005?), compiled and followed instructions (which need some editing work) to configure Reporting Services for it.  I get the logon page when invoking /Reports, but when I enter a username and password and click Logon, I get the error message: "An error occurred while attempting to get the ReportServer Url. Invalid namespace".  Taking a tip from some related blogs about this error, I changed the reportingservices.mof file, removing the "RS_" prefix from the instance name wherever namespace was mentioned, but still get the same error.

    I’ve contacted Microsoft Support, but am still playing phone tag with first-level support, who I am sure wouldn’t be able to help, anyway.  I am hoping this blog provides a short-circuit to the developers who can actually fix the code and provide working up-to-date samples.

  9. jcnovoa says:

    I was able to mimic anonymous access via the application pool security credentials and report viewer inside my application. Here are the steps:

    I create a new user in my Windows 2008 server. (i.e. ReportingServices)

    Created a classic application pool, and assigned the identity execution to my new ReportingServices account in the server

    Associated the ReportingServices credential to a browser role inside the report server (http://localhost/Reports) for the report being rendered inside my asp.net application using the report viewer. (Folders above reports are still locked, so no browsing allowed)

    Disabled prompting for report parameters and desabled default values for paramters (can’t render report from portal now)

    Set default parameter values via the parameter array of my report viewer.

    Associated ASP.Net application to application pool being ran by my ReportingSevices credentials

    Successfully impersonated user in reporting services hence implementing quasi anonymous access.

    Hope this helps someone.

  10. prometei82 says:

    I get a ready compiled file of this code and after give access to folders it worked.Thanks

    What I have to change in code to change access to new custom access to be only browser?

  11. prometei82 says:

    In order to can compile code you have to add references:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using Microsoft.ReportingServices.Interfaces;

    using System.Security.Principal;

    using System.Collections.Specialized;

    using System.Collections;

    Also get Microsoft.ReportingServices.Interfaces.dll to you project.

  12. JoGu says:

    I have the same question as prometei82:

    I get anonym access. What I have to change in code to change access to new custom access to be only browser?

  13. hardewsingh says:

    I tried the above approach – creating dll and changing the config files etc. However, it is not working.

    Here Reporting Service is running in the SharePointIntegratedMode. Both SharePoint Server and Reporting Service are running under same domain but in different servers. This setup is working fine.

    I have also tried by enabling anonymous access for SharePoint site from “Central Administration -> Application Management -> Authentication Providers -> Edit Authentication -> "Enable anonymous access" but no luck.

    Is there any different way/workaround to configure anonymous access?

    Thanks in advance.

  14. Dong Li says:

    Hi James,

    I tried all the steps, but i got "HTTP Error 503. The service is unavailable" error after I restart SQL Server Reporting Services (MSSQLSERVER), do you have any idea for this? Thanks!.

  15. Dong Li says:

    BTW, I am using SQL server 2008 R2 instead of 2008

  16. Hi James,

    I tried your solution on a SQL Server 2008 deployment and it works like a charm! Things fall apart on SQL SSRS R2… I get the same 503 issue as Dong. Any suggestions?

    Pieter

  17. Erin says:

    Where can I find the sample code files that I need to modify with the above code?

  18. Ron Mohamed says:

    Hey,

      Can you please post the SSRS 2008 R2 anonymous config in a blog post? Our company cannot upgrade from 2008 to 2008 R2 until we have this working. If I can't get it working soon, we will be looking at Business Opjects for reporting. I don't know why microsoft doesn't give the customer a choice. Put all the DISCLAIMERS you want, the fact remains that customers are looking for anonymous access. Thanks.

  19. Erik says:

    Got it working for SSRS 2008!  Thanks for the help!  For those of you not sure of how to build the .dll, just download the MS Visual C# Express Edition.  Create a class library project named Microsoft.Samples.ReportingServices.AnonymousSecurity.  Copy the code above into the class1.cs file.  Add the reference in the project  to ReportingServices.Interfaces.  Once you do that, just build the project and the dll will be in the …binrelease directory of the project.

  20. jameswu says:

    This will not work for sharepoint integrated mode. This is something that we wanted to support, but is unable to get to.

    I am currently working on a sample for 2008 R2. Not sure why you get HTTP 503 but the code should be almost identical.

  21. Surya says:

    I tried the same code to implement custom security, but facing an issue while opening the reportserver url i.e. http//localhost/reportserver

    "Unable to cast object of type 'Microsoft.Samples.ReportingServices.AnonymousSecurity.Authorization' to type 'Microsoft.ReportingServices.Interfaces.IAuthenticationExtension'. "

  22. Surya says:

    I figured out the issue mentioned above. I had missed an entry in config file. Now its working. Thanks for this post.

  23. JordanB says:

    Thanks for a great post, this worked great on RS 2008, haven' t tried it on RS 2008 R2 but it's pretty new, so maybe someday. It was easiest for me to just create a new C# project instead of trying to use the Reporting Services Security Extension Example on Codeplex. That can be confusing. A new class library, copy paste your code (grabbing the import list from the comment section), update a few config files and I am golden. Thanks!

  24. Viraj Kariyawasam says:

    any body  slove the Anonymous access +SQL RS 2008 R2 . i am stuck . please help me

  25. Viraj Kariyawasam says:

    any body  slove the Anonymous access in SQL RS 2008 R2 . i am stuck . please help me, virajtky@gmail.com… Please help mee…

  26. Andy Hudson says:

    Exact same SQL RS 2008 R2 problem. Code works on on our standard 2008 development server, but LIVE server is running 2008 R2 and we still do not have a solution.

    As per previous requests does anyone have a solution for this

  27. Jetr says:

    Hi.

    I tried your code in SQL2008 R2 getting the error "The token cannot be zero". Is there any solution for R2?

    Thanks!

  28. SLIM-Unholy says:

    Well I finally got it working in 2008 R2!

    The primary issue that was happening with the 503 was because of two new tags added for R2 in the Authentication element (from my original rsreportserver.config):

    <RSWindowsExtendedProtectionLevel>Off</RSWindowsExtendedProtectionLevel>

    <RSWindowsExtendedProtectionScenario>Proxy</RSWindowsExtendedProtectionScenario>

    SO the final Authentication element looks like:

    <Authentication>

    <AuthenticationTypes>

    <Custom/>

    </AuthenticationTypes>

    <RSWindowsExtendedProtectionLevel>Off</RSWindowsExtendedProtectionLevel>

    <RSWindowsExtendedProtectionScenario>Proxy</RSWindowsExtendedProtectionScenario>

    <EnableAuthPersistence>true</EnableAuthPersistence>

    </Authentication>

  29. subalexei says:

    Thanks guys, a life saver!!! Now why did I delete those tags from the R2 config in the first place ? :((

  30. Rashmi says:

    HI James,

    Am able to build the above said code ,but SSRS gives

    "‘ The request failed with HTTP status 404: Not Found’"

    U  have any idea about this error

  31. Ramya says:

    Hi,

    I tried this method and I get Report Server (MSSQLSERVER) cannot load the None extension.

    Can anyone help.

  32. Ramesh Tamma says:

    I tried the same steps and works well..

    Try to follow Erik 28 Jul 2010 1:15 PM # comments and original post..that's it..

    Thank you so much..

  33. Norman says:

    Hi James, is there a way to keep ReportManager security level as before

    <AuthenticationTypes>

    <RSWindowsNTLM/>

    </AuthenticationTypes>

    but change ReportServer security to anonymous access?

    TIA

  34. Jeff says:

    Just don't forget to compile in .Net 2.0 Framework. I had the issue on my Win2008 / SQL 2008 R2 Server. I had compiled the code with Visual C# 2010 in .Net 4.0 and I received a report server configuration error. To have some details, look in the SSRS Log and you will see this kind of message : Could not load file or assembly 'Microsoft.Samples.ReportingServices.AnonymousSecurity' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.

  35. Ramana says:

    <CodeGroup

                                       class="UnionCodeGroup"

                                       version="1"

                                       PermissionSetName="FullTrust"

                                       Name="Private_assembly"

                                       Description="This code group grants custom code full trust. ">

                                    <IMembershipCondition

                                           class="UrlMembershipCondition"

                                           version="1"

                                           Url="C:Program FilesMicrosoft SQL ServerMSRS10_50.MSSQLSERVERRSReporting ServicesReportServerbinMicrosoft.Samples.ReportingServices.AnonymousSecurity.dll"

                                   />

                          </CodeGroup>

    resulted in  

    System.Web.HttpException: Unable to read the security policy file for trust level 'RosettaMgr'.

    Can someone please help….

  36. Pablo says:

    Hi, i follow every step to configure it.

    But when i try to go  http://myserver/Reports does not work.

    I checked the event viewer and i have the following:

    Failed to initialize the AppDomain:ReportServer_MSSQLSERVER_0 Exception: System.Web.HttpException Message: Could not load file or assembly 'ReportingServicesWebServer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. Failed to grant permission to execute. (Exception from HRESULT: 0x80131418) (C:Program FilesMicrosoft SQL ServerMSRS10.MSSQLSERVERReporting ServicesReportServerweb.config line 10) StackTrace: at … and goes on.

    Any ideas?

  37. Ken says:

    I also need to get this to work in 2008 R2 but I also get the "cannot load the None extension."  on startup.

    Any ideas?

  38. kevin says:

    Pablo did you figure out your error, Failed to initialize the AppDomain:ReportServer_MSSQLSERVER_0?  I am having the same issue.

    SQL Server 2008 R2…

  39. raj says:

    Once done these changes, I am getting server error page in IE while trying to access the report server.

    Can any one help me ?

  40. aaa says:

    佳き日に、二人に送る<a href="http://www.d-mailer.com/">%E9%9B%BB%E5%A0%B1 結婚 文例</a>でお祝いの気持ちを伝える。

  41. NCR says:

    So, is there a way to have different levels of security for the ReportManager (authenticated) and the ReportServer (anonymous)?   I want regular users to just see the reports without authenticating, but I want a password dialog box for /localhost/reports

  42. Rakesh says:

    After making the changes, I am getting following error:

    "The attempt to connect to the report server failed.  Check your connection information and that the report server is a compatible version. "

    Please suggest.

  43. Vik says:

    how to configure anonymous access to only browse and execute the reprots not able to change anything else

  44. Vipul says:

    Big thanks to jameswu and SLIM-Unholy. Got anonymous access working on R2 less than 15 mins.

  45. Andrew says:

    Has anyone figured out the solution to the "cannot load the None extension."?  I'm stuck there.

  46. Andrew says:

    Thought I'd post the solution to my problem.  I had compiled the code into Microsoft.Samples.ReportingServices.CustomSecurity.dll  not AnonymousSecurity.dll simply because that's the DLL the FormsAuth sample builds.  My issue then became that I had to change the reference to the file.  In the RSReportServer.config file this line

    <Security>

        <Extension Name="None" Type="Microsoft.Samples.ReportingServices.AnonymousSecurity.Authorization, Microsoft.Samples.ReportingServices.AnonymousSecurity" />

     </Security>

    was changed to

    <Security>

        <Extension Name="None" Type="Microsoft.Samples.ReportingServices.AnonymousSecurity.Authorization, Microsoft.Samples.ReportingServices.CustomSecurity" />

     </Security>

    So the part after the comma references the file that the namespace and functions are in for AnonymousSecurity, and I hadn't realized that.

    Thanks for the blog post, this was crazy useful!

  47. Mike says:

    Work like a charm!

    Just remember to compile the DLL in .Net 2.0.

  48. norman says:

    Hi james.

    I manage to update 2008 R2 to accept anonymous based on your solution, problem is any of deployed reports parameter cannot be selected or is disabled.

    Any solution

  49. Xander says:

    I got this error:

    The attempt to connect to the report server failed.  Check your connection information and that the report server is a compatible version.

  50. Work like a charm..

    Thanks, jameswu. You have saved my life.

  51. indu says:

    i implemented same.but not restart the server.

  52. indu says:

    i am implemented same above code.but it is not working…i want urgent…

    please give me reply…

    my mail id is indiradevit@clearpractice.com

  53. indu says:

    please tel me correct procedure..

    i am waitimg for reply……

  54. indu says:

    what is . PassThroughCookies  means

    please tell me..

  55. Maurice says:

    Works fine for me on SQL Server 2008 R2!

    Is there also a solution so it works only for reportserver so i can configure reportmanager the normal way with windows autentication?

  56. John says:

    What idiot at Microsoft thought this dance above was better than providing us a built in way to share REPORTS only to the web???

    This is a nice work around but why is this necessary, does no one at MS live in the real world?

  57. Jonathan says:

    Does somebody make it works in SQL Server 2008 R2?  I receive this error message: ServerConfiguratinoErrorException: Could not create Extension of type: Authentication

    these are the modified parts from my config files:

    rsreportserver.config:

    <Authentication>

    <AuthenticationTypes>

    <Custom/>

    </AuthenticationTypes>

    <RSWindowsExtendedProtectionLevel>Off</RSWindowsExtendedProtectionLevel>

    <RSWindowsExtendedProtectionScenario>Proxy</RSWindowsExtendedProtectionScenario>

    <EnableAuthPersistence>true</EnableAuthPersistence>

    </Authentication>

    <Security>

    <Extension Name="None" Type="ReportingServices.AnonymousSecurity.AuthorizationExtension, ReportingServices.AnonymousSecurity" />

    </Security>

    <Authentication>

    <Extension Name="None" Type="ReportingServices.AnonymousSecurity.AuthenticationExtension, ReportingServices.AnonymousSecurity" />

    </Authentication>

    report server web.config

    <authentication mode="None" />

       <identity impersonate="false" />

    rssrvpolicy.config:

    <CodeGroup

                               class="FirstMatchCodeGroup"

                               version="1"

                               PermissionSetName="Nothing">

                           <IMembershipCondition

                                   class="AllMembershipCondition"

                                   version="1"

                           />

    <CodeGroup

    class="UnionCodeGroup"

    version="1"

    PermissionSetName="FullTrust"

    Name="Private_assembly"

    Description="This code group grants custom code full trust. ">

    <IMembershipCondition

    class="UrlMembershipCondition"

    version="1"

    Url="C:Program FilesMicrosoft SQL ServerMSRS10_50.MSSQLSERVERReporting ServicesReportServerbinReportingServices.AnonymousSecurity.dll"

                                   />

    </CodeGroup>

    </CodeGroup>

  58. Meera says:

    We have resolved this issue by granting FULL Access to IUSER on IIS WebSite.

    We got this issue when we try to launch SSRS Reports on Anonymous SharePoint site. When we try to access the report we are getting error as "This operation is not possible as IUser doesn't have permessions, then I have granted FULL access on my SharePoint site to IUSER and we able to resolve this issue.

    Thanks

    Meera

  59. Marcus Dardy says:

    I'm having trouble with the Microsoft.Samples.ReportingServices.AnonymousSecurity code. I get type or namespace errors on the following classes:

    IAuthenticationExtension

    IAuthorizationExtension

    AceCollection

    SecurityItemType

    ModelItemOperation

    ModelOperation

    CatalogOperation

    ReportOperation

    FolderOperation

    ResourceOperation

    DatasourceOperation

    SecurityItemType

    What do I need to do to fix that.

    Thanks

  60. Vladimir Magalhães says:

    I am receiving this message when trying to access SSRS:

    The report server is not responding. Verify that the report server is running and can be accessed from this computer.

    and see this one on event viewer:

    Message: Could not load file or assembly 'App_global.asax.ee1vt9t5, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Failed to grant permission to execute. (Exception from HRESULT: 0x80131418)

    Does anyone know how to solve this?

  61. saeid says:

    i managed to setup anonymous access. However everything on the report server is available to public. I want only reports be available to public (not datasources )

  62. EH says:

    use report viewer control credential.

  63. Manish says:

    Hi,  i got following Error, HTTP Error 503. The service is unavailable

    can you share with me config and dll file

    Regards,

    Manish

  64. Hi Any one can share your config and dll file if is working in your case

    i have SQL server 2008R2. i  have urgent to fix this issue.

    Regards,

    Manish

  65. I understand the xml setting but I didnt understand what to do with the code which is provided in the post

  66. Omkar Baviskar says:

    Nizam… You need to compile the code as Microsoft.Samples.ReportingServices.AnonymousSecurity.dll and save it @ C:Program FilesMicrosoft SQL ServerMSRS10_50.MSSQLSERVERReporting ServicesReportServerbin-> Location

  67. Ravuri says:

    Hi,

    Getting Error Like below."The attempt to connect to the report server failed. Check your connection information and that the report server is a compatible version in SSRS " worked as 2008 R2.

    Tell me why its coming?

  68. Norman says:

    still occur error 503 after following the step…..I have check the case sensitive as well.

    Please help…

  69. sammy says:

    This article could really help me if I could resolve the following errors when attempting to compile the code:

    IAuthenticationExtension

    IAuthorizationExtension

    AceCollection

    SecurityItemType

    ModelItemOperation

    ModelOperation

    CatalogOperation

    ReportOperation

    FolderOperation

    ResourceOperation

    DatasourceOperation

    SecurityItemType

    The type or namespace name 'ReportingServices' does not exist in the namespace 'Microsoft'

    and same with all the above?

    How do I resolve this?

  70. MILDRED CALINAWAN says:

    PLEASE ALLOW TO RELEASE THE TRANSACTION I MADE  PLS EMAIL ME INFORMATION MORE DEATILS IN MY ACCESS  THE TRANSACTION  IS BEING DONE IN CASH OUR IN LOCAL PLACE DISTINATION

  71. Jewel says:

    I did everything u have write in ur blog. But it is not working. Please help.

  72. An Infinite Monkey says:

    A solution for the below message after you implement this:

    The report server is not responding. Verify that the report server is running and can be accessed from this computer.

    Modify the web.config file in the same folder and look for these two lines:

       <authentication mode="Windows" />

       <identity impersonate="true" />

    Change them to:

       <authentication mode="None" />

       <identity impersonate="false" />

    The author mentions this above as the second thing to change but it's easy to miss due to the formatting of the post.

    FYI, this still works on SQL 2012 also.