exim4でsmtpauth

http://www.exim.org/eximwiki/FAQ/Policy_controls/Q0730
を参考にするとうまくいった。
/etc/exim4/exim4.conf.templateを編集する。
(2008/11/3注)
その後、実はちゃんと動いていないことが判明。TLSも含めて動くようにしました。

  • exim4.conf の先頭にの方に、AUTHDAEMON_SOCKETとacl_smtp_authが無いといけない。
  • /etc/exim4/conf.d/main/00_localmacrosという名前で、以下の内容を加える。
  • TLS/SSLconfigureationのすぐ下に、「MAIN_TLS_ENABLE = true」を加える。
MAIN_TLS_ENABLE = true
AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS = true
SYSTEM_ALIASES_PIPE_TRANSPORT = address_pipe
AUTH_PLAINTEXT = true
------------
*** exim4.conf.template.orig    2006-07-29 12:17:17.911222000 +0900
--- exim4.conf.template.2       2006-07-29 18:44:57.911222000 +0900
***************
*** 1,6 ****
--- 1,8 ----
  #####################################################
  ### main/01_exim4-config_listmacrosdefs
  #####################################################
+ #for SMTP_AUTH in MD5
+ AUTHDAEMON_SOCKET=/var/run/courier/authdaemon/socket
+ acl_smtp_auth = acl_check_auth

  ######################################################################
  #      Runtime configuration file for Exim 4 (Debian Packaging)      #
*************** CHECK_RCPT_REMOTE_LOCALPARTS = ^[./|] :
*************** begin acl
*** 400,405 ****
--- 401,409 ----

  ### acl/20_exim4-config_whitelist_local_deny
  #################################
+ # For SMTP_AUTH MD5
+ acl_check_auth:
+  accept set acl_c0 = <$pid.$tod_epoch@$primary_hostname>

  # This is used to determine whitelisted senders and hosts.
  # It checks for CONFDIR/local_host_whitelist and
*************** begin authenticators
*** 1493,1524 ****
  # advertise on unencrypted connections by default. You can set
  # AUTH_SERVER_ALLOW_NOTLS_PASSWORDS to advertise unencrypted clear text
  # password based authenticators on all connections.
!
! plain_server:
!   driver = plaintext
!   public_name = PLAIN
!   server_condition = "${if crypteq{$3}{${extract{1}{:}{${lookup{$2}lsearch{CONFDIR/passw
d}{$value}{*:*}}}}}{1}{0}}"
!   server_set_id = $2
!   server_prompts = :
!   .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
!   server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
!   .endif
!
! login_server:
!   driver = plaintext
!   public_name = LOGIN
!   server_prompts = "Username:: : Password::"
!   server_condition = "${if crypteq{$2}{${extract{1}{:}{${lookup{$1}lsearch{CONFDIR/passw
d}{$value}{*:*}}}}}{1}{0}}"
!   server_set_id = $1
!   .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
!   server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
!   .endif
!
! cram_md5_server:
!   driver = cram_md5
!   public_name = CRAM-MD5
!   server_secret = ${extract{2}{:}{${lookup{$1}lsearch{CONFDIR/passwd}{$value}fail}}}
!   server_set_id = $1

  # Here is an example of CRAM-MD5 authentication against PostgreSQL:
  #
--- 1499,1530 ----
  # advertise on unencrypted connections by default. You can set
  # AUTH_SERVER_ALLOW_NOTLS_PASSWORDS to advertise unencrypted clear text
  # password based authenticators on all connections.
! #
! #plain_server:
! #  driver = plaintext
! #  public_name = PLAIN
! #  server_condition = "${if crypteq{$3}{${extract{1}{:}{${lookup{$2}lsearch{CONFDIR/pass
wd}{$value}{*:*}}}}}{1}{0}}"
! #  server_set_id = $2
! #  server_prompts = :
! #  .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
! #  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
! #  .endif
!
! #login_server:
! #  driver = plaintext
! #  public_name = LOGIN
! #  server_prompts = "Username:: : Password::"
! #  server_condition = "${if crypteq{$2}{${extract{1}{:}{${lookup{$1}lsearch{CONFDIR/pass
wd}{$value}{*:*}}}}}{1}{0}}"
! #  server_set_id = $1
! #  .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
! #  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
! #  .endif
! #
! #cram_md5_server:
! # driver = cram_md5
! #  public_name = CRAM-MD5
! #  server_secret = ${extract{2}{:}{${lookup{$1}lsearch{CONFDIR/passwd}{$value}fail}}}
! #  server_set_id = $1

  # Here is an example of CRAM-MD5 authentication against PostgreSQL:
  #
*************** cram_md5_server:
*** 1664,1701 ****
  # You can set AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS to allow unencrypted
  # clear text password authentication on all connections.

! cram_md5:
!   driver = cram_md5
!   public_name = CRAM-MD5
!   client_name = ${extract{1}{:}{${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fa
il}}}
!   client_secret = ${extract{2}{:}{${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}
fail}}}

  plain:
    driver = plaintext
    public_name = PLAIN
