2

We are building an iOS MDM server to manage iOS devices. Below were the steps which were involved in enrolling an iOS device into the MDM server

  1. Send enroll configuration
  2. Perform SCEP
  3. send MDM server certificate.
  4. Create APNS certificate.
  5. Send push notification to the device.

The device receives the push notification and contacts the MDM server's "serverUrl". It responds with Status = "Idle" shown below

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Status</key>
    <string>Idle</string>
    <key>UDID</key>
    <string><udid-of-device></string>
</dict>
</plist>

In response to this command to get device information is sent as below.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Command</key>
        <dict>
            <key>RequestType</key>
            <string>DeviceInformation</string>
            <key>Queries</key>
            <array>
                <string>UDID</string>
                <string>DeviceName</string>
                <string>OSVersion</string>
                <string>ModelName</string>
                <string>IMEI</string>
            </array>
        </dict>
        <key>CommandUUID</key>
        <string>command-for-the-session</string>
    </dict>
</plist>

Device responds back with the device information as shown below

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CommandUUID</key>
    <string>command-for-the-session</string>
    <key>QueryResponses</key>
    <dict>
        <key>DeviceName</key>
        <string>iPhone</string>
        <key>IMEI</key>
        <string>01 353150 432467 8</string>
        <key>ModelName</key>
        <string>iPhone</string>
        <key>OSVersion</key>
        <string>7.1</string>
        <key>UDID</key>
        <string><udid-device></string>
    </dict>
    <key>Status</key>
    <string>Acknowledged</string>
    <key>UDID</key>
    <string><udid-device></string>
</dict>
</plist>

This flow works as required. After this i want to end connection with the device as there is nothing more to be sent to the device.

My query is how to stop or close this connection after we receive the valid details from the device for that CommandUUID. It keeps on calling the mdm server url and does not end the connection.

I have tried send an empty plist to stop the connection but no luck.

Kindly help.

Thanks for reading.!

Samreen
  • 139
  • 1
  • 14

2 Answers2

1

A device will continuously query your server for new commands by sending:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Status</key>
    <string>Idle</string>
    <key>UDID</key>
    <string><udid-of-device></string>
</dict>
</plist>

In the case, if you don't have any commands you should return HTTP 200 with an empty body. This signals to the device that it should stop polling until you will send next push notification.

Victor Ronin
  • 22,758
  • 18
  • 92
  • 184
  • Thanks for the reply. All your comments helped me a lot. I was confused and sent an empty plist. Instead we need to send empty response body. Status of the response is by default 200 in java if everything goes well. – Samreen Aug 21 '14 at 06:34
  • @Samreen I am trying to build MDM in PHP. Do you have any documentation of your own. I have read mdm protocol pdf & few other article. But still i am not able to get things clear. Please help me. – sau Jun 05 '15 at 10:19
  • Hello sau, due to corporate policies documentation is not allowed to be shared. Apple has provided enough documentation as believe you me, i have followed it with some hiccups which were solved through stackoverflow. You can refer all my posts over this implementation. Also please let me know where are you stuck?? – Samreen Jun 08 '15 at 05:51
0

This is what i did in java to send and empty response.

If all goes well the response status is defaulted to 200.

Code to send empty response:

response.setStatus(200); // set status explicitly in case device polls to the mdm server
OutputStream outStream = response.getOutputStream();
outStream.write(new byte[0]);
outStream.close();

And the server logs for the same below:

iPhone mdmd[302] <Notice>: (Note ) MDM: mdmd starting...
 iPhone mdmd[302] <Notice>: (Note ) MDM: Looking for managed app states to clean up
 iPhone profiled[303] <Notice>: (Note ) profiled: Service starting...
 iPhone mdmd[302] <Notice>: (Note ) MDM: Network reachability has changed.
 iPhone mdmd[302] <Notice>: (Note ) MDM: Network reachability has changed.
 iPhone mdmd[302] <Notice>: (Note ) MDM: Push token received.
iPhone mdmd[302] <Notice>: (Note ) MDM: Push token received.
iPhone mdmd[302] <Notice>: (Note ) MDM: Received push notification.
iPhone mdmd[302] <Notice>: (Note ) MDM: Polling MDM server https://myserver-url:port/server for next command.
 iPhone mdmd[302] <Notice>: (Note ) MDM: Transaction completed. Status: 200
 iPhone mdmd[302] <Notice>: (Note ) MDM: Attempting to perform MDM request: DeviceInformation
iPhone mdmd[302] <Notice>: (Note ) MDM: Command Status: Acknowledged
iPhone mdmd[302] <Notice>: (Note ) MDM: Polling MDM server https://myserver-url:port/server for next command.
iPhone profiled[303] <Notice>: (Note ) profiled: Service stopping.
iPhone mdmd[302] <Notice>: (Note ) MDM: Transaction completed. Status: 200
 iPhone mdmd[302] <Notice>: (Note ) MDM: Server has no commands for this device.
iPhone mdmd[302] <Notice>: (Note ) MDM: mdmd stopping.
Samreen
  • 139
  • 1
  • 14
  • Hi @Samreen, we get the logs as below, ```Polling MDM server https://port/api/serverapi?request= for next command. Handling request type: DeviceLock. Command Status: Acknowledged. Transaction completed. Status: 200, ResponseUUID: (Idle). Could not parse command. Error: (null). ``` As you can see even after sending back 200, we got error ```Could not parse command. Error: (null) ``` And then polling again keeps continuing, we are sure we send 200 in response to stop polling ```return this.Request.CreateResponse(200);``` with empty body. Can you help us with what we're doing wrong? – Sudhu Apr 22 '20 at 09:10