stream_socket_client unable to connect to Apple APNS (Permission Denied) - php

I have a rare situations for sending push notifications via php which I cant figure out. I have a simple php script that send the notification shown below. If I execute this file via the command line php script.php it works just fine. If I execute via web http://domain.com/script.php it give me a Permission Denied Error. I have the correct cert path, not password for the cert. Any ideas?
Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Permission denied)
...............
$apns = connect_apns('gateway.push.apple.com', '2195');
$write = send_payload($apns, $deviceToken, $payload);
fclose($apns);
}
function connect_apns($apnsHost, $apnsPort) {
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', 'cert.pem');
return stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
}
function send_payload($handle, $deviceToken, $payload) {
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
return fwrite($handle, $apnsMessage);
}

so after much time spending looking at this I noticed that I had Selinux enabled. If you want to keep it enabled you need to set the property httpd_can_network_connect to true by issuing this command: setsebool -P httpd_can_network_connect 1. Otherwise just just disable selinux by going to vim /etc/selinux/config and set SELINUX=disabled.

Related

Error when try to excute Apple Push Notification through php file

I'm working on push notification in IOS with php server and I produced the certificate and keys of the app also I'm ensure from unblocking port for ssl://gateway.sandbox.push.apple.com:2196 and 2195 but at all time I get this error during try to connect on ssl also I'm sure from the permission of all key files
Warning: stream_socket_client(): SSL: crypto enabling timeout in /Users/samahahmaed/Desktop/CER/newspush.php on line 24
Warning: stream_socket_client(): Failed to enable crypto in /Users/samahahmaed/Desktop/CER/newspush.php on line 24
Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Unknown error) in /Users/samahahmaed/Desktop/CER/newspush.php on line 24
Failed to connect: 0
Edited:
When I'm trying this command
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCertificate.pem -key PushKey.pem -CApath /etc/ssl/certs/Entrust_Root_Certification_Authority.pem
I get this error
CONNECTED(00000003)
write:errno=54
php file:
<?php
// Put your device token here (without spaces):
$deviceToken = 'mydevicetokenhere';
// Put your private key's passphrase here:
$passphrase = '1234';
$message = $argv[1];
$url = $argv[2];
if (!$message || !$url)
exit('Example Usage: $php newspush.php \'Breaking News!\' \'https://raywenderlich.com\'' . "\n");
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apple_push_notification_production.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.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
$body['aps'] = array(
'alert' => $message,
'sound' => 'default',
'link_url' => $url,
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
I searched a lot about this issue and I tried all possible solutions but without any result what I can do now ?
Edited:
After add -debug to openssl command the most strange thing these lines:
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apple_push_notification_production.pem');
This line looks like you are using production certificate to connect to sandbox APNS. Try using development certificate. You can get the same from apple developer dashboard.

getting warning messages while sending push notification to multiple iphone device

While i am sending push notifications to multiple iphone devices using php webservices i am getting warning messages like :
Warning: stream_socket_client() [function.stream-socket-client]: SSL: crypto enabling timeout in /home/sample_app/pushnotification.php on line 66
Warning: stream_socket_client() [function.stream-socket-client]: Failed to enable crypto in /home/sample_app/pushnotification.php on line 66
Warning: stream_socket_client() [function.stream-socket-client]: unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /home/sample_app/pushnotification.php on line 66
Warning: fclose() expects parameter 1 to be resource, boolean given in /home/sample_app/pushnotification.php on line 79
This is my code :
$message='testing';
$q1="select devicetoken from tbl_devicetokens";
$re1 = mysql_query($q1);
while($row1=mysql_fetch_row($re1))
{
pushMessage($row1[0],$message,'myapp');
}
function pushMessage($deviceToken,$message,$app) {
echo "Sending iPhone Push Notifications to " . $deviceToken . "<br /><br />";
echo "Your Message: " . $message . "<br /><br />";
$time = time();
$apnsHost = 'gateway.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-myapp.pem';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if($apns) {
$payload = array();
$payload['aps'] = array('alert' => $message, 'badge' => 0, 'sound' => 'default');
$payload = json_encode($payload);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
} else {
echo "Connection Failed - iPhone Push Notifications Server";
echo $errorString."<br />";
echo $error."<br />";
}
//socket_close($apns);
fclose($apns);
}
So, can any one tell me how to solve this problem
might seem like a dumb answer, but have you tried your firewall / iptables? Those errors without further information look like connection issues to me. First thing you need to resolve is the timeout problem.
Does this still happen when you push a single notification to a single device?
If it does:
Are you sure that you have the correct path to the certs?
Make sure that the cert file name does not contain other than alphabetic characters.
If not:
Make sure that you are using the correct cert for the correct device environment (development, production)
If a device is jailbroken it will not receive push notifications.

APNS push not working, and not 'failing', after moving to EC2 instance

So, I moved my application to an EC2 instance, and Apple Push Notification Service stopped working. I'm using the same certificate, same script, same everything.
I've opened port 2195 in the security group for the EC2 instance.
from the EC2 intance, telnet gateway.push.apple.com 2195 works
my script receives no errors... everything gets to the end, even fwrite returns true... yet, I receive no push.
Things to note.
My EC2 instance is accessed via https where my old server was http, but since the script would be running locally, and has nothing to do with Apache, I don't see why this should matter. But, perhaps it does, so I'm letting you know :D
My script:
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$ssl = 'ssl://' . $apnsHost . ':' . $apnsPort;
$apns = stream_socket_client($ssl, $error, $errorString, 30, STREAM_CLIENT_CONNECT, $streamContext);
if($apns == false){
echo "Error: $errorString";
return false;
}
$payload['aps'] = array('alert' => $message, 'badge'=>$badge, 'sound' => 'default');
$payload = json_encode($payload);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device_id)) . chr(0) . chr(strlen($payload)) . $payload;
if(fwrite($apns, $apnsMessage)){
return true;
}
return false;
I've checked all of my variables, they are set.
Any help would be greatly appreciated. This is driving me bonkers :P
Turns out I was giving a bad device id. The databases were different, and I stored something poorly. :(

Python equivalent to php's stream_context_create

I am following a tutorial that requires me to open a socket and send a payload with a certificate: http://blog.serverdensity.com/how-to-build-an-apple-push-notification-provider-server-tutorial/.
I am having a bit of difficulty in figuring out how to do the following with python:
// Open the connection
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-dev.pem';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
// Send the payload
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
// Close Resources
socket_close($apns);
fclose($apns);
I've used python-requests in the past. But only for simple get requests.
Can I use python-requests to rewrite the above code in python, or is there something better suited for this task?
Looking at the PHP documentation fo stream_context_create, and the tutorial you're following I think what you're trying to accomplish is opening a SSL secured socket connection to gatway.sandbox.push.apple.com.
I think the python module you want to look at is the ssl module. There's an example of connecting to a server from a client, probably setting the keyfile and certfile options of ssl.wrap_socket() to the certificate you created and registered to talk to the apple server.

Push notifications (iPhone) give "111 Connection refused"

When I try to send Push Notifications I get this error: "Connection refused", but I don't know why... I've uploaded my apns-dev.pem in the same directory as well in the root-directory but that won't work either.
<?php
$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-dev.pem';
$apnsPass = 'secret';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', $apnsPass);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns) {
echo "Error: $errorString ($error)";
}
// Do this for each
$deviceToken = '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000';
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
// End do
socket_close($apns);
fclose($apns);
?>
Does anyone know what I'm doing wrong? When I remove the passphrase and don't send it it doesn't work either...
Make sure the outgoing port 2195 is open.This would be in your firewall config.
You don't want a passphrase unless your .pem file requires one. The connection requires peer verification (option verify_peer) turned on. Also, make sure $apnsCert is the valid path to the certificate, you can use an absolute path as a sanity check.
Lastly, this shouldn't effect your ability to connect, but your device token needs to be valid.
I've know fixed that error by adding this: STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT
Know I'm not getting any errors, but I don't receive any notification. I think the Dev-token is not valid know, so, this is how it look like
numbers numbers numbers numbers numbers numbers numbers numbers.
The spaces are removed in this line:
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
Edit: I founded the problem:
My server is refusing the outgoing port, just sent a mail, hoping they can activate it...

Categories