Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Member Functions | Protected Attributes
Arc::DelegationProviderSOAP Class Reference

Extension of DelegationProvider with SOAP exchange interface. More...

#include <DelegationInterface.h>

Inheritance diagram for Arc::DelegationProviderSOAP:
Inheritance graph
[legend]
Collaboration diagram for Arc::DelegationProviderSOAP:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 DelegationProviderSOAP (const std::string &credentials)
 Creates instance from provided credentials.
 DelegationProviderSOAP (const std::string &cert_file, const std::string &key_file, std::istream *inpwd=NULL)
 Creates instance from provided credentials.
 ~DelegationProviderSOAP (void)
bool DelegateCredentialsInit (MCCInterface &mcc_interface, MessageContext *context)
 Performs DelegateCredentialsInit SOAP operation.
bool DelegateCredentialsInit (MCCInterface &mcc_interface, MessageAttributes *attributes_in, MessageAttributes *attributes_out, MessageContext *context)
 Extended version of DelegateCredentialsInit(MCCInterface&,MessageContext*).
bool UpdateCredentials (MCCInterface &mcc_interface, MessageContext *context, const DelegationRestrictions &restrictions=DelegationRestrictions())
 Performs UpdateCredentials SOAP operation.
bool UpdateCredentials (MCCInterface &mcc_interface, MessageAttributes *attributes_in, MessageAttributes *attributes_out, MessageContext *context, const DelegationRestrictions &restrictions=DelegationRestrictions())
 Extended version of UpdateCredentials(MCCInterface&,MessageContext*).
bool DelegatedToken (XMLNode parent)
 Generates DelegatedToken element.
const std::string & ID (void)
 Returns the identifier by service accepting delegated credentials.
 operator bool (void)
bool operator! (void)
std::string Delegate (const std::string &request, const DelegationRestrictions &restrictions=DelegationRestrictions())
 Perform delegation.

Protected Attributes

std::string request_
std::string id_

Detailed Description

Extension of DelegationProvider with SOAP exchange interface.

This class is also a temporary container for intermediate information used during delegation procedure.

Definition at line 114 of file DelegationInterface.h.


Constructor & Destructor Documentation

Arc::DelegationProviderSOAP::DelegationProviderSOAP ( const std::string &  credentials)

Creates instance from provided credentials.

Credentials are used to sign delegated credentials.

Definition at line 846 of file DelegationInterface.cpp.

                                                                          :DelegationProvider(credentials) {
}
Arc::DelegationProviderSOAP::DelegationProviderSOAP ( const std::string &  cert_file,
const std::string &  key_file,
std::istream *  inpwd = NULL 
)

Creates instance from provided credentials.

Credentials are used to sign delegated credentials. Arguments should contain filesystem path to PEM-encoded certificate and private key. Optionally cert_file may contain certificates chain.

Definition at line 849 of file DelegationInterface.cpp.

Definition at line 852 of file DelegationInterface.cpp.

                                                    {
}

Member Function Documentation

std::string Arc::DelegationProvider::Delegate ( const std::string &  request,
const DelegationRestrictions restrictions = DelegationRestrictions() 
) [inherited]

Perform delegation.

Takes X509 certificate request and creates proxy credentials excluding private key. Result is then to be fed into DelegationConsumer::Acquire

