How To: Walkthrough Using HttpListener or Http Server unmanaged code (C++) as an SSL Simple Server

There seems to be no simple end-to-end walkthrough for creating a simple HttpListener based SSL Listener that includes how to configure the computer by generating and installing a Certificate for this listener.

Basic concepts covered:

  • Write the listener code to listen for SSL requests
  • Generate a self signed Certificate
  • Configure the machine to use a Certificate

Write the listener code to listen for SSL requests

Here is the documentation for HttpListener: https://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx

UPDATE: You can also apply this to unmanaged listener based code such as what you can find here: https://msdn.microsoft.com/en-us/library/aa364640(VS.85).aspx 

Copy the code from the above page and paste it into a new C# Console application right under the Main() function.  Then add the System.Net namespace right under using System.Text;: using System.Net;

Now from the Main function call the function you pasted in passing the prefixes you wish to listen to.  In my case I will listen to http requests on port 8080 when the URI ends with the ‘listener’ prefix and https requests on port 8081 again with the ‘listener’ prefix.  Every time a request is handled you need to restart the program.

static void Main(string[] args)
       {
           string[] thePrefixes = { "https://+:8080/listener/", "https://+:8081/listener/" };
           SimpleListenerExample(thePrefixes);
       }

The code should now compile and you can run in the debugger.  I then used Internet Explorer to try and reach the listener: https://jsan17708317:8080/listener/ and this succeeds!  However the https site does not succeed: https://jsan17708317:8081/listener/".

The failure occurs because we have not set up a certificate for the listener to use for SSL traffic (https).  This brings us to the next two items.

Generate a self signed Certificate

First of all, if this is a production environment, you will want to get a server certificate issued by a Trusted Root authority.  This Post illustrates how to create a self signed certificate to test your code before you get a certificate from an authority.

This is the documentation for MakeCert.exe : https://msdn.microsoft.com/en-us/library/bfsktky3.aspx.  You can use this program to generate a self signed Server Certificate for the application.

Using Visual Studio 2008-2010 you can simply use the Visual Studio 2008 or 2010 command prompt from the program menu to access MakeCert.exe.  (NOTE: For Vista and later, make sure you are running as an Administrative command prompt so that you have appropriate permissions)

The syntax would look something like this (replace the name of the machine ‘jsan17708317’ with yours, and see the makecert documentation for an explanation of the arguments used here):

makecert.exe -sr LocalMachine -ss MY -a sha1 -n "CN=jsan17708317" -sky exchange -pe -eku 1.3.6.1.5.5.7.3.1

The command should return ‘Succeeded’.

Now you need to ensure the Root Authority is trusted.  To do this from the same command prompt you used above, type MMC.  Then choose ‘File’, ‘Add/Remove Snap-in…’

image

and then hit the ‘Add’ Button, select ‘Certificates’.  Click the ‘Add’ button…

image

Select ‘Computer account’ and then click ‘Next >’, ‘Finish’, ‘Close’ and ‘OK’.

image

You should them be able to expand the Tree on the left to show the Personal Certificates and find the one you just added (mine is the only one shown)…

image

Double click on your certificate and you will see something similar to this:

image

You need to resolve the Red X problem (the certificate cannot be verified up to a trusted root).

Click on the  ‘Certification Path’ tab in this dialog, and the problem certificate (Root Agency) then on ‘View Certificate’.

image

You will see the problem is that this Certificate is not in the ‘Trusted Root’ store. 

  image

To get it into the store, click the ‘Details’ Tab and then the ‘Copy to File…’ button

image

Hit ‘Next >’ twice then the ‘Browse’ button and save the file to your local Documents directory (name it something like ‘RootCert’) then finish up the wizard until you have successfully exported the certificate.  Now we will import the certificate into the trusted root store.

Expand the ‘Trusted Root Certification Authorities’ tree and right click on ‘Certificates’

image 

From the context menu select ‘All Tasks…’ then ‘Import…’ and navigate to where you saved the ‘RootCert’ and import the certificate by completing the Wizard.

Now you should be able to go back to your Server Certificate in the Personal Store and see that there are no problems with the Certificate (leave this dialog up for the next step):

image

The final step here is to get thumbprint hash for use in the next section.

Click on the ‘Details’ tab, and scroll down to the ‘Thumbprint’ Field in the dialog and click on it.  Then sweep out the numbers below with your mouse (don’t miss any) and copy those numbers with the Ctrl+C key combination.

image

