次に示す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;
}