// // C++ Example of Role Based Access Control // Implementation Using Object Technology // // John Barkley // (jbarkley@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 is an update of: // http://www.itl.nist.gov/div897/staff/barkley/rbacot/applint_cc.txt // It was compiled using GNU gcc version 3.4.4: // gcc applint_update.cc -lstdc++ // #include #include #include 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 std::ostrstream oss(buf, BUFLEN, std::ios::out); oss.seekp(std::ios::beg); oss << "Here's the patient record for patient ID: " << pid << std::endl << std::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; iGetIdinfo()); }; 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]; std::cout << "Enter role name: "; std::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; std::cout << "Enter user's patient id: "; std::cin >> pid; return(pid); }; main(){ char opt; Patid pid; while(1){ std::cout << "Enter i-GetIdlist, r-GetPR: " ; std::cin >> opt; if ( !std::cin ) {std::cout << std::endl; exit(0); }; switch (opt) { case 'i' : std::cout << prdbo.GetIdinfo() << std::endl; break; case 'r' : std::cout << "Enter patient id: "; std::cin >> pid; std::cout << prdbo.GetPR(pid) << std::endl; break; }; }; };