Back to index

nordugrid-arc-nox  1.1.0~rc6
Classes | Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes
ArcSec::Charon Class Reference

A Service which includes the ArcPDP functionality; it can be deployed as an independent service to provide request evaluation functionality for the other remote services. More...

#include <charon.h>

Inheritance diagram for ArcSec::Charon:
Inheritance graph
Collaboration diagram for ArcSec::Charon:
Collaboration graph

List of all members.


class  PolicyLocation

Public Member Functions

 Charon (Arc::Config *cfg)
virtual ~Charon (void)
virtual Arc::MCC_Status process (Arc::Message &inmsg, Arc::Message &outmsg)
 Method for processing of requests and responses.
bool RegistrationCollector (Arc::XMLNode &doc)
 Service specific registartion collector, used for generate service registartions.
virtual void AddSecHandler (Config *cfg, ArcSec::SecHandler *sechandler, const std::string &label="")
 Add security components/handlers to this MCC.
virtual std::string getID ()
 Service may implement own service identitifer gathering method.

Protected Member Functions

Arc::MCC_Status make_soap_fault (Arc::Message &outmsg, const std::string &msg="")
bool load_policies (void)
bool policies_modified (void)
bool ProcessSecHandlers (Message &message, const std::string &label="") const
 Executes security handlers of specified queue.

Protected Attributes

Glib::Mutex lock_
Arc::NS ns_
Arc::Logger logger_
std::string endpoint_
std::string expiration_
std::list< PolicyLocationlocations_
std::string evaluator_name_
std::map< std::string,
std::list< ArcSec::SecHandler * > > 
 Set of labeled authentication and authorization handlers.

Static Protected Attributes

static Logger logger
 Logger object used to print messages generated by this class.

Detailed Description

A Service which includes the ArcPDP functionality; it can be deployed as an independent service to provide request evaluation functionality for the other remote services.

Definition at line 16 of file charon.h.

Constructor & Destructor Documentation

