Tuesday, 9 August 2011

Oh, no, it's another certificates post

I came across a puzzling issue yesterday. I was trying to export a certificate as PFX file but I couldn't. The option to export the private key was greyed out and there was a little message informing me that The associated private key cannot be found. Only the certificate can be exported, see screenshot below.


This turns out to be yet another file permissions issue. When you make a certificate request from IIS, the private key is stored as a file in this directory C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys and Administrators as well as the System need to have Full Control of these files, if this is not the case you will get the issue above.


To compound the issue, if you have processed the request, rather than simply installed the certificate, it seems that you are past the point of no return and you need a new certificate request, which should be trivial, but in some places it seems to involve loads and loads of paperwork. I've not actually tested this, but read about it here.

It's a self signed world. The joy of certificates - Part 2.

The easiest way to get started with the certificate thingy™ is to use self signed certificates. In essence, a self signed certificate is a certificate that has been signed by the issuer, so there isn't a third party, a CA, ascertaining the certificate's bona fides. The most common use is for testing, but it can also be used in a production environment, although this is unusual, it could be a sensible choice for communication between two units within a company, for instance.

I have used makecert.exe, which is available with Visual Studio or downloading the Windows SDK, I'll try to do this process with openssl, which is a little less unwieldy than Visual Studio :).

The process is also rather involved and laborious, but at some point one has to say enough is enough and get on with it. There is no point in spending three days looking for a solution that will save 5 minutes for every project.

At any rate, here are the steps needed to create a self signed CA, Server and Client Certificate using the makecert tool, install the server certificate for a website and set up client certificate mapping.

1. Create CA. Note that you can change Root to my, if you don't want this Authority to be installed on the local computer Trusted Root Authority store.

makecert -pe -n "CN=SelfSignedCA" -ss Root -sr LocalMachine  -a sha1 -sky signature -r "SelfSignedCA.cer"

2. The certificate should be installed in your Trusted Root Authority store. In order to install it to another server, just follow the instructions on step 5 to export a personal information exchange file and step 10 for instructions on how to install it.

3. Create Server Certificate. Make sure that the CN entry is correct for your server, as otherwise your browser will complain.

makecert -pe -n "CN=servername.dev.com" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1  -in "SelfSignedCA" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 ourserver.cer

4. The ourserver.cer certificate is installed at the same time as it is created:


5. Export ourserver certificate as a personal information exchange file (pfx) with private key. From the certificate Console, see this link.

.

6. Install the exported pfx file(servername.pfx) as a website certificate. From the IIS manager console (Run inetmgr)


7. Create client certificate and install it to the personal store of the computer account (Local Machine)

makecert -pe -n "CN=myclient" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.2 -in "SelfSignedCA" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 myclient.cer

8. Use client.cer to set up the client mapping.

9. Repeat step 5 to export the client certificate as a personal information exchange file.

10. Install myclient.pfx to the client computer (Assuming that in step 9 you called it myclient.pfx). Double click on myclient.pfx

Make sure you select yes on this last step

That is it, you should now be able to use client certificates to authenticate to your website. In fact, you can remove any other form of authentication, so that only client certificates are used, like so:

So now, when you try to access the secure website, using IE, you'll see this prompt (if you don't then your client certificate has not been installed properly):


Monday, 1 August 2011

The joy of certificates - Part 1

We have a big project going into Operation Acceptance Testing and one of the things that the project, in its ∞ wisdom, has decided to leave for the last minute is, to get SSL/TLS working. This would not necessarily be a big problem if it wasn't for the fact that there still are a lot of questions about the application's architecture, in particular with respect to SSL. I won't go into details because I don't want to get into rant mode.

At any rate, there is a lot of FUD regarding cryptography, so I thought I would try to clarify things a little bit, more for my own understanding that anybody else's really.

What is a certificate?

A certificate is generally a public key, which in essence is a very long prime number, normally stored in base 64. Some certificate formats, such as pkcs12, also store the private key, which again is a very long prime number.

Certificates also contain metadata, which might tell you what the certificate has been designed for, e.g. Client or Server authentication, key length, expiration dates and so on. The key thing to remember is that the metadata does not really do anything. It's a bit like a label on some food packaging. The label might say that it has expired but you can chose to eat it.

