14

I've been working through Ray Wenderlich's tutorials on push notifications using a PHP Script.

Reference: http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1

http://www.raywenderlich.com/32963/apple-push-notification-services-in-ios-6-tutorial-part-2

I have done a ton of research but I have ran into an issue on part 2 where you run the push.php file using the ck.pem file.

/Applications/XAMPP/bin/php push.php development

My only difference is that I'm using XAMPP and not MAMP.

I have confirmed that all the extensions are installed.

I am able to test out my certificate in the terminal by doing this:

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

It asks me to enter my passphrase and I do. Everything works successfully in the terminal.

However, when I run the push.php file, I get these errors:

PHP Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed PHP Warning: stream_socket_client(): Failed to enable crypto in

PHP Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Unknown error) in on line 140

Line 140 in the php file is:

$this->fp = stream_socket_client('ssl://' . $this->server, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

I found these:

iOS push notification does not work when using crontab scheduler

https://devforums.apple.com/message/1054840#1054840

Push notification in PHP

I have literally retried everything. I know my passphrase is correct. I've re-created my certificates, pem files, and keys. Nothing works. Same error every time I do this.

I'm beyond confused.

Does anyone have any suggestions or know what's going on?

Thank you!

UPDATE 1:

I have also tried setting the full path to the ck.pem file that does not fix the error either.

Community
  • 1
  • 1
Sandy D.
  • 3,166
  • 1
  • 20
  • 31
  • Are you sure you exported your .p12 correctly ? Make sure you took the private key, and not only the public key when you export it from your keychain – Emilie Jan 29 '15 at 18:08
  • @Emilie I only exported the private key. I didn't export the public key since the tutorial didn't tell me too. – Sandy D. Jan 29 '15 at 18:11
  • what is the value of `$ctx`, and what options are set on it? – oflannabhra Jan 29 '15 at 18:42
  • @oflannabhra Options set: stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certificate); stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase); $ctx prints out Resource id #9 Of course, I have no idea what that means. – Sandy D. Jan 29 '15 at 18:49
  • `$this->certificate` should be the absolute filepath for your local certificate. – oflannabhra Jan 29 '15 at 19:59
  • @oflannabhra I had mentioned in Update 1 that using the full path didn't work. Please see my answer -- that was the problem. – Sandy D. Jan 30 '15 at 22:11
  • Download [Entrust.net Certification Authority (2048)](http://www.entrust.net/developer/) from Entrust's site. Then, use the certificate in the OpenSSL command with `-CAfile`: `openssl s_client -connect gateway.sandbox.push.apple.com:2195 -CAfile entrust-ca.pem`. You should probably user TLS 1.0 and SNI, too: `openssl s_client -connect gateway.sandbox.push.apple.com:2195 -CAfile entrust-ca.pem -tls1 -servername gateway.sandbox.push.apple.com`. – jww Jun 07 '15 at 10:10
  • @jww I've already answered this. But thanks. – Sandy D. Jun 08 '15 at 16:21

4 Answers4

58

Okay, I finally figured this out! After 2 days of working with this.

So, for anyone else who runs into this issue:

Download the entrust_2048_ca.cer certificate from: https://www.entrust.com/get-support/ssl-certificate-support/root-certificate-downloads/

Scroll down and get the Entrust.net Certificate Authority (2048)

Then, in the push.php file, after you set the context for the passphrase, add this line: stream_context_set_option($ctx, 'ssl', 'cafile', 'entrust_2048_ca.cer');

Sandy D.
  • 3,166
  • 1
  • 20
  • 31
  • 1
    That was of huge help! – gunjot singh Mar 29 '16 at 10:24
  • 3
    The URL in the answer is now broken. The correct one at this time is https://www.entrust.com/get-support/ssl-certificate-support/root-certificate-downloads/ and scroll down to **Entrust.net Certificate Authority (2048)**. – swifthorseman Sep 25 '16 at 20:22
  • 5
    I wish I found your post 5 hours ago! I've been pulling my hair out trying everything. I noticed if I removed the 'ssl://' from the url the script worked, but I never got the push notification on my iPhone. I ran across someone who said to add stream_context_set_option($ctx, 'ssl', 'verify_peer', false); which defeats the server validation. As a troubleshooting idea, I tried it and presto, the push worked. At that point, I knew the problem was server validation. Earlier, I had downloaded the entrust cert and added it to my system keychain, but that didn't help. I CAN'T THANK YOU ENOUGH!!! – One In a Million Apps Oct 05 '16 at 23:53
  • @OneInaMillionApps No problem! I'm glad this helped! =) – Sandy D. Oct 06 '16 at 14:20
  • 2
    Thanks a lot! In MacOS Sierra this is solution! – Resty Nov 18 '16 at 12:38
  • 1
    I would upvote your answer twice if I could. I was stuck on this for a few days and I'd started tearing my hair out. Thanks a lot! – Swapnil Dhanwal Jan 22 '17 at 05:22
  • Make sure you have both `stream_context_set_option($ctx, 'ssl', 'cafile', '/path/to/entrust_2048_ca.cer');` AND `stream_context_set_option($ctx, 'ssl', 'local_cert', 'PushChatKey.pem');` – egarc Apr 18 '17 at 19:15
  • Thanks it's Really helped me. – kalpesh jetani Jun 12 '17 at 12:46
6

Updated to macOS Sierra 10.12.4


The problem is in new PHP Version in macOS Sierra. They changed the way it works with certificates.

I would suggest a small changes in the accepted answer to make things explicit.

You have to setup path to entrust_2048_ca.cer and other parameters during creation of the stream context like

$streamContext = stream_context_create([
        'ssl' => [
            'verify_peer'      => true,
            'verify_peer_name' => true,
            'cafile'           => '/path/to/bundle/entrust_2048_ca.cer',
        ]
    ]);

The full explanation and links are here

Community
  • 1
  • 1
Sander
  • 1,325
  • 1
  • 11
  • 30
5

Update to macOS sierra 10.12.5

please add

stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

The problem is in new PHP Version in macOS Sierra

3

add

stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

which defeats the server validation. Credits @One In a Million Apps in a comment above.

Ahsan Ebrahim Khatri
  • 1,807
  • 1
  • 20
  • 27