Solaris Trusted Extensions 開発ガイド

下位レベルの信頼できないサーバーへのアクセス

場合によって、クライアントは、ラベル付けされていないシステムのサーバーにアクセスできなければなりません。「ラベル付けされていないシステム」は、Trusted Extensions ソフトウェアを実行しないシステムです。この場合、マルチレベルポートは、大域ゾーンまたはラベル付けされたゾーンで実行される特権サーバーに制限されるので使用できません。

たとえば、ブラウザが INTERNAL ゾーンで実行されているとします。tnrhdb データベースによって PUBLIC 機密ラベルが割り当てられた単一レベルネットワークで実行されている Web サーバーにアクセスしてみます。デフォルトでは、このようなアクセスは許可されません。それに対し、HTTP 要求を PUBLIC の Web サーバーに転送する特権プロキシーサーバーを記述できます。プロキシは、SO_MAC_EXEMPT と呼ばれる特別な Trusted Extensions ソケットオプションを使用します。このソケットオプションによって、信頼できない下位レベルのサービスに要求が送信され、サービスからの応答が要求元に返されます。


注 –

SO_MAC_EXEMPT オプションを使用する場合、保護されないダウングレードチャネルになるので、十分に注意が必要です。呼び出し元プロセスの実効セットに PRIV_NET_MAC_EXEMPT 特権がない場合は、SO_MAC_EXEMPT オプションを設定できません。このようなプロセスでは、高位レベルのデータが低位レベルのサービスに漏れないように、その自身のデータフィルタリングポリシーを強制する必要があります。たとえば、単語が値として使用されないように、URL の不適切な箇所をプロキシで削除します。


次のコード抜粋は、connect.c にある wget コマンドの connect_to_ip() ルーチンの変更バージョンにおけるSO_MAC_EXEMPT の使用方法を示します。SO_MAC_EXEMPT オプションの設定方法を明らかにするために、setsockopt() の呼び出しが追加されています。

int
connect_to_ip (const ip_address *ip, int port, const char *print)
{
  struct sockaddr_storage ss;
  struct sockaddr *sa = (struct sockaddr *)&ss;
  int sock;
  int on = 1;

  /* PRINT が NULL 以外の場合、PRINT は接続先のホスト名で
 "Connecting to..." 行を出力する。 */
  if (print)
    {
      const char *txt_addr = pretty_print_address (ip);
      if (print && 0 != strcmp (print, txt_addr))
	logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "),
		   escnonprint (print), txt_addr, port);
      else
	logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
    }

  /* sockaddr 情報を SA に格納する。 */
  sockaddr_set_data (sa, ip, port);

  /* アドレスに対応するファミリのソケットを作成する。  */
  sock = socket (sa->sa_family, SOCK_STREAM, 0);
  if (sock < 0)
    goto err;

  if (setsockopt (sock, SOL_SOCKET, SO_MAC_EXEMPT, &on, sizeof (on)) == -1) {
    perror("setsockopt SO_MAC_EXEMPT");
  }

#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY)
  if (opt.ipv6_only) {
    /* エラーの場合、そのまま実行する... */
    int err = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
  }
#endif