Trusted Solaris 開発ガイド

TCP/IP サーバー

サーバープロセスは、net_mac_read 特権を使用してマルチレベルポートに結合し、複数の機密レベルでシングルレベルクライアントに対応します。マルチレベルポートとシングルレベルポートの詳細は、第 11 章「プロセス間通信」を参照してください。

この msg_array 構造は、Confidential 、Secret 、Top Secret 、および NULL のミーティング情報を含みます。情報ラベル文字列は、サーバーがメッセージを送信する場合に使用する情報ラベルを示します。送信メッセージの情報ラベル属性を指定する場合、サーバープロセスは t6sendto(3N) ルーチンを使用します。サーバープロセスの情報ラベルは送信メッセージの情報ラベルと異なる可能性があるため、サーバープロセスは有効セットに net_upgrade_ilnet_downgrade_il 特権を必要とします。シングルレベルクライアントに応答するには、その子プロセスの機密ラベルをクライアントと同じレベルに変更するため、サーバープロセスの有効セットに proc_set_sl 特権が必要です。

#include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <string.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>

 #include <tsol/label.h>
 #include <tsix/t6attrs.h>

 struct msg {
 	char *sl;
 	bslabel_t *bsl;
 	char *msg;
 	char *il;
 	bilabel_t *bil;
 } msg_array[] = {
 	"CONFIDENTIAL", 0, "Staff Meeting at 1:00 pm, Rm 200", "CONFIDENTIAL", 0,
 	"SECRET", 0, "Manager Meeting at 10:00 am, Rm 303", "SECRET", 0,
 	"TOP SECRET", 0, "Exective Meeting at 3:00 pm, Rm 902", "TOP SECRET", 0,
 	0, 0, 0, 0, 0
 };

主プログラムのこの最初の部分は、子プロセスがその機密ラベルを要求クライアントの機密ラベルに設定できるように、プロセス認可上限を ADMIN_HIGH に設定します。この作業には、proc_setclr 特権が必要です。

コード内のコメントは、第 3 章「特権」で説明している特権ブラケットが必要な位置を示しています。特権ブラケットにより、要求クライアントの機密ラベルと情報ラベルではなく、msg_array データで指定された機密ラベルと情報ラベルでサーバーがクライアントに応答できるように、net_reply_equal 特権は無効にする必要があります。コードコメントは、この例を動作させるため、net_reply_equal 特権を無効にすべき位置を示しています。

main(int argc, char **argv)
 {
 	int fd, newfd, chpid, index, error;
 	struct sockaddr_in serv_addr;
 	bclear_t clearance;

 	if (argc != 2) {
 		printf("Usage: %s host¥n", argv[0]);
 		exit(1);
 	}
 	printf("PID = %ld¥n", getpid());

 	/* プロセスの認可上限を ADMIN_HIGH に設定する */
 	/* 有効セット内で proc_setclr 特権をオン (有効) にする */

 	bclearhigh(&clearance);
 	if (setclearance(&clearance) != 0) {
 		perror("setclearance");
 		exit(1);
 	}
 	/* proc_setclr 特権をオフ (無効) にする */

主プログラムの次のセグメントは、msg_array 内のデータから、バイナリの機密ラベルと情報ラベルを作成します。これらのバイナリラベルは、後に TSIX ライブラリルーチンとともに使用されます。

	/* 実行時の効率を良くするためバイナリラベルを得る */

 	index = 0;
 	while (msg_array[index].sl != NULL) {
 		if ((msg_array[index].bsl =
 			(bslabel_t *) malloc(sizeof (bslabel_t))) == NULL) {
 			printf("No memory");
 			exit (1);
 		}
 		if (stobsl(msg_array[index].sl, msg_array[index].bsl,
 			NEW_LABEL, &error) != 1) {
 			printf("converting SL %s failed¥n",
 			msg_array[index].sl);
 			exit(1);
 		}
 		if ((msg_array[index].bil =
 			(bilabel_t *) malloc(sizeof (bilabel_t))) == NULL) {
 			printf("No memory");
 			exit (1);
 		}
 		if (stobil(msg_array[index].il, msg_array[index].bil,
 			NEW_LABEL, &error) != 1) {
 			printf("converting IL %s failed¥n",
 			msg_array[index].il);
 			exit(1);
 		}
 		index++;
 	}

主プログラムの次のセグメントは、ソケットを作成して名前に結合し、クライアント要求を待機することによって、終端通信を設定します。コード内のコメントは、第 3 章「特権」で説明している特権ブラケットが必要な位置を示します。

	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 		perror("socket");
 		exit(1);
 	}
 	memset(&serv_addr, 0, sizeof (serv_addr));
 	serv_addr.sin_family = AF_INET;
 	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 	serv_addr.sin_port = htons(10000);

/* 有効セット内で net_mac_read をオン (有効) にする */
 	if (bind(fd, (struct sockaddr *) &serv_addr,
 		sizeof (serv_addr)) < 0) {
 		perror("bind");
 		exit(1);
 	}
/* net_mac_read をオフ (無効) にする */

 	listen(fd, 5);

