0

I'm writing a small WCF service and I'd like to be able to write to a custom event log. I've created an event log and source and a minimal service and the service can write to the log. Then I added impersonation and started getting 'Access is denied' errors at the client. When logged at the server, it takes the form of a 'Requested registry access is not allowed' error.

Although this wouldn't be the case with users of the service, the account being impersonated is (necessarily) a member of Administrators (in order to be able to debug using IIS).

I get the same results running the WCF Test Client on the same machine with a non-admin user, and on another machine with a non-admin user.

To recreate:

  1. Start PowerShell as Administrator
  2. New-EventLog -LogName Test42 -Source Test42.Web
  3. Close PowerShell
  4. Start Visual Studio as Administrator
  5. New Project - .NET Framework 4.5 > Visual C# > WCF > WCF Service Application 'ImpSvc1' (* Create directory for solution)
  6. Replace the contents of IService1.cs, Service1.svc and Web.config with the contents below.
  7. In the WCF Project Properties > Web (tab) > Servers - choose Local IIS and click Create Virtual Directory.
  8. Build the Project.
  9. Start IIS Manager - Select the Default Web Site
  10. Open IIS
  11. You'll need an Application Pool with a domain account (with no special permissions on the IIS machine) and integrated pipeline mode, so create one if you haven't got one.
  12. Select Default Web Site > Authentication. Ensure Windows Authentication is enabled and all others are disabled.
  13. Select ImpSvc1 > Basic Settings. Select the Application pool from above.
  14. Close IIS Manager.
  15. Start the WCF Test Client. File > Add Service > http://localhost/ImpSvc1/Service1.svc
  16. Double-click on the GetDate() method and click Invoke. You should get RESPONSE: user=; dateTime= and en event created in the Test42 event log.
  17. Uncomment the using statement, build and repeat the Invoke and you should get: RESPONSE: user=; dateTime= and en event created in the Test42 event log.
  18. Uncomment the EventLog.WriteEntry statement, build and repeat the Invoke and you should get an 'Access is denied' error in the WCF Test Client.
  19. If you start the project with Debugging, you'll see it's a 'Requested registry access is not allowed.'

IService1.cs

using System;
using System.ServiceModel;

namespace ImpSvc1
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        String GetData();
    }
}

Service1.svc

using System;
using System.Diagnostics;
using System.Security.Principal;
using System.ServiceModel;

namespace ImpSvc1
{
    public class Service1 : IService1
    {
        public String GetData()
        {
            EventLog.WriteEntry("Test42.Web", "Test message", 
                EventLogEntryType.Information, 1, 0);
            //using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
            //{
                //EventLog.WriteEntry("Test42.Web", "Test message from using statement", 
                //    EventLogEntryType.Information, 2, 0);
                return String.Format("RESPONSE: user={0}; dateTime={1}", 
                    WindowsIdentity.GetCurrent().Name, DateTime.Now);
            //}
        }
    }
}

Web.config

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" 
         value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" 
                 targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding closeTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:10:00"
                 sendTimeout="00:10:00">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" 
                           httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="basicHttpBinding" 
           scheme="http" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" 
                               multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
    <security>
      <authentication>
        <anonymousAuthentication enabled="false" />
        <windowsAuthentication enabled="true" />
      </authentication>
    </security>
  </system.webServer>

</configuration>
user2871239
  • 1,499
  • 2
  • 11
  • 27
  • This is obviously a permissions thing, check out this if you havent already https://support.microsoft.com/en-au/help/329291/prb-requested-registry-access-is-not-allowed-error-message-when-asp-ne – TheGeneral Sep 25 '18 at 10:17
  • Also this https://stackoverflow.com/questions/292883/event-log-securityexception-for-web-application and this https://social.msdn.microsoft.com/Forums/en-US/51243ba7-d02a-4e2a-8661-0c6b21cf20bc/requested-registry-access-is-not-allowed-even-while-impersonating-a-server-admin-account?forum=asmxandxml – TheGeneral Sep 25 '18 at 10:19
  • Those don't appear to be quite the same issue. They all appear to be trying to create the event source from the application. I was aware that you need admin privs to create an event source, so I created it separately. My code writes to the source successfully before impersonating the user but not whilst impersonation is underway. But it does look as if the WriteEntry method inside the impersonation can't see the source and so is checking for it before automatically creating it. – user2871239 Sep 25 '18 at 11:03
  • Administrator rights are required to create event sources, but any authenticated user can write to the log. You need to create the source outside of your application. This post gets into how to work around these issues. https://stackoverflow.com/a/14252008/3516555 – fourwhey Sep 25 '18 at 12:36
  • @fourwhey - as noted in the question, I've already created the event source and written to it. The issue is only that I can't write to it whilst impersonating the user. – user2871239 Sep 25 '18 at 15:09
  • Only the security event source has authorization tied to writing to it. All others, caveat being that they must exist, can be written to by any user. Given that, the account the service process is impersonating should work. I'll attempt to test what you're seeing. – fourwhey Sep 25 '18 at 17:24

0 Answers0