2013/10/09

z-pushとの闘い

まずは何も考えずダウンロードしてみる。

http://z-push.sourceforge.net/soswp/

# tar xzf z-push-2.1.0-1750.tar.gz
# cd z-push-2.1.0-1750
# ls
INSTALL  LICENSE  backend  config.php  include  index.php  lib  tools  version.php  z-push-admin.php  z-push-top.php

とりあえずINSTALLを読む。

サーバ要件:PHP5.1以上

ということは、PHP5.1とapacheの環境があればよいということか。

まずはDNS名(app.example.net)を用意する。

続いて鍵+証明書を作り、これをSSLサイトに食わせておく。

# openssl req -x509 -days 365 -newkey rsa:2048 -nodes -keyout app.example.net.key -out app.example.net.crt

インストールは書いてある通りにやってみよう。prefixは/usr/localにしてみる。
# sudo tar xzf z-push-2.1.0-1750.tar.gz -C /usr/local/share
# mkdir /var/lib/z-push /var/log/z-push
# chown apache:apache /var/lib/z-push /var/log/z-push
# vi /etc/httpd/conf.d/ssl.conf
# httpd -t
# service httpd reload

--- /etc/httpd/conf.d/ssl.conf      (before)
+++ /etc/httpd/conf.d/ssl.conf      (after)
@@ -81,5 +81,14 @@
        AllowOverride   all
   </Directory>

+
+       Alias /Microsoft-Server-ActiveSync /usr/local/share/z-push/index.php
+  <directory /usr/local/share/z-push>
+       php_flag magic_quotes_gpc off
+       php_flag register_globals off
+       php_flag magic_quotes_runtime off
+       php_flag short_open_tag on
+  </Directory>
+
  </VirtualHost>
 </IfModule>
というわけで、予想通りはまる。
なんか言ってる。
PHP-MAPI extension is not available

調べてみたところ、一部のパッケージが足りていなかったもよう。
# yum install php-imap php-soap php-process

と思ったら、php-processはPHP5.3のパッケージなのね。
あきらめて、php-*系のパッケージを全部捨てて、php53-*をインストール。

# rpm -e php php-たくさん
# yum install php-process php

やってみたがまだ動かぬ。
php-mapiってどこにあるんだよ!!
とりあえず「php-mapi rpm」で適当に探してくる。

.....fedoraprojectに落ちてたぽい。

# rpm -ivh php53-mapi-7.0.13-1.el5.i386.rpm
エラー: 依存性の欠如:
libicudata.so.36 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libicui18n.so.36 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libicuuc.so.36 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libinetmapi.so.1 は php53-mapi-7.0.13-1.el5.i386 に必要とされています
libmapi.so.0 は php53-mapi-7.0.13-1.el5.i386 に必要とされています

ぬおー。片っ端から探していれちまえ。
# rpm -ivh libmapi-7.0.13-1.el5.i386.rpm php53-mapi-7.0.13-1.el5.i386.rpm
エラー: 依存性の欠如:
libboost_filesystem-mt.so.5 は libmapi-7.0.13-1.el5.i386 に必要とされています
libboost_system-mt.so.5 は libmapi-7.0.13-1.el5.i386 に必要とされています
libical.so.0 は libmapi-7.0.13-1.el5.i386 に必要とされています
libicalss.so.0 は libmapi-7.0.13-1.el5.i386 に必要とされています
libvmime.so.0 は libmapi-7.0.13-1.el5.i386 に必要とされています
zarafa-client = 7.0.13-1.el5 は libmapi-7.0.13-1.el5.i386 に必要とされています

