Trusted Solaris 7 では、通常の UNIX ディレクトリとマルチレベルディレクトリ (MLD) が使用できます。MLD を使用すると、1 つのプログラムが複数の異なる機密ラベルで動作する場合でも、1 つのディレクトリを共通して使用でき、そのディレクトリ中にあるファイルの中でも現在のプログラムの機密ラベルと同等のものだけにアクセスすることができます。MLD にはシングルレベルディレクトリ (SLD) だけが含まれ、各 SLD はその SLD の機密ラベルでファイルを格納します。1 つの MLD 内では、同じ名前の複数のファイルを別々の SLD に格納できます。同じファイルのそれぞれのインスタンスは、格納先の SLD の機密ラベルに適したデータを含みます。これを、「ディレクトリとファイルの多重インスタンス化」と言います。
tmp ディレクトリとすべてのホームディレクトリは、システム管理者がユーザーマネージャでユーザー設定を行う際に、自動的に ADMIN_LOW の MLD になります。また、mkdir(1) にも MLD を作成するオプションがあります。図 8-1 は Zelda のホームディレクトリのディレクトリ構造を示しています。この図の MLD は ADMIN_LOW であり、機密ラベル Top Secret、Secret、Confidential の 3 つの SLD が入っています。
MLD は、別の MLD を含むことはできません。
SLD は、MLD も SLD も含むことができません。
SLD は、通常の UNIX ディレクトリおよびあらゆる種類のファイルを含むことができます。
SLD は、必要に応じ、パス名ルックアップ時に、getsldname(2) と fgetsldname(2) システムコールを使用して作成されます。SLD の機密ラベルは、システムにとって常に有効な機密ラベルです。
Secret で動作しているアプリケーションは、ADMIN_LOW のディレクトリパス /export/home/.MLD.zelda よりも優位で、Secret と Confidential の SLD よりも優位です。しかし、Top Secret の SLD よりは優位でありません。特権がなく任意アクセスがある場合、Secret で動作しているプロセスには次のアクセスがあります。
Secret SLD に対する読み取り、書き込み、および作成のアクセス
完全な装飾名 /export/home/.MLD.zelda/.SLD.1 を使用して、Confidential の SLD に下位読み取りを行う権限。「装飾名」 と 「装飾パス名の使用」 を参照してください。
完全な装飾名 /export/home/.MLD.zelda/.SLD.3 を使用して、Top Secret の SLD に上位書き込みを行う権限 (プロセス認可上限が Top Secret の SLD よりも優位な場合)。「装飾名」 と 「装飾パス名の使用」 を参照してください。
図 8-1 のディレクトリ構造において Confidential で動作しているプロセスは、次のファイルにアクセスできます。
.login
conf_proj
図 8-1 のディレクトリ構造において Secret で動作しているプロセスは、次のファイルにアクセスできます。
.login
secret_proj1
secret_proj2
図 8-1 のディレクトリ構造において Top Secret で動作しているプロセスは、次のファイルにアクセスできます。
.login
ts_proj
多くのアプリケーションは、/tmp ディレクトリにファイルを作成します。/tmp が機密ラベルを持つ通常の UNIX ディレクトリである場合、ほかの機密ラベルで動作している特権のないプロセスは /tmp にファイルを作成できません。Trusted Solaris 7 は、プロセスの機密ラベルに対応した SLD にアプリケーションがファイルを作成できるように、/tmp を MLD に設定します。
MLD とシンボリックリンクは、組み合わせて使用できます。たとえば、リンク先パス名が MLD に存在するシンボリックリンクのリンク先ファイルは、機密ラベルごとに異なります。SLD 内のシンボリックリンクは、通常のディレクトリ内のパス名を指すことができます。その場合は、異なる機密レベルで参照されるときでも MLD 内のパス名からその同じファイルを参照できるようになります。
プロセスがパス名の中で MLD を参照する場合、システムは、そのプロセスの機密ラベルに対応する SLD を含むように参照を透過的に拡張します。この操作を、「パス名変換」と言います。たとえば、Confidential で動作しているプロセスが /export/home/zelda を参照する場合、このプロセスは /export/home/zelda の Confidential の SLD にアクセスします。パス名変換は透過的であるため、プロセスはこの SLD を明示的に参照しません。
すべての MLD には、装飾があります。装飾は、システム管理者によって変更されないかぎり、.MLD. です。装飾を使用すると、プロセスは、プロセスと同じ機密ラベルの SLD を透過的に参照するのではなく、MLD を直接参照できます。プロセスは、次の処理を実行する場合、ls(1) コマンドを使用して装飾名を参照します。
MLD 内の SLD を表示する。装飾名を指定しないと、代わりにプロセスと同じ機密ラベルの SLD の内容が表示されます。
%ls /.MLD.tmp
MLD の装飾名を使用して、SLD を明示的に参照する
%ls /.MLD.tmp/.SLD.3
MLD または SLD の情報を取得したり、完全な装飾パス名を使用して SLD 内のオブジェクトにアクセスするには、必須アクセスと任意アクセスが必要です。
第 1 章「API とセキュリティポリシーの紹介」に示されている必須アクセスと任意アクセスの規則から言えば、SLD は、目的のファイルシステムオブジェクトが含まれるパス名の中の 1 要素と言えます。呼び出し元プロセスは、SLD に対する必須検索アクセスと任意検索アクセス、および目的のオブジェクトに対する適切なアクセスを必要とします。アクセスが拒否される場合は、特権が必要になる場合があります。
MLD 内の、指定された機密ラベルの SLD 名を取得する場合、呼び出し元プロセスは次の特権を必要とします。
呼び出し元プロセスの機密ラベルが SLD の機密レベルより完全に劣位な場合、呼び出し元プロセスは、有効セットに file_upgrade_sl 特権を必要とします。
SLD の機密ラベルがプロセスの機密ラベルより優位な場合、呼び出し元プロセスは、有効セットに file_downgrade_sl 特権を必要とします。
この章で説明しているプログラミングインタフェースを使用するには、次のヘッダーファイルが必要です。
#include <tsol/mld.h>
この章の例は、次のライブラリを使用してコンパイルしています。
-ltsol
bslabel_t 型の定義は、バイナリ CMW ラベルの機密ラベル部を示します。getsldname(2) システムコールは、bslabel_t 型の変数を受け取ります。
stat 構造体は、指定された MLD、SLD、シンボリックリンクのいずれかの情報を含みます。この構造体は、mldstat(2) と mldlstat(2) システムコールによって返されます。
型 |
フィールド |
内容 |
デフォルト |
mode_t |
st_mode |
ファイル形式とアクセス権 |
0 |
nlink_t |
st_nlink |
ハードリンクの数 |
1 |
uid_t |
st_uid |
所有者のユーザー ID |
0 |
gid_t |
st_gid |
所有者のグループ ID |
0 |
time_t |
st_atime |
示す最後のアクセス時間 (秒単位) |
現在の時間 |
time_t |
st_mtime |
示す最後の変更時間 (秒単位) |
現在の時間 |
time_t |
st_ctime |
示す最後の i ノード変更時間 (秒単位) |
現在の時間 |
次に、MLD と SLD の情報を取得するプログラミングインタフェースを示します。
システムコールを使用して、SLD 名、MLD 装飾、SLD または MLD のファイル属性情報などを取得できます。
getsldname(2) システムコールは、 path_name (パス名) に対する SLD 名を、指定された slabel (機密ラベル) で取得します。詳細は、getsldname(2) のマニュアルページを参照してください。fgetsldname(2) システムコールは、ファイル記述子を使用します。
int getsldname( const char *path_name, const bslabel_t *slabel, char *name_buf, const int len); int fgetsldname( const int fd, const bslabel_t *slabel_p, char *name_buf, const int len);
getmldadorn(2) システムコールは、path_name に対する完全な装飾名を取得します。fgetmldadorn(2) システムコールは、ファイル記述子を使用します。詳細は、getmldadorn(2) のマニュアルページを参照してください。
int getmldadorn( const char *path_name, char *adorn_buf[MLD_ADORN_MAX]); int fgetmldadorn( const int fd, char adorn_buf[MLD_ADORN_MAX]);
mldstat(2) システムコールは、path_name によって指定された MLD のファイル属性情報を返します。mldlstat(2) システムコールは、MLD シンボリックリンクの情報を返します。詳細は、mldstat(2) のマニュアルページを参照してください。
int mldstat( const char *path_name, struct stat *stat_buf); int mldlstat( const char *path_name, struct stat *stat_buf);
次のシステムコールの詳細は、第 2 章「プログラミングインタフェースの概要」の 「ファイルシステムのセキュリティ属性フラグの取得と設定」を参照してください。また、getfattrflag(2) のマニュアルページも参照してください。
int mldgetfattrflag( const char *path, secflgs_t *flags) int mldsetfattrflag( const char * path, secflgs_t which, secflgs_t flags))
ライブラリルーチンを使用して、現在の作業ディレクトリのパス名取得や、装飾を使用したパス名表示が行えます。
次のルーチンは、現在の作業ディレクトリの完全な装飾名を取得します。詳細は、mldgetcwd(3) のマニュアルページを参照してください。
char* mldgetcwd( char *buf, size_t size);
次のルーチンは、path_name で指定された MLD に対する装飾名を取得します。詳細は、adornfc(3) のマニュアルページを参照してください。
int adornfc( const char *path_name, char *adorned_name);
次のルーチンは、path_name で指定されたパス名を受け取り、すべてのシンボリックリンクを展開し、現在のディレクトリと親ディレクトリに対する相対パス名の参照を解決し、余分なスラッシュ文字を削除し、正しい MLD および SLD 装飾を加え、最終結果を resolved_path (解決済みパス) に格納します。この結果は、プロセスが動作している SLD、または指定された SLD のパス名を示します。詳細は、mldrealpath(3) のマニュアルページを参照してください。
char* mldrealpath( const char *path_name, char *resolved_path); char * mldrealpathl( const char *path_name, char *resolved_path, const bslabel_t *senslabel);
次のコードは、getmldadorn(2) システムコールを使用して MLD 装飾を照会し、getsldname(2) システムコールを使用して Top Secret SLD の SLD 名を照会します。この例では、Top Secret の SLD はまだ存在しないため、getsldname(2) に対する呼び出しがこれを作成します。
プロセスは、認可上限 Top Secret を使用して Confidential で動作しています。このプロセスは、Top Secret ラベルの変換に sys_trans_label 特権、Top Secret SLD の作成に file_upgrade_sl 特権、そして Top Secret SLD 情報のアクセスに file_mac_search 特権と file_mac_read 特権を必要とします。
#include <tsol/label.h> main() { int retval, error, length; bslabel_t label; char *buffer[1025], *buf[1025], *string = "TOP SECRET"; char *file = "/export/home/zelda"; retval = getmldadorn(file, buffer); printf("MLD adornment = %s¥n", buffer); /* 有効セット内で sys_trans_label をオン (有効) にする */ retval = stobsl(string, &label, NEW_LABEL, &error); /* sys_trans_label をオフ (無効) にする */ length = sizeof(buf); /* file_upgrade_sl、file_mac_search、file_mac_read */ /*をオン (有効) にする */ retval = getsldname(file, &label, buf, length); /* file_upgrade_sl、file_mac_search、file_mac_read */ /*をオフ (無効) にする*/ printf("SLD name = %s¥n", buf); }
printf(1) 文によって、次のように出力されます
MLD adornment = .MLD.
SLD name = .SLD.3
次の例は、mldgetcwd(3) ルーチンを使用して現在の作業ディレクトリ (MLD と現在の SLD) を照会し、adornfc(1) ルーチンを使用してこの MLD の装飾名を取得します。続いて、mldrealpath(1) ルーチンを使用して resolvefile (解決済みファイル) に格納されたパス名内の余分なスラッシュを削除し、実際のパスを見つけます。このプロセスは、Confidential で動作しています。
#include <tsol/label.h> #include <sys/types.h> main() { int retval; char *buffer[1025]; char *file = "/export/home/zelda"; char *string2, *name[1025], *string3, *resolved[1025]; size_t size; /* 文字列のエラーを解決する */ char *resolvefile = "./"; size = sizeof(buffer); string2 = (char *)mldgetcwd(buffer, size); printf("Current working directory = %s¥n", buffer); retval = adornfc(file, name); printf("Adorned name = %s¥n", name); string3 = (char *)mldrealpath(resolvefile, resolved); printf("Real path = %s¥n", resolved); }
printf 文によって、次のように出力されます。
adornfc(1) ルーチンに対するファイルパラメータに SLD 名が含められる場合、装飾名は /export/home/zelda/.MLD..SLD.1 のように SLD が追加された形式で返されます。
Current working directory = /export/home/.MLD.zelda/.SLD.2
Adorned name = /export/home/.MLD.zelda
Real path = /export/home/.MLD.zelda/.SLD.2
次の例は、/export/home/zelda MLD の属性情報を取得します。stat(2) システムコールマクロは、printf(1) 文で MLD がディレクトリであるか通常のファイルであるかを確認します。そして、ctime(3C) ルーチンによって、返された秒単位の時間がユーザーが読める形式に変換されます (詳細は、ctime(3C) のマニュアルページを参照)。
#include <tsol/label.h> #include <sys/stat.h> main() { int retval; struct stat statbuf; char *file = "/export/home/zelda"; retval = mldstat(file, &statbuf); printf("Is file system object a directory? = %d¥n", S_ISDIR(statbuf.st_mode)); printf("Is file system object a regular file? = %d¥n", S_ISREG(statbuf.st_mode)); printf("Number of links = %d¥n", statbuf.st_nlink); printf("Owner's user ID = %d¥n", statbuf.st_uid); printf("Owner's group Id = %d¥n", statbuf.st_gid); printf("Last access time = %s¥n", ctime(&statbuf.st_atime)); printf("Last modify time = %s¥n", ctime(&statbuf.st_mtime)); printf("Last status change = %s¥n", ctime(&statbuf.st_ctime)); }
printf 文によって、次のように出力されます。
Is file system object a directory? = 1
Is file system object a regular file? = 0
Number of links = 6
Owner's user ID = 29378
Owner's group Id = 10
Last access time = Wed May 28 10:58:25 1997
Last modify time = Wed May 28 09:39:18 1997
Last status change = Wed May 28 09:39:18 1997
open(2) や creat(2) のような、パス名を受け入れる UNIX システムコールは、通常のパス名に代わって完全な装飾パス名が渡されないかぎり、プロセスと同じ機密ラベルの SLD をアクセスします。完全な装飾パス名には、次のコード例に示すように、MLD の装飾と SLD のディレクトリ名が入ります。プロセスは、mkdir(1) システムコールを使用しても、MLD または SLD 内にファイルやディレクトリを作成できません。
「セキュリティポリシー」で説明している必須アクセス権制御と任意アクセス権制御が適用されます。
次の例では、プロセスは認可上限 Top Secret を使用して Confidential で動作しています。この Confidential プロセスは、Top Secret の SLD にアクセスするためには、有効セットに file_mac_search 特権を必要とします。ファイルが書き込みのために開かれており、セキュリティポリシーによって上位書き込みが許容されるため、この処理がすべての任意アクセス検査の条件を満たすのであれば、ほかに必要な特権はありません。
#include <tsol/label.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> main() { int filedes; /* プロセスが実行されている SLD でファイルを開く */ filedes = open("/export/home/zelda/afile", O_WRONLY); printf("File descriptor for regular path = %d¥n", filedes); /* Top Secret の SLD でファイルを開く */ /* 有効セット内で file_mac_search をオン (有効) にする */ filedes = open("/export/home/.MLD.zelda/.SLD.3/afile", O_WRONLY); /* file_mac_search をオフ (無効) にする */ printf("File descriptor for adorned path = %d¥n", filedes); }
printf 文によって、次のように出力されます。
File descriptor for regular path = 3
File descriptor for adorned path = 4
次の例では、プロセスは認可上限 Top Secret を使用して Confidential で動作しています。 Confidential プロセスは、Top Secret の SLD にアクセスするためには、有効セットに file_mac_search 特権を必要とします。Top Secret SLD 内にまだ afile が存在しない場合、プロセスは file_mac_write 特権を必要とします。これは、このプロセスの機密ラベルが SLD の機密ラベルと同等でないためです。afile がすでに存在する場合は、file_mac_write 特権は必要ありません。
#include <tsol/label.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> main() { int filedes; /* プロセスが実行されている SLD でファイルを開く */ filedes = creat("/export/home/zelda/afile", 660); printf("File descriptor for regular path = %d¥n", filedes); /* Top Secret の SLD でファイルを作成する */ /* 有効セット内で file_mac_search をオン (有効) にする */ filedes = creat("/export/home/.MLD.zelda/.SLD.3/afile", 660); /* file_mac_search をオフ (無効) にする */ printf("File descriptor for adorned path = %d¥n", filedes); }
printf 文によって、次のように出力されます。
File descriptor for regular path = 3
File descriptor for adorned path = 4