Exchange ActiveSync Building Blocks–Warming Up

Index for this series of posts can be found here:

Exchange ActiveSync Building Blocks – Intro

Following up on last week’s premise of delivering some Exchange ActiveSync protocol hacking I thought I’d get it semi-started with covering code common to later articles.

My language of choice will as stated be C#. I know you can do this stuff in Java, PHP, and whatnot, but I had to make a decision as to what I would be using and C# felt natural. I will be writing code compatible with .NET 3.5 unless something else is indicated. (For instance if I run into a feature which requires .NET 4.0.)

You can assume I have included the following .NET classes in the code:

using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

Skip System.Windows.Forms if your hacking it from a console app.

With the risk of repeating myself, (actually it’s not just a risk, but an actual re-run), communication from an ActiveSync client is all done through HTTP POST to a defined server address.

This address will usually be in the form of https://FQDN/Microsoft-Server-ActiveSync.

You can run it over plain HTTP as well, and as I’ve said before this is easier when debugging your coding attempts. This doesn’t really affect the code other than how you build up the address though. Note, however that the SSL certificate must be trusted by the device. (When running it on your Windows desktop it will use the regular certificate store.)

If you want to skip verification of certificates, and just trust them all you need to insert the following code snippet in your app:

System.Net.ServicePointManager.ServerCertificateValidationCallback =
delegate(object sender2, X509Certificate certificate, X509Chain chain, 
SslPolicyErrors sslPolicyErrors)
{ return true
;};

Of course if you want to make it more of an exercise for yourself you can parse out the reason the certificate fails, and handle this accordingly. (For instance failing to trust the issuing certificate authority is different than say incorrect date and time settings triggering a condition where the certificate points to a date three years in the future.) I’ll leave that as an exercise for the reader.

Authentication is something that also comes along quite naturally whether you like it or not. When using Basic HTTP authentication it’s just a matter of adding a header called Authorization:

Authorization Basic domain\user:password

The username and password is actually base64-encoded so it needs a couple of lines of code to get right. And since every web request needs authentication, you should split it into dedicated methods, rather than doing it as part of building up the request.

If you’re using domain\username format:

private string getEncCredentials

(string username, string password, string domain)

private string getEncCredentials (string username, string password, string domain) { string strDomain = domain; string strUsername = username; string strPassword = password; string strRawCredentials = strDomain + "\\" + strUsername + ":" + strPassword;   //Need to base64 encode the credentials System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); Byte[] byteSource = encoding.GetBytes(strRawCredentials); string strEncCredentials = System.Convert.ToBase64String(byteSource); return strEncCredentials; }

If you’re using username@domain format:

private string getEncCredentials

(string emailaddress, string password)

private string getEncCredentials(string emailadress, string password)
{
   string strEmailAddress = emailadress;
   string strPassword = password;

   string strRawCredentials = strEmailAddress + ":" + strPassword;

   //Need to base64 encode the credentials
   System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
   Byte[] byteSource = encoding.GetBytes(strRawCredentials);
   string strEncCredentials = System.Convert.ToBase64String(byteSource);

   return strEncCredentials;
}

You don’t have to support both styles, but if you want Autodiscover to work that requires the second method. (And you will basically want to have both of them available anyways.)

As for the actual web request it comes in different forms (depending on which headers you need to add for your specific request, but in it’s basic form it works like this:

HttpWebRequest webRequestOptions =    
(HttpWebRequest)WebRequest.Create(uri);

webRequestOptions.Method = "OPTIONS";
webRequestOptions.Headers.Add("Authorization", "Basic " 
+ getEncCredentials(username, password, domain));

try
{               
    WebResponse webResponse = webRequestOptions.GetResponse();
    if (webResponse == null)
    {
    }
    //No body, but we parse out the return headers
    int optionsHeadersCount = webResponse.Headers.Count;
    for (int i = 0; i < optionsHeadersCount; i++)
    {
        output += webResponse.Headers.Keys[i].ToString() + ":" +         
webResponse.Headers.Get(i).ToString() + "\r\n";
    }   
}
catch (WebException ex)
{
    //Do nothing in dummy code
}

I’ve illustrated the OPTIONS command that you should perform before establishing the synchronization relationship. This makes it possible for the ActiveSync client to establish which version of Exchange Server we’re dealing with, and adjust it’s expectations accordingly. (If you’re connecting to Exchange Server 2007, it doesn’t really help you that your client supports Exchange Server 2010 SP1.)

Some details are left out here – there’s no interaction with a UI or anything in these snippets. I will of course build out this code to be working code in later samples. But you may assume I’ve got some of this code behind the scenes even if it is not present in the code snippets I post.

I know this was a short post, with nothing really ready to compile, so let’s just call it setting the stage for things to come. The next article, which will contain a more feature complete sample, is right around the corner. Until then you can fire up your Visual Studio and make sure your Exchange Server is ready.

One thought on “Exchange ActiveSync Building Blocks–Warming Up”

Leave a Reply

Your email address will not be published. Required fields are marked *

*