lp/lib/lp/tx.c ファイルの get_peer_label() 関数は、Trusted Extensions におけるマルチレベル印刷のロジックを実装します。これ以降の各節でこの関数について説明し、順を追ってそれを実装します。
Trusted Extensions ソフトウェアでは、印刷サービスにおけるラベル処理のための多くのロジックは get_peer_label() 関数にあります。この関数は、ucred_t データ構造体の遠隔プロセスに関する資格を取得し、その資格からラベルを抽出します。
次は get_peer_label() のコードです。
int get_peer_label(int fd, char **slabel) { if (is_system_labeled()) { ucred_t *uc = NULL; m_label_t *sl; char *pslabel = NULL; /* peer's slabel */ if ((fd < 0) || (slabel == NULL)) { errno = EINVAL; return (-1); } if (getpeerucred(fd, &uc) == -1) return (-1); sl = ucred_getlabel(uc); if (label_to_str(sl, &pslabel, M_INTERNAL, DEF_NAMES) != 0) syslog(LOG_WARNING, "label_to_str(): %m"); ucred_free(uc); if (pslabel != NULL) { syslog(LOG_DEBUG, "get_peer_label(%d, %s): becomes %s", fd, (*slabel ? *slabel : "NULL"), pslabel); if (*slabel != NULL) free(*slabel); *slabel = strdup(pslabel); } } return (0); }
印刷サービスは、ラベル付けされている環境とラベル付けされていない環境で機能するように設計されています。そのため、印刷アプリケーションは、遠隔ホストのラベルが要求されるときと、そのラベルが適用されるか否かを決定する必要があります。印刷プロセスは、最初、それ自身の環境を検査します。プロセスがラベル対応の環境で実行されているか否かを確認します。
アプリケーションは、遠隔要求がラベル付けされているか否かを最初に判別しません。その代わりに、印刷アプリケーションはそれ自身の環境がラベル付けされているか否かを判別します。アプリケーションがラベル付けされているホストで実行されていない場合、MAC ポリシーによって、印刷アプリケーションはラベル付けされた要求を受信できません。
印刷サービスは is_system_labeled() 関数を使用して、ラベル付けされた環境でプロセスが実行されているか否かを判別します。この関数についての詳細は、is_system_labeled(3C) のマニュアルページを参照してください。
次のコード抜粋は、ラベル付けされた環境でアプリケーションが実行されているか否かをどのように判別するかを示します。
if (is_system_labeled()) { ucred_t *uc = NULL; m_label_t *sl; char *pslabel = NULL; /* peer's slabel */ if ((fd < 0) || (slabel == NULL)) { errno = EINVAL; return (-1); }
Trusted Extensions が設定されたシステムで印刷アダプタプロセスが実行されている場合、is_system_labeled() 関数は遠隔プロセスから ucred_t 資格抽象を取得します。次に、遠隔プロセスの ucred_t データ構造体およびピアのラベルが NULL
に設定されます。資格およびピアのラベルの値を返す関数がデータ構造体を満たします。そのデータ構造体については、次の節で説明します。
get_peer_label() ルーチン全体のソースは、「get_peer_label() ラベル対応関数」を参照してください。
Solaris OS ネットワーク API は、プロセスの資格の抽象を提供します。この資格データは、ネットワーク接続を通じて使用できます。資格は、Solaris 10 リリースで導入された ucred_t データ構造体によって表現されます。この構造体はプロセスのラベルを含むことができます。
ucred API には、遠隔プロセスから ucred_t データ構造体を取得するための関数があります。この API は、ucred_t データ構造体からラベルを抽出するための関数も提供します。
遠隔プロセスのラベルの取得は、2 ステップの手続きで実行されます。最初に、資格を取得します。次に、その資格からラベルを取得します。
資格は、遠隔プロセスの ucred_t データ構造体にあります。ラベルは、資格の m_label_t データ構造体にあります。遠隔プロセスの資格を取得したあとに、その資格からラベル情報を抽出します。
getpeerucred() 関数が、遠隔プロセスから ucred_t 資格データ構造体を取得します。ucred_getlabel() 関数が、ucred_t データ構造体からラベルを抽出します。get_peer_label() 関数では、次のように 2 ステップの手続きがコーディングされています。
if (getpeerucred(fd, &uc) == -1) return (-1); sl = ucred_getlabel(uc);
get_peer_label() ルーチン全体のソースは、「get_peer_label() ラベル対応関数」を参照してください。
この 2 つの関数については、getpeerucred(3C) および ucred_getlabel(3C) のマニュアルページを参照してください。
遠隔ホストのラベルのほかに、遠隔ホストのタイプも取得できます。遠隔ホストタイプを取得するには、tsol_getrhtype() ルーチンを使用します。「遠隔ホストタイプの取得」を参照してください。
資格および遠隔ホストラベルを取得したあとに、アプリケーションは label_to_str() を使用してラベルデータ構造体を文字列に変換できます。ラベルデータ構造体の文字列形式は、アプリケーションによって使用できます。
Trusted Extensions 印刷サービスでは、ラベルは文字列として返されます。get_peer_label() 関数は、m_label_t データ構造体でlabel_to_str() を呼び出すことによって取得される文字列を返します。この文字列値は、get_peer_label() 関数の slabel パラメータ、char** slabel に返されます。
次のコード抜粋は、label_to_str() 関数がどのように使用されるかを示します。
sl = ucred_getlabel(uc); if (label_to_str(sl, &pslabel, M_INTERNAL, DEF_NAMES) != 0) syslog(LOG_WARNING, "label_to_str(): %m"); ucred_free(uc); if (pslabel != NULL) { syslog(LOG_DEBUG, "get_peer_label(%d, %s): becomes %s", fd, (*slabel ? *slabel : "NULL"), pslabel); if (*slabel != NULL) free(*slabel); *slabel = strdup(pslabel); }
get_peer_label() ルーチン全体のソースは、「get_peer_label() ラベル対応関数」を参照してください。
「get_peer_label() ラベル対応関数」に示すように、多くの場合、ラベルは動的に割り当てられます。関数 str_to_label()、label_to_str()、 getdevicerange()、およびその他の関数は、呼び出し元によって解放されなければならないメモリーを割り当てます。これらの関数の次のマニュアルページに、メモリー割り当ての要件が説明されています。
getdevicerange(3TSOL)
label_to_str(3TSOL)
m_label(3TSOL)
str_to_label(3TSOL)
get_peer_label() 関数は、遠隔ホストからラベルを抽出し、そのラベルを文字列として返します。典型的なラベル対応アプリケーションと同様に、印刷アプリケーションは次の目的でラベルを使用します。
ラベルに関連付けられている情報が、正しいラベルではっきりとマークされていることを確認するため。バナーページとトレーラページ、およびヘッダーとフッターは、印刷されるドキュメントのラベルでマークされます。
ラベル付けされた別のリソースによって特定操作が実行されるのを、あるリソースのラベルが許可するのを検査するため。すなわち、要求プロセスのラベルは、その要求プロセスからの要求をプリンタが受け入れるのを許可します。この許可は、プリンタに割り当てられているラベルの範囲に基づきます。