Getting OMA CP right by Windows Mobile

Regular readers of this blog, (although I don’t rank on the Google 500 index I believe there are at least some people out there feeding off my rss), may be tempted to believe I’m playing my records on repeat when I bring up even more OMA, and yet again mentioning Windows Mobile in the same sentence. But previously I’ve only briefly mentioned some of the challenges involved. This time I thought I’d try and tackle some of these challenges. Maybe even solve a few :)

Ok, quick recap. OMA CP can be used to configure devices by sending SMS messages to them. But a lot of people have been struggling getting this to work on Windows Mobile. And since OMA CP is often used for setting up an OMA DM relationship that hasn’t really taken off on WM either. (Which does make it extra interesting that a product like System Center Mobile Device Manager from Microsoft uses OMA DM as it’s MDM engine.)

Read previous posts for more background info:
http://mobilitydojo.net/2008/10/10/whats-this-oma-dm-thingy-all-about/
http://mobilitydojo.net/2009/05/07/oma-dm-one-step-at-a-time/

So, with all the wonderful MDM platforms out there why spend time over this particular feature? Well, while I’ve previously explained why I don’t consider SMS messages a good method for continous MDM I do see how it might help in a couple of very specific scenarios:

  • Initial client deployment
  • Remote wipe
  • Out-of-band communications channel for when you want to send credentials or something in separate channels.

I’d like to get one particular disclaimer out of the way first; I’m testing on Windows Mobile 6.1. I know that things are different of Windows Mobile 5.0, and possibly things described here will not work on those devices. WM 6.0 is similar to 6.1, and identical on many levels, but I’m not making any guarantees. WM 6.5? Haven’t tested it yet. I tested the HTC X7510 and HTC Touch Diamond 2 so it’s not a large sample pool I’ve tested with. (Lesson to take away - don’t trust anything until you have tested it on your particular device.)

This complexity has helped build a common misconception that OMA CP and OMA DM doesn’t work on Windows Mobile at all, and that MSFT are trying hard not to follow standards. And you’ll often observe that when seeing those annoying ring tone commercials they’ll list a plethora of different devices that are supported, but Windows Mobile is usually absent from that list. (OMA CP are often the basis for triggering download of content.) But at the same time you find references to OMA CP all over the MSDN documentation regarding the Configuration Service Providers. What gives?

Since Windows Mobile was designed primarily with the enterprise market in sight security was not an afterthought. Trust is a major concern in different aspects of the OS. You cannot install an unsigned application without being prompted that you acknowledge the installation. With a two-tier lock level on the device you may not even be able to install unsigned apps at all. If you want to synchronize with an Exchange server using SSL you need to trust the issuer of the SSL certificate. It kind of follows that bytes received from the Internet are not necessarily considered trustworthy either. So when receiving binary SMS messages containing configuration the device pays special attention to these (as opposed to a regular text message). If I send off random configuration messages to random devices these should not consider me trusted under most circumstances. In a very sane manner the logic states that to be able to perform configurations you must be trusted by the device. Who gets to define this trust, you say in a paranoid manner?

Nokia devices (and a whole lot of other manufacturers too of course) are simple in the sense that if you buy a Nokia it is a Nokia. With a Windows Mobile device the logo might say HTC, or Samsung, or xyz. And an HTC device might be branded to an operator like Orange, T-Mobile, etc in addition to the “straight” HTC models. Microsoft didn’t want to go into the hardware business with Windows Mobile, and that’s ok, but in the process they left a couple of implementation details to other players, while providing the overall design and guidelines from Redmond. At this point the concept of security roles, and security policies comes into play. Depending on what the policy definitions say on the device, different roles get to perform different things to my device.

For a primer on the security roles you should skim through:
http://msdn.microsoft.com/en-us/library/bb416273.aspx

And the relevant security policies:
http://msdn.microsoft.com/en-us/library/bb737247.aspx
(The interesting policies being: 4104, 4105, 4108, 4109, 4110, 4111, 4113, 4121, 4124, 4132, 4141, 4142 & 4143)

