IO-Socket-SSL-0.91 > IO::Socket::SSL

名前

IO::Socket::SSL -- IO::Socket::INETのためのほとんど透過的なSSLのカプセル化

概要

    use IO::Socket::SSL;

    my $client = new IO::Socket::SSL("www.example.com:https");

    if (defined $client) {
        print $client "GET / HTTP/1.0\r\n\r\n";
        print <$client>;
        close $client;
    } else {
        warn "I encountered a problem: ",
          &IO::Socket::SSL::errstr();
    }

説明

このモジュールはリモートのサーバーやクライアントに転送される前にデータを 暗号化するためにSSLを使う、IO::Socket::INETの代わりになる本当の 差込式の代替品です。IO::Socket::SSLは完全な機能を持ったSSLクライアントや サーバー・アプリケーションを書くために必要な特別な機能を全てサポート しています: 複数のSSLコンテキスト、暗号の選択、証明書の検証、そして SSLバージョンの選択。さらに特別に、mod_perlでも完全に機能します。

SSLをこれまで使ったことがなければ、このモジュールを使おうとする前に 'SSLの使い方'という付録を読むべきです。

このモジュールを以前、使ったことがあるのであれば、読み続けてください。 というのもバージョン0.90以上はIO::Socket::SSLの内部を完全に 書き換えたことを示しているからです。

メソッド

IO::Socket::SSLはIO::Socket::INETからメソッドを継承し、必要に応じてそれを オーバーライドしています。SSLエラーがあれば、メソッド(あるいは操作)は 未定義値を返します。利用者の視点から変更されたメソッド、ここでもう一度、 ドキュメント化されています:

new(...)

新しいIO::Socket::SSLオブジェクトを作成します。(オプションで)以下のものも 含めて、IO::Socket::INETについてくる親切なオプションの全てを使うことが出来ます:

SSL_version

データを転送するために使われるSSLプロトコルのバージョンを設定します。デフォルトは SSLv2/3です。これはSSLv2とSSLv3と自動ネゴシエイトを行います。このように動いて 欲しくないのであれば、'SSLv2', 'SSLv3',あるいは'TLSv1'(大文字/小文字は区別されません) を指定することができます。

SSL_cipher_list

もしデフォルトの暗号のリスト('ALL:!LOW:!EXP')を好まないのであれば、OpenSSLのドキュメント (http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS)を見て、このオプションで 違う集合を指定してください。

SSL_use_cert

これが設定されると、SSLクライアントをセットアップしているときでさえも IO::Socket::SSLに証明書と鍵を使うよう強制させます。これが0(デフォルト)に 設定されると、サーバーとして設定したときにだけ、証明書と鍵が必要になります。

SSL_key_file

あなたのRSA秘密鍵がデフォルトの場所(サーバー用はcerts/server-key.pem、 クライアイント用はcerts/client-key.pem)になければ、これが別の場所を 指定するために使うオプションがです。(SSL_passwd_cbオプションが指定しない限り) 鍵はがPEM形式にされ、暗号化されていれば、ソケットが作られる前にパスワードを 入力するためのプロンプトが表示されます。

SSL_cert_file

あなたのSSL証明書がデフォルトの場所(サーバー用はcerts/server-cert.pem、 クライアント用はcerts/client-cert.pem )になければ、このオプションを使って 証明書の場所を指定しなければなりません。鍵と証明書はSSLサーバーのためにだけ 必須であることに注意してください。そのため認証されないクライアントを設定する ときには、これらのオプションを設定することに煩わされる必要はありません。

SSL_passwd_cb

あなたの秘密鍵が暗号化されているならば、Net::SSLeyからのデフォルトのパスワード・ プロンプトが望ましくないかもしれません。このオプションは秘密鍵を復号化するために 必要とされるパスワードを返すサブループンへのリファレンスを取ります。 この動作のためにはNet::SSLeay >= 1.16が必要であることに注意してください。

