5

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?

Cocowalla
  • 13,822
  • 6
  • 66
  • 112

1 Answers1

5

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.

Community
  • 1
  • 1
Scott
  • 21,211
  • 8
  • 65
  • 72
  • 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? Is the path to the certificate store also hard-coded? – Cocowalla Apr 23 '14 at 17:22
  • @Cocowalla I have updated the answer. The linked implementation of `Mozroots` tool should allow you to add your CA route certificate to the system during your application configuration stage. `X509StoreManager` is used to manage the certificate store, so the path should not be directly accessed. Hope this helps – Scott Apr 23 '14 at 20:39
  • 1
    I checked `X509StoreManager` (https://github.com/mono/mono/blob/a31c107f59298053e4ff17fd09b2fa617b75c1ba/mcs/class/Mono.Security/Mono.Security.X509/X509StoreManager.cs), which does indeed show that the paths are hard-coded. mkbundle is meant to mean that the user doesn't need Mono already installed... but it seems they do need a lot of paths to be in the hard-coded places :/ – Cocowalla Apr 24 '14 at 09:10
  • You could compile Mono from source with your own implementations of these classes that allow the path to be specified, or use the applications working directory for example. When mkbundle statically links it would do so using your custom implementation. Obviously you would have to weigh up the benefit of maintaining this custom build vs the hardcoded paths. But it's an option. – Scott Apr 24 '14 at 10:16
  • Might be an option. I'm not sure where this puts me from a licensing perspective tho. I think to comply I need to allow users to swap the libmono I will be bundling with their own. – Cocowalla Apr 24 '14 at 11:08
  • That's true, yeah I hadn't accounted for other people swapping libmono, I guess it's just something to live with to stay compliant with LGPL. I presume at the moment you just ship the bundled app produced by mkbundle, and allow people to request the `.exe` and `.dll`'s to bundle using mkbundle against their own version of mono on request? – Scott Apr 24 '14 at 11:30
  • 1
    Just now I plan to ship the mkbundle'd app (dynamically linked), along with the `libmono-sgen.so` shared library for the runtime, and users can, theoretically, swap out that runtime library for a different version if they really want – Cocowalla Apr 24 '14 at 11:38
  • The source code for Mono's `httpcfg` can be seen here (for example you will note it uses the port number to save the certificate file with `.cer` extensions): https://github.com/mono/mono/blob/master/mcs/tools/security/httpcfg.cs – Eric Mutta Dec 17 '20 at 22:21