Showing posts with label ssl. Show all posts
Showing posts with label ssl. Show all posts

Sunday, June 29, 2014

Practical Certificate Knowledge for .NET developers: HttpWebRequest Client Certificate Authentication

HttpWebRequest Client Certificate Authentication

Articles in this series:

Introduction

Finally, some C# code! This post builds upon part four, where we use an HttpWebRequest object to contact our web page. This example can be practically used when invoking REST-style HTTP services that use client certificate authentication. 

Sample Code

Copy and paste more easily from here (dotnet fiddle link).

In a new console app, use the following code, but be sure to update the port to match what you used in Part Four.

Additionally, you will need to import the MyClientCert.pfx file into the local computer's personal certificate store. In order to do this, follow Part Four, Step 3, but rather than selecting your user's certificate store, select the local computer's certificate store. 

Go ahead and run this code, and you should see the contents of your HTML file dumped out to the console. Note however, though, if you remove the association line request.ClientCertificates = collection; and re-execute the program, you'll get a 403 Forbidden error, since you aren't passing in the certificate required for the request. 

The code below is commented to walk through what is actually happening. Do note that when working with X509 certificates in .NET, you'll want to utilize the X509Certificate2 classes (not the X509Certificate classes), as the '2' classes are a newer, more fully featured class to handle X509 certs in code. 

using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace ClientCertInvocation
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a web request that points to our SSL-enabled client certificate required web site
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://my.local.machine:440/");

            // Use the X509Store class to get a handle to the local certificate stores. "My" is the "Personal" store.
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

            // Open the store to be able to read from it.
            store.Open(OpenFlags.ReadOnly); 

            // Use the X509Certificate2Collection class to get a list of certificates that match our criteria (in this case, we should only pull back one).
            X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "MyClientCert", true);

            // Associate the certificates with the request
            request.ClientCertificates = collection;

            // Make the web request
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            // Output the stream to a file.
            Stream stream = response.GetResponseStream();
            using (var fileStream = File.Create("copy.html"))
            {
                stream.CopyTo(fileStream);
            }
        }
    }
}

Sunday, June 15, 2014

Practical Certificate Knowledge for .NET developers: Client Certificates: IIS Setup

Client Certificates: IIS Setup

This week we're going to look at setting up a website in IIS that requires client certificate authentication to access. You'll need to have gone through at least parts two and three in order to follow along with this post. 


Introduction

Client certificates are commonly used to authenticate a client with a service provider. Typically the client will generate the client certificate, as it is required for the client to hold on to the private key. The client will pass the public key to the service provider, who will configure their service to accept and trust that public key, while typically mapping that public key to a particular user on the server side. Client certificates can be generated on your own or purchased through a generally trusted certificate authority. 

In this post, we'll be generating a client certificate signed by your root certificate and configuring the SSL site you set up in part three to associate that client certificate with a user on your system, as well as explore the IIS option to disallow, accept, or require a client certificate on connection.

Lastly, we'll validate that we've set up our site properly by visiting your local SSL-enabled site in a browser and ensuring that the client certificate gets passed properly.

Step 1: Validate your existing setup

If you've been following the previous posts, ensure that:
  1. Your MyRootCert.cer file has been imported to the Trusted Root Certification Authorities of both your user and local computer stores.
  2. That your my.local.machine certificate has been imported into the local computer's personal store.
  3. That your SSLSite web site has been set up in IIS properly with an HTTPS binding and is accessible by hitting https://my.local.machine:port/ with no certificate errors.
Step 2: Generate your client certificate

Open up a command prompt and navigate to the certificate directory you've been working in and run the following command:

makecert.exe -iv MyRootCert.pvk -ic MyRootCert.cer -n CN=MyClientCert -len 2048 -pe -sv MyClientCert.pvk -sky exchange -b 01/21/2010 -e 01/21/2020 MyClientCert -eku 1.3.6.1.5.5.7.3.2

The only difference in the command here vs the server certificates we've been generating is the -eku parameter, which is set to the value to specify a client certificate.

