Back to index

nordugrid-arc-nox  1.1.0~rc6
GACLPolicy.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <list>
00006 
00007 #include "GACLPolicy.h"
00008 #include "GACLRequest.h"
00009 
00010 Arc::Logger ArcSec::GACLPolicy::logger(Arc::Logger::rootLogger, "GACLPolicy");
00011 
00012 Arc::Plugin* ArcSec::GACLPolicy::get_policy(Arc::PluginArgument* arg) {
00013   if(arg==NULL) return NULL;
00014   Arc::ClassLoaderPluginArgument* clarg =
00015           arg?dynamic_cast<Arc::ClassLoaderPluginArgument*>(arg):NULL;
00016   if(!clarg) return NULL;
00017   Arc::XMLNode* doc = (Arc::XMLNode*)(*clarg);
00018   if(doc==NULL) {
00019     std::cerr<<"GACLPolicy creation needs XMLNode as argument"<<std::endl;
00020     return NULL;
00021   };
00022   if(!(*doc)) return new ArcSec::GACLPolicy;
00023   ArcSec::GACLPolicy* policy = new ArcSec::GACLPolicy(*doc);
00024   if(!(*policy)) {
00025     delete policy;
00026     return NULL;
00027   };
00028   return policy;
00029 }
00030 
00031 //loader_descriptors __arc_policy_modules__  = {
00032 //    { "gacl.policy", 0, &ArcSec::GACLPolicy::get_policy },
00033 //    { NULL, 0, NULL }
00034 //};
00035 
00036 using namespace Arc;
00037 using namespace ArcSec;
00038 
00039 GACLPolicy::GACLPolicy(void) : Policy() {
00040   NS ns;
00041   policynode.Replace(XMLNode(ns,"gacl"));
00042 }
00043 
00044 GACLPolicy::GACLPolicy(const XMLNode node) : Policy(node) {
00045   if((!node) || (node.Size() == 0)) {
00046     logger.msg(ERROR,"Policy is empty");
00047     return;
00048   };
00049   if(node.Name() != "gacl") {
00050     logger.msg(ERROR,"Policy is not gacl");
00051     return;
00052   };
00053   node.New(policynode);
00054 }
00055 
00056 GACLPolicy::GACLPolicy(const Source& source) : Policy(source.Get()) {
00057   XMLNode node = source.Get();
00058   if((!node) || (node.Size() == 0)) {
00059     logger.msg(ERROR,"Policy is empty");
00060     return;
00061   };
00062   if(node.Name() != "gacl") {
00063     logger.msg(ERROR,"Policy is not gacl");
00064     return;
00065   };
00066   node.New(policynode);
00067 }
00068 
00069 static bool CompareIdentity(XMLNode pid,XMLNode rid) {
00070   if(pid.Size() > 0) {
00071     for(int n=0;;++n) {
00072       XMLNode pitem = pid.Child(n);
00073       XMLNode ritem = rid[pitem.Name()];
00074       for(;(bool)ritem;++ritem) {
00075         if(CompareIdentity(pitem,ritem)) break;
00076       };
00077       if(!ritem) return false;
00078     };
00079     return true;
00080   };
00081   return (((std::string)pid) == ((std::string)rid));
00082 }
00083 
00084 static void CollectActions(XMLNode actions,std::list<std::string>& actions_list) {
00085   for(int n = 0;;++n) {
00086     XMLNode action = actions.Child(n);
00087     if(!action) break;
00088     actions_list.push_back(action.Name());
00089   };
00090 }
00091 
00092 static bool FindAction(const std::string& action,const std::list<std::string>& actions) {
00093   for(std::list<std::string>::const_iterator act = actions.begin();act!=actions.end();++act) {
00094     if((*act) == action) return true;
00095   };
00096   return false;
00097 }
00098 
00099 Result GACLPolicy::eval(EvaluationCtx* ctx){
00100   if(!ctx) return DECISION_INDETERMINATE;
00101   Request* req = ctx->getRequest();
00102   if(!req) return DECISION_INDETERMINATE;
00103   GACLRequest* greq = dynamic_cast<GACLRequest*>(req);
00104   if(!greq) return DECISION_INDETERMINATE;
00105   // Although it is possible to split GACL request and policy to 
00106   // attributes current implementation simply evaluates XMLs directly.
00107   // Doing it "right way" is TODO.
00108   //Result result = DECISION_DENY;
00109   XMLNode requestentry = greq->getXML();
00110   if(requestentry.Name() == "gacl") requestentry=requestentry["entry"];
00111   if(requestentry.Name() != "entry") return DECISION_INDETERMINATE;
00112   for(;(bool)requestentry;++requestentry) {
00113     XMLNode policyentry = policynode["entry"];  
00114     std::list<std::string> allow;
00115     std::list<std::string> deny;
00116     for(;(bool)policyentry;++policyentry) {
00117       bool matched = false;
00118       for(int n = 0;;++n) {
00119         XMLNode pid = policyentry.Child(n);
00120         if(!pid) break;
00121         if(pid.Name() == "allow") continue;
00122         if(pid.Name() == "deny") continue;
00123         if(pid.Name() == "any-user") { matched=true; break; };
00124         // TODO: somehow check if user really authenticated
00125         if(pid.Name() == "auth-user") { matched=true; break; };
00126         XMLNode rid = requestentry[pid.Name()];
00127         for(;(bool)rid;++rid) {
00128           if(CompareIdentity(pid,rid)) break;
00129         };
00130         if((bool)rid) { matched=true; break; };
00131       };
00132       if(matched) {
00133         XMLNode pallow = policyentry["allow"];
00134         XMLNode pdeny  = policyentry["deny"];
00135         CollectActions(pallow,allow);
00136         CollectActions(pdeny,deny);
00137       };
00138     };
00139     allow.sort(); allow.unique();
00140     deny.sort();  deny.unique();
00141     if(allow.empty()) return DECISION_DENY;
00142     std::list<std::string> rallow;
00143     CollectActions(requestentry["allow"],rallow);
00144     if(rallow.empty()) return DECISION_DENY; // Unlikely to happen 
00145     std::list<std::string>::iterator act = rallow.begin();
00146     for(;act!=rallow.end();++act) {
00147       if(!FindAction(*act,allow)) break;
00148       if(FindAction(*act,deny)) break;
00149     };
00150     if(act != rallow.end()) return DECISION_DENY;
00151     //if(act == rallow.end()) result=DECISION_PERMIT;
00152   };
00153   return DECISION_PERMIT;
00154   //return result;
00155 }
00156 
00157 EvalResult& GACLPolicy::getEvalResult(){
00158   return evalres;
00159 }
00160 
00161 void GACLPolicy::setEvalResult(EvalResult& res){
00162   evalres = res;
00163 }
00164 
00165 GACLPolicy::~GACLPolicy(){
00166 }