Now, this all makes sense. If I initiate something on the device it’s trusted. If I initiate something on the server side it may or may not be trusted. Orange devices have been “tampered with” so that the software certificate of Orange is preinstalled on the device. The SMSC of Orange is defined as a Trusted Provisioning Server. Pretty much all Qtek devices I saw in the European markets had Brightpoint and Dangaard root certs preinstalled. (Editor’s note: this would be the distributor of the non-operator branded devices.) Which means that whoever made the device available for me as a consumer had all the necessary rights to do whatever they want to my device. Which is nice. For them that is. Different models, and ROM builds, may have different settings. MSFT provides some default values, but the OEM is free to change the defaults. As a reference this is a registry snapshot of the emulator:
HKLM\SECURITY\Policies\Policies
Policies

(Values in hex, convert to decimal to line up with the SecurityPolicy DDF on MSDN.)

So how do I get the server initiated config to be trusted when I am not in a position where I get to decide the contens of the OS ROM? (I accept that MobilityDojo.net being a one-man operation does not have that power yet.) Finally we are getting to the point of the matter.

There’s disabling trust checking as much as possible on the device. I don’t know if all the checks can be disabled though. It would require you to touch the devices too, so while you’re at it you would probably be better off just enabling the trust relationship. And if you have access to touch every device before the user gets it there’s really not many limits to what you can do. But we want “zero touch deployments”.

A better solution would probably be to send the trust request in the first OMA CP message, have the user accept it interactively, and then you should be able to do your stuff. Let’s try that approach. A quick copy-paste from MSDN (msdn.microsoft.com/en-us/library/ms889523.aspx), and a minor adaptation, and we end up with the following xml:

<?xml version="1.0"?>
<!DOCTYPE wap-provisioningdoc PUBLIC "-//WAPFORUM//DTD PROV 1.0//EN"
"http://www.wapforum.org/DTD/prov.dtd">
<wap-provisioningdoc>
  <characteristic type="BOOTSTRAP">
    <parm name="PROVURL" value="http://www.mobilitydojo.net/TPS" />
  </characteristic>

  <characteristic type="PXLOGICAL">
    <parm name="NAME" value="WAP Push Gateway"/>
    <parm name="PROXY-ID" value="10.10.10.10"/>
    <parm name="TRUST"/>
    <characteristic type="PXPHYSICAL">
      <parm name="PHYSICAL-PROXY-ID" value="Push Gateway 1"/>
      <!-- The push gateway's SMS address -->
      <parm name="PXADDR" value="1234"/>
      <parm name="PXADDRTYPE" value="E164"/>
      <parm name="PUSHENABLED" value="1"/>
      <parm name="TO-NAPID" value="SMS NAP"/>
    </characteristic>
  </characteristic>

  <characteristic type="NAPDEF">
    <parm name="NAPID" value="SMS NAP"/>
    <parm name="NAME" value="SMS Connection"/>
    <parm name="NAP-ADDRESS" value="1234"/>
    <parm name="BEARER" value="GSM-SMS"/>
  </characteristic>
</wap-provisioningdoc>

A couple of pointers:

Type whatever you like in the dns name. (Apparently this does not matter as long as you’re only doing pushing from the server. If the device is to connect back to fetch data it probably would matter.)

The phone number is whatever you define as the from address in your Kannel. So once you bootstrap a device you should stick to the same phone number. It does not have to be an actual phone number, and the fictitious “1234″ above should work.

To test the procedure I sent out the following xml to disable WLAN (this one also requiring the user to accept it just be sure while testing):

<wap-provisioningdoc>
  <characteristic type="NetworkPolicy">
    <characteristic type="WiFi">
      <characteristic type="Settings">
        <parm name="Disabled" value="1"/>
      </characteristic>
    </characteristic>
  </characteristic>
</wap-provisioningdoc>