Once again, you'll be prompted to set a password for your client cert's private key (I did not, but you should for a production environment), and asked for MyRootCert's private key password in order to sign the client cert (which I had set to 'learning'). 

Next, run pvk2pfx.exe in order to generate MyClientCert.pfx:

pvk2pfx.exe -pvk MyClientCert.pvk -spc MyClientCert.cer -pfx MyClientCert.pfx

Step 3: Import your client certificate into your user's personal certificate store.

Now open up your Microsoft Management Console (Win+Rmmc, <Enter>) and add the certificate snap-in by going to File->Add/Remove Snap-In. Click on 'Certificates' in the left panel, then click add. Add the snap in for your current user.

Now import the MyClientCert.pfx file into your current user's personal certificate store, but ensure you mark the certificate as exportable, as shown:


Ensure the middle and last checkboxes are checked.


Step 4: Getting the base64 encoded certificate

In order to set up IIS, you'll need the base64 encoded version of the public key certificate. Take the following steps:


Right click on MyClientCert in the Current User's Personal Certificate Store, go to All Tasks->Export

Click 'Next'

No, do not export the private key

Select 'Base-64 encoded X.509'

Finish up the wizard and name the certificate MyClientCertBase64.cer

Now head to the directory where MyClientCertBase64.cer is, and open it in a text editor. You should see something like this, but the string will be different:



We'll do something with this further down.


Step 5: IIS Enhancement

Follow the instructions in IIS Client Certificate Mapping Authentication under 'setup' to install the support in IIS for client certificate mapping, replicated below for your convenience, which adds support for client certificate mapping. The linked page is worth reading, as it also explains the parameters we are going to set up in Step 6.

WINDOWS SERVER 2008 OR WINDOWS SERVER 2008 R2
  1. On the taskbar, click Start, point to Administrative Tools, and then click Server Manager.
  2. In the Server Manager hierarchy pane, expand Roles, and then click Web Server (IIS).
  3. In the Web Server (IIS) pane, scroll to the Role Services section, and then click Add Role Services.
  4. On the Select Role Services page of the Add Role Services Wizard, select IIS Client Certificate Mapping Authentication, and then click Next.
  5. On the Confirm Installation Selections page, click Install.
  6. On the Results page, click Close.

WINDOWS VISTA OR WINDOWS 7

  1. On the taskbar, click Start, and then click Control Panel.
  2. In Control Panel, click Programs and Features, and then click Turn Windows Features on or off.
  3. Expand Internet Information Services, then select IIS Client Certificate Mapping Authentication, and then click OK.
Step 6: IIS Configuration

In IIS, select your SSL site, then click on configuration editor:



You should see something similar to the following after setting 'Section' to 'system.webServer/security/authentication/iisClientCertificateMappingAuthentication'.



Now enter the following values:
Sectionsystem.webServer/security/authentication/iisClientCertificateMappingAuthentication : This sets the section of the configuration we are going to edit, pulled from the documentation site linked here.
From: ApplicationHost.config <location path='SSLSite'/> - sets the config file to edit.
enabled: True - turns on client certificate mapping authentication
logonMethod: ClearText - descriptions of the different types are in the documentation.

Ensure oneToOneCertificateMappingsEnabled is assigned to true, then click on the 'oneToOneMappings' row and click on the ... button that appears on the end of the row.

You should see a screen like:


This is the screen that lets you input a client certificate and map it to a single user. Click 'Add' on the right, and for the new user, set 'enabled' to 'true', and input the username and password of the windows user you want to be associated to your certificate (this can be the same logon you are currently using on your machine). 

For the certificate, head back to your MyClientCertBase64.cer file. open this in a text file, remove the very first line (-----BEGIN CERTIFICATE-----) and the very last line (-----END CERTIFICATE-----) and collapse the base64 encoded representation of your certificate to a single line. Copy and paste this line into the certificate field. Your window should look something like:


Close the window, and you should now see a Count=1 next to your oneToOneMappings line in the configuration edit. Click 'Apply' on the top right. 

