4

I'm using WCF to do inter-process communication on my machine, using WSHttpBinding, and I'd like to restrict the service so only processes on the current machine can call the service. How can I do this?

I would prefer to use NetNamedPipesBinding which inherently would perform this restriction, however this is not possible in my scenario, so I'd like a way to restrict it using WSHttpBinding. The reason I can't use NetNamedPipesBinding is that one of the clients to the service is running within a low-integrity process (Internet Explorer in Protected Mode) and doesn't have access to connect to a higher-integrity named pipe (without a lot of undocumented jiggery-pokery like this which looks good but I'd prefer to avoid).

One option would be to add an IDispatchMessageInspector that restricts by IP Address as described here. Is that the best approach?

UPDATE: This software will be deployed to hundreds of machines, so a solution like using certificates would likely be more work than desired.

Community
  • 1
  • 1
Rory
  • 40,559
  • 52
  • 175
  • 261
  • Sound like terrible solution. If you need IE to communicate this way it looks like scenario for browser control self hosted in custom winform application and all this complications will be gone because your application will be able to use named pipes. – Ladislav Mrnka Sep 13 '11 at 08:47
  • The software is a browser extension, installed on corporate desktops. Can't be a hosted control as that would require people using software other than IE to access the internet sites which the extension is designed to support. – Rory Sep 13 '11 at 10:58
  • In such case the service itself should be deployed in central location instead of per machine. It is funny that you are not able to call named pipes because of security restriction but in the same time you allow each machine to listening on HTTP requests on system level. – Ladislav Mrnka Sep 13 '11 at 11:03
  • No, there is a windows service running on each machine that the browser component needs to communicate with. This can't be on a central location for a variety of reasons, including network performance and availability. I want the two components (windows service & browser extension) to communicate. NamedPipes would be most appropriate but WCF doesn't expose an API to create low-integrity named pipes. IE Protected Mode doesn't restrict access to http requests, but I'd like to lock this down to ensure the http web service only listens to requests from the local machine. – Rory Sep 13 '11 at 11:37

1 Answers1

0

You could try using X509 certificates to create a security signature. That way, you can hold the lock and the key. Other IPs would be able to hit your service, but not communicate. You could do something like:

In the Service:

          <behaviors>
  <serviceBehaviors>
    <behavior name="wsHttpCertificateBehavior">
      <dataContractSerializer maxItemsInObjectGraph="50000"/>
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
      <serviceCredentials>
        <clientCertificate>
          <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" />
        </clientCertificate>
        <serviceCertificate findValue="CN=WSE2QuickStartServer" storeLocation="LocalMachine"
          storeName="My" x509FindType="FindBySubjectDistinguishedName" />
      </serviceCredentials>
    </behavior>
    <behavior name="">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>

In the Client:

    <behaviors>
  <endpointBehaviors>
    <behavior name="wsHttpCertificateBehavior">
      <dataContractSerializer maxItemsInObjectGraph="50000" />
      <clientCredentials>
        <clientCertificate findValue="CN=WSE2QuickStartClient" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectDistinguishedName" />
        <serviceCertificate>
          <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" trustedStoreLocation="LocalMachine" />
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>

<client>
  <endpoint address="https://localhost/ClientService.svc" behaviorConfiguration="wsHttpCertificateBehavior" binding="wsHttpBinding" bindingConfiguration="ApplicationServicesBinding" contract="GAINABSApplicationServices.Contracts.ServiceContracts.IClientService" name="ClientService">
    <!--<identity>
      <certificateReference storeName="AddressBook" storeLocation="CurrentUser"
        x509FindType="FindBySubjectName" findValue="WSE2QuickStartServer"
        isChainIncluded="true" />
    </identity>-->
  </endpoint>
 </client>

You may optionally need the Identity tag on the client to state that you are explicitly using the cert for the identity when communicating with the service. Hope this helps!

jonnyb
  • 352
  • 1
  • 2
  • 17
  • Thanks for this. I should have mentioned, this software will be running on hundreds of machines. So using certificates would be effective but the management/deployment around it probably makes it more complicated than necessary. – Rory Sep 13 '11 at 08:41