This blog describes a number of common issues encountered when implementing Windows Phone 8 Enterprise Mobile Device Management protocol along with troubleshooting tips which ISVs can use.  TIP: check the download link regularly to see if the documentation has been updated and some of the information below may have already been added to the documentation by the time you read this blog.

This blog assumes you have read the Windows Phone 8 Enterprise Mobile Device Management protocol document and are familiar with Open Mobile Alliance: SyncML protocol.

Tools

One major problem ISVs encounter during implementation of an Enterprise MDM service is the lack of debugging capability of the DM client on Windows Phone.  At the time of writing this blog the Windows Phone device is effectively a black box... there is no way for an ISV to get logging information out of a retail phone.  The alternative is to use network logging tools like Fiddler to examine the traffic to and from the device. 

  Most of the network traffic we are interested in debugging will be over an SSL encrypted connection.  In order to view these communications you need to use a tool which supports SSL packet inspection.  Fiddler does this by acting as a proxy and using a man-in-the-middle technique in which the proxy supplies it's own SSL certificate to the client, however this certificate is not trusted by the phone so you must manually install the certificate on the phone.  (see the Fiddler documentation for instructions on configuring HTTPS traffic recording. )

  A second option is to use a more traditional network capture utility, like NetMon or WireShark, which can decrypt traffic using the servers certificate... One caveat is that decryption requires access to the private key for the server SSL certificate which may be a problem if your server is using a commercial root authority. ( See your preferred network capture tools' documentation for instructions on decrypting SSL packets. ) 

Discovery and GetPolicies

  The Discovery and GetPolicies steps are fairly simple, and well documented, so most problems can be diagnosed by comparing the contents of your network capture against the samples in the documentation. 
  However, I will point out a few things that people commonly overlook:

  • You need a domain name server (DNS) which can resolve the appropriate host name.  This means that you cannot use an IP address in place of the host name.
  • All services must support secure connection (HTTPS) and the Subject Name, or Subject Alternative Name, of the Server SSL certificate must match the host name of the server.  (...wildcard certificates are not allowed.)
  • In the GetPoliciesResponse, the only policies which Windows Phone 8 supports are minimalKeyLength, hashAlgorithmOIDReference, and the associated <oID> node... other values in the response payload are ignored.
  • TIP: It's a good idea to write some test code to double check your XML payloads.  One of the most confusing issues I have had to diagnose was the result of an extra space in a namespace definition in one of the XML payloads.  (This applies to all enrollment steps.)

Enrollment

  The majority of problems you are likely to run into revolve around the RequestSecurityToken and RequestSecurityTokenResponse.

  Generating the Client Certificate:

    There are several things you should be aware of in regards to the PKCS#10 request for a client certificate and the resulting client certificate.

  • The client certificate you send in response to this request must have the same public key value as specified in the PKCS#10 request.
    If you return a client certificate with a different public key the enrollment will report success but the client certificate will not be able to use the pre-generated private key. 
    • This will prevent Company Hub download from working over HTTPS.
    • This will also prevent SyncML from connecting if the server requires client certificate
    • And will prevent the device from being able to renew the certificate when it expires. 
      • Note: once the certificate expires the user will be unable to launch any company signed apps associated with this enrollment. The only way to recover from this state is to un-enroll the device and then go through the enrollment process all over again.

        The following items only affect Company Hub download over HTTPS... these do not affect any other aspect of device management.

  • Windows Phone 8 uses a hard-coded value for Subject in this request, B1C43CD0-1624-5FBB-8E54-34CF17DFD3A1, and assumes that the server will replace this value in the supplied client certificate. 
    If the server returns a client certificate containing the same Subject value this can prevent the Company Hub download from working so the server should ALWAYS override the Subject.
  • The client certificate's Subject property should be encoded using ASN.1 string type: "PRINTABLE_STRING".
    Versions of Windows Phone 8 available at the time of writing this blog are unable to retrieve a client certificate unless the Subject property is encoded using ASN.1 string type: "PRINTABLE_STRING".  (note: PRINTABLE_STRING is a subset of UTF8STRING.)
  • The client Certificate's Subject property should not contain any null (0) bytes.  Since the CertificateSearchCriteria is stored as a string any null characters will be treated as string terminators causing the string to be truncated which prevents the company hub download service from finding the certificate.

Contents of the wap-provisioningdoc

  Next I'll discuss some issues related to the contents of the wap-provisioningdoc supplied in the RequestSecurityTokenResponse.

  SSLCLIENTCERTSEARCHCRITERIA

  • The value of SSLCLIENTCERTSEARCHCRITERIA must begin with "Subject=" as plain text followed by the URL encoded contents of the Subject property and should end with "&amp;Stores=My%5CUser".

  APPAUTH

  • There seems to be a lot of confusion regarding the function of the APPAUTH entries due to the names associated with the AAUTHLEVEL parameter.

    These entries contain the initial credentials used to for authentication during the SyncML process.  You must provide entries for both CLIENT and APPSRV in order for Windows Phone to initiate a SyncML session with the server.

    • The APPAUTH entry with AAUTHLEVEL of "CLIENT" represents the credentials which the server will send to the client.  These credentials must use DIGEST authentication.

    • The APPAUTH entry with AAUTHLEVEL of "APPSRV" represents the credentials which the client will send to the server when initiating a SyncML session.

  OmaDmRetry

  • The OmaDmRetry registry keys control the behavior of the initial SyncML session and subsequent periodic polling schedule.  Note: These values only affect the scheduling if set during initial enrollment or during renewal so if you make a mistake you will need to un-enroll then re-enroll.

    • If the phone fails to connect to your SyncML server immediately after enrollment completes then check to make sure that the values for AuxRetryInterval and AuxNumRetries are greater than zero.  The default values are 15 and 10 respectively.

    • The periodic polling schedule, specified by Aux2RetryInterval and Aux2NumRetries, will not start until the initial SyncML session completes successfully.

      • If the phone is unable to connect to the SyncML server after exhausting all retries then the user will need to select the manual refresh from the Company Apps detail page in order to kick-start the periodic schedule.

      • The same problem can occur if the phones clock is moved forward beyond the time when the initial sync would have exhausted all retry attempts.  (i.e. Current Time + NumRetries * RetryInterval + AuxNumRetries * AuxRetryInterval)

  EnterpriseAppManagement

  • The first level node under EnterpriseAppManagment is the "Enterprise ID".  The values for Enterprise ID and EnrollmentToken should be identical to the values in the *.aetx file created by the AETGenerator tool.  see How to generate an application enrollment token.

  • An enterprise signing certificate is required for creating the EnrollmentToken.  If you do not yet have an enterprise signing certificate then you should not include the EnterpriseAppManagment node in your wap-provisioningdoc.

  • CRLCheck: A certificate authority may include a certificate revocation list (CRL) Uri in the server certificate. In some cases, where the CRL publishing point is not reachable from the internet, you may need to set CRLCheck =0 to disable checking so that connection to the server can succeed.

  Company Hub Download troubleshooting:

  • If your company hub does not install, first check to see if there is any connection attempt at the server side. 
    Note: normal IIS server logs do not include failed connection attempts so you will need to use a tool like netmon on the server.

  • If you see download begin but abort prematurely:
    check to see if your server is responding with 206 (Partial Content)... if so make sure it also includes a Content-Range header.  If Content-Range header is missing then the download will fail.  
    Note: If you have trouble getting the server to send the Content-Range header then try disabling re-startable download for this file type.              
      

  • If using HTTPS scheme: 

    • If you see a connection attempt but download does not start then the problem is likely related to the server SSL certificate or some other server security setting.     

    • If you see no connection attempt at all then the problem is likely with the client certificate or CertificateSearchCriteria.
      Use certutil -asn <cert>.cer to dump the raw ASN encoding data for the certificate and check the following items:   

      • Make sure the client certificate's Subject property is using ASN.1 string type "PRINTABLE_STRING".     

        06 03                   ; OBJECT_ID (3 Bytes)
        |  55 04 03             ;   2.5.4.3 Common Name (CN)
        13 06                   ; PRINTABLE_STRING (6 Bytes)
           54 65 73 74 43 4e    ;   TestCN

      • Make sure the CertificateSearchCriteria matches the Subject property of the certificate.  From the sample above the CertificateSearchCriteria should be: "CN=TestCN".

      • Make sure there are no null characters in the Subject property.   

        •   

Certificate Renewal

  • You must set the EntDMID of the DMClient CSP prior to certificate renewal.  The value of EntDMID is used in the certificate renewal request.  If this value is not set then the renewal request will not be sent.

SyncML

  • Digest (MD5) authentication: When initiating a SyncML session the server must send a hash of the credentials agreed upon previously. (see APPAUTH above.)

    This calculation uses a random seed or "nonce" to increase security.  Usually, after the initial request and response packages, the client will send a challenge with a 'NextNonce' value.  The server must respond with a new hash value calculated using this nonce and must store this nonce value to use in future sessions with that device...until the client sends another challenge request with a new nonce.

  • Below is a code example of how this hash value is calculated: 

///<summary>
/// Calculates the OMA DM MD5 Digest hash for the given input parameters.
///</summary>
///<param name="Name">The ProviderID as specified in the APPLICATION provisioning during enrollment.</param>
///<param name="Password">The AAUTHSECRET from the APPAUTH configuration.</param>
///<param name="ServerNonce">The Base64 encoded AAUTHDATA from the APPAUTH configuration or the NextNonce value from the most recent challenge ('chal'). </param>
///<returns></returns>
private string calculateHash(string Name, string Password, string ServerNonce)
{

string hash = "";

// first compute hash of <username>:<password>
string tmp = String.Format("{0}:{1}", Name, Password);

byte[] buffer = Encoding.UTF8.GetBytes(tmp);

MD5 md5Hash = MD5.Create();

byte[] output = md5Hash.ComputeHash(buffer);

// convert result to Base64 string, add a colon separator, and get a byte array of the string.
string tmp2 = String.Format("{0}:", Convert.ToBase64String(output));

byte[] tmp3 = Encoding.UTF8.GetBytes(tmp2);

// convert input: ServerNonce from Base64 to a byte array.
byte[] tmp4 = Convert.FromBase64String(ServerNonce);

// Combine the arrays into a single buffer.
byte[] buffer2 = newbyte[tmp3.Length + tmp4.Length];

tmp3.CopyTo(buffer2, 0);

tmp4.CopyTo(buffer2, tmp3.Length);

// Compute the hash of the resulting buffer.
output = md5Hash.ComputeHash(buffer2);

// Convert the byte array into a Base64 string for inclusion in XML payload.
hash = Convert.ToBase64String(output);

return hash;

}

 

 

  The items described above are the most frequently asked questions and reported problems which I have encountered. 
  But there are some minor issues people report less frequently which I did not have space to cover.  If there is enough interest, and I have enough content, I may follow up with a second blog.

 Comments are welcome,both below and on twitter:#WSDevSol.

Related information:

Introduction to ASN.1 Syntax and Encoding

Debugging Windows Phone 7 device traffic with Fiddler - Fiddler ...‎

Configure the Windows Phone 8 Emulator to work with Fiddler ...