libdigidocpp
DDoc.cpp
Go to the documentation of this file.
1 /*
2  * libdigidocpp
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  */
19 
20 #include "DDoc_p.h"
21 #include "DDoc.h"
22 
23 #include "crypto/cert/X509Cert.h"
24 #include "crypto/ocsp/OCSP.h"
25 #include "crypto/signer/Signer.h"
26 #include "io/ISerialize.h"
27 #include "util/DateTime.h"
28 #include "util/File.h"
29 #include "XmlConf.h"
30 
31 #include <fstream>
32 
33 using namespace digidoc;
34 
35 #if defined(__APPLE__)
36 # define LIBDIGIDOC_NAME "libdigidoc.dylib"
37 #elif defined(_WIN32)
38 # define LIBDIGIDOC_NAME "digidoc.dll"
39 #else
40 # define LIBDIGIDOC_NAME "libdigidoc.so.2"
41 #endif
42 
43 
44 
46 
48 : ready(false)
49 , f_calculateDataFileSizeAndDigest(0)
50 , f_cleanupConfigStore(0)
51 , f_convertStringToTimestamp(0)
52 , f_createOrReplacePrivateConfigItem(0)
53 , f_createSignedDoc(0)
54 , f_DataFile_delete(0)
55 , f_DataFile_new(0)
56 , f_ddocPrepareSignature(0)
57 , f_ddocSaxReadSignedDocFromFile(0)
58 , f_ddocSigInfo_GetOCSPRespondersCert(0)
59 , f_ddocSigInfo_GetSignatureValue_Value(0)
60 , f_ddocSigInfo_GetSignersCert(0)
61 , f_ddocSigInfo_SetSignatureValue(0)
62 , f_getCountOfDataFiles(0)
63 , f_getCountOfSignatures(0)
64 , f_getDataFile(0)
65 , f_getErrorClass(0)
66 , f_getErrorInfo(0)
67 , f_getErrorString(0)
68 , f_getSignature(0)
69 , f_finalizeDigiDocLib(0)
70 , f_hasUnreadErrors(0)
71 , f_initDigiDocLib(0)
72 , f_initConfigStore(0)
73 , f_notarizeSignature(0)
74 , f_ddocSaxExtractDataFile(0)
75 , f_setGUIVersion(0)
76 , f_SignatureInfo_delete(0)
77 , f_SignedDoc_free(0)
78 , f_SignedDoc_new(0)
79 , f_verifySignatureAndNotary(0)
80 #ifndef LINKED_LIBDIGIDOC
81 , h(0)
82 #endif
83 , ref(0)
84 {
85  if( !loadSymbols() )
86  return;
87 
88 #ifdef WIN32
91 #else
92  f_initConfigStore( 0 );
93 #endif
94  f_setGUIVersion( appInfo().c_str() );
95  ready = true;
96 }
97 
99 {
100  if( ready )
101  {
103  //f_finalizeDigiDocLib(); // dont finalize it unloads openssl also
104  }
105 #ifndef LINKED_LIBDIGIDOC
106  unload();
107 #endif
108 }
109 
111 {
112  if( !m_instance )
113  return;
114  --m_instance->ref;
115  if( m_instance->ref > 0 )
116  return;
117  delete m_instance;
118  m_instance = 0;
119 }
120 
122 {
123  if( !m_instance )
124  m_instance = new DDocLibrary();
125  ++m_instance->ref;
126  return m_instance;
127 }
128 
130 {
131 #ifdef LINKED_LIBDIGIDOC
132  return
133  (f_calculateDataFileSizeAndDigest = calculateDataFileSizeAndDigest) &&
134  (f_cleanupConfigStore = cleanupConfigStore) &&
135  (f_convertStringToTimestamp = convertStringToTimestamp) &&
136  (f_createOrReplacePrivateConfigItem = createOrReplacePrivateConfigItem) &&
137  (f_createSignedDoc = createSignedDoc) &&
138  (f_DataFile_delete = DataFile_delete) &&
139  (f_DataFile_new = DataFile_new) &&
140  (f_ddocPrepareSignature = ddocPrepareSignature) &&
141  (f_ddocSaxReadSignedDocFromFile = ddocSaxReadSignedDocFromFile) &&
142  (f_ddocSigInfo_GetOCSPRespondersCert = ddocSigInfo_GetOCSPRespondersCert) &&
143  (f_ddocSigInfo_GetSignatureValue_Value = ddocSigInfo_GetSignatureValue_Value) &&
144  (f_ddocSigInfo_GetSignersCert = ddocSigInfo_GetSignersCert) &&
145  (f_ddocSigInfo_SetSignatureValue = ddocSigInfo_SetSignatureValue) &&
146  (f_getCountOfDataFiles = getCountOfDataFiles) &&
147  (f_getCountOfSignatures = getCountOfSignatures)&&
148  (f_getDataFile = getDataFile) &&
149  (f_getErrorClass = getErrorClass) &&
150  (f_getErrorInfo = getErrorInfo) &&
151  (f_getErrorString = getErrorString) &&
152  (f_getSignature = getSignature) &&
153  (f_finalizeDigiDocLib = finalizeDigiDocLib) &&
154  (f_hasUnreadErrors = hasUnreadErrors) &&
155  (f_initDigiDocLib = initDigiDocLib) &&
156  (f_initConfigStore = initConfigStore) &&
157  (f_notarizeSignature = notarizeSignature) &&
158  (f_ddocSaxExtractDataFile = ddocSaxExtractDataFile) &&
159  (f_setGUIVersion = setGUIVersion) &&
160  (f_SignatureInfo_delete = SignatureInfo_delete) &&
161  (f_SignedDoc_free = SignedDoc_free) &&
162  (f_SignedDoc_new = SignedDoc_new) &&
163  (f_verifySignatureAndNotary = verifySignatureAndNotary);
164 #else
165  return load() &&
166  (f_calculateDataFileSizeAndDigest = (sym_calculateDataFileSizeAndDigest)resolve("calculateDataFileSizeAndDigest")) &&
167  (f_cleanupConfigStore = (sym_cleanupConfigStore)resolve("cleanupConfigStore")) &&
168  (f_convertStringToTimestamp = (sym_convertStringToTimestamp)resolve("convertStringToTimestamp")) &&
169  (f_createOrReplacePrivateConfigItem = (sym_createOrReplacePrivateConfigItem)resolve("createOrReplacePrivateConfigItem")) &&
170  (f_createSignedDoc = (sym_createSignedDoc)resolve("createSignedDoc")) &&
171  (f_DataFile_delete = (sym_DataFile_delete)resolve("DataFile_delete")) &&
172  (f_DataFile_new = (sym_DataFile_new)resolve("DataFile_new")) &&
173  (f_ddocPrepareSignature = (sym_ddocPrepareSignature)resolve("ddocPrepareSignature")) &&
174  (f_ddocSaxReadSignedDocFromFile = (sym_ddocSaxReadSignedDocFromFile)resolve("ddocSaxReadSignedDocFromFile")) &&
175  (f_ddocSigInfo_GetOCSPRespondersCert = (sym_ddocSigInfo_GetOCSPRespondersCert)resolve("ddocSigInfo_GetOCSPRespondersCert")) &&
176  (f_ddocSigInfo_GetSignatureValue_Value = (sym_ddocSigInfo_GetSignatureValue_Value)resolve("ddocSigInfo_GetSignatureValue_Value")) &&
177  (f_ddocSigInfo_GetSignersCert = (sym_ddocSigInfo_GetSignersCert)resolve("ddocSigInfo_GetSignersCert")) &&
178  (f_ddocSigInfo_SetSignatureValue = (sym_ddocSigInfo_SetSignatureValue)resolve("ddocSigInfo_SetSignatureValue")) &&
179  (f_getCountOfDataFiles = (sym_getCountOfDataFiles)resolve("getCountOfDataFiles")) &&
180  (f_getCountOfSignatures = (sym_getCountOfSignatures)resolve("getCountOfSignatures")) &&
181  (f_getDataFile = (sym_getDataFile)resolve("getDataFile")) &&
182  (f_getErrorClass = sym_getErrorClass(resolve("getErrorClass"))) &&
183  (f_getErrorInfo = sym_getErrorInfo(resolve("getErrorInfo"))) &&
184  (f_getErrorString = (sym_getErrorString)resolve("getErrorString")) &&
185  (f_getSignature = (sym_getSignature)resolve("getSignature")) &&
186  (f_finalizeDigiDocLib = (sym_finalizeDigiDocLib)resolve("finalizeDigiDocLib")) &&
187  (f_hasUnreadErrors = sym_hasUnreadErrors(resolve("hasUnreadErrors"))) &&
188  (f_initDigiDocLib = (sym_initDigiDocLib)resolve("initDigiDocLib")) &&
189  (f_initConfigStore = (sym_initConfigStore)resolve("initConfigStore")) &&
190  (f_notarizeSignature = (sym_notarizeSignature)resolve("notarizeSignature")) &&
191  (f_ddocSaxExtractDataFile = (sym_ddocSaxExtractDataFile)resolve("ddocSaxExtractDataFile")) &&
192  (f_setGUIVersion = sym_setGUIVersion(resolve("setGUIVersion"))) &&
193  (f_SignatureInfo_delete = (sym_SignatureInfo_delete)resolve("SignatureInfo_delete")) &&
194  (f_SignedDoc_free = (sym_SignedDoc_free)resolve("SignedDoc_free")) &&
195  (f_SignedDoc_new = (sym_SignedDoc_new)resolve("SignedDoc_new")) &&
196  (f_verifySignatureAndNotary = (sym_verifySignatureAndNotary)resolve("verifySignatureAndNotary"));
197 #endif
198 }
199 
200 #ifndef LINKED_LIBDIGIDOC
201 #ifdef _WIN32
202 
203 bool DDocLibrary::load()
204 { return (h = LoadLibrary( TEXT(LIBDIGIDOC_NAME) )) != 0; }
205 
206 void* DDocLibrary::resolve( const char *symbol )
207 { return h ? (void*)GetProcAddress( h, symbol ) : 0; }
208 
209 void DDocLibrary::unload()
210 { if( h ) FreeLibrary( h ); h = 0; }
211 
212 #else
213 
215 { return (h = dlopen( LIBDIGIDOC_NAME, RTLD_LAZY )); }
216 
217 void* DDocLibrary::resolve( const char *symbol )
218 { return h ? dlsym( h, symbol ) : 0; }
219 
221 { if( h ) dlclose( h ); h = 0; }
222 
223 #endif
224 #endif
225 
226 
227 
229 : lib( DDocLibrary::instance() )
230 , doc(0)
231 {}
232 
234 {
235  for( std::vector<SignatureDDOC*>::const_iterator i = signatures.begin();
236  i != signatures.end(); ++i )
237  delete *i;
238  if( lib->f_SignedDoc_free )
240  lib->destroy();
241 }
242 
244 {
245  for( std::vector<SignatureDDOC*>::const_iterator i = signatures.begin();
246  i != signatures.end(); ++i )
247  delete *i;
248  signatures.clear();
249  int count = lib->f_getCountOfSignatures( doc );
250  for( int i = 0; i < count; ++i )
251  signatures.push_back( new SignatureDDOC( i, this ) );
252 }
253 
254 template<typename T>
255 void DDocPrivate::throwCodeError( int err, const std::string &msg, int line ) const
256 {
257  switch( err )
258  {
259  case ERR_OK: break;
260  case ERR_PKCS_LOGIN:
261  throwError<T>( "PIN Incorrect", line, err, Exception::PINIncorrect );
262  case ERR_OCSP_CERT_REVOKED:
263  throwError<T>( "Certificate status: revoked", line, err, Exception::CertificateRevoked );
264  case ERR_OCSP_CERT_UNKNOWN:
265  throwError<T>( "Certificate status: unknown", line, err, Exception::CertificateUnknown );
266  case ERR_OCSP_RESP_NOT_TRUSTED:
267  throwError<T>( "Failed to find ocsp responder.", line, err, Exception::OCSPResponderMissing );
268  case ERR_OCSP_CERT_NOTFOUND:
269  throwError<T>( "OCSP certificate loading failed", line, err, Exception::OCSPCertMissing );
270  case ERR_OCSP_UNAUTHORIZED:
271  throwError<T>( "Unauthorized OCSP request", line, err, Exception::OCSPRequestUnauthorized );
272  case ERR_CERT_READ:
273  case ERR_UNKNOWN_CA:
274  case ERR_SIGNERS_CERT_NOT_TRUSTED:
275  throwError<T>( msg, line, err, Exception::CertificateUnknown );
276  default:
277  throwError<T>( msg, line, err );
278  }
279 }
280 
281 void DDocPrivate::throwDocOpenError( int line ) const throw(BDocException)
282 {
283  if( !lib->ready )
284  throwError<BDocException>( "DDoc library not loaded", line );
285  if( !doc )
286  throwError<BDocException>( "Document not open", line );
287 }
288 
289 template<typename T>
290 void DDocPrivate::throwError( const std::string &msg, int line, int err, const Exception::ExceptionCode &code ) const
291 {
292  std::stringstream ddoc;
293  ddoc << msg;
294  if( lib->f_getErrorString )
295  {
296  const char *errorClass[] = {"NO_ERRORS", "TECHNICAL", "USER", "LIBRARY"};
297  while( lib->f_hasUnreadErrors() )
298  {
299  ErrorInfo *e = lib->f_getErrorInfo();
300  ddoc << "\nERROR " << e->code << " " << lib->f_getErrorString(e->code)
301  << " (" << e->fileName << ":" << e->line
302  << " " << e->assertion << " " << errorClass[lib->f_getErrorClass(e->code)] << ")";
303  }
304  }
305  T e( __FILE__, line, ddoc.str() );
306  e.setCode( code );
307  e.setDDoc( err );
308  throw e;
309 }
310 
311 void DDocPrivate::throwSignError( SignatureInfo *sig, int err, const std::string &msg, int line ) const throw(BDocException)
312 {
313  if( err && sig )
314  lib->f_SignatureInfo_delete( doc, sig->szId );
315  throwCodeError<BDocException>( err, msg, line );
316 }
317 
318 
319 
324 : Signature( id )
325 , d( new SignatureDDOCPrivate )
326 {
327  if( !priv )
328  throw SignatureException( __FILE__, __LINE__, "Null pointer in SignatureDDOC constructor" );
329  d->priv = priv;
330  d->lib = priv->lib;
331  d->sig = priv->lib->f_getSignature( priv->doc, id );
332  if( !d->sig )
333  throw SignatureException( __FILE__, __LINE__, "Null pointer in SignatureDDOC constructor" );
334 
336  catch( const Exception & ) {}
337 
339  DigiDocMemBuf *value = d->lib->f_ddocSigInfo_GetSignatureValue_Value( d->sig );
340  s.signature = (unsigned char*)value->pMem;
341  s.length = value->nLen;
342  setSignatureValue( s );
343 
345  if( d->sig->sigProdPlace.szCity )
346  l.city = d->sig->sigProdPlace.szCity;
347  if( d->sig->sigProdPlace.szStateOrProvince )
348  l.stateOrProvince = d->sig->sigProdPlace.szStateOrProvince;
349  if( d->sig->sigProdPlace.szPostalCode )
350  l.postalCode = d->sig->sigProdPlace.szPostalCode;
351  if( d->sig->sigProdPlace.szCountryName )
352  l.countryName = d->sig->sigProdPlace.szCountryName;
354 
355  SignerRole r;
356  for( int i = 0; i < d->sig->signerRole.nClaimedRoles; ++i )
357  r.claimedRoles.push_back( d->sig->signerRole.pClaimedRoles[i] );
358  setSignerRole( r );
359 
360  Timestamp ts;
361  d->lib->f_convertStringToTimestamp( d->priv->doc, d->sig->szTimeStamp, &ts );
362  setSigningTime( xml_schema::DateTime( ts.year, ts.mon, ts.day, ts.hour, ts.min, ts.sec, ts.tz, 0 ) );
363 }
364 
369 
373 std::string SignatureDDOC::getMediaType() const
374 {
375  std::ostringstream s;
376  s << d->priv->doc->szFormat << "/" << d->priv->doc->szFormatVer;
377  return s.str();
378 }
379 
383 std::vector<unsigned char> SignatureDDOC::getNonce() const
384 {
385  NotaryInfo *n = d->sig->pNotary;
386  if( !n )
387  return std::vector<unsigned char>();
388 
389  return digidoc::OCSP().getNonce( std::vector<unsigned char>(
390  (char*)n->mbufOcspResponse.pMem, (char*)n->mbufOcspResponse.pMem + n->mbufOcspResponse.nLen ) );
391 }
392 
397 {
398  try { return X509Cert( d->lib->f_ddocSigInfo_GetOCSPRespondersCert( d->sig ) ); }
399  catch( const Exception & ) {}
400  return X509Cert();
401 }
402 
406 std::string SignatureDDOC::getProducedAt() const
407 {
408  NotaryInfo *n = d->sig->pNotary;
409  if( !n || !n->timeProduced )
410  return "";
411  Timestamp ts = { 0, 0, 0, 0, 0, 0, 0 };
412  d->lib->f_convertStringToTimestamp( d->priv->doc, n->timeProduced, &ts );
413  return util::date::xsd2string( xml_schema::DateTime( ts.year, ts.mon, ts.day, ts.hour, ts.min, ts.sec, ts.tz, 0 ) );
414 }
415 
419 std::string SignatureDDOC::getResponderID() const
420 {
421  NotaryInfo *n = d->sig->pNotary;
422  return n ? std::string( (const char*)n->mbufRespId.pMem, n->mbufRespId.nLen ) : std::string();
423 }
424 
429 void SignatureDDOC::getRevocationOCSPRef(std::vector<unsigned char>& data, std::string& digestMethodUri) const throw(SignatureException)
430 {
431  NotaryInfo *n = d->sig->pNotary;
432  if( !n )
433  return;
434  data.resize( n->mbufOcspDigest.nLen );
435  std::copy( (unsigned char*)n->mbufOcspDigest.pMem,
436  (unsigned char*)n->mbufOcspDigest.pMem + n->mbufOcspDigest.nLen, data.begin() );
437  if( n->szDigestType )
438  digestMethodUri = n->szDigestType;
439 }
440 
452 {
453  int err = d->lib->f_verifySignatureAndNotary( d->priv->doc, d->sig, d->priv->filename.c_str() );
454  d->priv->throwCodeError<SignatureException>( err, "Failed to validate signature", __LINE__ );
455 }
456 
463 {
464  validateOffline();
465  return GOOD;
466 }
467 
474 
475 
476 
481 : d( new DDocPrivate )
482 {
483  if( !d->lib->ready )
484  return;
485  /*int err =*/ d->lib->f_SignedDoc_new( &d->doc, "DIGIDOC-XML", "1.3" );
486  //throwError( err, "Failed to create new document", __LINE__ );
487 }
488 
492 DDoc::~DDoc() { delete d; }
493 
497 digidoc::DDoc::DDoc(const std::string &path) throw(IOException, BDocException)
498  : d( new DDocPrivate )
499 {
500  if( !d->lib->ready )
501  d->throwError<BDocException>( "DDoc library not loaded", __LINE__ );
502 
503  d->filename = path;
504  loadFile();
505 }
506 
511 {
512  int err = d->lib->f_ddocSaxReadSignedDocFromFile( &d->doc, d->filename.c_str(), 0, 0 );
513  switch( err )
514  {
515  case ERR_OK:
516  case ERR_OCSP_CERT_REVOKED:
517  case ERR_OCSP_CERT_UNKNOWN:
518  if( d->doc )
519  break;
520  err = ERR_DIGIDOC_PARSE;
521  default:
522  d->lib->f_SignedDoc_free( d->doc );
523  d->doc = 0;
524  d->throwCodeError<BDocException>( err, "Failed to open ddoc file", __LINE__ );
525  return;
526  }
527 
528  std::string path = util::File::createTempDirectory();
529  int count = d->lib->f_getCountOfDataFiles( d->doc );
530  for( int i = 0; i < count; ++i )
531  {
532  DataFile *data = d->lib->f_getDataFile( d->doc, i );
533  Document doc( data->szFileName, util::File::path(path, data->szFileName), data->szMimeType, data->szId );
534  int err = d->lib->f_ddocSaxExtractDataFile( d->doc, d->filename.c_str(),
535  doc.getFilePath().c_str(), data->szId, CHARSET_UTF_8 );
536  if( err )
537  {
538  if( d->doc )
539  d->lib->f_SignedDoc_free( d->doc );
540  d->doc = 0;
541  d->throwCodeError<BDocException>( err, "Failed to exctract files", __LINE__ );
542  }
543  d->documents.push_back( doc );
544  }
545 
546  d->loadSignatures();
547 }
548 
558 void DDoc::addDocument( const Document &document ) throw(BDocException)
559 {
560  d->throwDocOpenError( __LINE__ );
561 
562  DataFile *data = 0;
563  int err = d->lib->f_DataFile_new( &data, d->doc, 0, document.getFilePath().c_str(),
564  CONTENT_EMBEDDED_BASE64, document.getMediaType().c_str(), 0, 0, 0, 0, CHARSET_UTF_8 );
565  d->throwCodeError<BDocException>( err, "Failed to add file '" + document.getFilePath() + "'" , __LINE__ );
566 
567  err = d->lib->f_calculateDataFileSizeAndDigest(
568  d->doc, data->szId, document.getFilePath().c_str(), DIGEST_SHA1 );
569  d->throwCodeError<BDocException>( err, "Failed calculate file digest and size", __LINE__ );
570  d->documents.push_back(
571  Document( document.getFileName(), document.getFilePath(), document.getMediaType(), data->szId ) );
572 }
573 
580 void DDoc::addSignature(const std::vector<unsigned char> &signature) throw(BDocException)
581 {
582  std::string fileName = util::File::tempFileName();
583  std::ofstream ofs(util::File::encodeName(fileName).c_str());
584  ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
585  ofs << "<SignedDoc format=\"DIGIDOC-XML\" version=\"1.3\" xmlns=\"http://www.sk.ee/DigiDoc/v1.3.0#\">\n";
586  for(std::vector<unsigned char>::const_iterator i = signature.begin(); i != signature.end(); ++i)
587  ofs << *i;
588  ofs << "</SignedDoc>";
589  ofs.flush();
590  ofs.close();
591 
592  SignedDoc *sigDoc = 0;
593  int err = d->lib->f_ddocSaxReadSignedDocFromFile( &sigDoc, fileName.c_str(), 0, 0 );
594  d->throwCodeError<BDocException>( err, "Failed to sign document", __LINE__ );
595 
596  SignatureInfo **signatures = (SignatureInfo**)realloc( d->doc->pSignatures,
597  (d->doc->nSignatures + sigDoc->nSignatures) * sizeof(void *));
598  if( !signatures )
599  {
600  d->lib->f_SignedDoc_free( sigDoc );
601  d->throwError<BDocException>( "Failed to sign document", __LINE__ );
602  }
603 
604  d->doc->pSignatures = signatures;
605  for( int i = 0; i < sigDoc->nSignatures; ++i )
606  {
607  d->doc->pSignatures[d->doc->nSignatures + i] = sigDoc->pSignatures[i]; // take ownership
608  sigDoc->pSignatures[i] = 0;
609  // from ddocReadNewSignaturesFromDdoc
610  ((char*)d->doc->pSignatures[d->doc->nSignatures + i]->pDocs[0]->szDigest)[0] = 0x0A;
611  }
612  d->doc->nSignatures += sigDoc->nSignatures;
613  sigDoc->nSignatures = 0;
614 
615  d->lib->f_SignedDoc_free( sigDoc );
616  d->loadSignatures();
617 }
618 
622 unsigned int DDoc::documentCount() const { return (unsigned int)d->documents.size(); }
623 
628 
636 Document DDoc::getDocument( unsigned int id ) const throw(BDocException)
637 {
638  d->throwDocOpenError( __LINE__ );
639 
640  if( id >= d->documents.size() )
641  {
642  std::ostringstream s;
643  s << "Incorrect document id " << id << ", there are only ";
644  s << d->documents.size() << " documents in container.";
645  d->throwError<BDocException>( s.str(), __LINE__ );
646  }
647 
648  return d->documents[id];
649 }
650 
658 const Signature* DDoc::getSignature( unsigned int id ) const throw(BDocException)
659 {
660  d->throwDocOpenError( __LINE__ );
661 
662  if( id >= d->signatures.size() )
663  {
664  std::ostringstream s;
665  s << "Incorrect signature id " << id << ", there are only ";
666  s << d->signatures.size() << " signatures in container.";
667  d->throwError<BDocException>( s.str(), __LINE__ );
668  }
669 
670  return d->signatures[id];
671 }
672 
681 void DDoc::removeDocument( unsigned int id ) throw(BDocException)
682 {
683  d->throwDocOpenError( __LINE__ );
684 
685  if( id >= d->documents.size() )
686  {
687  std::ostringstream s;
688  s << "Incorrect document id " << id << ", there are only ";
689  s << d->documents.size() << " documents in container.";
690  d->throwError<BDocException>( s.str(), __LINE__ );
691  }
692  if( !d->signatures.empty() )
693  {
694  d->throwError<BDocException>(
695  "Can not remove document from container which has signatures, "
696  "remove all signatures before removing document.", __LINE__ );
697  }
698 
699  int err = d->lib->f_DataFile_delete( d->doc, d->doc->pDataFiles[id]->szId );
700  d->throwCodeError<BDocException>( err, "Failed to delete file", __LINE__ );
701  d->documents.erase( d->documents.begin() + id );
702 }
703 
710 void DDoc::removeSignature( unsigned int id ) throw(BDocException)
711 {
712  d->throwDocOpenError( __LINE__ );
713 
714  if( id >= d->signatures.size() )
715  {
716  std::ostringstream s;
717  s << "Incorrect signature id " << id << ", there are only ";
718  s << d->signatures.size() << " signatures in container.";
719  d->throwError<BDocException>( s.str(), __LINE__ );
720  }
721 
722  int err = d->lib->f_SignatureInfo_delete( d->doc, d->doc->pSignatures[id]->szId );
723  d->throwCodeError<BDocException>( err, "Failed to remove signature", __LINE__ );
724  d->loadSignatures();
725 }
726 
736 {
737  d->throwDocOpenError( __LINE__ );
738  int err = d->lib->f_createSignedDoc( d->doc, d->filename.c_str(), d->filename.c_str() );
739  d->throwCodeError<BDocException>( err, "Failed to save document", __LINE__ );
740 }
741 
751 void DDoc::saveTo( const std::string &path ) throw(IOException, BDocException)
752 {
753  d->throwDocOpenError( __LINE__ );
754  int err = d->lib->f_createSignedDoc( d->doc, d->filename.c_str(), path.c_str() );
755  d->throwCodeError<BDocException>( err, "Failed to save document", __LINE__ );
756  d->filename = path;
757 }
758 
766 void DDoc::sign( Signer *signer ) throw(BDocException)
767 {
768  d->throwDocOpenError( __LINE__ );
769 
770  if( !signer->getCert() )
771  throw BDocException( __FILE__, __LINE__, "Failed to sign document, Certificate cannot be NULL" );
772 
773  X509 *x509 = 0;
774  try
775  {
776  x509 = X509_dup( signer->getCert() );
777  }
778  catch( const Exception &e )
779  {
780  throw BDocException( __FILE__, __LINE__, "Failed to sign document", e );
781  }
782 
783  std::ostringstream role;
784  SignerRole::TRoles r = signer->getSignerRole().claimedRoles;
785  for( SignerRole::TRoles::const_iterator i = r.begin(); i != r.end(); ++i )
786  {
787  role << *i;
788  if( i + 1 != r.end() )
789  role << " / ";
790  }
791  SignatureProductionPlace l = signer->getSignatureProductionPlace();
792 
793  SignatureInfo *info = 0;
794  int err = d->lib->f_ddocPrepareSignature( d->doc, &info, role.str().c_str(), l.city.c_str(),
795  l.stateOrProvince.c_str(), l.postalCode.c_str(), l.countryName.c_str(), x509, 0 );
796  d->throwSignError( info, err, "Failed to sign document", __LINE__ );
797 
798  int size = 0;
799  try
800  {
801  size = X509Cert(x509).getPaddingSize();
802  }
803  catch( const IOException &e )
804  {
805  d->lib->f_SignatureInfo_delete( d->doc, info->szId );
806  throw BDocException( __FILE__, __LINE__, "Failed to sign document", e );
807  }
808  std::vector<unsigned char> buf1(size);
809  Signer::Signature signatureSha1Rsa = { &buf1[0], (unsigned int)buf1.size() };
810 
811  std::vector<unsigned char> buf2(
812  (unsigned char*)info->pSigInfoRealDigest->mbufDigestValue.pMem,
813  (unsigned char*)info->pSigInfoRealDigest->mbufDigestValue.pMem + info->pSigInfoRealDigest->mbufDigestValue.nLen );
814  Signer::Digest digest = { NID_sha1, &buf2[0], (unsigned int)buf2.size() };
815 
816  try
817  {
818  signer->sign( digest, signatureSha1Rsa );
819  }
820  catch( const Exception &e )
821  {
822  d->lib->f_SignatureInfo_delete( d->doc, info->szId );
823  throw BDocException( __FILE__, __LINE__, "Failed to sign document", e );
824  }
825  err = d->lib->f_ddocSigInfo_SetSignatureValue( info, (const char*)signatureSha1Rsa.signature, signatureSha1Rsa.length );
826  d->throwSignError( info, err, "Failed to sign document", __LINE__ );
827 
828  Conf *c = Conf::getInstance();
829  if( !c->getProxyHost().empty() )
830  {
831  d->lib->f_createOrReplacePrivateConfigItem( 0, "USE_PROXY", "true" );
832  d->lib->f_createOrReplacePrivateConfigItem( 0, "DIGIDOC_PROXY_HOST", c->getProxyHost().c_str() );
833  d->lib->f_createOrReplacePrivateConfigItem( 0, "DIGIDOC_PROXY_PORT", c->getProxyPort().c_str() );
834  d->lib->f_createOrReplacePrivateConfigItem( 0, "DIGIDOC_PROXY_USER", c->getProxyUser().c_str() );
835  d->lib->f_createOrReplacePrivateConfigItem( 0, "DIGIDOC_PROXY_PASS", c->getProxyPass().c_str() );
836  }
837  else
838  d->lib->f_createOrReplacePrivateConfigItem( 0, "USE_PROXY", "false" );
839 
840  if( c->getPKCS12Disable() )
841  d->lib->f_createOrReplacePrivateConfigItem( 0, "SIGN_OCSP", "false" );
842  else
843  {
844  d->lib->f_createOrReplacePrivateConfigItem( 0, "SIGN_OCSP", "true" );
845  d->lib->f_createOrReplacePrivateConfigItem( 0, "DIGIDOC_PKCS_FILE",
846  c->getPKCS12Cert().c_str() );
847  d->lib->f_createOrReplacePrivateConfigItem( 0, "DIGIDOC_PKCS_PASSWD",
848  c->getPKCS12Pass().c_str() );
849  }
850 
851  err = d->lib->f_notarizeSignature( d->doc, info );
852  d->throwSignError( info, err, "Failed to sign document", __LINE__ );
853 
854  err = d->lib->f_verifySignatureAndNotary( d->doc, info, d->filename.c_str() );
855  d->throwSignError( info, err, "Failed to sign document", __LINE__ );
856 
857  d->loadSignatures();
858 }
859 
863 unsigned int DDoc::signatureCount() const { return (unsigned int)d->signatures.size(); }
864 
868 std::vector<unsigned char> DDoc::getFileDigest( unsigned int id ) throw(BDocException)
869 {
870  d->throwDocOpenError( __LINE__ );
871 
872  DataFile *data = d->lib->f_getDataFile( d->doc, id );
873  if( !data )
874  {
875  std::ostringstream s;
876  s << "Incorrect document id " << id << ", there are only ";
877  s << d->lib->f_getCountOfDataFiles( d->doc ) << " documents in container.";
878  d->throwError<BDocException>( s.str(), __LINE__ );
879  return std::vector<unsigned char>();
880  }
881 
882  return std::vector<unsigned char>( (unsigned char*)data->mbufDigest.pMem,
883  (unsigned char*)data->mbufDigest.pMem + data->mbufDigest.nLen );
884 }