ヘッダーをスキップ
TxRPCを使用したOracle Tuxedoアプリケーションのプログラミング
  目次へ移動
目次

前
 
 

B DCEゲートウェイ・アプリケーション

このトピックには次の項が含まれます:

この付録の内容

この付録は、付録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.)を参照してください。

DCEゲートウェイ・アプリケーションとは

このアプリケーションは、アプリケーション例rpcsimpの拡張版です。「付録A」の場合と同様に、クライアントはリモート・プロシージャ・コール(オペレーション) to_upper()とto_lower()を呼び出します。

この例では、RPCはOracle Tuxedo ATMIクライアントからDCEゲートウェイ・プロセスに転送され、DCEゲートウェイ・プロセスがリクエストをDCEサーバーに送ります。この例をもう少し現実的なものとするため、ゲートウェイ・プロセスからDCEサーバーへの通信では、自動バインドと認証済RPCのかわりに明示的バインディングを使用します。

次に本プログラム例を構成、実行する手順を解説します。クライアントは付録A「アプリケーション例」で説明した、どのプラットフォーム上でも実行できます。クライアントの構築や実行の方法は同じであるため、この章ではこれ以上の説明は行いません。ゲートウェイとDCEサーバーは、DCEソフトウェアがインストールされたPOSIXプラットフォームで実行する必要があります。この付録では、ワークステーション・プラットフォーム上でのクライアントのインストールやコンパイルについては説明しません。

このサンプル・プログラムはOSF/DCE準拠のソフトウェアを組み込んだプラットフォームで動作します。

rpcsimpアプリケーションのインストール、構成、実行

次のステップは、サンプル・アプリケーションのインストール、構成、実行を行う方法を示しています。

ステップ1:アプリケーション・ディレクトリの作成

rpcsimp用のディレクトリを作成し、そのディレクトリに移動します。

mkdir rpcsampdir
cd rpcsampdir

注:

このようにしておくと、作業開始時にあったrpcsimp関連のファイルと、作業中に作成した新たなファイルを容易に把握できます。標準シェル(/bin/sh)またはKornシェルを使用してください。Cシェル(csh)は使わないでください。

ステップ2:環境の設定

必要な環境変数を設定し、エクスポートします。

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

TUXDIRPATHは、Oracle Tuxedo ATMIのディレクトリ構造内のファイルにアクセスし、Oracle Tuxedo ATMIコマンドを実行するのに必要です。構成ファイルがロードできるようにするには、TUXCONFIGを設定する必要があります。共有オブジェクトを使用する場合、LD_LIBRARY_PATH環境変数も設定します。

ステップ3:ファイルのコピー

rpcsimp用のファイルをアプリケーション・ディレクトリにコピーします。