while ループは、各クライアント要求を処理するために、ソケットでクライアント接続を受け付け、プロセスを作成します。作成されたプロセスは、着信メッセージとその機密ラベルを受信し、プロセス CMW ラベルの機密ラベル部を着信機密ラベルに設定し、送信サーバー応答の情報ラベルを設定する構造を用意します。作成されたプロセスはまた、着信メッセージの機密ラベルを受信するために十分な領域の handle_in を割り当て、発信メッセージとともに機密ラベルを送信するために十分な領域の handle_out を割り当て、t6recvfrom(3N) ルーチンを使用してメッセージとセキュリティ属性情報を受信します。

	while (1) {
 		if ((newfd = accept(fd, NULL, 0)) < 0) {
 			perror("accept");
 			exit(1);
 		}
 		printf("Request Received¥n");
 		if ((chpid = fork()) < 0) {
 			perror("fork");
 			exit(1);
 		} else if (chpid == 0) {        /* 子プロセス */
 			t6attr_t handle_in;
 			t6attr_t handle_out;
 			t6mask_t mask_in = T6M_SL;
 			t6mask_t mask_out = T6M_IL;
 			bslabel_t *bsl;
 			bclabel_t bcmwlabel;
 			char buf[256];
 			int index, buflen = 256;
 			t6mask_t new_mask = T6M_NO_ATTRS;
 			char *string = (char *) 0;
 			char any;
 			close(fd);
 			printf("child PID = %ld¥n", getpid());

/* クライアント要求を処理する */
 			if ((handle_in = t6alloc_blk(mask_in)) == NULL) {
 				printf("t6attr_alloc: no memory");
 				exit(1);
 			}
 			if ((handle_out = t6alloc_blk(mask_out)) == NULL) {
 				printf("t6attr_alloc: no memory");
 				exit(1);
 			}
 			if (t6recvfrom(newfd, buf, buflen, 0, 0, 0,
 				handle_in, &new_mask) < 0) {
 				perror("t6recvfrom");
 				exit(1);
 			}

主プログラムの次のセグメントは、受信した機密ラベルを抽出し、プロセスの機密ラベルをクライアントの機密ラベルに設定します。コード内のコメントは、第 3 章「特権」で説明している特権ブラケットが必要な位置を示します。

	/* 機密ラベルを得る */
 			if ((bsl = (bslabel_t *) t6get_attr(T6_SL,
 				handle_in)) == NULL) {
 				printf("t6get_attr: no SL available");
 				exit(1);
 			}
 			if (bsltos(bsl, &string, 0, LONG_WORDS) < 0) {
 				perror("bsltos");
 				exit(1);
 			}
 			printf("Requestor's SL = %s¥n", string);

 	/* 子プロセスの機密ラベルをクライアントの機密ラベルに設定する */
 			if (getcmwplabel(&bcmwlabel) != 0) {
 				perror("getcmwplabel");
 				exit(1);
 			}
 			setcsl(&bcmwlabel, bsl);

 	/* 有効セット内で proc_set_sl をオン (有効) にする */
 			if (setcmwplabel(&bcmwlabel, SETCL_SL) < 0) {
 				perror("setcmwplabel");
 				exit (1);
 			}
 	/* proc_set_sl をオフ (無効) にする */

主プログラムのこの最後のセグメントは、着信クライアント要求の機密ラベルに基づいて、正しい情報ラベルと対応するミーティング情報を msg_array から見つけ、この情報ラベルを発信サーバー応答に入れます。情報ラベルが handle_out に格納され、t6sendto(3N) ルーチンが正しいミーティング情報と情報ラベルをパラメータに設定し呼び出されます。最後に、t6free_blk(3N) ルーチンが呼び出され、実行時に handle_inhandle_out に割り当てられた記憶領域を解放します。

				index = 0;
 				while (msg_array[index].sl != NULL) {
 					if (blequal(msg_array[index].bsl, bsl)) {
 						printf("Server's IL = %s¥n", msg_array[index].il);
 						if (t6set_attr(T6_IL,
 							(const void *) msg_array[index].bil,
 							handle_out) < 0) {
 							printf("t6set_attr: IL not allocated");
 							exit(1);
 						}
 						print_t6attr_t(handle_out);
 #if 0
 printf("press any key to continue¥n"); scanf("%c", &any);
 #endif
/* 有効セット内で net_replay_equal をオン (有効) にする */
 						if (t6sendto(newfd, msg_array[index].msg, strlen(
 							msg_array[index].msg), 0, 0, 0,
 							handle_out)< 0) {
 #if 0
 						if (sendto(newfd, msg_array[index].msg,
 							strlen(msg_array[index].msg), 0, 0, 0)< 0) {
 #endif
 							perror("t6sendto");
 							exit(1);
 						}
/* net_reply_equal をオフ (無効) にする */
 						break;
 					}
 					index++;
 				} /* end while */
 				if (msg_array[index].sl == NULL) {
 					printf("No Matching Msg Found¥n");
 				}
 				t6free_blk(handle_in);
 				t6free_blk(handle_out);
 				close(newfd);
 				printf("child: exiting¥n");
 				exit(0);
 			} else
 				close(newfd);
 		} /* end while */
 	} /* end main */