2006年08月
GNU screen の
最新バージョンである 4.0.2 において、
SJIS な端末で screen を走らせて screen のウィンドウで eucJP を使おうとすると、
1 バイト文字の前に 0x8E が挿入されてしまう。
つまり、
screen のコマンド「encoding eucJP SJIS」
(kanji euc sjis) を実行した場合とか、
あるいは「KJ=SJIS」を指定した端末で「defencoding eucJP」
(defkanji euc) を指定した
screen を使うといった場合である。
なぜだろうと思い、ソースを確認すると、encoding.c の 1154 行目あたりが 次のようになっている:
if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))
{
*statep = c;
return -1;
}
return c | (KANA << 16);
え? これってもしかして 2 バイト文字 (全角文字) 以外は 全て 1 バイトカナ (半角カナ) 扱いにしてしまっている?
screen 4.0.2 は、2004年1月27日に公開されていて (私の知る限り) これが最新版だと思うのだが、 このような単純なバグが 2年以上にわたって放置されているとは信じられないので、 すでにパッチが出回っていて、 開発元にも連絡が行っているのではないかと思う。 ご存じの方はご指摘頂ければ幸いである。 しばらく様子をみて、ご指摘が無いようであれば、 念のため開発元にパッチを送ってみる予定。
言うまでもなく、0x80 未満 (最上位ビットが 0) の文字は、 「KANA」扱いしてはいけないので、 上記コードは以下のようであるべきだ:
if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))
{
*statep = c;
return -1;
}
if (!(c & 0x80)) return c;
return c | (KANA << 16);
このような修正を加えることにより、例えば ~/.screenrc で
defkanji euc terminfo xterm KJ=sjis terminfo kterm KJ=euc terminfo vt100 AB=\E[4%p1%dm:AF=\E[3%p1%dm:KJ=euc
などと設定して、term=xterm な端末 (term は xterm であるが「シフトJIS」な漢字を表示できる) を使うような場合でも、 漢字を正しく表示できるようになった。
Linux の多くは EUC を標準的な漢字コードとして使っているはずで、 その一方で Windows は SJIS が標準的な漢字コードだったはず (最近は UTF8 の方が多い?) なので、 このような SJIS な端末で EUC な screen を使うケースは 決してレアケースではないと思うのだが、 なぜこのようなバグが放置されていたのかとても不思議である (ちなみに私は Windows 上の TeraTerm を EUC の設定で使っていたため、 このバグに今まで気づかなかった)。
このバグは、端末の漢字コードが SJIS で、かつ
screen のウィンドウの漢字コードが SJIS 以外の場合
(つまりコード変換が行なわれる場合) に発現する。
全ての 1 バイトコード (0x00 〜 0x1F のコントロールコードさえも!) の
前に「0x8E」をつけてくれるので、
screen の detach すらできなくなるという凶悪なものである。
念のため screen 4.0.2 に対する patch の形で修正点を示しておく:
--- encoding.c.org Mon Sep 8 23:25:23 2003
+++ encoding.c Mon Aug 28 18:11:57 2006
@@ -1151,6 +1151,7 @@
*statep = c;
return -1;
}
+ if (!(c & 0x80)) return c;
return c | (KANA << 16);
}
t = c;
いま読んでいる本:
フェルマーの最終定理 (文庫)
サイモン シン 著
の中につぎの一節を見つけた (323 ページ):
大事なのは、どれだけ考え抜けるかです。 考えをはっきりさせようと紙に書く人もいますが、 それは必ずしも必要ではありません。 とくに、袋小路に入り込んでしまったり、 未解決の問題にぶつかったりしたときには、 定石になったような考え方は何の役にも立たないのです。 新しいアイディアにたどりつくためには、 長時間とてつもない集中力で問題に向かわなければならない。 その問題以外のことを考えてはいけない。 ただそれだけを考えるのです。 それから集中を解く。 すると、ふっとリラックスした瞬間が訪れます。 そのとき潜在意識が働いて、 新しい洞察が得られるのです。
ついにフェルマーの最終定理を証明したワイルズの言葉であるが、 「潜在意識が働いて、新しい洞察が得られる」という部分に大変共感を覚えた。 「どうやったら無意識の思考をより活性化させることができるか」 考え続けてきた私としては、 我が意を得たりの感がある。
どうすれば無意識の思考をより働かせられるか、 ワイルズは「長時間とてつもない集中力で問題に向かわなければならない」と 表現した。 私は「同時に考えよう (1)」で書いたように、 「日頃から深く考え続けているような事に関しては、 ひらめく頻度が高いように感じる。 おそらく無意識で考え続けているのだろう」と思う。 意識した思考を長時間続けることが必要、 という点で共通しているのが興味深い。
なぜ、無意識の思考を働かせるには、 長時間の意識した思考が必要なのだろう?
なぜ、新しい洞察は、 意識した思考によってではなく、 無意識の思考によって得られるのだろう?
自身の脳の中で何が起っているのか、 そもそも無意識の思考とは何なのか? それが分かれば、 もっと「頭を使う」ことができるかもしれないし、 また自らの能力の限界がどのあたりにあるのか知ることも可能だろう。 ホフスタッターが言うように、 おそらく自由意思は錯覚なのだろう。 受動意識仮説は 「不思議の環」をとてもうまく説明する。
ゲーデル,エッシャー,バッハ―あるいは不思議の環 (単行本)
ダグラス・R・ホフスタッター 著
とはいえ、
脳が自分自身の動作原理を理解する、
などということが本当に可能なのだろうか?
自己言及の環となってパラドックスに陥ったりしないのだろうか?
マインズ・アイ―コンピュータ時代の「心」と「私」〈下〉 (単行本)
ダグラス・R・ホフスタッター/ダニエル・C・デネット 編著
の中の、クリストファー・チャーニアクの短編 「宇宙の謎とその解決」(第17章) に出てくる 「謎の昏睡」を、ふと思い出した。
stone 2.3c を リリースした。 現時点ではスナップショット扱いであるが、重大なバグが発見されない限り、 このバージョンを stone 2.3 に代えて正式リリースとする予定 (今度こそ!)。 stone 2.3b からの 変更点は以下の通り。
depth 値に依存せずに root CA 識別名を指定できるように
stone の SSL 認証 (3) で説明したように、 root CA から数えた階層数で「re数字=正規表現」を指定できるようにした。 root CA を「-1」とし、root CA の子CA が「-2」、以下順に数字が減っていく。
busy loop が起きるバグを修正
「stone 2.3b のバグ」 に書いたように、 stone 2.3b には SSL 接続が確立する前に TCP 接続が切れてしまうと、 まれに busy loop が発生するバグがあった。 stone.c 2.2.3.12 で修正済み。
さらに、万一 busy loop が起きたときに、それを検知するコードを追加した。 stone.c 2.2.3.13 には、 busy loop の誤検出するケースがあったので、 stone.c 2.2.3.14 で修正した。
SSL_accept 前に EOF となった場合にエラーを出さない
TCP レベルのヘルスチェックを行なっている場合、 SSL プロトコルを喋らずに shutdown する設定で運用するケースがある。 このような場合に、stone が SSL エラーとして出力してしまうと、 ログが無意味に肥大化してしまう。 そこで accept 直後に EOF になった場合は DEBUG メッセージのみ出力し、 エラーは出力しないようにした (stone.c 2.2.3.13)。
SSL close notify を送信できていなくてもエラーを出さない
SSL close notify を送信する前に通信相手が接続を切ってしまうケースがある。 あまり好ましいことではないが、 SSL セッションの再利用ができなくなる点を除けば実害はなく、 行儀が悪い通信相手のためにエラーログを肥大化させるのは割が合わないので、 これもエラーメッセージから DEBUG メッセージへ降格した (stone.c 2.2.3.13)。
「/udp」指定を転送元、転送先とで区別
従来は、転送先あるいは転送元のどちらかに「/udp」を指定していれば、 udp の中継を行なっていた。 今後は、udp の中継を行なう場合は、両方に「/udp」を指定する必要がある。 片方のみ「/udp」を指定した場合は、 udp から tcp への、あるいはその逆の変換を行なう指定とする予定(未実装)。
前々回と 前回で 説明したように、 stone で 通信相手の SSL 認証を行なうには、 通信相手がクライアントの時 (クライアント認証) は、
-z verify -z CApath=ディレクトリ
という設定で実行し、通信相手がサーバの時 (サーバ認証) は、
-q verify -q CApath=ディレクトリ
という設定で実行する。 「CApath=...」で指定したディレクトリに、 root CA 証明書を「ハッシュ値.数字」という形式のファイル名で 置いておくことにより、 通信相手が提示した証明書を検証することができ、 検証に成功したときのみ通信を許可する、 などのアクセス制限を行なうことができる。
ある root CA が発行した証明書、 あるいはその root CA の子, 孫, ... CA が発行した証明書、 いずれの証明書でも内容を問わず通信を許可して構わないのであれば、 これ以上の設定は不要であるが、 現実問題としては正規の証明書であれば何でも OK というケースは稀だろう。
メジャーな root CA だと、沢山の子 CA を持ち、 それぞれの子がさらに沢山の孫 CA を持っていたりする。 root CA 以外の CA を中間 CA と呼ぶが、 沢山の中間 CA がそれぞれ沢山の証明書を発行しているわけであるから、 その証明書の全てを許可していては、 不特定多数との通信を許可するのと大差ない。
そこで SSL 認証では、証明書を検証するだけでなく、 証明書の内容をも確認することが必要となる。 stone では証明書の識別名が満たすべき条件を正規表現の形で指定することができる。 証明書の識別名とは、例えば次のようなものである:
C=JP ST=Kanagawa L=Kawasaki O=GCD OU=Hiroaki Sengoku CN=test emailAddress=sengoku@gcd.org
これを「/」で区切って一行にした文字列:
/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=test/emailAddress=sengoku@gcd.org
この一行で表現した識別名が満たすべき正規表現を設定する。 この形式は、 前々回説明したクライアントが 既知の root CA (の子 CA) が発行した証明書を提示した場合の stone の出力例の 中に出てきている:
depth2=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/CN=GCD Root CA/emailAddress=root@gcd.org depth1=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=GCD_Sengoku_CA/emailAddress=sengoku@gcd.org depth0=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=test/emailAddress=sengoku@gcd.org
「depth2=」の行が、root CA 「GCD Root CA」の証明書の識別名であり、
「depth1=」の行が、「GCD Root CA」の子CA 「GCD_Sengoku_CA」の証明書の識別名であり、
「depth0=」の行が、「GCD_Sengoku_CA」が発行した証明書の識別名である。
root CA, 子, 孫, 曾孫, ... と、中間CA の階層数が増えて証明書の連鎖が続く場合、
「depth」の数字は大きくなり、
頂点である root CA の「depth」の数字が最も大きくなる。
一方、
サーバないしクライアント自身の証明書は常に「depth0」である。
stone では、depth0 から depth9 まで、扱うことができる。
各識別子 「depth0」〜「depth9」が満たすべき正規表現を、
それぞれ 「-z re0=正規表現」〜「-z re9=正規表現」(クライアント認証の場合)
あるいは 「-q re0=正規表現」〜「-q re9=正規表現」(サーバ認証の場合) で指定する。
stone の設定ファイルの一例を次に示す:
-z key=key.pem -z cert=cert.pem -z verify -z CApath=/usr/local/ssl/certs -z re2="/CN=GCD Root CA/" -z re1="/CN=GCD_Sengoku_CA/" -z re0="/CN=test[0-9]*/" localhost:25 465/ssl
指定した全ての「re0=正規表現」〜「re9=正規表現」が、 それぞれ証明書連鎖の「depth0」〜「depth9」とマッチするときに限り、 stone は接続を許可する。
stone 2.3c (近日公開予定) 以降では、 root CA から数えた階層数で「re数字=正規表現」を指定することもできる。 すなわち、root CA を「-1」とし、root CA の子CA が「-2」、 以下順に数字が減っていく。 したがって、上述の設定は以下の設定と等価である:
-z key=key.pem -z cert=cert.pem -z verify -z CApath=/usr/local/ssl/certs -z re-1="/CN=GCD Root CA/" -z re-2="/CN=GCD_Sengoku_CA/" -z re0="/CN=test[0-9]*/" localhost:25 465/ssl
CA の階層数が 2 (すなわち root CA が depth2) の場合、 「re2=」と「re-1=」、および「re1=」と「re-2=」は、 それぞれ同じ証明書を示す。 両方指定した場合、後者が優先される。 この指定方法を用いると、 中間CA の階層数が一定でなくても、 root CA あるいはその子CA の識別名が満たすべき正規表現を指定することが 可能である。 例えば、
-z re-1="/CN=GCD Root CA/" -z re0="/CN=test[0-9]*/"
などと指定すると、 中間 CA の階層数にかかわらず、 root CA が「GCD Root CA」であり、 CN が「test[0-9]*」にマッチするような証明書を許可する。
(次回に続く)
前回説明したように、 stone で SSL クライアント認証を行なうには、
-z verify -z CApath=ディレクトリ
という設定で実行すればよい。
クライアント認証の代わりにサーバ認証を行ないたい場合、 すなわちサーバが提示した証明書を検証して、 通信相手であるサーバが正に意図した通りの相手であるか確認したい場合は、 「-z」を「-q」に置き換える。 例えば、 ローカルホストの 12345番ポートへの接続を https://www.klab.org へ 中継しつつサーバ認証を行なう場合、 次のように実行する:
% stone -q verbose -q verify -q CApath=/usr/local/ssl/certs www.klab.org:443/ssl 12345 Aug 13 16:13:35.576345 16384 start (2.3c) [3925] Aug 13 16:13:35.588527 16384 stone 3: m139.tdc.klab.org:https/ssl <- 0.0.0.0:12345 Aug 13 16:13:41.364823 16384 3 TCP 6: [depth2=/L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//emailAddress=info@valicert.com] Aug 13 16:13:41.383216 16384 3 TCP 6: [depth1=/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./OU=http://www.starfieldtech.com/repository/CN=Starfield Secure Certification Authority/emailAddress=practices@starfieldtech.com] Aug 13 16:13:41.383495 16384 3 TCP 6: [depth0=/O=*.klab.org/OU=Domain Control Validated/CN=*.klab.org] Aug 13 16:13:41.465200 16384 [SSL cipher=AES256-SHA] Aug 13 16:13:41.482583 16384 [SSL serial=3db9d6] Aug 13 16:13:41.482633 16384 [SSL subject=/O=*.klab.org/OU=Domain Control Validated/CN=*.klab.org] Aug 13 16:13:41.482658 16384 [SSL issuer=/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./OU=http://www.starfieldtech.com/repository/CN=Starfield Secure Certification Authority/emailAddress=practices@starfieldtech.com]
この実行例では、 stone を実行した後、ローカルホストの 12345番ポートへ (telnet 等のプログラムを使って) 接続を行なっている。 すると、stone は www.klab.org の 443番ポートへ接続する。 www.klab.org が提示した証明書を受けて、 stone はその証明書を発行した root CA を調べる。
上記実行例 4行目「depth2=...」 に表示されているように、 root CA は「ValiCert Class 2 Policy Validation Authority」である。 この root CA の証明書 (ハッシュ値は bcdd5959) は、 「/usr/local/ssl/certs」ディレクトリに 「bcdd5959.0」というファイル名で用意してあったので、 stone はサーバ認証を行なうことができている。
Firefox などの WWWブラウザは、 メジャーな root CA の証明書を最初から全て持っている。 したがって https な URL を開くとき、 自動的にサーバ認証を行なうことができる。 stone の場合はデフォルトの状態では何も root CA 証明書を持っていないので、 サーバ認証/クライアント認証を行なおうとする場合は、 root CA 証明書を置くディレクトリを用意し、 CApath で指定する必要がある。
なお、WWW ブラウザで普通に「サーバ認証」を行なう場合は、 単にサーバが提示する証明書が既知の root CA から発行されているだけでは 充分ではなく、 その証明書の識別名において、 「CN=...」が示す FQDN がサーバのホスト名と一致しなければならない。
stone でも「CN=...」が示す FQDN をチェックすることができるが、 その方法については 次回説明する。
上記実行例 6行目「depth0=...」が、
サーバが提示したサーバ証明書である。
なお、「CN=*.klab.org」 と表示されていることから分かるように、
このサーバ証明書はワイルドカード証明書であり、
klab.org ドメインの任意のホストの身元証明に使用できる。
さて、これで stone を使って通信相手がサーバの時もクライアントの時も、 通信相手を SSL 認証することができるわけであるが、 逆に認証してもらう側はどのような設定を行なえばよいのだろうか?
実は、stone がサーバ認証を受ける側であるときの設定方法は、 すでに前回説明している。 サーバ証明書の秘密鍵および公開鍵が、 それぞれ「key.pem」と「cert.pem」というファイル名で 保存してあるなら、次のように stone を実行する。
stone -z key=key.pem -z cert=cert.pem localhost:80 443/ssl
stone がクライアント認証を受ける側であるときの設定方法は、 「-z」を「-q」に置き換えるだけである。 すなわち、
stone -q key=key.pem -q cert=cert.pem warp.klab.org:443/ssl 12345
このように実行しておいて、 ローカルホストの 12345番ポートへ接続すれば、 クライアント認証を要求する https サーバ「warp.klab.org」へ 接続することができる(もちろん、key.pem および cert.pem が適切であれば)。
(次回に続く)
stone の SSL 暗号化/復号の機能は、 おかげさまで沢山の方々に使って頂いている。 任意の TCP/IP 接続を手軽に SSL 化できるので、 SSL 化のためだけに stone を使っている、というかたも多そうだ。
例えば 25番ポートで接続を受付ける SMTP サーバがある場合、
stone -z key=key.pem -z cert=cert.pem localhost:25 465/ssl
などと実行するだけで、 SSL 化した SMTP を 465番ポートで受付けることができるようになる。 ここで、「key.pem」および「cert.pem」は、 それぞれ秘密鍵と公開鍵のファイルであり、 OpenSSL のコマンドを使って作ることができる (日経Linux に以前私が書いた連載記事の 「第 6 回 stone (後編) 公開かぎと秘密かぎ」でも作り方を説明した)。
SSL (Secure Socket Layer) というと 暗号化を思い浮かべる人が多いかも知れないが、 暗号化に負けず劣らず重要なのが、通信相手の認証である。 認証、つまり通信相手の確認をせずに通信内容だけ暗号化しても、 通信相手が意図した相手でなく盗聴者だったりしたら、 少しも「セキュア」ではない。
もちろん stone には通信相手を SSL で認証する機能がある。
クライアント認証、すなわち通信相手がクライアントの場合は、
「-z verify」を指定し、
サーバ認証、すなわち通信相手がサーバの場合は、
「-q verify」を指定する。
ちなみに stone の SSL 関連のオプションは 全て「-z」か「-q」が前につく。 「-z」は stone がサーバとして振る舞うときのオプション、 「-q」は stone がクライアントとして振る舞うときのオプションである。 通信相手がクライアントの場合というのはつまり stone がサーバとして振る舞う わけだから、「-z verify」になる。
前述した「SSL 化した SMTP」を受付ける stone の場合であれば、 通信相手はクライアントであるから、 「-z verify」を指定する。 このオプションを指定すると、 stone はクライアントに証明書の提示を要求する。 そして提示された証明書を検証するためには、 その証明書を発行した root CA の証明書が必要である。
もちろん、「証明書の提示」といっても、 証明書を送信すれば済む、というものではない。 証明書自体は公開情報 (公開鍵) なので、 それを送信してもクライアントの身の証にはならない。 証明書には対応する秘密鍵があって、 この秘密鍵を持っていることこそがクライアントの身の証である。 SSL プロトコルによってクライアントは秘密鍵をサーバに送信することなく、 自身が秘密鍵を有することをサーバに納得させることができる。
そして、クライアントの身元を第三者的に証明するのが CA の役割である。 ここで言う CA は、 Certificate Authority (認証局) のことであって、 もちろん Cabin Attendant のことではない。 CA を認証する親 CA といった形で CA の階層構造が作られ、 クライアントの証明書を発行するのは末端の CA であることもあるが、 stone が持っている必要があるのは階層構造の一番上、 root CA の証明書のみである (root つまり「根っこ」)。 root CA の証明書一つで、 root CA の子 CA, 孫 CA, ... 階層構造に含まれる全ての CA が発行した 証明書の検証を行なうことができる。
root CA の証明書を置くディレクトリは、
「-z CApath=ディレクトリ」で指定する。
例えば「/usr/local/ssl/certs」ディレクトリに
root CA の証明書を置く場合は、
「-z CApath=/usr/local/ssl/certs」と指定する。
stone がクライアントに証明書の提示を要求し、 クライアントがそれに答えた場合、 stone はクライアントが提示した証明書を発行した root CA を調べ、 その識別名の「ハッシュ値」を求める。 root CA の識別名のハッシュ値は、 root CA の証明書のファイル名を「CA-cert.pem」とすると、 次のように「openssl x509」コマンドで求めることができる。
% openssl x509 -hash -noout -in CA-cert.pem ee31d843
次に stone は、 「-z CApath=ディレクトリ」で指定された証明書ディレクトリ (この例では「/usr/local/ssl/certs」) の中の、 「ハッシュ値.数字」というファイル名の証明書を用いて、 クライアントが提示した証明書の検証を行なう。
例えば root CA の識別名のハッシュ値が「ee31d843」であり、 「/usr/local/ssl/certs/ee31d843.0」が存在するなら、 このファイルを root CA の証明書として用いる。 なぜ ファイル名に「.0」という拡張子をつけるかというと、 この証明書ディレクトリに複数の root CA 証明書を置きたい場合、 「たまたま」ハッシュ値が一致してしまう場合があり得るからである。 その場合は、どちらか一方の証明書の拡張子を「.1」にする。
root CA 証明書は、 「ハッシュ値.数字」という形式のファイル名でなければ stone は参照しないが、 かといって「ハッシュ値.数字」というファイル名では、 どのファイルがどの root CA の証明書だか分からなくなってしまうので、 次のように root CA 証明書「CA-cert.pem」のシンボリックリンクを 作成しておくとよいだろう。
% ln -s CA-cert.pem /usr/local/ssl/certs/ee31d843.0
Windows など、シンボリックリンクが存在しない OS の場合は、 単にコピーしておくだけでもよい。
C:\usr\local\ssl\certs> copy CA-cert.pem ee31d843.0
以上、まとめると stone の設定は次のようになる:
-z key=key.pem -z cert=cert.pem -z verify -z CApath=/usr/local/ssl/certs localhost:25 465/ssl
この設定を例えば stone.config というファイル名で保存し、 「stone -C stone.config」などと実行すれば、 正しいクライアント証明書を提示したクライアントからの接続のみ受付け、 証明書を提示しないクライアントや、 証明書ディレクトリに証明書が存在しない root CA が発行したクライアント証明書を 提示したクライアントからの接続を拒否する。
クライアントが、既知の root CA (の子 CA) が発行した証明書を提示した場合の例:
# stone -z verbose -C stone.config Aug 12 08:04:13.769309 16384 start (2.3c) [21093] Aug 12 08:04:13.773038 16384 stone 3: 127.0.0.1:smtp <- 0.0.0.0:465/ssl Aug 12 08:04:26.534690 16384 3 TCP 5: [depth2=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/CN=GCD Root CA/emailAddress=root@gcd.org] Aug 12 08:04:26.551203 16384 3 TCP 5: [depth1=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=GCD_Sengoku_CA/emailAddress=sengoku@gcd.org] Aug 12 08:04:26.551674 16384 3 TCP 5: [depth0=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=test/emailAddress=sengoku@gcd.org] Aug 12 08:04:26.573916 16384 [SSL cipher=AES256-SHA] Aug 12 08:04:26.573974 16384 [SSL serial=13] Aug 12 08:04:26.574000 16384 [SSL subject=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=test/emailAddress=sengoku@gcd.org] Aug 12 08:04:26.574022 16384 [SSL issuer=/C=JP/ST=Kanagawa/L=Kawasaki/O=GCD/OU=Hiroaki Sengoku/CN=GCD_Sengoku_CA/emailAddress=sengoku@gcd.org]
1行目のコマンドラインで「-z verbose」と指定しているが、 これは SSL 関係の詳細ログを表示させるためのオプションである。 「depth2=...」(4行目) が、 root CA の証明書の識別名である。 この証明書は stone にとって既知の証明書なので、 検証が成功する。 「depth1=...」(5行目) は、 root CA の子 CA の証明書の識別名であり、 「depth0=...」(6行目) は、 クライアントの証明書である。
クライアントが、未知の CA が発行したクライアント証明書を提示した場合の例:
Aug 12 08:05:15.587108 16384 3 TCP 5: [depth1=/C=JP/ST=Tokyo/L=Minato-ku/O=K Laboratory Co.,Ltd/CN=KLAB Root CA/emailAddress=root@klab.org] Aug 12 08:05:15.587172 16384 3 TCP 5: verify error err=19 self signed certificate in certificate chain Aug 12 08:05:15.587415 16384 3 TCP 5: SSL_accept lib error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned
1行目に、別の root CA の識別名を表示しているが、 この root CA は証明書ディレクトリの中に証明書が存在しないので、 この stone にとって未知である。 したがって、2行目 「verify error err=19 self signed certificate in certificate chain」 つまり「クライアントが自分で署名した証明書 (いわゆる「オレオレ証明書」) を 提示した」と、 検証に失敗した旨のエラーメッセージが出力されている。 クライアントからの接続はこの直後に切断される。
(次回に続く)
唐突に何かを「ひらめく」という経験は誰しもあるだろう。 「ひらめき」が天から降ってくる、というのは考えにくいので、 意識はしていないものの何らかの思考が脳の中で行なわれ、 その思考の結果が意識にのぼったとき、 「ひらめく」と考えるのが自然だろう。
この意識していない思考、すなわち「無意識の思考」を積極的に活用すれば、 同時に沢山のことを考えられる。 時間を効率的に使えるだけでなく、 自身の脳の中で何が起きているのか理解するきっかけになるのではないかと、 今まで考察を重ねてきた:
意識の「下」に、意識を支える広大な「無意識」がある、 というイメージで考え、 その無意識をもっと活用したい、という思いからいろいろ考えてきたわけであるが、 前野隆司氏のページを読んで、 文字通り天地が引っくり返ってしまった:
「脳はなぜ『心』を作ったのか」から引用:
1つの面白い実験結果がある。 人が指を動かそうとするとき, 脳の中の,「動かそう」と意図する働きを担う部分と, 筋肉を動かそうと指令する運動神経が, どんなタイミングで活動するかを計測したカリフォルニア大のリベット博士の実験だ。 結果は実に意外だった。 筋肉を動かすための運動神経の指令は, 心が「動かそう」と意図する脳活動よりも,0.5秒も先だというのだ。 常識的に考えると,まず人の心の「意識」が「動かそう」と決断し, それにしたがって体が動くと予想されるのに,結果は何と逆なのだ。
そうだったのか! それで全て辻褄が合う!
人の「意識」とは, 心の中心にあってすべてをコントロールしているものではなくて, 人の心の「無意識」の部分がやったことを, 錯覚のように,あとで把握するための装置に過ぎない。
まさに、 地球が宇宙の中心で、太陽や星が周囲を回っていると思っていた人が、 地動説を聞かされたときの気分だった。 「無意識の思考」と「意識した思考」の二種類があるのではなく、 「無意識の思考」が全てだったとは。
「あとで把握するための装置」という説明は私にとって、 とても納得のいく考え方だ。 すなわち、無意識の思考は様々なことを「同時に考えている」が、 実際に何を考えていたか、ほとんど忘れてしまう。 ごくわずかな例外が、「意識にのぼった思考」、否、 「意識という記録装置」によって「すくいあげられた思考」ということなのだろう。
同様のことが「夢」にも見られる。 外部刺激が夢に影響を与えることがある。 例えば、目覚まし時計が鳴る音が、 夢の中で電話の呼び出し音として登場するなど。 しかし、因果律で考えれば、目覚まし時計が鳴ることが原因で、 夢の中で電話が鳴ることが結果であるはずだ。 なぜ、
- 夢の中で、何かをしているとき、
- 電話が鳴る音を聞き、
- 受話器を取り上げようと行動しているうちに、
- 目覚め、
- 目覚まし時計が鳴る音を聞く、
という順番になるのだろうか? 電話が鳴る前に何も夢を見ていないのならまだ理解できるが、 夢なりに脈絡があるシチュエーション (1) で電話が鳴る (2) のである。
どうして外部からの刺激 (2) が原因なのに、 それが結果となるような夢 (1) を「たまたま」見ることができるのか、 とても不思議だった。 私が考えた仮説は、 外部刺激を受けた一瞬のうちに、 夢の全て (1)〜(3) (電話が鳴る前の全ての状況を含む) を見て、 そして目覚める、というものだった。
「夢」とは、 寝ている間の無意識の思考の一部を「すくいあげた」ものである、 と考えれば辻褄が合う。 寝ている間、無意識の思考は勝手にいろいろなことを考えるが、 そのほとんどは忘れてしまう。 唯一例外的に覚えているのは、「夢」として意識したエピソードなのであろう。 だから、時系列でいうと、
- 様々な無意識の思考が進行中...
- 目覚まし時計が鳴る
- 目覚まし時計の音の刺激を受けて、無意識の思考「電話が鳴る」が進行する
- 目覚める
- 「電話が鳴る」思考が、「夢」として意識される
「意識」は元々、「無意識の思考」の後に来るものなので、 因果律的には矛盾がない。 つまり、電話が鳴る音が先で、目覚めるのが後、と 意識する (正確に言えば、そういう記憶が残る) のは錯覚に過ぎない。 意識とは元々そういうものなのだ。
意識とは、脳というコンピュータにおけるロガー (unix で言うところの syslog ;-) に過ぎないのだろう。 つまり、自由意思で何かをしようと決断し、何か行動を起こす、のではなく、 「決断して行動した」という「記憶」が残っている、ということなのだろう。
にわかには信じがたい (人によっては不快とさえ思うかも知れない) 説ではあるが、 「単純なものほど真実に近い」はずであり、 「意識」が「エピソード記憶」のためにある、 という説はとても単純であるように思われる。 ちょうど、「地動説」が (ガリレオの時代の人々にとっては) 信じがたい説であったが、 惑星の見かけの動きを単純に説明できたように。
さっそく前野隆司氏の著書:
脳はなぜ「心」を作ったのか
「私」の謎を解く受動意識仮説
前野 隆司 著
を注文した。 将来のロボットは、本当に心を持つことができるようになるのだろうか?