Exchange ActiveSync Building Blocks – Provisioning

Index for the series:
Exchange ActiveSync Building Blocks – Intro

Background reading (not a pre-requisite):
[MS-ASCMD] Common Status Codes
[MS-ASPROV] ActiveSync Provision Protocol Specification
[MSDN] Provisioning, Policies, Remote Wipe, and ABQ in Exchange ActiveSync

I hope you’ve all been following along and gained a deeper understanding of the Exchange ActiveSync protocol, and possibly had time to play with coding something yourself if you are so inclined. We should at this time be able to do the initial FolderSync with Exchange, and handle most errors thrown at us.

There are of course tons of things ActiveSync I haven’t covered yet, and it is a "one step at a time" journey.

If you’re testing against an Exchange Server where you do not have direct access to the admin console, and it is under the control of an Exchange admin who doesn’t permit just about anyone to sync you might have run into issues related to provisioning already, so the next step for us is to cover this very topic.

Provisioning is the mechanism which ensures that ActiveSync clients implement a given set of security policies. If necessary; Exchange Server will block devices that don’t implement the policy set.

Let’s first define a couple of terms:

The "Allow non-provisionable" setting
There is a setting called "Allow non-provisionable devices" in the “Exchange ActiveSync Mailbox Policy” properties that we have toggled on and off a couple of times now. The definition of non-provisionable device is an ActiveSync client which is not able to apply policies to the device.

This comes in two flavors – devices that do not support provisioning at all, and devices that do support policies, but not the specific policies you want to apply. (For instance a commonly unsupported policy is "Encryption".) The device might not serve up an understandable explanation why it will not sync, and Exchange might just say non-provisionable, but the difference can be seen by sniffing the traffic between the device and Exchange.
A provisionable device will request that the server sends down the policy, and will reply with a yes/no to each setting, whereas a non-provisionable device will not request the policies at all.

The corollary to this is that a provisionable device is one that not only accepts policies in general, but also the settings specific to your Exchange Server.

This means that whether you can call a specific device provisionable or not can only be seen in combination with your environment. (If we want to get nitpicklingly technical we could say that Windows Mobile 6.1 and 6.5 are the only "true" provisionable devices as they are the only devices that support all policies.)

If you check the "Allow" switch this means that all devices will be able to sync regardless of whether they support the policies or not. But a device which indicates itself as provisionable will request the policies and implement as many as it can even when it is not forced to do so. If you allow all devices the content of this article will be purely an academical exercise for you, and you’ll be able to sync as shown in previous code samples. You can still tag along if you find it interesting nonetheless of course Smile

There are differences between Exchange 2007 and Exchange 2010 how the server side details are handled, and I will primarily describe the 2010 way of doing it. (My EAS MD utility handles it for ActiveSync protocol version 12.0 – 14.1 so don’t worry – source code can be provided for your specific scenario.)

The way you tell Exchange that you are provisionable is to add a header to your web request;
"X-MS-PolicyKey = 0". (Not adding it meaning that you are not provisionable.)

After that the process goes like this:
– Exchange interprets the inclusion of the header as "Hey, here’s someone who supports policies", and then sends back a response which indicates which policies should be enforced, and the corresponding values. Exchange also includes a temporary value for the PolicyKey. (A value of 0 indicates you’re not provisioned yet, or want to start anew.)
– The device parses out the policy settings as necessary, constructs a response indicating the status for each of the policies, and adds the temporary PolicyKey to the response before sending it off to the Exchange Server.
– If (Exchange 2010 SP1)
   {
       supply additional information about yourself; 
   }
– Exchange checks that the temporary PolicyKey is valid, and if supplied stores the information supplied by the device in Active Directory. The server then responds with the final PolicyKey as an acknowledgement that the device is considering provisioned.
– The final PolicyKey should then be included by the client in every request onwards. If the ActiveSync policy is changed server side, or hits a refresh interval, the client will be instructed to reprovision. 
– Rinse & repeat 🙂

