How to use SSL with HttpListener with an mkbundle&

2019-04-12 16:59发布

问题:

I have a .NET application built with Mono, that I've bundled into a native (Linux) executable using mkbundle. This is so that end users don't need to mess around and install Mono themselves.

The application uses ServiceStack, which under the hood uses HttpListener. I need the web services to be exposed over an SSL-enabled HTTP endpoint.

Normally, you would run something like httpcfg -add -port 1234 -p12 MyCert.pfx -pwd "MyPass" during configuration (all this really does is copy the certificate to a specific path), and HttpListener would automatically bind the certificate to the port.

So HttpListener loads certificates from a particular path at runtime.

Is that path hard-coded? Or is there some way I can tell it to use a certificate from another location, since the end user will not have Mono installed?

回答1:

Yes the path that HttpListener expects to find certificates at is predefined, and cannot be specified by the user, programatically or through a config file. The Mono EndPointListener class will look for the path:

~/.config/.mono/httplistener/

HttpListener code:

string dirname = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
string path = Path.Combine (dirname, ".mono");
path = Path.Combine (path, "httplistener");

As you have noted this is the same path the httpcfg copies certificates to.

Even though you are using mkbundle, this is still where HttpListener will expect to read the certificate from, regardless of the fact that the Mono runtime is installed.

In your application startup, you should:

  • Check for the existence of the directories, and create as required
  • Write your certificate and key to that path from an embedded resource in your application. PouPou's answer here shows the method used by HttpCfg.exe.

Therefore eliminating the requirement to run httpcfg, you will effectively be building that functionality straight into your application.


Does Mono perform any validation of the certificates it loads from there for HttpListener? i.e., will it expect to find the issuer's certificate in the certificate store?

I don't know for sure if Mono checks for a valid corresponding issuers certificate in the certificate store at the point of creating the listener, or upon each connection request. However you can add a CA cert to the certificate store yourself, or import all the standard Mozroot certificates.

The full source code for Mozroots is here. This shows how to import the CA certs.

Is the path to the certificate store also hard-coded?

The certificate store should be managed through the X509StoreManager provider.