Click back on your SSL site to return to the following view and click 'SSL Settings'.


Check the 'Require SSL' box, then check 'Require' under 'Client Certificates', then 'Apply' on the top right. Note the other options here, and note that you can only pass in a client cert if you've got an SSL connection established to the server.


IIS Should be all set up now.

Step 7: Validating you need the cert to access the site.

Before you try to connect to your site in a browser, open up IE. Press F10 if you can't see the menu bar, then click tools, internet options, click on the security tab, click 'local intranet', and click 'custom level'. Under 'Miscellaneous', select 'Disable' for "Don't prompt for client certificate selection when only one certificate exists."

This will ensure you'll get a popup asking you which cert to pass to the server, validating that the server is asking for your cert.

Click OK to save your custom level settings, then OK to save your internet options. 

Access your site via IE by going to https://my.local.machine:port/ (remember, port is what you set up in Part 3 in your site bindings). 

You should be prompted to supply your client certificate, but if not, click File->Properties to ensure that you changed your security settings for the correct zone that IE detects your site in.

If everything works properly, you should see:


And once you click OK, you should see your site content, successfully having presented the certificate:

As an exercise, you can feel free to remove MyClientCert from your Personal Store temporarily to see what comes up when you try to access your site again, proving that the cert is required to access the site (be sure it re-import MyClientCert.pfx afterwards, as we'll likely re-use this cert in subsequent posts).



There are quite a few additional settings in IIS for mapping client certs. Feel free to read over the documentation and understand the settings yourself in order to learn more.

Step 8: Validating you're logging in as the correct user



Let's ensure now that you're actually hitting the site as the logged in user. Open up IIS Manager, click on SSL site, and double click on Logging. Ensure your format is set to W3C, and click on 'Select Fields', ensuring that cs-username is selected. Click OK to save and close the select fields box, and note the directory of the logs. Open up the log directory and find the logs for SSLSite. Open up the latest ones, and you should see the username you configured inside the logs (mine is tchawla), whereas if you look at old logs, a - would be present for the username instead.



Conclusion

That's it for this post. Keep your certificates and setup around, as eventually I want to get into explaining how to call into web services that are hosted on this site and passing in the client cert via .NET code.

Sunday, June 8, 2014

Practical Certificate Knowledge for .NET developers: Setting Up SSL Locally

Setting Up SSL Locally

Last week's post was on generating your own certificates. This week we're going to look at setting up SSL locally. You will need to have gone through at least Part Two for this, and an upcoming posts about client certificates will require this post as a prerequisite.



There are a few different ways to do this, and I'm going to take the approach of generating a certificate on your own, importing to the proper certificate stores, and binding it to a web site yourself. This way you'll learn where these certificates live. You can also generate SSL certs directly inside of IIS if you'd like.

Step 1: Trusting Your Root Certificate

If you have not run through part two yet or you removed your MyRootCert.cer from your user's Trusted Root Certification Authorities folder, go ahead and re-import it again. Steps to do this in are in part two under 'Trusting the Root Certificate'.

Step 2: Generating Your SSL Certificate

If you went through part two, you already generated an SSL certificate (MySecondCert.cer). An SSL certificate is nothing more than a certificate with an extended key usage field set to server authentication. In our example today we'll work with a new cert signed by your MyRootCert's private key, which you can generate using the following command. Ensure you run this command from the folder where you kept makecert.exe and MyRootCert.cer and MyRootCert.pvk. This command is identical to the MySecondCert generation command from part two, only with different filenames for the .cer and .pvk file, and a different subject name.


makecert.exe -iv MyRootCert.pvk -ic MyRootCert.cer -n CN=my.local.machine -len 2048 -pe -sv my.local.machine.pvk -sky exchange -b 01/21/2010 -e 01/21/2020 my.local.machine.cer -eku 1.3.6.1.5.5.7.3.1

First you'll be asked to set a password for the new cert you'll be generating. You can if you would like, but in my case, I did not by pressing the 'None' button since this is not for a production system.

my.local.machine.pvk's password setting (I did not set one by clicking None)

Next you'll be asked for your password for the signing cert (in our case, MyRootCert). Last week we had set this to 'learning'. Remember that the certificate being created is being signed by MyRootCert's private key (the MyRootCert.pvk file), which is why you get prompted for MyRootCert.pvk's password.

Request for the MyRootCert.pvk password in order to use it to sign the new certificate.

After the command completes, you should see the my.local.machine.cer and my.local.machine.pvk file in your directory.

Step 3: Generating the my.local.machine.pfx file

In order to set up an SSL site, we'll need a .pfx file to import into the local computer's personal certificate store. Just like last post, use the pvk2pfx.exe program to generate this.

pvk2pfx.exe -pvk my.local.machine.pvk -spc my.local.machine.cer -pfx my.local.machine.pfx

You should now see the my.local.machine.pfx file in your directory.

Step 4: Importing the certificate and private key 

Now open up your Microsoft Management Console (Win+R, mmc, <Enter>) and add the certificate snap-in by going to File->Add/Remove Snap-In. Click on 'Certificates' in the left panel, then click add. This time, we'll want to add in the certificates snap in for the local machine, as follows:

Select 'Computer account' and click Next.
Select 'Local computer' and click Finish

The reason we want to import our my.local.machine cert into the local computer certificate store is because IIS does not run under your own user account, rather, it runs under a system account.

Once you see the cert store for the local computer, go ahead and import the my.local.machine.pfx file into the local computer's personal store with the default settings. Note that when you click import, the search window will default to showing .cer files only - you'll have to change the types in the bottom right corner in order to show .pfx files as well. 

Once the cert is imported successfully, you should be able to see it in the local computer's personal store. 

At this point, import your MyRootCert.cer file into the Trusted Root Certification Authorities for the local computer store as well so that all of your certs signed by MyRootCert are trusted by your computer.

Step 5: Set up the web site

Create a folder on your hard drive somewhere (mine is at C:\SSLSite) that will be the directory holding your site files. Inside of it, create a text file named Default.htm, edit it, and set the contents to just be 'SSL!'.

Now open IIS and create a new web site by right clicking on sites and clicking 'Add Web Site.'


Set up your site as the image below shows. Note that your physical path might be different based on where you created your site file directory. If port 443 on your machine is in use, feel free to choose another one that is not in use (for example, on my machine, it was, so you'll see future screenshots use 440 instead. Additionally, when typing in URLs below, you should only have to specify the port if you chose not to use 443).


Click OK when you are done filling out your settings, then open a browser and navigate to https://localhost:port/, where port is the port set in the binding section in the 'Add Web Site' dialog just above. You'll likely see an error message like the following:


This indicates that the certificate being offered is invalid. In Chrome, I continued on to the site, and once I clicked the x'd out lock icon by the https, Chrome told me that the server certificate is invalid because the server's certificate does not match the url. In this case, the server's certificate has a subject name of my.local.machine (set by the "CN=my.local.machine" when generating the cert), whereas the URL you're typing into your bar is localhost. Definitely not the same. Let's fix this! Move on to step 6.

Step 6: Match the URL to the certificate name

Open up the c:\windows\system32\drivers\etc\hosts file in a text editor. More info on the hosts file can be found here, but simple explanation is it allows you to map host names to IP addresses on your local machine. 

At the bottom of the file, add: 
127.0.0.1 my.local.machine

This will allow my.local.machine to resolve to the IP 127.0.0.1, which is the loopback address (read more here). 

We can test to ensure this is working by opening a command prompt (Win+r, cmd, <Enter>), and typing in ping my.local.machine. See how it resolves to 127.0.0.1?




Finally, head back to your browser and type in https://my.local.machine:port into the address bar, and that should eliminate any warnings and give you a nice, green https URL with a valid certificate. 


That concludes part 3 of this series. Keep this site set up, as in the future, we'll use this site to learn about client certificate authentication as well.