me はプロセスを生成するユーザ ID とファイルを生成するユーザ ID を表示する。例えば me を実行するとterm% me arisawa 111 0:00 0:00 184K Pread ps --rw-rw-rw- M 9 arisawa none 0 Dec 7 17:44 /usr/none/tmp/me
me の実行例
me のやっていることは単純で実際にプロセスとファイルを生成してみて生成者の ID を表示する。1行目が生成されたプロセスのユーザ ID、2行目が生成されたファイルのユーザ ID である。UNIX と異なり Plan 9 の場合にはこの2つのユーザ ID は同じとは限らない。
#!/bin/rc # note: chmod 777 /usr/none/tmp f=/usr/none/tmp/me ps|grep ' ps$' if(test -e $f) rm $f touch $f; ls -l $f
me の内容
である。/usr/none/tmp に生成する。このディレクトリは Plan 9 の標準設定ではユーザ none 以外の書き込めないのでchmod 777 /usr/none/tmp
/usr/local/bin に置いている。chmod 755 /usr/local/bin/rc/me
/bin に自動的に追加されるようにするのが手っ取り早い。/lib/namespace に次の行が含まれている事を確認する。. /lib/namespace.local
/lib/namespace が古いのでシステムを更新する。
/lib/namespace.local を作成する。
bind -a /usr/local/bin/386 /bin bind -a /usr/local/bin/rc /bin
/lib/namespace.local の内容
これで、どのユーザも me を実行できる。
fact を用意しました。次のように使います。term% fact --rw-r--r-- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/ctl key proto=p9sk1 dom=aichi-u.ac.jp user=arisawa !password? key proto=p9sk1 dom=aichi-u.ac.jp user=bootes !password? key proto=p9sk1 dom=aichi-u.ac.jp user=alice !password? term% fact -l -lrw------- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/confirm --rw-r--r-- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/ctl -lr-------- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/log -lrw------- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/needkey --r--r--r-- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/proto --rw-rw-rw- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/rpc term% fact -d deleting from /mnt/factotum/ctl delkey proto=p9sk1 dom=aichi-u.ac.jp user=arisawa !password? delkey proto=p9sk1 dom=aichi-u.ac.jp user=bootes !password? delkey proto=p9sk1 dom=aichi-u.ac.jp user=alice !password? send and ctl-D delkey proto=p9sk1 dom=aichi-u.ac.jp user=alice !password? term% fact -a adding to /mnt/factotum/ctl put data and ctl-D key proto=p9sk1 dom=aichi-u.ac.jp user=alice !password=xxxxx term%
ls -l /mnt/factotum および ls -l /mnt/term/mntfactotum を表示します。
注:
send」で送り、ctl-D で削除されます。複数のキーを選択できます。send」で送り、ctl-D で追加されます。複数のキーを選択できます。/mnt/factotum/ctl への書き込みによってキーの削除や追加を行いますが、場合によっては /mnt/term/mnt/factotum/ctl にアクセスする必要があり、オプションの -d や -a に続く文字(1または2)によってどちらであるかを選択できます。fact の内容は次の通りです。#!/bin/rc
usage='usage: fact [-adl]'
fn addkey <code>
        echo adding to $1
        echo 'put data and ctl-D'
        read -m >/$1
</code>
fn delkey <code>
        echo deleting from $1
        sed s/key/delkey/g<$1
        echo 'send and ctl-D'
        read -m>$1
</code>
ctl=()
f=(/mnt /mnt/term/mnt)^/factotum/ctl
if(test -w $f(2)) ctl=$f(2)
if(test -w $f(1)) ctl=$f(1)
while(~ $1 -*)<code>
        switch($1)<code>
        case    -d
                delkey $ctl
                exit
        case    -d1
                delkey $f(1)
                exit
        case    -d2
                delkey $f(2)
                exit
        case -a
                addkey $ctl
                exit
        case -a1
                addkey $f(1)
                exit
        case -a2
                addkey $f(2)
                exit
        case -l
                f=(/mnt /mnt/term/mnt)^/factotum
                for (x in $f)
                        if(test -e $x) ls -l $x
                exit
        case -*
                echo $usage
                exit usage
        </code>
        shift
</code>
for (x in $f)
        if(test -w $x)<code>
                ls -l $x
                cat $x
        </code>
