Back to index

nordugrid-arc-nox  1.1.0~rc6
XACMLEvaluator.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <fstream>
00006 #include <iostream>
00007 
00008 #include <arc/security/ClassLoader.h>
00009 #include <arc/security/ArcPDP/Request.h>
00010 #include <arc/security/ArcPDP/Response.h>
00011 #include <arc/security/ArcPDP/EvaluationCtx.h>
00012 
00013 #include "XACMLEvaluator.h"
00014 #include "XACMLEvaluationCtx.h"
00015 
00016 Arc::Plugin* ArcSec::XACMLEvaluator::get_evaluator(Arc::PluginArgument* arg) {
00017     Arc::ClassLoaderPluginArgument* clarg =
00018             arg?dynamic_cast<Arc::ClassLoaderPluginArgument*>(arg):NULL;
00019     if(!clarg) return NULL;
00020     return new ArcSec::XACMLEvaluator((Arc::XMLNode*)(*clarg));
00021 }
00022 
00023 using namespace Arc;
00024 using namespace ArcSec;
00025 
00026 Arc::Logger ArcSec::XACMLEvaluator::logger(Arc::Logger::rootLogger, "XACMLEvaluator");
00027 
00028 void XACMLEvaluator::parsecfg(Arc::XMLNode& cfg){
00029   std::string policystore, policylocation, functionfactory, attributefactory, combingalgfactory;
00030   XMLNode nd;
00031 
00032   Arc::NS nsList;
00033   std::list<XMLNode> res;
00034   nsList.insert(std::pair<std::string, std::string>("pdp","http://www.nordugrid.org/schemas/pdp/Config"));
00035   
00036   //Get the name of "PolicyStore" class
00037   //res = cfg.XPathLookup("//pdp:PolicyStore", nsList);
00038   //presently, there can be only one PolicyStore
00039   //if(!(res.empty())){
00040   //  nd = *(res.begin());
00041   //  policystore = (std::string)(nd.Attribute("name"));
00042   //  policylocation =  (std::string)(nd.Attribute("location"));
00043   //}
00044   //else if (res.empty()){ 
00045   //  logger.msg(ERROR, "No any policy exists, the policy engine can not be loaded");
00046   //  exit(1);
00047   //}
00048 
00049   //Get the name of "FunctionFactory" class
00050   res = cfg.XPathLookup("//pdp:FunctionFactory", nsList);
00051   if(!(res.empty())){
00052     nd = *(res.begin());
00053     functionfactory = (std::string)(nd.Attribute("name"));
00054   } 
00055   else { logger.msg(ERROR, "Can not parse classname for FunctionFactory from configuration"); return;}
00056           
00057   //Get the name of "AttributeFactory" class
00058   res = cfg.XPathLookup("//pdp:AttributeFactory", nsList);
00059   if(!(res.empty())){
00060     nd = *(res.begin());
00061     attributefactory = (std::string)(nd.Attribute("name"));
00062   }  
00063   else { logger.msg(ERROR, "Can not parse classname for AttributeFactory from configuration"); return;}
00064 
00065   //Get the name of "CombiningAlgorithmFactory" class
00066   res = cfg.XPathLookup("//pdp:CombingAlgorithmFactory", nsList);
00067   if(!(res.empty())){
00068     nd = *(res.begin());
00069     combingalgfactory = (std::string)(nd.Attribute("name"));
00070   }
00071   else { logger.msg(ERROR, "Can not parse classname for CombiningAlgorithmFactory from configuration"); return;}
00072 
00073   //Get the name of the "Request" class
00074   res = m_cfg->XPathLookup("//pdp:Request", nsList);
00075   if(!(res.empty())){
00076     nd = *(res.begin());
00077     request_classname = (std::string)(nd.Attribute("name"));
00078   }
00079   else { logger.msg(ERROR, "Can not parse classname for Request from configuration"); return;}
00080 
00081   //Get the name of the "Policy" class
00082   std::string policy_classname;
00083   res = m_cfg->XPathLookup("//pdp:Policy", nsList);
00084   if(!(res.empty())){
00085     nd = *(res.begin());
00086     policy_classname = (std::string)(nd.Attribute("name"));
00087   }
00088   else { logger.msg(ERROR, "Can not parse classname for Policy from configuration"); return;}
00089 
00090   //Get the ClassLoader object; The object which loads this XACMLEvaluator should have 
00091   //constructed ClassLoader by using ClassLoader(cfg), and putting the configuration 
00092   //information into it; meanwhile ClassLoader is designed as a Singleton, so here 
00093   //we don't need to intialte ClassLoader by using ClassLoader(cfg);
00094   ClassLoader* classloader;
00095   classloader=ClassLoader::getClassLoader();
00096 
00097   attrfactory=NULL;
00098   attrfactory = (AttributeFactory*)(classloader->Instance(attributefactory));
00099   if(attrfactory == NULL)
00100     logger.msg(ERROR, "Can not dynamically produce AttributeFactory");
00101 
00102   fnfactory=NULL;
00103   fnfactory = (FnFactory*)(classloader->Instance(functionfactory));
00104   if(fnfactory == NULL)
00105     logger.msg(ERROR, "Can not dynamically produce FnFactory");
00106 
00107   algfactory=NULL;
00108   algfactory = (AlgFactory*)(classloader->Instance(combingalgfactory));
00109   if(algfactory == NULL)
00110     logger.msg(ERROR, "Can not dynamically produce AlgFacroty");
00111 
00112   //Create the EvaluatorContext for the usage of creating Policy
00113   context = new EvaluatorContext(this);
00114 
00115   std::string alg("Permit-Overrides");
00116   //std::list<std::string> filelist;
00117   //filelist.push_back(policylocation);
00118   //plstore = new PolicyStore(filelist, alg, policy_classname, context);
00119   plstore = new PolicyStore(alg, policy_classname, context);
00120   if(plstore == NULL)
00121     logger.msg(ERROR, "Can not create PolicyStore object");
00122 }
00123 
00124 XACMLEvaluator::XACMLEvaluator(Arc::XMLNode* cfg) : Evaluator(cfg), m_cfg(cfg) {
00125   plstore = NULL;;
00126   fnfactory = NULL;
00127   attrfactory = NULL;
00128   algfactory = NULL;
00129   combining_alg = EvaluatorFailsOnDeny;
00130   combining_alg_ex = NULL;
00131   context = NULL;
00132 
00133   parsecfg(*m_cfg);
00134 }
00135 
00136 XACMLEvaluator::XACMLEvaluator(const char * cfgfile) : Evaluator(cfgfile){
00137   combining_alg = EvaluatorFailsOnDeny;
00138   combining_alg_ex = NULL;
00139   std::string str;
00140   std::string xml_str = "";
00141   std::ifstream f(cfgfile);
00142   while (f >> str) {
00143     xml_str.append(str);
00144     xml_str.append(" ");
00145   }
00146   f.close();
00147 
00148   Arc::XMLNode node(xml_str);
00149   parsecfg(node); 
00150 }
00151 
00152 void XACMLEvaluator::setCombiningAlg(EvaluatorCombiningAlg alg) {
00153   combining_alg = alg;
00154 }
00155 
00156 void XACMLEvaluator::setCombiningAlg(CombiningAlg* alg) {
00157   combining_alg_ex = alg;
00158 }
00159 
00160 Request* XACMLEvaluator::make_reqobj(XMLNode& reqnode){
00161   Request* request = NULL;
00162   std::string requestor;
00163 
00164   Arc::ClassLoader* classloader = NULL;
00165   //Since the configuration information for loader has been got before (when create XACMLEvaluator), 
00166   //it is not necessary to get once more here
00167   classloader = ClassLoader::getClassLoader();
00168 
00169   //Load the Request object
00170   request = (ArcSec::Request*)(classloader->Instance(request_classname,&reqnode));
00171   if(request == NULL)
00172     logger.msg(Arc::ERROR, "Can not dynamically produce Request");
00173 
00174   return request;
00175 }
00176 
00177 Response* XACMLEvaluator::evaluate(Request* request){
00178   Request* req = request;
00179   req->setAttributeFactory(attrfactory);
00180   //req->make_request();
00181 
00182   EvaluationCtx * evalctx = NULL;
00183   evalctx =  new XACMLEvaluationCtx(req);
00184 
00185   //evaluate the request based on policy
00186   if(evalctx)
00187     return evaluate(evalctx);
00188   return NULL;
00189 }
00190 
00191 
00192 Response* XACMLEvaluator::evaluate(const Source& req){
00193   //0.Prepare request for evaluation
00194   Arc::XMLNode node = req.Get();
00195   NS ns;
00196   ns["ra"]="http://www.nordugrid.org/schemas/request-arc";
00197   node.Namespaces(ns);
00198 
00199   //1.Create the request object according to the configuration
00200   Request* request = NULL;
00201   request = make_reqobj(node);
00202   
00203   //2.Pre-process the Request object
00204   request->setAttributeFactory(attrfactory);
00205   //request->make_request();
00206   
00207   EvaluationCtx * evalctx = NULL;
00208   evalctx =  new XACMLEvaluationCtx(request);
00209   
00210   //3.evaluate the request based on policy
00211   Response* resp = NULL;
00212   if(evalctx)
00213     resp = evaluate(evalctx);
00214   if(request)
00215     delete request;
00216 
00217   return resp;
00218 }
00219 
00220 Response* XACMLEvaluator::evaluate(EvaluationCtx* evl_ctx){
00221   //Split request into <subject, action, object, environment> tuples
00222   XACMLEvaluationCtx* ctx = dynamic_cast<XACMLEvaluationCtx*>(evl_ctx);
00223   
00224   std::list<PolicyStore::PolicyElement> policies;
00225   std::list<PolicyStore::PolicyElement>::iterator policyit;
00226 
00227   Response* resp = new Response();
00228 
00229   policies = plstore->findPolicy(ctx);
00230   std::list<PolicyStore::PolicyElement> permitset;
00231   
00232   //Combining algorithm should be present if there are mutiple <Policy/>
00233   std::list<Policy*> plist;
00234   // Preparing list of policies to evaluate
00235   for(policyit = policies.begin(); policyit != policies.end(); policyit++){
00236     plist.push_back((Policy*)(*policyit));
00237   };
00238   Result result;
00239   if(plist.size() == 1)
00240     result = ((Policy*)(*(policies.begin())))->eval(ctx);
00241   else
00242     result = combining_alg_ex->combine(ctx,plist);
00243 
00244   ResponseItem* item = new ResponseItem;
00245   item->res = result;
00246   resp->addResponseItem(item);
00247 
00248   if(ctx)
00249     delete ctx; 
00250   return resp;
00251 }
00252 
00253 Response* XACMLEvaluator::evaluate(Request* request, const Source& policy) {
00254   plstore->removePolicies();
00255   plstore->addPolicy(policy, context, "");
00256   Response* resp = evaluate(request);
00257   plstore->removePolicies();
00258   return resp;
00259 }
00260 
00261 Response* XACMLEvaluator::evaluate(const Source& request, const Source& policy) {
00262   plstore->removePolicies();
00263   plstore->addPolicy(policy, context, "");
00264   Response* resp = evaluate(request);
00265   plstore->removePolicies();
00266   return resp;
00267 }
00268 
00269 Response* XACMLEvaluator::evaluate(Request* request, Policy* policyobj) {
00270   plstore->removePolicies();
00271   plstore->addPolicy(policyobj, context, "");
00272   Response* resp = evaluate(request);
00273   plstore->releasePolicies();
00274   return resp;
00275 }
00276 
00277 Response* XACMLEvaluator::evaluate(const Source& request, Policy* policyobj) {
00278   plstore->removePolicies();
00279   plstore->addPolicy(policyobj, context, "");
00280   Response* resp = evaluate(request);
00281   plstore->releasePolicies();
00282   return resp;
00283 }
00284 
00285 const char* XACMLEvaluator::getName(void) const {
00286   return "xacml.evaluator";
00287 }
00288 
00289 XACMLEvaluator::~XACMLEvaluator(){
00290   //TODO delete all the object
00291   if(plstore)
00292     delete plstore;
00293   if(context)
00294     delete context;
00295   if(fnfactory)
00296     delete fnfactory;
00297   if(attrfactory)
00298     delete attrfactory;
00299   if(algfactory)
00300     delete algfactory;
00301 }
00302