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