これを me と同様に /usr/local/bin/rc に置くとよいでしょう。chmod 755 をお忘れなく。
su は UNIX の su と同様にユーザ ID を変更する。また UNIX の sudo の機能を併せ持っている。su のシンタックスはsu [-fnuwD] [-p password] [user [cmd arg ...]]
su alice
su はこの場合でも必要に応じてパスワードの入力を求めてくる:term% su alice password: blackcat su# me alice 122 0:00 0:00 184K Pread ps --rw-rw-rw- M 28 alice none 0 Dec 7 17:46 /usr/none/tmp/me su#入力を求められたパスワードなどの情報は、
/mnt/factotum が su を実行するユーザのものであれば、 factotum に自動的に登録される仕組みになっている。cpu コマンドでホストにログインして su を使う場合にはbind -b /mnt/term/mnt/factotum /mnt/factotum
auth/factotum
auth/factotum -n
ユーザ名が省略された場合には (UNIX と異なり)最も弱いユーザである none が仮定される。
/dev/hostdomain が存在する。しかしこれは今のところ利用されていない。ここは hostdomain の値を入れる場所のはずである。su は /dev/hostdomain を利用している。ここへの書き込みの権限はホストオーナーだけが持っている。/rc/bin/cpurc と /rc/bin/termrc に次のような行を入れればよい。echo -n aichi-u.ac.jp >/dev/hostdomain
aichi-u.ac.jp は筆者のシステムの hostdomain でありシステム毎に異なる。/dev/hostdomain に値が設定されていない場合には su は hostdomain の値の入力を要求してくる。
su ver.1.4 は http://plan9.aichi-u.ac.jp/netlib/cmd/su/ から手に入る
補注: 退職したので aichi-u.ac.jp では動いていません。  現在は su ver.1.6 が
 http://p9.nyx.link/netlib/cmd/su/
