|
この章で説明する手順を実行してみる前に、「PersonQuery サンプル アプリケーション」で解説した手順がすべて完了していることを確認してください。
InterceptorSec サンプル インターセプタにより、基本的なセキュリティ モデルを実装する単純なクライアント/サーバ インターセプタのペアが示されます。InterceptorSec クライアントサイド インターセプタは単に、ORB で処理される各クライアント要求をログに記録します。InterceptorSec ターゲットサイド インターセプタは、クライアント アプリケーションのユーザが要求のオペレーションの実行を認可されているかどうかを確認する、単純なセキュリティ メカニズムを実装します。
InterceptorSec サンプル インターセプタでは、単一の初期化関数で初期化され、単一のライブラリに実装された、クライアントおよびターゲット インターセプタのペアが示されます。単一の初期化関数が呼び出されるので、インターセプタ登録コマンドで登録されるのは初期化関数 1 つと実装ライブラリ 1 つです。
ターゲットサイド ORB で要求が受信されると、ORB は InterceptorSec ターゲットサイド インターセプタを呼び出し、クライアント要求からの RequestContext および DataInputStream オブジェクトを渡します。
ターゲットサイド インターセプタはその後、次の処理により、クライアント アプリケーションのユーザに対して要求に含まれるオペレーションの認可を行います。
INVOKE_NO_EXCEPTION を返します。PrimaryGroupId および AccessId と照合します。ユーザがこれら 2 つの属性の判定基準に問題なく一致していた場合、インターセプタは INVOKE_NO_EXCEPTION を返します。REPLY_EXCEPTION を返します。これにより、ターゲット オブジェクトへの要求の送信は回避されます。その代わりに、ORB はクライアント アプリケーションに例外を返します。
以降の節ではインターセプタのセキュリティについて説明し、InterceptorSec ターゲットサイド インターセプタの中から、該当するコードの抜粋部分を示します。
インターセプタは、Bootstrap オブジェクトではなく、ORB から SecurityCurrent オブジェクトを取得します。ORB から取得可能な SecurityCurrent オブジェクトには、インターセプタがクライアントの情報を取得するために必要とする API が含まれます。
インターセプタで ORB に対する resolve_initial_references(“SecurityCurrent”) オペレーションを呼び出すと、SecurityCurrent オブジェクトを取得できます。インターセプタは次に、SecurityCurrent リファレンスを SecurityCurrentLevel1 カレントにナロー変換します。
SecurityCurrent オブジェクトは、ORB からのみ取得可能です。このオブジェクトの主要な機能は、CORBA サーバ アプリケーションがクライアント呼び出し関連の属性にアクセスできるようにすることです。
ORB の resolve_initial_references(“SecurityCurrent”) メソッドは、インターセプタに SecurityCurrent オブジェクトのリファレンスを提供します。このオブジェクトから、インターセプタにレベル 1 のセキュリティ機能が与えられます。インターセプタは、SecurityCurrent オブジェクトの get_attributes メソッドを介してクライアント呼び出しの属性を取得します。このオブジェクトは、属性リストをインターセプタに返します。属性リストには、インターセプトされている呼び出しを実行したクライアント アプリケーションのユーザに関連する属性が含まれます。上記の例外を除けば、CORBA セキュリティ サービスからのどのメソッドの振る舞いも同じです。
次の C++ コードの抜粋では、SecurityCurrent オブジェクトの取得方法を示します。
try
{
sec_current = m_orb->resolve_initial_references("SecurityCurrent");
}
catch (...)
{
*m_outfile <<
"ERROR: ORB::resolve_initial_references threw exception"
<< endl << endl << flush;
excep_val = new CORBA::UNKNOWN();
return Interceptors::REPLY_EXCEPTION;
}
if (CORBA::is_nil(sec_current.in()))
{
*m_outfile << "ERROR: No SecurityCurrent present"
<< endl << endl << flush;
excep_val = new CORBA::NO_PERMISSION();
return Interceptors::REPLY_EXCEPTION;
}
m_security_current = SecurityLevel1::Current::_narrow(sec_current.in());
if (!m_security_current)
{
*m_outfile << "ERROR: Couldn't narrow security
current to SecurityLevel1::Current"
<< endl << endl << flush;
excep_val = new CORBA::NO_PERMISSION();
return Interceptors::REPLY_EXCEPTION;
}
この節のコード抜粋部分は、InterceptorSec ターゲットサイド インターセプタが、ユーザ属性のリストを作成し、その後このリスト内を調べて、ユーザが認可基準に適合しているかどうかを判定する方法を示します。
InterceptorSec サンプルでは、属性リストの作成と、そのリスト内容の検討は、個別の手順で行われます。長さ 0 のクライアント属性リストが返るように指定を行うと、SecurityCurrent オブジェクトはそのクライアントの全属性を返すことに注意してください。
// 認可チェックを行う必要のある情報に対応する
// 属性を取得する
// PrimaryGroupId (ログインしたクライアントのクライアント名)
// AccessId (ログインしたクライアントのユーザ名)
Security::AttributeList_var client_attr = 0;
try
{
client_attr = m_security_current->get_attributes(*m_attributes_to_get);
Security::AttributeTypeList_var attr = new Security::AttributeTypeList(2);
if (!attr.ptr())
{
cout <<
"ERROR: can't allocation security list: Out of memory"
<< endl << endl << flush;
return;
}
attr.inout().length(2);
attr[(CORBA::ULong)0].attribute_family.family_definer = 0;
attr[(CORBA::ULong)0].attribute_family.family = 1;
attr[(CORBA::ULong)0].attribute_type = Security::PrimaryGroupId;
attr[(CORBA::ULong)1].attribute_family.family_definer = 0;
attr[(CORBA::ULong)1].attribute_family.family = 1;
attr[(CORBA::ULong)1].attribute_type = Security::AccessId;
m_attributes_to_get = attr._retn();
return;
次の抜粋部分は、属性リストでユーザが認可基準に適合するかどうかを確認する方法を示します。
if (client_attr[i].attribute_type.attribute_type == Security::PrimaryGroupId)
{
//
// この属性はクライアント名。
// 何らかのクライアント名値と比較する。
// たとえば、「r」を含むすべての文字列か、
// NULL 文字列を受け入れるとする。その場合、クライアント名を、
// 認可済みの値のセットのどれかに比較する
//
if ((strlen(value_buffer) == 0) ||
(strchr(value_buffer, 'r') != 0))
{
*m_outfile << " INFO: Valid client name found: "
<< value_buffer << endl;
clientname_ok = 1;
}
else
{
*m_outfile << " ERROR: Invalid client name found: "
<< value_buffer << endl;
}
}
else if (client_attr[i].attribute_type.attribute_type == Security::AccessId)
{
// この属性はユーザ名。ユーザ ID 中に「r」、「n」
// または「p」が含まれるユーザであれば、任意に選択し、
// 認可する。別の認可基準を
// 選択することもできる
//
if ((strchr(value_buffer, 'r') != 0) ||
(strchr(value_buffer, 'R') != 0) ||
(strchr(value_buffer, 'P') != 0) ||
(strchr(value_buffer, 'p') != 0) ||
(strchr(value_buffer, 'N') != 0) ||
(strchr(value_buffer, 'n') != 0))
{
*m_outfile << " INFO: Valid username found: "
<< value_buffer << endl;
username_ok = 1;
}
「PersonQuery サンプル アプリケーション」の PersonQuery サンプル アプリケーションをビルドする makefile を実行すると、InterceptorSec インターセプタを含むサンプル インターセプタ一式全部が、同様にビルドされます。この節では、実行時に PersonQuery アプリケーションと共に機能するように InterceptorSec インターセプタを登録する方法を説明します。
InterceptorSec クライアント インターセプタおよびサーバ インターセプタを登録して実行するには、以下の手順に従います。
workdirectory は、「PersonQuery サンプル アプリケーション」に示す手順でインターセプタのサンプル アプリケーションをコピーしたディレクトリの名前を表します。> cd <workdirectory>\cxx\security_cxx$ cd <workdirectory>/cxx/security_cxx> nmake -f makefile.nt config
$ make -f makefile.mk config
> cd <workdirectory>\cxx\app_cxx
> tmboot -y
> PersonQueryClient
> cd <workdirectory>/cxx/app_cxx
> tmboot -y
> PersonQueryClient
> tmshutdown -y
InterceptorSec クライアント インターセプタおよびターゲット インターセプタは、指定されたファイルに出力のログを記録します。ファイル名はそれぞれ、InterceptorSecClientxxx.out および InterceptorSecTargetxxx.out です。これらのファイルには、インターセプタからのデバッグ出力が含まれます。これは PersonQuery アプリケーション用に、ORB によって自動的にロードおよび実行されます。
InterceptorSec サンプル インターセプタで PersonQuery サンプル アプリケーションを実行後に、次の手順でこれらのインターセプタの登録を解除できます。
> tmshutdown -y
workdirectory は、「PersonQuery サンプル アプリケーション」に示す手順でインターセプタのサンプル アプリケーションをコピーしたディレクトリの名前を表します。> cd <workdirectory>\cxx\security_cxx$ cd <workdirectory>/cxx/security_cxx> nmake -f makefile.nt unconfig
$ make -f makefile.mk unconfig
|