views:

218

answers:

3

I am looking for a way to use a WCF WebServiceHost without having to rely on the HttpListener class and it's associated permission problems (see this question for details).

I'm working on a application which communicates locally with another (third-party) application via their REST API.

At the moment we are using WCF as an embedded HTTP server. We create a WebServiceHost as follows:

String hostPath = "http://localhost:" + portNo;
WebServiceHost host = new WebServiceHost(typeof(IntegrationService), new Uri(hostPath));

// create a webhttpbinding for rest/pox and enable cookie support for session management
WebHttpBinding webHttpBinding = new WebHttpBinding();
webHttpBinding.AllowCookies = true;

ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IIntegrationService), webHttpBinding, "");

host.Open()

ChannelFactory<IIntegrationService> cf = new ChannelFactory<IIntegrationService>(webHttpBinding, hostPath);
IIntegrationService channel = cf.CreateChannel();

Everything works nicely as long as our application is run as administrator. If we run our application on a machine without administrative privileges the host.Open() will throw an HttpListenerException with ErrorCode == 5 (ERROR_ACCESS_DENIED).

We can get around the problem by running httpcfg.exe from the command line but this is a one-click desktop application and that's not really as long term solution for us.

We could ditch WCF and write our own HTTP server but I'd like to avoid that if possible.

What's the easiest way to replace HttpListener with a standard TCP socket while still using all of the remaining HTTP scaffolding that WCF provides?

A: 

Your problem is not related to HttpListener.

Your problem is: * You have a oneClick application with limited permissions that * Tries to open a Server port.

This is a contradiction. An untrusted limited permission application should NOT OPEN A SERVER PORT. This is why this is not allowed per definition.

Have you tried opening a normal socket port? It should not work either.

In general, limited trust end user applications should not host a web service ;)

That said, I ahve been in a similar situation trying to use WCF in a driver communication scenario - thank heaven my application runs with full permission.

TomTom
I appreciate what you're saying but I just double checked this and it *is* possible to open a normal listening socket in these conditions. The issue is specifically with HttpListener - presumably because it could allow a malicious application to run on the same port as something else (and so traffic could get inside the firewall - see http://www.leastprivilege.com/HttpCfgACLHelper.aspx for a few more details).The fact is that we'd have the same problem when running as a limited user regardless of how we deployed the application and there are lots of genuine reasons for wanting to do this.
sbyse
A: 

You can easily compose your own stack via CustomBinding, using the higher level protocol stuff "as is", and rolling your own version of HttpTransport that isn't backed by HttpListener or IIS. Do-able, sure, but it's a lot of work. Take the existing HttpTransport bits apart with Reflector- there are a LOT of moving parts in there. You could probably hack up a simple PoC over Socket in a day or two if you don't need anything fancy like HTTPS or chunking, but making it robust will be tricky. Here's a good wrapup of a bunch of resources (may be a bit dated now).

nitzmahone
Thanks for the link - this is pretty much the conclusion I came to.Unfortunately almost all of the classes I'd like to derive from (HttpChannelListener, HttpTransportManager etc) are marked as internal so you're right, there's a huge amount of reimplementation required. Ho hum.
sbyse
We didn't need anything fancy so I ended up rolling my own small HTTP server which was able to understand our pre-exising service contracts. The mass of internal classes and private methods made the WCF implementation too time consuming, shame.
sbyse
Agreed- I've done something similar where the WCF REST stuff fell down on us and the one TINY thing we had to change was too deep down in HttpTransport to be worthwhile. I could even make it work in the debugger by tweaking an internal member, but there was just no way to do it for real.
nitzmahone
A: 

You could also look at ripping apart enough of Cassini to make it hostable in your app, and loading the WCF pipeline in there (via .svc files and the service activation handler)- it'd require writing very little new code that way, but still give you a fairly robust and tested webserver.

nitzmahone