commit d67c0f0e0fe1a4c45972ca40fdd9aa681f7f2365
parent 4a76d8d5e9b24fe01d97fe583e8dafa9f0779d1e
Author: kyle <kyle@0x30.net>
Date: Mon, 28 Dec 2015 21:14:15 -0700
pushd_ios: commit wip ios "push daemon"
- apple apn requires http/2 tls protocol
- use Protocol::HTTP2 perl cpan lib to do heavy lifting there
- event loop AnyEvent has TLS support... so that's used for TLS
- code is lifted almost verbatim from Protocol::HTTP2 example file
- also commit apple certificates we need for TLS authentication
- in a twist of events, apn uses TLS for authentication
- that means we needed to get our key signed by apple
- made that happen through apple developer account interface
- apple certificates are DER encoded, this was converted to PEM for use with
the TLS library (wouldn't work otherwise)
Diffstat:
6 files changed, 233 insertions(+), 4 deletions(-)
diff --git a/pushd_ios b/pushd_ios
@@ -0,0 +1,141 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use AnyEvent;
+use AnyEvent::Socket;
+use AnyEvent::Handle;
+use Net::SSLeay;
+use AnyEvent::TLS;
+
+use Protocol::HTTP2;
+use Protocol::HTTP2::Client;
+use Protocol::HTTP2::Constants qw(const_name);
+
+Net::SSLeay::initialize();
+
+my $client = Protocol::HTTP2::Client->new(
+ on_change_state => sub {
+ my ( $stream_id, $previous_state, $current_state ) = @_;
+ printf "Stream %i changed state from %s to %s\n",
+ $stream_id, const_name( "states", $previous_state ),
+ const_name( "states", $current_state );
+ },
+ on_push => sub {
+ my ($push_headers) = @_;
+
+ # If we accept PUSH_PROMISE
+ # return callback to receive promised data
+ # return undef otherwise
+ print "Server want to push some resource to us\n";
+
+ return sub {
+ my ( $headers, $data ) = @_;
+ print "Received promised resource\n";
+ }
+ },
+ on_error => sub {
+ my $error = shift;
+ printf "Error occured: %s\n", const_name( "errors", $error );
+ }
+);
+
+my $host = 'api.development.push.apple.com';
+my $port = 443;
+
+# Prepare http/2 request
+$client->request(
+ ':scheme' => "https",
+ ':authority' => $host . ":" . $port,
+ ':path' => "/3/device/devid_goes_here",
+ ':method' => "POST",
+ # headers => [
+ # 'accept' => '*/*',
+ # 'user-agent' => 'perl-Protocol-HTTP2/0.01',
+ # ],
+ on_done => sub {
+ my ( $headers, $data ) = @_;
+ printf "Get headers. Count: %i\n", scalar(@$headers) / 2;
+ printf "Get data. Length: %i\n", length($data);
+ print $data;
+ },
+
+ data => "hello=world&test=done",
+);
+
+my $w = AnyEvent->condvar;
+
+tcp_connect $host, $port, sub {
+ my ($fh) = @_ or do {
+ print "connection failed: $!\n";
+ $w->send;
+ return;
+ };
+
+ my $tls;
+ eval {
+ $tls = AnyEvent::TLS->new(
+ method => "TLSv1_2",
+ cert_file => 'ssl/apn/aps.pem',
+ key_file => 'ssl/apn/aps.key'
+ );
+
+ # ALPN (Net-SSLeay > 1.55, openssl >= 1.0.2)
+ if ( exists &Net::SSLeay::CTX_set_alpn_protos ) {
+ Net::SSLeay::CTX_set_alpn_protos( $tls->ctx,
+ [Protocol::HTTP2::ident_tls] );
+ }
+
+ # NPN (Net-SSLeay > 1.45, openssl >= 1.0.1)
+ elsif ( exists &Net::SSLeay::CTX_set_next_proto_select_cb ) {
+ Net::SSLeay::CTX_set_next_proto_select_cb( $tls->ctx,
+ [Protocol::HTTP2::ident_tls] );
+ }
+ else {
+ die "ALPN and NPN is not supported\n";
+ }
+ };
+ if ($@) {
+ print "Some problem with SSL CTX: $@\n";
+ $w->send;
+ return;
+ }
+
+ my $handle;
+ $handle = AnyEvent::Handle->new(
+ fh => $fh,
+ tls => "connect",
+ tls_ctx => $tls,
+ autocork => 1,
+ on_error => sub {
+ $_[0]->destroy;
+ print "connection error\n";
+ $w->send;
+ },
+ on_eof => sub {
+ $handle->destroy;
+ $w->send;
+ }
+ );
+
+ # First write preface to peer
+ while ( my $frame = $client->next_frame ) {
+ $handle->push_write($frame);
+ }
+
+ $handle->on_read(
+ sub {
+ my $handle = shift;
+
+ $client->feed( $handle->{rbuf} );
+
+ $handle->{rbuf} = undef;
+ while ( my $frame = $client->next_frame ) {
+ $handle->push_write($frame);
+ }
+ $handle->push_shutdown if $client->shutdown;
+ }
+ );
+};
+
+$w->recv;
diff --git a/ssl/apn/aps.cer b/ssl/apn/aps.cer
Binary files differ.
diff --git a/ssl/apn/aps.csr b/ssl/apn/aps.csr
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICkTCCAXkCAQAwTDELMAkGA1UEBhMCY2ExFzAVBgNVBAMMDlNobGlzdCBBUE4g
+S2V5MSQwIgYJKoZIhvcNAQkBFhVhcHBsZUBnZXRhZGRyaW5mby5uZXQwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVNumyopIdz2mWYGdAkA4ZujgBld1W
+6YssexOAhVJeQ+v3e/8lUrGGyY0TAht8go2XQpl8HjwJr2C/PjHX+3BSw82JUyKR
+IkYEcNds/EhL9VpbHI3cHV8dLIvxfvJz7HDRpV4SbTZYV+Y0euhS23J5S7HNMdHY
+331VqqJEekY0EOH4c+UbuVTqeI07BlRzsMUOQe9jix0JxXlpNf3HbFcQn9FAadXY
+Nmz2sH1qTPLbossQsgirI5QivlCMHo7VApodtQEjMPmBquen9jOuhjevnAN9rjkg
+sW5kBwiOeDsomXY9FmJoPS5QyhoYgnO0Zn8xMe3bakJLRans7FH2+qj1AgMBAAGg
+ADANBgkqhkiG9w0BAQsFAAOCAQEAUIGJgjLZhYrDNvLW2LgAjntM6U1o5u/i/jqf
+lZ7iHLSgkZrFvzGV8lMBlPxMlYP58I7CGT9LPsX3wgO2cXokSy57q2f12OM591rj
+3WTeSIg5JnMJ1RiXpLkZBV+ApULwGvUpyCRxl+3vZ88zDpF8+VaPcA00sXnCuilp
+zMMADbNXe+/Km9KNtwbNGoX7GMLPNzGVdo/e3PRhtL1kymjvGFXIx35d+Kf+j8HN
+1K+4/WDOP2dbfLTQU1iDfvaRM3ElTyyHPKgcs4LYXQFVWBGzTuCfbdJzMHmoeGRR
+O2Yoh9IRsZT/OksIU2WPVBAAROfn6aIUrPP3p1fxyJoYPqUsdw==
+-----END CERTIFICATE REQUEST-----
diff --git a/ssl/apn/aps.key b/ssl/apn/aps.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA1TbpsqKSHc9plmBnQJAOGbo4AZXdVumLLHsTgIVSXkPr93v/
+JVKxhsmNEwIbfIKNl0KZfB48Ca9gvz4x1/twUsPNiVMikSJGBHDXbPxIS/VaWxyN
+3B1fHSyL8X7yc+xw0aVeEm02WFfmNHroUttyeUuxzTHR2N99VaqiRHpGNBDh+HPl
+G7lU6niNOwZUc7DFDkHvY4sdCcV5aTX9x2xXEJ/RQGnV2DZs9rB9akzy26LLELII
+qyOUIr5QjB6O1QKaHbUBIzD5garnp/YzroY3r5wDfa45ILFuZAcIjng7KJl2PRZi
+aD0uUMoaGIJztGZ/MTHt22pCS0Wp7OxR9vqo9QIDAQABAoIBAE3ilVPP1xhUn/ly
+lcUb2krDn5nUqNoKzfAdtW4JRaFxpkztWrLDll3qWkJLTscY2agbh/2y/bN8ARdb
+HNIM42cYZ4h2efYSUwlkPw1syuwUYEFQGPIDOK9rimNZQC/gewXaJpcMlgGHemxJ
+SXya9SIh6H1QaZuTaDFW95eUIvj5VxzQ6ZuxopVPph+yPVNOLGc+1ZOKXlxmFuwB
+pY+IoU2hGZ4MsbE772QzA4KcnJBRPieEHkLY0VguR7wGGX8/MlA62h1HLnT+sCQz
+qGxLtuZWtdA2ToNAcChnEgZHktSEwEGNiY8Y7JeZwAmibpI4kh0858l7eubOEzrU
+DsEvxwECgYEA7WCbL8/chRgeuJxm9tRbERPgHJISVVS7BHdrIefWc0SteNMdCgxP
+FTAGgrZ5+mB8fUDwuU4W6p0d/FdZ82NC3gnTJHHl5GHaVYfEHCYxqwu+8pRgRXA2
+svf9f+F5+J/vS4Iy3+2n9TWYkMDeuuyRrX9WCiDT53mfqfPBBY1I4XECgYEA5fEH
+egFxz4iV2RM4L1MpDO6VsvgjxMTcvTWgEYqoD0X0PEqAFZplsHyuxecF1lZ5LDnl
+F67tkFFRdI+kbNl3r++j/IPEsNF76OHrYWct5AEtpl+zVsd1xtVlmXip++nkwiqu
+Amhrm5DAygXJiA3ySVsf431M838Ky6bLd/xhfcUCgYEAxWW3x3vAcwGK0pRlX09a
+Z4oyrS+fhUxPtTglY+2qPPLYmwhcNrXjscfdMifSqa5A99vgEwjoL7P2cpilWauq
+uIBNEBqTRWdGLCgZohr05LuAz7Mpl7ToF834BbcYOfOuCAm+is7UBCrMs1tgHOuL
+fU7N2uBPt0dByg/E7Pv/plECgYEA1V30Tx06C5a1Xcn8z8U+CVb2qCyjnDoEjrpM
+/xoH2qxR9wQ2mFU92SfJUbCO9RYmuIg8cd6LaOhcSmnj7HFbI3GeXHm1MVIhxbal
+oSuKJNGHF6QkGPla65cnAOM78JtX/2h1MZzNhXwruQrnuA0g7zrUe1bQ6f3P+aub
+kIoruPUCgYAyEQO4KnN4qz+RpXjNNNLfPCsuxl0nZYxwlYkHmsWcPWsLc3ez7tky
+AIM8C3Kw6LOdi26hFTFpIibNrkVPxHZ29tpd3LXmtJSS0kyNhQTzo/ojGbc2mZf8
+gg9PfjHi1j6iM44RbfBqp66ZcrfdXP6mLipMx21Vv++5MYaUVpEYGg==
+-----END RSA PRIVATE KEY-----
diff --git a/ssl/apn/aps.pem b/ssl/apn/aps.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFDCCBPygAwIBAgIIbC9jyeG/1bAwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
+ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
+aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
+HhcNMTUxMjI4MjE1MTU0WhcNMTcwMTI2MjE1MTU0WjCBjDEiMCAGCgmSJomT8ixk
+AQEMEmNvbS5vY3RvcHVzLnNobGlzdDEwMC4GA1UEAwwnQXBwbGUgUHVzaCBTZXJ2
+aWNlczogY29tLm9jdG9wdXMuc2hsaXN0MRMwEQYDVQQLDApVMkZYWVVCVjVMMRIw
+EAYDVQQKDAlLeWxlIE1pbHoxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA1TbpsqKSHc9plmBnQJAOGbo4AZXdVumLLHsTgIVSXkPr
+93v/JVKxhsmNEwIbfIKNl0KZfB48Ca9gvz4x1/twUsPNiVMikSJGBHDXbPxIS/Va
+WxyN3B1fHSyL8X7yc+xw0aVeEm02WFfmNHroUttyeUuxzTHR2N99VaqiRHpGNBDh
++HPlG7lU6niNOwZUc7DFDkHvY4sdCcV5aTX9x2xXEJ/RQGnV2DZs9rB9akzy26LL
+ELIIqyOUIr5QjB6O1QKaHbUBIzD5garnp/YzroY3r5wDfa45ILFuZAcIjng7KJl2
+PRZiaD0uUMoaGIJztGZ/MTHt22pCS0Wp7OxR9vqo9QIDAQABo4ICbDCCAmgwHQYD
+VR0OBBYEFFgF/VEVeAkYSflwIaicT749/tXlMAwGA1UdEwEB/wQCMAAwHwYDVR0j
+BBgwFoAUiCcXCam2GGCL7Ou69kdZxVJUo7cwggEcBgNVHSAEggETMIIBDzCCAQsG
+CSqGSIb3Y2QFATCB/TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlz
+IGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2Yg
+dGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9u
+cyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBw
+cmFjdGljZSBzdGF0ZW1lbnRzLjA1BggrBgEFBQcCARYpaHR0cDovL3d3dy5hcHBs
+ZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkwMAYDVR0fBCkwJzAloCOgIYYfaHR0
+cDovL2NybC5hcHBsZS5jb20vd3dkcmNhLmNybDAOBgNVHQ8BAf8EBAMCB4AwEwYD
+VR0lBAwwCgYIKwYBBQUHAwIwEAYKKoZIhvdjZAYDAQQCBQAwEAYKKoZIhvdjZAYD
+AgQCBQAwfQYKKoZIhvdjZAYDBgRvMG0MEmNvbS5vY3RvcHVzLnNobGlzdDAFDANh
+cHAMF2NvbS5vY3RvcHVzLnNobGlzdC52b2lwMAYMBHZvaXAMH2NvbS5vY3RvcHVz
+LnNobGlzdC5jb21wbGljYXRpb24wDgwMY29tcGxpY2F0aW9uMA0GCSqGSIb3DQEB
+CwUAA4IBAQB1ooTJW7aLnW9OluGOUrqhCU2ZuTjLOED3sq2xx/BDIGX8m0jJmf1o
++2vkgn9YfAd6bM47QI1qPs0hbJYrxkW1c97RnHgXY0DKOoZvG8WDu8ImZp9ildgL
+eg7Ohq6HvBWi1VRCSMaISnEWDuPLcY5tZmFIjytpRzVZGg69ePs8LsQpMdRWedN3
+kz2Kz6dBzSt4z9Gkl8OTfT9ae5IIrcfJjW7cDlJP8vZPVDzuaXhb+PNNrufJRQ4t
+q/Edk02q45OxofSPv2rbCMzaPpzgz7B954OqSXxIPyOIBTvAmokn3O9LKEVu/M6z
+DXk1CxiFBU6+YFDuupx3MSzicP8KBncM
+-----END CERTIFICATE-----
diff --git a/ssl/notes.txt b/ssl/notes.txt
@@ -1,9 +1,19 @@
-Our certificates in ssl/ are provided by let's encrypt.
+ Server
+========
+
+Our certificates in this directory are provided by let's encrypt.
I think they will expire in 2016-03.
To get a certificate that IO::Socket::SSL will like, you have to concatenate
cert.pem and chain.pem to produce cert_chain.pem.
-Also, concatenating cert.pem and fullchain.pem works, but fullchain.pem has a
-larger file size. I'm unsure at this point which one is (more) correct, as they
-both work.
+
+ APN
+=====
+
+apn/ directory has all apple push notification certificates and keys.
+
+- apn/aps.key: 2048 bit rsa private key
+- apn/aps.csr: certificate signing request, created from aps.key
+- apn/aps.cer: DER encoded certificate from Apple, created from aps.csr
+- apn/aps.pem: conversion of aps.cer to PEM format for use in program