Adsense_top

2010年2月9日火曜日

C# POP3でAPOP認証を使用する

予告していた通りAPOPについて書きます。
あまり使われていないらしいですが、パスワードを暗号化するので平文でやり取るするPOP3よりは、セキュリティ的には高いと言っていいと思います。(ただし、すでに破られているとのことですが..)


POP3の認証の部分のみ異なるだけですので、その部分だけの記述にします。他の部分は、先に書いた、「C# POP3サーバーからメールを受信する」をご覧ください。


以下に引用した以前のコードの「----------ココから----------」から「----------ココまで----------」の部分

/// 
/// POP3サーバのすべてのメールを受信しサーバより削除します。
///

/// POP3サーバ名
/// ポート番号
/// ユーザー名(アカウント)
/// パスワード
public void ReceiveAll(string host, int port,
string user, string pass)
{
string result;
Stream stream = null;
TcpClient tcp;
tcp = new TcpClient();
try
{
// 接続
tcp.Connect(host, port);
// NetworkStreamを得る
stream = tcp.GetStream();
// タイムアウト時間の設定
stream.ReadTimeout = 30 * 1000;
stream.WriteTimeout = 30 * 1000;
// StreamReader、StreamWriterを被せる
StreamReader reader =
new StreamReader(stream, Encoding.ASCII);
StreamWriter writer =
new StreamWriter(stream, Encoding.ASCII);
// 改行文字とバッファフラッシュを設定
writer.NewLine = "\r\n";
writer.AutoFlush = true;
// サーバーからの挨拶コードを得る
//----------ココから----------
result = reader.ReadLine();
if (!result.StartsWith("+OK"))
throw new Exception(string.Format("エラー応答:{0}",result));
// USERコマンド
writer.WriteLine("USER {0}", user);
result = reader.ReadLine();
if (!result.StartsWith("+OK"))
throw new Exception(string.Format("エラー応答:{0}",result));
// PASSコマンド
writer.WriteLine("PASS {0}", pass);
result = reader.ReadLine();
if (!result.StartsWith("+OK"))
throw new Exception(string.Format("エラー応答:{0}",result));
//----------ココまで----------

を下記のように書き換えるだけです。


    result = reader.ReadLine();
if (!result.StartsWith("+OK"))
throw new Exception(string.Format("エラー応答:{0}",result));
Match challenge =
Regex.Match(result, @"^.+(<.+>).*$", RegexOptions.Compiled);
if (!challenge.Success)
throw new InvalidDataException(
string.Format(
"APOP認証のための識別子が見つかりません:{0}", result));
// チャレンジ文字列 + パスワードを元に生成します。
string plain = challenge.Groups[1].Value + pass;

// MD5に変換
MD5 md5 = MD5.Create();
byte[] bytes =
md5.ComputeHash(Encoding.ASCII.GetBytes(plain));

// 16進数小文字(x)の文字列にする
StringBuilder md5response = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
md5response.Append(data[i].ToString("x"));

writer.WriteLine("APOP {0} {1}", UserName,
md5response.ToString());
string result = ReadLine();
// 失敗
if (!result.StartsWith("+OK"))
throw new SecurityException(
string.Format("認証に失敗しました:{0}", result));

実際にテスト出来るサーバーのアカウントを持っていませんので、テストは出来ていません。
実際の使用する場合は必ずテストを行ってからにしてください。
また、テスト結果など教えていただければ嬉しいです。


0 件のコメント:

コメントを投稿