<!-- -*- mode:text coding:euc-jp -*-
   $FML: restriction.sgml,v 1.12 2010/03/18 20:28:05 fukachan Exp $
-->


<chapter id="restriction">
	<title>
	入力データの検査
	</title>

<para>
当然、
入力データ(特にコマンドなど)に対する正当性の検査( input validation )
が行なわれています。
</para>

<para>
全プログラムで統一された検査を行なうため、
FML::Restriction
クラスに基づいて検査が行なわれます。
</para>


<sect1 id="restriction.overview">
	<title>
	入力データ検査についての概要
	</title>

<sect2>
	<title>
	投稿メールに対して
	</title>

<para>
そもそも、
記事に対する入力制限(入力データの表現範囲の制限)は考えにくい概念です。
実際
FML::Restriction
クラスによる入力データチェックは行なわれていません。
</para>

<caution>
<para>
(SPAM であろうと思われる)一行メールなどをはじくために 
FML::Filter
クラスによるフィルタチェックが行なわれ得ます。
</para>

<para>
ただし、これは記事の内容に対するチェックではないので、
FML::Restriction
の対象としている操作とは意味合いが異なります。
</para>
</caution>

</sect2>


<sect2>
	<title>
	コマンドメールに対して
	</title>

<para>
コマンドメールは
FML::Process::Command
の中で一行ずつ
FML::Restriction::Command
で定義されている正規表現にしたがって入力されたコマンド列が検査されます。
検査に合格すれば、
FML::Command::{User,Admin}::コマンドの実行に進むことができます。
</para>

</sect2>


<sect2>
	<title>
	CGI に対して
	</title>

<para>
CGI の各プログラムでは、
safe_param_XXX() という関数経由でのみ
HTTP セッションからのデータを受けとることができます。
</para>

<para>
safe_param_*()
および
try_cgi_*() 
は安全な値を返すことになっています。
</para>

<para>
これらの safe_param_XXX() は
FML::Restriction::CGI (FML::Restriction::Base を継承している)
経由でパターンの検査をし、
検査に合格した場合にのみ値が返されています。
</para>

</sect2>


<sect2>
	<title>
	makefml および fml
	</title>

<para>
コマンドラインで実行する(シェルの上での操作が可能である)ので
「入力チェックをしない」
のがデフォルトです。
サーバのシェルが取れる時点で、正規のユーザであると認証されているはずです。
「正しいユーザ/そのユーザのすることはすべて正しい」と信じています。
</para>

<para>
もちろん、各モジュールごとの制限は受けます。
たとえば、adduser でアドレスを追加しようとしても、
正しいアドレスに見えないような文字列を入れれば拒否されます。
このあたりの制限は各モジュール依存です。
</para>

</sect2>

</sect1>


<sect1 id="restriction.class">
	<title>
	FML::Restriction クラス
	</title>

<para>
入力データや、
コマンドの ACL は
FML::Restriction
クラス以下にモジュールを配置することにしています。
</para>

<para>
たとえば、
CGI では
FML::Restriction::CGI
クラスのモジュールを用いて
入力データがある正規表現の中に収まるかどうか？の検査をしています。
</para>

<para>
FML::Restriction 以下では Base を継承していますが、
他のモジュールでは、
FML::Restriction クラスを object composition して使って下さい。
たとえば、
<screen>
use FML::Restriction::CGI;
$safe = new FML::Restriction::CGI;
my $allowed_regexp = $safe->param_regexp();

if ($value =~ /^$allowed_regexp{$key}$) { ... ok, do something ... ;}
</screen>
のように使います。
</para>

</sect1>


<sect1 id="restrictioncgi.input.data">
	<title>
	CGI における入力データの制限
	</title>

<para>
CGI では
FML::Restriction::CGI クラスのモジュールを用いて、
入力データがある正規表現の中に収まるかどうか？の検査をします。
</para>

<para>
入力値は、前述のクラスの入力制限をうけるべきです。
そのため、直接 param() を使ってはいけません。
必ず safe_param_xxx() メソッドを通じて、
param() ( CGI モジュール )からのデータ入力をして下さい。
</para>

<para>
なお、入力されたキーワード一覧を調べるために、
<screen>
for my $dirty_buf (param()) {
   ... check ...
}
</screen>
のような構文を許す必要があるでしょうが、
<screen>
param($dirtty_buf)
</screen>
などとはしてはいけません。必ず
<screen>
for my $key (param()) {
   ... check ...

   if (key eq $key) {
       value = safe_param_key()
   }
}
</screen>
のように書いて下さい。
</para>

</sect1>


<sect1>
	<title>
	議論: FML::Restriction の制限はきびし過ぎるか？
	</title>

<para>
FML::Restriction のクラスでは 
RFC などで許されている表現のごく一部だけを許しています。
</para>

<para>
そもそも RFC の定義が広すぎるので、
手抜きといえば手抜きになりますが、
コードは安全側にたおしています。
</para>

<para>
ただし
FML::Restriction::Command
によるコマンドのシンタックスチェックは、
もう少し粒度を上げるべきなのかもしれません
(現状、未実装です)。
</para>

</sect1>


</chapter>