えー。zarafa-clientが出てきたってことは、結局zarafaから落とした方がいいの?
でもさっきからEPELのパッケージ使ってるし….よし、ポリシーを緩めてEPEL解禁!
# rpm -ivh epel-release-5-4.noarch.rpm
# yum install php53-mapi
Dependencies Resolved
========================================================================================================================
Package                           Arch               Version                                  Repository          Size
========================================================================================================================
Installing:
php53-mapi                        i386               7.0.13-1.el5                             epel               217 k
Installing for dependencies:
boost141-filesystem               i386               1.41.0-4.el5                             epel                73 k
boost141-system                   i386               1.41.0-4.el5                             epel                25 k
libgsasl                          i386               0.2.29-1.el5                             epel               100 k
libical                           i386               0.48-1.el5                               epel               202 k
libmapi                           i386               7.0.13-1.el5                             epel               904 k
libntlm                           i386               1.0-1.el5                                epel                43 k
libvmime                          i386               0.9.2-0.1.20110626svn.el5                epel               887 k
zarafa-client                     i386               7.0.13-1.el5                             epel               1.3 M
zarafa-common                     i386               7.0.13-1.el5                             epel                22 k
Transaction Summary
========================================================================================================================
Install      10 Package(s)
Upgrade       0 Package(s)
Total download size: 3.7 M

Is this ok [y/N]: 

まぢで?そういうオチ?
とりあえず入れてみる…..入った。
気を取り直してapacheリロード。
# httpd -t
Syntax OK
# service httpd reload

とりあえず500はなくなった。

続いて、config.phpをいじって、imapバックエンドを使うように変更。
--- /usr/local/share/z-push/config.php     (before)
+++ /usr/local/share/z-push/config.php     (after)
@@ -45,7 +45,7 @@
*  Default settings
*/
// Defines the default time zone, change e.g. to "Europe/London" if necessary
-    define('TIMEZONE', '');
+    define('TIMEZONE', 'Asia/Tokyo');
// Defines the base path on the server
define('BASE_PATH', dirname($_SERVER['SCRIPT_FILENAME']). '/');
@@ -90,7 +90,7 @@
define('LOGFILE', LOGFILEDIR . 'z-push.log');
define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
define('LOGLEVEL', LOGLEVEL_INFO);
-    define('LOGAUTHFAIL', false);
+    define('LOGAUTHFAIL', true);


// To save e.g. WBXML data only for selected users, add the usernames to the array
@@ -185,7 +185,7 @@
*  Backend settings
*/
// the backend data provider
-    define('BACKEND_PROVIDER', '');
+    define('BACKEND_PROVIDER', 'BackendIMAP');