Hey, ho, that works!

Here’s a few screenshots showing it device side:

Accepting the message.

Userpin

You’ll get a message in the SMS inbox saying that the config was applied.  
ConfigAck

Oh, yeah, maybe I should add a few lines regarding what I’m doing in Kannel as well. OMA CP for Windows Mobile works much the same way as for the Nokia I used for my previous test runs. Do an HTTP GET against http:/kannel:13000/sendota?etc. I use “userpin” for authentication here. You cannot bootstrap without a security mechanism. What’s the difference between userpin and networkpin you say? (If you’ve read some of the MSDN links content that is.) Userpin is a code you define, and the user has knowledge of. For instance the user is provided with the pin 1234 in a separate text message sent first, or provided on a self service portal. The network pin is not readily available as this is the IMSI of the SIM card (on GSM devices, on CDMA it’s the ESN). The IMSI can be acquired programatically, but that’s usually the only way you’re going to get it. Most SIM cards have a long number printed on them, and while that is an identifying number it is usually not the IMSI. If you are the mobile operator you can do a database lookup inputing either the phone number or the IMEI of the device, but for some reason the mobile operators usually don’t expose an API for this to the general public :)

The bonus of the network PIN is that it will let you do further actions silently, and without user interaction. (I had some problems with this. I managed to get the device to accept the message without prompting the user, but for some reason it wouldn’t accept the settings. Haven’t looked further into why this isn’t working.)

With OMA CP in place you should probably be able to bootstrap the OMA DM server too. Haven’t tested it yet though. Let me know if it’s of interest - I have no idea if these Kannel related articles are playing to an audience of more than a few geeks with similar niche interests :)

Pushing Them OMA CP Messages With Kannel

While it was fascinating to be able to send SMS in a number of ways it’s time to step it up a notch. Kannel is still the main topic and we’ll be looking at OMA CP (Client Provisioning) today, also sometimes known as OTA (Over-the-Air). I’ve previously mentioned that there are a number of standards under the OMA parent protocol, and the provisioning protocol is a good starting point. (For an introduction: What’s This OMA-DM Thingy All About?)

OMA CP is typically used for configuring APN settings, MMS settings and similar on a number of devices. It does not have to be what we refer to as “smartphones”, and work well on simpler phones as well. You’ve probably run into it if you’ve ever visited a mobile operator’s web site to configure your device by entering your phone number and receiving a text message that magically configures the relevant settings for you. But if you have some custom settings the generic web page might not be of help. So like so many other things - you can do it yourself :)

We’ve already got a Kannel server running, but while testing OMA CP I discovered that it wasn’t entirely smooth sailing to get working with what we’ve installed so far. The short story is that you need to compile in support for OpenSSL in your kannel files, and you need to be running Kannel 1.4.1 (as opposed to the newest build which is 1.4.3 as of the present time.) The long story is that SSL is required as a security measure, and the charset has changed from ISO-8859 in 1.4.1 to UTF-8 in 1.4.3. You are of course welcome to work out those bits and get it working on the newest release, but for me it turned out to be a quicker approach to turn to an older version than doing a workaround.

Check off “openssl” and “openssl-devel” when installing Cygwin. (Located under the “Libs” category.)
OpenSSL

Remember how the basic interaction with Kannel was an HTTP GET to /sendsms with some parameters? Well it still is more or less - we just GET them from /sendota instead. Your basic string would be something like this:
http://kannel:13000/sendota?user=dummy&password=dummy&from=1234&to=12345678&text=urlencodedmessage

You’ll need a few more parameters for the message to get through; &settings=oma-settings, &coding=2, &sec=userpin, &pin=1234. (An explanation can be found in the Kannel reference docs. If you find that more academic than useful just try to the above settings, and turn to the docs if it doesn’t work on your specific device.)

In C# we end up with the following code:

