PHPのimap_openでExchange Server 2007への接続に失敗する

必要があってPHPでMicrosoft Exchange Server 2007のサーバにIMAPの接続をするような設定を行っていたのだけれど、いくらやっても接続に失敗する。最終的にはうまくいったけれど、今後のためにもメモ。

まず失敗したときのPHPコードだけど、これ自体は簡単なもので、

$imap_stream = imap_open('{example.com:143/imap/notls}INBOX', 'user', 'password');
if ($imap_stream) {
    echo "ok\n";
    imap_close($imap_stream);
}
else {
    echo "fail\n";
}

みたいな感じ。これでたとえばphpコマンドから直接実行すると、エラーメッセージには見慣れない

PHP Notice:  Unknown: Kerberos error: Unknown code krb5 195 (try running kinit) for example.com (errflg=1) in Unknown on line 0

のような文字列が出る。一般的なメールソフトやtelnetによるプロトコルの直接操作でも問題ないことは確認済み。いったいなぜなんだと悩んでいたら、認証方式が問題だった。

相手のExchangeサーバにtelnetでつないで、

? CAPABILITY

と実行すると、

* CAPABILITY IMAP4 IMAP4rev1 AUTH=NTLM AUTH=GSSAPI AUTH=PLAIN IDLE NAMESPACE LITERAL+
? OK CAPABILITY completed.

というような結果が返ってくる。で、問題はAUTH=GSSAPIの部分。ExchangeサーバではActiveDirectoryとの連携による認証方式がサポートされている。その認証方式を表すのが、おそらくGSSAPIの部分。これがPHPのIMAPモジュールの認証方式と関係してくる。

PHPのIMAPモジュールでは、Kerberosが有効な状態でビルドされていると、GSS-API認証方式が有効になる。php_imap.cの関連部分のコードを抜き出してみると(バージョンは5.2.11)、

#ifndef PHP_WIN32
    auth_link(&auth_log);       /* link in the log authenticator */
    auth_link(&auth_md5);       /* link in the cram-md5 authenticator */
#if HAVE_IMAP_KRB && defined(HAVE_IMAP_AUTH_GSS)
    auth_link(&auth_gss);       /* link in the gss authenticator */
#endif
    auth_link(&auth_pla);       /* link in the plain authenticator */
#endif

のようになっている。PLAIN認証より先にGSS-API認証が来てる。さらに先ほどのExchangeサーバの応答では、LOGとCRAM-MD5での認証は使えない。とすると、PHPからはGSS-API認証を実行するようになり、その準備がきちんと行われていない場合、認証に失敗して接続ができない、ということになる。先ほどの得体のしれないエラーメッセージも、ActiveDirectoryでの認証に必要なKerberosの設定ができていないということを示していたみたいだ。

問題を解決するには、たとえばESAdminにあるような形でkerberosの設定とクライアントの認証を行って、チケットを取得しておく必要があるようだ。エラーメッセージのkinitはまさにチケット取得のためのコマンドである。調べてみたら、kinitはCentOS 5ではkrb5-workstationというパッケージに含まれていた。

でも、残念ながら今回は、自分で管理しているActiveDirectoryサーバじゃないので、Kerberosの設定に必要なRealmその他の情報が全くわからない。仕方がないのでPHPのIMAPモジュールを、Kerberosを外した状態で再コンパイルした。Kerberosを外して再コンパイルするには、CentOS 5の場合、IMAPモジュールが使うlibc-clientの設定が関係してくる。CentOS 5の標準のlibc-clientパッケージのように、もしこれがKerberosを有効な状態でコンパイルしてあると、PHPのconfigureがそれを検知して、configureのオプションにwith-kerberosをつけろと要求してくる。回避するためには、 /usr/include/imap/linkage.h の中の

extern AUTHENTICATOR auth_gss;

を削除しておかなければいけない。削除した上で、configureオプションにwithout-kerberosをつけてIMAPモジュールを作ればよい。こうしてできたIMAPモジュールをインストールしてから接続を試せば、さっきのサーバではPLAIN方式しか有効ではないので、それで認証を行ってきちんとログインできるようになる。

blog/2009/12/phpのimap_openでexchange_server_2007への接続に失敗する.txt · 最終更新: 2009/12/03 23:01 by zushi
CC Attribution-Noncommercial-Share Alike 3.0 Unported www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0