2000年05月23日 (火)

* sendmail 8.10.1 で SMTP AUTH

覚え書き。時間ができたらしっかりまとめまたいと思いますが、とりあえず、時系列と作業の依存関係はグチャグチャのまま。
MTA
FreeBSD 4.0-RELEASE + Cyrus SASL 1.15.5 + sendmail 8.10.1
MUA
XEmacs 21.1.9 + Mew 1.95b35
という環境で、CRAM-MD5 を使って SMTP AUTH 認証を行う話。
下準備
sendmail 8.10.1 で SMTP AUTH 機能を使うには Cyrus SASL (Simple Authentication and Security Layer) ライブラリをリンクして、SASL の提供する認証機能を利用する。まずは Cyrus SASL をインストールし、saslpasswd コマンドを使ってユーザの登録を行う。
root@tole# saslpasswd issei
Cyrus IMAP サーバの imtest などを使って、SASL データベースへの登録/検索が行えることを確認しておく。一時的に、sasldb は cyrus imapd 権限で読めるように設定しておき、テストが終わったら chown root, chmod 600 する。

sendmail を次の設定で再コンパイルする。IPv6 不要な場合には -DNETINET6 は削除。

devtools/Site/site.config.m4

APPENDDEF(`confENVDEF', `-DSASL -DNETINET6')
APPENDDEF(`conf_sendmail_LIBS', `-lsasl')
APPENDDEF(`confLIBDIRS', `-L/usr/local/lib')
APPENDDEF(`confINCDIRS', `-I/usr/local/include/sasl')
次に sendmail.cf を作る。現時点では、CF は sendmail 8.10.1 には対応していないようなので、sendmail に含まれる cf を利用して作成する。蝙蝠本と cf/REAADME を参照。雛形は cf/m4 以下にあるので、これも眺めておく。

freebsd-auth.mc

divert(0)dnl
VERSIONID(`freebsd-auth')
OSTYPE(bsd4.4)dnl
DOMAIN(generic)dnl
#
FEATURE(always_add_domain)dnl
FEATURE(nouucp,reject)dnl
FEATURE(smrsh)dnl
MAILER(local)dnl
MAILER(smtp)dnl
#
define(`_REC_END_', `for $u; $|;
        $.$b$?g
        (envelope-from $g)$.')
define(`confRECEIVED_HEADER', `_REC_HDR_
        _REC_FULL_AUTH_)
        $.by $j ($v/$Z)$?r with $r$.$?{daemon_family}/${daemon_family}$. id $i$?u
        _REC_END_')
define(`confTO_IDENT',`5s')
define(`confPRIVACY_FLAGS',`authwarnings,noexpn,noreceipts,novrfy')
DAEMON_OPTIONS(`Family=inet,Family=inet6')dnl
TRUST_AUTH_MECH(`DIGEST-MD5,CRAM-MD5')dnl
肝要なのは OSTYPE, MAILER と TRUS_AUTH_MECH に利用する認証メカニズムを列挙する部分。上のファイルでは、セキュリティ関係をちょっと強化した上で、Received: ヘッダに比較的詳しい情報を出力するようにしてある。デバッグ用。

GNU m4 を使って sendmail.cf を作成

% gm4 cf/m4/cf.m4 /some/where/freebsd-auth.mc > freebsd-auth.cf
sendmail.cf ファイルの準備ができたところで、sendmail が SMTP AUTH 付きでコンパイルできていることを確認する。この際、sendmail が sasldb ファイルにアクセスするので root 権限で実行すること。
root@tole# ./obj.FreeBSD.4.0-STABLE.i386/sendmail/sendmail -bs -C ./freebsd-auth.cf 
220 tole.issei.org ESMTP Sendmail 8.10.1/8.10.1; Tue, 23 May 2000 04:18:15 +0900 (JST)
EHLO localhost
250-tole.issei.org Hello root@localhost, pleased to meet you
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-SIZE
250-ONEX
250-ETRN
250-XUSR
250-AUTH DIGEST-MD5 CRAM-MD5
250 HELP
QUIT
AUTH の行が表示されていれば OK。ダメならログファイルを見てチェック (ありがちなミスは、sasldb のパーミションが 600 でないこと)。詳しいログを出力したければ -O LogLevel=99 する。

問題なければ sendmail と sendmail.cf をインストールする。FreeBSD 4.0-RELEASE を使うなら、mailwrapper の設定を活用すると管理が楽。
しかし、一筋縄では行かなくて
これで MTA 側の準備は完了ということで、早速Mew 1.95b35 を使って SMTP AUTH の動作確認を行うと、認証に失敗する。同じ SASL ライブラリを使っている Cyrus IMAP サーバを imtest (1) で叩いてみると、CRAM-MD5, DIGST-MD5 とも認証が行えているので、SASL 側には問題なし。

sendmail <-> mew の間の TCP/IP パケットをダンプして解析する限りでは、両者の間の通信には問題がないように見える。

sendmail の設定ミスでもなさそうだし、ということで SASL と sendmail のソースコードを眺めて、問題が出ているところの前後に syslog() を挟んで、変数の値を書き出させてみる。その結果、Cyrus IMAP サーバと sendmail 8.10.1 では SASL の内部関数getsecret() に渡ってくる値が違っていることが判明する。
May 23 03:44:23 tole sasl/getsecret[73495]: key = issei, key_len = 15, mechanism = CRAM-MD5, realm =  
May 23 03:44:59 tole sasl/getsecret[73498]: key = issei, key_len = 29, mechanism = CRAM-MD5, realm = tole.issei.org 
上が sendmail の場合、下が Cyrus IMAP サーバの場合。getsecret() を呼び出している sendmail 側の関数を辿っていくと、sendmail/srvsmtp.c にある smtp() 関数に行き着く。

sendmail/srvsmtp.c から抜粋

# if SASL
        sasl_ok = FALSE;        /* SASL can't be used (yet) */
        n_mechs = 0;

        /* SASL server new connection */
        hostname = macvalue('j', e);
#  if SASL > 10505
        /* use empty realm: doesn't work in SASL <= 1.5.5 */
        result = sasl_server_new("smtp", hostname, "", NULL, 0, &conn);
#  else /* SASL > 10505 */
        /* use no realm -> realm is set to hostname by SASL lib */
        result = sasl_server_new("smtp", hostname, NULL, NULL, 0, &conn);
#  endif /* SASL > 10505 */
マクロ SASL は sendmail.h の中で再定義されていて、Cyrus SASL 1.15.5 では結局 10515 になるので sasl_server_new("smtp", hostname, "", NULL, 0, &conn); が呼び出される。

ところが Cyrus SASL 1.15.5 の saslpasswd でユーザを登録すると、デフォルトでは realm がホスト名となってしまうので、不一致が生じることになる。今回は、SASL のバージョンによらず realm として "sendmail" を使うようにソースファイルを書き換えて対処することに。

登録し直し

# saslpasswd -u sendmail issei
できあがり

SMTP AUTH を使って送信したメールの例

Return-Path: issei@issei.org
Received: from tole.issei.org (IDENT:ef4Dc0k9rDMSlYM7kcuo1vTWXMNzuXTENf0bJzQTVWGXn+DYSgQH2hH4M5LNGH9+@tole.issei.org [3ffe:505:a:1:200:f8ff:fe05:9fa2])
        by mx1.issei.org (8.10.1/8.10.1) with ESMTP id e4MMYSw11239
        for <issei@issei.org>; Tue, 23 May 2000 07:34:28 +0900 (JST)
        (envelope-from issei@issei.org)
Received: from localhost (IDENT:M0rytTE9Poqk/I43wsxANrCNzCJPnNhu3MdNcNfCs3NqSW3TMqgxNPUrLZHqpjcK@tole.issei.org [3ffe:505:a:1:200:f8ff:fe05:9fa2])
        (authenticated as issei with CRAM-MD5)
        by tole.issei.org (8.10.1/8.10.1) with ESMTP id e4MMYSs10924
        for <issei@issei.org>; Tue, 23 May 2000 07:34:28 +0900 (JST)
        (envelope-from issei@issei.org)
Message-Id: <20000523.073425.58909708.issei@issei.org>
Mime-Version: 1.0
X-UIDL: bc0d340a59acbd196b0679c99ed2ead0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Subject: test
From: Issei Suzuki <issei@issei.org>
To: issei@issei.org
Date: Tue, 23 May 2000 07:34:25 +0900 (JST)
X-Mailer: Mew version 1.95b35 on XEmacs 21.1 (Canyonlands)

OK?

© Copyright 2001 Issei Suzuki <issei@issei.org>
$Issei: smtpauth.html,v 1.2 2002/09/23 13:00:49 issei Exp $