Support for various warnings about expiring encryption certificates.
[gpgme.git] / gpgmeplug / gpgmeplug.c
1 /* -*- Mode: C -*-
2
3   $Id$
4
5   GPGMEPLUG - an GPGME based cryptography plug-in following
6               the common CRYPTPLUG specification.
7
8   Copyright (C) 2001 by Klarälvdalens Datakonsult AB
9
10   GPGMEPLUG is free software; you can redistribute it and/or modify
11   it under the terms of GNU General Public License as published by
12   the Free Software Foundation; version 2 of the License.
13
14   GPGMEPLUG is distributed in the hope that it will be useful,
15   it under the terms of GNU General Public License as published by
16   the Free Software Foundation; version 2 of the License
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
24 */
25
26
27
28 /*! \file gpgmeplug.c
29     \brief GPGME implementation of CRYPTPLUG following the
30     specification located in common API header cryptplug.h.
31
32     CRYPTPLUG is an independent cryptography plug-in API
33     developed for Sphinx-enabeling KMail and Mutt.
34
35     CRYPTPLUG was designed for the Aegypten project, but it may
36     be used by 3rd party developers as well to design pluggable
37     crypto backends for the above mentioned MUAs.
38
39     \note All string parameters appearing in this API are to be
40     interpreted as UTF-8 encoded.
41
42     \see cryptplug.h
43 */
44
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48 #include <stdio.h>
49 #include <string.h>
50 #include <assert.h>
51 #include <errno.h>
52 #include <time.h>
53 #include <ctype.h>
54
55 #ifndef BUG_URL
56 #define BUG_URL "http:://www.gnupg.org/aegypten/"
57 #endif
58
59 #include "gpgme.h"
60 #ifndef GPGMEPLUG_PROTOCOL
61 #define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_OpenPGP
62 #endif
63
64 // definitions for signing
65 #ifndef GPGMEPLUG_SIGN_MAKE_MIME_OBJECT
66 #define GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT true
67 #define GPGMEPLUG_SIGN_MAKE_MIME_OBJECT  true
68 #define GPGMEPLUG_SIGN_MAKE_MULTI_MIME   true
69 #define GPGMEPLUG_SIGN_CTYPE_MAIN        "multipart/signed;protocol=application/pgp-signature;micalg=pgp-sha1"
70 #define GPGMEPLUG_SIGN_CDISP_MAIN        ""
71 #define GPGMEPLUG_SIGN_CTENC_MAIN        ""
72 #define GPGMEPLUG_SIGN_CTYPE_VERSION     ""
73 #define GPGMEPLUG_SIGN_CDISP_VERSION     ""
74 #define GPGMEPLUG_SIGN_CTENC_VERSION     ""
75 #define GPGMEPLUG_SIGN_BTEXT_VERSION     ""
76 #define GPGMEPLUG_SIGN_CTYPE_CODE        "application/pgp-signature"
77 #define GPGMEPLUG_SIGN_CDISP_CODE        ""
78 #define GPGMEPLUG_SIGN_CTENC_CODE        ""
79 #define GPGMEPLUG_SIGN_FLAT_PREFIX       ""
80 #define GPGMEPLUG_SIGN_FLAT_SEPARATOR    ""
81 #define GPGMEPLUG_SIGN_FLAT_POSTFIX      ""
82 #endif
83 // definitions for encoding
84 #ifndef GPGMEPLUG_ENC_MAKE_MIME_OBJECT
85 #define GPGMEPLUG_ENC_INCLUDE_CLEARTEXT  false
86 #define GPGMEPLUG_ENC_MAKE_MIME_OBJECT   true
87 #define GPGMEPLUG_ENC_MAKE_MULTI_MIME    true
88 #define GPGMEPLUG_ENC_CTYPE_MAIN         "multipart/encrypted; protocol=application/pgp-encrypted"
89 #define GPGMEPLUG_ENC_CDISP_MAIN         ""
90 #define GPGMEPLUG_ENC_CTENC_MAIN         ""
91 #define GPGMEPLUG_ENC_CTYPE_VERSION      "application/pgp-encrypted"
92 #define GPGMEPLUG_ENC_CDISP_VERSION      "attachment"
93 #define GPGMEPLUG_ENC_CTENC_VERSION      ""
94 #define GPGMEPLUG_ENC_BTEXT_VERSION      "Version: 1"
95 #define GPGMEPLUG_ENC_CTYPE_CODE         "application/octet-stream"
96 #define GPGMEPLUG_ENC_CDISP_CODE         "inline; filename=\"msg.asc\""
97 #define GPGMEPLUG_ENC_CTENC_CODE         ""
98 #define GPGMEPLUG_ENC_FLAT_PREFIX        ""
99 #define GPGMEPLUG_ENC_FLAT_SEPARATOR     ""
100 #define GPGMEPLUG_ENC_FLAT_POSTFIX       ""
101 #endif
102 // Note: The following specification will result in
103 //       function encryptAndSignMessage() producing
104 //       _empty_ mails.
105 //       This must be changed as soon as our plugin
106 //       is supporting the encryptAndSignMessage() function.
107 #ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT
108 #define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false
109 #define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT  false
110 #define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME   false
111 #define GPGMEPLUG_ENCSIGN_CTYPE_MAIN        ""
112 #define GPGMEPLUG_ENCSIGN_CDISP_MAIN        ""
113 #define GPGMEPLUG_ENCSIGN_CTENC_MAIN        ""
114 #define GPGMEPLUG_ENCSIGN_CTYPE_VERSION     ""
115 #define GPGMEPLUG_ENCSIGN_CDISP_VERSION     ""
116 #define GPGMEPLUG_ENCSIGN_CTENC_VERSION     ""
117 #define GPGMEPLUG_ENCSIGN_BTEXT_VERSION     ""
118 #define GPGMEPLUG_ENCSIGN_CTYPE_CODE        ""
119 #define GPGMEPLUG_ENCSIGN_CDISP_CODE        ""
120 #define GPGMEPLUG_ENCSIGN_CTENC_CODE        ""
121 #define GPGMEPLUG_ENCSIGN_FLAT_PREFIX       ""
122 #define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR    ""
123 #define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX      ""
124 #endif
125
126 #include "cryptplug.h"
127
128
129 typedef struct {
130   const char*             bugURL;
131   const char*             signatureKeyCertificate;
132   SignatureAlgorithm      signatureAlgorithm;
133   SendCertificates        sendCertificates;
134   SignEmail               signEmail;
135   bool                    saveSentSignatures;
136   bool                    warnNoCertificate;
137   PinRequests             numPINRequests;
138   bool                    checkSignatureCertificatePathToRoot;
139   bool                    signatureUseCRLs;
140   EncryptionAlgorithm     encryptionAlgorithm;
141   EncryptEmail            encryptEmail;
142   bool                    saveMessagesEncrypted;
143   bool                    checkEncryptionCertificatePathToRoot;
144   bool                    encryptionUseCRLs;
145   bool                    encryptionCRLExpiryNearWarning;
146   int                     encryptionCRLNearExpiryInterval;
147   struct DirectoryServer *directoryServers;
148   unsigned int            numDirectoryServers;
149   CertificateSource       certificateSource;
150   CertificateSource       cRLSource;
151   bool                    warnSendUnsigned;
152   int                     numPINRequestsInterval;
153   bool                    signatureCertificateExpiryNearWarning;
154   int                     signatureCertificateExpiryNearInterval;
155   bool                    cACertificateExpiryNearWarning;
156   int                     cACertificateExpiryNearInterval;
157   bool                    rootCertificateExpiryNearWarning;
158   int                     rootCertificateExpiryNearInterval;
159   bool                    warnSendUnencrypted;
160   bool                    checkCertificatePath;
161   bool                    receiverCertificateExpiryNearWarning;
162   int                     receiverCertificateExpiryNearWarningInterval;
163   bool                    certificateInChainExpiryNearWarning;
164   int                     certificateInChainExpiryNearWarningInterval;
165   bool                    receiverEmailAddressNotInCertificateWarning;
166 } Config;
167
168
169 Config config;
170
171 #define NEAR_EXPIRY 14
172
173 bool initialize()
174 {
175   config.bugURL                               = malloc( strlen( BUG_URL ) + 1 );
176   strcpy( (char* )config.bugURL,                BUG_URL );
177   config.signatureKeyCertificate              = malloc( 1 );
178   strcpy( (char* )config.signatureKeyCertificate, "" );
179   config.signatureAlgorithm                   = SignAlg_SHA1;
180   config.sendCertificates                     = SendCert_SendChainWithRoot;
181   config.signEmail                            = SignEmail_SignAll;
182   config.saveSentSignatures                   = true;
183   config.warnNoCertificate                    = true;
184   config.numPINRequests                       = PinRequest_Always;
185   config.checkSignatureCertificatePathToRoot  = true;
186   config.signatureUseCRLs                     = true;
187   config.encryptionAlgorithm                  = EncryptAlg_RSA;
188   config.encryptEmail                         = EncryptEmail_Ask;
189   config.saveMessagesEncrypted                = true;
190   config.checkEncryptionCertificatePathToRoot = true;
191   config.encryptionUseCRLs                    = true;
192   config.encryptionCRLExpiryNearWarning       = true;
193   config.encryptionCRLNearExpiryInterval      = NEAR_EXPIRY;
194   config.directoryServers                     = NULL;
195   config.numDirectoryServers                  = 0;
196   config.certificateSource                    = CertSrc_Server;
197   config.cRLSource                            = CertSrc_Server;
198   config.warnSendUnsigned                             = true;
199   config.numPINRequestsInterval                       = NEAR_EXPIRY;
200   config.signatureCertificateExpiryNearWarning        = true;
201   config.signatureCertificateExpiryNearInterval       = NEAR_EXPIRY;
202   config.cACertificateExpiryNearWarning               = true;
203   config.cACertificateExpiryNearInterval              = NEAR_EXPIRY;
204   config.rootCertificateExpiryNearWarning             = true;
205   config.rootCertificateExpiryNearInterval            = NEAR_EXPIRY;
206   config.warnSendUnencrypted                          = false;
207   config.checkCertificatePath                         = true;
208   config.receiverCertificateExpiryNearWarning         = true;
209   config.receiverCertificateExpiryNearWarningInterval = NEAR_EXPIRY;
210   config.certificateInChainExpiryNearWarning          = true;
211   config.certificateInChainExpiryNearWarningInterval  = NEAR_EXPIRY;
212   config.receiverEmailAddressNotInCertificateWarning  = true;
213
214   return true;
215 };
216
217
218 void deinitialize()
219 {
220   unsigned int i;
221   for( i = 0; i < config.numDirectoryServers; ++i ) {
222     free( (char *)config.directoryServers[i].servername );
223     free( (char *)config.directoryServers[i].description );
224   }
225   free( config.directoryServers );
226 }
227
228
229 bool hasFeature( Feature flag )
230 {
231   switch ( flag ) {
232     case CryptPlugFeat_SignMessages:              return true;
233     case CryptPlugFeat_VerifySignatures:          return true;
234     case CryptPlugFeat_EncryptMessages:           return true;
235     case CryptPlugFeat_DecryptMessages:           return true;
236     // undefined or not yet implemented:
237     case CryptPlugFeat_undef:                     return false;
238     default:                                      return false;
239   }
240 }
241
242
243 const char* bugURL(){ return config.bugURL; }
244
245
246 void unsafeStationery( void** pixmap, const char** menutext, char* accel,
247           const char** tooltip, const char** statusbartext ){}
248
249 void signedStationery( void** pixmap, const char** menutext, char* accel,
250           const char** tooltip, const char** statusbartext ){}
251
252 void encryptedStationery( void** pixmap, const char**
253           menutext, char* accel,
254           const char** tooltip, const char** statusbartext ){}
255
256 void signedEncryptedStationery( void** pixmap, const char**
257           menutext, char* accel,
258           const char** tooltip, const char** statusbartext ){}
259
260 const char* signatureConfigurationDialog(){ return 0; }
261
262 const char* signatureKeySelectionDialog(){ return 0; }
263
264 const char* signatureAlgorithmDialog(){ return 0; }
265
266 const char* signatureHandlingDialog(){ return 0; }
267
268 void setSignatureKeyCertificate( const char* certificate )
269 {
270   config.signatureKeyCertificate = certificate;
271 }
272
273 const char* signatureKeyCertificate()
274 {
275   return config.signatureKeyCertificate;
276 }
277
278 void setSignatureAlgorithm( SignatureAlgorithm sigAlg )
279 {
280   config.signatureAlgorithm = sigAlg;
281 }
282
283 SignatureAlgorithm signatureAlgorithm()
284 {
285   return config.signatureAlgorithm;
286 }
287
288 void setSendCertificates( SendCertificates sendCert )
289 {
290   config.sendCertificates = sendCert;
291 }
292
293 SendCertificates sendCertificates()
294 {
295   return config.sendCertificates;
296 }
297
298 void setSignEmail( SignEmail signMail )
299 {
300   config.signEmail = signMail;
301 }
302
303 SignEmail signEmail()
304 {
305   return config.signEmail;
306 }
307
308
309
310
311
312 void setWarnSendUnsigned( bool flag )
313 {
314   config.warnSendUnsigned = flag;
315 }
316
317 bool warnSendUnsigned()
318 {
319   return config.warnSendUnsigned;
320 }
321
322
323
324
325
326
327 void setSaveSentSignatures( bool flag )
328 {
329   config.saveSentSignatures = flag;
330 }
331
332 bool saveSentSignatures()
333 {
334   return config.saveSentSignatures;
335 }
336
337 void setWarnNoCertificate( bool flag )
338 {
339   config.warnNoCertificate = flag;
340 }
341
342 bool warnNoCertificate()
343 {
344   return config.warnNoCertificate;
345 }
346
347
348 bool isEmailInCertificate( const char* email, const char* certificate )
349 {
350     /* PENDING(g10) this function should return true if the email
351        address passed as the first parameter is contained in the
352        certificate passed as the second parameter, and false
353        otherwise. This is used to alert the user if his own email
354        address is not contained in the certificate he uses for
355        signing.
356        Note that the parameter email can be anything that is allowed
357        in a From: line.
358        Another note: OK, OK, we'll handle that in the MUA. You can
359        assume that you only get the email address.
360     */
361     return false; // dummy
362 }
363
364
365 void setNumPINRequests( PinRequests reqMode )
366 {
367   config.numPINRequests = reqMode;
368
369   /* PENDING(g10) Put this value into gpg and make it ask for the pin
370      according to this. Note that there is also
371      setNumPINRequestsInterval() which is only used if reqMode ==
372      PinRequest_AfterMinutes.
373   */
374 }
375
376 PinRequests numPINRequests()
377 {
378   return config.numPINRequests;
379 }
380
381
382
383 void setNumPINRequestsInterval( int interval )
384 {
385   config.numPINRequestsInterval = interval;
386
387   /* PENDING(g10) Put this value into gpg and make it ask for the pin
388      according to this. Note that this should only be used if
389      config.numPINRequests (set with setNumPINRequests()) has the
390      value PinRequest_AfterMinutes.
391   */
392 }
393
394 int numPINRequestsInterval()
395 {
396   return config.numPINRequestsInterval;
397 }
398
399
400
401 void setCheckSignatureCertificatePathToRoot( bool flag )
402 {
403   config.checkSignatureCertificatePathToRoot = flag;
404 }
405
406 bool checkSignatureCertificatePathToRoot()
407 {
408   return config.checkSignatureCertificatePathToRoot;
409 }
410
411 void setSignatureUseCRLs( bool flag )
412 {
413   config.signatureUseCRLs = flag;
414 }
415
416 bool signatureUseCRLs()
417 {
418   return config.signatureUseCRLs;
419 }
420
421
422
423
424
425
426 void setSignatureCertificateExpiryNearWarning( bool flag )
427 {
428   config.signatureCertificateExpiryNearWarning = flag;
429 }
430
431 bool signatureCertificateExpiryNearWarning( void )
432 {
433   return config.signatureCertificateExpiryNearWarning;
434 }
435
436
437 int signatureCertificateDaysLeftToExpiry( const char* certificate )
438 {
439     /* PENDING(g10)
440        Please return the number of days that are left until the
441        certificate specified in the parameter certificate expires.
442     */
443     return 10; // dummy that triggers a warning in the MUA
444 }
445
446
447 void setSignatureCertificateExpiryNearInterval( int interval )
448 {
449   config.signatureCertificateExpiryNearInterval = interval;
450 }
451
452 int signatureCertificateExpiryNearInterval( void )
453 {
454   return config.signatureCertificateExpiryNearInterval;
455 }
456
457 void setCACertificateExpiryNearWarning( bool flag )
458 {
459   config.cACertificateExpiryNearWarning = flag;
460 }
461
462 bool caCertificateExpiryNearWarning( void )
463 {
464   return config.cACertificateExpiryNearWarning;
465 }
466
467 int caCertificateDaysLeftToExpiry( const char* certificate )
468 {
469     /* PENDING(g10)
470        Please return the number of days that are left until the
471        CA certificate for the certificate specified in the parameter
472        certificate expires.
473     */
474     return 10; // dummy that triggers a warning in the MUA
475 }
476
477 void setCACertificateExpiryNearInterval( int interval )
478 {
479   config.cACertificateExpiryNearInterval = interval;
480 }
481
482 int caCertificateExpiryNearInterval( void )
483 {
484   return config.cACertificateExpiryNearInterval;
485 }
486
487 void setRootCertificateExpiryNearWarning( bool flag )
488 {
489   config.rootCertificateExpiryNearWarning = flag;
490 }
491
492 bool rootCertificateExpiryNearWarning( void )
493 {
494   return config.rootCertificateExpiryNearWarning;
495 }
496
497 int rootCertificateDaysLeftToExpiry( const char* certificate )
498 {
499     /* PENDING(g10)
500        Please return the number of days that are left until the
501        root certificate for the certificate specified in the parameter
502        certificate expires.
503     */
504     return 10; // dummy that triggers a warning in the MUA
505 }
506
507
508 void setRootCertificateExpiryNearInterval( int interval )
509 {
510   config.rootCertificateExpiryNearInterval = interval;
511 }
512
513 int rootCertificateExpiryNearInterval( void )
514 {
515   return config.rootCertificateExpiryNearInterval;
516 }
517
518
519
520
521
522
523
524
525 const char* encryptionConfigurationDialog(){ return 0; }
526
527 const char* encryptionAlgorithmDialog(){ return 0; }
528
529 const char* encryptionHandlingDialog(){ return 0; }
530
531 const char* encryptionReceiverDialog(){ return 0; }
532
533 void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
534 {
535   config.encryptionAlgorithm = cryptAlg;
536 }
537
538 EncryptionAlgorithm encryptionAlgorithm()
539 {
540   return config.encryptionAlgorithm;
541 }
542
543 void setEncryptEmail( EncryptEmail cryptMode )
544 {
545   config.encryptEmail = cryptMode;
546 }
547
548 EncryptEmail encryptEmail()
549 {
550   return config.encryptEmail;
551 }
552
553
554
555
556
557
558 void setWarnSendUnencrypted( bool flag )
559 {
560   config.warnSendUnencrypted = flag;
561 }
562
563 bool warnSendUnencrypted()
564 {
565   return config.warnSendUnencrypted;
566 }
567
568
569
570
571
572
573
574
575
576 void setSaveMessagesEncrypted( bool flag )
577 {
578   config.saveMessagesEncrypted = flag;
579 }
580
581 bool saveMessagesEncrypted()
582 {
583   return config.saveMessagesEncrypted;
584 }
585
586
587
588
589
590
591
592 void setCheckCertificatePath( bool flag )
593 {
594   config.checkCertificatePath = flag;
595 }
596
597 bool checkCertificatePath()
598 {
599   return config.checkCertificatePath;
600 }
601
602
603
604
605
606
607
608
609 void setCheckEncryptionCertificatePathToRoot( bool flag )
610 {
611   config.checkEncryptionCertificatePathToRoot = flag;
612 }
613
614 bool checkEncryptionCertificatePathToRoot()
615 {
616   return config.checkEncryptionCertificatePathToRoot;
617 }
618
619
620
621
622
623
624
625 void setReceiverCertificateExpiryNearWarning( bool flag )
626 {
627   config.receiverCertificateExpiryNearWarning = flag;
628 }
629
630 bool receiverCertificateExpiryNearWarning()
631 {
632   return config.receiverCertificateExpiryNearWarning;
633 }
634
635
636 int receiverCertificateDaysLeftToExpiry( const char* certificate )
637 {
638     /* PENDING(g10)
639        Please return the number of days that are left until the
640        certificate specified in the parameter certificate expires.
641     */
642     return 10; // dummy that triggers a warning in the MUA
643 }
644
645
646 void setReceiverCertificateExpiryNearWarningInterval( int interval )
647 {
648   config.receiverCertificateExpiryNearWarningInterval = interval;
649 }
650
651 int receiverCertificateExpiryNearWarningInterval()
652 {
653   return config.receiverCertificateExpiryNearWarningInterval;
654 }
655
656 void setCertificateInChainExpiryNearWarning( bool flag )
657 {
658   config.certificateInChainExpiryNearWarning = flag;
659 }
660
661 bool certificateInChainExpiryNearWarning()
662 {
663   return config.certificateInChainExpiryNearWarning;
664 }
665
666
667 int certificateInChainDaysLeftToExpiry( const char* certificate )
668 {
669     /* PENDING(g10)
670        Please return the number of days that are left until the
671        the first certificate in the chain of the specified certificate
672        expires.
673     */
674     return 10; // dummy that triggers a warning in the MUA
675 }
676
677
678 void setCertificateInChainExpiryNearWarningInterval( int interval )
679 {
680   config.certificateInChainExpiryNearWarningInterval = interval;
681 }
682
683 int certificateInChainExpiryNearWarningInterval()
684 {
685   return config.certificateInChainExpiryNearWarningInterval;
686 }
687
688 void setReceiverEmailAddressNotInCertificateWarning( bool flag )
689 {
690   config.receiverEmailAddressNotInCertificateWarning = flag;
691 }
692
693 bool receiverEmailAddressNotInCertificateWarning()
694 {
695   return config.receiverEmailAddressNotInCertificateWarning;
696 }
697
698
699
700
701
702
703
704
705 void setEncryptionUseCRLs( bool flag )
706 {
707   config.encryptionUseCRLs = flag;
708
709   /* PENDING(g10) Store this setting in gpgme and use it. If true,
710      every certificate used for encryption should be checked against
711      applicable CRLs.
712   */
713 }
714
715 bool encryptionUseCRLs()
716 {
717   return config.encryptionUseCRLs;
718 }
719
720
721 int encryptionCRLsDaysLeftToExpiry()
722 {
723     /* PENDING(g10)
724        Please return the number of days that are left until the
725        CRL used for encryption expires.
726     */
727     return 10; // dummy that triggers a warning in the MUA
728 }
729
730 void setEncryptionCRLExpiryNearWarning( bool flag )
731 {
732   config.encryptionCRLExpiryNearWarning = flag;
733 }
734
735 bool encryptionCRLExpiryNearWarning()
736 {
737   return config.encryptionCRLExpiryNearWarning;
738 }
739
740 void setEncryptionCRLNearExpiryInterval( int interval )
741 {
742   config.encryptionCRLNearExpiryInterval = interval;
743 }
744
745 int encryptionCRLNearExpiryInterval()
746 {
747   return config.encryptionCRLNearExpiryInterval;
748 }
749
750
751 const char* directoryServiceConfigurationDialog(){ return 0; }
752
753 void appendDirectoryServer( const char* servername,
754                             int         port,
755                             const char* description )
756 {
757   struct DirectoryServer *newServers = NULL;
758   newServers = realloc( config.directoryServers,
759                         (1+config.numDirectoryServers) * sizeof *newServers );
760   if( newServers ) {
761     config.directoryServers = newServers;
762     newServers[ config.numDirectoryServers ].servername =
763       malloc( 1+strlen( servername ) );
764     if( newServers[ config.numDirectoryServers ].servername ) {
765       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
766         servername );
767       newServers[ config.numDirectoryServers ].description =
768         malloc( 1+strlen(  description ) );
769       if( newServers[ config.numDirectoryServers ].description ) {
770         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
771           description );
772         newServers[ config.numDirectoryServers ].port = port;
773         config.numDirectoryServers += 1;
774       }
775     }
776   }
777 }
778
779 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
780 {
781   unsigned int i;
782   int oldSize = config.numDirectoryServers;
783   struct DirectoryServer *newServers = NULL;
784   newServers = calloc ( size, sizeof *newServers );
785   if( newServers ) {
786     for( i=0; i < oldSize; ++i ) {
787       free( (char *)config.directoryServers[i].servername );
788       free( (char *)config.directoryServers[i].description );
789     }
790     free( config.directoryServers );
791     for( i=0; i < size; ++i ) {
792       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
793       if( newServers[ i ].servername ) {
794         strcpy( (char *)newServers[ i ].servername, server[i].servername );
795         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
796         if( newServers[ i ].description ) {
797           strcpy( (char *)newServers[ i ].description, server[i].description );
798           newServers[ i ].port = server[i].port;
799         }
800       }
801     }
802     config.directoryServers = newServers;
803     config.numDirectoryServers = size;
804   }
805 }
806
807 struct DirectoryServer * directoryServers( int* numServers )
808 {
809   if( numServers )
810     *numServers = config.numDirectoryServers;
811   return config.directoryServers;
812 };
813
814 void setCertificateSource( CertificateSource source )
815 {
816   config.certificateSource = source;
817 }
818
819 CertificateSource certificateSource()
820 {
821   return config.certificateSource;
822 }
823
824 void setCRLSource( CertificateSource source )
825 {
826   config.cRLSource = source;
827 }
828
829 CertificateSource crlSource()
830 {
831   return config.cRLSource;
832 }
833
834
835 bool certificateValidity( const char* certificate,
836                           int* level ){ return true; }
837
838
839 void storeNewCharPtr( char** dest, const char* src )
840 {
841   int sLen = strlen( src );
842   *dest = malloc( sLen + 1 );
843   strcpy( *dest, src );
844   (*dest)[sLen] = '\0';
845 }
846
847
848 bool signMessage( const char*  cleartext,
849                   const char** ciphertext,
850                   const char*  certificate,
851                   struct StructuringInfo* structuring )
852 {
853   GpgmeCtx ctx;
854   GpgmeError err;
855   GpgmeData data,  sig;
856   size_t rSLen = 0;
857   char*  rSig  = 0;
858   bool   bOk   = false;
859   int sendCerts = 1;
860
861   init_StructuringInfo( structuring );
862
863   if( !ciphertext )
864     return false;
865
866   err = gpgme_new (&ctx);
867   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
868
869   gpgme_set_armor (ctx, 1);
870   gpgme_set_textmode (ctx, 1);
871
872   switch ( config.sendCertificates ) {
873     case SendCert_undef:
874       break;
875     case SendCert_DontSend:
876       sendCerts = 0;
877       break;
878     case SendCert_SendOwn:
879       sendCerts = 1;
880       break;
881     case SendCert_SendChainWithoutRoot:
882       sendCerts = -2;
883       break;
884     case SendCert_SendChainWithRoot:
885       sendCerts = -1;
886       break;
887     default:
888       sendCerts = 0;
889       break;
890   }
891   gpgme_set_include_certs (ctx, sendCerts);
892
893   // PENDING(g10) Implement this
894   //gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm );
895
896   gpgme_data_new_from_mem (&data, cleartext,
897                             strlen( cleartext ), 1 );
898   gpgme_data_new ( &sig );
899   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
900
901   if (!err) {
902     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
903     *ciphertext = malloc( rSLen + 1 );
904     if( *ciphertext ) {
905       if( rSLen ) {
906         bOk = true;
907         strncpy((char*)*ciphertext, rSig, rSLen );
908       }
909       ((char*)(*ciphertext))[rSLen] = '\0';
910     }
911     free( rSig );
912   }
913   else {
914     gpgme_data_release( sig );
915     *ciphertext = 0;
916     // hier fehlt eine Fehlerbehandlung, falls das
917     // Signieren schiefging
918   }
919   gpgme_data_release( data );
920   gpgme_release (ctx);
921
922   if( bOk && structuring ) {
923     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
924     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
925     if( structuring->makeMimeObject ) {
926       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
927       storeNewCharPtr( &structuring->contentTypeMain,
928                        GPGMEPLUG_SIGN_CTYPE_MAIN );
929       storeNewCharPtr( &structuring->contentDispMain,
930                        GPGMEPLUG_SIGN_CDISP_MAIN );
931       storeNewCharPtr( &structuring->contentTEncMain,
932                        GPGMEPLUG_SIGN_CTENC_MAIN );
933       if( structuring->makeMultiMime ) {
934         storeNewCharPtr( &structuring->contentTypeVersion,
935                          GPGMEPLUG_SIGN_CTYPE_VERSION );
936         storeNewCharPtr( &structuring->contentDispVersion,
937                          GPGMEPLUG_SIGN_CDISP_VERSION );
938         storeNewCharPtr( &structuring->contentTEncVersion,
939                          GPGMEPLUG_SIGN_CTENC_VERSION );
940         storeNewCharPtr( &structuring->bodyTextVersion,
941                          GPGMEPLUG_SIGN_BTEXT_VERSION );
942         storeNewCharPtr( &structuring->contentTypeCode,
943                          GPGMEPLUG_SIGN_CTYPE_CODE );
944         storeNewCharPtr( &structuring->contentDispCode,
945                          GPGMEPLUG_SIGN_CDISP_CODE );
946         storeNewCharPtr( &structuring->contentTEncCode,
947                          GPGMEPLUG_SIGN_CTENC_CODE );
948       }
949     } else {
950       storeNewCharPtr( &structuring->flatTextPrefix,
951                        GPGMEPLUG_SIGN_FLAT_PREFIX );
952       storeNewCharPtr( &structuring->flatTextSeparator,
953                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
954       storeNewCharPtr( &structuring->flatTextPostfix,
955                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
956     }
957   }
958   return bOk;
959 }
960
961
962 static const char*
963 sig_status_to_string( GpgmeSigStat status )
964 {
965   const char *result;
966
967   switch (status) {
968     case GPGME_SIG_STAT_NONE:
969       result = "Oops: Signature not verified";
970       break;
971     case GPGME_SIG_STAT_NOSIG:
972       result = "No signature found";
973       break;
974     case GPGME_SIG_STAT_GOOD:
975       result = "Good signature";
976       break;
977     case GPGME_SIG_STAT_BAD:
978       result = "BAD signature";
979       break;
980     case GPGME_SIG_STAT_NOKEY:
981       result = "No public key to verify the signature";
982       break;
983     case GPGME_SIG_STAT_ERROR:
984       result = "Error verifying the signature";
985       break;
986     case GPGME_SIG_STAT_DIFF:
987       result = "Different results for signatures";
988       break;
989     default:
990       result = "Error: Unknown status";
991       break;
992   }
993
994   return result;
995 }
996
997
998 bool checkMessageSignature( const char* ciphertext,
999                             const char* signaturetext,
1000                             bool signatureIsBinary,
1001                             int signatureLen,
1002                             struct SignatureMetaData* sigmeta )
1003 {
1004   GpgmeCtx ctx;
1005   GpgmeSigStat status;
1006   GpgmeData datapart, sigpart;
1007   GpgmeError err;
1008   GpgmeKey key;
1009   time_t created;
1010   int sig_idx = 0;
1011   const char* statusStr;
1012   const char* fpr;
1013
1014   gpgme_new( &ctx );
1015   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1016   gpgme_set_armor (ctx,    signatureIsBinary ? 0 : 1);
1017 //  gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1);
1018
1019   gpgme_data_new_from_mem( &datapart, ciphertext,
1020                           strlen( ciphertext ), 1 );
1021
1022   gpgme_data_new_from_mem( &sigpart,
1023                            signaturetext,
1024                            signatureIsBinary
1025                            ? signatureLen
1026                            : strlen( signaturetext ),
1027                            1 );
1028
1029   gpgme_op_verify( ctx, sigpart, datapart, &status );
1030   gpgme_data_release( datapart );
1031   gpgme_data_release( sigpart );
1032
1033   /* Provide information in the sigmeta struct */
1034   /* the status string */
1035   statusStr = sig_status_to_string( status );
1036   sigmeta->status = malloc( strlen( statusStr ) + 1 );
1037   if( sigmeta->status ) {
1038     strcpy( sigmeta->status, statusStr );
1039     sigmeta->status[strlen( statusStr )] = '\0';
1040   } else
1041     ; // nothing to do, is already 0
1042
1043   // Extended information for any number of signatures.
1044   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
1045   sigmeta->extended_info = 0;
1046   while( fpr != NULL ) {
1047     struct tm* ctime_val;
1048     const char* sig_status;
1049
1050     void* realloc_return = realloc( sigmeta->extended_info,
1051                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
1052     if( realloc_return ) {
1053       sigmeta->extended_info = realloc_return;
1054       // the creation time
1055       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
1056       if( sigmeta->extended_info[sig_idx].creation_time ) {
1057         ctime_val = localtime( &created );
1058         memcpy( sigmeta->extended_info[sig_idx].creation_time,
1059                 ctime_val, sizeof( struct tm ) );
1060       }
1061
1062       err = gpgme_get_sig_key (ctx, sig_idx, &key);
1063       sig_status = sig_status_to_string( status );
1064       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
1065       if( sigmeta->extended_info[sig_idx].status_text ) {
1066         strcpy( sigmeta->extended_info[sig_idx].status_text,
1067                 sig_status );
1068         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
1069       }
1070
1071       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
1072       if( sigmeta->extended_info[sig_idx].fingerprint ) {
1073         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
1074         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
1075       }
1076     } else
1077       break; // if allocation fails once, it isn't likely to
1078               // succeed the next time either
1079
1080     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
1081   }
1082   sigmeta->extended_info_count = sig_idx;
1083   sigmeta->nota_xml = gpgme_get_notation( ctx );
1084   sigmeta->status_code = status;
1085
1086   gpgme_release( ctx );
1087   return ( status == GPGME_SIG_STAT_GOOD );
1088 }
1089
1090 bool storeCertificatesFromMessage(
1091         const char* ciphertext ){ return true; }
1092
1093
1094 /* returns the next address in a comma-separated list
1095    or NULL if the list is empty. The function honors double quotes 
1096    and '(' ')' comments.
1097    A non-NULL return value should be deleted with free().
1098 */
1099 static char* nextAddress( const char** address )
1100 {
1101   const char *start = *address;
1102   char* result = NULL;
1103   int quote = 0;
1104   int comment = 0;
1105   int found = 0;
1106   if( *address == NULL ) return NULL;
1107   while( **address ) {
1108
1109     switch( **address ) {
1110     case '\\': /* escaped character */
1111       ++(*address);
1112       break;
1113     case '"':
1114       if( comment == 0 ) {
1115         if( quote > 0 ) --quote;
1116         else ++quote;
1117       }
1118       break;
1119     case '(': /* comment start */
1120       if( quote == 0 ) ++comment;
1121       break;
1122     case ')': /* comment end */
1123       if( quote == 0 ) --comment;
1124       break;      
1125     case '\0':
1126     case ',': /* delimiter */
1127       if( quote == 0 && comment == 0 ) {
1128         found = 1;
1129       }
1130       break;
1131     }
1132     ++(*address);
1133     if( found ) break;
1134   }
1135   if( found || **address == 0 ) {
1136     size_t len;
1137     while( isspace( *start ) ) ++start;
1138     len = *address - start;
1139     if( len > 0 ) {
1140       if( **address != 0 ) --len;
1141       result = malloc( len*sizeof(char)+1 );
1142       strncpy( result, start, len );
1143       result[len] = '\0';
1144     }  
1145   }
1146   return result;
1147 }
1148
1149 bool encryptMessage( const char* cleartext,
1150                      const char** ciphertext,
1151                      const char* addressee,
1152                      struct StructuringInfo* structuring )
1153 {
1154   GpgmeCtx ctx;
1155   GpgmeError err;
1156   GpgmeData gCiphertext, gPlaintext;
1157   GpgmeRecipients rset;
1158   size_t rCLen = 0;
1159   char*  rCiph = 0;
1160   bool   bOk   = false;
1161
1162   init_StructuringInfo( structuring );
1163
1164   gpgme_new (&ctx);
1165   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1166
1167   gpgme_set_armor (ctx, 1);
1168   gpgme_set_textmode (ctx, 1);
1169
1170   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1171                             1+strlen( cleartext ), 1 );
1172   err = gpgme_data_new ( &gCiphertext );
1173
1174   gpgme_recipients_new (&rset);
1175
1176
1177   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1178   {
1179     gpgme_recipients_add_name_with_validity (rset,
1180       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE",
1181       GPGME_VALIDITY_FULL );
1182     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1183   }
1184   else
1185   {
1186     const char* p = addressee;
1187     char* tok;
1188     while( (tok = nextAddress( &p ) ) != 0 ) { 
1189       gpgme_recipients_add_name (rset, tok);
1190       fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", tok );
1191       free(tok);
1192     }
1193   }
1194
1195   // PENDING(g10) Implement this
1196   // Possible values: RSA = 1, SHA1 = 2, TripleDES = 3
1197   //gpgme_set_encryption_algorithm( ctx, config.encryptionAlgorithm );
1198
1199
1200   // PENDING(g10) Implement this
1201   // gpgme_set_encryption_check_certificate_path(
1202   // config.checkCertificatePath )
1203
1204   // PENDING(g10) Implement this
1205   // gpgme_set_encryption_check_certificate_path_to_root(
1206   // config.checkEncryptionCertificatePathToRoot )
1207
1208
1209   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1210   if( err )
1211     fprintf( stderr, "gpgme_op_encrypt() returned this error code:  %i\n\n", err );
1212
1213   gpgme_recipients_release (rset);
1214   gpgme_data_release (gPlaintext);
1215
1216   if( !err ) {
1217     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
1218     *ciphertext = malloc( rCLen + 1 );
1219     if( *ciphertext ) {
1220       if( rCLen ) {
1221         bOk = true;
1222         strncpy((char*)*ciphertext, rCiph, rCLen );
1223       }
1224       ((char*)(*ciphertext))[rCLen] = 0;
1225     }
1226     free( rCiph );
1227   }
1228   else {
1229     gpgme_data_release ( gCiphertext );
1230     *ciphertext = 0;
1231     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
1232     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
1233     // das signieren.
1234   }
1235
1236   gpgme_release (ctx);
1237
1238   fflush( stderr );
1239
1240   if( bOk && structuring ) {
1241     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1242     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1243     if( structuring->makeMimeObject ) {
1244       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1245       storeNewCharPtr( &structuring->contentTypeMain,
1246                        GPGMEPLUG_ENC_CTYPE_MAIN );
1247       storeNewCharPtr( &structuring->contentDispMain,
1248                        GPGMEPLUG_ENC_CDISP_MAIN );
1249       storeNewCharPtr( &structuring->contentTEncMain,
1250                        GPGMEPLUG_ENC_CTENC_MAIN );
1251       if( structuring->makeMultiMime ) {
1252         storeNewCharPtr( &structuring->contentTypeVersion,
1253                          GPGMEPLUG_ENC_CTYPE_VERSION );
1254         storeNewCharPtr( &structuring->contentDispVersion,
1255                          GPGMEPLUG_ENC_CDISP_VERSION );
1256         storeNewCharPtr( &structuring->contentTEncVersion,
1257                          GPGMEPLUG_ENC_CTENC_VERSION );
1258         storeNewCharPtr( &structuring->bodyTextVersion,
1259                          GPGMEPLUG_ENC_BTEXT_VERSION );
1260         storeNewCharPtr( &structuring->contentTypeCode,
1261                          GPGMEPLUG_ENC_CTYPE_CODE );
1262         storeNewCharPtr( &structuring->contentDispCode,
1263                          GPGMEPLUG_ENC_CDISP_CODE );
1264         storeNewCharPtr( &structuring->contentTEncCode,
1265                          GPGMEPLUG_ENC_CTENC_CODE );
1266       }
1267     } else {
1268       storeNewCharPtr( &structuring->flatTextPrefix,
1269                        GPGMEPLUG_ENC_FLAT_PREFIX );
1270       storeNewCharPtr( &structuring->flatTextSeparator,
1271                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1272       storeNewCharPtr( &structuring->flatTextPostfix,
1273                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1274     }
1275   }
1276   return bOk;
1277 }
1278
1279
1280 bool encryptAndSignMessage( const char* cleartext,
1281                             const char** ciphertext,
1282                             const char* certificate,
1283                             struct StructuringInfo* structuring )
1284 {
1285   bool bOk;
1286
1287   init_StructuringInfo( structuring );
1288
1289   bOk = false;
1290
1291   // implementation of this function is still missing
1292
1293   if( bOk && structuring ) {
1294     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1295     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1296     if( structuring->makeMimeObject ) {
1297       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1298       storeNewCharPtr( &structuring->contentTypeMain,
1299                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1300       storeNewCharPtr( &structuring->contentDispMain,
1301                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1302       storeNewCharPtr( &structuring->contentTEncMain,
1303                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1304       if( structuring->makeMultiMime ) {
1305         storeNewCharPtr( &structuring->contentTypeVersion,
1306                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1307         storeNewCharPtr( &structuring->contentDispVersion,
1308                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1309         storeNewCharPtr( &structuring->contentTEncVersion,
1310                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1311         storeNewCharPtr( &structuring->bodyTextVersion,
1312                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1313         storeNewCharPtr( &structuring->contentTypeCode,
1314                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1315         storeNewCharPtr( &structuring->contentDispCode,
1316                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1317         storeNewCharPtr( &structuring->contentTEncCode,
1318                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1319       }
1320     } else {
1321       storeNewCharPtr( &structuring->flatTextPrefix,
1322                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1323       storeNewCharPtr( &structuring->flatTextSeparator,
1324                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1325       storeNewCharPtr( &structuring->flatTextPostfix,
1326                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1327     }
1328   }
1329   return bOk;
1330 }
1331
1332 bool decryptMessage( const char* ciphertext,
1333                      const char** cleartext,
1334                      const char* certificate )
1335 {
1336   GpgmeCtx ctx;
1337   GpgmeError err;
1338   GpgmeData gCiphertext, gPlaintext;
1339   size_t rCLen = 0;
1340   char*  rCiph = 0;
1341   bool bOk = false;
1342
1343   if( !ciphertext )
1344     return false;
1345
1346   err = gpgme_new (&ctx);
1347   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1348
1349   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1350                            1+strlen( ciphertext ), 1 );
1351   gpgme_data_new( &gPlaintext );
1352
1353   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1354   gpgme_data_release( gCiphertext );
1355
1356   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1357
1358   *cleartext = malloc( rCLen + 1 );
1359   if( *cleartext ) {
1360       if( rCLen ) {
1361           bOk = true;
1362           strncpy((char*)*cleartext, rCiph, rCLen );
1363       }
1364       ((char*)(*cleartext))[rCLen] = 0;
1365   }
1366
1367   free( rCiph );
1368   gpgme_release( ctx );
1369   return bOk;
1370 }
1371
1372 bool decryptAndCheckMessage( const char* ciphertext,
1373           const char** cleartext, const char* certificate,
1374           struct SignatureMetaData* sigmeta ){ return true; }
1375
1376
1377 const char* requestCertificateDialog(){ return 0; }
1378
1379 bool requestDecentralCertificate( const char* name, const char*
1380           email, const char* organization, const char* department,
1381           const char* ca_address ){ return true; }
1382
1383 bool requestCentralCertificateAndPSE( const char* name,
1384           const char* email, const char* organization, const char* department,
1385           const char* ca_address ){ return true; }
1386
1387 bool createPSE(){ return true; }
1388
1389 bool registerCertificate( const char* certificate ){ return true; }
1390
1391 bool requestCertificateProlongation( const char* certificate,
1392                                      const char* ca_address ){ return true; }
1393
1394 const char* certificateChain(){ return 0; }
1395
1396 bool deleteCertificate( const char* certificate ){ return true; }
1397
1398 bool archiveCertificate( const char* certificate ){ return true; }
1399
1400
1401 const char* displayCRL(){ return 0; }
1402
1403 void updateCRL(){}