Open notepad and paste these numbers into it for use in the next step.

 

Supplemental note:

If you have IIS installed, I like the SSL Diagnostics tool instead of Makecert: https://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=cabea1d0-5a10-41bc-83d4-06c814265282 Instructions for generating the certificate are in the help file for this tool.  Once you run this tool it creates a temporary certificate and installs it in the local computer Trusted Root Authorities Certificate store for you!

Configure the machine to use a Certificate

Finally you need to configure the machine to associate the certificate you just created, with the port and ip address that the HttpListener is listening on for https requests.

UPDATE: For Vista and above you will use the netsh http commands listed here and NOT httpcfg.exe: https://msdn.microsoft.com/en-us/library/cc307236(VS.85).aspx

You need to obtain httpcfg.exe to do this next step.  Search Technet for the latest version of this tool for your OS.  For example, XP SP2 tools have it (Note: this is an optional component for XP so you will need to do a COMPLETE install to get this tool): https://www.microsoft.com/downloads/details.aspx?FamilyId=49AE8576-9BB9-4126-9761-BA8011FABF38&displaylang=en

You will need to run httpcfg from the command line and supply the Thumbprint hash you obtained in the previous section but you need to remove the spaces between the numbers.  In my example I removed the spaces and the hash is: f4bb35424190e006e5476e97430c5b8136ee5da5

This is the httpcfg command I ran to associate the cert for all IP addresses associated with my machine and port 8081 (/i 0.0.0.0:8081):

C:\Program Files\Support Tools>httpcfg set ssl /i 0.0.0.0:8081 /h f4bb35424190e006e5476e97430c5b8136ee5da5

UPDATE: For Vista and above, you need to generate a guid first. From the VS prompt you used above to generate the certificate you can type: guidgen.exe. Then hit the copy button to copy the newly created GUID. Paste this into Notepad along with your hash. You will want the first part of the text (for example: {FCB0C645-E745-490F-9E7D-2171E03DC9B0}) for the next step. Now use this netsh command: netsh http add sslcert ipport=0.0.0.0:8081 certhash=f4bb35424190e006e5476e97430c5b8136ee5da5 appid={FCB0C645-E745-490F-9E7D-2171E03DC9B0}

When you run this you will see the result: HttpSetServiceConfiguration completed with 0.

Now double check the SSL bindings for this computer:

C:\Program Files\Support Tools>httpcfg query ssl
    IP                      : 0.0.0.0:8081
    Hash                    : f4bb35424190e0 6e5476e9743 c5b8136ee5da5
    Guid                    : {00000000-0000-0000-0000-000000000000}
    CertStoreName           : (null)
    CertCheckMode           : 0
    RevocationFreshnessTime : 0
    UrlRetrievalTimeout     : 0
    SslCtlIdentifier        : (null)
    SslCtlStoreName         : (null)
    Flags                   : 0
------------------------------------------------------------------------------

 UPDATE: For Vista and above the command is: netsh http show sslcert

You can verify that the IP shows up and the Hash you entered (note that weirdness where some of the 0 characters do not appear… I don’t know why that is).

Now you should be able to run the above Test application and hit the SSL Site using Internet Explorer.  In my case the URL is: https://jsan17708317:8081/listener/

Troubleshooting

If the app does not work, first verified you did each step above correctly (did not leave out something or some step).

Verify your certificate appears with the IP and Hash fields the correspond with what you are listening for and that the Hash is the hash you obtained previously for the certificate.

Check with httpcfg query ssl and see if there are other listeners that may conflict for that same port.  Delete conflicts with the command http delete ssl /i x.x.x.x:8081  (replace x.x.x.x with any IP address you see that are listening on the same port).

For Vista and above, ensure you are running your HttpListener code with Administrative privileges or you will not be able to register your machine name (you will get access denied or Error code 5 from unmanaged code).

Supplemental Information

This is a simple example.  You probably do not want to stop listening after you process one request.  You will need to provide a way to gracefully close the listener and handle the requests on worker threads.

You can specify a specific IP range in HttpCfg (search MSDN for HttpCfg syntax).  In my example you can use this to bind to the ip address 10.10.3.4:
httpcfg set ssl /i 10.10.3.4:8081 /h f4bb35424190e006e5476e97430c5b8136ee5da5

You cannot listen for http and https traffic on the same port.

 

I hope this gets you started with your HttpListener project and will help you troubleshoot the initial setup of your code.  Please Drop me a note if you find this useful!