string sendSMS(string uri)
{
   WebRequest webRequest = WebRequest.Create(uri);
   webRequest.ContentType = "x-www-form-urlencoded";
   webRequest.Method = "GET";

   try
   {
      WebResponse webResponse = webRequest.GetResponse();
      if (webResponse == null)
      {
         return null;
      }
      StreamReader sr = 

         new StreamReader(webResponse.GetResponseStream());
      return sr.ReadToEnd().Trim();
  }
   catch (WebException ex)
   {
      return ex.ToString();
   }
}

private void btnSendOTA_Click(object sender, RoutedEventArgs e)
{
   kannelServer = txtServer.Text;
   kannelPort = txtPort.Text;
   smsPath = txtOtaPath.Text;
   userName = txtUser.Text;
   passWord = txtPass.Text;

   string fromAddress = txtOtaFrom.Text;
   string toAddress = txtOtaTo.Text;
   string msgContent = txtOTAMsg.Text;
   string type = "oma-settings";
   string sec = "userpin";
   string pin = "1234";
   string coding = "2";

   msgContent = HttpUtility.UrlEncodeUnicode(msgContent);

   string otaPost = kannelServer + ":" + kannelPort + smsPath + 

   "?user=" + userName + "&pass=" + passWord + "&from=" + fromAddress
   + "&to=%2B" + toAddress + "&sec=" + sec + "&pin=" + pin + "&coding=" 

   + coding + "&type=" + type + "&text=" + msgContent;

   string kannelRes = sendSMS(otaPost);
}

And I’ve updated the UI of my test application:

CinnamonOTA_Config
CinnamonOTA_Send

Fair enough - but what would we go about typing into this message? A fairly good reference (for Nokia devices) would be the following doc:
forum.nokia.com - S60 OMA Client Provisioning

Most of these setttings are generic, and should work on other devices as well, but I’ve only tested these with my Nokia E75.

So say that you want to provision APN settings - you’ll use the following xml:

<?xml version="1.0"?>
<!DOCTYPE wap-provisioningdoc PUBLIC "-//WAPFORUM//DTD PROV 1.0//EN"
"http://www.wapforum.org/DTD/prov.dtd">
<wap-provisioningdoc version="1.0">
<characteristic type="BOOTSTRAP">
<parm name="NAME" value="My internjet"/>
</characteristic>
<CHARACTERISTIC TYPE="ADDRESS">
<PARM NAME="BEARER" VALUE="GPRS"/>
<PARM NAME="GPRS_ACCESSPOINTNAME" VALUE="internjet"/>
<PARM NAME="PPP_AUTHTYPE" VALUE="PAP"/>
<PARM NAME="PPP_AUTHNAME" VALUE="">
<PARM NAME="PPP_AUTHSECRET" VALUE=""/>
</CHARACTERISTIC>
</wap-provisioningdoc>

You’ll get a message on your device, you’ll need to enter a pin code to open the message, (I’ve set 1234 as a default), and you can then save the settings. Remember to include the “bootstrap” characteristic, or your device is not going to actually apply the settings.

Now, hold on a minute. I’ve created some cpf/cab files for Windows Mobile before to configure settings, and this seems familiar… Can I send off these messages to my WM devices as well? Ehh.. Yes…and no…or sort of… In the MSDN library you can see a lot of references to OMA CP samples for a lot of things. The problem is that your Windows Mobile device is running in a slightly different security context. By default the device doesn’t trust any OMA CP server. So if you send a message to the device you will not be able to use it. You’ll have to configure the trust first, and then send xml over-the-air. Which makes it slightly less usable in most scenarios. But as a “poor mans MDM solution” you could play around with it. Ok, that sounds a bit harsh. I’ve elaborated before on the differences of SMS-based and IP-based MDM solutions, and if I had to choose one of them I’d probably go for the IP-based. (MDM & “Enterprise Concerns”) But there’s nothing preventing you from using a hybrid model where most actions are performed over IP, but some are handled via SMS - possibly as a backup link to the device. I’ll be looking over some details in my lab, and if I come up with something of interest I’ll do a separate article on the perils of Windows Mobile and OTA.

