Search code examples
phpiosmdmtalend-mdm

iOS MDM push notification using Php, not working


i know it's duplicate of this, but this one is not working for me.

My Php code to send notification is

// Put your device token here (without spaces):
$deviceToken = '6hPQc2HvdA20XGlQkznJxlappCrzm3kJccljjOsgF2k=\n'; #base64 encoded
// Put your private key's passphrase here:
$passphrase = 'Temp1234';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', './Certificates_push_dev_new.pem');
stream_context_set_option($ctx, 'ssl', 'cafile', './entrust_2048_ca.cer');

stream_context_set_option($ctx, 'ssl', 'verify_peer', true);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body

$payload = json_encode(array(
                             'mdm' => '3742A63A-5BB3-4D61-9D4B-E7968DADAF84',
                             'topic' => 'com.apple.mgmt.External.e5814e69-1c24-437f-bae9-562049fd3cd5'
                             ));

echo $payload . PHP_EOL;
// Build the binary notification
#$msg = chr(0).pack('n', 32).$deviceToken . pack('n', strlen($payload)).$payload;

// Build the binary notification
#$msg = chr(0) . pack('n', 32) . pack('J', $deviceToken) . pack('n', strlen($payload)) . $payload;

#$msg = chr(0).chr(0).chr(32).bin2hex(base64_decode($deviceToken)).chr(0).chr(strlen($payload)).$payload;
$msg = chr(0).chr(0).chr(32).bin2hex(base64_decode($deviceToken)).chr(0).chr(strlen($payload)).$payload;

// Send it to the server
# $result = fwrite($fp, $msg, strlen($msg));
$result = fwrite($fp, $msg);

if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);

Device Token with base64 Encoded

$deviceToken = '6hPQc2HvdA20XGlQkznJxlappCrzm3kJccljjOsgF2k=\n'; #base64 encoded

I have tried device token without base64 encoded as well in that case my token was

$deviceToken = '\xEA\u0013\xD0sa\xEFt\r\xB4\\iP\x939\xC9\xC6V\xA9\xA4*\xF3\x9By\tq\xC9c\x8C\xEB \u0017i';

To Check certificate validation, below command is working fine.

openssl s_client -connect gateway.push.apple.com:2195 -cert apns-dev.pem -key key.pem -CAfile entrust_2048_ca.cer

i don't receive any error while executing above php code. But device never contact our MDM server to pull configuration changes.

when my TestMDM installed profile, have "SIGNING CERTIFICATE" SECTION My MDM installed profile missing "SIGNING CERTIFICATE" SECTION

could "SIGNING CERTIFICATE" section cause be of issue, device not receiving notification ?, one screenshot is of TestMDM vendor and second is of my i.e MobiLock


Solution

  • I've had a go at pushing notifications myself, using PHP on Windows. One of the things I've noticed that might be wrong is your inclusion of the topic in the push payload. This isn't required.

    Here is some PHP code I've written to test using a device I registered in TestMDM. I'm not a PHP developer, but using this (http://codular.com/sending-ios-push-notifications-with-php) as a baseline and taking the pushMagic and deviceToken strings from my TestMDM database, I got it to successfully send a push.

    As I'm on Windows, I also use a PFX certificate for push.

    $deviceToken = '<YOUR DEVICE TOKEN AS BASE64 STRING>'; #base64 encoded
    $token = bin2hex(base64_decode($deviceToken));
    
    // Put your private key's passphrase here:
    $passphrase = '<YOUR PASSWORD>';
    
    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', './Push.pfx');
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
    
    $fp = stream_socket_client('gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
    
    if (!$fp) {
        exit("Failed to connect: $err $errstr" . PHP_EOL);
    }
    
    echo 'Connected to APNS' . PHP_EOL . "<br />";
    
    $payload = '{ \'mdm\' = \'<YOUR PUSH MAGIC FOR THIS DEVICE>\' }';
    
    $inner = chr(1) . pack('n', 32) . pack('H*', $token)
            . chr(2) . pack('n', strlen($payload)). $payload
            . chr(3) . pack('n', 4) . pack('N', 1)
            . chr(4) . pack('n', 4)
            . pack('N', time() + 86400)
            . chr(5) . pack('n', 1) . chr(10);
    
    $notification = chr(2) . pack('N', strlen($inner)) . $inner;
    
    echo $payload . PHP_EOL;
    
    $result = fwrite($fp, $notification, strlen($notification));
    
    echo $result;
    

    Once I run the script, I can see this in the logs of my device, which indicates it is working:

    Jul 11 10:16:10 Toms-iPod mdmd[11218] <Notice>: (Note ) MDM: mdmd starting...
    Jul 11 10:16:10 Toms-iPod mdmd[11218] <Notice>: (Note ) MDM: Network reachability has changed.
    Jul 11 10:16:10 Toms-iPod mdmd[11218] <Notice>: (Note ) MDM: Network reachability has changed.
    Jul 11 10:16:10 Toms-iPod mdmd[11218] <Notice>: (Note ) MDM: Push token received.
    Jul 11 10:16:10 Toms-iPod mdmd[11218] <Notice>: (Note ) MDM: Received push notification.
    Jul 11 10:16:10 Toms-iPod mdmd[11218] <Notice>: (Note ) MDM: Polling MDM server https://testmdm.azurewebsites.net/<redacted> for next command.
    

    Hopefully this will help.

    T