SSL_ca_file

相手の証明書がきちんとした認証局(certificate authority)によって署名されたかを 確認したければ、certs/my-ca.pemになければ、きちんとした認証局のcertificateが 入っているファイルの場所を示すため、このオプションを使わなければなりません。

SSL_ca_path

OpenSSLドキュメントに非常に精通してれば、証明書のインデックスと一緒に 信頼される証明書を別のファイルとして入っているディレクトリを設定させているかも しれません。確認のために、そのディレクトリを使いたければ、そしてそのディレクトリが ca/でなければ、IO::Socket::SSLに参照するべき場所を示すため、このオプションを 使ってください。

SSL_verify_mode

このオプションは相手の証明書のための確認モードを設定します。デフォルト(0x00)は 何も認証を行いません。デフォルトを変更するため、0x01 (相手を確認), 0x02 (fail 相手の証明書がなければ確認失敗;クライアントに対しては無視), 0x04 (一度、クライアントは確認) を組み合わせることができます。

SSL_reuse_ctx

上記のオプション(SSL_use_cert から SSL_verify_mode;これはSSL_cipher_listは、まだ 含まれません)を、IO::Socket::SSLの前のインスタンスのために設定していれば、 それをSSL_reuse_ctxパラメータの値として渡すことにより、そのインスタンスの SSLコンテキストを再利用することができます。コンテキストに関連した オプションを渡しても、それらは無視されます。IO::Socket::SSLの前のバージョンとは 反対に、グローバルなSSLコンテキストは暗黙のうちには使われないことに注意してください。

close(...)

close()を使うことについて注意しなければ、waitに関連していくつかのやっかいな罠があります。 まず最初にソケットでshutdown()を使っていると、これにより困ったことになります。 SSLプロトコルはソケットをクローズ前にSSL"close notify"メッセージが送信されるよう 権限を与え、ソケットの書込みチャネルをクローズするshutdown()はclose呼び出しを ハングさせてしまいます。同じような理由で、(サーバーをforkするとき)ソケットのコピーを closeしようとすると、元のソケットにも影響を与えます。これらの問題を回避するため、 以下のパラメータの1つあるいは複数でオブジェクト指向の書き方 (例えばsocket->close(SSL_no_shutdown => 1))でclose()を呼び出してください。

SSL_no_shutdown

true値に設定すると、このオプションは、shutdown()やソケットのコピーで動いている ならば、close()に、close操作が問題なく完了できるよう、疑わしいソケットに対して SSL_shutdown()を使わないようにさせます。

SSL_ctx_free

それをクローズするとき、そのソケットのSSLコンテキストが破壊されることを 確実にしたければ、このオプションをtrue値に設定してください。

peek()

この関数はsysread()と全く同じ書き方をします。そしてほとんど同じ仕事を行います( ソケットからデータを読み込みます)。しかし連続して同じ引数でpeek()を呼び出すと 同じ結果が返るように、読み込み位置を進めません。 この関数が機能するためには、Net::SSLeay v1.19以上とOpenSSL 0.9.6a以降が必要です。

pending()

この関数はすぐにソケットから読み込むことが準備ができるデータのバイト数を教えてくれます。 これは特にブロックしたソケットで読み込みをしているときや、ソケット越しに新しいデータが 送信されたかを知りたいだけのときには特に使いやすいでしょう。

get_cipher()

IO::Socket::SSLが使っている暗号を文字列の形で返します。

dump_peer_certificate()

相手のSSL証明書から選択フィールドが入った解析可能な文字列を返します。 このメソッドはNet::SSLeayのdump_peer_certificate()メソッドの結果を直接、返します。

peer_certificate($field)

