rfc.tls
- トランスポート・レイヤ・セキュリティ ¶このモジュールはTCPソケット上のセキュアな接続を処理します。
rfc.http
で、https接続を実現するのに使われています
(rfc.http
- HTTPクライアント参照)。
実行中のGaucheがTLSをサポートしているかどうかは機能識別子
gauche.net.tls
で判別できます。
機能識別子については機能条件式を参照してください。
GaucheはTLS実装としてMbedTLS(https://tls.mbed.org/)を使っています。 以前は複数のTLSサブシステムをサポートしていたので、ライブラリは複数のサブシステムを 切り替えて使えるようになっています。将来また別のTLSサブシステムをサポートするかもしれません。
{rfc.tls
}
TLS実装のベースクラスです。このクラスのインスタンスを使って、
セキュアなコネクションを張って通信ができます。
通常、具体的なサブクラスを気にする必要はありません。
このクラスは<connection>
を継承します (gauche.connection
- コネクションフレームワーク参照)。
{rfc.tls
}
MbedTLSサブシステムを実装しているクラスです。
{rfc.tls
}
デフォルトのTLSサブシステムです。現在のバージョンでは、
これは<mbed-tls>
クラスか#f
です。
#f
は、GaucheがTLSをサポートしていないことを示します。
{rfc.tls
}
新たなTLSインスタンスを作って返します。インスタンスの具体的なクラスは
default-tls-class
の値が使われます。
TLSインスタンスはtls-connect
に渡すことでクライアントとして使ったり、
tls-bind
とtls-accept
に渡すことでサーバーとして使うことができます。
以下のそれぞれのサブセクションを参照してください。
引数はTLSクラスに渡されるキーワード-値リストでなければなりません。 以下のキーワード引数が認識されます。
:server-name
TLS Server Name Indication拡張に使うサーバー名を指定します。 一般的には、TLSオブジェクトをクライアントとして使う場合に接続先サーバ名を渡します。 サーバとして使う場合は必要ありません。
:skip-verification
クライアントのみ。この引数が真の値の場合、接続時の証明書の認証を省略します。 これは危険な動作なので、実験目的以外では使わないでください。
{rfc.tls
}
TLSコネクションを閉じます。通信相手は接続が閉じられたことを知ります。
tlsがひとたびクローズされるとそれはもう使うことができません。
tlsに対しconnection-close
を呼び出すことでも同じ動作になります
(gauche.connection
- コネクションフレームワーク参照)。
{rfc.tls
}
tlsが接続状態にある時、これらは相手と通信するための入力ポートと出力ポートを
それぞれ返します。
tlsが接続状態に無い時にこれらを呼ぶと#f
が返されます。
tlsに対しconnection-input-port
および
connection-output-port
を呼び出すことでも同じ動作になります
(gauche.connection
- コネクションフレームワーク参照)。
{rfc.tls
}
tlsが読み込みもしくは書き込み可能になるまで待ちます。tlsは既に
bindされているか接続されていなければなりません。そうでない場合は直ちに()
が
返されます。
rwはシンボルread
、write
の組み合わせのリストで、
待つべき条件を指定します。timeout引数は、
時刻を指定する<time>
オブジェクトか、
現在からの経過時間を秒で指定する実数値か、
タイムアウトしないことを指示する#f
です。省略時は#f
が使われます。
戻り値は満たされた条件のリストです。例えばrw引数に
(read)
もしくは(read write)
を指定して、tlsが読み込み可能になったら
(read)
が返されます。条件が満たされる前にタイムアウトした場合は()
が
返されます。
{rfc.tls
}
これはトラブルシューティング用のAPIです。
TLSサブシステムのグローバルなデバッグログレベルをlevelに設定します。level
は0(ログなし、デフォルト)から9(ログ最大)までの正確な整数です。
実際のログ段階の細かさは各TLSサブシステムにより、0-9のレベルがサブシステムのサポートする 段階へとマップされます。いくらか試行して適切な値を見つけてください。
クライアントとしてサーバにTLS接続する場合、
サーバの認証を適切に行うために、CA証明書が必要です。
Gaucheは自前でCA証明書を持っておらず、デフォルトでシステムのCA証明書バンドルを利用します。
Unixベースのシステムでは、いくつかのよくあるパスを探索します。
例えばLinuxディストリビューションならca-certificates
やそれに類する
パッケージをインストールしておくと良いでしょう。
OSXではopensslをHomebrewでインストールしておくのをおすすめします。
WindowsではWincrypt API経由でシステムの証明書ストアを使います。
デフォルトのコンフィグレーションでは、Gaucheは初期化時にシステムのCA証明書バンドルを探し、 見つかればそれを使うようになっています。かわりとなるCA証明書バンドルのパスを指定したり、 接続毎に独自の証明書を与えることもできます。
もし、何らかの理由で、システム全体で使えるCA証明書バンドルがインストールできない場合、 独自にCurlのCA証明書バンドルをhttps://curl.haxx.se/ca/cacert.pemから ダウンロードしてGaucheのインストールディレクトリに置いておくことができます。 便利なスクリプトが用意してあります。 Gaucheをインストールした後、次のコマンドを実行してください。
gosh tools/get-cacert
curlがシステムにインストールされている必要があります。また、Gaucheをインストールする時に root権限で行ったのであれば、このコマンドがCA証明書バンドルをインストールする時に sudoのパスワードを尋ねるでしょう。
もしこの方法を取ることに決めたなら、時々このコマンドを実行してCA証明書バンドルを 最新版に更新するのを忘れないようにしてください。 CA証明書は期限が切れたり無効化されることがあります。
{rfc.tls
}
CA証明書バンドルのパスを保持しています。値は、CA証明書バンドルファイルの
パス名、シンボルsystem
、あるいは#f
のいずれかです。
この値がsystem
の場合、Gaucheはシステムのデフォルトの証明書バンドルを
使おうとします。もしそれが見つからなければ接続時にエラーが報告されます。
この値が#f
の場合、CA証明書は自動的にロードされないので、
tls-load-object
を使って自分で適切な証明書をロードしてやる必要があります。
(このオプションは<ax-tls>
のみ有効です。
<mbed-tls>
を使う場合は、必ず有効なCA証明書バンドルが必要です。)
デフォルトのコンフィグレーションでは、Gaucheはrfc.tls
モジュール初期化時に
システムのCA証明書バンドルが使えるかどうか調べて、使えるならtls-ca-bundle-path
の
初期値をsystem
に、使えないなら#f
にセットします。
したがって、デフォルトのコンフィグレーションで使っている限り、
この値がsystem
であればシステムのCA証明書を使えると考えて良いでしょう。
このデフォルトの振る舞いはconfigure時に--with-ca-bundle
オプションで
変えられます。使っているGaucheのコンフィグレーションが変えられているかどうかは、
gauche-config --reconfigure
コマンドを実行して--with-ca-bundle
オプションがあるかどうかを見ればわかります。
{rfc.tls
}
クライアントとして、指定されたサーバにTLSで接続します。
tls引数はまだ接続されていないTLSオブジェクトでなければなりません。
hostとportは文字列で、それぞれサーバのホスト名とポートを指定します。
ホスト名についてはドメイン名のほか、IP表記が使えます
(例: "127.0.0.1"
、"[::1]"
)。
ポートについては整数のポート番号も名前による指定(例: "https"
)も使えます。
proto引数はシンボルtcp
かudp
のどちらかでなければならず、
省略時はtcp
とみなされます
(udpを指定した場合はTLSのかわりにDTLSが使われることになりますが、
今はDTLSを実用的に使うために必要なAPIがいくつか未実装です。)
サーバにコンタクトできたら、この手続きはサーバ証明書を入手して
CA証明書を使ってバリデーションを試みます。
バリデーションが失敗したらエラーが投げられます。正しく接続を確立するには、
有効なCA証明書ストアがパラメータtls-ca-bundle-path
で指定されていなければ
なりません。
接続が確立してTLSハンドシェイクが成功したら、 引数に渡したtlsオブジェクトはconnected状態になり、 相手とデータをやりとりすることができます。
TLSコネクションをサーバとして使うには、秘密鍵、サーバ証明書、および中間証明書を 用意する必要があります。これらはクライアントからのTLS接続を受け付ける前に 読み込まれている必要があります。
{rfc.tls
}
pathで示されるファイルに格納されたサーバ証明書を読み込みます。
ファイル中に複数の証明書を含めることができます。また、この関数は複数回呼び出せて、
tlsに中間証明書を追加してゆくことができます。
{rfc.tls
}
pathで示されるファイルに格納されたサーバの秘密鍵を読み出して登録します。
秘密鍵が暗号化されている場合はpasswordにパスワードを指定します。
秘密鍵が暗号されていない場合はpasswordに#f
を渡します。
{rfc.tls
}
TLS接続のサーバー側エンドポイントを作ります。
tls引数はまだ接続もbindもされていないTLSオブジェクトでなければなりません。
host引数は文字列のホスト名か#f
です。
port引数は整数のポート番号か文字列によるポート名です。
protoにはシンボルtcp
かudp
を渡します。
省略時はtcp
が仮定されます。
(NB: udpサーバー (DTLS) を使うにはいくつか追加のAPIサポートが
必要なので、今のところDTLSは使えません)。
socket-bind
と同じように、portに0を指定することで、
空いているポート番号をシステムに選んでもらうことができます。
実際にどのポートにバインドされたかは
(sockaddr-port (connection-self-address tls))
でわかります。
{rfc.tls
}
引数のtlsは、tls-bind
でバインドされたTLSオブジェクトでなければなりません。
サーバ証明書と秘密鍵はtls-load-certificate
およびtls-load-private-key
によってtlsにロードされていなければなりません。
この手続きはクライアントの接続要求を待ちます。接続要求が来たら、 サーバ証明書をクライアントに提示し、TLSハンドシェークを行います。 全てが成功すれば、クライアントに接続された新たなtlsオブジェクトを作って返します。
<tls>
クラスはコネクションフレームワークを実装しているので、
以下のメソッドがtlsオブジェクトに対して使えます。特に最初の2つは
下位にあるコネクションのIPアドレスを得るのに使えます。
connection-self-address (c <tls) connection-peer-address (c <tls>) connection-input-port (c <tls>) connection-output-port (c <tls>) connection-close (c <tls>)