cp $TUXDIR/apps/rpcsimp/* .

一部のファイルを編集してから、実行形式ファイルを作成することがあるので、本ソフトウェアで提供されたオリジナルのファイルではなく、コピーしたファイルを用いて作業することをお薦めします。

ステップ4:ファイルの一覧表示

ファイルを一覧表示します。

$ ls
client.c
dcebind.c
dceepv.c
dcemgr.c
dceserver.c
rpcsimp.mk
simp.idl
simpdce.acf
ubbconfig
$

(このセクションで参照しない一部のファイルは省略しています。)

アプリケーションを構成するファイルは次のセクションで説明します。「アプリケーション例」で説明したファイル、client.csimp.idlubbconfigについては、ここでは解説しません。

IDL ACFファイル - simpdce.acf

サンプル・コードB-1 simpdce.acf

[explicit_handle]interface changecase
{
}

「付録A」の例で用いたsimp.idlファイルは、ゲートウェイとDCEサーバーの構築に使用されます。しかし、simp.idlファイルはDCEコンパイラとOracle TuxedoのIDLコンパイラの両方でコンパイルされるために、2つのsimp.hヘッダー・ファイルが同じ名前で作成されます。また、クライアントにではなく、サーバーに明示的バインドを指定できるように、この例ではACFファイルを使用しています。バインドを指定しないTxRPC用のものと、明示的ハンドルをもつDCE/RPC用のものを使用して、同一ディレクトリ内で第2のファイル名にIDLファイルをリンクすることをお薦めします。この場合、simp.idlsimpdce.idlに名前が変更され、また関連するACFファイルはsimpdce.acfになります。Makefileはsimpdce.idlを作成し、さらにIDLコンパイラを実行するときにsimpdce.acfも検索します。インタフェースのすべてのオペレーションが明示的ハンドルを使用することを示すために、ACFファイルが使用されている点に注意してください。第1パラメータとして[handle]パラメータを指定せずにオペレーションがIDLファイル内で定義されているので、1つのオペレーションが自動的に関数プロトタイプとスタブ関数呼出しに追加されます。

関数のバインド - dcebind.c

ここではページ数の制限から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

サンプル・コード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 ATMIサーバー・スタブによって呼び出され、DCEクライアント・スタブを呼び出します。構造体のデータ型はsimpdce.hで定義され、dceepv.cにインクルードされます。またデータ型は、ローカル関数myto_upper()myto_lower()によって初期化されます。これらの関数はそれぞれdobind()を呼び出して、認証済RPCのためにアノテーションが付けられたバインド・ハンドルを取得し、関連するクライアント・スタブ関数を呼び出します。

DCEマネージャ - dcemgr.c

サンプル・コード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検査は認証検査の後、オペレーションの実行の前に行われます。

DCEサーバー - dceserver.c

ここではページ数の制限から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() (argcargvコマンド行オプションを持ちます)を生成します。

  • インタフェースの登録

  • サーバー・バインド情報とエンドポイントの作成

  • サーバー表内の情報による、サーバー・プリンシパル用のDCEログイン・コンテキストの確立

  • 認証情報の登録

  • バインドの取得と、エンドポイント・マップ内への情報の登録

  • バインド情報のディレクトリ・ネームスペースへのエクスポート

  • ネームスペース内のグループへの名前の追加(オプション)

  • リクエストのリスニング

  • rpc_server_listenが復帰した後のクリーンアップ

このプログラムは、コマンド行オプションを調べ、それらを使用するように修正できます。

-DTCLIENTでコンパイルすると、このファイルは前述のようにmain()を生成しますが、tpinit()を呼び出してクライアントとしてOracle Tuxedo ATMIアプリケーションに参加し、終了する前にtpterm()を呼び出します。これは、プロセスがDCEサーバーおよびOracle Tuxedo ATMIクライアントになるような、DCEからOracle Tuxedoに渡される呼出し用のDCEゲートウェイとして使用されます。

-DTPSVRINITでコンパイルすると、このファイルは、次の作業行うOracle Tuxedoサーバーのためにtpsvrinit() (argcargvサーバー・コマンド行オプションを持ちます)を生成します。

  • サーバー・キー表内の情報を使用して、プリンシパル用のDCEログインの確立。

  • 認証情報の登録

  • サーバーに関連付けられたリソース・マネージャを開くためのtx_openの呼出し。

このプログラムは、コマンド行オプションを調べ、それらを使用するように修正できます。

これらの各事例で、ログイン・コンテキストはestablish_identityを呼び出すことで確立されますが、このestablish_identityは、サーバーのネットワーク識別子を取得し、キー表ファイル内のサーバーのシークレット・キーを使用して識別子を解除し、プロセスのログイン・コンテキストを設定します。最初のスレッドは有効期限が切れる前にログイン・コンテキストを最新状態に更新し、もう一つのスレッドはサーバーのシークレット・キーを定期的に変更します。

Makefile - rpcsimp.mk

サンプル・コード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には複数のプラットフォームに対応した設定が含まれています。使用しているプラットフォームに応じて、該当するDCECFLAGSDCELIBS変数ペアのコメント文指定を解除します(シャープ記号を削除します)。異なるプラットフォームを使用しているのであれば、独自の定義を追加します。

makefileを少し書きなおせば、クライアントは付録A「アプリケーション例」の場合と同じ方法で構築できます。simpdce.idlblds_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.odcemgr.oをインクルードすることで構築されます。

ステップ5: 構成の変更

  1. ASCIIのubbconfig構成ファイルを、付録A「アプリケーション例」の説明どおりに変更します。(このステップは必須です。)

  2. SERVERSセクションでは、シャープ記号(#)を行の先頭に付けてserver行をコメント文にします。(dceserver行ではコメント文の指定を解除します。)

ステップ6:アプリケーションの構築

  1. ソフトウェアを構築する前に、前述で説明したようにrpcsimp.mkを修正してDCEサーバーを構築するために正しいオプションとライブラリを設定する必要があります。

  2. 次のコマンドを実行してクライアントとサーバー・プログラムを構築します。

    make -f rpcsimp.mk TUXDIR=$TUXDIR all2
    

ステップ7: 構成ファイルのロード

次のコマンドを実行してバイナリのTUXCONFIG構成ファイルをロードします。

tmloadcf -y ubbconfig

ステップ8: DCEの構成

前述で説明したアプリケーション例を実行するためのDCEエンティティの設定手順を次に示します。すべての文字が大文字で表される識別子は、使用する環境に応じてカスタマイズ化します。

  • すでに独自のDCEプリンシパルを持っている場合は、MYGROUPMYPRINCIPAL、または関連するアカウントを作成する必要はありません。

  • この例では、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

ステップ9: 構成の起動

  1. SERVER_PRINCIPAL (サーバー・キー表のオーナー)としてログインします。

  2. 次のコマンドを実行してDCEサーバーを起動します。

    dceserver &
    

    DCEサーバーは、リクエストのリスンを開始する前に「Server ready」というメッセージを表示します。

  3. 次のコマンドを実行してOracle Tuxedo ATMIアプリケーションを起動します。

    tmboot -y
    

ステップ10:クライアントの実行

変換する文字列を指定してクライアント・プログラムを実行できます。変換する文字列は省略できます。クライアント・プログラムは、まず文字列を大文字に変換し、この後小文字に変換します。

$ client HeLlO
to_upper returns: HELLO
to_lower returns: hello
$

ステップ11: 構成の停止

  1. 次のコマンドを実行して、アプリケーションを停止します。

    tmshutdown -y
    
  2. DCEサーバーを停止します。

ステップ12:作成ファイルのクリーンアップ

次のコマンドを入力して、作成したファイルを削除します。

make -f rpcsimp.mk clean