OpenSSLのs_clientでGMailにアクセス

こまつ みつのり(Mitsunori Komatsu) 2008-04-25 12:30:45

現在、メールクライアントとしてThunderbirdを使っていて機能的にはまぁ満足しているんですが、結構重い… なので、GUIじゃなくて、Cygwin + Teraterm上で動かせるような軽いCUIのメールクライアントを、最近欲しています。

CUIでは、以前Emacsを使っていたときにMewというメールクライアントを使っていました。かなり快適に使えていたのですが、左手小指の痛みと共にEmacsと決別してしまったので、それ以降はBecky->Thunderbirdと乗り換えてきました。

MuttというCUIメールクライアントがあるので、後々はこれを試してみようかと思っているのですが、折角なのでOCamlで自作を試みてみようかと思います(OCaml縛り中なので)。そしてあっさり玉砕してMuttに乗り換えてしまう姿が目に浮かびます。

それではメールクライアントを作るうえで必要なプロトコルの一つ、POP3を練習してみます。何せメールクライアントを作るのですから、手打ちでサーバーと会話できるようになっておきたいものです。基本的にはtelnetコマンドで110ポートに接続して、

・USER ユーザ名

・PASS パスワード

・LIST

・STAT

・RETR メッセージ番号

等のコマンドを叩けば、簡単に会話できます。Web上にたくさん参考例があるので興味のある方は試してみてください。

ところで私はGMailをつかっているのですが、その場合はSSL上でPOP3プロトコルを話さなければなりません。そうするとtelnetだととても難しい。そこで、opensslサブコマンドの一つs_clientを使ってみます。

 


 

$ openssl s_client -host pop.gmail.com -port 995

CONNECTED(00000003)

depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

verify error:num=20:unable to get local issuer certificate

verify return:1

depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

verify error:num=27:certificate not trusted

verify return:1

depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

verify error:num=21:unable to verify the first certificate

verify return:1

---

Certificate chain

 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority

---

Server certificate

    :

---

No client certificate CA names sent

---

SSL handshake has read 891 bytes and written 332 bytes

---

New, TLSv1/SSLv3, Cipher is DES-CBC3-SHA

Server public key is 1024 bit

SSL-Session:

    Protocol  : TLSv1

    Cipher    : DES-CBC3-SHA

    Session-ID: 187DA38D74524F731EDAE3AF1F62EB183C5E0122D69B27464F643FC1E8629C49

    Session-ID-ctx:

    Master-Key: 2C566EFC2C1CEDE6FA53CAC421E815D0B2CBC31B70EF080E1BF1CBCB496A2DA736F5E5746DF5E0223DE7FA579EC588C3

    Key-Arg   : None

    Start Time: 1208679843

    Timeout   : 300 (sec)

    Verify return code: 21 (unable to verify the first certificate)

---

+OK Gpop ready for requests from xxx.xxx.xxx.xxx xxxxxxxxx.0

USER xxxxxxx

+OK send PASS

PASS xxxxxxxx

+OK Welcome.

LIST

+OK 61 messages (11242524 bytes)

1 30389

2 124225

3 3394

4 5433

5 141886

       :

.

RETR 1

RENEGOTIATING

depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

verify error:num=20:unable to get local issuer certificate

verify return:1

depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

verify error:num=27:certificate not trusted

verify return:1

depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com

verify error:num=21:unable to verify the first certificate

verify return:1

 

 

がーん、RETRコマンドでメールを取得しようとするとRENEGOTIATINGとなり再認証しようとして失敗してしまうようです。Web上を軽く探してみましたが対応方法がのってません。

仕方がないのでopensslのソースでも見てみましょう(@FreeBSD)。

 


 

$ pwd

/usr/ports/security/openssl

$ sudo make extract

===>  Vulnerability check disabled, database not found

=> openssl-0.9.8g.tar.gz doesn't seem to exist in /usr/ports/distfiles/.

=> Attempting to fetch from http://www.openssl.org/source/.

openssl-0.9.8g.tar.gz                         100% of 3276 kB  100 kBps 00m00s

===>  Extracting for openssl-0.9.8g

=> MD5 Checksum OK for openssl-0.9.8g.tar.gz.

=> SHA256 Checksum OK for openssl-0.9.8g.tar.gz.

===>   openssl-0.9.8g depends on file: /usr/local/bin/perl5.8.8 - found

$

 

 

これでソースが取れました。それではどこでRENEGOTIATINGと返しているか探しましょう。

 


 

$ find . -type f | xargs grep RENEGOTIATING

./apps/s_client.c:                              BIO_printf(bio_err,"RENEGOTIATINGn");

 

 

apps/s_client.cを見てみると…

 


 

1223       if (crlf)

1224         {

1225         int j, lf_num;

1226

1227         i=read(fileno(stdin),cbuf,BUFSIZZ/2);

     :

1254       if ((!c_ign_eof) && (cbuf[0] == 'R'))

1255         {

1256         BIO_printf(bio_err,"RENEGOTIATINGn");

1257         SSL_renegotiate(con);

1258         cbuf_len=0;

1259         }

 

 

う〜〜〜む、標準入力から読み込んだバッファの一文字目が'R'だとSSL_renegotiate()が呼ばれるようですねぇ。詳細には深入りせず、ここは「小文字なら見逃してはくれまいか?」と安直に考えてみましょう。再度、s_clientコマンド上から…

 


 

retr 63

+OK message follows

Delivered-To: xxxxxxxx@gmail.com

Received: by xxx.xxx.xxx.xxx with SMTP id yyyyyyyyy;

     :

 

 

やったぁ。成功です。よくわからんが小文字 'r' は見逃してくれたようです。このあと当該メールの件名や本文も無事表示されました。

今回は、s_clientを経由したので、大文字 'R' でRENEGOTIATINGしていましたが、メールクライアントプログラムではあまり懸念しなくてもよさそうです。

後は、SMTPプロトコルとOCamlのSSLライブラリを調べれば、なんとか目処が立ちそうな気がしております。

※このエントリはZDNetブロガーにより投稿されたものです。朝日インタラクティブ および ZDNet編集部の見解・意向を示すものではありません。

SpecialPR