相手の証明書があれば、この関数はそれから値を取り出します。今は、それが返すことができる フィールドは"authority"と"owner"だけです(もしOpenSSL名を使いたければ、"issuer"と"subject" です)、相手の証明書に署名した認証局と相手の証明書の所有者に対応します。この関数は 解析可能な行の1つに入っている特定のフィールドについての全ての情報が入った文字列を 返します。

errstr()

発生した最後のエラーを(文字列形式で)返します。このメソッドを実行するための 本物のオブジェクトを持っていなければ、代わりに&IO::Socket::SSL::errstr()を 呼び出してください。 ブロックしていないソケットの読み込みや書込みに、このメソッドは、 もう一方の側がソケットからの読み込みや書き込みを待っていて、あなたが何かする前に 満足させて欲しいと思っていることを意味する、 SSL wants a read first! あるいは SSL wants a write first! を文字列に入れるかもしれません。

IO::Socket::SSL::socket_to_SSL($socket, ... )

これは、あなたが与えたglobリファレンスやソケットをIO::Socket::SSLオブジェクトに 変換します。コンテキストやnew()を呼び出すときのような接続オプションを指定するため、 パラメータを渡すこともできます。もしこの関数をaccept()されたソケットに使うのであれば、 パラメータ"SSL_server"を1に設定しなければなりません。つまり IO::Socket::SSL::socket_to_SSL($socket, SSL_server => 1) です。

以下のメソッドはサポートされていません(役に立たないといっているわけではありません!) そしてあなたがそれらを使うほどのオバカさんであれば、IO::Socket::SSLは巨大な CROAK()を吐き出すことになります。

truncate
stat
ungetc
setbuf
setvbuf
fdopen

デバッグの方法