You will notice that as I have alluded to before, Exchange Server is not able to actually enforce these policies on the device. I can respond "I support all policies" knowing full well that I don’t support anyone of them. It’s a matter of trust basically. While it’s only in an initial phase, one of the objectives for the “Exchange ActiveSync Logo Program" from Microsoft is that devices which sports the logo are guaranteed to be obeying by the rules. Windows Mobile, Windows Phone, and iOS all play by the rules, and although I haven’t tried it out I’m guessing both Microsoft and Apple would hesitate to allow third-party ActiveSync clients that blatantly bypasses the policies in their App Store/Marketplace. For Android…Well, let’s just say I’ve seen ActiveSync clients that do not necessarily follow the protocol to the letter. (And how do you handle guys like us connecting from a desktop operating system?)

You could argue that I’m highlighting a weakness in the ActiveSync protocol, but MSFT has never claimed this to be a fireproof way of enforcing policies. It was just less clear what was going on behind the scenes before the protocol specifications publicly documented this in full detail. (Of course it was more fun implementing this without the specs the first time around.) If you are relying on Exchange to enforce policies, and let users bring whatever devices they can find, you should not be sitting comfortable during a security audit. While Exchange is a wonderful product it never was intended as a full-featured Mobile Device Management system. The devil is in the details, and those details should be handled by other software solutions dedicated to management of mobile devices. (As well as a policy document which is understood and agreed to by the user.)

That being said I think security policies in Exchange makes sense, and is a good idea in general. I’m just saying that you should be aware of what scenarios you are solving, and which scenarios you are not solving by configuring ActiveSync policies.

Ok, let’s get down to business. By now we have our "standard" FolderSync test app. This time I’ve re-introduced trusting all certificates, and added a checkbox called "Provisionable" that enables the provisioning process. The idea is that you should be able to attempt a sync and have it fail, (when Exchange does not allow non-provisionable devices), and the re-run it and fake the whole provisioning process. Should look roughly like this (for this test I did not allow non-provisionable devices):

image

Note: Exchange doesn’t always handle things correctly when a given device ID changes between the two states so you might have to delete the device from OWA between tests. (You could also change the device ID, thus creating a new device, but for that you’ll have to modify the code since I have hardwired it.)

There’s some code to go along with it. Actually a little over 350 lines of code in my not entirely optimized C# so I’m not going to include it all here. (Check the downloadable files section for this.) But the first try-catch illustrates some key concepts:

try
{
   Stream sw = webRequest.GetRequestStream();
   sw.Write(postBytes, 0, postBytes.Length);
   sw.Close();
   WebResponse webResponse = webRequest.GetResponse();

   if (webResponse == null)
   {
   }
   txtOutput.Text += "Requesting temporary policy key ";

   StreamReader sr = 
   new StreamReader(webResponse.GetResponseStream());

   string responseBody = sr.ReadToEnd().Trim();
   Byte[] byteResp = utf8Encoding.GetBytes(responseBody);
   Byte[] polKey = new Byte[14];

   int intRecBytes = 0;
   bool recBytes = false;
   char chrPolKey;
   string hexStrResp = "";

   //to get the temp key we loop the array, 
   //and "record" only the necessary bytes
   for 
   (int loopCounter = 0; loopCounter < byteResp.Length; loopCounter++)
   {
      hexStrResp = byteResp[loopCounter].ToString();
      chrPolKey = (char)byteResp[loopCounter];

      //set recording on when finding the start character
      if (chrPolKey == 'I')
      {
         recBytes = true;
      }
      //end recording when finding the end character
      if (hexStrResp == "1")
      {
         recBytes = false;
      }
      //record the temp policy key
      if (recBytes == true)
      {
         polKey[intRecBytes] = byteResp[loopCounter];
         intRecBytes++;
      }
   }

   for (int loopTmpPolKey = 1; loopTmpPolKey < 13; loopTmpPolKey++)
   {
      postBytesFinal[loopTmpPolKey + 38] = polKey[loopTmpPolKey];
   }

   txtOutput.Text += "\r\n";

}
catch (WebException ex)
{
   ex.ToString();
}