/**********************************************************************************
*  Search provider settings

んで、imap側のconfig.phpもいじる。
--- /usr/local/share/z-push/backend/imap/config.php     (before)
+++ /usr/local/share/z-push/backend/imap/config.php     (after)
@@ -46,13 +46,13 @@
// ************************

// Defines the server to which we want to connect
-define('IMAP_SERVER', 'localhost');
+define('IMAP_SERVER', '127.0.0.1');
// connecting to default port (143)
-define('IMAP_PORT', 143);
+define('IMAP_PORT', 993);
// best cross-platform compatibility (see http://php.net/imap_open for options)
-define('IMAP_OPTIONS', '/notls/norsh');
+define('IMAP_OPTIONS', '/tls/norsh');

// overwrite the "from" header if it isn't set when sending emails
// options: 'username'    - the username will be set (usefull if your login is equal to your emailaddress)

で、iPhone側でExchangeアカウントをセット。
やってみるが"Connection Serfer Failed."などと言って一歩も動かない。
アカウント追加時の認証チェックは通っていたぽいので、パスワード周りは間違っていないはず。。。

しかし動かず。
とりあえず、いろんなところのデバッグフラグをONにしてみる。

--- /usr/local/share/z-push/config.php (before)
+++ /usr/local/share/z-push/config.php (after)
@@ -89,7 +89,7 @@
     define('LOGFILEDIR', '/var/log/z-push/');
     define('LOGFILE', LOGFILEDIR . 'z-push.log');
     define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
-    define('LOGLEVEL', LOGLEVEL_INFO);
+    define('LOGLEVEL', LOGLEVEL_DEBUG);
     define('LOGAUTHFAIL', true);

--- /usr/local/share/z-push/config.php  (before)
+++ /usr/local/share/z-push/config.php  (after)
@@ -52,7 +52,7 @@
 define('IMAP_PORT', 993);

 // best cross-platform compatibility (see http://php.net/imap_open for options)

-define('IMAP_OPTIONS', '/tls/norsh');
+define('IMAP_OPTIONS', '/tls/norsh/debug');

 // overwrite the "from" header if it isn't set when sending emails
 // options: 'username'    - the username will be set (usefull if your login is
equal to your emailaddress)

しかしまだ動かない。
webでアクセスしてみても、しばらく待ってから再度認証を求められ、その直前に下記のようなログが出る。
/usr/local/share/z-push-2.1.0-1750/backend/imap/imap.php:99 imap_open(): Couldn't open stream {127.0.0.1:993/imap/tls/norsh/debug} (2)

気づいた。オレオレ証明書じゃん。
というわけで、接続オプションを変更。
--- /usr/local/share/z-push/config.php  (before)
+++ /usr/local/share/z-push/config.php  (after)
@@ -52,7 +52,7 @@
 define('IMAP_PORT', 993);

 // best cross-platform compatibility (see http://php.net/imap_open for options)

-define('IMAP_OPTIONS', '/tls/norsh/debug');
+define('IMAP_OPTIONS', '/tls/norsh/novalidate-cert');

 // overwrite the "from" header if it isn't set when sending emails
 // options: 'username'    - the username will be set (usefull if your login is
equal to your emailaddress)
まだ動かない。
imap_open()でコケると言っているが、dovecotのログがぜんぜんにぎやかじゃない。どーゆーことだ???
ということは、認証かセッション確立でこけてると予想。
imap_open()を使って直接たたいてみる。

imap_open("{127.0.0.1/tls/norsh/novalidate-cert}INBOX", $username, $password);


しっかり60秒待ってからエラーが表示された。
うーん、セッション確立の影響だなぁ。

で、下記のように変えてみた。
--- /usr/local/share/z-push/config.php  (before)
+++ /usr/local/share/z-push/config.php  (after)
@@ -52,7 +52,7 @@
 define('IMAP_PORT', 993);

 // best cross-platform compatibility (see http://php.net/imap_open for options)

-define('IMAP_OPTIONS', '/tls/norsh/novalidate-cert');
+define('IMAP_OPTIONS', '/ssl/norsh/novalidate-cert');

 // overwrite the "from" header if it isn't set when sending emails
 // options: 'username'    - the username will be set (usefull if your login is equal to your emailaddress)

StartTLSによるSSL確立ではなく、最初からSSLで突っ込むようにしてみた。
お!動いた!!



というわけで、今回の反省。
いろんな環境を整理して調査にあたる必要がありますね。
  • imapのSSL状態。 どっちが直接の原因となるかは分からないけど、iPhoneでUse SSLを有効にしてるため、もしくはdovecot.confで「protocols=imaps」としているため、のいずれかもしくは両方の理由により、imap_open()のフラグに「/ssl」が必要。「/tls」ではだめ。
  • 証明書。 自前でやる場合はそんなにお金かけてられないので、往々にしてオレオレ証明書を利用することに。dovecotから見れば、z-pushは当然普通のクライアントなので、当然証明書はチェックされます。なので、人的介入無しに証明書エラーをくぐり抜ける必要があります。
  • ログはよく観察すること! いろんなログ(今回の場合はapache/dovecot/z-push)を見ましたが、特定のログだけを見ていても気づかないことが多いです。それぞれのコンポーネントがどのように連携しているのか?イベントが発生したタイミングで、どのログが流れてどのログが流れないのか?このあたりをちゃんと考慮してログを見ると、どこの部分でエラーが発生しているかのアタリがつけやすくなります。
というわけで、おしまいっ