Appendix A - Code for Role-based Access Control using Object Technology
//
// C++ Example of Role Based Access Control
// Implementation Using Object Technology
//
// John Barkley
// (barkley@sst.ncsl.nist.gov)
//
// This C++ program illustrates the implementation of RBAC using Object
// Technology. In this example, there are two methods which provide
// a healthcare application with access to patient records:
// GetIdinfo() - provides a list of patient names and their IDs
// GetPR(pid) - given a patient ID, returns the patient record
// These two methods are associated with several classes:
// Access_PRDBO - this class provides the basic access methods
// to patient information
// Role_PRDBO - the abstract role class
// Pat_PRDBO - the patient role class
// Doc_PRDBO - the doctor role class
// PRDBO - the application programming interface class
//
// For each role, there is a role class for that role derived from the
// abstract role class. The methods in each role class contain the
// conditions under which a user in that role may perform the
// corresponding methods in a basic access methods class
// (Access_PRDBO in this example). The methods in the basic
// access methods class perform actions on the information. The
// methods in each role class are invoked by corresponding methods
// in the application programming interface class (PRDBO in this // example).
//
// This approach permits much of the generality of the RBAC concept of
// "action" to be realized, i.e., once the basic actions
// on information have been established, any conditions permitting
// actions on information specified in an RBAC policy may be
// implemented. In addition, this approach permits roles to be
// created, removed, and modified without having to recompile either
// the application or the basic access methods class. When a role
// is added, removed, or modified in the policy, a role class is
// added, removed, or modified.
//
// This example was compiled using the GNU C++ compiler.
//
#include <stdio.h>
#include <iostream.h>
#include <strstream.h>
const int ROLE_NAME_LENGTH = 50;
const int NUMBER_OF_ROLES = 2;
typedef char *Idlist;
typedef char *Patrec;
typedef int Patid;
extern char * get_role();
extern int get_user_pid();
extern "C" void exit(int);
// basic access methods class
class Access_PRDBO{
public:
Idlist GetIdinfo(){ return("Here's the list of patients and their IDs\n"); };
Patrec GetPR(Patid pid){
const int BUFLEN = 128;
static char buf[BUFLEN];
static ostrstream oss(buf, BUFLEN, ios::out);
oss.seekp(ios::beg);
oss << "Here's the patient record for patient ID: "
<< pid << endl << ends;
return(buf);
};
};
Access_PRDBO access_prdbo;
// role classes:
// one for each role derived from the abstract class Role_PRDBO
class Role_PRDBO{
public:
virtual Idlist GetIdinfo()=0;
virtual Patrec GetPR(Patid patid)=0;
};
class Pat_PRDBO:public Role_PRDBO{
public:
// the policy does not permit patients to access
// the list of patient names and their IDs
virtual Idlist GetIdinfo(){
return("ERROR: patient cannot access patient id list\n");
};
// the policy only permits a patient to have access
// to his own patient information
virtual Patrec GetPR(Patid pid){
if (pid == get_user_pid())
return(access_prdbo.GetPR(pid));
else
return("ERROR: patients cannot get other's records\n");
};
};
static Pat_PRDBO pat_prdbo;
class Doc_PRDBO:public Role_PRDBO{
public:
// the policy permits doctors to have access
// to all information on any patient
virtual Idlist GetIdinfo(){ return(access_prdbo.GetIdinfo()); };
virtual Patrec GetPR(Patid pid){ return(access_prdbo.GetPR(pid)); };
};
static Doc_PRDBO doc_prdbo;
// this procedure, which must be changed when roles are added or
// deleted, would be a system call which finds the the role object
// given the user's role
Role_PRDBO *get_role_obj(char *role_name){
struct{
char role_name[ROLE_NAME_LENGTH];
Role_PRDBO *role_object;
} role_tab[NUMBER_OF_ROLES] =
{
{"patient", &pat_prdbo},
{"doctor", &doc_prdbo}
};
for(int i=0; i<NUMBER_OF_ROLES; i++)
if (strcmp(role_name, role_tab[i].role_name) == 0)
return(role_tab[i].role_object);
return((Role_PRDBO *) NULL);
};
// application interface class
class PRDBO{
public:
Idlist GetIdinfo(){
char * role_name;
Role_PRDBO *roleobj;
role_name = get_role();
roleobj = get_role_obj(role_name);
if (roleobj == (Role_PRDBO *)NULL)
return("ERROR: no such role\n");
return(roleobj->GetIdinfo());
};
Patrec GetPR(Patid patid){
char * role_name;
Role_PRDBO *roleobj;
role_name = get_role();
roleobj = get_role_obj(role_name);
if (roleobj == (Role_PRDBO *)NULL)
return("ERROR: no such role\n");
return(roleobj->GetPR(patid));
};
};
PRDBO prdbo;
// this procedure would be a system call to return the
// user's current role
char * get_role(){
static char role_name[ROLE_NAME_LENGTH];
cout << "Enter role name: ";
cin >> role_name;
return(role_name);
};
// this procedure would be a system call to return the user's patient ID
int get_user_pid(){
int pid;
cout << "Enter user's patient id: ";
cin >> pid;
return(pid);
};
main(){
char opt;
Patid pid;
while(1){
cout << "Enter i-GetIdlist, r-GetPR: " ;
cin >> opt;
if ( !cin ) {cout << endl; exit(0); };
switch (opt) {
case 'i' : cout << prdbo.GetIdinfo() << endl;
break;
case 'r' : cout << "Enter patient id: ";
cin >> pid;
cout << prdbo.GetPR(pid) << endl;
break;
};
};
};
Up Previous
Next