次に示すUDFのサンプルCコードでは、セキュリティ ポリシーを強制的に実施します。この例で使用されるポリシーは、次のとおりです。
- INSERT操作の場合、新しい行にはセッションの機密度ラベルが含まれている必要がある。
- UPDATE操作の場合、セッションのセキュリティ ラベルが対象行のラベルよりも上位でなければ、更新を拒否する必要がある。UPDATEが許可された場合、更新された行のラベルにはセッションのレベルとカテゴリ(セッションのカテゴリと現在行のカテゴリの組み合わせ)を含める必要がある。
- DELETE操作の場合、機密度レベルが未分類であり、機密度カテゴリがNULLでないときには、行は削除できない。
- SELECT操作の場合、セッションの機密度ラベルが対象行のラベルよりも上位である必要がある。
#define SQL_TEXT Latin_Text #include <sqltypes_td.h> typedef unsigned char byte; // INSERT Level UDF void InsertLevel( short int *sess_level, short int *new_row ) { // Level of new row equals that of the session // return level to DBS *new_row = *sess_level; return; } // UPDATE Level UDF void UpdateLevel( short int *sess_level, short int *curr_row, short int *upd_row ) { // Session's level must be equal to or greater than row’s to allow // the update. If update is allowed, then the level of the updated // row is changed to that of the session. // can the session update the row? if (*sess_level >= *curr_row) // set level in updated row to session's level *upd_row = *sess_level; else // update is not allowed *upd_row = 0; return; } //DELETE Level UDF void DeleteLevel( short int *curr_row, char *result ) { // Row can only be deleted if it has a label of unclassified if (*curr_row == 1) // delete is allowed *result = 'T'; else *result = 'F'; return; } // SELECT Level UDF void ReadLevel( short int *sess_level, short int *curr_row, char *result ) { // Read allowed if session's level is equal to or greater than row's if (*sess_level >= *curr_row) // select is allowed *result = 'T'; else //select is not allowed *result = 'F'; return; } //INSERT Category UDF void InsertCategory( byte sess_cat[], byte new_row[], int *indic1, int *retindic) { int i; // policy is that category for new row equals that for the session if (*indic1 == -1) // null session, then null new row *retindic = -1; else // non-null session, then new row equals session { *retindic = 0; for (i = 0; i < 8; i++) new_row[i] = sess_cat[i]; } return; } // UPDATE Category UDF void UpdateCategory( byte sess_cat[], byte curr_row[], byte new_row[], int *indic1, int *indic2, int *retindic) { int i; // Policy is that row can be updated if user's category is a // superset of the row's category. If the update is allowed, // then the category for the new row is a combination of the // categories of the current row plus those of the session. if (*indic1 == -1) // if session’s category is null { if (*indic2 == -1) // if row’s category is null, update is allowed { // both are null *retindic = -1; // new row constraint is null return; } else { // session is null and row is not, so disallow update *retindic = 0; for (i = 0; i < 8; i++) new_row[i] = 0; // set return category to null for error return; } } // session’s category is not null *retindic = 0; // must return a category if (*indic2 == -1) // if row’s category is null, then update // is allowed { for (i = 0; i < 8; i++) new_row[i] = sess_cat[i]; //set return category to session return; } // session’s category and input row’s category are not null for (i = 0; i < 8; i++) // does session dominate row? if ((sess_cat[i] & curr_row[i]) != curr_row[i]) // no it does not, so update is not allowed { for (i = 0; i < 8; i++) new_row[i] = 0; // set return category to all zeroes //for error return; } // update is allowed; set return category to a combination of // session’s and row’s categories for (i = 0; i < 8; i++) new_row[i] = sess_cat[i] | curr_row[i]; //inclusive or return; } // DELETE Category UDF void DeleteCategory( byte curr_row[], char *result, int *indic1, int *retindic) { // Policy is that row can be deleted only if its category is null *retindic = 0; // result is always not null if (*indic1 == -1) // if row's category is not null *result = 'T'; // delete is allowed else *result = 'F'; // delete is not allowed return; } // SELECT Category UDF void ReadCategory( byte sess_cat[], byte curr_row[], char *result, int *indic1, int *indic2, int *retindic) { int i; // Policy is that row can be selected if user's category is a // superset of the row's category. *retindic = 0; // result is always not null *result = 'T'; if ((*indic1 == *indic2) && (*indic1 == -1)) // both are null return; // allow select if (*indic2 == -1) // row is null and session isn't return; // allow select // both are not null *result = 'F'; for (i = 0; i < 8; i++) // does session dominate row // does session dominate if ((curr_row[i] ^ sess_cat[i]) & curr_row[i]) return; // no, so select is not allowed *result = 'T'; // yes, so allow select return; }