Definition at line 263 of file charon.cpp.

                            :RegisteredService(cfg), logger_(Arc::Logger::rootLogger, "Charon"), eval(NULL) {
  // Define supported namespaces

  //Load the Evaluator object
  evaluator_name_ = (std::string)((*cfg)["Evaluator"].Attribute("name"));
  logger.msg(Arc::INFO, "Evaluator: %s", evaluator_name_);

  //Get the policy location, and put it into evaluator
  Arc::XMLNode policystore = (*cfg)["PolicyStore"];
  Arc::XMLNode location = policystore["Location"];
  for(;(bool)location;++location) {
    std::string policyfile = location;
    std::string autoreload = location.Attribute("AutoReload");
    bool autoreload_b = true;
    if((autoreload == "false") || (autoreload == "0")) autoreload_b = false;
    if(policyfile.empty()) continue;
    logger.msg(Arc::INFO, "Policy location: %s", policyfile);

Here is the call graph for this function:

ArcSec::Charon::~Charon ( void  ) [virtual]

Definition at line 322 of file charon.cpp.

    delete eval;
  eval = NULL;

Member Function Documentation

void Arc::Service::AddSecHandler ( Config cfg,
ArcSec::SecHandler sechandler,
const std::string &  label = "" 
) [virtual, inherited]

Add security components/handlers to this MCC.

For more information please see description of MCC::AddSecHandler

Definition at line 14 of file Service.cpp.

    if(sechandler) {
        sechandlers_[label].push_back(sechandler); //need polishing to put the SecHandlerFactory->getinstance here
        XMLNode cn = (*cfg)["SecHandler"];
        Config cfg_(cn);

Here is the caller graph for this function:

virtual std::string Arc::Service::getID ( ) [inline, virtual, inherited]

Service may implement own service identitifer gathering method.

This method return identifier of service which is used for registering it Information Services.

Reimplemented in ARex::ARexService.

Definition at line 69 of file Service.h.

{ return ""; };
bool ArcSec::Charon::load_policies ( void  ) [protected]

Definition at line 297 of file charon.cpp.

  ArcSec::EvaluatorLoader eval_loader;
  if(eval) delete eval;
  eval = eval_loader.getEvaluator(evaluator_name_);
  if(eval == NULL) {
    logger.msg(Arc::ERROR, "Can not dynamically produce Evaluator");
    return false;
  else logger.msg(Arc::INFO, "Succeeded to produce Evaluator");
  for(std::list<PolicyLocation>::iterator p = locations_.begin();
                   p != locations_.end(); ++p) {
    logger.msg(Arc::VERBOSE, "Loading policy from %s",p->path);
    SourceFile source(p->path);
    if(!source) {
      logger.msg(Arc::ERROR, "Failed loading policy from %s",p->path);
      delete eval;
      eval = NULL;
      return false;
  return true;

Here is the call graph for this function:

Here is the caller graph for this function:

Arc::MCC_Status ArcSec::Charon::make_soap_fault ( Arc::Message outmsg,
const std::string &  msg = "" 
) [protected]

Definition at line 44 of file charon.cpp.

  Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_,true);
  Arc::SOAPFault* fault = outpayload?outpayload->Fault():NULL;
  if(fault) {
    if(msg.empty()) {
      fault->Reason("Failed processing request");
    } else {
  return Arc::MCC_Status(Arc::STATUS_OK);

Here is the call graph for this function:

Here is the caller graph for this function:

bool ArcSec::Charon::policies_modified ( void  ) [protected]

Definition at line 289 of file charon.cpp.

  for(std::list<PolicyLocation>::iterator p = locations_.begin();
                   p != locations_.end(); ++p) {
    if(p->IsModified()) return true;
  return false;

Here is the caller graph for this function:

Arc::MCC_Status ArcSec::Charon::process ( Arc::Message request,
Arc::Message response 
) [virtual]

Method for processing of requests and responses.

This method is called by preceeding MCC in chain when a request needs to be processed. This method must call similar method of next MCC in chain unless any failure happens. Result returned by call to next MCC should be processed and passed back to previous MCC. In case of failure this method is expected to generate valid error response and return it back to previous MCC without calling the next one.

requestThe request that needs to be processed.
responseA Message object that will contain the response of the request when the method returns.
An object representing the status of the call.

Implements Arc::MCCInterface.

Definition at line 59 of file charon.cpp.


  std::string method = inmsg.Attributes()->get("HTTP:METHOD");

  // Identify which of served endpoints request is for.
  // Charon can only accept POST method
  if(method == "POST") {
    logger.msg(Arc::VERBOSE, "process: POST");
    // Both input and output are supposed to be SOAP
    // Extracting payload
    Arc::PayloadSOAP* inpayload = NULL;
    try {
      inpayload = dynamic_cast<Arc::PayloadSOAP*>(inmsg.Payload());
    } catch(std::exception& e) { };
    if(!inpayload) {
      logger.msg(Arc::ERROR, "input is not SOAP");
      return make_soap_fault(outmsg);
    // Analyzing request
    Arc::XMLNode request = (*inpayload)["GetPolicyDecisionRequest"];
    if(!request) {
      request = (*inpayload)["XACMLAuthzDecisionQuery"];
      if(!request) {
        logger.msg(Arc::ERROR, "soap body does not include any request node");
        return make_soap_fault(outmsg);
      std::string req_xml;
      logger.msg(Arc::VERBOSE, "Request: %s",req_xml);

    Arc::XMLNode arc_requestnd;
    bool use_saml = false;
    std::string request_name = request.Name();
    if(request_name.find("GetPolicyDecisionRequest") != std::string::npos)
      arc_requestnd = request["Request"];
    else if(request_name.find("XACMLAuthzDecisionQuery") != std::string::npos) {
      arc_requestnd = request["Request"];
      use_saml = true;
    if(!arc_requestnd) {
      logger.msg(Arc::ERROR, "request node is empty");
      return make_soap_fault(outmsg);

    if(!eval) {
      logger.msg(Arc::ERROR, "Evaluator is not initialized");
      return make_soap_fault(outmsg,"Internal policy processing error");

    //Call the functionality of policy engine
    //Here the decision algorithm is the same as that in ArcPDP.cpp,
    //so this algorithm implicitly applies to policy with Arc format;
    //for xacml policy (the "rlist" will only contains one item), this 
    //decision algorithm also applies.
    Response *resp = NULL;
    // Evaluator stores results inside, hence can't be used multi-threaded
    // TODO: fix multi-threading for Evaluator
    Glib::Mutex::Lock eval_lock(lock_);
    if(policies_modified()) {
      logger.msg(Arc::INFO, "Policy(ies) modified - reloading evaluator");
    resp = eval->evaluate(Source(arc_requestnd));
    ResponseList rlist = resp->getResponseItems();
    int size = rlist.size();
    int i;

    bool atleast_onedeny = false;
    bool atleast_onepermit = false;

    for(i = 0; i < size; i++){
      ResponseItem* item = rlist[i];
      RequestTuple* tp = item->reqtp;

      if(item->res == DECISION_DENY)
        atleast_onedeny = true;
      if(item->res == DECISION_PERMIT)
        atleast_onepermit = true;
      if(tp) {
        Subject::iterator it;
        Subject subject = tp->sub;
        for (it = subject.begin(); it!= subject.end(); it++){
          AttributeValue *attrval;
          RequestAttribute *attr;
          attr = dynamic_cast<RequestAttribute*>(*it);
            attrval = (*it)->getAttributeValue();
            if(attrval) logger.msg(Arc::INFO, "%s", (attrval->encode()));

    bool result = false;
    if(atleast_onedeny) result = false;
    else if(!atleast_onedeny && atleast_onepermit) result = true;
    else if(!atleast_onedeny && !atleast_onepermit) result = false;

    if(result) logger.msg(Arc::INFO, "Authorized from Charon service");
    else logger.msg(Arc::ERROR, "Not authorized from Charon service; Some of the RequestItem does not satisfy Policy");

    // Put those request items which satisfy the policies into the 
    // response SOAP message (implicitly means the decision result: 
    // <ItemA, permit>, <ItemB, permit>, <ItemC, deny> (ItemC will 
    // not be in the response SOAP message).
    // The client of the pdpservice (normally a policy enforcement 
    // point, like job executor) is supposed to compose the policy
    // decision request to pdpservice by parsing the information 
    // from the request (aiming to the client itself), and permit 
    // or deny the request by using the information responded from 
    // pdpservice; Here pdpservice only gives some coarse decision 
    // to pdpservice invoker.
    if(!use_saml) {
      Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_);
      Arc::XMLNode response = outpayload->NewChild("pdp:GetPolicyDecisionResponse");
      Arc::XMLNode arc_responsend = response.NewChild("response:Response");
      Arc::XMLNode authz_res = arc_responsend.NewChild("response:AuthZResult");
      if(result) authz_res = "PERMIT";
      else authz_res = "DENY";

      for(i = 0; i<size; i++){
        ResponseItem* item = rlist[i];
        if(item->res == DECISION_PERMIT)

    } else {
      Arc::NS samlp_ns, saml_ns;
      samlp_ns["samlp"] = SAMLP_NAMESPACE;
      saml_ns["saml"] = SAML_NAMESPACE;
      saml_ns["xsi"] = "";

      Arc::XMLNode authz_response(samlp_ns, "samlp:Response");
      std::string local_dn = inmsg.Attributes()->get("TLS:LOCALDN");
      std::string issuer_name = Arc::convert_to_rdn(local_dn);
      authz_response.NewChild("samlp:Issuer") = issuer_name;

      std::string response_id = Arc::UUID();
      authz_response.NewAttribute("ID") = response_id;
      std::string responseto_id = (std::string)(request.Attribute("ID"));
      authz_response.NewAttribute("InResponseTo") = responseto_id;
      Arc::Time t;
      std::string current_time = t.str(Arc::UTCTime);
      authz_response.NewAttribute("IssueInstant") = current_time;
      authz_response.NewAttribute("Version") = std::string("2.0");

      Arc::XMLNode status = authz_response.NewChild("samlp:Status");
      Arc::XMLNode statuscode = status.NewChild("samlp:StatusCode");
      std::string statuscode_value = "urn:oasis:names:tc:SAML:2.0:status:Success";
      statuscode.NewAttribute("Value") = statuscode_value;

      Arc::XMLNode assertion = authz_response.NewChild("saml:Assertion", saml_ns);
      assertion.NewAttribute("Version") = std::string("2.0");
      std::string assertion_id = Arc::UUID();
      assertion.NewAttribute("ID") = assertion_id;
      Arc::Time t1;
      std::string current_time1 = t1.str(Arc::UTCTime);
      assertion.NewAttribute("IssueInstant") = current_time1;
      assertion.NewChild("saml:Issuer") = issuer_name;

      Arc::NS xacml_saml_ns; xacml_saml_ns["xacml-saml"] = XACML_SAML_NAMESPACE;
      Arc::XMLNode authz_statement = assertion.NewChild("xacml-saml:XACMLAuthzDecisionStatement", xacml_saml_ns);
      //See "xacml-context" specification
      Arc::NS xacml_ns; xacml_ns["xacml-context"] = XACML_CONTEXT_NAMESPACE;
      Arc::XMLNode xacml_response = authz_statement.NewChild("xacml-context:Response", xacml_ns);
      Arc::XMLNode xacml_result = xacml_response.NewChild("xacml-context:Result");
      xacml_result.NewAttribute("ResourceId") = "resource-id"; //TODO
      if(result) xacml_result.NewChild("xacml-context:Decision") = "Permit";
      else xacml_result.NewChild("xacml-context:Decision") = "Deny"; //TODO: Indeterminate, NotApplicable
      //TODO: "xacml-context:Status"  "xacml:Obligations"

      Arc::NS soap_ns;
      Arc::SOAPEnvelope envelope(soap_ns);
      Arc::PayloadSOAP *outpayload = new Arc::PayloadSOAP(envelope);

      std::string tmp;
      std::cout<<"Output payload: "<<tmp<<std::endl;


    if(resp) delete resp;
    return Arc::MCC_Status(Arc::STATUS_OK);
  else {
    delete inmsg.Payload();
    logger.msg(Arc::VERBOSE, "process: %s: not supported",method);
    return Arc::MCC_Status(); 
  return Arc::MCC_Status();

Here is the call graph for this function:

bool Arc::Service::ProcessSecHandlers ( Message message,
const std::string &  label = "" 
) const [protected, inherited]

Executes security handlers of specified queue.

For more information please see description of MCC::ProcessSecHandlers

Definition at line 22 of file Service.cpp.

    std::map<std::string,std::list<ArcSec::SecHandler*> >::const_iterator q = sechandlers_.find(label);
    if(q == sechandlers_.end()) {
        logger.msg(DEBUG, "No security processing/check requested for '%s'", label);
        return true;

    std::list<ArcSec::SecHandler*>::const_iterator h = q->second.begin();
    for(;h!=q->second.end();++h) {
        const ArcSec::SecHandler* handler = *h;
        if(handler) if(!(handler->Handle(&message))) {
            logger.msg(DEBUG, "Security processing/check for '%s' failed", label);
            return false;
    logger.msg(DEBUG, "Security processing/check for '%s' passed", label);
    return true;

Here is the call graph for this function:

Here is the caller graph for this function:

Service specific registartion collector, used for generate service registartions.

In implemented service this method should generate GLUE2 document with part of service description which service wishes to advertise to Information Services.

Reimplemented from Arc::Service.

Definition at line 328 of file charon.cpp.

  Arc::NS isis_ns; isis_ns["isis"] = "";
  Arc::XMLNode regentry(isis_ns, "RegEntry");
  regentry.NewChild("SrcAdv").NewChild("Type") = "";
  return true;

Here is the call graph for this function:

Member Data Documentation

std::string ArcSec::Charon::endpoint_ [protected]

Definition at line 30 of file charon.h.

Definition at line 34 of file charon.h.

std::string ArcSec::Charon::evaluator_name_ [protected]

Definition at line 33 of file charon.h.

std::string ArcSec::Charon::expiration_ [protected]

Definition at line 31 of file charon.h.

Definition at line 32 of file charon.h.

Glib::Mutex ArcSec::Charon::lock_ [protected]

Definition at line 27 of file charon.h.

Logger Arc::Service::logger [static, protected, inherited]

Logger object used to print messages generated by this class.

Reimplemented in Echo::Service_Echo, Arc::Service_JavaWrapper, SPService::Service_SP, Compiler::Service_Compiler, Hopi::Hopi, and Arc::Service_PythonWrapper.

Definition at line 43 of file Service.h.

Definition at line 29 of file charon.h.

Definition at line 28 of file charon.h.

std::map<std::string,std::list<ArcSec::SecHandler*> > Arc::Service::sechandlers_ [protected, inherited]

Set of labeled authentication and authorization handlers.

MCC calls sequence of handlers at specific point depending on associated identifier. in most aces those are "in" and "out" for incoming and outgoing messages correspondingly.

Definition at line 40 of file Service.h.

The documentation for this class was generated from the following files: