実行 - みる会図書館


検索対象: UNIX MAGAZINE 1999年10月号
68件見つかりました。

1. UNIX MAGAZINE 1999年10月号

連載 / Linux でリラックス Debian GNU/Linux の /etc/inittab ファイル 図 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 # The default runlevel . id: 2 : initdefault : ←デフォルトの実行レベルは 2 # Boot—time system configuration/initialization script . # This is run first except when booting in emergency (—b) mode. /etc/init . d executes the S and K scripts upon change : S:wait : /sbin/sulogin ←シングノレユーザー・モードのときに実彳予 What tO dO in single—user mode . SI : : sysinit : /etc/init . d/rcS ←起動時に 1 度だけ実行 # Run1eve1s 2 ー 5 are multi—user . # Run1eve1 1 is single—user. # Run1eve1 0 is halt . # of runlevel . # Run1eve1 6 is reboot . 10. 11 12. 13. 14. 15. 16. ・ 5 : ・ 4 : wait ・ 2 : wait : 1 : wait ・ 0 :wait : /etc/init . d/rc :/etc/init . d/rc :/etc/init .d/rc ・ 3 :wait : /etc/init . d/rc :/etc/init . d/rc 4 : /etc/init . d/rc ・ 6 :wait :/etc/init . d/rc 0 1 2 3 5 6 ←システムの停止時に実行 ←シングルューサー・モードのときに実行 ←実行レベルが 2 のときに実行 ←実行レベルが 3 のときに実行 ←実行レベルが 4 のときに実行 ←実行レベルが 5 のときに実行 ←システムの再起動時に実行 # Norma11y not reached , but fallthrough in case of emergency ・ ←システムの再起動に失敗したときに実行 z6 : 6 :respawn: /sbin/sulogin # What tO dO when CTRL—ALT—DEL is pressed. po : :powerokwait : /etc/init. d/powerfail stop pn : : powerfailnow : /etc/init . d/powerfail now pf : :powerwait : /etc/init . d/powerfail start # What to do when the power fails/returns . ↑ Alt 十↑キーが押されたときに実行 kb: :kbrequest : /bin/echo "Keyboard Request——edit /etc/inittab tO let this work. # Action on special keypress (ALT-UpArrow) . ↑ CtrI 十 AIt 十 DeI キーが押されたときに実行 ca: 12345 : ctrlaltdel : /sbin/shutdown —tl —a —r now # The " id" field MUST be the same as the last /sbin/getty invocations for the runlevels . ↑ UPS デーモンと組み合わせて使用される characters 0f the device (after "tty") . Format : く id> : く runlevels> : く action>: く process> 1 : 2345 :respawn: /sbin/getty 38400 ttyl 2 :23:respawn:/sbin/getty 38400 tty2 3 : 23 : respawn : /sbin/getty 38400 tty3 4 : 23:respawn: /sbin/getty 38400 tty4 5 :23:respawn:/sbin/getty 38400 tty5 6:23:respawn:/sbin/getty 38400 tty6 108 ←実行レベルが 2 ~ 5 なら getty を起動 ←実行レベルが 2 または 3 なら、 仮想コンソール 2 ~ 6 でも getty を起動 UNIX MAGAZINE 1999.10

2. UNIX MAGAZINE 1999年10月号

