Back to index

nordugrid-arc-nox  1.1.0~rc6
X509Token.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #ifdef WIN32
00006 #include <arc/win32.h>
00007 #endif
00008 #include <stdlib.h>
00009 #include <sys/time.h>
00010 
00011 #include <string>
00012 #include <sstream>
00013 #include <fstream>
00014 #include <iostream>
00015 //#include <iomanip>
00016 
00017 //#include <glibmm.h>
00018 
00019 #include <xmlsec/base64.h>
00020 #include <xmlsec/errors.h>
00021 #include <xmlsec/xmltree.h>
00022 #include <xmlsec/xmldsig.h>
00023 #include <xmlsec/xmlenc.h>
00024 #include <xmlsec/templates.h>
00025 #include <xmlsec/crypto.h>
00026 
00027 #include <xmlsec/openssl/app.h>
00028 #include <openssl/bio.h>
00029 
00030 #include <openssl/evp.h>
00031 #include <openssl/sha.h>
00032 #include <openssl/rand.h>
00033 #ifdef CHARSET_EBCDIC
00034 #include <openssl/ebcdic.h>
00035 #endif 
00036 
00037 #include <arc/DateTime.h>
00038 #include <arc/Base64.h>
00039 #include <arc/StringConv.h>
00040 
00041 #include <arc/xmlsec/XmlSecUtils.h>
00042 #include "X509Token.h"
00043 
00044 namespace Arc {
00045 
00046 #define WSSE_NAMESPACE   "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
00047 #define WSSE11_NAMESPACE "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"
00048 #define WSU_NAMESPACE    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
00049 #define XENC_NAMESPACE   "http://www.w3.org/2001/04/xmlenc#"
00050 #define DSIG_NAMESPACE   "http://www.w3.org/2000/09/xmldsig#"
00051 
00052 #define X509TOKEN_BASE_URL "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0"
00053 #define BASE64BINARY "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soapmessage-security-1.0#Base64Binary"
00054 #define STRTRANSFORM "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soapmessage-security-1.0#STR-Transform"
00055 #define PKCS7 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#PKCS7"
00056 #define X509V3 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
00057 #define X509PKIPATHV1 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"
00058 #define X509SUBJECTKEYID "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"
00059 
00060 bool X509Token::Check(SOAPEnvelope& soap) {
00061   XMLNode header = soap.Header();
00062   if(header.NamespacePrefix(WSSE_NAMESPACE).empty()){
00063     std::cerr<<"No wsse namespace in SOAP Header"<<std::endl;
00064     return false;
00065   }
00066   XMLNode wsse;
00067   if(!(wsse=header["wsse:Security"])) {
00068     std::cerr<<"No Security element in SOAP Header"<<std::endl;
00069     return false;
00070   };
00071   if((bool)(wsse["wsse:BinarySecurityToken"])) {
00072     tokentype = Signature;
00073   }
00074   else if((bool)(wsse["xenc:EncryptedKey"])) {
00075     tokentype = Encryption;
00076   }
00077   else {
00078     std::cerr<<"No wsse:Security or xenc:EncryptedKey element in SOAP Header"<<std::endl;
00079     return false;
00080   };
00081   return true;
00082 }
00083 
00084 X509Token::operator bool(void) {
00085   return (bool)header;
00086 }
00087 
00088 X509Token::X509Token(SOAPEnvelope& soap, const std::string& keyfile) : SOAPEnvelope(soap){
00089   if(!Check(soap)){
00090     return;    
00091   }
00092 
00093   //if(!init_xmlsec()) return; 
00094  
00095   if(tokentype == Signature) {
00096     // Apply predefined namespace prefix
00097     NS ns;
00098     ns["wsse"]=WSSE_NAMESPACE;
00099     ns["wsse11"]=WSSE11_NAMESPACE;
00100     ns["wsu"]=WSU_NAMESPACE;
00101     header.Namespaces(ns);
00102 
00103     XMLNode xt = header["wsse:Security"];   
00104     XMLNode signature = xt["Signature"];
00105     XMLNode token = xt["wsse:BinarySecurityToken"];
00106     cert_str = (std::string)token;
00107 
00108     //Body reference
00109     xmlNodePtr bodyPtr = ((X509Token*)(&body))->node_;
00110     xmlDocPtr docPtr = bodyPtr->doc;
00111     xmlChar* id = xmlGetProp(bodyPtr, (xmlChar *)"Id");
00112     xmlAttrPtr id_attr = xmlHasProp(bodyPtr, (xmlChar *)"Id");
00113     xmlAddID(NULL, docPtr, (xmlChar *)id, id_attr);
00114     xmlFree(id);
00115 
00116     //BinaryToken reference
00117     xmlNodePtr tokenPtr = ((X509Token*)(&token))->node_;
00118     id_attr = xmlHasProp(tokenPtr, (xmlChar *)"Id");
00119     xmlAddID(NULL, docPtr, (xmlChar *)"binarytoken", id_attr);
00120 
00121     //Signature 
00122     signature_nd = ((X509Token*)(&signature))->node_; 
00123     if(!signature_nd) { std::cerr<<"No Signature node in SOAP header"<<std::endl; return; }
00124   }
00125   else{
00126     //Compose the xml structure
00127     NS ns;
00128     ns["xenc"] = XENC_NAMESPACE;
00129     ns["ds"] = DSIG_NAMESPACE;
00130     XMLNode encrypted_data(ns,"xenc:EncryptedData");
00131     encrypted_data.NewAttribute("Id") = (std::string)(body["xenc:EncryptedData"].Attribute("Id"));
00132     encrypted_data.NewAttribute("Type") = (std::string)(body["xenc:EncryptedData"].Attribute("Type"));
00133     XMLNode enc_method1 = get_node(encrypted_data, "xenc:EncryptionMethod");
00134     enc_method1.NewAttribute("Algorithm") = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"; 
00135     XMLNode keyinfo1 = get_node(encrypted_data, "ds:KeyInfo");
00136     XMLNode enc_key = get_node(keyinfo1, "xenc:EncryptedKey");
00137     XMLNode enc_method2 = get_node(enc_key, "xenc:EncryptionMethod");
00138     enc_method2.NewAttribute("Algorithm") = (std::string)(header["wsse:Security"]["xenc:EncryptedKey"]["xenc:EncryptionMethod"].Attribute("Algorithm"));
00139     XMLNode keyinfo2 = get_node(enc_key, "ds:KeyInfo");
00140     XMLNode key_cipherdata = get_node(enc_key, "xenc:CipherData");
00141     XMLNode key_ciphervalue = get_node(key_cipherdata, "xenc:CipherValue") = (std::string)(header["wsse:Security"]["xenc:EncryptedKey"]["xenc:CipherData"]["xenc:CipherValue"]);
00142 
00143     XMLNode cipherdata = get_node(encrypted_data, "xenc:CipherData");
00144     XMLNode ciphervalue = get_node(cipherdata, "xenc:CipherValue");
00145     ciphervalue = (std::string)(body["xenc:EncryptedData"]["xenc:CipherData"]["xenc:CipherValue"]); 
00146 
00147     std::string str;
00148     encrypted_data.GetXML(str);
00149     //std::cout<<"Before Decryption++++: "<<str<<std::endl;
00150 
00151     xmlNodePtr todecrypt_nd = ((X509Token*)(&encrypted_data))->node_;
00152 
00153     //Create encryption context
00154     xmlSecKeysMngr* keys_mngr = NULL;
00155     //TODO: which key file will be used should be got according to the issuer name and 
00156     //serial number information in incoming soap head
00157     std::string issuer_name = (std::string)(header["wsse:Security"]["xenc:EncryptedKey"]["ds:KeyInfo"]["wsse:SecurityTokenReference"]["ds:X509Data"]["ds:X509IssuerSerial"]["ds:X509IssuerName"]);
00158     std::string serial_number = (std::string)(header["wsse:Security"]["xenc:EncryptedKey"]["ds:KeyInfo"]["wsse:SecurityTokenReference"]["ds:X509Data"]["ds:X509IssuerSerial"]["ds:X509SerialNumber"]);
00159  
00160     keys_mngr = load_key_from_keyfile(&keys_mngr, keyfile.c_str());
00161 
00162     xmlSecEncCtxPtr encCtx = NULL;
00163     encCtx = xmlSecEncCtxCreate(keys_mngr);
00164     if(encCtx == NULL) {
00165       std::cerr<<"Failed to create encryption context"<<std::endl;
00166       return;
00167     }
00168 
00169     // Decrypt the soap body
00170     xmlSecBufferPtr decrypted_buf;
00171     decrypted_buf = xmlSecEncCtxDecryptToBuffer(encCtx, todecrypt_nd);
00172     if(decrypted_buf == NULL) {
00173       std::cerr<<"Decryption failed"<<std::endl;
00174       if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
00175     }
00176     else { std::cout<<"Decryption succeed"<<std::endl; }
00177 
00178     //encrypted_data.GetXML(str);
00179     //std::cout<<"After Decryption: "<<str<<std::endl;
00180 
00181     std::cout<<"Decrypted data: "<<decrypted_buf->data<<std::endl;
00182 
00183     //Insert the decrypted data into soap body
00184     std::string decrypted_str((const char*)decrypted_buf->data);
00185     XMLNode decrypted_data(decrypted_str); 
00186     // TODO: less copies
00187     body.Replace(decrypted_data);
00188 
00189     //Destroy the wsse:Security in header
00190     header["wsse:Security"].Destroy();
00191 
00192     //Ajust namespaces, delete mutiple definition
00193     ns = envelope.Namespaces();
00194     envelope.Namespaces(ns);
00195 
00196     //if(decrypted_buf != NULL)xmlSecBufferDestroy(decrypted_buf);
00197     if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
00198     if(keys_mngr != NULL)xmlSecKeysMngrDestroy(keys_mngr);
00199   }
00200 
00201 } 
00202 
00203 bool X509Token::Authenticate(void) {
00204   xmlSecDSigCtx *dsigCtx;
00205   dsigCtx = xmlSecDSigCtxCreate(NULL);
00206 
00207   //Load public key from incoming soap's security token
00208   xmlSecKey* pubkey = get_key_from_certstr(cert_str);
00209   if (pubkey == NULL){
00210     xmlSecDSigCtxDestroy(dsigCtx);
00211     std::cerr<<"Can not load public key"<<std::endl; return false;
00212   }
00213   dsigCtx->signKey = pubkey;
00214 
00215   if (xmlSecDSigCtxVerify(dsigCtx, signature_nd) < 0) {
00216     xmlSecDSigCtxDestroy(dsigCtx);
00217     std::cerr<<"Signature verification failed"<<std::endl;
00218     return false;
00219   }
00220 
00221   if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
00222     std::cout<<"Succeed to verify the signature in SOAP message"<<std::endl;
00223     xmlSecDSigCtxDestroy(dsigCtx); return true;
00224   }
00225   else { std::cerr<<"Invalid signature"<<std::endl; xmlSecDSigCtxDestroy(dsigCtx); return false; }
00226 }
00227 
00228 bool X509Token::Authenticate(const std::string& cafile, const std::string& capath) {
00229   xmlSecKeysMngr* keys_manager = NULL;
00230   xmlSecDSigCtx *dsigCtx;
00231 
00232   keys_manager = load_trusted_certs(&keys_manager, cafile.c_str(), capath.c_str());
00233   //Load keyInfo. Because xmlsec only accept standard <X509Data/>, here we are using some 
00234   //kind of hack method by insertinga <X509Data/> into <KeyInfo/>, after verification, we 
00235   //delete the node.
00236   //TODO. The other option is to implement a "key data" object and some "read" "write" method as 
00237   //xmlsec does, it will be more complicated but it is a more correct way. Put it as TODO
00238   XMLNode keyinfo_nd = header["wsse:Security"]["Signature"]["KeyInfo"];
00239   XMLNode st_ref_nd = keyinfo_nd["wsse:SecurityTokenReference"];
00240   XMLNode x509data_node = get_node(keyinfo_nd, "X509Data");
00241   XMLNode x509cert_node = get_node(x509data_node, "X509Certificate");
00242   x509cert_node = cert_str;
00243 
00244   dsigCtx = xmlSecDSigCtxCreate(keys_manager);
00245   if (xmlSecDSigCtxVerify(dsigCtx, signature_nd) < 0) {
00246     xmlSecDSigCtxDestroy(dsigCtx);
00247     if (keys_manager) xmlSecKeysMngrDestroy(keys_manager);
00248     std::cerr<<"Signature verification failed (with trusted certificate checking)"<<std::endl;
00249     x509data_node.Destroy();
00250     return false;
00251   }
00252   
00253   if(keys_manager != NULL)xmlSecKeysMngrDestroy(keys_manager);
00254   if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
00255     std::cout<<"Succeed to verify the signature in SOAP message (with trusted certificate checking)"<<std::endl;
00256     xmlSecDSigCtxDestroy(dsigCtx); x509data_node.Destroy(); return true;
00257   }
00258   else { std::cerr<<"Invalid signature"<<std::endl; xmlSecDSigCtxDestroy(dsigCtx); x509data_node.Destroy(); return false; }
00259 
00260 }
00261 
00262 
00263 X509Token::X509Token(SOAPEnvelope& soap, const std::string& certfile, const std::string& keyfile, X509TokenType token_type) : SOAPEnvelope (soap), tokentype(token_type) {
00264 
00265   //if(!init_xmlsec()) return;
00266 
00267   if(tokentype == Signature) {
00268     // Apply predefined namespace prefix
00269     NS header_ns, ns;
00270     header_ns["wsse"]=WSSE_NAMESPACE;
00271     header_ns["wsse11"]=WSSE11_NAMESPACE;
00272     header.Namespaces(header_ns);
00273 
00274     ns = envelope.Namespaces();
00275     ns["wsu"]=WSU_NAMESPACE;
00276     envelope.Namespaces(ns);
00277 
00278     xmlNodePtr signature = NULL;
00279     xmlNodePtr reference = NULL;
00280 
00281     // Insert the wsse:Security element
00282     XMLNode wsse = get_node(header,"wsse:Security");
00283 
00284     //Here only "Reference to a Binary Security Token" is generated, see:
00285     //Web service security X.509 Certificate Token Profile 1.1
00286     // Insert the wsse:BinarySecurityToken
00287     std::string cert;
00288     cert = get_cert_str(certfile.c_str());
00289     XMLNode token = wsse.NewChild("wsse:BinarySecurityToken");
00290     token.NewAttribute("wsu:Id") = "binarytoken";
00291     token.NewAttribute("ValueType") = X509V3;
00292     token.NewAttribute("EncodingType") = BASE64BINARY;
00293     token = cert; 
00294 
00295     //Add signature template 
00296     signature = xmlSecTmplSignatureCreate(NULL,
00297                             xmlSecTransformExclC14NId,
00298                             xmlSecTransformRsaSha1Id, NULL);
00299 
00300     //Add signature into wsse
00301     xmlNodePtr wsse_nd = ((X509Token*)(&wsse))->node_;
00302     xmlAddChild(wsse_nd, signature);
00303 
00304     //Add reference for signature
00305     //Body reference
00306     xmlNodePtr bodyPtr = ((X509Token*)(&body))->node_;
00307     xmlDocPtr docPtr = bodyPtr->doc;
00308 
00309     xmlChar* id = NULL;
00310     id =  xmlGetProp(bodyPtr, (xmlChar *)"Id");
00311     if(!id) { 
00312       std::cout<<"There is not wsu:Id attribute in soap body, add a new one"<<std::endl;
00313       body.NewAttribute("wsu:Id") = "body";
00314     }
00315     id =  xmlGetProp(bodyPtr, (xmlChar *)"Id");
00316 
00317     std::string body_uri; body_uri.append("#"); body_uri.append((char*)id);
00318 
00319     reference = xmlSecTmplSignatureAddReference(signature, xmlSecTransformSha1Id,
00320                                               NULL, (xmlChar *)(body_uri.c_str()), NULL);
00321     xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
00322     xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
00323   
00324     xmlAttrPtr id_attr = xmlHasProp(bodyPtr, (xmlChar *)"Id");
00325     xmlAddID(NULL, docPtr, (xmlChar *)id, id_attr);
00326     xmlFree(id);
00327 
00328     //BinaryToken reference
00329     xmlNodePtr tokenPtr = ((X509Token*)(&token))->node_;
00330  
00331     std::string token_uri; token_uri.append("#").append("binarytoken");
00332 
00333     reference = xmlSecTmplSignatureAddReference(signature, xmlSecTransformSha1Id,
00334                                                     NULL, (xmlChar *)(token_uri.c_str()), NULL);
00335     xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
00336     xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
00337   
00338     id_attr = xmlHasProp(tokenPtr, (xmlChar *)"Id");
00339     xmlAddID(NULL, docPtr, (xmlChar *)"binarytoken", id_attr);
00340 
00341     xmlNodePtr key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
00342     //xmlSecTmplKeyInfoAddX509Data(key_info);
00343 
00344     XMLNode keyinfo_nd = wsse["Signature"]["KeyInfo"];
00345     XMLNode st_ref_nd = keyinfo_nd.NewChild("wsse:SecurityTokenReference");
00346     XMLNode ref_nd = st_ref_nd.NewChild("wsse:Reference");
00347     ref_nd.NewAttribute("URI") = token_uri;
00348 
00349     //Sign the SOAP message
00350     xmlSecDSigCtx *dsigCtx = xmlSecDSigCtxCreate(NULL);
00351     //load private key, assuming there is no need for passphrase
00352     dsigCtx->signKey = xmlSecCryptoAppKeyLoad(keyfile.c_str(), xmlSecKeyDataFormatPem, NULL, NULL, NULL);
00353     //dsigCtx->signKey = xmlSecCryptoAppKeyLoad(keyfile.c_str(), xmlSecKeyDataFormatPem, NULL, (void*)passphrase_callback, NULL);
00354     if(dsigCtx->signKey == NULL) {
00355       xmlSecDSigCtxDestroy(dsigCtx);
00356       std::cerr<<"Can not load key"<<std::endl; return;
00357     }
00358     /* the following code could be necessary if we need <dsig:X509Data/>
00359     if(xmlSecCryptoAppKeyCertLoad(dsigCtx->signKey, certfile.c_str(), xmlSecKeyDataFormatPem) < 0) {
00360       xmlSecDSigCtxDestroy(dsigCtx);
00361       std::cerr<<"Can not load certificate"<<std::endl; return;       
00362     }
00363     */
00364     if (xmlSecDSigCtxSign(dsigCtx, signature) < 0) {
00365       xmlSecDSigCtxDestroy(dsigCtx);
00366       std::cerr<<"Can not sign soap message"<<std::endl; return;
00367     }
00368 
00369     if(dsigCtx != NULL)xmlSecDSigCtxDestroy(dsigCtx);
00370 
00371     std::string str;
00372     envelope.GetXML(str);
00373     std::cout<<"Envelope: "<<str<<std::endl;
00374   }
00375   else {
00376     // Apply predefined namespace prefix
00377     NS ns, header_ns;
00378     header_ns["wsse"]=WSSE_NAMESPACE;
00379     header_ns["wsse11"]=WSSE11_NAMESPACE;
00380     header_ns["wsu"]=WSU_NAMESPACE;
00381     header_ns["ds"]=DSIG_NAMESPACE;
00382     header.Namespaces(header_ns);
00383 
00384     ns = envelope.Namespaces();
00385     ns["xenc"]=XENC_NAMESPACE;
00386     envelope.Namespaces(ns);
00387  
00388     // Insert the wsse:Security element
00389     XMLNode wsse = get_node(header,"wsse:Security");
00390 
00391     //Generate a copy of body node, now all of the things will based on this node;
00392     //After the encryption, the body node will be copy back to original one
00393     XMLNode body_cp;
00394     body.New(body_cp);
00395 
00396     xmlNodePtr bodyPtr = ((X509Token*)(&body_cp))->node_;
00397     xmlDocPtr docPtr = bodyPtr->doc;
00398 
00399     xmlNodePtr encDataNode = NULL;
00400     xmlNodePtr keyInfoNode = NULL;
00401     xmlNodePtr encKeyNode = NULL;
00402     xmlNodePtr keyInfoNode2 = NULL;
00403     xmlSecEncCtxPtr encCtx = NULL;
00404  
00405     //Create encryption template for a specific symetric key type
00406     encDataNode = xmlSecTmplEncDataCreate(docPtr , xmlSecTransformDes3CbcId,
00407                             (const xmlChar*)"encrypted", xmlSecTypeEncElement, NULL, NULL);
00408     if(encDataNode == NULL) { std::cerr<<"Failed to create encryption template"<<std::endl; return; }
00409 
00410     // Put encrypted data in the <enc:CipherValue/> node
00411     if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL){
00412      std::cerr<<"Failed to add CipherValue node"<<std::endl;   
00413      if(encDataNode != NULL) xmlFreeNode(encDataNode);
00414      return;
00415     }
00416 
00417     // Add <dsig:KeyInfo/>
00418     keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
00419     if(keyInfoNode == NULL) { 
00420       std::cerr<<"Failed to add key info"<<std::endl;
00421       if(encDataNode != NULL) xmlFreeNode(encDataNode);
00422       return;
00423     }
00424 
00425     // Add <enc:EncryptedKey/> to store the encrypted session key
00426     encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, 
00427                                 xmlSecTransformRsaPkcs1Id, 
00428                                 NULL, NULL, NULL);
00429     if(encKeyNode == NULL) { 
00430       std::cerr<<"Failed to add key info"<<std::endl;
00431       if(encDataNode != NULL) xmlFreeNode(encDataNode);
00432       return;
00433     }
00434 
00435     // Put encrypted key in the <enc:CipherValue/> node
00436     if(xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) std::cerr<<"Error: failed to add CipherValue node"<<std::endl;
00437 
00438     // Add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> 
00439     keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
00440     if(keyInfoNode2 == NULL){
00441       std::cerr<<"Failed to add key info"<<std::endl;
00442       if(encDataNode != NULL) xmlFreeNode(encDataNode);
00443       return;
00444     }
00445 
00446     //Create encryption context
00447     xmlSecKeysMngr* keys_mngr = NULL;
00448     keys_mngr = load_key_from_certfile(&keys_mngr, certfile.c_str());
00449 
00450     encCtx = xmlSecEncCtxCreate(keys_mngr);
00451     if(encCtx == NULL) {
00452       std::cerr<<"Failed to create encryption context"<<std::endl;
00453       if(encDataNode != NULL) xmlFreeNode(encDataNode);
00454       return;
00455     }
00456 
00457     // Generate a Triple DES key
00458     encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession);
00459     if(encCtx->encKey == NULL) {
00460       std::cerr<<"Failed to generate session des key"<<std::endl;
00461       if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
00462       if(encDataNode != NULL) xmlFreeNode(encDataNode);
00463       return;
00464     }
00465     // Encrypt the soap body, here the body node is encrypted, not only the content under body node
00466     // TODO: not sure whether the body node, or the content under body node shoud be encrypted
00467     if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, bodyPtr) < 0) { 
00468       std::cerr<<"Encryption failed"<<std::endl;
00469       if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
00470       if(encDataNode != NULL) xmlFreeNode(encDataNode);
00471     }
00472 
00473     //The template has been inserted in the doc
00474     ((X509Token*)(&body_cp))->node_ = (bodyPtr=encDataNode);
00475     encDataNode = NULL;
00476 
00477     //if(encCtx != NULL){ xmlSecEncCtxDestroy(encCtx); encCtx = NULL; }
00478     
00479     std::string str;
00480     body_cp.GetDoc(str);
00481     std::cout<<"Body new : "<<str<<std::endl;
00482 
00483     //Put the encrypted information into soap head and soap body according to x509token specification
00484 
00485     XMLNode encrypted_data = body_cp;//.GetRoot();
00486     encrypted_data.GetXML(str);
00487     std::cout<<"Encrypted data : "<<str<<std::endl; 
00488 
00489     //Delete the existing element under <Body/>
00490     for(int i=0;;i++) {
00491       XMLNode nd = body.Child(i);
00492       if(!nd) break;
00493       nd.Destroy();
00494     }
00495 
00496     XMLNode body_encdata = get_node(body,"xenc:EncryptedData");
00497     body_encdata.NewAttribute("wsu:Id") = (std::string)(encrypted_data.Attribute("Id"));
00498     body_encdata.NewAttribute("Type") = (std::string)(encrypted_data.Attribute("Type"));
00499     
00500     XMLNode body_cipherdata = get_node(body_encdata,"xenc:CipherData");
00501     get_node(body_cipherdata,"xenc:CipherValue") = (std::string)(encrypted_data["CipherData"]["CipherValue"]); 
00502 
00503  
00504     XMLNode enc_key = get_node(wsse,"xenc:EncryptedKey");
00505 
00506     XMLNode enc_method = get_node(enc_key,"xenc:EncryptionMethod");   
00507     enc_method.NewAttribute("Algorithm") = (std::string)(encrypted_data["KeyInfo"]["EncryptedKey"]["EncryptionMethod"].Attribute("Algorithm"));  
00508 
00509     XMLNode keyinfo = get_node(enc_key, "ds:KeyInfo");
00510     XMLNode sec_token_ref = get_node(keyinfo, "wsse:SecurityTokenReference");
00511     XMLNode x509_data =  get_node(sec_token_ref, "ds:X509Data");
00512     XMLNode x509_issuer_serial = get_node(x509_data, "ds:X509IssuerSerial");
00513     XMLNode x509_issuer_name = get_node(x509_issuer_serial, "ds:X509IssuerName");
00514     XMLNode x509_serial_number = get_node(x509_issuer_serial, "ds:X509SerialNumber");
00515     //TODO: issuer name and issuer number should be extracted from certificate
00516     //There should be some way by which the sender could get the peer certificate
00517     //and use the public key inside this certificate to encrypt the message. 
00518     X509* cert = NULL;
00519     BIO* certbio = NULL;
00520     certbio = BIO_new_file(certfile.c_str(), "r");
00521     cert = PEM_read_bio_X509(certbio, NULL, NULL, NULL);
00522 
00523     //get formated issuer name from certificate
00524     BIO* namebio = NULL;
00525     namebio = BIO_new(BIO_s_mem());
00526     X509_NAME_print_ex(namebio, X509_get_issuer_name(cert), 0, XN_FLAG_SEP_CPLUS_SPC);
00527     char name[256]; 
00528     memset(name,0,256);
00529     int length = BIO_read(namebio, name, 256);
00530     //char* name = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
00531 
00532     std::string issuer_name(name);
00533     //OPENSSL_free(name);
00534     int serial = (int) ASN1_INTEGER_get(X509_get_serialNumber(cert));
00535     std::stringstream ss; std::string serial_number;
00536     ss<<serial; ss>>serial_number;
00537     x509_issuer_name = issuer_name;
00538     x509_serial_number = serial_number;
00539 
00540     XMLNode key_cipherdata = get_node(enc_key, "xenc:CipherData");
00541     key_cipherdata.NewChild("xenc:CipherValue") = (std::string)(encrypted_data["KeyInfo"]["EncryptedKey"]["CipherData"]["CipherValue"]);
00542 
00543     XMLNode ref_list = get_node(enc_key, "xenc:ReferenceList");
00544     XMLNode ref_item = get_node(ref_list,"xenc:DataReference");
00545     ref_item.NewAttribute("URI") = "#" + (std::string)(encrypted_data.Attribute("Id"));
00546 
00547     if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
00548     if(keys_mngr != NULL)xmlSecKeysMngrDestroy(keys_mngr);
00549 
00550     envelope.GetXML(str);
00551     std::cout<<"Envelope: "<<str<<std::endl;
00552   }
00553 }
00554 
00555 X509Token::~X509Token(void) {
00556   //final_xmlsec();
00557 }
00558 } // namespace Arc
00559