Back to index

nordugrid-arc-nox  1.1.0~rc6
delegation.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <iostream>
00006 #include <sys/types.h>
00007 
00008 #include <arc/DateTime.h>
00009 #include <arc/loader/Loader.h>
00010 #include <arc/message/PayloadSOAP.h>
00011 #include <arc/message/PayloadRaw.h>
00012 #include <arc/message/PayloadStream.h>
00013 #include <arc/credential/Credential.h>
00014 #include <arc/Thread.h>
00015 
00016 #include "delegation.h"
00017 
00018 namespace ArcSec {
00019 
00020 #define ARC_DELEGATION_NAMESPACE "http://www.nordugrid.org/schemas/delegation"
00021 
00022 //static Arc::LogStream logcerr(std::cerr);
00023 
00024 static Arc::Plugin* get_service(Arc::PluginArgument* arg) {
00025     Arc::ServicePluginArgument* srvarg =
00026             arg?dynamic_cast<Arc::ServicePluginArgument*>(arg):NULL;
00027     if(!srvarg) return NULL;
00028     return new Service_Delegation((Arc::Config*)(*srvarg));
00029 }
00030 
00031 Arc::MCC_Status Service_Delegation::make_soap_fault(Arc::Message& outmsg) {
00032   Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_,true);
00033   Arc::SOAPFault* fault = outpayload?outpayload->Fault():NULL;
00034   if(fault) {
00035     fault->Code(Arc::SOAPFault::Sender);
00036     fault->Reason("Failed processing delegation request");
00037   };
00038   outmsg.Payload(outpayload);
00039   return Arc::MCC_Status(Arc::STATUS_OK);
00040 }
00041 
00042 class Service_Delegation::CredentialCache {
00043  public:
00044   time_t start_;
00045   std::string credential_;
00046   std::string id_;
00047   std::string credential_identity_;
00048   std::string credential_delegator_ip_;
00049   CredentialCache(void):start_(time(NULL)) {
00050   };
00051   CredentialCache(const std::string& cred):start_(time(NULL)),credential_(cred) {
00052   };
00053   CredentialCache& operator=(const std::string& cred) {
00054     credential_=cred; start_=time(NULL); return *this;
00055   };
00056 }; 
00057 
00058 Arc::MCC_Status Service_Delegation::process(Arc::Message& inmsg,Arc::Message& outmsg) {
00059   std::string method = inmsg.Attributes()->get("HTTP:METHOD");
00060 
00061   if(!ProcessSecHandlers(inmsg,"incoming")) {
00062     logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00063     return Arc::MCC_Status();
00064   };
00065 
00066   Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_);
00067   if(!outpayload) {
00068     logger_.msg(Arc::ERROR, "Can not create output SOAP payload for delegation service");
00069     return make_soap_fault(outmsg);
00070   };
00071 
00072   // Identify which of served endpoints request is for.
00073   // Delegation can only accept POST method
00074   if(method == "POST") {
00075     logger_.msg(Arc::VERBOSE, "process: POST");
00076     // Both input and output are supposed to be SOAP
00077     // Extracting payload
00078     Arc::PayloadSOAP* inpayload = NULL;
00079     try {
00080       inpayload = dynamic_cast<Arc::PayloadSOAP*>(inmsg.Payload());
00081     } catch(std::exception& e) { };
00082     if(!inpayload) {
00083       logger_.msg(Arc::ERROR, "input is not SOAP");
00084       delete outpayload;
00085       return make_soap_fault(outmsg);
00086     };
00087     // Analyzing request
00088     if((*inpayload)["DelegateCredentialsInit"]) {
00089       if(!deleg_service_->DelegateCredentialsInit(*inpayload,*outpayload)) {
00090         logger_.msg(Arc::ERROR, "Can not generate X509 request");
00091         delete outpayload;
00092         return make_soap_fault(outmsg);
00093       }
00094     } else if((*inpayload)["UpdateCredentials"]) {
00095       std::string cred;
00096       std::string identity;
00097       if(!deleg_service_->UpdateCredentials(cred,identity,*inpayload,*outpayload)) {
00098         logger_.msg(Arc::ERROR, "Can not store proxy certificate");
00099         delete outpayload;
00100         return make_soap_fault(outmsg);
00101       }
00102       logger_.msg(Arc::DEBUG,"Delegated credentials:\n %s",cred.c_str());
00103 
00104       CredentialCache* cred_cache = NULL;
00105       std::string id = (std::string)((*inpayload)["UpdateCredentials"]["DelegatedToken"]["Id"]);
00106       std::string credential_delegator_ip = inmsg.Attributes()->get("TCP:REMOTEHOST");
00107       cred_cache = new CredentialCache(cred);
00108       cred_cache->credential_delegator_ip_ = credential_delegator_ip;
00109       cred_cache->credential_identity_ = identity;
00110       cred_cache->id_ = id;
00111       id2cred_.insert(std::pair<std::string,CredentialCache*>(id,cred_cache));  
00112       identity2cred_.insert(std::pair<std::string,CredentialCache*>(identity,cred_cache)); 
00113 
00114       //Need some way to make other services get the proxy credential
00115 
00116     } else if((*inpayload)["AcquireCredentials"]) {
00117       CredentialCache* cred_cache = NULL;
00118       std::string cred;
00119       std::string id = (std::string)((*inpayload)["AcquireCredentials"]["DelegatedTokenLookup"]["Id"]);
00120       std::string cred_identity = (std::string)((*inpayload)["AcquireCredentials"]["DelegatedTokenLookup"]["CredIdentity"]);
00121       std::string cred_delegator_ip = (std::string)((*inpayload)["AcquireCredentials"]["DelegatedTokenLookup"]["CredDelegatorIP"]);
00122       std::string x509req_value = (std::string)((*inpayload)["AcquireCredentials"]["DelegatedTokenLookup"]["Value"]);
00123       if(!id.empty()) cred_cache = id2cred_.find(id)->second;
00124       else if(!cred_identity.empty() && !cred_delegator_ip.empty()) {
00125         Identity2CredMapReturn ret;
00126         Identity2CredMapIterator it;
00127         ret = identity2cred_.equal_range(cred_identity);
00128         for(it = ret.first; it!=ret.second; ++it) {
00129           cred_cache = (*it).second;
00130           if(!(cred_cache->credential_delegator_ip_).empty()) break;
00131         }
00132       }
00133       if(!cred_cache) {
00134         logger_.msg(Arc::ERROR, "Can not find the corresponding credential from credential cache");
00135         return make_soap_fault(outmsg);
00136       }; 
00137       cred = cred_cache->credential_;
00138 
00139       Arc::NS ns; ns["deleg"]=ARC_DELEGATION_NAMESPACE;
00140       Arc::XMLNode cred_resp = (*outpayload).NewChild("deleg:AcquireCredentialsResponse");
00141       Arc::XMLNode token = cred_resp.NewChild("deleg:DelegatedToken");
00142       token.NewChild("deleg:Id") = cred_cache->id_;
00143       token.NewAttribute("deleg:Format") = std::string("x509");
00144 
00145       //Sign the proxy certificate
00146       Arc::Time start;
00147       //Set proxy path length to be -1, which means infinit length
00148       Arc::Credential proxy(start,Arc::Period(12*3600), 0, "rfc", "inheritAll","",-1);
00149       Arc::Credential signer(cred, "", trusted_cadir, trusted_capath, "", false);
00150       std::string signedcert;
00151       proxy.InquireRequest(x509req_value);
00152       if(!(signer.SignRequest(&proxy, signedcert))) {
00153         logger_.msg(Arc::ERROR, "Signing proxy on delegation service failed");
00154         delete outpayload;
00155         return Arc::MCC_Status();
00156       }
00157 
00158       std::string signercert_str;
00159       std::string signercertchain_str;
00160       signer.OutputCertificate(signercert_str);
00161       signer.OutputCertificateChain(signercertchain_str);
00162       signedcert.append(signercert_str);
00163       signedcert.append(signercertchain_str);
00164 
00165       token.NewChild("deleg:Value") = signedcert;
00166 
00167       logger_.msg(Arc::DEBUG,"Delegated credentials:\n %s",signedcert.c_str());
00168     }
00169 
00170     //Compose response message
00171     outmsg.Payload(outpayload);
00172 
00173     if(!ProcessSecHandlers(outmsg,"outgoing")) {
00174       logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00175       delete outmsg.Payload(NULL);
00176       return Arc::MCC_Status();
00177     };
00178 
00179     return Arc::MCC_Status(Arc::STATUS_OK);
00180   }
00181   else {
00182     delete inmsg.Payload();
00183     logger_.msg(Arc::VERBOSE, "process: %s: not supported",method);
00184     return Arc::MCC_Status();
00185   }
00186   return Arc::MCC_Status();
00187 }
00188 
00189 Service_Delegation::Service_Delegation(Arc::Config *cfg):RegisteredService(cfg), 
00190     logger_(Arc::Logger::rootLogger, "Delegation_Service"), deleg_service_(NULL) {
00191 
00192   //logger_.addDestination(logcerr);
00193   ns_["delegation"]="http://www.nordugrid.org/schemas/delegation";
00194 
00195   deleg_service_ = new Arc::DelegationContainerSOAP;
00196   max_crednum_ = 1000;
00197   max_credlife_ = 43200;
00198 
00199   trusted_cadir = (std::string)((*cfg)["CACertificatesDir"]);
00200   trusted_capath = (std::string)((*cfg)["CACertificatePath"]);
00201 }
00202 
00203 Service_Delegation::~Service_Delegation(void) {
00204   if(deleg_service_) delete deleg_service_;
00205 }
00206 
00207 bool Service_Delegation::RegistrationCollector(Arc::XMLNode &doc) {
00208   Arc::NS isis_ns; isis_ns["isis"] = "http://www.nordugrid.org/schemas/isis/2008/08";
00209   Arc::XMLNode regentry(isis_ns, "RegEntry");
00210   regentry.NewChild("SrcAdv").NewChild("Type") = "org.nordugrid.security.delegation";
00211   regentry.New(doc);
00212   return true;
00213 }
00214 
00215 } // namespace ArcSec
00216 
00217 Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = {
00218     { "delegation.service", "HED:SERVICE", 0, &ArcSec::get_service },
00219     { NULL, NULL, 0, NULL }
00220 };
00221