views:

179

answers:

3

I'm working on a self-hosted WCF service for which encrypted communications is an option. Everything works fine when a certificate is already bound to the port as described here.

However, I want to avoid asking the user to run a command line tool. Is there a way the binding can be done programmatically? Perhaps using WMI?

+2  A: 

I believe the way to create an HTTP.SYS namespace reservation is through the HttpSetServiceConfiguration() unmanaged API; so you'll need some P/Invoke for that. There's some sample code that might be useful in one of Keith Brown's MSDN columns.

tomasr
I'm voting this up because Tomas was first and we basically said the same thing. :)
Drew Marsh
+1  A: 

Yes, but you have to use the HTTP API yourself which which there is currently no .NET wrapper, so you must use P/Invoke. Specifically I think you're looking for HttpSetServiceConfiguration with the HttpServiceConfigSSLCertInfo config id.

Drew Marsh
A: 

The MSDN documentation, Keith Brown's MSDN column, and pinvoke.net got me most of the way there. But getting the PSOCKADDR in the HTTP_SERVICE_CONFIG_SSL_KEY correct was tricky. I found Beej's Guide to Network Programming very helpful in figuring out what it should look like. I was able to use the .NET SocketAddress and then copy the bytes to an array that could be marshaled.

// serialize the endpoint to a SocketAddress and create an array to hold the values.  Pin the array.
SocketAddress socketAddress = ipEndPoint.Serialize();
byte[] socketBytes = new byte[socketAddress.Size];
GCHandle handleSocketAddress = GCHandle.Alloc(socketBytes, GCHandleType.Pinned);

// Should copy the first 16 bytes (the SocketAddress has a 32 byte buffer, the size will only be 16, which is what the SOCKADDR accepts
for (int i = 0; i < socketAddress.Size; ++i)
{
    socketBytes[i] = socketAddress[i];
}
dmo