SMTP-AUTHでtelnetの認証失敗

SMTP-AUTHの認証失敗でドハマリ。
メールクライアントからはSMTP-AUTHで接続できていたが、telnetを使用して確認した時に認証失敗して一苦労。

■事象

SMTP-AUTHのPLAIN認証を確認するため、"ユーザ名\0ユーザ名\0パスワード"の形式で、BASE64エンコードする。

[root@dev ~]# perl -MMIME::Base64 -e 'print encode_base64("user01\0user01\0passwd");'
dXNlcjAxAHVzZXIwMQBwYXNzd2Q=

以下の様な感じで、認証に失敗する。

[root@dev ~]# telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 dev.larcaim.intra ESMTP MailServer
EHLO dev.larcaim.intra
250-dev.larcaim.intra
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-AUTH PLAIN
250-AUTH=PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN dXNlcjAxAHVzZXIwMQBwYXNzd2Q=
535 5.7.8 Error: authentication failed: 
■原因

今回の事象の原因は以下の2つ。
1.そもそも認証時の書式が間違っている。
正しくは"ユーザ名\0パスワード"。
2.BASE64エンコード時のエスケープが間違っている
NULL値をエスケープする場合に、「"」と「'」の使い方で結果が異なる。
[root@dev ~]# perl -MMIME::Base64 -e "print encode_base64('user01\0user01\0passwd');"
dXNlcjAxXDB1c2VyMDFcMHBhc3N3ZA==
[root@dev ~]# perl -MMIME::Base64 -e 'print encode_base64("user01\0user01\0passwd");'
dXNlcjAxAHVzZXIwMQBwYXNzd2Q=

■対処

"ユーザ名\0パスワード"の形式で、BASE64エンコードする。クォートの使い方を正す。

[root@dev ~]# perl -MMIME::Base64 -e "print encode_base64('user01\0passwd');"
dXNlcjAxXDBwYXNzd2Q=
■調査

そもそも解決の糸口となったのは、以下のサイト。
Chiral Software, Inc. GSA IT70 Java, Android, security software developers in Los Angeles
http://chiralsoftware.com/linux-system-administration/secure-relaying-postfix-sasl-tls-dovecot.seam
このサイトではJarファイルをダウンロードすることで、Javaで簡単にBase64エンコードできる方法が記載されているが、
この方法で、生成した文字列でSMTP-AUTH認証に成功した。(使い所少ないけど、Perlエンコードより覚えやすい)
Base64可逆なのでデコードしてみると、書式が間違っていることが判明。
さらに、PerlBase64エンコードする場合、NULL値をエスケープすると「"」と「'」の使い方で結果が異なることがわかった。

# 「'」でエンコード
[root@dev ~]# perl -MMIME::Base64 -e "print encode_base64('user01\0user01\0passwd');"
dXNlcjAxXDB1c2VyMDFcMHBhc3N3ZA==
# 「"」でエンコード
[root@dev ~]# perl -MMIME::Base64 -e 'print encode_base64("user01\0user01\0passwd");'
dXNlcjAxAHVzZXIwMQBwYXNzd2Q=

# エンコードした文字列をデコードする
[root@dev ~]# perl -MMIME::Base64 -e "print decode_base64('dXNlcjAxXDB1c2VyMDFcMHBhc3N3ZA==');"
user01\0user01\0passwd
[root@dev ~]# perl -MMIME::Base64 -e "print decode_base64('dXNlcjAxAHVzZXIwMQBwYXNzd2Q=');"
user01user01passwd

# NULL値(\0)がなければ、結果は変わらない。
[root@dev ~]# perl -MMIME::Base64 -e 'print encode_base64("user");'
dXNlcg==
[root@dev ~]# perl -MMIME::Base64 -e "print encode_base64('user');"
dXNlcg==

よって、SMTP-AUTH時に、認証メカニズムでLOGINから認証している場合は、おそらくエンコード結果が変わらないので問題なかったはず。
PLAINでの書式でNULL値が入っていたため、結果が異なり困った。
ほとんどのサイトで上記設定でイケてるようなので、そもそもOpenVPS上でやってる自分の環境がおかしいのかもしれない。

Dovecot2やLDAP2.4など、アップデートされた構築は一苦労。CentOS5から6に乗り換えてるだけだけど。