それで以前にC#でTLS物を作ろうとして苦労をしていたのを思い出したのですが、.NET 2.0なるとSSLStreamとかってクラスが追加されてて、簡単に出来そうな感じだったので試してみました。
元のサンプルプログラムを弄っただけもので、あくまでもクラスのテスト用のコードですが。
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
namespace ConsoleSecureTcpClient
{
class SecureClient
{
[STAThread]
static void Main()
{
string server = "pop.gmail.com";
string sUser = "USER " + "Your Account@gmail.com" + "\r\n";
string sPassword = "PASS " + "Your Password" + "\r\n";
int port = 995;
SslStream stream = null;
try
{
TcpClient client = new TcpClient(server, port);
RemoteCertificateValidationCallback callback =
new RemoteCertificateValidationCallback(OnCertificateValidation);
stream = new SslStream(client.GetStream(), false, callback);
stream.AuthenticateAsClient(server);
if (stream.IsAuthenticated)
{
Console.WriteLine("IsAuthenticated: {0}", stream.IsAuthenticated);
Console.WriteLine("IsMutuallyAuthenticated: {0}", stream.IsMutuallyAuthenticated);
Console.WriteLine("IsEncrypted: {0}", stream.IsEncrypted);
Console.WriteLine("IsSigned: {0}", stream.IsSigned);
Console.WriteLine("IsServer: {0}", stream.IsServer);
}
Byte []data = new Byte[256];
int bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
data = System.Text.Encoding.ASCII.GetBytes(sUser);
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));
data = new Byte[256];
bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
data = System.Text.Encoding.ASCII.GetBytes(sPassword);
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));
data = new Byte[256];
bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
data = System.Text.Encoding.ASCII.GetBytes("QUIT\r\n");
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));
data = new Byte[1024*1024];
bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
}
catch (AuthenticationException ex)
{
Console.WriteLine(ex.Message);
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (stream != null)
stream.Close();
}
Console.WriteLine("\n Press Enter to continue...");
Console.Read();
}
private static bool OnCertificateValidation(object sender, X509Certificate certificate
, X509Chain chain, SslPolicyErrors errors)
{
Console.WriteLine("Server Certificate Issued To: {0}", certificate.GetName());
Console.WriteLine("Server Certificate Issued By: {0}", certificate.GetIssuerName());
if (errors != SslPolicyErrors.None)
{
Console.WriteLine("Server Certificate Validation Error");
Console.WriteLine(errors.ToString());
return false;
}
else
{
Console.WriteLine("No Certificate Validation Errors");
return true;
}
}
}
}
以前は、
Mentalis.org Security Library を使用して満足していましたが、Frameworkに入ったという事でこれはこれでよい感じです。
しかしFrameworkもここまでくると、IntelliSense無しのCodingはちょっと辛いですね。