root/middleware-offline/trunk/_src/eidmw/applayer/SigVerifier.cpp @ 256

Revision 256, 19.9 KB (checked in by vsilva, 7 years ago)

Fix some bugs in PDF native signature. Support more OS

Line 
1#include <cstring>
2#include "MWException.h"
3#include "ByteArray.h"
4#include "Log.h"
5#include "Util.h"
6#include "MiscUtil.h"
7
8// Xerces
9
10#include <xercesc/util/PlatformUtils.hpp>
11#include <xercesc/framework/MemBufInputSource.hpp>
12#include <xercesc/parsers/XercesDOMParser.hpp>
13#include <xercesc/util/XMLException.hpp>
14#include <xercesc/util/Janitor.hpp>
15
16//XML-Security
17#include <xsec/framework/XSECProvider.hpp>
18#include <xsec/framework/XSECException.hpp>
19#include <xsec/dsig/DSIGReference.hpp>
20#include <xsec/dsig/DSIGSignature.hpp>
21#include <xsec/dsig/DSIGObject.hpp>
22#include <xsec/dsig/DSIGReferenceList.hpp>
23#include <xsec/dsig/DSIGConstants.hpp>
24#include <xsec/dsig/DSIGKeyInfoX509.hpp>
25#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp>
26#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
27#include <xsec/enc/XSECKeyInfoResolverDefault.hpp>
28#include <xsec/enc/XSECCryptoUtils.hpp>
29#include <xsec/enc/XSECCryptoException.hpp>
30#include <xsec/utils/XSECBinTXFMInputStream.hpp>
31#include <xsec/transformers/TXFMBase.hpp>
32#include <xsec/transformers/TXFMChain.hpp>
33
34//OpenSSL
35#include <openssl/sha.h>
36#include <openssl/evp.h>
37#include <openssl/pem.h>
38#include <openssl/bio.h>
39#include <openssl/err.h>
40
41#include <curl/curl.h>
42
43#include "APLConfig.h"
44
45#include "static_pteid_certs.h"
46#include "SigVerifier.h"
47
48//Make up for the absence of strptime on Windows CRT
49#ifdef _WIN32
50#include "strptime.c"
51#endif
52
53#define XERCES_NS XERCES_CPP_NAMESPACE_QUALIFIER
54#define SHA1_LEN 20
55
56XERCES_CPP_NAMESPACE_USE
57
58namespace eIDMW
59{
60
61        //PIMPL Idiom, just to avoid exposing private details in the header file
62        class SignatureImpl
63        {
64        public:
65                bool checkExternalRefs(DSIGReferenceList *refs, tHashedFile **hashes);
66                XERCES_NS DOMNode *m_signature_dom;
67        };
68
69
70        SignatureVerifier::SignatureVerifier(const char *sig_container_path)
71        {
72                m_sigcontainer_path = (char *)malloc(strlen(sig_container_path)+1);
73                strcpy((char *)m_sigcontainer_path, sig_container_path);
74                m_time_and_date = (char *)calloc(50, sizeof(char));
75               
76                pimpl = new SignatureImpl();
77                pimpl->m_signature_dom = NULL;
78                m_cert = NULL;
79
80        }
81
82        SignatureVerifier::~SignatureVerifier()
83        {
84                free(m_sigcontainer_path);
85                free(m_time_and_date);
86                delete pimpl;
87        }
88
89        size_t curl_write_validation_data(char *ptr, size_t size, size_t nmemb, void * userdata)
90        {
91                size_t realsize = size * nmemb;
92                CByteArray * buffer = (CByteArray *)userdata;
93                buffer->Append((const unsigned char*)ptr, realsize);
94
95                return realsize;
96
97        }
98
99        char *getHexString(unsigned char *bytes, unsigned int len)
100        {
101                char *hex = new char[len*2+1];
102                memset (hex, 0, len*2+1);
103
104                for (unsigned int i = 0; i!=len; i++)
105                        sprintf(hex+(i*2), "%02x", bytes[i]);
106
107                return hex;
108        }
109
110
111        void SignatureVerifier::base64Decode(const char *array, unsigned int inlen, unsigned char *&decoded, unsigned int &decoded_len)
112        {
113
114                BIO *bio, *b64;
115                unsigned int outlen = 0;
116                unsigned char *inbuf = new unsigned char[512];
117                memset(inbuf, 0, 512);
118
119                b64 = BIO_new(BIO_f_base64());
120                BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
121
122                bio = BIO_new_mem_buf((void *)array, inlen);
123                bio = BIO_push(b64, bio);
124
125                outlen = BIO_read(bio, inbuf, 512);
126                decoded = inbuf;
127
128                decoded_len = outlen;
129
130                BIO_free_all(bio);
131        }
132
133        char *strip_newlines(const char *str)
134        {
135                char *cleaned = new char[strlen(str)];
136                int j = 0;
137                for (unsigned int i=0; i < strlen(str); i++)
138                {
139                        if (str[i] != '\n')
140                                cleaned[j++] = str[i]; 
141                }
142                cleaned[j] = 0;
143                return cleaned;
144        }
145
146        /* This function validates timestamps using the HTTP Form available
147           at http://ts.cartaodecidadao.pt/tsaclient/validate.html */
148#define TSA_VALIDATE_URL "http://ts.cartaodecidadao.pt/tsaclient/validate.html"
149
150        CByteArray SignatureVerifier::do_post_validate_timestamp(char *input, long input_len, char *sha1_string)
151        {
152
153                CURL *curl;
154                CURLcode res;
155                char error_buf[CURL_ERROR_SIZE];
156
157                CByteArray *validate_data = new CByteArray();
158
159                static const char expect_header[] = "Expect:";
160
161                curl_global_init(CURL_GLOBAL_ALL);
162
163                curl = curl_easy_init();
164
165                if (curl) 
166                {
167
168                        struct curl_slist *headers= NULL;
169                        struct curl_httppost* formpost = NULL;
170                        struct curl_httppost* lastptr = NULL;
171
172                        headers = curl_slist_append(headers, "User-Agent: PTeID Middleware v2");
173                        headers = curl_slist_append(headers, expect_header);
174
175                        /* Build the form contents */
176
177                        curl_formadd(&formpost,
178                                        &lastptr,
179                                        CURLFORM_COPYNAME, "hash",
180                                        CURLFORM_COPYCONTENTS, sha1_string,
181                                        CURLFORM_END);
182
183                        curl_formadd(&formpost,
184                                        &lastptr,
185                                        CURLFORM_COPYNAME, "filename", "filename.xml",
186                                        CURLFORM_COPYCONTENTS, generateId(20),  //It should have some randomness
187                                        CURLFORM_END);
188
189                        curl_formadd(&formpost,
190                                        &lastptr,
191                                        CURLFORM_COPYNAME, "fileUpload",
192                                        CURLFORM_BUFFER, "ts_resp",
193                                        CURLFORM_BUFFERPTR, input,
194                                        CURLFORM_BUFFERLENGTH, input_len,
195                                        CURLFORM_END);
196
197                        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
198
199                        /* Now specify the POST data */ 
200                        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
201
202                        curl_easy_setopt(curl, CURLOPT_URL, TSA_VALIDATE_URL);
203
204                        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
205
206                        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buf);
207
208                        //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
209
210                        //This is the ByteArray to where curl_write_validation_data will write
211                        curl_easy_setopt(curl, CURLOPT_WRITEDATA, validate_data);
212                        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_write_validation_data);
213
214                        /* Perform the request, res will get the return code */ 
215                        res = curl_easy_perform(curl);
216
217                        if (res != 0)
218                        {
219                                MWLOG(LEV_ERROR, MOD_APL, L"Timestamp Validation error in HTTP POST request. LibcURL returned %ls\n", 
220                                                utilStringWiden(string(error_buf)).c_str());
221                        }
222
223                        /* always cleanup */ 
224                        curl_easy_cleanup(curl);
225
226                        curl_slist_free_all(headers);
227                        curl_formfree(formpost);
228
229                        curl_global_cleanup();
230                }
231                return *validate_data;
232
233        }
234
235SigVerifyErrorCode SignatureVerifier::ValidateTimestamp (CByteArray signature, CByteArray ts_resp)
236{
237
238        bool errorsOccured = false;
239
240        bool result = false;
241        unsigned char * signature_bin;
242
243        if (signature.Size() == 0)
244        {
245                MWLOG(LEV_ERROR, MOD_APL, L"ValidateTimestamp() received empty Signature. This most likely means a corrupt zipfile");
246                return XADES_ERROR_INVALID_TIMESTAMP;
247        }
248
249        initXerces();
250
251        //Load XML from a MemoryBuffer
252        MemBufInputSource * source = new MemBufInputSource(signature.GetBytes(),
253                        (XMLSize_t)signature.Size(),
254                        XMLString::transcode(generateId(20)));
255
256
257        XercesDOMParser * parser = new XercesDOMParser;
258        Janitor<XercesDOMParser> j_parser(parser);
259
260        parser->setDoNamespaces(true);
261        parser->setCreateEntityReferenceNodes(true);
262
263        // Now parse out file
264
265        xsecsize_t errorCount = 0;
266        try
267        {
268                parser->parse(*source);
269        }
270
271        catch (const XMLException& e)
272        {
273                MWLOG(LEV_ERROR, MOD_APL, L"An error occured during parsing\n   Message: %s",
274                                XMLString::transcode(e.getMessage()));
275                errorsOccured = true;
276        }
277        catch (const DOMException& e)
278        {
279                MWLOG(LEV_ERROR, MOD_APL, L"A DOM error occured during parsing\n   DOMException code: %d",
280                                e.code);
281                errorsOccured = true;
282        }
283
284        if (errorsOccured) {
285                MWLOG(LEV_ERROR, MOD_APL, L"Errors parsing XML Signature, bailing out");
286                return XADES_ERROR_BROKENSIG;
287        }
288
289       
290        DOMNode *doc;           // The document that we parsed
291
292        doc = parser->getDocument();
293
294        //XERCES_NS DOMNode * doc = pimpl->m_signature_dom;
295
296        // Find the signature node
297       
298        XERCES_NS DOMNode *sigNode = findDSIGNode(doc, "Signature");
299
300        XSECProvider prov;
301        unsigned char signature_hash[SHA1_LEN];
302        char time_and_date[100];
303        unsigned int sig_len = 0;
304        memset(time_and_date, 0, sizeof(time_and_date));
305        XERCES_NS DOMDocument * theDOM = dynamic_cast<XERCES_NS DOMDocument *>(doc);
306        DSIGSignature * sig = prov.newSignatureFromDOM(theDOM, sigNode);
307       
308        sig->load();
309
310        const char* tmp = XMLString::transcode(sig->getSignatureValue());
311        char *tmp2 = strip_newlines(tmp);
312        base64Decode(tmp2, strlen(tmp2), signature_bin, sig_len);
313        SHA1(signature_bin, sig_len, signature_hash);
314
315        char * sha1_string = getHexString(signature_hash, SHA1_LEN);
316       
317        CByteArray validate_data = do_post_validate_timestamp((char *)ts_resp.GetBytes(), (long)ts_resp.Size(), sha1_string);
318
319        if (validate_data.Size() == 0)
320        {
321                MWLOG(LEV_ERROR, MOD_APL, L"Timestamp Validation form returned nothing!");
322                return XADES_ERROR_INVALID_TIMESTAMP;
323        }
324       
325        result = grep_validation_result(validate_data);
326
327        return result? XADES_ERROR_OK : XADES_ERROR_INVALID_TIMESTAMP;
328
329
330}
331/*
332 * A little HTML-scraping to get the validation result and timestamp value
333 */
334bool SignatureVerifier::grep_validation_result (CByteArray validate_data)
335{
336       
337        // Accented 'a' encoded in latin-1 as expected
338        const char * valid_timestamp_pattern = "Selo Temporal V\xE1lido.";
339        const char * invalid_timestamp_pattern = "Selo Temporal n\xE3o corresponde ao ficheiro seleccionado";
340        const char * general_error_pattern = "Ocorreu um erro";
341        // const char * signed_by = getString(16);
342        unsigned char *haystack = validate_data.GetBytes();
343
344        if (validate_data.Size() == 0)
345        {
346                MWLOG(LEV_DEBUG, MOD_APL, L"ValidateTimestamp: grep_validation_result called with empty mp_timestamp_data");
347                return false;
348        }
349       
350        const char *ts_str = strstr((const char *)haystack, valid_timestamp_pattern);
351
352        //Warning: magic offsets ahead...
353        if (ts_str != NULL)
354        {
355                //Grab the TimeDate string
356                strncpy(m_time_and_date, ts_str+36, 27);
357                m_time_and_date[27] = 0;
358
359                return true; 
360        }
361        else
362        {
363                if (strstr((const char *)haystack, invalid_timestamp_pattern) == NULL)
364                //Unexpected output but invalid nonetheless!
365                        MWLOG(LEV_ERROR, MOD_APL, 
366                L"ValidateTimestamp: Unexpected output in the timestamp validation form, considered invalid but "
367                        L"probably the webform we're using is broken...");
368
369                return false; 
370        }
371
372}
373void SignatureVerifier::initXMLUtils()
374{
375        try {
376
377                XMLPlatformUtils::Initialize();
378                XSECPlatformUtils::Initialise();
379
380        }
381        catch (const XMLException &e) {
382
383                MWLOG(LEV_ERROR, MOD_APL, L"Error during initialisation of Xerces. Error Message: %s",
384                                e.getMessage()) ;
385                throw CMWEXCEPTION(EIDMW_XERCES_INIT_ERROR);
386        }
387}
388
389void SignatureVerifier::terminateXMLUtils()
390{
391        XSECPlatformUtils::Terminate();
392        XMLPlatformUtils::Terminate();
393}
394
395        SigVerifyErrorCode SignatureVerifier::Verify()
396        {
397
398                if (strlen(m_sigcontainer_path) == 0)
399                        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
400
401                if (!CPathUtil::existFile(m_sigcontainer_path))
402                        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
403
404                tHashedFile **hashes = NULL;
405                int i = 0;
406                SigVerifyErrorCode result;
407                Container *container = new Container(m_sigcontainer_path);
408                int n_files = 0;
409
410                hashes = container->getHashes(&n_files);
411
412                CByteArray sig_content = container->ExtractSignature();
413                CByteArray timestamp = container->ExtractTimestamp();
414
415                delete container;
416
417                initXMLUtils();
418                result = ValidateXades(sig_content, hashes);
419                terminateXMLUtils();
420               
421                //Dont check the Timestamp if the signature is invalid
422                if (result == eIDMW::XADES_ERROR_OK)
423                {
424                        if (timestamp.Size() > 0)
425                        {
426
427                                result = ValidateTimestamp(sig_content, timestamp);
428
429                        }
430                }
431
432                return result;
433
434        }
435
436X509 *loadCertFromPEM(const char *pem_buffer)
437{
438
439        char * final_pem = (char *)calloc(strlen(pem_buffer)+ 65, sizeof(char));
440        strcat(final_pem, "-----BEGIN CERTIFICATE-----\n");
441        strcat(final_pem, pem_buffer);
442        strcat(final_pem, "-----END CERTIFICATE-----\n");
443
444        BIO *pem_bio = BIO_new_mem_buf((void *)final_pem, -1);
445        X509 *cert = NULL;
446
447        if (pem_bio != NULL)
448        {
449                cert = PEM_read_bio_X509(pem_bio, NULL, NULL, NULL);
450                if (cert == NULL)
451                        MWLOG(LEV_ERROR, MOD_APL, L"Error parsing certificate from PEM string!");
452
453        }
454       
455        BIO_free_all(pem_bio); 
456        return cert;
457
458}
459
460char * SignatureVerifier::GetSigner()
461{
462
463        if (m_cert == NULL)
464                throw CMWEXCEPTION(EIDMW_ERR_CHECK);
465
466        return parseSubjectFromCert();
467
468}
469
470
471//TODO: Add some more exception-handling
472char * SignatureVerifier::GetTimestampString()
473{
474        if (strlen(m_time_and_date) == 0)
475                return NULL;
476
477        return m_time_and_date;
478
479}
480
481time_t SignatureVerifier::GetUnixTimestamp()
482{
483        if (strlen(m_time_and_date) == 0)
484                throw CMWEXCEPTION(EIDMW_ERR_CHECK);
485
486        struct tm time;
487        //This will ignore the milliseconds and timezone components...
488        char * ret = strptime(m_time_and_date, "%d-%m-%Y %H:%M:%S", &time);
489        if (ret == NULL)
490                printf("strptime failed!\n");
491
492        return mktime(&time);
493}
494
495
496char * SignatureVerifier::parseSubjectFromCert()
497{
498 
499       //Subject name
500       X509 *cert;
501
502       X509_NAME * subject_struct = X509_get_subject_name(m_cert);     
503
504       int space_needed = X509_NAME_get_text_by_NID(subject_struct, NID_commonName, NULL, 0) +1;
505       char *subject = (char *)malloc(space_needed);
506
507       X509_NAME_get_text_by_NID(subject_struct, NID_commonName, subject, space_needed);
508
509       return subject;
510}
511
512
513bool SignatureVerifier::ValidateCert(const char *pem_certificate)
514{
515        if (pem_certificate == NULL || strlen(pem_certificate) == 0)
516                return false;
517
518        bool bStopRequest = false;
519        bool res = false;
520
521        OpenSSL_add_all_algorithms();
522
523        X509_STORE *store = X509_STORE_new();
524       
525        X509 *pCert = NULL;
526        unsigned char * cert_data = NULL;
527        char *parsing_error = NULL;
528
529
530        for (unsigned int i = 0; i != CERTS_N;
531                i++)
532        {
533                pCert = NULL;
534                cert_data = PTEID_CERTS[i].cert_data;
535            pCert = d2i_X509(&pCert, (const unsigned char **)&cert_data, 
536                        PTEID_CERTS[i].cert_len);
537
538                if (pCert == NULL)
539                {
540                        parsing_error = ERR_error_string(ERR_get_error(), NULL);
541                MWLOG(LEV_ERROR, MOD_APL, L"XadesSignature::ValidateCert: Error parsing certificate #%d. Details: %s",
542                                i, parsing_error);
543                }
544                else
545                {
546                        if(X509_STORE_add_cert(store, pCert) == 0)
547                                printf("XadesSignature::ValidateCert: error adding certificate #%d\n",  i);
548                }
549       
550        }
551       
552        X509_STORE_CTX *ctx;
553        X509 *cert = NULL;
554
555        ctx = X509_STORE_CTX_new();
556
557        if (ctx == NULL)
558        {
559                /* Bad error */
560                return false;
561        }
562       
563        cert = loadCertFromPEM(pem_certificate);
564        m_cert = cert;
565
566        if (cert == NULL)
567        {
568                MWLOG(LEV_ERROR, MOD_APL, L"ValidateCert(): Broken or corrupt certificate");
569                return false;
570        }
571
572        //Load cert chain into store
573
574        X509_STORE_CTX_init(ctx, store, cert, NULL);
575
576        X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CB_ISSUER_CHECK);
577       
578        int validate_res = X509_verify_cert(ctx);
579
580        if (validate_res == 1)
581        {
582                MWLOG(LEV_DEBUG, MOD_APL, L"ValidateCert(): Valid certificate");
583                res = true;
584        }
585        else
586        {
587                res = false;
588                char subject_buf[1024];
589                std::string ssl_error = std::string(X509_verify_cert_error_string(ctx->error));
590                MWLOG(LEV_DEBUG, MOD_APL, L"ValidateCert(): Invalid certificate! OpenSSL Error: %ls", 
591                        utilStringWiden(ssl_error).c_str());
592
593                X509* error_cert = X509_STORE_CTX_get_current_cert(ctx);
594                X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), subject_buf, sizeof(subject_buf));
595                std::string subject_str = std::string(subject_buf);
596                MWLOG(LEV_DEBUG, MOD_APL, L"Certificate that caused the error: %ls",
597                        utilStringWiden(subject_str).c_str());
598
599        }
600
601        X509_STORE_CTX_free(ctx);
602        return res;
603
604}
605
606void SignatureVerifier::initXerces()
607{
608        try {
609
610                XMLPlatformUtils::Initialize();
611                XSECPlatformUtils::Initialise();
612
613        }
614        catch (const XMLException &e) {
615
616                MWLOG(LEV_ERROR, MOD_APL, L"Error during initialisation of Xerces. Error Message: %s",
617                     e.getMessage()) ;
618                throw CMWEXCEPTION(EIDMW_XERCES_INIT_ERROR);
619        }
620}
621
622
623
624bool SignatureImpl::checkExternalRefs(DSIGReferenceList *refs, tHashedFile **hashes)
625{
626        const char * URI;
627        XMLByte arr[SHA1_LEN*sizeof(unsigned char)];
628
629        bool res;
630        int j;
631        tHashedFile *hashed_file=NULL;
632
633        for ( j = 0 ; hashes[j] != NULL; j++)
634        {       
635                res = false;   
636                hashed_file = hashes[j];
637                for (int i = 0; i!=refs->getSize() ; i++)
638                {       
639                        DSIGReference * r = refs->item(i);
640
641                        r->readHash(arr, 20);
642
643                        if (memcmp(arr, hashed_file->hash->GetBytes(), SHA1_LEN) == 0)
644                        {   
645                                res = true;
646                                break;
647                        }
648
649                }
650                // If a single hash reference fails then abort
651                if (res == false)
652                {
653                        MWLOG (LEV_ERROR, MOD_APL,
654                                        L" checkExternalRefs(): SHA-1 Hash Value for file %ls doesn't match.",
655                                        utilStringWiden(*(hashed_file->URI)).c_str());
656                        return false;
657                }
658        }
659       
660        //If container has no signed files this test is automatically false
661        if (j == 0)
662        {
663                MWLOG (LEV_DEBUG, MOD_APL, L"checkExternalRefs(): Container has no signed files!");
664                return false;
665        }
666
667        MWLOG (LEV_DEBUG, MOD_APL, L" checkExternalRefs(): All External References matched.");
668        return true;
669}
670
671
672SigVerifyErrorCode SignatureVerifier::ValidateXades(CByteArray signature, tHashedFile **hashes)
673{
674        bool errorsOccured = false;
675       
676        MWLOG(LEV_DEBUG, MOD_APL, L"ValidateXades() called with XML content of %d bytes."
677                , signature.Size());
678
679        if (signature.Size() == 0)
680        {
681                MWLOG(LEV_ERROR, MOD_APL, L"ValidateXades() received empty Signature. This most likely means a corrupt zipfile");
682                return XADES_ERROR_NOSIG;
683        }
684
685//      initXerces();
686
687        //Load XML from a MemoryBuffer
688        MemBufInputSource * source = new MemBufInputSource(signature.GetBytes(),
689                        (XMLSize_t)signature.Size(),
690                        XMLString::transcode(generateId(20)));
691
692
693        XercesDOMParser * parser = new XercesDOMParser;
694        Janitor<XercesDOMParser> j_parser(parser);
695
696        parser->setDoNamespaces(true);
697        parser->setCreateEntityReferenceNodes(true);
698
699        // Now parse out file
700
701        xsecsize_t errorCount = 0;
702        try
703        {
704                parser->parse(*source);
705        }
706
707        catch (const XMLException& e)
708        {
709                MWLOG(LEV_ERROR, MOD_APL, L"An error occured during parsing\n   Message: %s",
710                                XMLString::transcode(e.getMessage()));
711                errorsOccured = true;
712        }
713        catch (const DOMException& e)
714        {
715                MWLOG(LEV_ERROR, MOD_APL, L"A DOM error occured during parsing\n   DOMException code: %d",
716                                e.code);
717                errorsOccured = true;
718        }
719
720        if (errorsOccured) {
721                MWLOG(LEV_ERROR, MOD_APL, L"Errors parsing XML Signature, bailing out");
722                return XADES_ERROR_BROKENSIG;
723        }
724
725       
726        DOMNode *doc;           // The document that we parsed
727
728        doc = parser->getDocument();
729        /*
730        //Saving the DOM Node as an instance variable to avoid reparsing
731        // We need to clone the Node because its memory is owned by the parser object
732        try
733        {
734        pimpl->m_signature_dom = doc->cloneNode(true);
735        }
736        catch (const DOMException& e)
737        {
738       
739                MWLOG(LEV_ERROR, MOD_APL, L"An error occured during cloneNode(). Message: %s",
740                                e.getMessage());
741        }
742        */
743
744        XERCES_NS DOMDocument *theDOM = parser->getDocument();
745
746
747        // Find the signature node
748       
749        DOMNode *sigNode = findDSIGNode(doc, "Signature");
750
751        // Create the signature checker
752
753        if (sigNode == NULL) {
754
755                MWLOG(LEV_ERROR, MOD_APL, L"ValidateXades: Could not find <Signature> node in the signature provided");
756                return XADES_ERROR_BROKENSIG;
757        }
758
759        MWLOG(LEV_DEBUG, MOD_APL, L"ValidateXades: XML signature correctly parsed.");
760
761        XSECProvider prov;
762        XSECKeyInfoResolverDefault theKeyInfoResolver;
763
764        DSIGSignature * sig = prov.newSignatureFromDOM(theDOM, sigNode);
765
766        // The only way we can verify is using keys read directly from the KeyInfo list,
767        // so we add a KeyInfoResolverDefault to the Signature.
768
769        sig->setKeyInfoResolver(&theKeyInfoResolver);
770        sig->registerIdAttributeName(MAKE_UNICODE_STRING("ID"));
771
772        bool result = false;
773        bool extern_result = false; 
774        try {
775
776                sig->load();
777                               
778                // Validate signing certificate first
779                DSIGKeyInfo *keyinfo = sig->getKeyInfoList()->item(0);
780                // If keyinfo is NULL this most certainly means a broken signature
781                // just skip certificate checking
782                if (keyinfo != NULL)
783                {
784
785                        //This should always be the case for signatures created by pteid-mw
786                        if (keyinfo->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509)
787                        {
788                                DSIGKeyInfoX509 *cert_element = dynamic_cast<DSIGKeyInfoX509 *> (keyinfo);
789                                const XMLCh *pem_cert = cert_element->getCertificateItem(0);
790                                char * tmp_cert = XMLString::transcode(pem_cert);
791                       
792                                bool cert_result = ValidateCert(tmp_cert);
793
794                                if (!cert_result)
795                                {
796                                        return XADES_ERROR_INVALID_CERTIFICATE;
797                                }
798
799                               
800                                XMLString::release(&tmp_cert);
801                        }
802                }
803               
804
805                DSIGReferenceList *refs = sig->getReferenceList();
806
807                if (refs != NULL)
808                        extern_result = pimpl->checkExternalRefs(refs, hashes);
809                if (!extern_result)
810                {
811                        return XADES_ERROR_EXTERNAL_REFS;
812                }
813               
814                result = sig->verifySignatureOnly();
815
816        }
817        catch (XSECException &e) {
818                MWLOG(LEV_ERROR, MOD_APL, L"ValidateXades(): XSECException thrown. Detail: %ls",
819                        e.getMsg());
820                result = false;
821        }
822        catch (XSECCryptoException &e) {
823                MWLOG(LEV_ERROR, MOD_APL, L"ValidateXades(): XSECCryptoException thrown. Detail: %ls",
824                        e.getMsg());
825                result = false;
826        }
827
828//      XSECPlatformUtils::Terminate();
829//      XMLPlatformUtils::Terminate();
830
831        if (result == false)
832        {
833                return XADES_ERROR_INVALID_RSA;
834        }
835
836        return XADES_ERROR_OK;
837
838}
839
840}
Note: See TracBrowser for help on using the browser.