に置かれています。
bootes や bob が su によってパスワードなしに alice に変身できるか否かがここでの関心である。
su alice
su はパスワードの入力を求める。パスワードの入力が求められなくても、su を実行するユーザの factotum に alice のパスワードが含まれていることが変身可能な理由であれば、変身にはパスワードが必要であると考えよう。すると結果は次のように纏める事ができる。
| カーネル | 実行者 | パスワード | 結果(プロセス) | 結果(ファイル) | 
|---|---|---|---|---|
| 9pcdisk | bob | 無 | OK | OK | 
| 9pcf | bob | 無 | OK | OK | 
| 9pc | bob | 無 | OK | NO | 
| 9pc | bob | 有 | OK | OK | 
| 9pcauth | bootes | 無 | OK | OK | 
| 9pcauth | bob | 無 | NO | NO | 
| 9pcauth | bob | 有 | OK | OK | 
| 9pccpu | bootes | 無 | OK | OK | 
| 9pccpu | bootes | 有 | OK | OK | 
| 9pccpu | bob | 無 | NO | NO | 
| 9pccpu | bob | 有 | OK | OK | 
/lib/ndb/auth でその権限が与えられているからである。
/mnt/factotum かそれとも /mnt/term/mnt/factotum か?/mnt/factotum あるいは (cpu コマンドでログインした場合には) /mnt/term/mnt/factotum に置かれているが、認証に関する場面では Plan 9 のライブラリはどれも /mnt/factotum を使っている。(従って su もそのスタイルを守っている)
/mnt/factotum か?/mnt/factotum は場合によっては su を実行するユーザのもの、場合によってはホストオーナーのものでなくてはならない。このことがプログラミングでは混乱の原因になる。例えば bob がsu alice
/mnt/factotum は bob のものでなくてはならない。他方 bob はホストオーナーに対して alice のプロセスの生成者となるようにパスワードを添えてお願いしなくてはならない。この場面では /mnt/factotum はホストオーナーのものでなくてはならない。newns(char *user, char *nsfile) は問題を抱えている。引数 user が実際上働いていないのである(環境変数の設定にしか使われていない)。これは factotum を導入したことに伴う問題点(バグ)である。(Plan 9 にとって本質的なものではなく、ライブラリの修正によって克服可能な問題点である。)newns では最初の factotum キーが参照される。例えば bob のキーがkey proto=p9sk1 dom=aichi-u.ac.jp user=alice !password? key proto=p9sk1 dom=aichi-u.ac.jp user=bob !password? key proto=p9sk1 dom=aichi-u.ac.jp user=carol !password?
newns("bob", nil) や newns("carol", nil) が実行されても、生成される名前空間は alice のもの、即ち bob はファイルシステムに対しては alice として認証される。この事は newns() を利用したアプリケーションを作成するときにセキュリティ上の落とし穴になる。user を名前空間の構築の中で生かす事、もう1つは newns の引数から user を捨てる事。後者の場合には user は /dev/user を参照して決定する事になる。筆者は /dev/user によって決定される名前空間が好ましいと考えるが、これまでの newns() との互換性と将来の柔軟性を重視すれば前者の方が選択されるであろう。su ver.1.4 の中には修正した newns.c が含まれている。(su の構成に必要な分だけ含まれており、そのため addns() は捨てられている。)AuthInfo* auth_userpasswd(char *user, char *passwd)
/mnt/factotum はホストオーナーのものを使う。) パスワードはコマンド引数などによって明示的に与えてもよいが、factotum から読み取らせてもよい。factotum から読み取らせる場合にはUserPasswd* auth_getuserpasswd(AuthGetkey *getkey, char* fmt, ...)
su を実行するユーザ bob のものである。factotum からパスワードを貰えるためにはキーの形式は proto=pass である。(この場合には factotum は生のパスワードを記憶しており、それを渡す事ができる。)proto=pass のキーを持たなくても、リモートホストの中にユーザのプロセスを生成する。このメカニズムは筆者は今のところ分かっていない。
getkey である。Plan 9 はそのための標準ライブラリ関数 auth_getkey() を持っている。auth_getkey は /dev/cons を使用する。パスワードの入力の際にエコーバックを止めたいからである。しかし /dev/cons はホストオーナーの所有であり、ホストオーナーだけが使用できる。ホストオーナーでない bob が su を実行し、factotum が auth_getkey を呼び出したら、ここで致命的なエラーが発生するとこになる。従って su は auth_getkey() を使わない。su はエコーバックの問題を犠牲にして標準入出力を使用する。その関数 getkey() が su.c に含まれている。su alice
getkey() は bob から受け取った alice の認証情報を、bob の factotum に格納する。それは bob が所有する /mnt/factotum/ctl に書き出す事によって実現される。このファイルはプロセス factotum による仮想ファイルであり、そのオーナーは factotum の生成者である。従って su は、もしも  /mnt/factotum/ctl が bob のものでないなら、factotum を生成しなくてはならない。su alice
/mnt/factotum/ctl に書き出そうとすると(既に su のプロセスは alice のものだから)書き込みを拒否される。getkey() ではもう1つの工夫がされている。getkey() で得られた認証情報を確実に bob の factotum に送り込むために、bob の /mnt/factotum/ctl を最初に開いてしまい、その fd (ファイルディスクリプタ) を使い続けるのである。
su alice
getkey() を呼び出さない。そのために su の中では次の連続した手順が踏まれている。/srv/factotum を /mnt にマウントしanewns("alice", nil) を実行するanewns() は newns() の修正版である。getkey() を呼び出す。/mnt/factotum が存在する。1. は新たに bootes の /mnt/factotum を作成する。既に存在するものと、新たに作成されるものはどこが違うのか? その違いが今の筆者にはよく分からないのである。
/lib/ndb/auth に hostid で指定されている場合に[注1]、このオプションによってパスワード無しに任意のユーザに変身できる。su を実行するユーザ名が bootes の場合には su の内部で自動的にこのオプションが設定される。
/lib/ndb/auth/lib/ndb/auth には「信頼できるユーザ」が定義されている。この内容は標準設定ではhostid=bootes uid=!sys uid=!adm uid=*となっている。これは bootes のキーによって、adm と sys を除く他のユーザを認証することを意味している。もしも
hostid=bootes uid=!sys uid=!adm uid=* hostid=bob uid=aliceとなっていれば、その他に bob は alice に対してのみパスワード無しでファイルサーバに認証されることになる。
/lib/ndb/auth の hostid は行の先頭から書き始めなくてはならない。他方 uid は先頭から書いてはいけない。
term% fact --rw-r--r-- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/ctl key proto=p9sk1 dom=aichi-u.ac.jp user=bootes !password? key proto=p9sk1 dom=aichi-u.ac.jp user=bob !password? term%の場合には bob は bootes のキーを知っていることになる。そして bootes は
/lib/ndb/auth の中で hostid で指定されている。従って su の -f オプションは有効である。 普通は bob のキーは factotum の先頭に置かれる[注2]。term% fact --rw-r--r-- M 11 arisawa arisawa 0 Dec 7 21:30 /mnt/factotum/ctl key proto=p9sk1 dom=aichi-u.ac.jp user=bob !password? key proto=p9sk1 dom=aichi-u.ac.jp user=bootes !password? term%その場合には bob も hostid で指定されていない限り
-f オプションは有効ではない。
newns() の抱えている問題のためにホストオーナーのキーは factotum の先頭に置く必要がある。
su [-fnuwD] [- p password] user cmd [arg ... ]
user は必ず必要である。ユーザ none の場合には user には none を指定する。cmd は実行すべきコマンド名であり、arg はそれに与える引数である。コマンド名には絶対パス、相対パス、あるいは /bin からの相対パスが指定できる。/ で始まる。相対パスは ./ あるいは ../ で始まる。いずれでもないものは /bin からの相対パスであると見なされる。su none ps su alice me su alice ./foo
foo はカレントディレクトリにあるとしている。
最近になって、
auth/as
auth/login + auth/as + auth/none
補注: auth/su で変更されるのはプロセスのオーナーだけて、ファイルに対する権限は変更されない。(2021)
数年前に Plan9 からの派生OSが生まれた。9front と言う。これに関しては別の機会に触れることとする。Plan9 と 9front の表面的な違いであるが、管理者 id が Plan9 の bootes から glenda に変更されている。ver.1.5 までの su は、管理者 id が bootes である事が使われている。そこで ver.1.6 では、glenda でも構わないように書き換えた。また -w オプションを廃止し、さらに、詳しいヘルプメッセージを出すようにした。