ここでは、次の内容について説明します。
この付録は、「アプリケーション例」で解説したアプリケーション例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クライアントからDCEゲートウェイ・プロセスに転送され、DCEゲートウェイ・プロセスがリクエストをDCEサーバーに送ります。この例をもう少し現実的なものとするため、ゲートウェイ・プロセスからDCEサーバーへの通信では、自動バインドと認証済みRPCのかわりに明示的バインディングを使用します。
以下に本プログラム例を構成、実行する手順を解説します。 クライアントは「アプリケーション例」で説明した、どのプラットフォーム上でも実行できます。 クライアントの構築や実行の方法は同じなので、この章ではこれ以上の説明は行いません。 ゲートウェイとDCEサーバーは、DCEソフトウェアがインストールされたPOSIXプラットフォームで実行する必要があります。 この付録では、ワークステーション・プラットフォーム上でのクライアントのインストールやコンパイルについては説明しません。
このサンプル・プログラムはOSF/DCE準拠のソフトウェアを組み込んだプラットフォームで動作します。
以下のステップは、サンプル・アプリケーションのインストール、構成、実行を行う方法を示しています。
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のディレクトリ構造内のファイルにアクセスし、Oracle Tuxedoコマンドを実行するのに必要です。 構成ファイルがロードできるようにするには、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 $
(このセクションで参照しない一部のファイルは省略しています。)
アプリケーションを構成するファイルは次のセクションで説明します。 「アプリケーション例」で説明したファイル、client.c
、simp.idl
、ubbconfig
については、ここでは解説しません。
「付録A」の例で用いた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の構成」の項に示します。
サンプル・コードB-2 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サーバー・スタブによって呼び出され、DCEクライアント・スタブを呼び出します。 構造体のデータ型はsimpdce.h
で定義され、dceepv.c
にインクルードされます。またデータ型は、ローカル関数myto_upper()
とmyto_lower()
によって初期化されます。 これらの関数はそれぞれdobind()
を呼び出して、認証済みRPCのためにアノテーションが付けられたバインド・ハンドルを取得し、関連するクライアント・スタブ関数を呼び出します。
サンプル・コードB-3 dcemgr.c
#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アプリケーションに参加し、終了する前にtpterm
()を呼び出します。 これは、プロセスがDCEサーバーおよびOracle Tuxedoクライアントになるような、DCEからOracle Tuxedoに渡される呼出し用のDCEゲートウェイとして使用されます。
-DTPSVRINIT
でコンパイルすると、このファイルは、次の作業行うOracle Tuxedoサーバーのためにtpsvrinit
() (argc
とargv
サーバー・コマンドライン・オプションを持ちます)を生成します。
サーバー・キー表内の情報を使用して、プリンシパル用のDCEログインの確立。
認証情報の登録。
サーバーに関連付けられたリソース・マネージャを開くためのtx_open
の呼出し。
このプログラムは、コマンドライン・オプションを調べ、それらを使用するように修正できます。
これらの各事例で、ログイン・コンテキストはestablish_identity
を呼び出すことで確立されますが、このestablish_identityは、サーバーのネットワーク識別子を取得し、キー表ファイル内のサーバーのシークレット・キーを使用して識別子を解除し、プロセスのログイン・コンテキストを設定します。2つのスレッドが開始されます。最初のスレッドは有効期限が切れる前にログイン・コンテキストを最新状態にリフレッシュし、もう一つのスレッドはサーバーのシークレット・キーを定期的に変更します。
サンプル・コードB-4 rpcsimp.mk
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を少し書き直せば、クライアントは「アプリケーション例」の場合と同じ方法で構築できます。 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
をインクルードすることで構築されます。
ASCIIのubbconfig
構成ファイルは、「アプリケーション例」の説明どおりに変更する必要があります。 このステップは必須です。
また*SERVERS
セクションでは、シャープ記号(#
)を行の先頭に付け"server
"行をコメント文にし、 dceserver
行ではコメント文の指定を解除します。
ソフトウェアを構築する前に、上記で説明した様にrpcsimp.mk
を修正してDCEサーバーを構築するために正しいオプションとライブラリを設定する必要があります。
次のコマンドを実行してクライアントとサーバー・プログラムを構築します。
make -f rpcsimp.mk TUXDIR=$TUXDIR all2
上記で説明したアプリケーション例を実行するためのDCEエンティティの設定手順を次に示します。すべての文字が大文字で表される識別子は、使用する環境に応じてカスタマイズ化します。
すでに独自のDCEプリンシパルを持っている場合は、MYGROUP
やMYPRINCIPAL
、または関連するアカウントを作成する必要はありません。
この例では、cell_admin
パスワードはデフォルトの-dce
と想定していますが、 このパスワードは必要に応じて変更できます。
サーバーはOracle Tuxedo管理者として起動し、サーバー・キー表の読取りが行える必要があるので、SERVER_PRINCIPAL
はOracle Tuxedo管理者の識別子と同じにします。
サンプル・コードB-5 DCE構成
$ 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
SERVER_PRINCIPAL
(サーバー・キー表のオーナー)としてログインします。
次のコマンドを実行してDCEサーバーを起動します。
dceserver &
DCEサーバーは、リクエストのリスニングを開始する前に「Server ready」
というメッセージを表示します。
次のコマンドを実行してOracle Tuxedo ATMIアプリケーションを起動します。
tmboot -y