! .ifndef AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS
!   client_send = "${if !eq{$tls_cipher}{}{\
!                      ^${extract{1}{::}\
!                      {${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fail}}}\
!                    ^${extract{2}{::}\
!                      {${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fail}}}\
!                  }fail}"
! .else
!   client_send = "^${extract{1}{::}{${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value
}fail}}}^${extract{2}{::}{${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fail}}}"
! .endif

! login:
    driver = plaintext
!   public_name = LOGIN
! .ifndef AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS
!   client_send = "${if !eq{$tls_cipher}{}{}fail}\
!                  : ${extract{1}{::}\
!                       {${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fail}}} \
!                : ${extract{2}{::}\
!                    {${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fail}}}"
! .else
!   client_send = ": ${extract{1}{::}{${lookup{$host}lsearch*{CONFDIR/passwd.client}{$valu
e}fail}}} : ${extract{2}{::}{${lookup{$host}lsearch*{CONFDIR/passwd.client}{$value}fail}}}
"
! .endif
  #####################################################
  ### end auth/30_exim4-config_examples
  #####################################################
--- 1670,1708 ----
  # You can set AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS to allow unencrypted
  # clear text password authentication on all connections.

! # LOGIN authenticator

+ login:
+   driver = plaintext
+   public_name = LOGIN
+   server_prompts = Username:: : Password::
+   server_condition = ${extract {address} {${readsocket{AUTHDAEMON_SOCKET} \
+     {AUTH ${strlen:exim\nlogin\n$1\n$2\n}\nexim\nlogin\n$1\n$2\n} }} {yes} fail}
+   server_set_id = $1
+
+ # PLAIN authenticator
  plain:
    driver = plaintext
    public_name = PLAIN
!   server_prompts = :
!   server_condition = ${extract {address} {${readsocket{AUTHDAEMON_SOCKET} \
!     {AUTH ${strlen:exim\nlogin\n$2\n$3\n}\nexim\nlogin\n$2\n$3\n} }} {yes} fail}
!   server_set_id = $2

! cram_md5:
    driver = plaintext
!   public_name = CRAM-MD5
!   server_prompts = $acl_c0
!   server_set_id = ${sg {${extract {1}{ }{$1} }} {[^a-zA-Z0-9.-_]} {?}}
!   server_condition = ${if eq \
!     {${extract {address} \
!       {${readsocket{AUTHDAEMON_SOCKET} \
!         {AUTH ${strlen:exim\ncram-md5\n${str2b64:$acl_c0}\n${str2b64:$1}\n}\nexim\ncram-
md5\n${str2b64:$acl_c0}\n${str2b64:$1}\n} \
!       }} \
!     {$value} fail}} \
!     {${extract {1}{ }{$1} }} \
!     {yes}}
!
  #####################################################
  ### end auth/30_exim4-config_examples
  #####################################################

修正後 /etc/exim4/update-exim4.conf.confをチェックして

  • update-exim4.conf -v ; /etc/init.d/exim4 restart

を実行して設定ファイルを作成する。また、パスワードについては、

  • userdbpw -hmac-md5 | userdb users/XXX set hmac-md5pw

で設定済みのはずです。ただし、MD5では無い場合をテストに使ったので、その場合、authdaemonはeximpwかsystempwを見に行きます。そこで、eximpwも設定しておきます。

  • userdbpw | userdb users/XXX set eximpw
  • /etc/init.d/authdaemon restart; /etc/init.d/exim4 restart

で再起動します。
*確認方法 (2008/11/3追加)

  • パスワードは userdb -show users/XXX で、 hmac-md5pwやeximpwがあることを確認。
  • eximの機能についてはtelnet localhost 25で、
elnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 arches ESMTP Exim 4.50 Mon, 03 Nov 2008 22:08:19 +0900
EHLO localhost
250-XXXXX Hello localhost [127.0.0.1]
250-SIZE 52428800
250-PIPELINING
250-AUTH LOGIN PLAIN CRAM-MD5
250-STARTTLS
250 HELP
AUTH PLAIN XXXXXXXXXXXXXXXXXXXXX==
235 Authentication succeeded
QUIT

の様に試すことができる。/var/log/exim4/mainlogも参照のこと。
「250-AUTH LOGIN PLAIN CRAM-MD5」が出れば、SMTP AUTHが使えるようになっており、「250-STARTTLS」があれば、TLSが使えるようになっている。
AUTH PLAIN の後に続くXXXXXXXXXXXXX==は、

perl -MMIME::Base64 -e 'print encode_base64("user名\0user名\0パスワード");'

で表示される文字列。

Authenticationに失敗する場合は、/etc/courier/authdaemonrc の最初に DEBUG_LOGIN=1の行を追加して、/etc/init.d/authdaemon restartし、tail -f /var/log/syslog で、様子を見る。