ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
Trusted Extensions 開発者ガイド Oracle Solaris 10 1/13 Information Library (日本語) |
1. Trusted Extensions API およびセキュリティーポリシー
9. Solaris Trusted Extensions ラベル API のための試験的な Java バインディング
Trusted Extensions ソフトウェアは、次に示すソケットベースのメカニズムを使用して、通信エンドポイント間の IPC をサポートします。
Berkeley ソケット
トランスポートレイヤーインタフェース (TLI)
リモート手続き呼び出し (RPC)
このセクションでは、ソケット通信メカニズムおよび関連するセキュリティーポリシーの概要を示します。セキュリティーポリシーおよび該当する特権に関する具体的な情報については、該当するマニュアルページを参照してください。
これらのメカニズムに加えて、Trusted Extensions はマルチレベルポートもサポートします。「マルチレベルポート情報」を参照してください。
Trusted Extensions ソフトウェアは、Berkeley ソケットおよび TLI を使用した、シングルレベルポートおよびマルチレベルポート間でのネットワーク通信をサポートします。AF_UNIX ファミリのシステムコールは、完全に解決されたパス名を使用して指定された特殊ファイルを使用することによって、同一のラベルが付いたゾーン内でプロセス間通信を確立します。AF_INET ファミリのシステムコールは、IP アドレスおよびポート番号を使用して、ネットワーク経由のプロセス間接続を確立します。
AF_UNIX ファミリのインタフェースでは、単一の特殊ファイルへの 1 つのサーバーバインドのみを確立でき、これは UNIX ドメインソケットです。AF_UNIX ファミリはマルチレベルポートをサポートしません。
UNIX ドメインソケットのように、ドアおよび名前付きパイプは、ランデブー目的の特殊ファイルを使用します。
Trusted Extensions のすべての IPC メカニズムのデフォルトポリシーは、ラベル付けされた単一ゾーン内で機能するようにすべて制約されるというものです。このポリシーの例外を次に示します。
大域ゾーン管理者は、所有側のゾーンより優位なラベルを持つゾーンに対して名前付きパイプ (FIFO) を使用可能にすることができます。管理者は、FIFO を含むディレクトリをループバックマウントすることによってこれを実行します。
より高いレベルのゾーンで実行するプロセスは、FIFO を読み取り専用モードで開くことが許可されます。プロセスは FIFO を使用してライトダウンすることができません。
大域ゾーンランデブーファイルがラベル付きゾーンにループバックマウントされた場合、ラベル付きゾーンは大域ゾーンドアサーバーにアクセスできます。
Trusted Extensions ソフトウェアはドアポリシーに基づいて、labeld および nscd ドアベースサービスをサポートします。デフォルトの zonecfg テンプレートは、大域ゾーンの /var/tsol/doors ディレクトリが、ラベル付けされた各ゾーンにループバックマウントされることを指定しています。
AF_INET ファミリでは、プロセスは特権付きポート番号または特権なしポート番号に対してシングルラベル接続またはマルチラベル接続を確立できます。特権付きのポート番号に接続するには、net_priv_addr 特権が必要です。マルチレベルポート接続が求められる場合、net_bindmlp 特権も必要になります。
マルチレベルポート接続を行う場合、サーバープロセスはその実効セット内に net_bindmlp 特権が必要です。代わりにシングルレベルポート接続が実行される場合、サーバープロセスはソケットに対する必須の同位書き込みアクセスが必要で、クライアントプロセスは必須の同位読み取りアクセスが必要です。どちらのプロセスも、ファイルへの必須アクセスおよび任意アクセスが必要です。ファイルへのアクセスが拒否された場合、アクセスが拒否されたすべてのプロセスは、その実効セット内にアクセスを取得するための適切なファイル特権が必要です。
次のコード例では、マルチレベルサーバーが、接続されたクライアントのラベルを取得する方法を示しています。標準の C ライブラリ関数 getpeerucred() が、接続されたソケットまたは STREAM ピアの資格を取得します。Trusted Extensions のコンテキストで、マルチレベルポートサーバーの待機中ソケットが接続リクエストを受け入れたとき、最初の引数は通常、クライアントソケットファイル記述子です。Trusted Extensions アプリケーションは、通常のアプリケーションプログラムが行うのとまったく同じ方法で getpeerucred() 関数を使用します。Trusted Extensions の追加関数は ucred_getlabel() で、これはラベルを返します。詳細は、ucred_get(3C) のマニュアルページを参照してください。
/* * This example shows how a multilevel server can * get the label of its connected clients. */ void remote_client_label(int svr_fd) { ucred_t *uc = NULL; m_label_t *sl; struct sockaddr_in6 remote_addr; bzero((void *)&remote_addr, sizeof (struct sockaddr_in6)); while (1) { int clnt_fd; clnt_fd = accept(svr_fd, (struct sockaddr *)&remote_addr, &sizeof (struct sockaddr_in6)); /* * Get client attributes from the socket */ if (getpeerucred(clnt_fd, &uc) == -1) { return; } /* * Extract individual fields from the ucred structure */ sl = ucred_getlabel(uc); /* * Security label usage here * ..... */ ucred_free(uc); close(clnt_fd); } }
Trusted Extensions ソフトウェアは、リモート手続き呼び出し (RPC) 用のマルチレベルポートサポートを提供しています。クライアントアプリケーションはサーバーの PORTMAPPER サービス (ポート 111) に対して、特定のサービスが使用可能かどうかを照会する問い合わせを送信できます。リクエストされたサービスがサーバー上の PORTMAPPER に登録されている場合、サーバーは匿名ポートを動的に割り当て、このポートをクライアントに返します。
Trusted Extensions システムでは、管理者は PORTMAPPER ポートをマルチレベルポートとして構成することで、複数のシングルレベルアプリケーションがこのサービスを使用できるようにすることが可能です。PORTMAPPER ポートがマルチレベルポートにされた場合、PORTMAPPER サービスによって割り当てられたすべての匿名ポートもマルチレベルポートになります。匿名マルチレベルポートを管理するためのプログラム可能なインタフェースまたは管理インタフェースはほかにありません。
前のセクションで説明した PORTMAPPER サービスは、UDP を使用して実装されます。TCP とは異なり、UDP ソケットは接続指向でないため、マルチレベルポート上のクライアントに応答する際、どの資格を使用するかについて、あいまいさが発生する可能性があります。したがって、クライアントのリクエストソケットを、サーバーの応答パケットに明示的に関連付ける必要があります。この関連付けを実行するには、SO_RECVUCRED ソケットオプションを使用します。
SO_RECVUCRED が UDP ソケットに設定された場合、カーネル UDP モジュールは ucred 構造内のラベルを付属データとしてアプリケーションに渡すことができます。ucred の level および type の値はそれぞれ SOL_SOCKET および SCM_UCRED です。
アプリケーションはこの ucred 構造を、次のいずれかの方法で処理することができます。
この ucred 構造を受信側バッファーから送信側バッファーにコピーする
受信側バッファーを送信側バッファーとして再使用し、ucred 構造は受信側バッファー内に残す
次のコードの抜粋は、再使用するケースを示します。
/* * Find the SCM_UCRED in src and place a pointer to that * option alone in dest. Note that these two 'netbuf' * structures might be the same one, so the code has to * be careful about referring to src after changing dest. */ static void extract_cred(const struct netbuf *src, struct netbuf *dest) { char *cp = src->buf; unsigned int len = src->len; const struct T_opthdr *opt; unsigned int olen; while (len >= sizeof (*opt)) { /* LINTED: pointer alignment */ opt = (const struct T_opthdr *)cp; olen = opt->len; if (olen > len || olen < sizeof (*opt) || !IS_P2ALIGNED(olen, sizeof (t_uscalar_t))) break; if (opt->level == SOL_SOCKET && opt->name == SCM_UCRED) { dest->buf = cp; dest->len = olen; return; } cp += olen; len -= olen; } dest->len = 0; }
次のコードの抜粋は、受信側バッファーからユーザー資格にアクセスする方法を示しています。
void examine_udp_label() { struct msghdr recv_msg; struct cmsghdr *cmsgp; char message[MAX_MSGLEN+1]; char inmsg[MAX_MSGLEN+1]; int on = 1; setsockopt(sockfd, SOL_SOCKET, SO_RECVUCRED, (void *)&on, sizeof (int)); [...] while (1) { if (recvmsg(sockfd, &recv_msg, 0) < 0) { (void) fprintf(stderr, "recvmsg_errno: %d\n", errno); exit(1); } /* * Check ucred in ancillary data */ ucred = NULL; for (cmsgp = CMSG_FIRSTHDR(&recv_msg); cmsgp; cmsgp = CMSG_NXTHDR(&recv_msg, cmsgp)) { if (cmsgp->cmsg_level == SOL_SOCKET && cmsgp->cmsg_type == SCM_UCRED) { ucred = (ucred_t *)CMSG_DATA(cmsgp); break; } if (ucred == NULL) { (void) sprintf(&message[0], "No ucred info in ancillary data with UDP"); } else { /* * You might want to extract the label from the * ucred by using ucred_getlabel(3C) here. */ } } [...] if (message != NULL) (void) strlcpy(&inmsg[0], message, MAX_MSGLEN); /* * Use the received message so that it will contain * the correct label */ iov.iov_len = strlen(inmsg); ret = sendmsg(sockfd, &recv_msg, 0); } }