セキュリティ統合アーキテクチャ (SIA) を使用すると,ローカルおよび分散型のセキュリティ認証メカニズムを Tru64 UNIX オペレーティング・システム上に階層化できます。SIA 構成フレームワークは,セキュリティを扱うコマンドを特定のセキュリティ・メカニズムから切り離します。Tru64 UNIX のセキュリティを扱うコマンドは,メカニズムに依存するルーチン群を呼び出すために変更されています。固有のルーチン群を持つライブラリを用意することで,開発者は,セキュリティを扱うコマンド自体を変更せずに,そのコマンドの動作を変更することができます。SIA では,SIA 構成に必要な,セキュリティ・メカニズムに依存するインタフェース (siad_*()
ルーチン) を定義しています。図 6-1
は,SIA を形成する構成要素の関係を示しています。
セキュリティを扱うコマンドを,表 6-1
に示します。
表 6-1: セキュリティを扱うオペレーティング・システム・コマンド
コマンド | 説明 |
chfn |
finger 情報を変更します。 |
chsh |
ログイン・シェル情報を変更します。 |
dnascd |
DECnet と接続します。 |
ftpd |
インターネット・ファイル転送プロトコル・サービスを行います。 |
login |
ユーザの認証を行います。 |
passwd |
ユーザ・パスワードを設定または変更します。 |
rshd |
リモート実行のサービスを行います。 |
su |
ユーザ ID を切り替えます。 |
表 6-2
および表 6-3
は,SIA ポート・ルーチンを示しています。
表 6-2: SIA のメカニズム非依存ルーチン
SIA ルーチン | 説明 |
sia_init() |
SIA 構成を初期化します。 |
sia_chk_invoker() |
呼び出し元アプリケーションの特権をチェックします。 |
sia_collect_trm() |
パラメータを収集します。 |
sia_chg_finger() |
finger 情報を変更します。 |
sia_chg_password() |
ユーザのパスワードを変更します。 |
sia_chg_shell() |
ログイン・シェルを変更します。 |
sia_ses_init() |
SIA セッション処理を初期化します。 |
sia_ses_authent() |
エンティティの認証を行います。 |
sia_ses_reauthent() |
ユーザのパスワードを再確認します。 |
sia_ses_suauthent() |
su
コマンドを処理します。 |
sia_ses_estab() |
セッションのためのコンテキストを確立します。 |
sia_ses_launch() |
セッション開始および TTY 状態のログをとります。 |
sia_ses_release() |
セッションに関連するリソースを解放します。 |
sia_make_entity_pwd() |
SIAENTITY のパスワード構造体を用意します。 |
sia_audit() |
監査レコードを生成します。 |
sia_chdir() |
現ディレクトリを安全に変更します (NFS セーフ)。 |
sia_timed_action() |
時間制限およびシグナルの保護付きで呼び出しを行います。 |
sia_become_user() |
su
ルーチン。 |
sia_validate_user() |
ユーザのパスワードを確認します。 |
sia_get_groups() |
グループを取得します。 |
SIA ルーチン | 説明 |
siad_init() |
処理を初期化します (リブートのたびに呼び出されます)。 |
siad_chk_invoker() |
呼び出し元プログラムの特権をチェックします。 |
siad_ses_init() |
セッションを初期化します。 |
siad_ses_authent() |
セッションの認証を行います。 |
siad_ses_estab() |
リソースとライセンスをチェックします。 |
siad_ses_launch() |
セッション開始のログをとります。 |
siad_ses_suauthent() |
su
コマンドを処理します。 |
siad_ses_reauthent() |
ユーザのパスワードを再確認します。 |
siad_ses_release() |
セッションのリソースを解放します。 |
siad_chg_finger() |
chfn
コマンドを処理します。 |
siad_chg_password() |
パスワードを変更する関数を呼び出します。 |
siad_chg_shell() |
chsh
コマンドを処理します。 |
siad_getpwent() |
getpwent()
および
getpwent_r()
を処理します。 |
siad_getpwuid() |
getpwuid()
および
getpwuid_r()
を処理します。 |
siad_getpwnam() |
getpwnam()
および
getpwnam_r()
を処理します。 |
siad_setpwent() |
一連の
getpwent()
呼び出しを初期化します。 |
siad_endpwent() |
一連の
getpwent()
呼び出し後にリソースを解放します。 |
siad_getgrent() |
getgrent()
および
getgrent_r()
を処理します。 |
siad_getgrgid() |
getgrgid()
および
getgrgid_r()
を処理します。 |
siad_getgrnam() |
getgrnam()
および
getgrnam_r()
を処理します。 |
siad_setgrent() |
一連の
getgrent()
呼び出しを初期化します。 |
siad_endgrent() |
一連の
getgrent()
呼び出しをクローズします。 |
siad_chk_user() |
要求された情報をメカニズムが変更できるか確認します。 |
siad_get_groups() |
ユーザの補助グループの配列を埋めます。 |
SIA は,セキュリティを扱うコマンドと,セキュリティ・メカニズムに依存する関数を提供するセキュリティ・メカニズムの間に,レイヤを確立します。セキュリティを扱う SIA ルーチンは,セキュリティ・メカニズムをそれぞれ 4 つまで使用するように構成できます (呼び出される順序はまちまちです)。
どのセキュリティ・メカニズムをどのような順序で呼び出すかは,スイッチ・テーブル・ファイル
/etc/sia/matrix.conf
で決定されます (『セキュリティ管理ガイド』を参照)。この方法は,/etc/svc.conf
を使って
libc
get*
関数を制御する方法と似ています。ただし,呼び出しメカニズムは明らかに異なります。
SIA の呼び出しメカニズムは,シェアード・ライブラリ内のルーチンのアドレスを見つけて呼び出し,特定のセキュリティ・メカニズムのルーチンにアクセスします。SIA には,Tru64 UNIX の
getpw*
関数および
getgr*
関数の代わりとなる制御および構成が用意されています。
SIA の階層構造により,透過性を必要とする新しいセキュリティ・メカニズムやセキュリティを扱うコマンドに対し,国際化メッセージ・カタログ・サポートおよびスレッド・セーフのポート・インタフェースが確立されます。SIA インタフェースのタイプごとに用意されたロック群によって,スレッド・セーフが実現されています。ただし,SIA はユーティリティとセキュリティ・メカニズムとの間のレイヤであるため,再入可能性を実現するのは,レイヤード・セキュリティ・メカニズムの責任となります。
SIA の主な目的は,将来のセキュリティ要件に対応できるだけ柔軟で拡張性がある,login
,su
,および
passwd
などの,セキュリティを扱うコマンド用の透過的なインタフェースを提供することです。Tru64 UNIX 上のレイヤード・プロダクトのうち,新しいセキュリティ・メカニズムを作成するか,セキュリティを扱うコマンドを含む製品には,透過的なインタフェースを維持するために SIA を統合する必要があります。
SIA の構成要素は,ユーザ・レベルのモジュールだけで構成されます。これらの構成要素は,セキュリティを扱うコマンドが複数のセキュリティ・メカニズムを利用するという構成上の問題を解決します。SIA の構成要素は,複数のセキュリティ・メカニズムの構成および利用に伴うカーネル関連の問題は解決しません。
6.2 SIA のアーキテクチャ
Tru64 UNIX の SIA で導入された階層型アーキテクチャには,次の 2 つのグループのインタフェース・ルーチンがあります。
sia_*
()セキュリティを扱うコマンドが使う,セキュリティ・メカニズムに依存しないインタフェース
siad_*
()特定のセキュリティ・メカニズムによって提供される,セキュリティ・メカニズムに依存するインタフェース
各セキュリティ・メカニズムでは,siad_*()
ルーチンを含むシェアード・ライブラリを提供しています。また,構成に合った,固有のセキュリティ・メカニズム名を提供しています。どのメカニズムをどのような順序で呼び出すかを指定するために,1 単語のセキュリティ・メカニズム名とライブラリ名を,matrix.conf
ファイル内のキーとして使います。
Tru64 UNIX のセキュリティを扱うコマンドは,メカニズムに依存しない
sia_*()
ルーチンを使うように変更されています。これらのルーチンは,特定のセキュリティ技術に依存しないセキュリティ関数にアクセスするために,コマンドとユーティリティで使います。matrix.conf
ファイルで選択された構成に応じて,各
sia_*
() ルーチンは,メカニズムに依存する,関連の
siad_*
() ルーチンを呼び出します。このファイルについての詳細は,『セキュリティ管理ガイド』を参照してください。
メカニズムに依存する
siad_*
() インタフェース・ルーチンは,セキュリティ・メカニズムが提供する,メカニズム依存関数へのコールアウトとして,SIA で定義されています。matrix.conf
ファイルは,各 SIA 関数に対して呼び出されるセキュリティ・メカニズムと,その順序を決定するために使用されます。
指定されたセキュリティ・メカニズム内の特定のモジュールを呼び出し,必要な状態を渡す処理は,メカニズムに依存しない層で行われます。呼び出し元プロセスは,シェアード・ライブラリ関数を使って,セキュリティ・メカニズムで提供される指定のシェアード・ライブラリ内の特定のモジュール・アドレスにアクセスしたり,アドレスを見つけたりします。
名前の衝突をなくし,呼び出し手順を簡単にするために,セキュリティ・メカニズムに依存するモジュール
siad_*
() ルーチンの名前は固定です。Tru64 UNIX は,dlopen
() および
dlsym
() シェアード・ライブラリ・インタフェースを使って,特定のセキュリティ・メカニズムのシェアード・ライブラリをオープンし,siad_*
() 関数のアドレスを見つけます。siad_*
() ルーチンを優先使用 (preempt) する必要がある場合,ライブラリ内で
_ _siad_*
という形式の名前にしなければなりません。また,そのライブラリを
libc
より先にリンクしなければなりません。命名と優先使用の要件についての詳細は,6.17 節
を参照してください。
6.2.1 ライブラリ
SIA のセキュリティ・メカニズムは,個別のシェアード・ライブラリとして構成されます。このシェアード・ライブラリのエントリ・ポイントには,SIA で定義された名前を付けます。各メカニズムは,一意のメカニズム識別子を持つ必要があります。セキュリティ・メカニズムで提供される,シェアード・ライブラリ内の実際のエントリ・ポイントは各メカニズムとも同じで,siad_*
() 形式のエントリ・ポイントです。
省略時のセキュリティ構成は,libc
に含まれている BASE セキュリティ・メカニズムです。省略時の BASE セキュリティ・メカニズムは,ユーザ・データベースとして
/etc/passwd
ファイル (つまり,ハッシュ・データベース・バージョン),グループのデータベースとして
/etc/group
ファイルを使います。NIS (Network Information Service) が構成されている場合は,省略時の BASE メカニズムはこのサービスも使います。シングルユーザ・モードのとき,またはインストール時には,BASE セキュリティ・メカニズムが有効になります。
6.2.2 ヘッダ・ファイル
SIA インタフェースと構造体は,ファイル
/usr/include/sia.h
および
/usr/include/siad.h
に定義されています。sia*.h
ファイルは,プログラム開発サブセットに含まれています。
6.3 SIA システムの初期設定
SIA は,システムがリブートされるたびに各セキュリティ・メカニズムへのコールアウトを用意します。このコールアウトは,/usr/sbin/siainit
プログラムが実行します。このプログラムは,構成されている各セキュリティ・メカニズムの
siad_init()
エントリ・ポイントを呼び出します。これにより,セキュリティ・メカニズムはリブート時の初期化を行うことができます。siad_init()
呼び出しから SIADFAIL 応答があると,システムはリブートしなくなり,SIA INITIALIZATION FAILURE (SIA 初期化障害) メッセージがコンソールへ送信されます。このため,siad_init
() 呼び出しが SIADFAIL 応答を行うのは,セキュリティ上の問題や,root
にログインが許可されないという問題だけとする必要があります。
6.4 SIAENTITY 構造体
SIAENTITY 構造体には,セッション処理のパラメータが格納されています。これらのパラメータは,セッション処理の段階間でセッションの状態を引き渡すために使用されます。例 6-1 は,SIAENTITY 構造体を示しています。
typedef struct siaentity { char *name; /* collected name */ char *password; /* entered or collected password */ char *acctname; /* verified account name */ char **argv; /* calling command argument list */ int argc; /* number of arguments */ uid_t suid; /* starting ruid */ char *hostname; /* requesting host NULL=>local */ char *tty; /* pathname of local tty */ int can_collect_input; /* 1 => yes, 0 => no input */ int error; /* error message value */ int authcount; /* Number of consecutive */ /* failed authent attempts */ int authtype; /* Type of last authent */ struct passwd *pwd; /* pointer to passwd struct */ char *gssapi; /* for gss_api prototyping */ char *sia_pp; /* for passport prototyping */ int *mech[SIASWMAX]; /* pointers to mech-specific data */ /* allocated by mechanisms indexed */ /* by the mechind argument */ } SIAENTITY;
SIA にはパラメータ収集コールバック機能があるため,どのようなグラフィカル・ユーザ・インタフェース (GUI) でもコールバックを利用することができます。sia_collect_trm()
ルーチンは,端末パラメータの収集に使います。sia_*()
ルーチンを呼び出すコマンドは,引数として,適切な収集ルーチンへのポインタを渡します。このため,セキュリティ・メカニズムでは,ユーザに入力を求めることができます。収集ルーチンの引数が NULL の場合,セキュリティ・メカニズムは,収集が許可されていないため,要求を満たすために他の引数を使用する必要があるものと判断します。NULL は,非対話式のコマンドの場合に使用されます。信頼性を向上するには,可能な限り収集ルーチンを使ってください。
can_collect_input
引数は,セッション処理に含まれており,警告やエラー・メッセージを出力できる状態のまま,入力用の収集機能を使用不能にします。収集ルーチンは,簡単なフォームとメニューによるデータ収集をサポートしています。ある程度のフィールド検証機能がサポートされており,パラメータの長さと内容 (英数字,数字のみ,英字のみ,および非表示) がチェックされます。セキュリティを扱うコマンドやユーティリティで用意される収集ルーチンでは,表示特性を適切に設定する必要があります。
パラメータの収集機能は,sia.h
で定義されている
sia_collect_trm
() インタフェースを使用する SIA によって提供されます。例 6-2
を参照してください。
例 6-2: sia.h でのパラメータ収集インタフェースの定義
int sia_collect_trm(timeout, rendition, title, num_prompts, prompts); int timeout /* number of seconds to wait */ /* 0 => wait forever */ int rendition SIAMENUONE 1 /* select one of the choices given */ SIAMENUANY 2 /* select any of the choices given */ SIAFORM 3 /* fill out the form */ SIAONELINER 4 /* One question with one answer */ SIAINFO 5 /* Information only */ SIAWARNING 6 /* ERROR or WARNING message */ unsigned char *title /* pointer to a title string. */ */ /* NULL => no title */ int num_prompts /* Number of prompts in collection */ prompt_t *prompts /* pointer to prompts */ typedef struct prompt_t { unsigned char *prompt; unsigned char *result; int max_result_length; /* in chars */ int min_result_length; /* in chars */ int control_flags; } prompt_t; control_flags SIARESINVIS 0x2 result is invisible SIARESANY 0x10 result can contain any ASCII chars SIAPRINTABLE 0x20 result can contain only printable chars SIAALPHA 0x40 result can contain only letters SIANUMBER 0x80 result can contain only numbers SIAALPHANUM 0x100 result can contain only letters and numbers
パラメータ収集についての詳細は,
sia_collect_trm
(3)6.6 状態の保守
一部のコマンドでは,sia_*()
への呼び出しを複数回行うため,これらの複数の呼び出しに渡って状態を保守する必要があります。状態は必ず,特定のユーザ (エンティティとも呼ばれる) に対応しています。SIA ではエンティティという用語を,認証できるユーザ,プログラム,またはシステムという意味で使用します。エンティティ識別子は,ユーザ ID (UID) です。Tru64 UNIX に移植されたすべてのセキュリティ・メカニズムは,この UID が各メカニズムに同等にマッピングされるように管理されなければなりません。この条件により,複数のセキュリティ・メカニズムを共存させ,連携して動作させることができます。セキュリティ・メカニズムにユーザの代替識別子がある場合は,他のメカニズムが正しく連携して動作するようにし,同期のとれたセキュリティ情報を提供するために,一意の UID へのマッピングを行わなければなりません。
SIAENTITY 構造体 (6.4 節を参照) へのポインタは,セキュリティ・セッション機能を要求しているエンティティを識別するための中間状態を持つ引数として使います。また,SIAENTITY 構造体を使うと,セッション処理中にセキュリティ・メカニズム間で状態を共有することができます。
libc
ライブラリは,SIAENTITY 構造体の基本要素の割り当てと解放を行う機能を提供しています。SIAENTITY 構造体の割り当ては,セッション初期化ルーチン
sia_ses_init
() の一部として行われます。SIAENTITY 構造体の割り当て解除は,セッション解放ルーチン
sia_ses_release
() への呼び出しで行われます。セッション処理中 (たとえば,sia_ses_*authent
() ルーチンの中) にエラーが発生し,再試行せずにあきらめるときには,sia_ses_release
() を呼び出して,そのセッションに関係する SIAENTITY 構造体をクリーンにする (つまり解放する) 必要があります。sia_ses_estab()
ルーチンまたは
sia_ses_launch
() ルーチンの途中でエラーが発生して障害状態が戻された場合は,これらのルーチンが
sia_ses_release
() を呼び出します。
6.7 SIA のリターン値
SIA は,成功または失敗を示す応答を,呼び出し元のコマンドまたはユーティリティへ戻します。SIAENTITY 構造体には,エラー・コード・フィールド (error) があり,エラーの詳細の定義に利用できます。
siad_ses_*()
ルーチンは,次の状態を示すビットマップ値を戻します。
条件付きの失敗を示します。最下位ビットに 0 が設定されます。次のセキュリティ・メカニズムを引き続き呼び出します。
条件付きの成功を示します。最下位ビットに 1 が設定されます。
「無条件」の戻りを示します。最下位から 2 番目のビットに 1 が設定されます。SIADFAIL または SIADSUCCESS のどちらかと一緒に設定されます。
SIA は,デバッグおよびロギングの機能をサポートしており,データを
/var/adm/sialog
ファイルに追加することができます。SIA のロギング機能では,次の 3 つのログ項目タイプをサポートしています。
SIA 処理中の成功の場合
SIA 処理中の失敗の場合
SIA インタフェース内のセキュリティ構成またはセキュリティ・リスクの場合
sia_log
() のロギング・ルーチンは,セキュリティ・メカニズムで使用でき,printf
() の書式と互換性のある書式付き文字列を受け入れます。各ログ・エントリにはタイムスタンプが付きます。例 6-3
は,一般的な
/var/adm/sialog
ファイルです。
例 6-3: 一般的な /var/adm/sialog ファイル
SIA:EVENT Wed Feb 3 05:21:31 1999 Successful SIA initialization SIA:EVENT Wed Feb 3 05:22:08 1999 Successful session authentication for terry on :0 SIA:EVENT Wed Feb 3 05:22:08 1999 Successful establishment of session SIA:ERROR Wed Feb 3 05:22:47 1999 Failure to authenticate session for root on :0 SIA:ERROR Wed Feb 3 05:22:52 1999 Failure to authenticate session for root on :0 SIA:EVENT Wed Feb 3 05:22:59 1999 Successful session authentication for root on :0 SIA:EVENT Wed Feb 3 05:22:59 1999 Successful establishment of session SIA:EVENT Wed Feb 3 05:23:00 1999 Successful launching of session SIA:EVENT Wed Feb 3 05:24:40 1999 Successful authentication for su from root to terry SIA:EVENT Wed Feb 3 05:25:46 1999 Successful password change for terry
sia_log
() ルーチンは,デバッグ用にのみ使用できます。_ses_*
ルーチンは,監査のログをとるために
audgen
() を使います。
6.9 SIA のセキュリティ・メカニズムの統合
要求されている SIA 処理のクラスまたはタイプによって,使用するセキュリティ・メカニズムとその順序は変化します。セキュリティ・メカニズムの組み合わせとしては,ローカル・メカニズム (ローカル・システム・セキュリティのみを扱う) と分散セキュリティ・メカニズム (いくつかのシステムにまたがったセキュリティ事項のみを扱う) が含まれるのが一般的です。SIA の階層構造によって,これら 2 つのセキュリティ・メカニズムを共存させたり,さらに進めて統合することができます。
セキュリティ・メカニズムの統合の例としては,ログイン処理やセッション処理があります。SIA の階層構造によって,セッション処理時に,各種のセキュリティ・メカニズム間で状態 (SIAENTITY) が受け渡されます。この状態には,収集された名前およびパスワードと,セッション処理の現状態が含まれます。ローカル・セキュリティ・メカニズムは,先に実行されたセキュリティ・メカニズムの認証処理を信頼するように設計することができます。 これにより,認証の保証が可能になります。この場合,分散メカニズムでユーザが正常に認証されると,ローカル・メカニズムではその認証を信頼して受け入れ,セッション処理を継続することができます。
また SIA では,ローカル・メカニズムが保証を受け入れないようにすることもできます。この場合,以前の認証結果に関係なく,ローカル・メカニズムで独自の認証処理が行われます。その結果,ユーザはユーザ名とパスワードの入力を何度も求められることになります。SIA では任意の順序でセキュリティ・メカニズムを使用できますが,保証を受け入れるメカニズムを,保証を受け入れないメカニズムの後に使用する必要があります。
注意
省略時のセキュリティ・メカニズム BASE は,認証の保証を受け入れます。
SIA のレイヤは,セキュリティ・メカニズムを,コマンドの個々のユーザ・インタフェースから分離する働きをします。この分離を行うために,呼び出し元のコマンドは,パラメータ収集ルーチンへのポインタを
sia_*
() への引数として渡します。収集ルーチンでは,簡単なフォームと,メニュー・タイプの処理をサポートしなければなりません。収集ルーチンの定義や必要条件は,sia.h
に定義されています。セキュリティ・メカニズムからユーザ・インタフェースを分離することによって,ユーザ・インタフェースを柔軟に変更することができます。たとえば,ワークステーションに適応させたり,ダム端末モデルに適応させることができます。
6.10 SIA セッション処理
セッション処理インタフェースは,後で別のエンティティとなる必要がある,または別のエンティティとして動作する必要のある,ユーティリティまたはコマンドの処理に関連しています。図 6-2 は,一般的なログイン・セッションでの SIA ルーチンと,それらのルーチンの関係を示しています。
セキュリティ・メカニズムに依存するルーチン (siad_*()
) へのセッション処理インタフェースでは,リターン値を使って,セッションの状態の判断と,継続するかどうかの判断を行います。リターン値は,次のとおりです。
セキュリティ・メカニズムの
siad_*()
ルーチンからの SIADFAIL 応答は,セキュリティ・メカニズムが失敗したが,処理を継続する必要があることを示します。
セキュリティ・メカニズムの
siad_*()
ルーチンからの SIADFAIL | SIADSTOP 応答は,セキュリティ・メカニズムが失敗し,セッション処理を停止する必要があることを示します。セキュリティ上の重大な問題またはリスクが見つかった場合に,この応答が使用されます。このような場合は,sialog
ファイルに ALERT イベントを送る必要があります。
最後の応答は SIADSUCCESS で,セキュリティ・メカニズムがセッション処理のフェーズを正常に終了したことを示します。場合によっては,SIADSUCCESS | SIADSTOP というリターン値も使用できます。
すべてのセキュリティ・メカニズムが,セッション処理の各フェーズで必要な処理を備えているわけではありません。通常,省略時の応答は SIADFAIL です。この応答が戻されたときには,構成されている他のセキュリティ・メカニズムから,SIADSUCCESS 応答を得る必要があります。この唯一の例外は,セッション処理の最初と最後の段階です。セキュリティ・メカニズムでは,セッションの初期化またはセッションの解放時に何も行う必要がない場合,SIADSUCCESS 応答を返す必要があります。セッション処理のその他のフェーズでは,SIADFAIL 応答が省略時の値になります。
セッション処理インタフェースは通常,次の順序で呼び出されます。
sia_ses_init()
セッションを初期化します。
sia_ses_authent()
セッションの認証を行います。失敗したときには,再度呼び出して再試行することができます。
sia_ses_estab()
セッションを確立します。失敗した場合,sia_ses_release()
を呼び出します。
sia_ses_launch()
セッションを起動します。失敗した場合,sia_ses_release()
を呼び出します。
sia_ses_release()
セッションを解放します。
メカニズム・インデックス (mechind
) の一貫性を保つために,すべてのセッション・ルーチンには,同じ数のメカニズムを同じ順序で指定する必要があります。
例 6-4
は,login
コマンドのセッション処理を示すコードです。
例 6-4: login コマンドのセッション処理
. . . /* SIA LOGIN PROCESS BEGINS */ /* Logging of failures to sia_log is done within the libsia */ /* Logging to syslog is responsibility of calling routine */ if((sia_ses_init(&entity, oargc, oargv, hostname, loginname, \ ttyn, 1, NULL)) == SIASUCCESS) { /***** SIA SESSION AUTHENTICATION *****/ if(!fflag) { for(cnt=5; cnt; cnt--) { if((authret=sia_ses_authent(sia_collect,NULL,entity)) \ == SIASUCCESS) break; else if(authret & SIASTOP) break; fputs(MSGSTR(INCORRECT, "Login incorrect\n"), stderr); } if(cnt <= 0 || (authret & SIASTOP)) { sia_ses_release(&entity); exit(1); } } /***** SIA SESSION ESTABLISHMENT *****/ if(sia_ses_estab(sia_collect,entity) == SIASUCCESS) { /****** set up environment *******/ /* destroy environ. unless user requested preservation */ if (!pflag) { pp = getenv("TERM"); if (pp) strncpy(term, pp, sizeof term); clearenv(); } (void)setenv("HOME", entity->pwd->pw_dir, 1); if(entity->pwd->pw_shell && *entity->pwd->pw_shell) strncpy(shell, entity->pwd->pw_shell, sizeof shell); (void)setenv("SHELL", shell, 1); if (term[0] == ' ') (void)strncpy(term, stypeof(tty), sizeof(term)); (void)setenv("TERM", term, 0); (void)setenv("USER", entity->pwd->pw_name, 1); (void)setenv("LOGNAME", entity->pwd->pw_name, 1); (void)setenv("PATH", _PATH_DEFPATH, 0); /***** SIA LAUNCHING SESSION *****/ if(sia_ses_launch(sia_collect,entity) == SIASUCCESS) { /* 004 - start */ if ((entity -> pwd != NULL) && (entity -> pwd -> pw_dir != NULL) && (entity -> pwd -> pw_dir [0] != 0)) sprintf (hush_path, "%s/%s", entity -> pwd -> pw_dir, _PATH_HUSHLOGIN); else strcpy (hush_path, _PATH_HUSHLOGIN); quietlog = access(hush_path, F_OK) == 0; /* 004 - end */ if(!quietlog) quietlog = !*entity->pwd->pw_passwd && \ !usershell(entity->pwd->pw_shell); if (!quietlog) { struct stat st; motd(); (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, \ entity->pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) (void)printf(MSGSTR(MAIL, "You have %smail.\n"), (st.st_mtime > st.st_atime) ? MSGSTR(NEW, \ "new ") : ); } sia_ses_release(&entity); /******* Setup default signals **********/ (void)signal(SIGALRM, SIG_DFL); (void)signal(SIGQUIT, SIG_DFL); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTSTP, SIG_IGN); tbuf[0] = '-'; (void)strcpy(tbuf + 1, (p = rindex(shell, '/')) ? p + 1 : shell); /****** Nothing left to fail *******/ if(setreuid(geteuid(),geteuid()) < 0) { perror("setreuid()"); exit(3); } execlp(shell, tbuf, 0); (void)fprintf(stderr, MSGSTR(NO_SHELL, \ "login: no shell: %s.\n"), strerror(errno)); exit(0); } /***** SIA session launch failure *****/ } /***** SIA session establishment failure *****/ } logerror(entity); exit(1); } logerror(entity) SIAENTITY *entity; { if(entity != NULL) { sia_ses_release(&entity); } syslog(LOG_ERR, MSGSTR(FAILURE3," LOGIN FAILURE ")); } . . .
セッションの初期化は,sia_ses_init()
ルーチンで行います。sia_ses_init()
ルーチンは,構成されている各セキュリティ・メカニズムの
siad_ses_init()
エントリ・ポイントを呼び出し,セッション処理の開始に関連する処理を行います。セッションの初期化段階では,SIAENTITY 構造体を初期化する必要があります。この構造体は,セッション処理のさまざまな段階にわたって状態を管理するために使います。
6.10.2 セッションの認証
セッション処理の認証段階では,セッションの ID を割り当てます。セション処理のこの段階では,セッションに対応させるエンティティを決定しなければなりませ。エンティティを決定できない場合,認証は失敗します。認証に成功したら,エンティティが得られます。
最上位の SIA セッション認証ルーチン
sia_ses_authent()
は,matrix.conf
ファイルに格納されている構成済の順序に従って,セキュリティ・メカニズムに依存する
siad_ses_authent()
を呼び出します。複数の認証ルーチンが呼び出されるため,SIAENTITY 構造体を使って,事前収集パラメータ (名前,パスワード,および最終的にはエンティティに対応する
/etc/passwd
エントリなど) が保持されます。
事前収集パラメータを使うことによって,セキュリティ・メカニズムは引数を再収集する必要がなくなります。たとえば,最初に DCE の
siad_ses_authent()
ルーチンを呼び出し,次にローカルの ENHANCED (エンハンスト・セキュリティ) の
siad_ses_authent()
を呼び出すように構成されているシステムに
root
がログインしようとする場合があります。
通常,DCE の認証処理では,root
を認証することはできません。ただし,ユーザに名前とパスワードを求めることはできます。これらの情報は,SIAENTITY 構造体を使って ENHANCED の
siad_ses_authent()
ルーチンに渡されます。これにより,ENHANCED メカニズムで
root
の名前とパスワードを確認することができ,root
を認証することができます。セッションの認証段階が終了するとすぐに,パスワード・フィールドがクリアされます。
セキュリティ・メカニズムに依存する認証ルーチンは,認証に成功したときにエンティティを決定して設定する機能を持たなければなりません。セキュリティ・メカニズムで,エンティティを独自に解釈する場合,共通の SIA エンティティ (ユーザ名と UID) への変換機能を提供しなければなりません。この制約なしでは,セキュリティ・メカニズム間でのエンティティの一貫性を確保することができません。
セッションの認証段階が正常に終了したときには,SIAENTITY 構造体に,認証されたエンティティのユーザ名とユーザ ID が格納されていなければなりません。セッションの認証に失敗した場合,呼び出し元のコマンドまたはプログラムは,sia_ses_authent()
を再度呼び出して認証処理を再試行することができます。一部のメカニズムでは,セッション処理のこの段階を,別のメカニズムに代行させることがあります。このような状況が発生するのは,ローカル・メカニズムが認証処理を省略し,別の分散メカニズムにゆだねた場合です。
6.10.3 セッションの確立
セッションの確立段階は,セッションの認証段階が正常に終了した後に,sia_ses_estab()
で起動されます。sia_ses_estab()
ルーチンは,複数のセキュリティ・メカニズムの
siad_ses_estab()
ルーチンを,matrix.conf
ファイルに定義されている順序で呼び出すように構成されています。セッション処理のセッション確立段階では,メカニズム・リソースとライセンスをチェックし,このセッションを正常に起動できるか確認します。passwd struct
エントリとその他の必要なセキュリティ・コンテキストの確認は,この段階で行う必要があります。セッション確立段階が正常に終了すると,システムはセッションを起動できる状態になります。
6.10.4 セッションの起動
セッションの起動段階では,セッションのスタートアップに関するロギングとアカウント処理を行います。ローカル・メカニズムでは,さらに
wtmp
エントリおよび
utmp
エントリを設定し,エンティティに対応する UID を実効 UID として設定します。lastlog
の更新の他に,setgid()
および
initgroup()
ルーチンによる処理も,ローカル・メカニズムで行います。重大なエラーが検出された場合だけ,セションを継続せずに停止します。
6.10.5 セッションの解放
セッション処理手順の最後の段階では,成功か失敗かにかかわらず,sia_ses_release()
ルーチンを呼び出します。このルーチンは,SIAENTITY 構造体などの,セッション処理リソースすべてを解放します。構成されているメカニズムが呼び出され,セッションで不要となったリソースが解放されます。
6.10.6 特定のセッション処理
以降の項では,login
,rshd
,および
rlogind
コマンドに特有のセッション処理について説明しています。
6.10.6.1 login プロセス
最も一般的なセッション処理は,login プロセスが,ユーザに対応するエンティティになるときです。エンティティは,認証を行って権限が与えられる人またはプロセスの一意の SIA 識別子です。例 6-4
のコードは,login
コマンドの一部分です。
6.10.6.2 rshd プロセス
/usr/sbin/rshd
のセッション処理は,login
とは異なります。rshd
プロセスは,ruserok()
を呼び出し,.rhosts
ファイルと
host.equiv
ファイルを参照して承認処理を行います。ruserok()
が失敗すると,rshd
も失敗します。
6.10.6.3 rlogind プロセス
rlogind
プログラムは,ruserok()
の呼び出しが成功した場合,-f
フラグを付けて
login
コマンドを実行します。ruserok()
の呼び出しが失敗した場合には,-f
フラグを付けないで実行します。-f
フラグを付けないで
login
を実行した場合は,ユーザ名とパスワードの入力を求める
sia_ses_authent()
が必要に応じて呼び出されます。
6.11 セキュア情報の変更
この節で説明しているルーチンは,従来の
/etc/passwd
エントリ情報の変更を行います。このクラスのルーチンは,その他のタイプの共通セキュア情報も取り扱うように拡張することができます。従来の
passwd
,chfn
,および
chsh
タイプのコマンド処理だけが規定されています。これらの各ルーチンは,同じオペレーション・モデルに従っています。ユーザが変更を要求すると,このクラスのルーチンは,構成された各メカニズムの
siad_chk_user()
を呼び出して,ユーザがそのメカニズムに登録されているか調べます。ユーザが 2 つ以上のセキュリティ・メカニズムに登録されている場合は,変更対象のメカニズムを選択できるように,収集ルーチンが選択メニューを表示します。要求を処理するメカニズムが 1 つだけ構成されている場合は,そのメカニズムが直接呼び出されます。
6.11.1 ユーザのパスワードの変更
パスワードを変更するために,sia_chg_password()
は
siad_chg_password()
ルーチンを使って,構成されているメカニズムを呼び出します。どのメカニズムがそのユーザをサポートしているかを調べるために,siad_chg_passwd()
ルーチンが構成されているすべてのメカニズムに対して,siad_chk_user()
が呼び出されます。ユーザが複数のメカニズムに登録されている場合,そのユーザには選択肢が表示されます。ユーザが 1 つのメカニズムだけに登録されている場合は,そのメカニズムが呼び出されます。
6.11.2 ユーザの finger 情報の変更
sia_chg_finger()
ルーチンは,構成されているメカニズムを
siad_chg_finger()
ルーチンを使って呼び出し,finger 情報を変更します。どのメカニズムがそのユーザをサポートしているかを調べるために,siad_chg_finger()
ルーチンが構成されているすべてのメカニズムに対して,siad_chk_user()
が呼び出されます。ユーザが複数のメカニズムに登録されている場合,そのユーザには選択肢が表示されます。ユーザが 1 つのメカニズムだけに登録されている場合は,そのメカニズムが呼び出されます。
6.11.3 ユーザのシェルの変更
sia_chg_shell()
ルーチンは,構成されているメカニズムを
siad_chg_shell()
ルーチンを使って呼び出し,ユーザのログイン・シェルを変更します。どのメカニズムがそのユーザをサポートしているかを調べるために,siad_chg_shell()
ルーチンが構成されているすべてのメカニズム対して,siad_chk_user()
が呼び出されます。ユーザが複数のメカニズムに登録されている場合,そのユーザには選択肢が表示されます。ユーザが 1 つのメカニズムだけに登録されている場合は,そのメカニズムが呼び出されます。
6.12 セキュリティ情報へのアクセス
以降の項で説明している SIA インタフェースは,従来の UNIX の
/etc/passwd
情報および
/etc/group
情報へのアクセスを処理します。他の共通のセキュア情報へのアクセスを処理するルーチンを作成することもできます。メカニズムに依存するセキュリティ情報へのアクセスは,アクセス対象の情報タイプを大半のメカニズムがサポートしている場合以外は,SIA インタフェースでは処理しないでください。
sia.h
に定義されている
sia_context
構造体および
mech_contexts
構造体は,メカニズム間で状態を受け渡すために使います。これらの構造体を,次に示します。
struct mech_contexts { void *value; void (*destructor)(); }; struct sia_context { FILE *fp; union { struct group *group; struct passwd *pass; } value; int pkgind; unsigned buflen; char *buffer; struct mech_contexts mech_contexts[SIASWMAX]; };
getgr*()
および
getpw*()
ルーチンには SIA インタフェースがあるため,セキュリティ・メカニズムでは,再入可能および再入不可の両方のスレッド・セーフ・アプリケーション用のルーチンを 1 つだけ用意する必要があります。この機能は,引数をセキュリティ・メカニズムの
siad_*()
ルーチン用の共通形式にカプセル化する,sia_getpasswd()
および
sia_getgroup()
ルーチンによって実現されます。
6.12.1 /etc/passwd 情報へのアクセス
従来の
/etc/passwd
エントリは,libc
および
libc_r
内の
getpw*()
ルーチンを使ってアクセスされます。SIA レイヤの
sia_getpasswd()
ルーチンは,呼び出し方法が現在の
getpw*()
ルーチンと同じですが,この呼び出し方法を,シングルスレッドおよびマルチスレッドの両方のプロセスで使用できる,1 つの共通ルーチンに変換します。この変換を行うことで,セキュリティ・メカニズムでは 1 組の
getpw*()
ルーチンをサポートするだけで済みます。getpwent()
ルーチンの処理は,すべてのエントリが処理されるまで,構成されている各セキュリティ・メカニズムを,事前に定義された順序で呼び出すことで行われます。
6.12.2 /etc/group 情報へのアクセス
従来の
/etc/group
エントリは,libc
および
libc_r
内の
getgr*()
ルーチンを使ってアクセスされます。SIA レイヤの
sia_getgroup()
ルーチンは,呼び出し方法が現在の
getgr*()
ルーチンと同じですが,この呼び出し方法を,シングルスレッドおよびマルチスレッドの両方のプロセスで使用できる,1 つの共通ルーチンに変換します。1 つのルーチンに変換することにより,必要なルーチンの数が少なくなるため,セキュリティ・メカニズムの移植性が向上します。getgrent()
ルーチンの処理は,すべてのエントリが処理されるまで,構成されている各セキュリティ・メカニズムを,事前に定義された順序で呼び出すことで行われます。
6.13 セッション・パラメータの収集
SIA セッション・インタフェースと,セキュア情報を変更するインタフェースでは,事前に定義されたパラメータ収集機能を使います。呼び出し元のアプリケーションは,パラメータ収集ルーチンのアドレスを,SIA を介して
siad_*()
ルーチンへ渡します。収集ルーチンは,ユーザ・インタフェースの詳細を意識することなく,さまざまなセキュリティ・メカニズムを使って,さまざまなパラメータの入力をユーザに求めることができます。
この機能により,SIA セキュリティ・メカニズムを,ユーザ・インタフェースや,簡単なフォームやメニューによる入力処理から独立させることができます。この収集機能には,各種のユーザ・インタフェース・パッケージやウィンドウ・システムで簡単に実装できるように,制限が設けられています。ただし,収集ルーチンは,簡単な (8 項目までの) メニューと,フォーム・スタイルの処理をサポートしていなければなりません。ダム端末では,フォーム処理は 1 行単位の質問のセットになります。この機能がないと,セキュリティ上の新しい質問をサポートするために,アプリケーションを変更する必要が生じます。
6.14 SIA 製品のパッケージ
SIA では,Tru64 UNIX システムへ移植するために必要なセキュリティ・メカニズム構成要素を定義しています。これらの構成要素は,次のとおりです。
メカニズムに依存する (siad_*()
) ルーチンを含むシェアード・ライブラリ。コマンドおよびユーティリティへのインタフェースとして使います。
省略時の構成ファイル
/etc/sia/matrix.conf
。このファイルは,SIA を介してセキュリティ・メカニズムを使うためにインストールされます。
シェアード・ライブラリには,表 6-3
で示すすべての
siad_*()
ルーチンが入っていなければなりません。siad_*()
ルーチン用の省略時のダミー・ルーチンは常に,失敗を示す SIADFAIL 応答を戻します。セキュリティ・メカニズムでダミー・ルーチンを用意している場合は,これらのルーチンを
matrix.conf
ファイルに構成しないでください。
/etc/sia/matrix.conf
ファイルには,各
siad_*()
ルーチンに対して行が 1 つあります。この行には,メカニズム識別子 (mech_types
と呼ぶ) とセキュリティ・メカニズム・ライブラリへの実際のパスを記述します。sia_*()
ルーチンは,この鍵のセットを使って,右から左の順番でメカニズムを呼び出します。Tru64 UNIX での
matrix.conf
の省略時の設定については,『セキュリティ管理ガイド』を参照してください。
DCE セキュリティ・メカニズムを最初に呼び出してから,BASE (BSD) セキュリティ・メカニズムを呼び出す場合は,siad_init()
の構成行は次のようになります。
siad_init=(DCE,/usr/shlib/libdcesia.so)(BSD,libc.so)
レイヤード・セキュリティ・プロダクトでは,事前にテストされた
matrix.conf
ファイルをキットに含めて配布しなければなりません。SIA の
matrix.conf
ファイルを変更したときには,リブートを行わなければなりません。システム管理者は,使用中の
matrix.conf
ファイルを手作業で編集してはなりません。
matrix.conf
ファイルについての詳細は,『セキュリティ管理ガイド』を参照してください。
6.15 セキュリティ・メカニズムに依存するインタフェース
セキュリティ・メカニズムには,すべての
siad_*()
エントリ・ポイントを用意する必要があります。表 6-3
を参照してください。省略時のスタブ・ルーチンでは,SIADFAIL を返す必要があります。セッション・ルーチンの場合を除き,/etc/sia/matrix.conf
ファイルではスタブを呼び出してはなりません。メカニズム・インデックス (mechind
) の一貫性を確保するために,すべてのセッション・ルーチンには,同じ順序で同じ数のメカニズムを記述する必要があります。ただし,構成に誤りがあった場合は,適切な SIADFAIL 応答をスタブ・ルーチンが戻します。
/etc/sia/matrix.conf
ファイル内のセキュリティ・メカニズムの順序は,どのクラスのインタフェースでも同じです。このため,セキュリティ・メカニズムがセッション処理をサポートしている場合は,セッション関連のすべてのインタフェースに対して,セキュリティ・メカニズムが同じ順序で呼び出されます。
レイヤード・セキュリティ・メカニズムでは,プレフィックスが
mechanism_name__
のプライベート・エントリ・ポイント群を,各
siad_*()
エントリに対して用意する必要があります。これらのエントリは,メカニズム内で
siad_*()
ルーチンを内部的に呼び出すために使用されます。この例は,libc
内の BASE メカニズム内にあります。BASE メカニズムが自身の
siad_getpwuid()
ルーチンを確実に呼び出すようにするには,別のエントリ・ポイントを作成し,siad_getpwuid()
エントリから次のようにこのエントリ・ポイントを呼び出します。
int siad_getpwuid(uid_t uid, struct passwd *result, \ char *buffer, int buflen) { return(bsd_siad_getpwuid(uid,result,buffer,buflen)); } static int bsd_siad_getpwuid(uid_t uid, struct passwd *result, \ char *buffer, int buflen) { /* The BSD security mechanism siad_getpwuid() routine */ }
この内部名が
siad_*()
エントリ・ポイントすべてに対して用意されている場合,レイヤード・セキュリティ・メカニズムは,セキュリティ・メカニズムに依存するコードすべてを別のライブラリとして作成することができます。これにより,構成されるシェアード・ライブラリは,別のライブリを呼び出すスタブだけになります。
セキュリティ・メカニズムは一般に,ローカル・メカニズムと分散メカニズムの 2 つのカテゴリに分けられます。ローカル・セキュリティ・メカニズムは,ローカル・システム上のセッションを確立するために必要なローカル・コンテキストすべてを確立する責任があります。Tru64 UNIX には,BASE メカニズムと ENHANCED メカニズムの 2 つのローカル・セキュリティ・メカニズムがあります。
DCE などの分散メカニズムは,Kerberos チケットなどの分散セッション・コンテキストの確立に深く関わります。ただし,分散セキュリティ・メカニズムも,ローカル・セキュリティ・メカニズムで使うことのできる,一部のローカル・コンテキストを提供することがあります。分散セキュリティ・メカニズムは,十分に強力な認証を提供することができるため,ローカル・メカニズムはこの認証に頼ることもできます。あるメカニズムが別のメカニズムを信頼するというこの概念は,保証と呼ばれます。この概念により,ログイン・セッションを確立するためのユーザの認証が,1 回だけで済みます。ローカル・メカニズムは必ず,呼び出し順序の最後に構成する必要があります。
この節で示した SIA 機能はすべて,複数のセキュリティ・メカニズムを使うように構成できます。
6.16 シングルユーザ・モード
独自のシングルユーザ・セキュリティ・モードが必要な場合は,影響を受けるコマンドおよびユーティリティ (たとえば,/sbin
にある,静的にリンクされたバイナリ) を再構築して置き換える必要があります。再構築および置き換えを行うには,影響を受けるコマンドのリンク順序として,siad_*()
ルーチンのライブラリを指定してから
libc
を指定します。
新しいルーチンでは,siad_*()
ルーチンではなく,_ _siad_*()
ルーチンを置き換える必要があります。siad_*()
形式の名前は弱いシンボルのエントリ・ポイントですが,_ _siad_*()
形式の名前は実際に使用される強いシンボルのエントリ・ポイントです。ルーチンの命名規則についての詳細は,6.17 節
を参照してください。
6.17 SIA ルーチンのシンボル優先使用
この節では,開発者が追加するルーチンを ANSI C ルーチンの命名規則に準拠させるためのルーチン命名規則について説明しています。
6.17.1 シンボル優先使用の問題の概要
libc.a
の前にロードされるライブラリに SIA ルーチンと同じ名前のルーチン (たとえば,siad_ses_init()
) を用意するだけでは,libc
内の SIA ルーチンが使用しているシンボルを無効にすることはできません。これは,ANSI C での
libc
のルーチン名の命名規則と,ユーザ用に予約されたシンボルのためです。
libc.a
ライブラリと
libc.so
ライブラリ内にどのようなエントリ・ポイントを置けるかについて,ANSI C の必要条件とアプリケーション開発者の要望に食い違いがあります。ANSI C 標準では,使用可能なシンボルをリストしています。そして,これらのシンボル以外を置くときには,「ベンダ用に予約された」形式でなければなりません。つまり,これらのシンボルは 2 つの下線で始まるか,1 つの下線と大文字で始まらなければなりません。これらのシンボルは制限されているので,一般的なユーザの要望には合っていません。
6.17.2 Tru64 UNIX での解決方法
ANSI C と開発者の要望の両方を満たすために,Tru64 UNIX では,「強い」シンボルおよび「弱い」シンボルを使って追加の名前を提供しています。たとえば,bcopy()
というルーチンが ANSI C で使用できない場合は,bcopy()
という名前の弱いシンボルと
_ _bcopy()
という名前の強いシンボルを用意します。
弱いシンボルは,libc
内の
bcopy()
ルーチンに影響することなく,ユーザが優先使用することができます。ライブラリでは,これらの「名前スペース保護」ルーチンに対して,強いシンボルを使うためです。
SIA ルーチンの場合,siad_ses_init
という名前の弱いシンボルがあり,通常は強いシンボル
_ _siad_ses_init()
にバインドされることを意味します。別のコードが既にシンボル
siad_ses_init()
を使っている場合,弱いシンボルのバインドだけが影響を受けます。
libc
内の SIA コードは,自分自身が使用する場合には,強いシンボル
_ _siad_ses_init()
を参照します。このため,シングルユーザ・モードの省略時の BASE セキュリティ・メカニズムを無効にするには,_ _siad_ses_init()
ルーチンを置き換えるルーチンを用意する必要があります。
SIA ルーチンと
/etc/sia/matrix.conf
ファイルの制御下で動的にのみロードされるライブラリの場合は,siad_ses_init()
形式のシンボル名だけを用意すれば済みます。動的にロードされるライブラリが必ず
matrix.conf
ファイルを介して使用される場合は,シンボルの両方の形式を提供することもできます。これにより,コードが簡略化されます。ただし,ライブラリの使い方が変って,動的なロードだけではなくリンクが必要になった場合は,安全ではなくなります。
6.17.3 シングルユーザ環境の置き換え
例 6-5
は,セキュリティ・メカニズム・ライブラリの開発者が,通常のシェアード・ライブラリを
matrix.conf
用に提供する他に,シングルユーザ環境を置き換える必要がある場合に使うコードを示しています。
例 6-5: シングルユーザ環境のシンボル優先使用
/* preempt libc.a symbols in single-user mode */ #ifdef SINGLE_USER # pragma weak siad_ses_init = _ _siad_ses_init # define siad_ses_init _ _siad_ses_init #endif #include <sia.h> #include <siad.h>
シングルユーザ (静的) ライブラリのモジュールは,その後,次のようにコンパイルされます。
% cc -DSINGLE_USER ...
これで,シェアード・ライブラリが
libc.so
のシンボルに干渉するのを防ぎますが,シングルユーザ・モードで使用する非共用イメージの
libc.a
のシンボルの優先使用を可能にします。そして,非共用イメージは次の例のように,リンカへのパラメータとして
libc.a
の前に置き換え版のメカニズム・ライブラリを指定して構築されます。
% cc -non_shared -o passwd passwd.o -ldemo_mech
シェアード・ライブラリは,通常の方法で構築されます。