POP3 クライアントを作ってみよう(3)

前へ << POP3 クライアントを作ってみよう(2) echo サーバを作ってみよう (1) >> 次へ

ユーザ認証

先程の POP3 クライアントには問題点があります。 まずはユーザ認証についてです。

pop3-client.pl

   34: print SOCKET "USER $username\r\n";
   35: print SOCKET "PASS $passwd\r\n";
の部分で行っていましたが、エラーチェックをまったく行っていません。 パスワードの間違いなどが原因でユーザ認証ではねられた場合は、 その旨メッセージを表示する方が親切でしょう。

また、USERPASS コマンドを使った認証は、 ネットワーク上に生のパスワードが流れるため、セキュリティ的には 好ましくありません。生のパスワードが流れないようにした APOP というコマンドがありますので、それを使った方が安全です。

APOP の使い方を簡単に解説します。telnet で POP3 サーバに接続してください。

% telnet pop3.host.com pop3
Trying xxx.xxx.xxx.xxx...
Connected to pop3.host.com.
Escape character is '^]'.
+OK QPOP (version 2.53) at pop3.host.com starting.  <23075.918978711@pop3.host.com>
bold 表記の <23075.918978711@pop3.host.com> の部分を タイムスタンプといい、接続するたびに毎回異なる文字列が渡されます。
もしタイムスタンプが表示されていない場合は、そのサーバは APOP には対応していないということです。 APOP の使用はあきらめてください。
APOP の場合、クライアントがパスワードをそのまま送るのではなく、
「タイムスタンプの末尾にパスワードを付けたもの」の MD5 でのダイジェスト文字列
を送ります。

ユーザ名が username、パスワードが secret という場合を例にあげてみます。 タイムスタンプとパスワードを繋げた「<23075.918978711@pop3.host.com>secret」という文字列の MD5 でのダイジェスト文字列は a45c6c8ae2d1ad23a07d3af3960617ec です。 つまり USER・PASS コマンドの代わりに、

APOP username a45c6c8ae2d1ad23a07d3af3960617ec
という文字列を POP3 サーバに送るわけです。これで生のパスワードをネットワーク上に流すことを 防げます。

ただし POP3 サーバに接続したときに、サーバからタイムスタンプが渡されなかった場合は、 そのサーバは APOP 未対応、ということです。

APOP はその原理上、必ずサーバ側に生パスワードを保存しておく必要があります。 この一点において、APOP は欠陥プロトコルです。 SMTP や IMAP には APOP と似た認証の仕組みとして、CRAM-MD5 や、それを改善した DIGEST-MD5 などの認証方法がありますが、 こちらも同様にサーバ側に生パスワードを保存する必要があります。

MD5 については 「UNIX の部屋」の MD5 の項 を参考にしてください。 要はダイジェスト文字列から元の文字列を推測することが不可能な仕組みです。

行頭の「.」の扱い

正規表現 m/^\.\r\n$/で、`.' のみの行かどうか調べ、 それを各メールの終りと認識していました。では、メールの 本文に `.'のみの行が含まれている場合はどうなるのでしょうか。

先頭の `.' は自動的に「..」に変換されて送られてきます。 注意したいのは、`.' のみの行だけではなく、 `.' で始まる行についても、先頭の `.' が `..' に変換されることです。つまりメールの中の

.
は、
..
となって送られてきますが、それだけではなく
.cshrcを書き換えて…
という文は
..cshrcを書き換えて…
となります (これは `.cshrc' という文字列が文頭にある場合だけです。お間違えなく)。

これらの `..' を `.' に戻すのは POP3 クライアントの仕事です。

前へ << POP3 クライアントを作ってみよう(2) echo サーバを作ってみよう (1) >> 次へ

ご意見・ご指摘は Twitter: @68user までお願いします。