Back to index

nordugrid-arc-nox  1.1.0~rc6
XACMLTarget.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 <arc/security/ArcPDP/attr/AttributeValue.h>
00008 #include <arc/security/ArcPDP/attr/BooleanAttribute.h>
00009 #include <arc/security/ArcPDP/fn/EqualFunction.h>
00010 
00011 #include "XACMLPolicy.h"
00012 #include "XACMLRule.h"
00013 #include "XACMLTarget.h"
00014 
00015 static Arc::Logger logger(Arc::Logger::rootLogger, "XACMLTarget");
00016 
00017 using namespace Arc;
00018 using namespace ArcSec;
00019 
00020 XACMLTargetMatch::XACMLTargetMatch(XMLNode& node, EvaluatorContext* ctx) : matchnode(node), 
00021   attrval(NULL), function(NULL), selector(NULL), designator(NULL){
00022   attrfactory = (AttributeFactory*)(*ctx);
00023   fnfactory = (FnFactory*)(*ctx); 
00024 
00025   matchId = (std::string)(node.Attribute("MatchId"));
00026   //get the suffix of xacml-formated matchId, like
00027   //"urn:oasis:names:tc:xacml:1.0:function:string-equal",
00028   //and use it as the function name
00029   std::size_t found = matchId.find_last_of(":");
00030   std::string funcname = matchId.substr(found+1);
00031 
00032   //If matchId does not exist, compose the DataType and "equal" function
00033   //e.g. if the DataType of <AttributeValue> inside this <Match> is "string", then 
00034   //suppose the match function is "string-equal"
00035   std::string datatype = (std::string)(node["AttributeValue"].Attribute("DataType"));
00036   if(funcname.empty()) funcname = EqualFunction::getFunctionName(datatype); 
00037   
00038   //create the Function based on the function name
00039   function = fnfactory->createFn(funcname);
00040   if(!function) { logger.msg(ERROR, "Can not create function %s", funcname); return; }
00041 
00042   //create the AttributeValue, AttributeDesignator and AttributeSelector
00043   XMLNode cnd;
00044 
00045   XMLNode attrval_nd;
00046   std::string attrval_id;
00047   std::string attrval_type;
00048   for(int i = 0;;i++ ) {
00049     cnd = node.Child(i);
00050     if(!cnd) break;
00051     std::string name = cnd.Name();
00052     if(name.find("AttributeValue") != std::string::npos) {
00053        std::string data_type = cnd.Attribute("DataType");
00054        //<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
00055        //  http://www.med.example.com/schemas/record.xsd
00056        //</AttributeValue>
00057        attrval_nd = cnd;
00058        std::size_t f = data_type.find_last_of("#"); //http://www.w3.org/2001/XMLSchema#string
00059        if(f!=std::string::npos) {
00060          attrval_type = data_type.substr(f+1);
00061        }
00062        else {
00063          f=data_type.find_last_of(":"); //urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name
00064          attrval_type = data_type.substr(f+1);
00065        }
00066     }
00067     else if(name.find("AttributeSelector") != std::string::npos) {
00068       selector = new AttributeSelector(cnd, attrfactory);
00069       attrval_id = (std::string)(cnd.Attribute("AttributeId"));   
00070     }
00071     else if(name.find("AttributeDesignator") != std::string::npos) {
00072       designator = new AttributeDesignator(cnd, attrfactory);
00073       attrval_id = (std::string)(cnd.Attribute("AttributeId"));
00074     }
00075   }
00076   //kind of hack here. Because in xacml, <AttributeValue/> (the policy side)
00077   //normally xml attribute "AttributeId" is absent, but in our implementation 
00078   //about comparing two attribute, "AttributeId" is required.
00079   attrval_nd.NewAttribute("AttributeId") = attrval_id;
00080   attrval = attrfactory->createValue(attrval_nd, attrval_type);
00081 }
00082 
00083 XACMLTargetMatch::~XACMLTargetMatch() {
00084   if(attrval != NULL) delete attrval;
00085   if(selector != NULL) delete selector;
00086   if(designator != NULL) delete designator;
00087 }
00088 
00089 MatchResult XACMLTargetMatch::match(EvaluationCtx* ctx) {
00090   std::list<AttributeValue*> attrlist;
00091   if(selector != NULL) attrlist = selector->evaluate(ctx);
00092   else if(designator != NULL) attrlist = designator->evaluate(ctx);
00093 
00094   AttributeValue* evalres = NULL;
00095   std::list<AttributeValue*>::iterator i;
00096   for(i = attrlist.begin(); i != attrlist.end(); i++) {
00097 std::cout<<"Request side: "<<(*i)->encode()<<" Policy side:  "<<attrval->encode()<<std::endl;
00098     evalres = function->evaluate(attrval, (*i), false);
00099     BooleanAttribute bool_attr(true);
00100     if((evalres != NULL) && (evalres->equal(&bool_attr))) { 
00101       std::cout<<"Matched!"<<std::endl; 
00102       delete evalres; break; 
00103     }
00104     if(evalres) delete evalres;
00105   }
00106   while(!(attrlist.empty())) {
00107     AttributeValue* val = attrlist.back();
00108     attrlist.pop_back();
00109     delete val;
00110   }
00111   if(evalres) return MATCH;
00112   else return NO_MATCH;
00113 }
00114 
00115 
00116 XACMLTargetMatchGroup::XACMLTargetMatchGroup(XMLNode& node, EvaluatorContext* ctx) : matchgrpnode(node) {
00117   XMLNode cnd;
00118   std::string name;
00119   for(int i = 0;;i++ ) {
00120     cnd = node.Child(i);
00121     if(!cnd) break;
00122     name = cnd.Name();
00123     if(name.find("Match") != std::string::npos)
00124       matches.push_back(new XACMLTargetMatch(cnd, ctx));
00125   }
00126 }
00127 
00128 XACMLTargetMatchGroup::~XACMLTargetMatchGroup() {
00129   while(!(matches.empty())) {
00130     XACMLTargetMatch* tm = matches.back();
00131     matches.pop_back();
00132     delete tm;
00133   }
00134 }
00135 
00136 MatchResult XACMLTargetMatchGroup::match(EvaluationCtx* ctx) {
00137   MatchResult res;
00138   std::list<XACMLTargetMatch*>::iterator i;
00139   for(i = matches.begin(); i!= matches.end(); i++) {
00140     res = (*i)->match(ctx);
00141     if(res == MATCH) break;
00142   }
00143   return res;
00144 }
00145 
00146 
00147 XACMLTargetSection::XACMLTargetSection(Arc::XMLNode& node, EvaluatorContext* ctx) : sectionnode(node) {
00148   XMLNode cnd;
00149   std::string name;
00150   for(int i = 0;;i++ ) {
00151     cnd = node.Child(i);
00152     if(!cnd) break;
00153     name = cnd.Name();
00154     if(name == "Subject" || name == "Resource" || 
00155       name == "Action" || name == "Environment" || 
00156       name == "AnySubject" || name == "AnyResource" || 
00157       name == "AnyAction" || name == "AnyEnvironment") {
00158       groups.push_back(new XACMLTargetMatchGroup(cnd, ctx));
00159     }
00160     if(name == "AnySubject" || name == "AnyResource" ||
00161       name == "AnyAction" || name == "AnyEnvironment") break;
00162   }
00163 
00164 }
00165 
00166 XACMLTargetSection::~XACMLTargetSection() {
00167   while(!(groups.empty())) {
00168     XACMLTargetMatchGroup* grp = groups.back();
00169     groups.pop_back();
00170     delete grp;
00171   }
00172 }
00173 
00174 MatchResult XACMLTargetSection::match(EvaluationCtx* ctx) {
00175   MatchResult res;
00176   std::list<XACMLTargetMatchGroup*>::iterator i;
00177   for(i = groups.begin(); i!= groups.end(); i++) {
00178     res = (*i)->match(ctx);
00179     if(res == MATCH) break;
00180   }
00181   return res;
00182 }
00183 
00184 
00185 XACMLTarget::XACMLTarget(Arc::XMLNode& node, EvaluatorContext* ctx) : targetnode(node) {
00186   XMLNode cnd;
00187   std::string name;
00188   for(int i = 0;;i++ ) {
00189     cnd = node.Child(i);
00190     if(!cnd) break;
00191     name = cnd.Name();
00192     if(name == "Subjects" || name == "Resources" ||
00193       name == "Actions" || name == "Environments") {
00194       sections.push_back(new XACMLTargetSection(cnd, ctx));
00195     }
00196   }
00197 }
00198 
00199 XACMLTarget::~XACMLTarget() {
00200   while(!(sections.empty())) {
00201     XACMLTargetSection* section = sections.back();
00202     sections.pop_back();
00203     delete section;
00204   }
00205 }
00206 
00207 MatchResult XACMLTarget::match(EvaluationCtx* ctx) {
00208   MatchResult res;
00209   std::list<XACMLTargetSection*>::iterator i;
00210   for(i = sections.begin(); i!= sections.end(); i++) {
00211     res = (*i)->match(ctx);
00212     if(res != MATCH) break;
00213   }
00214   return res;
00215 }
00216