この付録は、
付録A「アプリケーション例」で説明した
rcpsimpアプリケーションをベースにして作成されています。サーバーはOSF/DCEサーバーに変更され、またゲートウェイが使用されるので、Oracle Tuxedo ATMIクライアントは明示的バインドと認証済RPCを使用してサーバーと通信できます。この対話型アプリケーションのソース・ファイルは、Oracle Tuxedo ATMIソフトウェア開発キットに付属しています。
このトピックではDCEに関する知識が必要ですが、このドキュメントにはDCEチュートリアルは含まれていません。参考文献として『Guide to Writing DCE Applications』(John Shirley、O'Reilly and Associates, Inc.)を参照してください。
このアプリケーションは、アプリケーション例
rpcsimpの拡張版です。「付録A」の場合と同様に、クライアントはリモート・プロシージャ・コール(オペレーション)
to_upper()と
to_lower()を呼び出します。
この例では、RPCはOracle Tuxedo ATMIクライアントからDCEゲートウェイ・プロセスに転送され、DCEゲートウェイ・プロセスがリクエストをDCEサーバーに送ります。この例をもう少し現実的なものとするため、ゲートウェイ・プロセスからDCEサーバーへの通信では、自動バインドと認証済RPCのかわりに明示的バインディングを使用します。
次に本プログラム例を構成、実行する手順を解説します。クライアントは
付録A「?$paratext>.?」で説明した、どのプラットフォーム上でも実行できます。クライアントの構築や実行の方法は同じであるため、この章ではこれ以上の説明は行いません。ゲートウェイとDCEサーバーは、DCEソフトウェアがインストールされたPOSIXプラットフォームで実行する必要があります。この付録では、ワークステーション・プラットフォーム上でのクライアントのインストールやコンパイルについては説明しません。
このサンプル・プログラムはOSF/DCE準拠のソフトウェアを組み込んだプラットフォームで動作します。
rpcsimpアプリケーションのインストール、構成、実行
次のステップは、サンプル・アプリケーションのインストール、構成、実行を行う方法を示しています。
rpcsimp用のディレクトリを作成し、そのディレクトリに移動します。
mkdir rpcsampdir
cd rpcsampdir
注意:
|
このようにしておくと、作業開始時にあった rpcsimp関連のファイルと、作業中に作成した新たなファイルを容易に把握できます。標準シェル( /bin/sh)またはKornシェルを使用してください。Cシェル( csh)は使わないでください。
|
TUXDIR=<
pathname of the Oracle Tuxedo root directory>
TUXCONFIG=
<pathname of your present working directory>/tuxconfig
PATH=$PATH:$TUXDIR/bin
# SVR4, Unixware
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib
# HPUX
SHLIB_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib
# RS6000
LIBPATH=$LD_LIBRARY_PATH:$TUXDIR/lib
export TUXDIR TUXCONFIG PATH LD_LIBRARY_PATH SHLIB_PATH LIBPATH
TUXDIRと
PATHは、Oracle Tuxedo ATMIのディレクトリ構造内のファイルにアクセスし、Oracle Tuxedo ATMIコマンドを実行するのに必要です。構成ファイルがロードできるようにするには、
TUXCONFIGを設定する必要があります。共有オブジェクトを使用する場合、
LD_LIBRARY_PATH環境変数も設定します。
rpcsimp用のファイルをアプリケーション・ディレクトリにコピーします。
cp $TUXDIR/apps/rpcsimp/* .
一部のファイルを編集してから、実行形式ファイルを作成することがあるので、本ソフトウェアで提供されたオリジナルのファイルではなく、コピーしたファイルを用いて作業することをお薦めします。
$ ls
client.c
dcebind.c
dceepv.c
dcemgr.c
dceserver.c
rpcsimp.mk
simp.idl
simpdce.acf
ubbconfig
$
(このセクションで参照しない一部のファイルは省略しています。)
アプリケーションを構成するファイルは次のセクションで説明します。
付録A「?$paratext>,?」で説明したファイル、
client.c、
simp.idlおよび
ubbconfigについては、ここでは解説しません。
IDL ACFファイル - simpdce.acf
[explicit_handle]interface changecase
{
}
前述の例で使用した
simp.idl ファイルは、ゲートウェイとDCEサーバーの構築に使用されます。しかし、simp.idlファイルはDCEコンパイラとOracle TuxedoのIDLコンパイラの両方でコンパイルされるために、2つの
simp.hヘッダー・ファイルが同じ名前で作成されます。また、クライアントにではなく、サーバーに明示的バインドを指定できるように、この例ではACFファイルを使用しています。バインドを指定しないTxRPC用のものと、明示的ハンドルをもつDCE/RPC用のものを使用して、同一ディレクトリ内で第2のファイル名にIDLファイルをリンクすることをお薦めします。この場合、
simp.idlは
simpdce.idlに名前が変更され、また関連するACFファイルは
simpdce.acfになります。Makefileは
simpdce.idlを作成し、さらにIDLコンパイラを実行するときに
simpdce.acfも検索します。インタフェースのすべてのオペレーションが明示的ハンドルを使用することを示すために、ACFファイルが使用されている点に注意してください。第1パラメータとして[handle]パラメータを指定せずにオペレーションがIDLファイル内で定義されているので、1つのオペレーションが自動的に関数プロトタイプとスタブ関数呼出しに追加されます。
ここではページ数の制限から
dcebind.c用のソース・コードは示していませんが、
$TUXDIR/apps/rpcsimpにあります。
このファイルには次の3種類の作業を行う関数、
dobind()が含まれます。
•
|
目的のインタフェース仕様でDCEサーバー用のバインド・ハンドルを取得し、さらに完全に解決されたハンドルの関連するエンドポイントを取得します。
|
•
|
サーバーのプリンシパル名を取得し、セキュリティ・レジストリをチェックしてプリンシパルが指定されたグループのメンバーであるかどうか判別することによって、サーバーの認証をある程度行います。
|
•
|
認証済RPCが実行されるようバインド・ハンドルにアノテーションを付けます。保護レベルは、DCE秘密鍵による認証とDCE PACを基本とした認可を使用するパケット・レベルの整合性(パケット・チェックサム checksumによる呼出しごとの相互認証)です。
|
dcebind.cでは次の事項を修正する必要があります。
•
|
< HOST>は、DCEサーバーが実行されるホスト・マシンの名前に変更する必要があります。これはディレクトリに格納されるサービス名の一部で、サービス名は _hostで終わるという規約に従っています。完全に接尾辞を取り除くこともできます(削除する場合は、 dceserver.cでも同じ変更を行う必要があります)。
|
•
|
< SERVER_PRINCIPAL_GROUP>は、サーバーを実行するDCEプリンシパルに関連付けられたグループに変更する必要があります。これは相互認証の一部として使用されます。
|
•
|
cell_adminとして rgy_editを実行してサーバー・プリンシパル・グループを作成します。サーバー・プリンシパルを作成し、グループを持つプリンシパルにアカウントを追加して、サーバーにキー表を作成します。クライアントを実行するためには、ユーザー自身のプリンシパルとアカウントも作成します。これらのDCEエンティティを生成するスクリプト例をステップ8の「DCEの構成」の項に示します。
|
エントリ・ポイント・ベクトル - dceepv.c
#include <simpdce.h> /* header generated by IDL compiler */
#include <dce/rpcexc.h> /* RAISE macro */
static void myto_upper(rpc_binding_handle_t hdl, idl_char *str);
static void myto_lower(rpc_binding_handle_t hdl, idl_char *str);
/*
* A manager entry point vector is defined so that we can generate
* a valid DCE binding handle to go to the DCE server.
* Note that the input handle to entry point functions will always
* be NULL since Tuxedo TxRPC doesn't support handles.
*/
/* Manager entry point vector with two operations */
changecase_v1_0_epv_t changecase_v1_0_s_epv = {
myto_upper,
myto_lower
};
int dobind(rpc_binding_handle_t *hdl);
void
myto_upper(rpc_binding_handle_t hdl, idl_char *str)
{
rpc_binding_handle_t handle;
if (dobind(&handle) 0) { /* get binding handle for server */
userlog("binding failed");
RAISE(rpc_x_invalid_binding);
}
to_upper(handle, str); /* call DCE client stub */
}
void
myto_lower(rpc_binding_handle_t hdl, idl_char *str)
{
rpc_binding_handle_t handle;
if (dobind(&handle) 0) { /* get binding handle for server */
userlog("binding failed");
RAISE(rpc_x_invalid_binding);
}
to_lower(handle, str); /* call DCE client stub */
}
dceepv.cにはゲートウェイで使用されるマネージャ・エントリ・ポイント・ベクトルが含まれます。マネージャ・エントリ・ポイント・ベクトルはOracle Tuxedo ATMIサーバー・スタブによって呼び出され、DCEクライアント・スタブを呼び出します。構造体のデータ型は
simpdce.hで定義され、
dceepv.cにインクルードされます。またデータ型は、ローカル関数
myto_upper()と
myto_lower()によって初期化されます。これらの関数はそれぞれ
dobind()を呼び出して、認証済RPCのためにアノテーションが付けられたバインド・ハンドルを取得し、関連するクライアント・スタブ関数を呼び出します。
#include <stdio.h>
#include <ctype.h>
#include "simpdce.h" /* header generated by IDL compiler */
#include <dce/rpcexc.h> /* RAISE macro */
#include <dce/dce_error.h> /* required to call dce_error_inq_text */
#include <dce/binding.h> /* binding to registry */
#include <dce/pgo.h> /* registry i/f */
#include <dce/secidmap.h> /* translate global name -> princ name */
void
checkauth(rpc_binding_handle_t handle)
{
int error_stat;
static unsigned char error_string[dce_c_error_string_len];
sec_id_pac_t *pac; /* client pac */
unsigned_char_t *server_principal_name; /* requested server principal */
unsigned32 protection_level; /* protection level */
unsigned32 authn_svc; /* authentication service */
unsigned32 authz_svc; /* authorization service */
sec_rgy_handle_t rgy_handle;
error_status_t status;
/*
* Check the authentication parameters that the client
* selected for this call.
*/
rpc_binding_inq_auth_client(
handle, /* input handle */
(rpc_authz_handle_t *)&pac, /* returned client pac */
&server_principal_name, /* returned requested server princ */
&protection_level, /* returned protection level */
&authn_svc, /* returned authentication service */
&authz_svc, /* returned authorization service */
&status);
if (status != rpc_s_ok) {
dce_error_inq_text(status, error_string, &error_stat);
fprintf(stderr, "%s %s\n", "inq_auth_client failed",
error_string);
RAISE(rpc_x_invalid_binding);
return;
}
/*
* Make sure that the caller has specified the required
* level of protection, authentication, and authorization.
*/
if (protection_level != rpc_c_protect_level_pkt_integ ||
authn_svc != rpc_c_authn_dce_secret ||
authz_svc != rpc_c_authz_dce) {
fprintf(stderr, "not authorized");
RAISE(rpc_x_invalid_binding);
return;
}
return;
}
void
to_upper(rpc_binding_handle_t handle, idl_char *str)
{
idl_char *p;
checkauth(handle);
/* Any ACL or reference monitor checking could be done here */
/* Convert to upper case */
for (p=str; *p != '\0 '; p++)
*p = toupper((int)*p);
return;
}
void
to_lower(rpc_binding_handle_t handle, idl_char *str)
{
idl_char *p;
checkauth(handle);
/* Any ACL or reference monitor checking could be done here */
/* Convert to lower case */
for (p=str; *p != '\0 '; p++)
*p = tolower((int)*p);
return;
}
dcemgr.cにはDCEサーバー用のマネージャ・コードがあります。
checkauth()関数は、クライアントの認証(保護、認証、認可のレベル)を検査するユーティリティ関数です。各オペレーション、
to_upperおよび
to_lowerはこの関数を呼び出してクライアントの妥当性を検査し、次にオペレーション自体を実行します。アクセス制御リストを使用するアプリケーションでは、ACL検査は認証検査の後、オペレーションの実行の前に行われます。
ここではページ数の制限から
dceserver.c用のソース・コードは示しません。使用する環境に応じて、このファイルにはいくつか修正を加える必要があります。
•
|
<HOST>は、DCEサーバーが実行されるホスト・マシンの名前に変更する必要があります。これはディレクトリに格納されるサービス名の一部で、サービス名は _hostで終わるという規約に従っています。完全に接尾辞を取り除くこともできます(削除する場合は、 dcebind.cでも同じ変更を行う必要があります)。
|
•
|
<DIRECTORY>は、サーバー・キー表を作成するディレクトリのフルパス名を設定する必要があります。次のコマンドを実行すると、キー表が作成されます。
|
rgy_edit
ktadd -p
SERVER_PRINCIPAL -pw
PASSWORD -f
SERVER_KEYTAB
q
ここで、
SERVER_PRINCIPALは、サーバーが実行されるDCEプリンシパル、
PASSWORDはプリンシパルに関連付けられたパスワード、
SERVER_KEYTABはサーバー・キー表の名前です。
<PRINCIPAL>は、サーバーが実行されるDCEプリンシパルの名前に変更する必要があります。
ANNOTATIONは、アノテーションがサーバー用のディレクトリ・エントリに保存されるように変更できます。
dceserver.cは、実際にはアプリケーションで2回使用されます。1回はDCEサーバー用の
main()として使用され、もう1回はDCEゲートウェイ用の
tpsvrinit() (makefileで
gwinit.cにリンクされ、
DTPSVRINITを使用してコンパイルされます)として使用されます。
特別なマクロ定義を指定しないでコンパイルすると、このファイルは、次の作業を行うDCEサーバーのための
main() (
argcと
argvコマンド行オプションを持ちます)を生成します。
•
|
サーバー表内の情報による、サーバー・プリンシパル用のDCEログイン・コンテキストの確立
|
•
|
バインドの取得と、エンドポイント・マップ内への情報の登録
|
•
|
バインド情報のディレクトリ・ネームスペースへのエクスポート
|
•
|
ネームスペース内のグループへの名前の追加(オプション)
|
•
|
rpc_server_listenが復帰した後のクリーンアップ
|
このプログラムは、コマンド行オプションを調べ、それらを使用するように修正できます。
-
DTCLIENTでコンパイルすると、このファイルは前述のように
main()を生成しますが、
tpinit()を呼び出してクライアントとしてOracle Tuxedo ATMIアプリケーションに参加し、終了する前に
tpterm()を呼び出します。これは、プロセスがDCEサーバーおよびOracle Tuxedo ATMIクライアントになるような、DCEからOracle Tuxedoに渡される呼出し用のDCEゲートウェイとして使用されます。
-
DTPSVRINITでコンパイルすると、このファイルは、次の作業行うOracle Tuxedoサーバーのために
tpsvrinit() (
argcと
argvサーバー・コマンド行オプションを持ちます)を生成します。
•
|
サーバー・キー表内の情報を使用して、プリンシパル用のDCEログインの確立。
|
•
|
サーバーに関連付けられたリソース・マネージャを開くための tx_openの呼出し。
|
このプログラムは、コマンド行オプションを調べ、それらを使用するように修正できます。
これらの各事例で、ログイン・コンテキストは
establish_identityを呼び出すことで確立されますが、このestablish_identityは、サーバーのネットワーク識別子を取得し、キー表ファイル内のサーバーのシークレット・キーを使用して識別子を解除し、プロセスのログイン・コンテキストを設定します。最初のスレッドは有効期限が切れる前にログイン・コンテキストを最新状態に更新し、もう一つのスレッドはサーバーのシークレット・キーを定期的に変更します。
CC=cc
CFLAGS=
TIDL=$(TUXDIR)/bin/tidl
LIBTRPC=-ltrpc
all: client server
# Tuxedo client
client: simp.h simp_cstub.o
CC=$(CC) CFLAGS=$(CFLAGS) $(TUXDIR)/bin/buildclient -oclient \
-fclient.c -fsimp_cstub.o -f$(LIBTRPC)
#
# OMIT Tuxedo server
#
# Tuxedo Gateway example
# Uses Tuxedo client above plus a gateway server and a DCE server
#
#
# Alpha FLAGS/LIBS
#DCECFLAGS=-D_SHARED_LIBRARIES -Dalpha -D_REENTRANT -w -I. \
-I/usr/include/dce -I$(TUXDIR)/include
#DCELIBS=-ldce -lpthreads -lc_r -lmach -lm
#
#
# HPUX FLAGS/LIBS
#DCECFLAGS=-Aa -D_HPUX_SOURCE -D_REENTRANT -I. \
-I/usr/include/reentrant -I${TUXDIR}/include
#DCELIBS=-Wl,-Bimmediate -Wl,-Bnonfatal -ldce -lc_r -lm
#
IDL=idl
ALL2=client simpgw dceserver
all2: $(ALL2)
# TUXEDO-to-DCE Gateway
simpdce.idl: simp.idl
rm -f simpdce.idl
ln simp.idl simpdce.idl
gwinit.c: dceserver.c
rm -f gwinit.c
ln dceserver.c gwinit.c
gwinit.o: gwinit.c
$(CC) -c $(DCECFLAGS) -DTPSVRINIT gwinit.c
dceepv.o: dceepv.c simpdce.h
$(CC) -c $(DCECFLAGS) dceepv.c
dcebind.o: dcebind.c simpdce.h
$(CC) -c $(DCECFLAGS) dcebind.c
simpgw: simpdce.idl gwinit.o dcebind.o dceepv.o
blds_dce -i -no_mepv -o simpgw -f -g -f gwinit.o -f \
dcebind.o -f dceepv.o simpdce.idl
# DCE server
simpdce_sstub.o simpdce.h: simpdce.idl
$(IDL) -client none -keep object simpdce.idl
dceserver.o: dceserver.c simpdce.h
$(CC) -c $(DCECFLAGS) dceserver.c
dcemgr.o: dcemgr.c simpdce.h
$(CC) -c $(DCECFLAGS) dcemgr.c
dceserver: simpdce_sstub.o dceserver.o dcemgr.o
$(CC) dceserver.o simpdce_sstub.o dcemgr.o -o dceserver \
$(DCELIBS)
# Cleanup
clean::
rm -f *.o server $(ALL2) ULOG.* TUXCONFIG
rm -f stderr stdout *stub.c *.h simpdce.idl gwinit.c
clobber: clean
makefileは実行可能クライアント、ゲートウェイ、DCEサーバー・プログラムを構築します。
このソフトウェアを構築する前に、
rpcsimp.mkを修正してDCEサーバーを構築するための正しいオプションとライブラリを設定する必要があります。前述で示したように、makefileには複数のプラットフォームに対応した設定が含まれています。使用しているプラットフォームに応じて、該当する
DCECFLAGSと
DCELIBS変数ペアのコメント文指定を解除します(シャープ記号を削除します)。異なるプラットフォームを使用しているのであれば、独自の定義を追加します。
makefileを少し書きなおすことにより、クライアントは
付録A「?$paratext>.?」の場合と同じ方法で構築できます。
simpdce.idlを
blds_dceに渡すことでDCEゲートウェイが構築され、blds_dceはDCEに対してゲートウェイとして機能するOracle Tuxedo ATMIサーバーを構築します。
gwinit.o (-
DTPSVRINITでコンパイルされた
dceserver.c)、
dobind.o (DCEサーバー用のバインド・ハンドルを取得)、
dceepv.o (マネージャ・エントリ・ポイント・ベクトル)も含まれています。IDLコンパイラが独自のマネージャ・エントリ・ポイント・ベクトルを生成しないよう、
-i -no_mepv が指定されることに注意してください。DCEサーバーは、DCE IDLコンパイラで
simpdce.idlをコンパイルし、
dceserver.oと
dcemgr.oをインクルードすることで構築されます。
2.
|
SERVERSセクションでは、シャープ記号( #)を行の先頭に付けて server行をコメント文にします。( dceserver行ではコメント文の指定を解除します。)
|
1.
|
ソフトウェアを構築する前に、前述で説明したように rpcsimp.mkを修正してDCEサーバーを構築するために正しいオプションとライブラリを設定する必要があります。
|
2.
|
次のコマンドを実行してクライアントとサーバー・プログラムを構築します。
|
make -f rpcsimp.mk TUXDIR=$TUXDIR all2
次のコマンドを実行してバイナリの
TUXCONFIG構成ファイルをロードします。
前述で説明したアプリケーション例を実行するためのDCEエンティティの設定手順を次に示します。すべての文字が大文字で表される識別子は、使用する環境に応じてカスタマイズ化します。
•
|
すでに独自のDCEプリンシパルを持っている場合は、 MYGROUPや MYPRINCIPAL、または関連するアカウントを作成する必要はありません。
|
•
|
この例では、 cell_adminパスワードはデフォルトの -dceと想定しています。 (このパスワードは必要に応じて変更できます。)
|
•
|
サーバーはOracle Tuxedo管理者として起動し、サーバー・キー表の読取りが行える必要があるので、 SERVER_PRINCIPALはOracle Tuxedo管理者の識別子と同じにします。
|
$ dce_login cell_admin -dce-
$ rgy_edit
> domain group
> add SERVER_PRINCIPAL_GROUP
> add MYGROUP
> domain principal
> add SERVER_PRINCIPAL
> add MYPRINCIPAL
> domain account
> add SERVER_PRINCIPAL -g SERVER_PRINCIPAL_GROUP -o none -pw \
SERVERPASSWORD -mp -dce-
> add MYPRINCIPAL -g MYGROUP -o none -pw MYPASSWORD -mp -dce-
> ktadd -p SERVER_PRINCIPAL -pw SERVERPASSWORD -f SERVER_KEYTAB
> q
$ chown SERVER_PRINCIPAL SERVER_KEYTAB
$ chmod 0600 SERVER_KEYTAB
1.
|
SERVER_PRINCIPAL (サーバー・キー表のオーナー)としてログインします。
|
2.
|
次のコマンドを実行してDCEサーバーを起動します。
|
DCEサーバーは、リクエストのリスンを開始する前に
「Server ready」というメッセージを表示します。
3.
|
次のコマンドを実行してOracle Tuxedo ATMIアプリケーションを起動します。
|
変換する文字列を指定してクライアント・プログラムを実行できます。変換する文字列は省略できます。クライアント・プログラムは、まず文字列を大文字に変換し、この後小文字に変換します。
$ client HeLlO
to_upper returns: HELLO
to_lower returns: hello
$
1.
|
次のコマンドを実行して、アプリケーションを停止します。
|
次のコマンドを入力して、作成したファイルを削除します。