Back to index

nordugrid-arc-nox  1.1.0~rc6
test_client2voms_saml_service.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <string>
00006 #include <iostream>
00007 #include <fstream>
00008 #include <signal.h>
00009 
00010 #include <arc/ArcConfig.h>
00011 #include <arc/Logger.h>
00012 #include <arc/XMLNode.h>
00013 #include <arc/message/SOAPEnvelope.h>
00014 #include <arc/message/PayloadSOAP.h>
00015 #include <arc/message/MCC.h>
00016 #include <arc/StringConv.h>
00017 #include <arc/XMLNode.h>
00018 #include <arc/DateTime.h>
00019 #include <arc/GUID.h>
00020 #include <arc/credential/Credential.h>
00021 #include <arc/client/ClientInterface.h>
00022 #include <arc/URL.h>
00023 
00024 #ifdef WIN32
00025 #include <arc/win32.h>
00026 #endif
00027 
00028 #include "../../hed/libs/xmlsec/XmlSecUtils.h"
00029 #include "../../hed/libs/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 
00034 #define XENC_NAMESPACE   "http://www.w3.org/2001/04/xmlenc#"
00035 #define DSIG_NAMESPACE   "http://www.w3.org/2000/09/xmldsig#"
00036 
00039 int main(void) {
00040   signal(SIGTTOU,SIG_IGN);
00041   signal(SIGTTIN,SIG_IGN);
00042   signal(SIGPIPE,SIG_IGN);
00043   Arc::Logger logger(Arc::Logger::rootLogger, "SAMLTest");
00044   Arc::LogStream logcerr(std::cerr);
00045   Arc::Logger::rootLogger.addDestination(logcerr);
00046   
00047   // -------------------------------------------------------
00048   //    Compose request and send to voms saml service
00049   // -------------------------------------------------------
00050   //Compose request
00051   Arc::NS ns;
00052   ns["saml"] = SAML_NAMESPACE;
00053   ns["samlp"] = SAMLP_NAMESPACE;
00054 
00055   std::string cert("../../tests/echo/usercert.pem");
00056   std::string key("../../tests/echo/userkey-nopass.pem");
00057   std::string cafile("../../tests/echo/testcacert.pem");
00058   std::string cadir("../../tests/echo/certificates");
00059 
00060   Arc::Credential cred(cert, key, cadir, cafile);
00061   std::string local_dn_str = cred.GetDN();
00062   std::string local_dn;
00063   size_t pos1 = std::string::npos;
00064   size_t pos2;
00065   do { //The DN should be like "CN=test,O=UiO,ST=Oslo,C=NO", so we need to change the format here
00066     std::string str;
00067     pos2 = local_dn_str.find_last_of("/", pos1);
00068     if(pos2 != std::string::npos && pos1 == std::string::npos) { 
00069       str = local_dn_str.substr(pos2+1);
00070       local_dn.append(str);
00071       pos1 = pos2-1;
00072     }
00073     else if (pos2 != std::string::npos && pos1 != std::string::npos) {
00074       str = local_dn_str.substr(pos2+1, pos1-pos2);
00075       local_dn.append(str);
00076       pos1 = pos2-1;
00077     }
00078     if(pos2 != (std::string::npos+1)) local_dn.append(",");
00079   }while(pos2 != std::string::npos && pos2 != (std::string::npos+1));
00080 
00081   //Compose <samlp:AttributeQuery/>
00082   Arc::XMLNode attr_query(ns, "samlp:AttributeQuery");
00083   std::string query_id = Arc::UUID();
00084   attr_query.NewAttribute("ID") = query_id;
00085   Arc::Time t;
00086   std::string current_time = t.str(Arc::UTCTime);
00087   attr_query.NewAttribute("IssueInstant") = current_time;
00088   attr_query.NewAttribute("Version") = std::string("2.0");
00089 
00090   //<saml:Issuer/>
00091   std::string issuer_name = local_dn;
00092   Arc::XMLNode issuer = attr_query.NewChild("saml:Issuer");
00093   issuer = issuer_name;
00094   issuer.NewAttribute("Format") = std::string("urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName");
00095 
00096   //<saml:Subject/>
00097   Arc::XMLNode subject = attr_query.NewChild("saml:Subject");
00098   Arc::XMLNode name_id = subject.NewChild("saml:NameID");
00099   name_id.NewAttribute("Format")=std::string("urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName");
00100   name_id = local_dn;
00101 
00102   //Add one or more <Attribute>s into AttributeQuery here, which means the Requestor would
00103   //get these <Attribute>s from AA
00104   //<saml:Attribute/>
00105  /* 
00106   Arc::XMLNode attribute = attr_query.NewChild("saml:Attribute");
00107   attribute.NewAttribute("Name")=std::string("urn:oid:1.3.6.1.4.1.5923.1.1.1.6");
00108   attribute.NewAttribute("NameFormat")=std::string("urn:oasis:names:tc:SAML:2.0:attrname-format:uri");
00109   attribute.NewAttribute("FriendlyName")=std::string("eduPersonPrincipalName");
00110   */
00111 
00112   Arc::init_xmlsec();
00113   Arc::XMLSecNode attr_query_secnd(attr_query);
00114   std::string attr_query_idname("ID");
00115   attr_query_secnd.AddSignatureTemplate(attr_query_idname, Arc::XMLSecNode::RSA_SHA1);
00116   if(attr_query_secnd.SignNode(key,cert)) {
00117     std::cout<<"Succeeded to sign the signature under <samlp:AttributeQuery/>"<<std::endl;
00118   }
00119 
00120 
00121   std::string str;
00122   attr_query.GetXML(str);
00123   std::cout<<"AttributeQuery: "<<str<<std::endl;
00124 
00125   Arc::NS soap_ns;
00126   Arc::SOAPEnvelope envelope(soap_ns);
00127   envelope.NewChild(attr_query);
00128   Arc::PayloadSOAP request(envelope);
00129 
00130   std::string tmp;
00131   request.GetXML(tmp);
00132   std::cout<<"SOAP request: "<<tmp<<std::endl<<std::endl;
00133  
00134   // Send request
00135   Arc::MCCConfig cfg;
00136   if (!cert.empty())
00137     cfg.AddCertificate(cert);
00138   if (!key.empty())
00139     cfg.AddPrivateKey(key);
00140   if (!cafile.empty())
00141     cfg.AddCAFile(cafile);
00142   if (!cadir.empty())
00143     cfg.AddCADir(cadir);
00144 
00145 
00146   std::string path("/voms/test_saml/services/VOMSSaml");
00147   std::string service_url_str("https://omii002.cnaf.infn.it:8443");
00148 
00149 //  std::string path("/aaservice");
00150 //  std::string service_url_str("https://squark.uio.no:60001");
00151 
00152 //  std::string path("/voms/saml/knowarc/services/AttributeAuthorityPortType");
00153 //  std::string service_url_str("https://squark.uio.no:8444");
00154 
00155 //  std::string path("/voms/saml/testvo/services/AttributeAuthorityPortType");
00156 //  std::string service_url_str("https://127.0.0.1:8443");
00157 
00158 //  std::string path("/voms/saml/omiieurope/services/AttributeAuthorityPortType");
00159 //  std::string service_url_str("https://omii002.cnaf.infn.it:8443");
00160 
00161   Arc::URL service_url(service_url_str + path);
00162   Arc::ClientSOAP client(cfg, service_url);
00163 
00164   Arc::PayloadSOAP *response = NULL;
00165   Arc::MCC_Status status = client.process(&request,&response);
00166   if (!response) {
00167     logger.msg(Arc::ERROR, "Request failed: No response");
00168     return -1;
00169   }
00170   if (!status) {
00171     std::string tmp;
00172     response->GetXML(tmp);
00173     std::cout<<"SOAP Response: "<<tmp<<std::endl;
00174     logger.msg(Arc::ERROR, "Request failed: Error");
00175     return -1;
00176   }
00177 
00178   response->GetXML(str);
00179   std::cout<<"SOAP Response: "<<str<<std::endl<<std::endl;
00180 
00181   // -------------------------------------------------------
00182   //   Consume the response from saml voms service
00183   // -------------------------------------------------------
00184   //Consume the response from AA
00185   Arc::XMLNode attr_resp;
00186   
00187   //<samlp:Response/>
00188   attr_resp = (*response).Body().Child(0);
00189   attr_resp.GetXML(str);
00190   std::cout<<"SAML Response: "<<str<<std::endl<<std::endl;
00191 
00192   //TODO: metadata processing.
00193   //std::string aa_name = attr_resp["saml:Issuer"]; 
00194  
00195   //Check validity of the signature on <samlp:Response/>
00196   std::string resp_idname = "ID";
00197 /*
00198   Arc::XMLSecNode attr_resp_secnode(attr_resp);
00199   if(attr_resp_secnode.VerifyNode(resp_idname, cafile, cadir)) {
00200     logger.msg(Arc::INFO, "Succeeded to verify the signature under <samlp:Response/>");
00201   }
00202   else {
00203     logger.msg(Arc::ERROR, "Failed to verify the signature under <samlp:Response/>");
00204     Arc::final_xmlsec(); return -1;
00205   }
00206 */
00207 
00208   //Check whether the "InResponseTo" is the same as the local ID
00209 
00210   std::string responseto_id = (std::string)(attr_resp.Attribute("InResponseTo"));
00211   if(query_id != responseto_id) {
00212     logger.msg(Arc::INFO, "The Response is not going to this end");
00213     Arc::final_xmlsec(); return -1;
00214   }
00215 
00216 
00217   std::string resp_time = attr_resp.Attribute("IssueInstant");
00218 
00219   //<samlp:Status/>
00220   std::string statuscode_value = attr_resp["Status"]["StatusCode"].Attribute("Value");
00221   if(statuscode_value == "urn:oasis:names:tc:SAML:2.0:status:Success")
00222     logger.msg(Arc::INFO, "The StatusCode is Success");
00223   else logger.msg(Arc::ERROR, "Can not find StatusCode");
00224 
00225 
00226   //<saml:Assertion/>
00227   Arc::XMLNode assertion = attr_resp["saml:Assertion"];
00228 
00229   //TODO: metadata processing.
00230   //std::string aa_name = assertion["saml:Issuer"];
00231  
00232   //Check validity of the signature on <saml:Assertion/>
00233 
00234   assertion.GetXML(tmp);
00235   std::cout<<"SAML Assertion: "<<tmp<<std::endl<<std::endl;
00236 
00237 
00238   std::string assertion_idname = "ID";
00239   Arc::XMLSecNode assertion_secnode(assertion);
00240   if(assertion_secnode.VerifyNode(assertion_idname, cafile, cadir,false)) {
00241     logger.msg(Arc::INFO, "Succeeded to verify the signature under <saml:Assertion/>");
00242   }
00243   else {
00244     logger.msg(Arc::ERROR, "Failed to verify the signature under <saml:Assertion/>");
00245     Arc::final_xmlsec(); return -1;
00246   }
00247 
00248 
00249   //<saml:Subject/>, TODO: 
00250   Arc::XMLNode subject_nd = assertion["saml:Subject"];
00251 
00252   //<saml:Condition/>, TODO: Condition checking
00253   Arc::XMLNode cond_nd = assertion["saml:Conditions"];
00254 
00255   //<saml:AttributeStatement/>
00256   Arc::XMLNode attr_statement = assertion["saml:AttributeStatement"];
00257 
00258   //<saml:Attribute/>
00259   Arc::XMLNode attr_nd;
00260   std::vector<std::string> attributes_value;
00261   for(int i=0;;i++) {
00262     attr_nd = attr_statement["saml:Attribute"][i];
00263     if(!attr_nd) break;
00264 
00265     std::string name = attr_nd.Attribute("Name");
00266     std::string nameformat = attr_nd.Attribute("NameFormat");
00267 
00268     for(int j=0;;j++) {
00269       Arc::XMLNode attr_value = attr_nd["saml:AttributeValue"][j];
00270       if(!attr_value) break;
00271       std::string str;
00272       str.append("Name=").append(name).append(" Value=").append(attr_value);
00273       attributes_value.push_back(str);
00274     }
00275   }
00276 
00277   for(int i=0; i<attributes_value.size(); i++) {
00278     std::cout<<"Attribute Value: "<<attributes_value[i]<<std::endl;  
00279   }
00280 
00281   Arc::final_xmlsec();
00282   return 0;
00283 }