'SSLの使い方(=Using SSL)'とラベルがついた、このドキュメントの前のセクションを暗証する ことができるにも関わらずIO::Socket::SSLを使っていて問題を持っているのであれば、 デバッグを有効にしてみるべきです。デバッグ・レベルを指定するためには 呼び出すとき、'debug#'(#は0から4までの数字)をIO::Socket::SSLに渡してください。

use IO::Socket::SSL qw(debug0);

#デバッグなし(デフォルト)

use IO::Socket::SSL qw(debug1);

#エラーを出力するだけ

use IO::Socket::SSL qw(debug2);

#エラーと暗号ネゴシエイションを出力

use IO::Socket::SSL qw(debug3);

#進行状況、暗号そしてエラーを出力

use IO::Socket::SSL qw(debug4);

#データも含めて全てを出力

$IO::Socket::SSL::DEBUGを0から4に設定することもできます。でも説明しなくても いいよね、でもない?

使用例

'example'ディレクトリをご覧ください。

バグ

私は既知のバグがあるモジュールを出したことはありません。そしてIO::Socket::SSLでも それは変わりません。このモジュールにバグを見つけたと感じ、Net::SSLeayの 最新バージョンを使っているのであれば、'IO::Socket::SSL Bug'という件名で behroozi@www.pls.uni.eduにすぐにメールを送ってください。 私はあなたのコードの問題には責任ありません。そのため送信する前に例が 実際に動くことを確認してください。これはバグレポートを私に送るのであれば、 単に受入可能であるに過ぎません。問題を示す小さなコードを送信してくれると よりよいことです。パッチを送ってくれるのであれば、それが一番です--パッチが よければ、翌日、CPANで次のリリースを見るかもしれません。 そうでなければ、何週間もかかってしまうかもしれません...

制限

IO::Socket::SSLは、SSLの面倒くさい部分への素晴らしいインターフェースである OpenSSLへの素晴らしいインターフェースとしてNet::SSLeayを使っています。 その結果、このモジュールを使う前にNet::SSLeay(1.20 推奨) と OpenSSL (0.9.6g 推奨)の両方があなたのコンピュータに必要となります。

廃棄予定(DEPRECATIONS)

以下の関数は廃棄予定(deprecate)になり、互換性のためだけに維持されています:

context_init()

(コンテキストを再利用したければ、SSL_reuse_ctxオプションを使ってください)

socketToSSL()

(socket_to_SSL()に名前が変わりました)

get_peer_certificate()とその仲間

(代わりにpeer_certificate()関数を使ってください)

want_read() と want_write()

(適切な文字列をerrstr()で探してください)

以下のクラスは削除されています:

SSL_SSL

(いずれにしても、これに直接アクセスするできではありませんでした):

X509_Certificate

(しかしそれでも、get_peer_certificate()は正しい事をおこないます(Do The Right Thing))

参考資料

IO::Socket::INET, Net::SSLeay.

作者

Peter Behroozi, behroozi@www.pls.uni.edu。

Marko Asplund, aspa@kronodoc.fi, が最初のIO::Socket::SSLの作者でした。

著作権(COPYRIGHT)

The rewrite of this module is Copyright (C) 2002 Peter Behroozi.

This module is Copyright (C) 1999-2002 Marko Asplund.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

付録: SSLの使い方

OpenSSLの動き方をよく知らないのであれば、よく出来たリファレンスが "Network Security with OpenSSL" (Oreilly & Assoc.)という本とWebサイト http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/にあります。 簡単な概要については読み続けてください。

長いもの(詳細)

SSLを使う普通の理由はあなたのデータを安全に保つためです。つまりネットワークを通って 転送される間、データを暗号化するだけではなく、正しい人がデータを取得することを確実に しなければなりません。これをSSLで実現するためには、証明書を使わなければなりません。 証明書は政府が発行したIDに(少なくとも信用することが出来るというとこで)非常によく 似ています。IDには名前や住所のような識別するためのいくつかの情報が入っています。 そして通常は政府の承認(Government Approval)の印が押されています。理論上、 これは、あなたはそのカードにある情報を信頼し、そのカードの所有者と取引を行ってもいい ことを意味します。 その考えをSSL証明書に当てはめます。それはいくつかの識別情報を持っていて、 十分に識別情報を確認すると信用することができるだれか(認証局(=Certificate Authority)) により、"印が押されています"[ほとんどの人々はこれを、代わりに署名するといいます]。 この場合、いくつかの賢い数学理論のおかげで、印を押す処理を偽造することは非常に困難です。 もう一つの数学理論の有用な結果は、データを(証明書にある情報を使って)暗号化し、 証明書の所有者だけが復号化することができるように、証明書が暗号化処理に結び付けられて いることです。

これはあなたにとってどのような意味をもつでしょうか。飲み物を得るためには、 パーティーの中で少なくとも1人はIDを持っている必要があるということです :-) まじめな話、あなたのデータが安全であることを確実にするためには、 コミュニケーションする人々のうちの1人は証明書を持たなければなりません。 クライアント/サーバーの対話では、サーバーは常に証明書を持っていなければなりません。 もしサーバーがクライアントが安全であることを確認したければ、クライアントも個人的な 証明書を持たなければなりません。 証明書が安全であることを確認するためには、同じであることを確認するため 証明書に押されている"印"[一般的に暗号化ダイジェスト/ハッシュ/署名と 呼ばれます]と認証局の公式の"印"を比較します。これをおこなうためには、 [残念ながら名前がついている]認証局の証明書を必要とします。 これらの全てが手元にあれば、SSL接続を設定し、だれもあなたのデータを読んでいないと 合理的に確信することができます。

短いもの(要約)

サーバーでは、暗号秘密鍵を生成し、証明書要求を生成する必要があります。 本当の証明書を取得するため証明書要求を認証局に送付しなければなりません。 証明書を取得した後人々にサービスを提供できるようになります。クライアントでは、 サーバーが確認を求めない限りは何も必要ありません。その場合にも、秘密鍵と本当の 証明書が必要となります。これらを取得方法についての更なる詳細は、 http://www.modssl.org/docs/2.8/ssl_faq.html#ToC24をご覧ください。