openssl s_client で chat.facebook.com に STARTTLS で接続する2012年09月04日

先日書いた「facebook のチャットをパソコンの専用のクライアントで」で XMPP で facebook のチャットに接続することを書いたのですが、これをちょっと手動でやってみたくなりました。

SSL/TLS でつなぎたいので、openssl の s_client で STARTTLS するように指示してつないでみます。openssl の s_client コマンドは -starttls の後にプロトコルを指定すると、プロトコルごとの STARTTLS を実行し、SSL/TLS が開始されます。メールなら -startls smtp などとしますが、XMPP なので、-starttls xmpp とします。

$ openssl s_client -starttls xmpp -connect chat.facebook.com:5222 
CONNECTED(00000003)
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 400 bytes and written 122 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

あれ? SSL/TLS のハンドシェイクがうまくいってないようです。原因が知りたいので、TELNET で chat.facebook.com につないで確認します。

$ telnet chat.facebook.com 5222
(略)
クライアント→サーバー: <?xml version="1.0"?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='chat.facebook.com' version='1.0'>
サーバー→クライアント: <?xml version="1.0"?><stream:stream id="BC39B9EB" from="chat.facebook.com" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" xml:lang="en"><stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>X-FACEBOOK-PLATFORM</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>
クライアント→サーバー: </stream:stream>
サーバー→クライアント: </stream:stream>
Connection closed by foreign host.

<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/> がサーバーからの応答にあるので、STARTTLS は使えるはずです (参考: RFC 3920 Section 5.1 等)。なぜ openssl が正常に動作しないのかわかんないので openssl のソースコードを見ます。

openssl.orgから 1.0.1c のソースコードを持ってきて apps/s_client.c を見てみます。

  1475 while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'"))
  1476         {
  1477         if (strstr(mbuf, "/stream:features>"))
  1478                 goto shut;

えらく単純な文字列検索で判定しているようです。starttls 開始タグ内の xmlns 属性の値がシングルクォートで括られていることを前提としていますね。しかし chat.facebook.com の応答では xmlns="urn:ietf... のように、ダブルクォートで括られています。うーん、ちゃんと XML を parse しないといけんかねぇ、と思って、openssl の request tracker を見てみます。ありました。

#2565: More tolerant detection of XMPP starttls sequence

ここにあるパッチを見ると、strstrstrcasestr に置き換えられ、かつ、シングルクォートだけでなくダブルクォートの候補についても検索されるようになってます。

パッチをあてて、コンパイルし、再度実行します。

$ ./openssl s_client -starttls xmpp -connect chat.facebook.com:5222
CONNECTED(00000003)
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance CA-3
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Palo Alto/O=Facebook, Inc./CN=chat.facebook.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance CA-3
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance CA-3
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGqDCCBZCgAwIBAgIQDmU69yuszbx5RbMUTPVxADANBgkqhkiG9w0BAQUFADBm
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
(以下略)

処理としてはまだ甘いコードですが、今回の目的は成功です。

<< 2012/09 >>
01
02 03 04 05 06 07 08
09 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30

RSS