The take away point is that, the way certificates are dealt with is implementation dependent. Let me repeat it for emphasis (in bold this time), the way certificates are dealt with is implementation dependent. Your browser will complain if you visit a SSL/TLS page that is not signed by a known CA, but your own app can choose not to implement a warning, ditto for expiry dates etc...

To repeat myself, a certificate is a very long prime number (public key) and might also contain another long prime number (private key).

Should we HTTPS?

HTTPS is based on SSL/TLS and its main purpose is two-fold:
  1. Ensure the identity of the website being visited.
  2. Ensure that browsing is encrypted.
The first is accomplished by a Certification (or Certificate) Authority that signs the server certificate. There is an implied trust on these CAs. In other words, you are assuming that the CA is trustworthy and will only issue legitimate certificates to its legitimate owners, so that if I say to Verisign or Entrust, Can you please issue a certificate for a domain called www.hsbc.co.uk to me manyrootsofallevil? They'll want to make sure that I actually represent HSBC and I'm not just trying it on, so that I can get unsuspecting HSBC customers to provide me with their login details.

Encryption works by using a secret session key. Diffie-Hellman or a similar scheme is normally used to exchange the keys and arrive at this shared, secret, session key that can then be used to symmetrically encrypt the communication or browsing in this case.  There is more to it that this though, as the client and server need to agree on SSL protocol, compression methods, etc.. The whole process is called a SSL or TLS Handshake and at the end of it we end up with a secure communication between a server and a client.

In other words, HTTPS is based on Public Key Infrastructure.

A bit of theory done, we can now look at how this certificate thingy™ works in practice, after all you know what they say:
In theory, there is no difference between theory and practice. In practice, there is.

Friday, 29 July 2011

Load Balancing in MS Dynamics CRM

In its infinite wisdom Microsoft decided to make my life harder by making it MS Dynamics CRM not work out of the box with a load balancer and I'm not talking about Microsoft software based network load balancing although it would apply too, if memory servers right, but a proper hardware based solution, which if again, memory serves me right, it's a Cisco 11506, but that is by the by.

In a normal load balancing situation, you would want a DNS entry for your load balancer's VIP and you would direct your clients to that VIP, so far so good. The problem is that there is a few pesky rows in the DeploymentProperties table in the MSCRM_CONFIG database
ADSdkRootDomain
ADWebApplicationRootDomain
The NvarCharColumn for these rows is, by default, set to the first server in a deployment, which is all well and good if you have a single server in your deployment, but the minute you add another server you are creating a single point of failure, because if the first server goes down, down goes your application. In actual fact it won't come down until the app pool gets recycled if I remember correctly. It will also refuse to start if the first server is down.

In the three+ years since we encountered this problem, it seems that this is all now clearly documented, I should've done a search in google before I wrote all this, oh well.

Note that some people have reported that this setting also needs changing, I guess it depends on whether or not you are using asynchronous plugins, which we don't.
AsyncSdkRootDomain

C# Interview questions -- part 2

Following from my previous post, the last question I had was a MS Dynamics CRM question, which I did not get around to do. Essentially the problem was to create an entity called maet (team backwards) and another one called tluser (result backwards), you can see where this is going, to keep track of match results.
  • Maet had to have a name attribute only, the name of the maet.
  • Tluser had to display two maets and had to have a score attribute for each team and a result attribute (actually, I think it was a tluser attribute, but you get the picture).
The final task was to create a plugin, which I have forgotten what it was meant to do.

