Back to index

nordugrid-arc-nox  1.1.0~rc6
arcdecision.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <stdexcept>
00006 
00007 #include <iostream>
00008 #include <fstream>
00009 #include <cstdlib>
00010 #include <glibmm/stringutils.h>
00011 #include <glibmm/fileutils.h>
00012 #include <glibmm.h>
00013 
00014 #include <arc/XMLNode.h>
00015 #include <arc/ArcConfig.h>
00016 #include <arc/StringConv.h>
00017 #include <arc/URL.h>
00018 #include <arc/User.h>
00019 #include <arc/Utils.h>
00020 #include <arc/UserConfig.h>
00021 #include <arc/message/MCC.h>
00022 #include <arc/client/ClientInterface.h>
00023 #include <arc/ArcLocation.h>
00024 #include <arc/OptionParser.h>
00025 #include <arc/GUID.h>
00026 #include <arc/credential/Credential.h>
00027 
00028 //#include <arc/xmlsec/XmlSecUtils.h>
00029 //#include <arc/xmlsec/XMLSecNode.h>
00030 
00031 #define SAML_NAMESPACE "urn:oasis:names:tc:SAML:2.0:assertion"
00032 #define SAMLP_NAMESPACE "urn:oasis:names:tc:SAML:2.0:protocol"
00033 #define XACML_SAMLP_NAMESPACE "urn:oasis:xacml:2.0:saml:protocol:schema:os"
00034 
00035 #define XENC_NAMESPACE   "http://www.w3.org/2001/04/xmlenc#"
00036 #define DSIG_NAMESPACE   "http://www.w3.org/2000/09/xmldsig#"
00037 
00038 int main(int argc, char* argv[]){
00039 
00040     setlocale(LC_ALL, "");
00041 
00042     Arc::LogStream logcerr(std::cerr);
00043     logcerr.setFormat(Arc::ShortFormat);
00044     Arc::Logger::getRootLogger().addDestination(logcerr);
00045     Arc::Logger::getRootLogger().setThreshold(Arc::WARNING);
00046 
00047     Arc::ArcLocation::Init(argv[0]);
00048 
00049     Arc::OptionParser options(istring("service_url request_file"));
00050 
00051     std::string service_url;
00052     options.AddOption('s', "service",
00053                       istring("url of the policy decision service"),
00054                       istring("string"), service_url);
00055 
00056     std::string request_path;
00057     options.AddOption('r', "request",
00058                       istring("path to request file"),
00059                       istring("path"), request_path);
00060 
00061     bool use_saml = false;
00062     options.AddOption('p', "saml", istring("use SAML 2.0 profile of XACML v2.0 to contact the service"), use_saml);
00063 
00064     std::string config_path;
00065     options.AddOption('c', "config",
00066                       istring("path to config file"),
00067                       istring("path"), config_path);
00068 
00069     int timeout = -1;
00070     options.AddOption('t', "timeout", istring("timeout in seconds (default 20)"),
00071                       istring("seconds"), timeout);
00072                       
00073     std::string debug;
00074     options.AddOption('d', "debug",
00075                       istring("FATAL, ERROR, WARNING, INFO, VERBOSE or DEBUG"),
00076                       istring("debuglevel"), debug);
00077 
00078     bool version = false;
00079     options.AddOption('v', "version", istring("print version information"),
00080                       version);
00081 
00082     std::list<std::string> params = options.Parse(argc, argv);
00083 
00084     // If debug is specified as argument, it should be set before loading the configuration.
00085     if (!debug.empty())
00086       Arc::Logger::getRootLogger().setThreshold(Arc::string_to_level(debug));
00087 
00088     Arc::UserConfig usercfg(config_path, Arc::initializeCredentialsType(Arc::initializeCredentialsType::RequireCredentials));
00089     if (!usercfg) {
00090       std::cerr<<"Failed configuration initialization"<<std::endl;
00091       return EXIT_FAILURE;
00092     }
00093   
00094     if (debug.empty() && !usercfg.Verbosity().empty())
00095       Arc::Logger::getRootLogger().setThreshold(Arc::string_to_level(usercfg.Verbosity()));
00096 
00097     if (timeout > 0)
00098       usercfg.Timeout(timeout);
00099   
00100     if (version) {
00101         std::cout << Arc::IString("%s version %s", "arcdecision", VERSION)
00102                   << std::endl;
00103         return 0;
00104     }
00105 
00106     try{
00107       const std::string& key_path = usercfg.KeyPath();
00108       const std::string& cert_path = usercfg.CertificatePath();
00109       const std::string& proxy_path = usercfg.ProxyPath();
00110       const std::string& ca_dir = usercfg.CACertificatesDirectory();
00111       const std::string& ca_file = usercfg.CACertificatePath();
00112       //Create a SOAP client
00113       Arc::URL url(service_url);
00114       if(!url) throw std::invalid_argument("Can't parse specified URL");
00115       Arc::MCCConfig cfg;
00116       if(!proxy_path.empty()) cfg.AddProxy(proxy_path);
00117       if(!cert_path.empty()) cfg.AddCertificate(cert_path);
00118       if(!key_path.empty()) cfg.AddPrivateKey(key_path);
00119       if(!ca_dir.empty()) cfg.AddCADir(ca_dir);
00120       if(!ca_file.empty()) cfg.AddCAFile(ca_file);
00121 
00122       Arc::ClientSOAP client(cfg,url,usercfg.Timeout());
00123 
00124       // Read the request from file to string
00125       std::ifstream requestfile(request_path.c_str());
00126       std::string request_str;
00127       if (!requestfile)
00128         throw std::invalid_argument("Could not open " + request_path);
00129       getline(requestfile, request_str, '\0');
00130       Arc::XMLNode request_xml(request_str); 
00131 
00132       if(use_saml) {
00133         Arc::NS ns;
00134         ns["saml"] = SAML_NAMESPACE;
00135         ns["samlp"] = SAMLP_NAMESPACE;
00136         ns["xacml-samlp"] = XACML_SAMLP_NAMESPACE; 
00137         Arc::XMLNode authz_query(ns, "xacml-samlp:XACMLAuthzDecisionQuery");
00138         std::string query_id = Arc::UUID();
00139         authz_query.NewAttribute("ID") = query_id;
00140         Arc::Time t;
00141         std::string current_time = t.str(Arc::UTCTime);
00142         authz_query.NewAttribute("IssueInstant") = current_time;
00143         authz_query.NewAttribute("Version") = std::string("2.0");
00144 
00145         Arc::Credential cred(cert_path.empty() ? proxy_path : cert_path, 
00146            cert_path.empty() ? proxy_path : key_path, ca_dir, ca_file);
00147         std::string local_dn_str = cred.GetDN();
00148         std::string local_dn = Arc::convert_to_rdn(local_dn_str);
00149         std::string issuer_name = local_dn;
00150         authz_query.NewChild("saml:Issuer") = issuer_name;
00151 
00152         authz_query.NewAttribute("InputContextOnly") = std::string("false");
00153         authz_query.NewAttribute("ReturnContext") = std::string("true");
00154 
00155         authz_query.NewChild(request_xml);
00156 
00157         Arc::NS req_ns;
00158         Arc::SOAPEnvelope req_env(req_ns);
00159         req_env.NewChild(authz_query);
00160         Arc::PayloadSOAP req(req_env);
00161 
00162         Arc::PayloadSOAP *resp = NULL;
00163         Arc::MCC_Status status = client.process(&req,&resp);
00164         if(!status) {
00165           std::cerr<<"Policy Decision Service invokation failed"<<std::endl;
00166           throw std::runtime_error("Policy Decision Service invokation failed");
00167         }
00168         if(resp == NULL) {
00169           std::cerr<<"There was no SOAP response"<<std::endl;
00170           throw std::runtime_error("There was no SOAP response");
00171         }
00172         std::string str;     
00173         resp->GetXML(str);
00174         std::cout<<"Response: "<<str<<std::endl;
00175 
00176         std::string authz_res = (std::string)((*resp)["samlp:Response"]["saml:Assertion"]["xacml-saml:XACMLAuthzDecisionStatement"]["xacml-context:Response"]["xacml-context:Result"]["xacml-context:Decision"]);
00177 
00178         if(resp) delete resp;
00179 
00180         if(authz_res == "Permit") { std::cout<<"Authorized from remote pdp service"<<std::endl; }
00181         else { std::cout<<"Unauthorized from remote pdp service"<<std::endl; }
00182 
00183       } else {
00184         //Invoke the remote pdp service
00185         Arc::NS req_ns;
00186         req_ns["pdp"] = "http://www.nordugrid.org/schemas/pdp";
00187         Arc::PayloadSOAP req(req_ns);
00188         Arc::XMLNode reqnode = req.NewChild("pdp:GetPolicyDecisionRequest");
00189         reqnode.NewChild(request_xml);
00190 
00191         std::string str;
00192         req.GetDoc(str);
00193         std::cout<<"SOAP message:"<<str<<std::endl;
00194 
00195         Arc::PayloadSOAP* resp = NULL;
00196         Arc::MCC_Status status = client.process(&req,&resp);
00197         if(!status) {
00198           std::cerr<<"Policy Decision Service invokation failed"<<std::endl;
00199           throw std::runtime_error("Policy Decision Service invokation failed");
00200         }
00201 
00202         if(resp == NULL) {
00203           std::cerr<<"There was no SOAP response"<<std::endl;
00204           throw std::runtime_error("There was no SOAP response");
00205         }
00206 
00207         resp->GetXML(str);
00208         std::cout<<"Response: "<<str<<std::endl;
00209 
00210         std::string authz_res = (std::string)((*resp)["pdp:GetPolicyDecisionResponse"]["response:Response"]["response:AuthZResult"]);
00211 
00212         if(resp) delete resp;
00213 
00214         if(authz_res == "PERMIT") { std::cout<<"Authorized from remote pdp service"<<std::endl; }
00215         else { std::cout<<"Unauthorized from remote pdp service"<<std::endl; }
00216       }      
00217       return EXIT_SUCCESS;
00218     } catch (std::exception& e){
00219       // Notify the user about the failure
00220       std::cerr << "ERROR: " << e.what() << std::endl;
00221       return EXIT_FAILURE;
00222     }
00223 }