While OMA CP is often used to provision OMA DM settings, and they are related, it is not the same thing. The xml is different, and usually the CP messages is just the gateway to the DM messages. Sending out complicated configurations over SMS has its drawbacks, and often you’ll just want to trigger a connection to the server for the actual configuration to occur over IP. OMA DM is more than a “push” service, and requires you to have a server on the back-end handling incoming requests from the devices. You could make your own OMA DM server (Nokia has a sample in Java you can start off with), or you can use System Center Mobile Device Manager from Microsoft, Afaria from Sybase, and a number of other products out there. Be aware though that some of these solutions might have different implementations of the OMA DM standard, and you may not necessarily be able to plug in your Kannel directly. (Afaria uses Kannel, so you can use what you know about interfacing with Kannel to make it a great combo.) And even if OMA DM is a standard there might be proprietary extensions to the server.

Kannel Integration With Exchange

After this post you might be thinking I’m a one-trick pony when it comes to Kannel, but I promise to move on. I just get all these fun (and sometimes useless) ideas along the way :)

In a true case of code reuse I took the C# code for sending SMS through Kannel, and made two more implementations.

The less interesting of the two first - in case you are thinking the title is misleading. I created a client for Windows Mobile that will let you - send SMS from your mobile device! Amazing, right? With a really slick interface and everything:
CinnamonMobile

Ok, you’re thinking that must be the dumbest idea ever. Creating an extra application for something that really is simpler to do through the regular interface. Granted, I don’t expect to make a lot of money selling this application, but it was only a simple proof-of-concept, and didn’t take much time to put together.
Things you might want to use it for include:
- Being able to set arbitrary “from” addresses even though you are sending from a device.
- Sending SMS through GPRS (and converted back to SMS for the receiver of course). This might be handy if your mobile operator is gouging you for sending SMS back home when you’re out of the country. (Presuming it comes off cheaper using a data connection that is.) Actually if you put a little effort into it you can create this as a console app that integrates with the regular user interface. This way the user doesn’t notice if the message is sent one way or the other, but you would for instance check whether the device is roaming and act accordingly in the background.
- I tested the app in the emulator running Windows Mobile Classic. So you don’t need a SIM card or a real device to send SMS with this.
- If I extend the app to sending binary SMS messages in the future it might even do something useful that you can’t do with the built-in SMS facilities on the device.

Another application of the code that might be more worthwhile is integration with Exchange. I’m not going to give a lecture of Exchange architecture, or development in general, (because there are a lot of other resources out there, and many more knowledgable than me), but with Exchange 2007 it’s easy to extend some of the core functionality in Exchange. All mail that is sent through an Exchange server passes through the Hub Transport role, and possibly the Edge role if you are using that. This is where different rules are applied to the mail. For instance throwing out spam, making sure that confidential mail cannot be sent to external recipients, etc. This functionality is implemented as so-called Transport Agents, and if you don’t mind writing some code it’s actually quite simple to create your own agents. (With the definition of simple obviously being dependent on what you are trying to achieve.)

Why not have an agent that will let your Exchange server send out SMS messages based on a set of parameters? For instance tagging a mail as important will send an SMS alert. Mail alerts sent from monitoring systems being converted to SMS instead. Prefixing the subject with “SMS:” for sending it through your Kannel box. You can most likely come up with a good use of your own as well if the above are of no use to your specific scenario.

I’ve created a small example of how this can be done. It’s a “stupid” agent in the sense that it triggers on all mail that is sent, and it has a pre-defined “to address”, and message. You’d probably integrate with AD, and filter the contents in some way if you were to actually use it for something worthwhile on an actual Exchange Server.

I have tested my dll on an Exchange 2010 Beta server, but to my knowledge it should run on Exchange 2007 as well. (RTM & SP1.)