The only "tricky" thing here is what relationships are needed. Each tluser needs to show in its form two maets, thus we need to create two N:1 relationships between tluser and maet, in other words each maet can belong to N tlusers, which makes sense if you think about it. Each team is going to have several results, for each match it plays. As a rule of thumb the 1 entity shows up in the form of N entity (this is different for native N:N relationships, but I won't go into them).


Note that these relationships show as 1:N in the maet entity, as below.

At any rate, this is what I would have done, had I had the time to do it in. (Yes, I know it can be prettified, but that takes time).


There are loads of pitfalls with the way this is done, e.g. you could set both maets to be the same, or the result to field to be meaningless, but with a bit of time all of this can be sorted.

Tuesday, 26 July 2011

C# Interview questions -- part 1

I had a couple of interviews a few weeks ago and I thought I would share the technical questions that I was asked here.

I was not really impressed at being asked theoretical questions about object oriented programming, perhaps because I struggled with the answers, not because I did not know what the concepts were, or how to use them, but because I couldn't recall what they were called, I'm looking at you encapsulation. You might be reading this and thinking he doesn't have a clue, and you'd be right, but think about it like this. You don't need to know what method overloading is actually called, you just need to know that can have methods with the same name as long as you change something , e.g. number or order of arguments or return type, at any rate. Rant over, let's get on with it.

Can you explain what a class is? Class
Can you explain what encapsulation is?  Encapsulation
Can you explain what inheritance is? Inheritance
Can you explain what a design pattern is? Design Pattern
Can you explain what Database normalization is? Database normalization

Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz". This is straight from this post.

Write a program that prints the reverses the words for the following sentence "the quick brown fox jumps over the lazy dog".

Write a program that prints the fibonacci sequence (i.e. 1,1,2,3,5,8 ...):
  1. Any method is available (i.e. use recursion)
  2. Do not use recursion.
I know it is possible to do step 2, I have done it, see below, but in a interview situation, I simply could not do it.

   1         public static long fibiter(long number)
   2         {
   3             long fTerm = 0, sTerm = 1;
   4                         
   5             for (int i = 0; i < number; ++i)
   6             {
   7                 long temp = fTerm;
   8                 fTerm = sTerm;
   9                 sTerm += temp;
  10             }
  11                         
  12             return fTerm;
  13 
  14         }

Friday, 22 July 2011

Pure Lunacy or Sheer Genius, You Decide.

I've been doing a code review for a new Microsoft Dynamics CRM 4.0 based application that is coming in and today I found the method below:


   1 
   2     [WebMethod]
   3     public string Engaged(string oId, string strValues)
   4     {
   5         try
   6         {
   7             LogEntry("TRACE", "WebService : Engaged", String.Format("Start: Call oId: {0}, strValues: {1}", oId, strValues));
   8             call outcall = new call();
   9 
  10             CrmBoolean boolean = new CrmBoolean();
  11            
  12             String engagedValue = strValues.Substring((strValues.Length - 3), 2); //Request.QueryString["oId"].Substring((Request.QueryString["oId"].Length - 2), 2).ToString();
  13             if (engagedValue == "No")
  14             {
  15                 boolean.Value = true;
  16             }
  17             else
  18             {
  19                 boolean.Value = false;
  20             }
  21             LogEntry("TRACE", "WebService : Engaged", string.Format("1. Set Call Engaged Status to {0}.",boolean.Value));
  22             outcall.engaged = boolean;
  23 
  24             Key key = new Key();
  25             key.Value = new Guid(oId); 
  26             outcall.callid = key;
  27 
  28             LogEntry("TRACE", "WebService : Engaged", "2. Update Call record");
  29             crmservice.Update(outcall);
  30 
  31              LogEntry("TRACE", "WebService : Engaged", "Return: All Done.");
  32 
  33             return "";
  34         }
  35         
  36         catch (Exception e)
  37         {
  38             LogEntry("ERROR", "WebService : Engaged", string.Format("Error in Engaged Engaged.  Exception {0}.", e.ToString()));
  39 
  40             return e.ToString();
  41         }
  42     }

This method gets invoked with a isv button on the home page. Call here is actually a custom entity.  oId contains the Call guid and strValues, I was not prepared for this, contains a string that is generated like this:

   1 if (document.all.crmGrid.InnerGrid.SelectedRecords.length > 0)
   2 {
   3 var url = "/WebService.asmx/Engaged";
   4 var oXmlHTTP = new ActiveXObject("Msxml2.XMLHTTP");
   5 oXmlHTTP.Open("POST", url, false);
   6 oXmlHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
   7 oXmlHTTP.Send("oId=" + document.all['crmGrid'].InnerGrid.SelectedRecords[0][0] +"&strValues=" + document.all['crmGrid'].InnerGrid.SelectedRecords[0][3].innerText);
   8 document.getElementById('crmGrid').Refresh();
   9 }

Oh, yes we are screen scraping, in our own App, for which we have full control over everything, a perfectly good SDK and is actually all hosted within the same datacentre and inside a secure network, accessed by a single company.

You might be inclined to think that this is a response to a very slow network and that by skipping a call to the database to get the Call instance that we are updating, we might make the user experience better. I would be willing to concede on this point, if it wasn't for the rest of the code that makes calls to the database with careless abandon.

I won't even go into returning an empty string, how the entity has different views (some of which don't contain the engaged attribute) or the fact that if it fails the user is not notified in any way.