の起重加に、どのような初期化スクリプトが、どのような 順番で実行されるのかをすこし詳しく説明します。 そのあと、 Debian GNU/Linux パッケージの使用法 に関するドキュメントの探し方を説明します。 dselect コ マンドなどを利用してさまざまなパッケージをインストー ルしてみたものの、パッケージの使い方がよく分からない ために、使いこなせない人も多いのではないでしようか。 そこで、新た ( ンヾッケージをインストールしたときに、ど うやってドキュメントを探せばいいのかを紹介します。さ らに、パッケージの成疋ファイルやログファイルがどのよ うなディレクトリにオタされているのかもあわせて説明し ます。 Debian の初期化スクリプト init テーモン Debian GNU/Linux にかぎらず、一殳の UNIX オ ペレーティング・システムでは、ハードウェアの初期化 やデーモンの起動などをおこなう初期化スクリプトはⅲ it デーモンによって起動されます。これは、カーネルが最初 ( プロセス番号 1 ) のプロセスとして起重丿けるデーモンであ り、他のすべてのプロセスの親プロセスとなります。 他の多くの Linux 配布パッケージと同様、 Debian GNU/Linux では、 init デーモンとして MiqueI van Smoorenburg が作成した SystemV 互換の sysvinit を用いています。 sysvinit の詳細は、 Slackware の初期 化スクリプトをとりあげたとき ( 2 月号 ) に解説したの こでは sysvinit そのものについては説明しません。 で、 sysvinit における実行レベル (runlevel) の定義や、 init デーモンの成疋ファイルである /etc/inittab ファイルの 書式などについては、 2 月号を参照してください。 /etc/init. d ディレクトリ Debian GNU/Linux の初期化スクリプトは、すべて /etc/init. d というディレクトリ内にオ内されています。 これらの初期化スクリプトは、システムの起重加 ( 正確に は init デーモンの起重加 ) や、システムの夫行レベルか変 化するときに、 init デーモンによって実行されます。これ らのネ月化スクリプトにより、さまざまなサービスの開始 連載 / 凵 nux でリラックスー 104 や終了などがおこなわれます。 ただし、実行する初期化スクリプトの不頁は、実行レベ ルに応して変化します。また、初期化スクリプトを実行す る順番も重要です。たとえば、ネットワークの設定をお こなう初期化スクリプトや、ノヾックグラウンドでデーモン を起動する初期化スクリプトなどは、一殳にシングルユー サー・モードでは実行する必要はありません。また、ネット ワークの設定をおこなうネノ期化スクリプトは、ネットワー クを利用するデーモンを起動する初期化スクリプトよりも 前に実行しておく必要があります。 Debian GNU/Linux では、基本的に SystemV と同 じ方式 2 で、どのようなスクリプトをどのような順番で起 重丿庁るのかを決定しています。つまり、それぞれの実行レ ベルに対して、 /etc/rcrunlevel. d というディレクトリを用意し、 こから /etc/init. d ディ レクトリ内のネノ期化スクリプトにシンポリック・リンクを 作成しています。このシンポリック・リンクにより、実 行する初期化スクリプトや、その実行順序を決定していま す。ここで、 runlevel は現在の実行レベル ( 0 ~ 6 ) 、また はシステムの起重丿時を表す S のいすれかです。 シンポリック・リンクの名前は、 S れれスクリプト名 もしくは、 K れれスクリプト名 という形式になります。れれは、初期化スクリプトの実行 順を表す 2 桁の数字です。、、スクリプト名 " は初期化スク リプト名で、通常はリンク先のファイル名 (/etc/init. d ディレクトリ内の初期化スクリプトのファイル名 ) です。 init デーモンは、夫行レベルが襯 e 眦 I に変化したと きに、ます /etc/rcrunlevel.d ディレクトリ内のネ月化ス クリプトのうち、、、 K " て始まるもの ( サービスの停止ス クリプト ) をれれの小さい順 ( れれか 1 司番の場合はアルファ べッい印に実行します。このとき、ネ加月化スクリプトに stop" という引数を与えて実行します。正確には、 init デーモンか初期化スクリプトを直接実行するのではなく、 init デーモンから起動される / etc / ⅲ it. d / rc スクリプト 2 ただし、 init デーモンから実行されるスクリプト名 (/etc/init. d/rc など ) は一緇 ; 異なります。 UNIX MAGAZINE 1999.10

3. UNIX MAGAZINE 1999年10月号

連載 / Linux でリラックスー /etc/rcrunlevel. d ディレクトリから、、スクリプト名 " て指定した初期化スクリプトへのシンポリック・リンク をすべて削除します。 update-rc. d コマンドは、 /etc/ init. d ディレクトリに、、スクリプト名 " の琪月化スクリ プトが残っている場合は、シンポリック・リンクを削 除しません。強制的にシンポリック・リンクを削除する 場合には、 update-rc. d コマンドに一 f オプションを指 定します。 たとえば、 /etc/init. d/exim へのシンポリック・リン クを削除するには以下のようにします。 # update—rc . d —f eX1m remove update—rc. d: /etc/init . d/exim exists during rc . d purge (continuing) Removing any system startup links for /etc/rc6. d/K20exim /etc/rc5. d/S20exim /etc/rc4. d/S20exim /etc/rc3. d/S20exim /etc/rc2. d/S20exim /etc/rcl . d/K20exim /etc/rcO . d/K20exim /etc/init . d/exim す。これにより、 exim パッケージをシステムから削除 update-rc. d コマンドに一 f オフションを指定していま /etc/init. d/exim スクリプトが存在しているため、 /etc/inittab ファイ ) レ ンクを標準出力に表示します。 ンクの削除はおこなわす、削除されるシンポリック・リ なお、 -n オプションを指定すると、シンポリック・リ きます。 することなしに、 exim デーモンか起動しないように UNIX MAGAZINE 1999.10 デーモンの起重加に、 /etc/init. d/rcS というプログラ また、 Debian GNU/Linux の起重加 ( 正確には init 行レベルは 2 であることが分かります。 5 行目から、 Debian GNU/Linux のデフォルトの実 います ) 。 の内容を図 2 に示します ( 説明のために行番号をイ寸加して のノヾージョン 2.76-3 に含まれる ) /etc/inittab ファイル Linux 2.1 に含まれる ( 正確には、 sysvinit パッケージ うな順番で実行されるかを説明します。 Debian GNU/ イルをとりあげ、どのような初期化スクリプトが、どのよ 以下では、 Debian GNU/Linux の /etc/inittab ファ ム ( シェル・スクリプト ) か実行されることカ吩かります ( 9 行目 ) 。工ントリの不頁が、、 sys ⅲ it " であるため、この スクリプトはシステムの起重加寺に 1 度だけ実行されます。 init デーモンは、このスクリプトカ鮗了するまで他の処理 をおこないません。 こで、 /etc/init. d/rcS スクリプトの中身も見てみま しよう ( 図 3 ) 。 /etc/init. d/rcS スクリプトは環境変数 などの設定をおこなったあと、図 3 の 26 行目で /etc/ default/rcS ファイルを言売み込んでいます。このファイル では、初期化スクリプトのためのデフォルト値がいくつか 設定されています。たとえば、 CMOS クロックが GMT ( グリニッジ標 ~ おを示しているかどうかなどの設定も こにあります。そのあと、 /etc/rcS. d ディレクトリ内 に存在するスクリプトのうち、ファイル名が S て始まる ものを順番に実行します ( 37 ~ 56 行目 ) 。さらに、 /etc/ rc. boot ディレクトリ内のすべての砌化スクリプトを順 番に実行します ( 61 行目 ) 。 さて、 /etc/inittab ファイルに戻りましよう。 /etc/ init. d/rcS スクリプトの実行カ鮗ったあと、現在の実行レ ベルを引数として、 /etc/init. d/rc スクリプトを実行して います ( 図 2 の 22 ~ 28 行目 ) 。工ントリの不頁が、、 wait であるため、ⅲ it デーモンはこのスクリプトカ冬了するま ・で他の処理をおこないません。 こで、 /etc/init. d/rc スクリプトの中身も覗いてみ ましよう ( 図 4 ) 。ます、現在の実行レベルと直前の実行 レベルを調べています ( 図 4 の 43 ~ 47 行目 ) 。そのあ と、直前の実行レベルが、、 N " でなければ、、、 K " で始まる すべての初期化スクリプトを順番に実行します ( 57 ~ 64 行目 ) 。シェルのワイルドカードを使用しているため、前 述の 2 桁の数字 ( れれ ) の小さいスクリプトから順番に実行 S て始まるすべての開始スクリプ されます。さらに、 こでは、直前の トを順番に実行します ( 67 ~ 95 行目 ) 。 実行レベルが、、 N " ではなく、なおかっ直前の実行レベル で同じ初期化スクリプトかま行されていれば、ふたたひ初 期化スクリプトを実行しない点に注意してください ( 71 ~ 86 行目 ) 。 以 - ヒのように初期化スクリプトの実行か完了したあと、 init デーモンは getty プロセスを起動します ( 図 2 の 50 ~ 55 行目 ) 。この点で、ようやくューザーのシステムへ のログインが可能になります。 107

4. UNIX MAGAZINE 1999年10月号

連載 / Linux でリラックスー 図 4 Debian GNU/Linux の /etc/init. d/rc スクリプト # Now find out what the current and what the previous run1eve1 are . ←現在の実行レベル runIeve1=$RUNLEVEL # Get first argument . Set new runlevel tO this argument . ] & & runlevel=$l ←引数があれは、これをもとに実行レベルを決定 ←直則の実行レベノレ previous=$PREVLEVEL export runlevel previous # ls there an rc directory for this new runlevel? if [ -d /etc/rc$runlevel. d ] ← /etc/rcrunlevel.d ディレクトリが存在するか ? then # First, run the KILL scripts ・ ←直前の実行レベルが N でなけれは・・・ if [ $previous ! = N ] then for i in /etc/rc$runlevel . d / K [ 0 ー 9 ] [ 0 ー 9 ] * ↑停止スクリプトを順番に実行 do # Check if the script is there . [ ! —f $i ] & & continue ↑リンク先が存在するかどうかをチェック # Stop the service . startup $i stop ←初期化スクリプトの引数に st 。 p を指定 done # Now run the START scripts for this runlevel . for i in /etc/rc$runlevel . d/S* ↑開始スクリプトを順番に実行 do [ ! —f $i ] & & continue ↑リンク先が存在するかどうかをチェック if [ $previous ! = N ] then 1 っ 3 -4 5 一ト一 0 1 っつけ一 4 一り一 8 9 0 一 1 っつけ 4 一り冖ー 8 0 ー 1 っ 1 一ト り【ー一 8 一一 0 11 っ 1 っ -4 一り ( ー 4 -4 4 -4 4 4 -4 一 4 4 5 - り 5 - り”り 5 一り 1 り 5 6 6 6 ー「ー冖ー suffix=$i#/etc/rc$runlevel . d/S [ 0 ー 9 ] [ 0 ー 9 ] stop=/etc/rc$runlevel. d/K [ 0 ー 9 ] [ 0 ー 9 ] $suffix previous-start=/etc/rc$previous . d/S [ 0 ー 9 ] [ 0 ー 9 ] $suffix [ —f $previous—start ] & & [ ! —f $stop ] & & continue ↑直前の実行レベルでサービスが開始されていればスキップする in 0 ) ←実行レベルが 0 または 6 なら、 startup $i stop 引数に st 叩を指定 startup $i start ←実行レベルがそれ以外なら、 引数に start を指定 # eof /etc/init . d/rc ノヾッケージの制罹卩ファイノレの Description フィールド ( 7 次々とインストールすることも容易です。 月号参照 ) にパッケージの簡単な説明か書かれており、 しかし、、、パッケージをインストールしてみたものの、 れを見川ま、それぞれのパッケージの概要を知ることがで どのようにして使えばいいのか分からない " という場合も きます。 dselect コマンドを使用すれは、パッケージの説 あるでしよう。 Debian のポリシー・マニュアルでは、パ 明にざっと目をとおして、おもしろそうなパッケージを ッケージのドキュメントに関しても日寉なルールを定めて 110 UNIX MAGAZINE 1999.10

5. UNIX MAGAZINE 1999年10月号

図 4 通常の一里 図 5 プログラミング・テクニック クライアント 逆向きの一里 socket() PASV 要求 クライアント socket() bind() listen() acce pt() 要求 socket() connect() initconn() socket() bind() listen() PASV 応答 要求 connect() 接続の確立 す。このときクライアントが dataconn 関数で accept を 実行することにより、接続か確立されます ( 図 4 ) 。 逆向き ( 制御用の接続と同じ向き ) に接続を張る場合に は、もうすこし工夫が必要です。さきはどの図で、たんに クライアントとサーバーの彳難リを逆にすることはできませ ん。サーバー側で bind や listen をいつ実行すればよいか カ吩からないからです。要求がきてから準備するガ去も考 えられますが、その場合、クライアント側は要求を出した あとしばらく待ってから connect を実行する必喫があり ます。、、しばらく " とはどの程度でしようか。これはマシ ンの能などに左右されるので、このガ去ではうまくいか ない場合があります。 実際の FTP では、逆向きの接続をサポートするために 新たな要求か加えられています。これを用いた処理の様子 を図 5 に示します。クライアントは、 initconn 関数のな かで socket によりソケットを作成したあと、 PASV 要求 をサーバーに送ります。 PASV 要求を受けたサーバーは、 socket 、 bind 、 listen を実行して接続を受け入れる準備 をします。そのあとで PASV 要求に対する応答を返しま す。応答を受け取ったクライアントは connect を実行し て実際に接続を試みます。 則回、 connect システムコーノレはサーノヾーカゞ accept シ ステムコールを実行するまでプロックすると書きました。 正確には、 listen システムコールを実行していれば con- nect システムコールはプロックしません。ごめんなさい。 ということで、クライアントが connect システムコー ルを実行しても、処理は続けられます。ここでサーバーに 対して実際のファイルの要求を出します。するとサー 側では、 select システムコールて接続要求を尉見しながら UNIX MAGAZINE 1999 ユ 0 接続の確立 dataconn() select() accept() accept システムコールを実行します。これで無事接続が 確立することになります。クライアント側の datac 。Ⅱ n 関 数ではすることがなくなってしまい、 initconn 関数で作 成したソケットを返すだけになります。 レジューム機能 最近の FTP て粳利だなと思うのは、レジューム機能 です。ネットワークの或は以前にくらべれは齧瞿的に太 くなっていますが、転送されるデータ量やネットワーク の利用者数も増えています。場合によっては、目的のファ イルの転送がうまくいかないこともあります。このような とき、途中まで取得したデータを捨てて、最初からやりな おすのはもったいない話です。そこで、すでに取得したも のを活かしながら本を得ようというのがレジューム機能 です。 この機能を寒見しているプログラムをみる前に、プロト コルとしてどのような仕組みが用意されているのカ召介し ておきましよう。しつは、これはごく簡単な仕組みです。 最初にどこから先か欲しいのかをサーバーに伝えてからフ ァイルの中幻医を開始します。すると、サーバーは指定され た場戸励、らの残りをクライアントに転送します。クライア ントでは、以偂弭え得したファイルと今回渡されたデータを 連結してファイル本を構成します。 レジューム機能を利用するには、サーバーとクライアン トがともにレジューム機能に対応していなけれは・なりませ 129

6. UNIX MAGAZINE 1999年10月号

連載 / 遠隔オフィスとの接続ー return ERROR; / * コマンドを実行する * / int exec—command() FILE *fp; int C , i ; C ommand , / * 実行結果を tmp パッフアに読み込む * / system(tmp) ; / * コマンドの実行 * / sprintf (tmp, "%s >%s 2 & > 1 " / * 実行するコマンド文字列を作る * / tmpf) ; if ( (fp=fopen(tmpf , "r")) = = NULL) { *tmp } else { for (i = 0 ; (c=getc(fp)) ! = EOF & & i く BUFSIZE; tmp[i] unlink (tmpf) ; void message(char *msg) printf ( "Content—type : text/html\n\n" ) ; printf(" く html> く head><tit1e>Run Command Message く /title> く /head>\n") ; 66 message(tmp) ; exec—command() ; } else { message("Permission denied く p>\n") ; } else if (setuid-process() = = ERROR) { message("lnvalid input\n") ; = ERROR) { if (parse() init() ; char *argv ロ ; int argc ; main(argc , argv) printf ( " く body> く pre>%s く /pre> く /body> く /html>\n" ,msg) ; UNIX MAGAZINE 1999.10

7. UNIX MAGAZINE 1999年10月号

連載 / Linux でリラックスー 図 1 /etc/rcO. d ディレクトリ内のキ琪手化スクリプト列 K11cron K12kerne1d K20exim K20gpm K20samba K20skkserv K25nfs—server K30netstd_misc K50net at alk K89atd K90sysk10gd S20sendsigs S25h clock . sh S30urandom ・ restart S40umountfs S90ha1t K15netstd-init K2010goutd K18netbase K20autofs K201pd K20ppp によって実行されます。なお、直前の実行レベルが、、 N " の場合は、これらの、、 K " から始まる初期化スクリプトは 実行されません。 次に、 init デーモンは /etc/rcrunlevel.d ディレクト リの初期化スクリプトのうち、 S て始まるもの ( サービ スの開始スクリプト ) を同しく数字十アルファベット順に 実行します。このとき、ネ川月化スクリプトに、、 start" とい う引数を与えます。ただし、実行レベルが 0 または 6 の ときは、初期化スクリプト名が S から始まっていても 、 stop" という引数をケえて実行します。 たとえば、 /etc/rcO. d ディレクトリに図 1 のような初 期化スクリプト ( 実体はシンポリック・リンク ) があったと します。この場合、実行レベルが 0 に変化したときには、 サービスをいったん中止し、その後あらためてサービス を開始する。 ・ reload サービスを中断することなく を再度読み込む。 ・ force— 、サービスの成疋ファイノレ → → → → → → → K11cro 取 stop K12kerne1d stop K89atd stop K90sysk10gd stop S20sendsigs stop S25hwc10ck. sh stop S40umountfs stop S90haIt stop 可能ならば、サービスを中断することなく、サーピスの 故疋ファイルを再度読み込む。これができない場合は、 サーピスをいったん中止し、その後あらためてサービス を開始する。 Debian GNU/Linux では、デーモンとして重川乍する ようなサーピスに対してはかならす初期化スクリプトが用 意されています。また、ほとんどの匆月化スクリプトでは、 start 、 stop 、 restart 、 force-reload といった引数を使 用することができます。 このため、サービスの起動や終了などは、サービスの種 類によらすすべて統一されたガ去でおこなうことができま す。たとえば、 exim ( メール中幻医工ージェント ) デーモン を終了したいとしましよう。多くの UNIX オペレーティ ング・システムでは、 # ps ax ー grep exim の順でネノ琪月化スクリプトか実行されることになります。実 行レベルが 0 なので、 S から始まる初期化スクリプト であっても、、 stop" という引数が与えられることに注意し てください。 初期化スクリプトの本髄 このように、初期化スクリプトには、、 start" や、、 stop などの引数が与・えられて実行されます。 Debian GNU/ Linux では、初期化スクリプトの引数として、以下のよう UNIX MAGAZINE 1999.10 ・ stop ・ start サービスを中止する。 サービスを開始する。 な値か定義されています。 582 aO S 169 ? S 502 al S # k 土 11 169 0 : 00 grep exim 0 : 00 /usr/sbin/exim —bd —q30m 0 : 00 vi /etc/init . d/exim のように いったん exim デーモンのプロセス番号を調 ペそのあとにシグナルを送ってプロセスを終了させる必 要があります。一方、 Debian GNU/Linux では、 exim デーモン用に初期化スクリプトか用意されているため、 # /etc/init . d/exim stop のようにしてデーモンを終了させることかて、きます。もち ろん、 exim デーモンをふたたひ開始するには、 # /etc/init . d/exim start 105

8. UNIX MAGAZINE 1999年10月号

連載 / 遠隔オフィスとの接続ー parse() の最後の、 if (*user ! = *command ! = return OK; } else { return ERROR; 図 4 CGI の実行結果 河井集表示 ( ) ジャンプ喞 Oøm 取 0 ヘルプ ( 印 : Run 00 宿衂聞 d M 鱸 3 e - 権 0 夘を & & *pass イの 再読み込み耒ーム検幸 ガイド 場所 : い / 帚 0 ゴト bin/AP runcgi 印 セキュリティ ' 関連サイト では、 Web プラウザからすべての情報か渡されているか どうかを石薩忍し、不足があれば工ラーにします。この処理 は、 JavaScript などを使って Web プラウザ側でおこな うようにすることもできます。 setuid-process() 関数は、この CGI のなかでもっと も重要な部分です。ここでは、 UNIX のアカウント情報 とユーサーが入力した情報をもとに認証をおこない、成功 したらプロセスの実イ限を変更します。 UNIX MAGAZINE 1999.10 定します。たとえは、ユーザーカ甘旨定したコマンドが、 ます、 tmp 変数には実行するコマンド列をそのまま設 system(tmp) ; command , tmpf) ; sprintf (tmp, "%s >%s 2 & > 1 " command() 関数はかなり簡略化しています。 Web プラウサから渡されたコマンドを実行する exec- でプロセスの権限を変更しています。 setuid(pw—>pw—uid) ューザー名とパスワードの組合で認証か成功したら、 OK & & pw¯>pw—passwd) if (strcmp (crypt (pass ,pw—>pw-passwd) , スワードであるかどうかを判定しています。 があります。以下のコードでは、これを利用して正しいパ て暗号化すると、もとの暗号化されたものと一致する性質 暗号化されたものをもう一度クリアテキストのパスワード います。 UNIX で使われているパスワードは、 crypt() で に登録されている暗号化されたパスワード文字列が入って ます。 pw->pw-passwd には、 /etc/passwd ファイル て、入力されたパスワードと一致しているかどうかを卩串ヾ 次に、エントリからパスワードのフィールドを抜き出し pw = getpwnam (user) ; ポインタである pw 変数に設定しています。 たユーサー名のエントリを探し出し、 passwd 構造体への 以下のコードは、 /etc/passwd ファイルから指定され ・カクーク Is /etc LGTOuscsi TI MEZONE を 00 を 引こ色 &pache apache. Old asppp . cf au [ 0 ー hO を をしを 0- 用を ster autopush 0 を t を b 尾 5 chroot 0 「 0 n cron. d 035. conf だったとすると、 tmp 変数には次のようなコマンドが設 定されます。 ls /etc >/usr/tmp/runPT 、 ocessID 2 & > 1 C のプログラムからコマンドを実行するガ去には何通り かありますが、 こでは system() 関数を使っています。 system() は、シェルを起動して引数で受け取った文字列 をそのまま実行します。このプログラムでは、ユーザーが 指定したコマンドを実行し、標準出力と標準ェラー出力に 出力されるメッセージを /usr/tmp/runProcessID に保 存しています。 最後の処理は、出力したメッセージを読み込んで web プラウサに返すことです。ここでは message() 関数を流 用するためにすこし手抜きをしていて、 tmp 変数に保存で きる長さ ( 1 , 024 バイト ) だけメッセージを読み込み、そ れを送り返しています。したがって、返された結果の最後 の 1 文字だけか文字化けすることがあります。これは、 2 バイト文字 ( 全角のかなや漢字など ) の前半の 1 バイトだ けが送られたからだと捉えてください。 図 4 の画面は、 Web プラウザから正しいユーサー情 報とパスワードを入力し、 "ls /etc" コマンドを実行させ たときの結果です。そっけない表示ではありますが、 /etc ディレクトリのファイルの一覧が表示されています。 ☆ 今回は、ユーザー認証や権限設定時の安全性に重点をお いて、 CGI を作る際の注意点を説明しました。 CGI を安 全なものにするには、プログラムの安全性を考えるだけで はなく、システム本でセキュリティ・ホールを作らない ように注意することも必要です。 63

9. UNIX MAGAZINE 1999年10月号

連載 / 遠隔オフィスとの接続ー 図 3 フォームにユーサー名やパスワードを入力 フを新第第町を : 0 明純イ 0 ーへせ はう第、 3 み ~ を一 ~ はは 当ノトンブド ! 0 / 宿、ッ′を ! 0 : っ 11 ・冢・行′を ユーサー名 : パスワード : 実行するコマント : C で作った CGI プログラム ・「エ関直りイト それでは、任意の UNIX のコマンドを実行する CGI プログラムの C 言語版を紹介しましよう。末尾のリスト 2 にこのプログラム run. c を示しました。 run. c は、ユー サー認証をおこない、指定されたユーサーの権限て指定さ れたコマンドを実行します。 なお、このプログラムは、理解しやすさを第一に考え てエラー処理や入力値の判定をはとんどおこなっていませ ん。実用化するには、もうすこし書き足す必喫があるでし よう。また、デバイスを制御する一にのコマンドや、イン タラクテイプなコマンドに対応する仕組みもありません。 このようなコマンドを使いたいのであれは、仕組みそのも のを根底から変更する必があります。 さっそく、ソースコードを見てみましよう。 ストの最後の main() 関数を見てください。 main(argc , argv) int argc ; char *argv ロ ; init ( ) ; if (parse ( ) = = ERROR) { message("lnvalid input\n") ; } else if (setuid-process() = = ERROR) message("Permission denied く p>\n") ; } else { exec—command() ; message(tmp) ; まず、リ こでは、実際に処理をおこなっている関数を呼び出 し、エラーメッセージや処理結果を message() 関数を使 って表示します。全体の流れは次のようになっています。 62 1. init() 関数で初期化 2. parse() 関数で Web プラウサから受け取ったデータを 角財斤し、変数に保存 UNIX MAGAZINE 1999.10 ます。 ている decode() 関数は、変換された文字をもとに戻し という処理をおこないます。 parse() 関数から呼び出され ( は 16 進 ・そのはかの使用できない文字は、、 % " の形式に変換 ・空白文字は、、十 " に変換 に使えない文字列について、 pass 、 command に保存します。 Web プラウサは URL ウザからのデータを読み込み、内容を角斤して変数 user 、 parse() 関数は、標準入力へ送られてきた Web プラ 使われます。 ァイルは、コマンドの実行結果を一印判勺に保存するために というファイルのパス名を保存している変数てす。このフ /usr/tmp/runProcessID 最後の tmpf は、 ・ tmpf ・ command ・ pass ・ user 数をネ川月化しています。 init() 関数では、プログラム中て利用する次の 4 つの変 Web プラウサ ( 標準出力 ) に出力するだけの関数です。 これは、引数で渡された文字列を HTML の形式にし、 く /html>\n" ,msg) ; printf ( " く body> く pre>%s く /pre> く /body> Message く /title> く /head>\n") ; printf (" く html> く head> く tit1e>Run Command printf ( "Content—type : text/html\n\n" ) ; void message(char *msg) 面の都合上、で折り返しています。以羽司様 ) message() 関数の部分は以下のようになっています ( 誌 5. 実行結果を Web プラウザに返送 4. コマンドを実行 ロセスの権限を変更 3. setuid-process() 関数でユーザー認証をおこない、プ

10. UNIX MAGAZINE 1999年10月号

連載 / 遠隔オフィスとの接続ー ーム ・ファイルの所有者を root に変更したときに、 set user- bit をクリアする。 また、ネットワーク上の言算機どうしのアクセス権を設 定する、 ・ hosts. equiv ファイノレ ・ . rhosts ファイ / レ などにも注意してください。 NFS で公開しているファイ ルの権限も適切に管理する必要があります。 システムに負荷を加える攻撃 Web サーバーや FTP サーバーに対して、ま可間に何 度もアクセスをしたり、巨大なファイルを繰り返しダウン ロードするような攻撃もあります。 その結果、回線の容量カ坏要なアクセスでパンクした り、過負荷のためにユーザーに対するサービスカ歸ったり します。 このような攻撃の景些を軽減する手段として、 攻撃をしかけてくるシステムよりも能力か高いシステム を用意する ・攻撃をしかけてくるシステムからのアクセスをネットワ ークの入口 ( ルータなど ) で拒否する などのガ去があります。 しかし、前者はシステムの導入のためにコストと時間が かかるので、あまり現実的とはいえません。 後者は迷惑なアクセスから身を守るための孝第斗書的な対 去ですが、攻撃者がいくつものシステムを使い分けてい たり、複数の攻撃者がいる場合には、つねに不正アクセス を見張ってルータなどの設定を変更する必要があるのでイ タチごっこになってしまうかもしれません。 いずれにしても、このような攻撃に対しては根本的な回 避策がないのか伏です。 UNIX コマンド実行用の CGI 前回は、遠隔オフィスから Web インターフェイスを使 い、本社のホストの任意のコマンドを実行する CGI を紹 介しました。 UNIX MAGAZINE 1999.10 リスト 1 UNIX のコマンド列を実行するフォ く html> く head> く tit1e>Run Command く /title> く /head> く body> く form method="POST" action= ューサー名 : く br> く blockquote> く input type="text" name= く /blockquote> / くスワード . く br> く blockquote> "/cgi-bin/run ・ cgi"> く br> く input type= password" name= password"> く br> く /blockquote> 実行するコマンド : く br> く blockquote> く input type="text" name=ttcommand"> く /blockquote> く input type=" submit " value=" 送信 " > く input type="reset" value=" クリア” > く /form> く /body> く /html> この CGI は、 Web サーバーの権限で実行されます。で すから、各ューザーの権限でコマンドを実行するには、所 有者が root の setuid プログラムとして重川させ、コマ ンドを指定されたユーサーの権限に変更する必要がありま した。ところが、紹介した CGI はシェル・スクリプトで 入力フォーム た CGI プログラムを紹介します。 そこで、今回はコンパイル言語である C 言語で作成し を奪わ書き換えられる危険があります。 作られていたので、前述のようにスーパーユーサーの権限 図 3 は、このフォームにユーザー名やパスワードを入 ん。 としていること以外は、とくに注意すべき点はありませ ・フォームのデータの受け渡し方式に POST を使う ・パスワードの入力には input タグの password 属性を づき、 サから呼び出すためのフォームです。前述の注意点にもと リスト 1 は、 UNIX の任意のコマンドを Web プラウ 力した状態です。 61