Back to index

nordugrid-arc-nox  1.1.0~rc6
DelegationPDP.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <iostream>
00006 
00007 #include <arc/loader/Plugin.h>
00008 #include <arc/XMLNode.h>
00009 #include <arc/Thread.h>
00010 #include <arc/ArcConfig.h>
00011 #include <arc/ArcLocation.h>
00012 #include <arc/Logger.h>
00013 #include <arc/security/ArcPDP/Response.h>
00014 #include <arc/security/ArcPDP/attr/AttributeValue.h>
00015 #include <arc/security/ArcPDP/EvaluatorLoader.h>
00016 
00017 #include "DelegationPDP.h"
00018 
00019 // NOTE: using factories/attrbites provided ArcPDP
00020 //  This PDP is mostly same as ArcPDP. The difference 
00021 //  is that it takes both request and policies from SecAttr.
00022 //  Also currently for flexibility it performs every evaluation
00023 //  per request. Later it should become clever and distinguish
00024 //  if delegated policy comes per request or per session.
00025 
00026 Arc::Logger ArcSec::DelegationPDP::logger(ArcSec::PDP::logger,"DelegationPDP");
00027 
00028 using namespace Arc;
00029 
00030 namespace ArcSec {
00031 
00032 Plugin* DelegationPDP::get_delegation_pdp(PluginArgument* arg) {
00033     PDPPluginArgument* pdparg =
00034             arg?dynamic_cast<PDPPluginArgument*>(arg):NULL;
00035     if(!pdparg) return NULL;
00036     return new DelegationPDP((Config*)(*pdparg));
00037 }
00038 
00039 DelegationPDP::DelegationPDP(Config* cfg):PDP(cfg) {
00040   XMLNode pdp_node(*cfg);
00041   XMLNode filter = (*cfg)["Filter"];
00042   if((bool)filter) {
00043     XMLNode select_attr = filter["Select"];
00044     XMLNode reject_attr = filter["Reject"];
00045     for(;(bool)select_attr;++select_attr) select_attrs.push_back((std::string)select_attr);
00046     for(;(bool)reject_attr;++reject_attr) reject_attrs.push_back((std::string)reject_attr);
00047   };
00048 }
00049 
00050 DelegationPDP::~DelegationPDP(){
00051 }
00052 
00053 bool DelegationPDP::isPermitted(Message *msg) const {
00054   MessageAuth* mauth = msg->Auth()->Filter(select_attrs,reject_attrs);
00055   MessageAuth* cauth = msg->AuthContext()->Filter(select_attrs,reject_attrs);
00056   if((!mauth) && (!cauth)) {
00057     logger.msg(ERROR,"Missing security object in message");
00058     return false;
00059   };
00060 
00061   // Extract policies
00062   // TODO: Probably make MessageAuth do it or there should be some other way
00063   //       to avoid multiple extraction of same object.
00064   // Currently delegated policies are simply stored under special name "DELEGATION POLICY"
00065   // To have multiple policies in same object MultiSecAttr class may be used. Then
00066   // Policies are catenated under top-level element "Policies".
00067   // Otherwise in case of single policy (current implementation) top-level element is "Policy".
00068 
00069   bool result = false;
00070   Evaluator* eval = NULL;
00071   try {
00072     SecAttr* mpolicy_attr = mauth?(*mauth)["DELEGATION POLICY"]:NULL;
00073     SecAttr* cpolicy_attr = cauth?(*cauth)["DELEGATION POLICY"]:NULL;
00074     if((cpolicy_attr == NULL) && (mpolicy_attr == NULL)) {
00075       logger.msg(INFO,"No delegation policies in this context and message - passing through");
00076       result=true; throw std::exception();
00077     };
00078 
00079     // Create evaluator
00080     std::string evaluator = "arc.evaluator";
00081     EvaluatorLoader eval_loader;
00082     eval = eval_loader.getEvaluator(evaluator);
00083     if(!eval) {
00084       logger.msg(ERROR, "Can not dynamically produce Evaluator");
00085       throw std::exception();
00086     };
00087     // Just make sure algorithm is proper one
00088     eval->setCombiningAlg(EvaluatorFailsOnDeny);
00089 
00090     // Add policies to evaluator
00091     int policies_num = 0;
00092     if(mpolicy_attr) {
00093       NS ns; XMLNode policyxml(ns,"");
00094       if(!mpolicy_attr->Export(SecAttr::ARCAuth,policyxml)) {
00095         logger.msg(ERROR,"Failed to convert security information to ARC policy");
00096         throw std::exception();
00097       };
00098       if(policyxml.Name() == "Policy") {
00099         eval->addPolicy(policyxml); ++policies_num;
00100       } else if(policyxml.Name() == "Policies") {
00101         for(XMLNode p = policyxml["Policy"];(bool)p;++p) {
00102           eval->addPolicy(p); ++policies_num;
00103         };
00104       };
00105     };
00106     if(cpolicy_attr) {
00107       NS ns; XMLNode policyxml(ns,"");
00108       if(!cpolicy_attr->Export(SecAttr::ARCAuth,policyxml)) {
00109         logger.msg(ERROR,"Failed to convert security information to ARC policy");
00110         throw std::exception();
00111       };
00112       if(policyxml.Name() == "Policy") {
00113         eval->addPolicy(policyxml); ++policies_num;
00114         {
00115           std::string s; policyxml.GetXML(s);
00116           logger.msg(DEBUG,"ARC delegation policy: %s",s);
00117         };
00118       } else if(policyxml.Name() == "Policies") {
00119         for(XMLNode p = policyxml["Policy"];(bool)p;++p) {
00120           eval->addPolicy(p); ++policies_num;
00121           {
00122             std::string s; policyxml.GetXML(s);
00123             logger.msg(DEBUG,"ARC delegation policy: %s",s);
00124           };
00125         };
00126       };
00127     };
00128     if(policies_num == 0) {
00129       logger.msg(INFO,"No delegation policies in this context and message - passing through");
00130       result=true; throw std::exception();
00131     };
00132 
00133     // Generate request
00134     NS ns; XMLNode requestxml(ns,"");
00135     if(mauth) {
00136       if(!mauth->Export(SecAttr::ARCAuth,requestxml)) {
00137         logger.msg(ERROR,"Failed to convert security information to ARC request");
00138         throw std::exception();
00139       };
00140     };
00141     if(cauth) {
00142       if(!cauth->Export(SecAttr::ARCAuth,requestxml)) {
00143         logger.msg(ERROR,"Failed to convert security information to ARC request");
00144         throw std::exception();
00145       };
00146     };
00147     {
00148       std::string s;
00149       requestxml.GetXML(s);
00150       logger.msg(DEBUG,"ARC Auth. request: %s",s);
00151     };
00152     if(requestxml.Size() <= 0) {
00153       logger.msg(ERROR,"No requested security information was collected");
00154       throw std::exception();
00155     };
00156 
00157    
00158     //Call the evaluation functionality inside Evaluator
00159     Response *resp = eval->evaluate(requestxml);
00160     logger.msg(INFO, "There are %d requests, which satisfy at least one policy", (resp->getResponseItems()).size());
00161     bool atleast_onedeny = false;
00162     bool atleast_onepermit = false;
00163     if(!resp) {
00164       logger.msg(ERROR,"No authorization response was returned");
00165       throw std::exception();
00166     };
00167 
00168     ResponseList rlist = resp->getResponseItems();
00169     int size = rlist.size();
00170     for(int i = 0; i < size; i++) {
00171       ResponseItem* item = rlist[i];
00172       RequestTuple* tp = item->reqtp;
00173       if(item->res == DECISION_DENY) atleast_onedeny = true;
00174       if(item->res == DECISION_PERMIT) atleast_onepermit = true;
00175     }
00176     delete resp;
00177 
00178     if(atleast_onepermit) result = true;
00179     if(atleast_onedeny) result = false;
00180 
00181   } catch(std::exception&) {
00182   };
00183   if(result) {
00184     logger.msg(INFO, "Delegation authorization passed");
00185   } else {
00186     logger.msg(INFO, "Delegation authorization failed");
00187   };
00188   if(mauth) delete mauth;
00189   if(cauth) delete cauth;
00190   if(eval) delete eval;
00191   return result;
00192 }
00193 
00194 
00195 } // namespace ArcSec
00196