The steps you need to perform are as follows:
Create a new project in Visual Studio. You’ll want a Visual C#->Windows->Class Library. Choose .NET 3.5 if you are testing on Exchange 2010, or .NET 2.0 for Exchange 2007.

Copy off Microsoft.Exchange.Data.Common.dll & Microsoft.Exchange.Data.Transport.dll from your Exchange server to your Visual Studio box. (By default they are located in “C:\Program Files\Microsoft\Exchange Server\V14\Public” on E2K10.) Place it in the “\debug” and/or “\release” folders under your “Projectname\bin” directory.

Add references to your project - more specifically the dll files you just pasted in.

Build your code based on the following sample code, or read more over at MSDN and build from scratch:)

using Microsoft.Exchange.Data.Transport;
using Microsoft.Exchange.Data.Transport.Routing;
using System.Net;
using System.IO;

namespace MobilityDojo.CinnamonExch
{
   public class SMSRoutingAgentFactory : RoutingAgentFactory
   {
      public override RoutingAgent CreateAgent(SmtpServer server)
      {
         RoutingAgent myAgent = new SMSAgent();
         return myAgent;
      }
   }
}  

public class SMSAgent : RoutingAgent
{
   public SMSAgent()
   {
      //Trigger whenever a message is submitted
      base.OnSubmittedMessage += 

      new SubmittedMessageEventHandler(SMSAgent_OnSubmittedMessage);
   }

   void SMSAgent_OnSubmittedMessage

   (SubmittedMessageEventSource source, QueuedMessageEventArgs e)
   {
      string kannelServer = "http://kannel";
      string kannelPort = "13000";
      string smsPath = "/cgi-bin/sendsms";
      string username = "";
      string passWord = "";
      string fromAddress = "Exchange";
      string toAddress = "";
      string msgContent = "Hello Exchange";

      string smsPost = kannelServer + ":" + kannelPort + smsPath
         + "?user=" + username + "&pass=" + passWord + "&from="
         + fromAddress + "&to=%2B" + toAddress + "&text=" + msgContent;

      string kannelRes = sendSMS(smsPost);
   }

   string sendSMS(string uri)
   {
      WebRequest kannelRequest = WebRequest.Create(uri);
      kannelRequest.ContentType = "x-www-form-urlencoded";
      kannelRequest.Method = "GET";

      try
      {
         WebResponse kannelResponse = kannelRequest.GetResponse();
         if (kannelResponse == null)
         {
            return null;
         }

         StreamReader sr = 

            new StreamReader(kannelResponse.GetResponseStream());
         return sr.ReadToEnd().Trim();
      }
      catch (WebException ex)
      {
         return ex.ToString();
      }
   }
}

You’ve now got a dll file that can be copied to your Exchange server. You choose the destination folder.

Open up the Exchange Management Shell. There’s a bug in the Exchange 2010 Beta build so you need to open the “Local Powershell” version of the shell. (Does not apply to Exchange 2007.)

Run the following cmdlet:

Install-TransportAgent -Name “CinnamonExch”

-TransportAgentFactory “MobilityDojo.CinnamonExch.SMSRoutingAgentFactory”

-AssemblyPath “C:\myAgent\CinnamonExch.dll”

Install_Agent

Exit the shell, re-enter the shell and enable the agent:

Enable-TransportAgent -Identity “CinnamonExch”

Enable_Agent

Restart the “Microsoft Exchange Transport” service.

Restart_Service

Test it. In my simple agent a mail sent to yourself through OWA should do the trick. (Contents doesn’t matter as I’ve already defined that in the HTTP GET in the code.)

Trigger_Mail

I don’t make any modifications to the original message so the mail should come through as usual with no visible trace client side that an SMS was sent.

Were still doing basic stuff, but you can do some neat stuff nonetheless if you use some imagination. Yes, there are a lot of software out there already that will plug-in to Exchange, custom SMSC integration, and whatnot. Some times it’s cheaper buying off-the-shelf software, but it doesn’t beat the satisfaction it gives to implement it yourself :)