So what do you think, Pure Lunacy or Sheer Genius?

Monday, 18 July 2011

NTP -- Synchronize time using other NTP peers

Let's start by configuring an NTP server. You can install the ntp server with:
yum install ntp -y
Make sure that it starts on system start up:
chkconfig ntp on
Open the firewall and save the changes:
 iptables -I INPUT -p udp --dport ntp -j ACCEPT; service iptables save
Edit the ntp config file /etc/ntp.conf and add the following line:
restrict 10.168.20.0 mask 255.255.255.0 nomodify notrap
This will allow any client in the 10.168.20.0 network to get its time from the ntp server, except that it does not quite do it for me, as I don't have an internet connection. This is because a local server is way down in the pecking order or stratum, so a few extra steps are required:
echo "10.168.20.227" >> /etc/ntp/step-tickers
echo "10.168.20.227" >> /etc/ntp/ntpservers
Assuming that 10.168.20.227 is the ip address of your ntp server. You can now start your ntp server with:
service ntpd start
Interestingly, there are no SELinux settings related to ntp and you can block hosts by using iptables rules.

In order to configure a client to use this ntp server, simply add the following line to the ntp config file of your server:
server 10.168.20.227
Set the ntp daemon to start at boot time and start the service:
chkconfig ntpd on
service ntpd start
You can now use the following command to check the configuration is working:
ntpq -p
which should have a result like this:

          remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 10.168.20.227   LOCAL(0)        11 u   45   64    1    0.479  263675.   0.000

Sunday, 17 July 2011

SSH -- Configure additional options described in documentation

How long is a piece of string?

All I can say about this objective, is that you had better familiarize yourself with the SSH daemon config file (/etc/ssh/sshd_config) and the manual pages (man sshd & man sshd_config) as well as the ssh client config (/etc/ssh/ssh_confg) and manual pages (man ssh & man ssh_config).

Saturday, 16 July 2011

SSH -- Configure key-based authentication

This is actually a fairly simple objective. The default configuration is to accept key-based authentication, note this line on the /etc/ssh/sshd_config file:
#PubkeyAuthentication yes
Although the line is commented out, this is actually the default and as such does no need to be explicitly stated, if you wanted to prevent key based authentication, just add this line:
PubkeyAuthentication no
At any rate back to the objective. On the client, issue the following command, and follow the instructions, to generate a key:
ssh-keygen
Note that you don't actually need to add a passphrase, just press enter. This will allow you to login without being prompted for a passprhase.

The last step is to copy the public key that you have just generated to the server you want to login to:
ssh-copy-id  user@<servername>
That's it, if you did not provide a passphrase, you should be able to login with:
ssh user@<servername>
Note, that both ssh-keygen and ssh-copy-id have several options and that you should study them to see what they do.

I guess that in the exam you could be asked to install ssh, even if it does get installed by default. At any rate, just issue the following command:
yum install openssh-server -y
You should then make sure that it is set to run at boot time:
chkconfig sshd on
You can allow ssh traffic through by opening port 22:
iptables -I INPUT -p tcp --dport 22 -j ACCEPT; service iptables save
Depending on your configuration, you might need to change SELinux settings. You can check the SELinux settings like this:
getsebool -a | grep ssh
Finally, you can limit the users that can login by using the DenyUsers directive in the  /etc/ssh/sshd_config file like so:
DenyUsers naughtyuser
Remember to restart the daemon after any changes:
service sshd restart
If you want to prevent hosts from accessing SSH, you can do it by using iptables rules, e.g.:
iptables -I INPUT -p tcp --dport 22 -s 10.168.20.233 -j DROP; service iptables save
I think this pretty much covers this objective.