(rontolisp) docs
← 関数

rontolisp:tls-connect

(rontolisp:tls-connect host port) (rontolisp:tls-connect host port :insecure value)

host/port へブロッキング TCP 接続を開き、TLS ハンドシェイクを行って 双方向ストリームハンドルを返します — rontolisp:tcp-connect の暗号化版です。ハンドルは ファイルストリームと同じハンドル空間にあるため、標準のストリーム関数がそのまま 使えます: read-linewrite-lineread-bytewrite-byteclose。プレーンなソケットと同様、書き込みは即座に送信され、相手が 接続を閉じると read-linenil を返します。

サーバー証明書は JDK デフォルトのトラストストアで検証され、ホスト名も検証されます (HTTPS 方式のエンドポイント識別)。そのため、信頼されていない証明書やホスト名の 一致しない証明書を持つサーバーへの接続はエラーを通知します。自己署名証明書を 信頼するには、標準の javax.net.ssl.trustStore / javax.net.ssl.trustStorePassword システムプロパティで独自のトラストストアを 指定してください。これらは呼び出しのたびに再読み込みされます。

:insecurenil 以外の value を渡すと、両方の検証を無効化します — 証明書チェーンを無条件に受け入れ、ホスト名も検証しません。これは自己署名サーバー に対する開発用途を想定したものです。中間者攻撃に対する保護がすべて失われるため、 実運用のエンドポイントには決して使わないでください。:insecure nil はオプションを 省略した場合(検証あり)と同じです。

以下の例は TLS 上で HTTP/1.1 を手書きで話します(リクエスト行は CRLF で終わる 必要があるため、キャリッジリターンを明示的に付加しています。レスポンス側の CR は read-line が取り除きます)。実際の HTTPS リクエストには rontolisp:fetch を使ってください — tls-connect は 任意の TLS でラップされたプロトコルのためのものです:

(let ((sock (rontolisp:tls-connect "example.com" 443))
      (cr (princ-to-string (code-char 13))))
  (write-line (concatenate 'string "GET / HTTP/1.1" cr) sock)
  (write-line (concatenate 'string "Host: example.com" cr) sock)
  (write-line (concatenate 'string "Connection: close" cr) sock)
  (write-line cr sock)
  (print (read-line sock))   ; "HTTP/1.1 200 OK"
  (close sock))

バックエンドのサポート

  • インタープリタJVM: JDK の TLS スタック(SSLSocket)を使います。 host にはホスト名または IP リテラルを指定できます。接続やハンドシェイクの 失敗(ポート拒否、信頼されていない証明書、ホスト名の不一致)はエラーを通知 します。
  • WASM: 現時点では非サポート — tls-connect は Preview 1 と --component のどちらのモードでもコンパイルエラーです。component モードのクライアントは wasmtime の実験的な wasi:tls@0.3.0-draft インターフェイス上に構築できますが、このインターフェイスは不安定です (semver の保証なし)。安定するまではインタープリタか JVM バックエンドを使ってください。
  • ブラウザプレイグラウンド: 非サポート — ブラウザのサンドボックスには生の TCP ソケットがないため、tls-connect はエラーを通知します。

制限事項

  • :insecure はすべてを無効化するオプトアウトです(証明書ごとのピン留めは できません)。検証を有効にしたまま特定の追加証明書を信頼するには、代わりに トラストストアのシステムプロパティを使ってください。TLS のサーバー側は rontolisp:tls-listen を参照してください。
  • read(S 式リーダー)はソケットハンドルでは動きません。行またはバイトで 読み取り、明示的にパースしてください(例: read-from-string)。