Definition at line 520 of file DelegationInterface.cpp.

                                                                                                          {
#ifdef HAVE_OPENSSL_PROXY
  X509 *cert = NULL;
  X509_REQ *req = NULL;
  BIO* in = NULL;
  EVP_PKEY *pkey = NULL;
  ASN1_INTEGER *sno = NULL;
  ASN1_OBJECT *obj= NULL;
  ASN1_OCTET_STRING* policy_string = NULL;
  X509_EXTENSION *ex = NULL;
  PROXY_CERT_INFO_EXTENSION proxy_info;
  PROXY_POLICY proxy_policy;
  const EVP_MD *digest = EVP_sha1();
  X509_NAME *subject = NULL;
  const char* need_ext = "critical,digitalSignature,keyEncipherment";
  std::string proxy_cn;
  std::string res;
  time_t validity_start = time(NULL);
  time_t validity_end = (time_t)(-1);
  DelegationRestrictions& restrictions_ = (DelegationRestrictions&)restrictions;
  std::string proxyPolicy;
  std::string proxyPolicyFile;

  if(!cert_) {
    std::cerr<<"Missing certificate chain"<<std::endl;
    return "";
  };
  if(!key_) {
    std::cerr<<"Missing private key"<<std::endl;
    return "";
  };

  in = BIO_new_mem_buf((void*)(request.c_str()),request.length());
  if(!in) goto err;

  if((!PEM_read_bio_X509_REQ(in,&req,NULL,NULL)) || (!req)) goto err;
  BIO_free_all(in); in=NULL;

 
  //subject=X509_REQ_get_subject_name(req);
  //char* buf = X509_NAME_oneline(subject, 0, 0);
  //std::cerr<<"subject="<<buf<<std::endl;
  //OPENSSL_free(buf);

  if((pkey=X509_REQ_get_pubkey(req)) == NULL) goto err;
  if(X509_REQ_verify(req,pkey) <= 0) goto err;

  cert=X509_new();
  if(!cert) goto err;
  //ci=x->cert_info;
  sno = ASN1_INTEGER_new();
  if(!sno) goto err;
  // TODO - serial number must be unique among generated by proxy issuer
  if(!rand_serial(sno)) goto err;
  if (!X509_set_serialNumber(cert,sno)) goto err;
  proxy_cn=tostring(ASN1_INTEGER_get(sno));
  ASN1_INTEGER_free(sno); sno=NULL;
  X509_set_version(cert,2L);

  /*
   Proxy certificates do not need KeyUsage extension. But
   some old software still expects it to be present.

   From RFC3820:

   If the Proxy Issuer certificate has the KeyUsage extension, the
   Digital Signature bit MUST be asserted.
  */

  X509_add_ext_by_nid(cert,NID_key_usage,(char*)need_ext,-1);

  /*
   From RFC3820:

   If a certificate is a Proxy Certificate, then the proxyCertInfo
   extension MUST be present, and this extension MUST be marked as
   critical.
  
   The pCPathLenConstraint field, if present, specifies the maximum
   depth of the path of Proxy Certificates that can be signed by this
   Proxy Certificate. 

   The proxyPolicy field specifies a policy on the use of this
   certificate for the purposes of authorization.  Within the
   proxyPolicy, the policy field is an expression of policy, and the
   policyLanguage field indicates the language in which the policy is
   expressed.

   *  id-ppl-inheritAll indicates that this is an unrestricted proxy
      that inherits all rights from the issuing PI.  An unrestricted
      proxy is a statement that the Proxy Issuer wishes to delegate all
      of its authority to the bearer (i.e., to anyone who has that proxy
      certificate and can prove possession of the associated private
      key).  For purposes of authorization, this an unrestricted proxy
      effectively impersonates the issuing PI.

   *  id-ppl-independent indicates that this is an independent proxy
      that inherits no rights from the issuing PI.  This PC MUST be
      treated as an independent identity by relying parties.  The only
      rights this PC has are those granted explicitly to it.
  */
  /*
  ex=X509V3_EXT_conf_nid(NULL,NULL,NID_proxyCertInfo,"critical,CA:FALSE");
  if(!ex) goto err;
  if(!X509_add_ext(cert,ex,-1)) goto err;
  X509_EXTENSION_free(ex); ex=NULL;
  */
  memset(&proxy_info,0,sizeof(proxy_info));
  memset(&proxy_policy,0,sizeof(proxy_policy));
  proxy_info.pcPathLengthConstraint=NULL;
  proxy_info.proxyPolicy=&proxy_policy;
  proxy_policy.policyLanguage=NULL;
  proxy_policy.policy=NULL;
  proxyPolicy=restrictions_["proxyPolicy"];
  proxyPolicyFile=restrictions_["proxyPolicyFile"];
  if(!proxyPolicyFile.empty()) {
    if(!proxyPolicy.empty()) goto err; // Two policies supplied
    std::ifstream is(proxyPolicyFile.c_str());
    std::getline(is,proxyPolicy,(char)0);
    if(proxyPolicy.empty()) goto err;
  };
  if(!proxyPolicy.empty()) {
    obj=OBJ_nid2obj(NID_id_ppl_anyLanguage);  // Proxy with policy
    if(!obj) goto err;
    policy_string=ASN1_OCTET_STRING_new();
    if(!policy_string) goto err;
    ASN1_OCTET_STRING_set(policy_string,(const unsigned char*)(proxyPolicy.c_str()),proxyPolicy.length());
    proxy_policy.policyLanguage=obj;
    proxy_policy.policy=policy_string;
  } else {
    obj=OBJ_nid2obj(NID_id_ppl_inheritAll);  // Unrestricted proxy
    if(!obj) goto err;
    proxy_policy.policyLanguage=obj;
  };
  if(X509_add1_ext_i2d(cert,NID_proxyCertInfo,&proxy_info,1,X509V3_ADD_REPLACE) != 1) goto err;
  if(policy_string) ASN1_OCTET_STRING_free(policy_string); policy_string=NULL;
  ASN1_OBJECT_free(obj); obj=NULL;
  /*
  PROXY_CERT_INFO_EXTENSION *pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL);
  typedef struct PROXY_CERT_INFO_EXTENSION_st {
        ASN1_INTEGER *pcPathLengthConstraint;
        PROXY_POLICY *proxyPolicy;
        } PROXY_CERT_INFO_EXTENSION;
  typedef struct PROXY_POLICY_st {
        ASN1_OBJECT *policyLanguage;
        ASN1_OCTET_STRING *policy;
        } PROXY_POLICY;
  */

  subject=X509_get_subject_name((X509*)cert_);
  if(!subject) goto err;
  subject=X509_NAME_dup(subject);
  if(!subject) goto err;
  if(!X509_set_issuer_name(cert,subject)) goto err;
  if(!X509_NAME_add_entry_by_NID(subject,NID_commonName,MBSTRING_ASC,(unsigned char*)(proxy_cn.c_str()),proxy_cn.length(),-1,0)) goto err;
  if(!X509_set_subject_name(cert,subject)) goto err;
  X509_NAME_free(subject); subject=NULL;
  if(!(restrictions_["validityStart"].empty())) {
    validity_start=Time(restrictions_["validityStart"]).GetTime();
  };
  if(!(restrictions_["validityEnd"].empty())) {
    validity_end=Time(restrictions_["validityEnd"]).GetTime();
  } else if(!(restrictions_["validityPeriod"].empty())) {
    validity_end=validity_start+Period(restrictions_["validityPeriod"]).GetPeriod();
  };
  //Set "notBefore"
  if( X509_cmp_time(X509_get_notBefore((X509*)cert_), &validity_start) < 0) {
    X509_time_adj(X509_get_notBefore(cert), 0L, &validity_start);
  }
  else {
    X509_set_notBefore(cert, X509_get_notBefore((X509*)cert_));
  }
  //Set "not After"
  if(validity_end == (time_t)(-1)) {
    X509_set_notAfter(cert,X509_get_notAfter((X509*)cert_));
  } else {
    X509_gmtime_adj(X509_get_notAfter(cert), (validity_end-validity_start));
  };
  X509_set_pubkey(cert,pkey);
  EVP_PKEY_free(pkey); pkey=NULL;

  if(!X509_sign(cert,(EVP_PKEY*)key_,digest)) goto err;
  /*
  {
    int pci_NID = NID_undef;
    ASN1_OBJECT * extension_oid = NULL;
    int nid;
    PROXY_CERT_INFO_EXTENSION* proxy_cert_info;
    X509_EXTENSION *                    extension;

    pci_NID = OBJ_sn2nid(SN_proxyCertInfo);
    for(i=0;i<X509_get_ext_count(cert);i++) {
        extension = X509_get_ext(cert,i);
        extension_oid = X509_EXTENSION_get_object(extension);
        nid = OBJ_obj2nid(extension_oid);
        if(nid == pci_NID) {
            CleanError();
            if((proxy_cert_info = (PROXY_CERT_INFO_EXTENSION*)(X509V3_EXT_d2i(extension))) == NULL) {
              goto err;
              std::cerr<<"X509V3_EXT_d2i failed"<<std::endl;
            }
            break;
        }
    }
  }
  */

  if(!x509_to_string(cert,res)) { res=""; goto err; };
  // Append chain of certificates
  if(!x509_to_string((X509*)cert_,res)) { res=""; goto err; };
  if(chain_) {
    for(int n=0;n<sk_X509_num((STACK_OF(X509) *)chain_);++n) {
      X509* v = sk_X509_value((STACK_OF(X509) *)chain_,n);
      if(!v) { res=""; goto err; };
      if(!x509_to_string(v,res)) { res=""; goto err; };
    };
  };

err:
  if(res.empty()) LogError();
  if(in) BIO_free_all(in);
  if(req) X509_REQ_free(req);
  if(pkey) EVP_PKEY_free(pkey);
  if(cert) X509_free(cert);
  if(sno) ASN1_INTEGER_free(sno);
  if(ex) X509_EXTENSION_free(ex);
  if(obj) ASN1_OBJECT_free(obj);
  if(subject) X509_NAME_free(subject);
  if(policy_string) ASN1_OCTET_STRING_free(policy_string);
  return res;
#else
  return "";
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

Performs DelegateCredentialsInit SOAP operation.

As result request for delegated credentials is received by this instance and stored internally. Call to UpdateCredentials should follow.

Definition at line 855 of file DelegationInterface.cpp.

                                                                                                    {
  MessageAttributes attributes_in;
  MessageAttributes attributes_out;
  return DelegateCredentialsInit(interface,&attributes_in,&attributes_out,context);
}

Here is the caller graph for this function:

bool Arc::DelegationProviderSOAP::DelegateCredentialsInit ( MCCInterface mcc_interface,
MessageAttributes attributes_in,
MessageAttributes attributes_out,
MessageContext context 
)

Extended version of DelegateCredentialsInit(MCCInterface&,MessageContext*).

Additionally takes attributes for request and response message to make fine control on message processing possible.

Definition at line 861 of file DelegationInterface.cpp.

                                                                                                                                                                       {
  NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
  PayloadSOAP req_soap(ns);
  req_soap.NewChild("deleg:DelegateCredentialsInit");
  Message req;
  Message resp;
  req.Attributes(attributes_in);
  req.Context(context);
  req.Payload(&req_soap);
  resp.Attributes(attributes_out);
  resp.Context(context);
  MCC_Status r = interface.process(req,resp);
  if(r != STATUS_OK) return false;
  if(!resp.Payload()) return false;
  PayloadSOAP* resp_soap = NULL;
  try {
    resp_soap=dynamic_cast<PayloadSOAP*>(resp.Payload());
  } catch(std::exception& e) { };
  if(!resp_soap) { delete resp.Payload(); return false; };
  XMLNode token = (*resp_soap)["DelegateCredentialsInitResponse"]["TokenRequest"];
  if(!token) { delete resp_soap; return false; };
  if(((std::string)(token.Attribute("Format"))) != "x509") { delete resp_soap; return false; };
  id_=(std::string)(token["Id"]);
  request_=(std::string)(token["Value"]);
  delete resp_soap;
  if(id_.empty() || request_.empty()) return false;
  return true;
}

Here is the call graph for this function:

Generates DelegatedToken element.

Element is created as child of provided XML element and contains structure described in delegation.wsdl.

Definition at line 927 of file DelegationInterface.cpp.

                                                          {
  if(id_.empty()) return false;
  if(request_.empty()) return false;
  std::string delegation = Delegate(request_);
  if(delegation.empty()) return false;
  NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
  parent.Namespaces(ns);
  XMLNode token = parent.NewChild("deleg:DelegatedToken");
  token.NewAttribute("deleg:Format")="x509";
  token.NewChild("deleg:Id")=id_;
  token.NewChild("deleg:Value")=delegation;
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const std::string& Arc::DelegationProviderSOAP::ID ( void  ) [inline]

Returns the identifier by service accepting delegated credentials.

This identifier may then be used to refer to credentials stored at service.

Definition at line 152 of file DelegationInterface.h.

{ return id_;};
Arc::DelegationProvider::operator bool ( void  ) [inline, inherited]

Definition at line 74 of file DelegationInterface.h.

{ return key_ != NULL; };
bool Arc::DelegationProvider::operator! ( void  ) [inline, inherited]

Definition at line 75 of file DelegationInterface.h.

{ return key_ == NULL; };

Performs UpdateCredentials SOAP operation.

This concludes delegation procedure and passes delagated credentials to DelegationConsumerSOAP instance.

Definition at line 890 of file DelegationInterface.cpp.

                                                                                                                                         {
  MessageAttributes attributes_in;
  MessageAttributes attributes_out;
  return UpdateCredentials(interface,&attributes_in,&attributes_out,context);
}

Here is the caller graph for this function:

bool Arc::DelegationProviderSOAP::UpdateCredentials ( MCCInterface mcc_interface,
MessageAttributes attributes_in,
MessageAttributes attributes_out,
MessageContext context,
const DelegationRestrictions restrictions = DelegationRestrictions() 
)

Extended version of UpdateCredentials(MCCInterface&,MessageContext*).

Additionally takes attributes for request and response message to make fine control on message processing possible.

Definition at line 896 of file DelegationInterface.cpp.

                                                                                                                                                                                                            {
  if(id_.empty()) return false;
  if(request_.empty()) return false;
  std::string delegation = Delegate(request_,restrictions);
  if(delegation.empty()) return false;
  NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
  PayloadSOAP req_soap(ns);
  XMLNode token = req_soap.NewChild("deleg:UpdateCredentials").NewChild("deleg:DelegatedToken");
  token.NewAttribute("deleg:Format")="x509";
  token.NewChild("deleg:Id")=id_;
  token.NewChild("deleg:Value")=delegation;
  Message req;
  Message resp;
  req.Attributes(attributes_in);
  req.Context(context);
  req.Payload(&req_soap);
  resp.Attributes(attributes_out);
  resp.Context(context);
  MCC_Status r = interface.process(req,resp);
  if(r != STATUS_OK) return false;
  if(!resp.Payload()) return false;
  PayloadSOAP* resp_soap = NULL;
  try {
    resp_soap=dynamic_cast<PayloadSOAP*>(resp.Payload());
  } catch(std::exception& e) { };
  if(!resp_soap) { delete resp.Payload(); return false; };
  if(!(*resp_soap)["UpdateCredentialsResponse"]) 
  delete resp_soap;
  return true;
}

Here is the call graph for this function:


Member Data Documentation

std::string Arc::DelegationProviderSOAP::id_ [protected]

Definition at line 117 of file DelegationInterface.h.

std::string Arc::DelegationProviderSOAP::request_ [protected]

Definition at line 116 of file DelegationInterface.h.


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