I haven’t implemented decoding of WBXML here. I just loop through the response body knowing what characters to look out for as the start and end of the key.

When I have the temporary key I do a similar loop with a new web request and parse out the final key:

char[] finalKey = new char[14];
strPolicyKey = "0";

for (int loopTmpPolKey = 2; loopTmpPolKey < 13; loopTmpPolKey++)
{
   finalKey[loopTmpPolKey] = (char)polKey[loopTmpPolKey];
   //we need to filter out the escaped zeroes
   if (finalKey[loopTmpPolKey] == '\0')
   {
      strPolicyKey += "";
   }
   else
   {
      strPolicyKey += finalKey[loopTmpPolKey];
   }
}

txtOutput.Text += "Policy Key: " + strPolicyKey + "\r\n";
txtOutput.Text += "\r\n";

The WBXML I use for the second web request has a long sequence of zeros which are replaced by the policy key, and the rest is “ACK policies”:

byte[] postBytesFinal = 
   new byte[60]{03,01,106,00,00,14,69,70,71,72,03,77,83,45,69,65,
   83,45,80,114,111,118,105,115,105,111,110,105,110,103,45,87,
   66,88,77,76,00,01,73,00,00,00,00,00,00,00,00,00,
   00,00,00,01,75,03,49,00,01,01,01,01};

After that I can just add the PolicyKey to my headers before I do the actual FolderSync command:

if (chkProvisionable.Checked == true)
{
   string strPolicyKey =
   Provision(strUsername, strEncCredentials, strServerAddress);
   webRequest.Headers.Add("X-MS-PolicyKey", strPolicyKey);
}

You will need to read all the code to get the bigger picture here, but I hope you understand the algorithm even without going into all the details Smile

You might say that this isn’t very clean code, and that it looks kind of sloppy. As I have said before this isn’t a neat and tidy coding class at all times. It doesn’t have to scale in a scenario where it’s used for diagnostic purposes only.

I also left out the part that makes it 2010 SP1 compatible above, but it feeds in some data about the device, and as you can see from OWA Exchange is very convinced that we are provisionable all the way:

image

The beauty is that while I’m supposed to answer yes and no to each setting in the policy it is possible to give a wildcard “yes” response, and for the purposes of this exercise I don’t pay any closer attention to what the settings actually are.

I don’t know about you, but I think this has a certain coolness factor to it. It’s not like we’re “hacking” Exchange or anything, but bypassing security policies still feeds the satisfaction of your inner black hat Smile

Downloads:

C# Source – Provision.cs

C# Source – EAS_BB_Part-05_01.zip

5 thoughts on “Exchange ActiveSync Building Blocks – Provisioning”

  1. Thanks for the great tutorial.

    I am wondering if there is an API that we can use to CREATE mailbox policies? There are PowerShell cmdlets that do, but I am looking for an API.

    Thanks!

  2. I am not aware of any APIs for this purpose. There are the Exchange Web Services, and the EWS Managed API which is basically just a wrapper for the web services.
    If you are on the same domain as the Exchange Server you can do remote Powershell, if not you might have to do a wrapper for Powershell and expose as a web service.
    Not a very neat approach I suppose, but I can’t think of any other means right now (if anyone else has ideas shout them out).
    On the other hand – unless you’re changing policies frequently is there a particular reason it cannot be done in the management console?

  3. Andreas,

    Supercool tutorials man! You have no idea how much you have helped me. Can you do an example for an actual ping to the exchange server. There is Zero info on this stuff. and the Proto docs barely even mentions it , ironically its the engine making instantly syncing possible.

    If you can send me an XML sample for the ping request it would be great. I am confused on the folder id stuff. Keep getting a #3 error for the PING cmd.

    Thanks in advance,
    Dean

  4. This has actually been on my to-do list for a while 🙂
    That is, I don’t have a complete post on it yet, but I’m intending to look into it real soon.

Leave a Reply

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

*